日経アメリカ株式市場アービトラージ プログラミングで説検証
公開日:
:
無料配布EA(MT5 用), 初心者EA自作, MT5/MQL5
目次/もくじ
よく「日本の株式市場は前日のニューヨーク市場の後追いをする」と言われています。実際に裁量トレードするときも、ニューヨークが大きく動いた場合には翌朝の日経225の方向性の参考にされます。
しかし、そもそも日本の株式市場がアメリカの後追いをするのにどれだけの優位性があるのかをちゃんと数字で示した根拠はありません。
そこで今回は実際にプログラミングを組んでみて、もし本当に日経がアメリカ市場の後追いをするなら、その自動売買で一儲け、もし日経がアメリカ市場の後追いをすると言えないなら、嘘を暴いたということで検証します。
日経がアメリカ市場を後追いするなら…
上:日経225日足チャート 下:SP500日足チャート コロナショック時
日足で見比べてみると確かに相関はありそう、というかほぼ一緒。
世界的なコロナショックが原因でたまたま同じようなチャートになった可能性もあるので、他の期間もランダムに調べてみると、
上:日経225日足チャート 下:SP500日足チャート 2018/9/20~2019/1/14
どうやら日足チャートには強い相関がありそうです。次に1時間足で詳しく見てみます。
上:日経2251時間足チャート 下:SP500 1時間足チャート
どうやら日足未満のロウソク足チャートでも相関があるようです。
しかし、今回調べたいのは二つのインデックスの相関のレベルではなく、”ニューヨークが先行しているかどうか”なので、これでは不十分です。
日経とニューヨーク市場のセオリーの確認
まず、おさらいですが、ニューヨーク市場にはダウとSP500があります。ダウは注目度としては高いですが、30社の平均であるという時点で数字的にはSP500の方が安定しています。(一社の突発的な影響力が小さい)
もともとダウはコンピュータがなかった時代に手計算で即座に計算できるのが30社であった、という名残りなのでニューヨーク市場のトレードシンボルはSP500にします。
また、日経は日経225です。TOPIX400を採用しているブローカーならTOPIXの方が良いかもしれません。
ベースとなる古典的戦略は、
- ニューヨーク市場が日足単位(始値ー終値)で〇point以上上がったら、日経で買い
- ニューヨーク市場が日足単位(始値ー終値)で〇point以上下がったら、日経で売り
が基本方針です。
ただし、アジア時間とアメリカ時間は、グリニッジ標準時の関係でアジア時間が先に来ます。金曜日の夜のニューヨークの値動き月曜日の日経にまで影響するには2日空いてしまうので、月曜日に関しては条件を満たしていてもエントリーを見送ります。
日に行うトレードは1回のみです。
また、決済に関しては日足をまたぐポジションの保有はせずに、遅くとも日経の日足の更新のタイミングで損益に関わらず決済します。また、指値・逆指値決済はパラメータで可変な値に設定します。
決済
- 日をまたがずに決済(新しい日足が出たら即決済)
- 損切り、利確はエントリーレートからの固定幅(パラメータ変更可)
2つのチャートを同時に過去検証できるのは
MT4のバックテストでは、一つのチャートのデータを参考にして別のチャートでエントリー&決済する、という処理ができません。日経225チャートにセットしても、SP500のチャートデータを参照することができずに、エラーになります。
(ライブトレードであれば可能です。)
そのため、バックテストでこのロジックを検証するためにはMT5&MQL5による開発が必要です。
MT5でインデックスが検証&トレード可能な業者
海外FX業者であればインデックスのトレードはどこでもできるので、どの業者でもOKです。
https://fxantenna.com/mt5-company/
ただし、日本国内のMT5対応の業者では、インデックスのトレードができないことが多いので、事前によく調べておいた方が賢明です。
コーディング
基本的戦略が古典的なので、このプログラミングは超簡単です。
エントリー
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
//Entry if( ThisPairsPositionTotal() < MaxPosition_thisPair && TimeCurrent() > LastOrderCloseTime + 60*60*24 && DateTime.day_of_week != 1 ) //月曜日はエントリーしない { //Buy Entry Condition if( iClose(SP500SymbolName,PERIOD_D1,1) - iOpen(SP500SymbolName,PERIOD_D1,1) >= EntryGap_in_point*_Point ) { Print("Order send to broker server now-------------------------------------------"); OrderSending(0); Print("Order Ticket returned now"); NikkeiOpenWhenEntry = iOpen(Nikkei225SymbolName,PERIOD_D1,1); } //Sell Entry Condition if( iOpen(SP500SymbolName,PERIOD_D1,1) - iClose(SP500SymbolName,PERIOD_D1,1) >= EntryGap_in_point*_Point ) { Print("Order send to broker server now-------------------------------------------"); OrderSending(1); Print("Order Ticket returned now"); NikkeiOpenWhenEntry = iOpen(Nikkei225SymbolName,PERIOD_D1,1); } } |
決済
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
//Close-------------------------------------- int OrdersTotal_ = PositionsTotal(); for(int i=0; i<OrdersTotal_;i++) { if( PositionGetTicket(i)>0 ) { if( PositionGetInteger(POSITION_MAGIC) == Magic && PositionGetString(POSITION_SYMBOL) == Nikkei225SymbolName ) { //日足が変わったら問答無用で決済 if( NikkeiOpenWhenEntry != iOpen(Nikkei225SymbolName,PERIOD_D1,1) ) { OrderClose(PositionGetTicket(i)); } if( PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY ) { //Nomarl Exit if( SymbolInfoDouble(Symbol(),SYMBOL_BID) - PositionGetDouble(POSITION_PRICE_OPEN) > TP_in_point*_Point ) { Print("Exit order is sending now"); OrderClose(PositionGetTicket(i)); LastOrderCloseTime = TimeCurrent(); Print("EXIT order returned now"); Print("EXIT"); Print("MarketInfo Spread for Exit "+SymbolInfoInteger(Nikkei225SymbolName,SYMBOL_SPREAD)+" point"); } //Failsafe Exit(Market SL) else if( PositionGetDouble(POSITION_PROFIT) < 0 && PositionGetDouble(POSITION_PRICE_OPEN) - SymbolInfoDouble(Nikkei225SymbolName,SYMBOL_BID) > SL_in_point*_Point ) { Print("Exit by SL"); OrderClose(PositionGetTicket(i)); LastOrderCloseTime = TimeCurrent(); } } else if( PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL ) { //Normal Exit if( PositionGetDouble(POSITION_PRICE_OPEN) - SymbolInfoDouble(Nikkei225SymbolName,SYMBOL_ASK) > TP_in_point*_Point) { Print("Exit order is sending now"); OrderClose(PositionGetTicket(i)); LastOrderCloseTime = TimeCurrent(); Print("EXIT order returned now"); Print("EXIT"); Print("MarketInfo Spread for Exit "+SymbolInfoInteger(Nikkei225SymbolName,SYMBOL_SPREAD)+" point"); Print("-------------------------------------------"); } else if( PositionGetDouble(POSITION_PROFIT) < 0 && SymbolInfoDouble(Symbol(),SYMBOL_ASK) - PositionGetDouble(POSITION_PRICE_OPEN) > SL_in_point*_Point ) { Print("Exit by SL"); OrderClose(PositionGetTicket(i)); LastOrderCloseTime = TimeCurrent(); } } } } } |
MT5にはネッティングタイプとヘッジタイプがあり、それぞれオーダーの仕方が異なるので、汎用型のオーダー関数を作っておくと便利です。特に決済の処理には場合分けが必要です。ただし、最近はヘッジタイプの口座しか見かけないので、ヘッジ専用で作ってもまず問題はないと思います。
どちらかと言うと、採用しているフィリングモードによるエラーの方が多発しやすいので、フィリングモードをEAのパラメータで選択できるようにしておくとよいでしょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
enum FillingType{ FOK = ORDER_FILLING_FOK, IOC = ORDER_FILLING_IOC, Return = ORDER_FILLING_RETURN }; input FillingType FillingMode; static int FillingMode_; void OrderSending(int Direction) { MqlTradeRequest TRequest; MqlTradeResult TResult; ZeroMemory(TRequest); ZeroMemory(TResult); if( Direction == 0 ) { TRequest.type = ORDER_TYPE_BUY; TRequest.price = SymbolInfoDouble(Nikkei225SymbolName,SYMBOL_ASK); Print("Order send Ask is "+TRequest.price); } else if( Direction == 1 ) { TRequest.type = ORDER_TYPE_SELL; TRequest.price = SymbolInfoDouble(Nikkei225SymbolName,SYMBOL_BID); Print("Order send Bid is "+TRequest.price); } TRequest.volume = Lot; TRequest.action = TRADE_ACTION_DEAL; TRequest.symbol = Nikkei225SymbolName; TRequest.sl=0; TRequest.tp=0; TRequest.magic = Magic; TRequest.comment = ""; TRequest.deviation = Slippage_in_point; TRequest.type_filling = FillingMode_; R = OrderSend(TRequest,TResult); if( !R ) Print("OrderSend for Open was rejected"); //we should check the return just in case. } void OrderClose(int Ticket) { MqlTradeRequest CRequest; MqlTradeResult CResult; ZeroMemory(CRequest); ZeroMemory(CResult); //ネッティングタイプの場合(ポジションが合体させられる場合)------------------------------------------------------------ if( AccountInfoInteger(ACCOUNT_MARGIN_MODE) == ACCOUNT_MARGIN_MODE_RETAIL_NETTING ) { //そのポジションと逆向きに同じ量の反対ポジションをとる R = PositionSelectByTicket(Ticket); if( PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY ) { CRequest.type = ORDER_TYPE_SELL; CRequest.price = SymbolInfoDouble(PositionGetString(POSITION_SYMBOL),SYMBOL_BID); Print("Order close Bid is "+CRequest.price); } else if( PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL ) { CRequest.type = ORDER_TYPE_BUY; CRequest.price = SymbolInfoDouble(PositionGetString(POSITION_SYMBOL),SYMBOL_ASK); Print("Order close Ask is "+CRequest.price); } CRequest.action = TRADE_ACTION_DEAL; CRequest.symbol = PositionGetString(POSITION_SYMBOL); CRequest.volume = PositionGetDouble(POSITION_VOLUME); CRequest.sl=0; CRequest.tp=0; CRequest.magic = PositionGetInteger(POSITION_MAGIC); CRequest.comment = PositionGetString(POSITION_COMMENT); CRequest.type_filling = FillingMode_; R = OrderSend(CRequest,CResult); if(!R) Print("OrderClose was rejected"); } //ヘッジタイプの場合(MT4ライクな場合)------------------------------------------------------------------------- if( AccountInfoInteger(ACCOUNT_MARGIN_MODE) == ACCOUNT_MARGIN_MODE_RETAIL_HEDGING ) { m_trade.PositionClose(Ticket,Slippage_in_point); } } |
MT5には標準ライブラリのCTradeがあるのでそれを使うとまた楽ちんです。
1 2 |
#include <TradeTrade.mqh> CTrade m_trade; |
いよいよ検証
このロジックは基本は日足単位でトレードの判定を行うので、検査期間を長めに設定します。これによって短い時間足のヒストリーデータが取得できなくなる可能性があるので、テスト方式は全ティックではなくても可です。(ヒストリーが少なすぎるとストラテジーテスターがテストを拒否する可能性があります。)
パラメータ(SL/TP/SP500がどれくらい上下したらエントリーするか)は全探索の最適化をします。
SL/TP/SP500がどれくらい上下したらエントリーするか 最適化3Dグラフ
3つ同時にテストしたらよく分からない結果になったので、まずSP500が上下したと判定するための値幅を決定します。
2018年2月から2020年4月までの期間で、この条件が発生する回数を考えると、エントリーするためのSP500のギャップは400~750程度であることがざっくりと分かります。テストした業者のSP500の小数点桁数は4~7.5USDです。
SL/TPで決済しないように大きな数字にして、日足の終わりで決済する条件でテストしてみると…
何とも言えないグラフになりました。
ここから少し改良します。
[非公開コンテンツ]
EAの使い方
日経225のチャートにセットしてください。(EAの内部で日経225縛りをしているので、他のチャートにセットしても大丈夫ですが…)
- Lot: トレードロット。日経225はFXとは最小ロットが異なる可能性があります。
- SP500SymbolName:利用しているMT5上でのSP500の名称を入れてください。
- Nikkei225SymbolName:利用しているMT5上での日経225の名称を入れてください。(例:Nikkei, Nikkei225, JP225)
- EntryGap_in_point:日経225で順張りエントリーするためのSP500の値動き幅(point単位) 業者によって最小桁数が違うので注意
- TP_in_point: 日経225でのポジションの利確幅(ポイント単位)
- SL_in_point: 日経225でのポジションの損切幅(ポイント単位)
- FillingMode:MT5の注文方法。フィリングモード。エントリーしなかったらこれを変えてみてください。
このEAのダウンロード
「日経225がSP500の後追いをするなら」EAのダウンロード
現在、EAを持て余したプログラマによる EA無料使い放題企画をしています。EAのパスコードは企画参加者に配布しています。
詳しくはこちら
テーマ2:日経225とSP500でアービトラージ/裁定取引
日経がアメリカ市場を後追いするというのがもはや過去のセオリーであるという確率が高いと判明したので、その過程で発見した仮説”日経225とSP500には相関がある”というロジックを今度は検証します。
日経225とSP500はグラフのぱっと見は似ていますが、縦軸のスケールに大きな違いがあります。そのため、単純なレートの比較ではトンチンカンな比較になってしまいます。
二つの縦軸が異なるグラフを比較する方法には様々なものがありますが、ここではもっとも単純で分かりやすい”レートの変化倍率の差”を使います。
”レートの変化倍率の差”とはいいかえると、ある一定期間に何%上下に変位したかを表します。つまり、ROCのことです。ROCはレートの変化倍率を表したテクニカル指標であり、ROCの比較をすることにより縦軸の値を統一することができます。
ROC = ((CLOSE (i) – CLOSE (i – n)) / CLOSE (i – n)) * 100
ただし:
CLOSE (i) – 現在足の終値;
CLOSE (i – n) – n本前の終値;
ROC – ROCの値
ROCを使うと「何日前から差をとるか」という問題が発生します。これは通貨強度のときにもよく問題になるテーマです。しかし、二つの類似したグラフを比較をする際にはどうしても比較対象の”起点”が発生してしまいます。
とりあえず、今は目をつぶりましょう。
ROCはMT5には標準搭載されていないので、関数化します。
1 2 3 4 5 6 |
double iROC(string Symbol_,int Periods_, int ROC_period_) { double ROC; ROC = 100*(iClose(Symbol_,Periods_,0) - iClose(Symbol_,Periods_,ROC_period_))/iClose(Symbol_,Periods_,ROC_period_); return(ROC); } |
このROCはオリジナルで、ROCのコーダーによっては分母が現在の終値の場合もあります。
あとのロジックはかんたんで、単純に日経225のROCとSP500のROCに乖離が生じたら、両建てエントリー。乖離が閉じたら決済するだけです。
2020/2/1~2020/4/14 H1 日経225vsSP500さや取り結果 ROCの差:3でエントリー
最適化する前のバックテストでも良い成績であることがわかります。スプレッドはMT5なのでリアルスプレッドです。(日経:1600 SP500:100)
エントリーの条件となるROCの差の数値だけ最適化します。
すると、
どの数値でもプラスにすることができていますが、数値が少ない方がトレード回数が増えて最終的な利益が大きくなることが分かります。
2020/2/1~2020/4/14 H1 日経225vsSP500さや取り結果 ROCの差:1でエントリー
極値が見えていないので、さらに、細かく最適値を探索してみます。1.0周りで同じ期間最適化をします。
すると、どうやら1.0よりもさらに小さい値の方が良いことがわかります。
さらに繰り返します。
一応、0.06近辺に極値のようなものがありますが、あまりに取引回数が多くなりスプレッドの影響が大きくなりそうなので、ここら辺でやめておきます。テストしているMT5の口座がECNで実際にトレードするときには別途取引手数料がかかるのですが、バックテスト上ではその取引手数料が考慮されていない可能性があります。
とりあえず、現実的にはEntryはROCの差が0.1前後あたりがよさそうです。
2020/2/1~2020/4/14 H1 日経225vsSP500さや取り結果 ROCの差:0.1でエントリー ROC期間:7
約定までの遅延が大きいと右肩上がりのグラフにならない可能性があります。ping=200msなどは厳しいです。
ただ、この最適化は過剰最適化や異常値の可能性がほぼないので、実際のトレードで勝てるかどうかは別にしても、相場の中にある法則性を一つ見つけた、と言えるのではないかと思います。
ちなみに、テストする際に「リアルティックに基づいたすべてのティック」以外のモード、たとえば「全ティック」にすると存在しない疑似ティックでオーダー条件が満たされることがあります。しかし、その瞬間で成り行き注文してもテスター上では「Invalid Price」となって注文が通らないことがあります。
もしグラフが右肩下がりになった場合はそのMT5上のバグというか瑕疵というか仕様による原因の確率が高いです。リアルティックに基づいたすべてのティックでテストしてみてください。
リアルティックヒストリーデータはDukascopyのサイトで入手できます。
ちなみにTradeViewでテストしたのですが、TradeViewではSP500のスプレッドと比べて日経225のスプレッドが広大です。
日経225に関してはXMの方がスプレッドが狭いです。
TitanFXもTradeViewと似ていますが、SP500はちょっとだけ安いです。
両建てをやめてSP500だけでエントリーするという手もあります。
2020/2/1~2020/4/14 M1 日経225vsSP500 SP500のみエントリー ROCの差:1でエントリー ROC期間:500
ROCの起点の問題については、時間足の選択+ROCの期間=起点とする時間なので、1分足でROCの期間を最適化すれば滑らかな起点の最適化が可能です。
具体的に言うと、
”1時間足チャートでROCの期間を7”とするのは、”1分足チャートでROCの期間を7*60=420”とするのと同じです。(注:これはROCにのみ適応されます。他のテクニカルの場合にも同じことが言えるとは限りません。)
つまり、1分足チャートでROCの期間だけを最適化すれば、時間枠の最適化は必要ない、ということになり、最適化の変数を一つ減らすことができます。
日経225 SP500裁定取引EA 使い方
- Lot: トレードロット。日経225はFXとは最小ロットが異なる可能性があります。
- SP500SymbolName:利用しているMT5上でのSP500の名称を入れてください。(SP500, SPX, US500)
- Nikkei225SymbolName:利用しているMT5上での日経225の名称を入れてください。(例:Nikkei, Nikkei225, JP225)
- TradeSP500:SP500をトレードする
- TradeNikkei225: 日経225をトレードする
- ROC_EntryGap:エントリーするROCの差。この値以上の差が発生したら両建てエントリーします。
- ROC_ExitGap: 決済するROCの差。この値未満になったら決済します。
- ROC_period: ROCの期間(比較期間)
- FillingMode:MT5の注文方法。フィリングモード。エントリーしなかったらこれを変えてみてください。
このEAは日経225かSP500のチャートどちらかに一つのチャートにセットすればOKです。2枚セットする必要はありません。また、業者によってはどちらも同時にエントリーできない時間帯がある場合があるので、取引可能時間帯を必ずチェックしてください。
日経225 SP500 裁定取引EAダウンロード
現在、EAを持て余したプログラマによる EA無料使い放題企画をしています。EAのパスコードは企画参加者に配布しています。
詳しくはこちら
更新情報
2020/4/19 いろいろバグ修正。ポジションの最小保有時間を指定できるように改良。MinTradeInterval_Sec
結論
「日経225はSP500の後追いをする」というセオリーは情報が電子ネットで飛び交う今の時代のものではなく、いにしえのセオリーだといった方が賢明です。
むしろ現在の電子取引が当たり前の社会では、日経とニューヨーク市場がリアルタイムで相関関係にあるといった方がより正確で、二つのチャートを利用したトレードを行うのであれば、日経225とSP500でさや取り、両建てトレードした方がトレードチャンスがあると考えられます。
ただ、ここまで日経とSP500に相関がありすぎると、日本とアメリカの経済事情の差などがまったく無視されているのではないかと思います。本来であれば、日本とアメリカの市場の差が相場にも反映されるはずなのに、ほぼ同じような関数を描くというのは、アナリストや経済評論家が思っているほど相場の変数は多くないのかもしれません。
次に問題となるのは、では香港市場やフランス市場、ドイツ市場などの他の国のインデックスはどういった相関があるのか、という点です。たまたま、日本と所縁があるせいでアメリカと日本で検証しましたが、他により強い相関がある市場があれば日経を選ぶ必然性はありません。
この後、学術的な方面に進むのであれば、「なぜ各国の経済事情はさまざまなのに、結局アメリカ市場の追随をしてしまうのか」や「各国のインデックスがアメリカ市場を模倣する理由」などをつらつらと研究すれば良いのでしょうが、トレーダーからしてみると金さえ稼げればそんなことは割とどうでもいい(‘ω’)ので、稼げるうちにさっさと稼いでしまうのが結局のところ経済合理性なのかと思います。
関連記事
-
プライスアクションEA (MT5) 勝てる[無料配布]
バックテスト結果 GBPUSD 2019/1/1~2019/12/31 M30
-
初心者向けMT5の使い方 インストールからバックテスト
MT5はMT4に慣れ親しんだトレーダーであれば比較的簡単に移行することができるトレードプラットフォー
-
(MQL4)初めてのEA自作のための教科書~実用編~[EA自作]
実用に向けたEAのコーディングについて説明します。本当に1からEAの開発について知りたい方はこちら。
-
MACDのEA(MT5)FX 仮想通貨対応[無料]
MACD, ストキャスティクス, モメンタムのEAです。 バックテスト結果
-
短いコードでも右肩上がりのグラフにできることの証明(MT4EA)非実用
バックテスト結果 ソースコードはこちら 33行あるやんけ...
コメント
同じ条件と期間でBTしてみても、ROC差は0.8が最適で0.1とかになると爆損になりますね・・・なぜ違いが出るんでしょう。損益も、右肩あがりというよりは横ばいが長くてたまにドカッと上がる感じのグラフになりますね。
ROC期間は、分足500が最適なのは共通してるのですが。
SP500とダウで裁定取引するとそんな感じになりますが、Nikkeiの代わりにUS30になってませんか
いえ、Nikkeisymbolnameのパラメータはちゃんと日経になっていました。
あとリアルタイムで1日監視してみましたが、SP500日経のROC差は0.3~1.2が多いような印象でした。
0.1だと、常にエントリーしている状態になる気がしますね。。。
もし0.1でリアルトレードでも爆益ならもちろんそれがベストだと思いますので、ご報告お待ちしておりますm(__)m
確かにライブ口座でリアルトレードするときは、1.0~の方が堅実だと思います。
レイテンシーアービトラージ同様に、業者によって設定値は細かく調整するべき類の代物だと思います。
今はコロナショックがひと段落して相場自体がちょっと凪の状態ですが、荒れ相場になったら期待ですね。
2週間くらいライブでROC0.7エントリー設定ですが勝ち負けトントンで経過しています。
エントリー直後に担がれることは少ないため、負ける場合はs/l直行というよりは、「方向が合っていて大幅プラスだったのに、ROC差が開いたまま決済されずに逆行していき結局s/lで決済」ということが多々あります。
決済はトレーリングストップを入れるとだいぶ勝てるような印象があります。ご検討いただければと思います。もしくは裁量で決済を入れるだけでもいいかもしれませんが。。
「方向が合っていて大幅プラスだったのに、ROC差が開いたまま決済されずに逆行していき結局s/lで決済」
と
決済はトレーリングストップを入れるとだいぶ勝てる
が相反するということはおいておいて、
欲張らずにササっと利確すべきだという点は賛成です。
タートルズ様(よう)のATRによるSLTP決済も実装しているので、それはできると思います。
s/lという表現は間違ってましたね。SP500をbuyで入って大幅プラスの状態から、ROC差が縮まらずに(決済されずに)SP500が落ちて行って損益がマイナスに転じるという現象です。
Exit gapをデフォルトの0から上げるとトレーリングストップの代わりになりそうなので、試してみようと思います。
EAの概念的にも、トレーリングストップで単一株価の動きで決済するよりROC差の動きで最大利益を狙うほうが合ってるような気もしますし。
すみません。日経の個別株のイナゴトレードのEAと勘違いしていました。
確かに、こっちの場合、
「方向が合っていて大幅プラスだったのに、ROC差が開いたまま決済されずに逆行していき結局s/lで決済」
と
決済はトレーリングストップを入れるとだいぶ勝てる
という確からしいですね。こっちにはATRによる損切機能などはないので、追加した方が良いかもですね。
ご検討ありがとうございます。
話は変わりますが、日経とSP500の関連より、ダウとナスダックの方が関連性は強く、かつ大体の場面でナスダック>(SP500)>ダウの強弱の相関があるように思えます。
ダウ売りナスダック買いの両建てで差分を取るというつまらない案しか浮かんでこないのですが、もしなにかの参考になれば・・・。
パラメータ設定で日経とSP500の箇所をナスダックとダウにすればナスダックとダウの裁定取引EAになりますよ。
インデックスCFD裁定取引EAのコメント欄のCAPTCHAが壊れてたのでこちらにコメントします。
SP500とEU50でやっているのですが、決済が片方取り残される現象が起こりました。
22:59:40にSP500の方のみクローズし、EU50は3:15市場が開いた時に決済しマイナスが多くなってしまいました。
片方のティックが来てない時は決済をせずホールドする方が傷は少なくなりそうですが、そういった機能はどうでしょうか?
ティックというよりは相場の開いている時間が異なる業者間で週末にポジションを持ち越したことが原因ですね。
両建てアービトラージの場合、さやが縮まるのが短期間であると確定しているのであれば、週末直前はエントリーしないという方法も可能ですが、
場合によっては何日もレート差が縮小しないというケースの方が多いので、下手に決済する機能をEA内部に付けない方が良いとは思います。