2016-06-23 9 views
0
"""Some simulations to predict the future portfolio value based on past distribution. x is 
    a numpy array that contains past returns.The interpolated_returns are the returns 
    generated from the cdf of the past returns to simulate future returns. The portfolio 
    starts with a value of 100. portfolio_value is filled up progressively as 
    the program goes through every loop. The value is multiplied by the returns in that 
    period and a dollar is removed.""" 

    portfolio_final = [] 
    for i in range(10000): 
     portfolio_value = [100] 
     rand_values = np.random.rand(600) 
     interpolated_returns = np.interp(rand_values,cdf_values,x) 
     interpolated_returns = np.add(interpolated_returns,1) 

     for j in range(1,len(interpolated_returns)+1): 
      portfolio_value.append(interpolated_returns[j-1]*portfolio_value[j-1]) 
      portfolio_value[j] = portfolio_value[j]-1 

     portfolio_final.append(portfolio_value[-1]) 
print (np.mean(portfolio_final)) 

numpyを使用してこのコードを書き込む方法が見つかりませんでした。私はnditerを使って繰り返しを見ていましたが、私は先に進むことができませんでした。Numpyで次のループをベクトル化するにはどうすればよいですか?

+1

いくつかの質問:これは、ポートフォリオのパフォーマンスが10000とは独立した評価ですか?これは書かれているので、ポートフォリオの値の配列は10000 * 600の値でなければなりませんが、最初の600で作業するだけです。あるいは、コードを誤読していますか?また、 'portfolio_value.append(interpolated_returns [j-1] * portfolio [j-1])'行のポートフォリオは何ですか?それはあなたが一度初期化し、後で使用する600値の長い配列ですか?あるいは、実際にあなたのポートフォリオの進化があるように、代わりにportfolio_valueにする必要がありますか? –

+0

私はちょうどあなたのコメントを編集し、それを修正するコードを編集しました。 はい、10,000シミュレーションです。私は、ポートフォリオの進化の10000サンプルパスを作成したいと思います。 これは、10,000x600のマトリックスとしても実行できます。 このコード行については正しいですか。単一のシミュレーションで展開されるポートフォリオの価値を保持します。サンプルパスごとに再初期化されます(これはコードの誤りです)。 –

答えて

0

私はあなたのものをベクトル化する方法を理解する最も簡単な方法は、あなたの進化を支配する方程式を見て、あなたのポートフォリオが実際に反復する方法を見て、コードをベクトル化しようとする代わりにベクトル化できるパターンあなたはすでに持っています。あなたは、おしゃべりが実際にあなたの反復でかなり頻繁に現れることに気づいたでしょう。

ただし、以下の半ベクトル化コードを見つけることができます。結果を比較できるようにコードも含めました。私はまた多くのが簡単で数学的方程式に翻訳できるあなたのコードの単純なループバージョンを含んだ。このコードを他の人と共有するなら、私は間違いなく単純なループオプションを使用します。ファンシーパンツをベクトル化したい場合は、ベクターバージョンを使用できます。単一のステップを追跡する必要がある場合は、配列を単純ループオプションに追加し、すべてのステップでpvを追加することもできます。

希望に役立ちます。

編集:私はスピードのために何もテストしていません。それはあなたが簡単に時間を過ごすことができるものです。

import numpy as np 
from scipy.special import erf 

# Prepare simple return model - Normal distributed with mu &sigma = 0.01 
x = np.linspace(-10,10,100) 
cdf_values = 0.5*(1+erf((x-0.01)/(0.01*np.sqrt(2)))) 

# Prepare setup such that every code snippet uses the same number of steps 
# and the same random numbers 
nSteps = 600 
nIterations = 1 
rnd = np.random.rand(nSteps) 

# Your code - Gives the (supposedly) correct results 
portfolio_final = [] 
for i in range(nIterations): 
    portfolio_value = [100] 
    rand_values = rnd 
    interpolated_returns = np.interp(rand_values,cdf_values,x) 
    interpolated_returns = np.add(interpolated_returns,1) 

    for j in range(1,len(interpolated_returns)+1): 
     portfolio_value.append(interpolated_returns[j-1]*portfolio_value[j-1]) 
     portfolio_value[j] = portfolio_value[j]-1 

    portfolio_final.append(portfolio_value[-1]) 
print (np.mean(portfolio_final)) 

# Using vectors 
portfolio_final = [] 
for i in range(nIterations): 
    portfolio_values = np.ones(nSteps)*100.0 
    rcp = np.cumprod(np.interp(rnd,cdf_values,x) + 1) 
    portfolio_values = rcp * (portfolio_values - np.cumsum(1.0/rcp)) 
    portfolio_final.append(portfolio_values[-1]) 
print (np.mean(portfolio_final)) 

# Simple loop 
portfolio_final = [] 
for i in range(nIterations): 
    pv = 100 
    rets = np.interp(rnd,cdf_values,x) + 1 
    for i in range(nSteps): 
     pv = pv * rets[i] - 1 
    portfolio_final.append(pv) 
print (np.mean(portfolio_final)) 
+0

うわー。これは美しいです。魅力的で速く動作します。 'timeit'は5回の走行で2.32秒を与えてくれました。それを高速化する必要があり、それを行うためにcythonを使用します ありがとう!数学を分かったのだろうか。 –

0

np.nditerを忘れてしまった。反復のスピードは向上しません。あなたが1つに行き、Cバージョン(cython経由)を使用する場合にのみ使用してください。

私はその内側のループについて困惑しています。特別なことをやろうとしているのは何ですか?なぜループ?シミュレートされた値を持つ試験において

コードのこれら2つのブロックが同じものを製造:

interpolated_returns = np.add(interpolated_returns,1) 
for j in range(1,len(interpolated_returns)+1): 
    portfolio_value.append(interpolated_returns[j-1]*portfolio[j-1]) 
    portfolio_value[j] = portfolio_value[j]-1 

interpolated_returns = (interpolated_returns+1)*portfolio - 1 
portfolio_value = portfolio_value + interpolated_returns.tolist() 

Iはinterpolated_returnsportfolioは、同じ長さの1次元配列であると仮定。

+0

コードを変更しました。変数 'portfolio'は' portfolio_value'でなければなりません。 –

+0

その場合、 'np.cumprod'が役に立ちます。 – hpaulj

+0

はい、私はそれを試みましたが、ロジックは失敗します。私はその600回の反復ごとにポートフォリオから$ 1を取り除く必要があります。数学的には、それは正しくありません。 私が必要とするのは、減算の後に行われる次の乗算です。タンデムで。しかし、カンプroードは$ 1の減算を許さずに一度にすべての乗算を行います。 –

関連する問題