2016-05-19 10 views
2

4変数、oq、aq、lev、valの値を変えて多数のバックテストを生成するネストループ構造を持っています。考えられるのは、提供される範囲内で以下の変数のすべての組み合わせを実行することです。条件が満たされていなくてもループ実行コードの条件付きネストされた

したがって、このループは合計で5 * 6 * 5 * 5 = 750回実行し、約5-10秒でそれぞれ数時間かかることになります。しかし、すべての重みが正確に1(tot_wgt)に合わなければならないという制約があります。 ifステートメントを追加することで、そのようなケースを単に破棄したいと考えました。

if (tot_wgt != 1): 
    continue 

残念ながら、コードはまだtot_wgtは1.本の価値を持っていないときに時々実行すると思われるヴァル・ループがサイクルを完了した(そしてときに、他の3の各おそらくも発生しているたびに発生するようですループは1サイクルを完了した)。

問題解決:私はインデントエラーがありました。私は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> 

答えて

4

これは、コンピュータハードウェアの浮動小数点数をベース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にequvelentされていません。それを解決する1つの簡単な方法は、

if abs(tot_wgt - 1) < 0.0001 : 

のPython 3.5は、おおよその平等をテストするためmath.iscloseを追加して、ちょうどラインとif (tot_wgt != 1):交換することです。以前のバージョンでは、同等の機能は次のとおりです。

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を使用して、2つの配列が要素内で許容値内で等しいかどうかをテストします。

# 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]) 
+1

ありがとうございます。はい、私はそれも問題になるかもしれないと思っていた、あなたの解決策はエレガントです。 – Carl

関連する問題