考え方とコード
先日ブログにメモとして残したロジック(OS_OF_ver4)に対して,下記変更を加えた.
- 売買判定条件にRSIを加え,高値掴みを避ける.
- トレンド判定やナンピン判定,損切判定のスレッシュを,直近の最大レートに対する割合で設定
- ナンピン条件を見直し(一定レート差で注文するように)
# 長期トレンドに従いつつ,8時間足には逆らうヤーツ.一応,USD,EUR,GBP,AUD,NZD,CADすべてで,2002~2020年トータルで黒字. # 統一ラベル化 # 210101 改修中. 注文時の通貨量を,口座残高に応じて決める.具体的には,残高×1/(10×5回×Nペア分)とする. # 210106 改修中. ナンピンロジックを変更(終値とポジション平均レートの差がdV→終値と端っこのポジションレートの差がdV). def OS_OF_ver6(InputData_DF, jNow,Posi_pre,Vp_pre, Balance,Npair,Amount): #jNowは,売買判断に使う最新足の位置を決定.何もなきゃ0.ひとつ前の足なら1 N_RSI=6 #RSIのスレッシュ判定に用いる足の本数 Settle = 0 Order = 0 #パラメータ初期化 N_Data = len(InputData_DF) - jNow Vc_Y = np.zeros((N_Data, 1)) delta_LS2_L_Y = np.zeros((N_Data, 1)) LS2_L_Y = np.zeros((N_Data, 1)) RSI_Y= np.zeros((N_Data, 1)) #パラメータ代入 for jj in range(N_Data-1): Vc_Y[jj] = InputData_DF.at[jNow+jj, "Vc"] delta_LS2_L_Y[jj] = InputData_DF.at[jNow+jj, "LS2_120"] - InputData_DF.at[jNow+jj+1, "LS2_120"] LS2_L_Y[jj] = InputData_DF.at[jNow+jj, "LS2_120"] RSI_Y[jj] = InputData_DF.at[jNow + jj, "RSI"] #スレッシュ定義 Thre_LS2_L = max(Vc_Y[0:N_Data-1])*0.00037 #0.0003~5 MaxNamPin=5 #各通貨ペアの,新規注文上限.例えば,買い注文は,初回+MaxNamPin-1回分,ナンピン買い出来る Loss = max(Vc_Y[0:N_Data-1])*0.025 # 損切ラインをどう設定するかね.直近の終値最高値×0.02~0.03あたり. dV_GRD = max(Vc_Y[0:N_Data - 1]) * 0.01 # USDで1円設定がロバストだった dV_NamPin = max(Vc_Y[0:N_Data - 1]) * 0.0015 # For ver6. 0.001~0.003? Trend0_L = 0 if delta_LS2_L_Y[0] > Thre_LS2_L: Trend0_L = 1 if delta_LS2_L_Y[0] < -Thre_LS2_L: Trend0_L = -1 # 実際は回数ではなくて,ポジション量で上限を切る. MaxAmount = (MaxNamPin - 1) * Amount # 買い注文ロジック if Posi_pre <=0 : if Trend0_L==1 and Vc_Y[0]-Vc_Y[1]<0 and Vc_Y[0]-LS2_L_Y[0]<dV_GRD and min(RSI_Y[0:N_RSI])<55: Order = Amount elif Posi_pre <=MaxAmount: #if Vc_Y[0]<Vp_pre-dV_NamPin: if Vc_Y[0] < Vp_pre - dV_NamPin/2*(Amount+abs(Posi_pre))/Amount: Order = Amount # 売り注文ロジック if Posi_pre >= 0: if Trend0_L==-1 and Vc_Y[0]-Vc_Y[1]>0 and Vc_Y[0]-LS2_L_Y[0]>-dV_GRD and max(RSI_Y[0:N_RSI])>45: Order = -Amount elif Posi_pre >= -MaxAmount: #if Vc_Y[0] > Vp_pre+dV_NamPin: if Vc_Y[0] > Vp_pre + dV_NamPin/2*(Amount+abs(Posi_pre))/Amount: Order = -Amount # 買い玉を売り決済するロジック if Posi_pre > 0: if Trend0_L==-1: Settle=-1 if Vc_Y[0]-Vp_pre<-Loss:#損切り Settle=-1 # 売り玉を買い決済するロジック if Posi_pre < 0: if Trend0_L==1: Settle = 1 if Vc_Y[0]-Vp_pre>Loss:#損切り Settle=1 PosiMax = CalPosiMax_ver1(Balance) Amount_new = round(PosiMax / (Npair * MaxNamPin)) # 決済する際,それが損となるとき if (Settle == -1 and Vc_Y[0] < Vp_pre - 0.3) or (Settle == 1 and Vc_Y[0] > Vp_pre + 0.3): #ここで,Amountを更新 Amount = max(Amount_new, Amount) Amount=1000 #ここで固定すれば,一応注文量は常に固定となる return (Amount,Settle, Order) # 決済は±1か0で出力,新規注文は±通貨量かoで出力
バックテスト
2005~2020年のデータを使い,バックテストをしてみた.初回口座残高は50,000円,取引通貨量は1,000,スプレッドは0.03円(3銭)としてみた.通貨ペアはクロス円でUSD,CAD,EUR,GBP,AUD,NZDの6通りとし,すべて同じ定数設定で計算した.…損失が膨らむ年もあるけど,おおむね右肩上がりで収益を積み上げている.少なくとも大損はしないかな…思ったより悪くない…のか??
…正直このロジックが良いのかダメなのかわからない.とりあえず,同じ定数設定で長期的に損しないなら,まあいいかくらい.欲を言えば,損する年がないように改良したい.
…パフォーマンスが良いかの問題だが,例えば,ウォーレン・バフェット氏が率いるバークシャー社で,確か1年あたり20%のリターンを継続しているのが”驚異的”とのこと.福利がなければ,5年で2倍,15年で4倍か…上記バックテストに当てはめると,5万円を15年で20万円にできればバークシャー相当ということ…と考えると,バックテストの成績としては意外と悪くないのかもしれない.
…まあ,しょせんバックテストだから,こんなパフォーマンスを出せるとは思っちゃいけないのよ.きっと.
<USD_JPY>
<CAD_JPY>
<EUR_JPY>
<GBP_JPY>
<AUD_JPY>
<NZD_JPY>
コメント