条件嵌套 for 循环执行代码,即使条件不满足
conditional nested for loop executing code even when condition not satisfied
我有一个嵌套循环结构,通过改变 4 个变量 oq、aq、lev 和 val 的值来生成大量回测。这个想法是在提供的范围内执行以下变量的每个组合。
在没有约束的情况下,此循环将因此执行总共 5 * 6 * 5 * 5 = 750 次,每次约 5-10 秒将花费数小时。但是,有一个限制条件,即所有权重之和必须恰好为 1 (tot_wgt)。通过添加 if 语句,我希望简单地丢弃这种情况。
if (tot_wgt != 1):
continue
不幸的是,当 tot_wgt 的值不为 1 时,代码有时似乎仍然会执行。这似乎在每次 val 循环完成一个循环时都会发生(并且大概也会在每个 val 循环完成时发生)其他3个循环完成一个循环)。
问题已解决:我有一个缩进错误:我需要在 if 语句的级别。但是请参阅关于识别浮点数的优秀答案。
mom = 0
for oq in [0.3, 0.4, 0.5, 0.6, 0.7]:
for aq in [0.05, 0.1, 0.15, 0.2, 0.25, 0.3]:
for lev in [0.0, 0.05, 0.1, 0.15, 0.2]:
for val in [0.0, 0.05, 0.1, 0.15, 0.2]:
tot_wgt = oq + aq + lev + val + mom
if (tot_wgt != 1): #we only want to backtest where the weights add up to 1. If <1 or >1, simply skip
continue
<MAIN BACKTEST CODE HERE>
这是由于在计算机硬件中将浮点数表示为基数 2(二进制)分数的局限性造成的。详细说明参见Floating Point Arithmetic: Issues and Limitations。
例如,在您的情况下,
>>> 0.7 + 0.2 + 0.0 + 0.1 + 0
0.9999999999999999
# more specific
>>> from decimal import Decimal
>>> Decimal(0.7 + 0.2 + 0.0 + 0.1 + 0)
Decimal('0.99999999999999988897769753748434595763683319091796875')
如您所见,这不等同于 1
。解决它的一种简单方法是将行 if (tot_wgt != 1):
替换为
if abs(tot_wgt - 1) < 0.0001 :
Python 3.5 增加了 math.isclose
用于测试近似相等。对于较早的版本,等效函数如下
def isclose(a, b, rel_tol=1e-09, abs_tol=0.0):
return abs(a-b) <= max(rel_tol * max(abs(a), abs(b)), abs_tol)
使用 numpy.isclose
测试两个数组在元素方面是否在公差范围内相等。
# Usage
numpy.isclose(a, b, rtol=1e-05, atol=1e-08, equal_nan=False)
# An example
>>> import numpy as np
>>> np.isclose([1e10,1e-7], [1.00001e10,1e-8])
array([True, False])
我有一个嵌套循环结构,通过改变 4 个变量 oq、aq、lev 和 val 的值来生成大量回测。这个想法是在提供的范围内执行以下变量的每个组合。
在没有约束的情况下,此循环将因此执行总共 5 * 6 * 5 * 5 = 750 次,每次约 5-10 秒将花费数小时。但是,有一个限制条件,即所有权重之和必须恰好为 1 (tot_wgt)。通过添加 if 语句,我希望简单地丢弃这种情况。
if (tot_wgt != 1):
continue
不幸的是,当 tot_wgt 的值不为 1 时,代码有时似乎仍然会执行。这似乎在每次 val 循环完成一个循环时都会发生(并且大概也会在每个 val 循环完成时发生)其他3个循环完成一个循环)。
问题已解决:我有一个缩进错误:我需要在 if 语句的级别。但是请参阅关于识别浮点数的优秀答案。
mom = 0
for oq in [0.3, 0.4, 0.5, 0.6, 0.7]:
for aq in [0.05, 0.1, 0.15, 0.2, 0.25, 0.3]:
for lev in [0.0, 0.05, 0.1, 0.15, 0.2]:
for val in [0.0, 0.05, 0.1, 0.15, 0.2]:
tot_wgt = oq + aq + lev + val + mom
if (tot_wgt != 1): #we only want to backtest where the weights add up to 1. If <1 or >1, simply skip
continue
<MAIN BACKTEST CODE HERE>
这是由于在计算机硬件中将浮点数表示为基数 2(二进制)分数的局限性造成的。详细说明参见Floating Point Arithmetic: Issues and Limitations。
例如,在您的情况下,
>>> 0.7 + 0.2 + 0.0 + 0.1 + 0
0.9999999999999999
# more specific
>>> from decimal import Decimal
>>> Decimal(0.7 + 0.2 + 0.0 + 0.1 + 0)
Decimal('0.99999999999999988897769753748434595763683319091796875')
如您所见,这不等同于 1
。解决它的一种简单方法是将行 if (tot_wgt != 1):
替换为
if abs(tot_wgt - 1) < 0.0001 :
Python 3.5 增加了 math.isclose
用于测试近似相等。对于较早的版本,等效函数如下
def isclose(a, b, rel_tol=1e-09, abs_tol=0.0):
return abs(a-b) <= max(rel_tol * max(abs(a), abs(b)), abs_tol)
使用 numpy.isclose
测试两个数组在元素方面是否在公差范围内相等。
# Usage
numpy.isclose(a, b, rtol=1e-05, atol=1e-08, equal_nan=False)
# An example
>>> import numpy as np
>>> np.isclose([1e10,1e-7], [1.00001e10,1e-8])
array([True, False])