「コナーズの短期売買実践」のトレード戦略のEA化【第3弾】
トレンドフォローの押し目、戻りを狙った王道の戦略。バックテストは以下の条件で実施しました。
- 対象EA:TripleDayPullBack
- 通貨ペア:EURUSD
- ローソク足の種類:始値のみ
- モデル:全ティック
- スプレッド:3pips固定
- バックテスト期間:2008/1/1~2016/7/5
- ヒストリカルデータ:Dukascopy社のJForexからダウンロードした1分足
- 初期口座残高:10,000ドル
- ロット数:0.01固定
結果はこちらです。
実はひっそりとパラメータをいじっています。具体的にはADXは25でも30でもなく35に、手仕舞いは6本目ではなく7本目(仕掛けてから3本後)にしています。
これぞカーブフィッティング!(笑)
日足ではパラメータに手を加えることで、ようやくプラスになるEAになりましたが、1時間足や4時間足では何をやってもマイナスのままでした。
2011年6月に出版された書籍ですが、本書内で使われているデータは古く、1990年代だったりします。相場は変わってしまったと見るべきなのでしょうか…。
とは言え、まだ3つの手法しか試していません。現在の相場では使えないと断定するには早すぎますね。作ったコードは再利用できますので、めげずにこれからもどんどん作っていこうと思います!
TripleDayPullBack.mq4のコードを公開しますので、良かったら参考になさってください。
//+------------------------------------------------------------------+ //| Sample.mq4 | //| Copyright (c) 2016, りゅーき | //| https://autofx100.com/ | //+------------------------------------------------------------------+ #property copyright "Copyright (c) 2016, りゅーき" #property link "https://autofx100.com/" #property version "1.00" //+------------------------------------------------------------------+ //| ライブラリ | //+------------------------------------------------------------------+ #include <stderror.mqh> #include <stdlib.mqh> #include <WinUser32.mqh> #include <Original/Application.mqh> #include <Original/Basic.mqh> #include <Original/DateAndTime.mqh> #include <Original/LotSizing.mqh> #include <Original/OrderHandle.mqh> #include <Original/OrderReliable.mqh> //+------------------------------------------------------------------+ //| 定数 | //+------------------------------------------------------------------+ // #define //+------------------------------------------------------------------+ //| EAパラメータ設定情報 | //+------------------------------------------------------------------+ extern string Note01 = "=== General =================================================="; extern int MagicNumber = 7777777; extern int SlippagePips = 5; extern string Comments = ""; extern double FixLotSize = 0.01; extern string Note02 = "=== Entry ===================================================="; extern int ADX_Period = 14; extern double ADX_Value = 25.0; extern string Note03 = "=== Exit ====================================================="; extern double SL_Pips = 0.0; extern double TP_Pips = 0.0; extern int ExitInterval = 2; /* extern string Note03_1 = "--- Trailing Stop --------------------------------------------"; extern bool UseTS = false; extern double TS_StartPips = 15.0; extern double TS_StopPips = 10.0; */ //+------------------------------------------------------------------+ //| グローバル変数 | //+------------------------------------------------------------------+ // 共通 double gPipsPoint = 0.0; int gSlippage = 0; color gArrowColor[6] = {Blue, Red, Blue, Red, Blue, Red}; //BUY: Blue, SELL: Red int gPrvBars = 0; // バックテストでひとまず動作確認しているだけなので、仕掛け時のローソク足本数はグローバル変数でOK。 // 但し、実運用を考えた場合、ポジション保有中にMT4を閉じるケースを考慮する必要がある。 // そうしないと、そのポジションは永遠に手仕舞いされ無くなってしまう。 // ※グローバル変数の格納先はメモリで、メモリ上のデータはMT4のプロセスが終了してしまうと消えてしまう int gEntryBars = 0; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { gPipsPoint = currencyUnitPerPips(Symbol()); gSlippage = getSlippage(Symbol(), SlippagePips); gPrvBars = Bars; return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { int currentBars = Bars; // ----------------------------------------------------------------- // 手仕舞い // ----------------------------------------------------------------- if(gEntryBars != 0 && Bars - gEntryBars >= ExitInterval){ allOrderClose(MagicNumber, gSlippage); gEntryBars = 0; } /* if(UseTS){ trailingStopGeneral(MagicNumber, TS_StartPips, TS_StopPips); } */ // ----------------------------------------------------------------- // 仕掛けフィルター // ----------------------------------------------------------------- // 新しい足を生成した時ではない場合は、仕掛けない if(currentBars == gPrvBars){ gPrvBars = currentBars; return; } // オーダーが1つ以上ある場合は、仕掛けない double orderNum = sumOrderNumberOrLotSize(OP_OPEN, MagicNumber, SUM_ORDER_NUMBER); if(orderNum > 0.0){ gPrvBars = currentBars; return; } // ----------------------------------------------------------------- // 仕掛け // ----------------------------------------------------------------- double ADX = iADX(NULL, 0, ADX_Period, PRICE_CLOSE, MODE_MAIN, 1); double P_DI = iADX(NULL, 0, ADX_Period, PRICE_CLOSE, MODE_PLUSDI, 1); double M_DI = iADX(NULL, 0, ADX_Period, PRICE_CLOSE, MODE_MINUSDI, 1); double open1 = NormalizeDouble(Open[1], Digits); double open2 = NormalizeDouble(Open[2], Digits); double open3 = NormalizeDouble(Open[3], Digits); double close1 = NormalizeDouble(Close[1], Digits); double close2 = NormalizeDouble(Close[2], Digits); double close3 = NormalizeDouble(Close[3], Digits); if(ADX > ADX_Value){ if(P_DI > M_DI){ if((close3 < open3 && close2 < open2 && close1 < open1) && (close3 > close2 && close2 > close1)){ int ticket = orderSendReliableRange(Symbol(), OP_BUY, FixLotSize, Ask, gSlippage, SL_Pips, TP_Pips, Comments, MagicNumber, 0, gArrowColor[OP_BUY]); gEntryBars = Bars; } }else if(M_DI > P_DI){ if((close3 > open3 && close2 > open2 && close1 > open1) && (close3 < close2 && close2 < close1)){ ticket = orderSendReliableRange(Symbol(), OP_SELL, FixLotSize, Bid, gSlippage, SL_Pips, TP_Pips, Comments, MagicNumber, 0, gArrowColor[OP_SELL]); gEntryBars = Bars; } } } // 本来はticketの値によって後続の処理を制御する必要があるが、簡単のため、ここでは無視 gPrvBars = currentBars; }