目次
前日の高値・安値
前日の高値・安値は、多くのトレーダーが意識しています。
そのため、そのラインを抜けた時には、値段が大きく動きやすいです。
トレードルール
メインルール
・前日の高値を上回ったら、買う
・前日の安値を下回ったら、売る
サブルール
・損切は10Pips、利確は20pips
・損切した場合、次のエントリーは30分以上経過してから行う
・利確した場合、その日はエントリーしない
ソースコード
※以下のソースコードは、
『FXメタトレーダー実践プログラミング (現代の錬金術師シリーズ)』(豊嶋久道)
で紹介されているライブラリーを使用しています。
そのため、コピペだと動きません。
EA自作に興味のある方は、この本の購入をお勧めします。
(自分で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 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 |
// // マイライブラリー #include <MyLib.mqh> // マジックナンバー #define MAGIC 20094060 #define COMMENT "前日ブレイク" // 外部パラメータ extern double Lots=0.1; extern int Slippage=3; extern int SLpips = 10; // 損切り値幅(pips) extern int TPpips = 20; // 利食い値幅(pips) extern int OffsetPips=1; //オフセット(pips)。規定値の場合、前日の高値・安値ラインより1Pips高い(安い)ラインで取引する extern double LimitSlowSlope=5;// 傾き判定の限度 extern ENUM_APPLIED_PRICE applied_price=PRICE_CLOSE; extern ENUM_MA_METHOD ma_method=MODE_EMA; //損切した場合、次のエントリーは30分(1800秒)以上経過してから行う extern int entryWaitTime=1800; //状態管理(最後にエクジットした時間を記録する) datetime _lastSucceededBuyExitTime=TimeCurrent(); datetime _lastFailedBuyExitTime=TimeCurrent(); datetime _lastSucceededSellExitTime=TimeCurrent(); datetime _lastFailedSellExitTime=TimeCurrent(); //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ int EntrySignal(int magic) { // オープンポジションの計算 double pos=MyCurrentOrders(MY_OPENPOS,magic); //前日の高値・安値 double yesterday_high=iHigh(NULL,PERIOD_D1,1); double yesterday_low=iLow(NULL,PERIOD_D1,1); bool isHighPriceBreak=Close[0]>yesterday_high+OffsetPrice(); bool isLowPriceBreak=Close[0]<yesterday_low-OffsetPrice(); orderCheck(); //損切して一定時間経過したか確認する bool isWaitRetryBuyTime=TimeCurrent()-_lastFailedBuyExitTime>entryWaitTime; bool isWaitRetrySellTime=TimeCurrent()-_lastFailedSellExitTime>entryWaitTime; //最後に利確した日が今日か確認する(利確した場合、その日はエントリーしない) string today=TimeToStr(TimeCurrent(),TIME_DATE); string lastSucceededBuyExitDay=TimeToStr(_lastSucceededBuyExitTime,TIME_DATE); string lastSucceededSellExitDay=TimeToStr(_lastSucceededSellExitTime,TIME_DATE); bool isWaitEnoughBuyDayTime=today!=lastSucceededBuyExitDay; bool isWaitEnoughSellDayTime=today!=lastSucceededSellExitDay; bool BuySignal=isHighPriceBreak && isWaitRetryBuyTime && isWaitEnoughBuyDayTime; bool SellSignal=isLowPriceBreak && isWaitRetrySellTime && isWaitEnoughSellDayTime; int ret=0; // 買いシグナル if(pos<=0 && BuySignal) ret=1; // 売りシグナル if(pos>=0 && SellSignal) ret=-1; return(ret); } // スタート関数 int start() { // エントリーシグナル int sig_entry=EntrySignal(MAGIC); // 買い注文 if(sig_entry>0) { MyOrderClose(Slippage,MAGIC); MyOrderSendSL(OP_BUY,Lots,Ask,Slippage,SLpips,TPpips,COMMENT,MAGIC); } // 売り注文 if(sig_entry<0) { MyOrderClose(Slippage,MAGIC); MyOrderSendSL(OP_SELL,Lots,Bid,Slippage,SLpips,TPpips,COMMENT,MAGIC); } return(0); } // オーダー送信関数(損切り・利食いを値幅で指定) bool MyOrderSendSL(int type,double lots,double price,int slippage,int slpips,int tppips,string comment,int magic) { int mult=1; if(Digits == 3 || Digits == 5) mult=10; slippage *= mult; if(type==OP_SELL || type==OP_SELLLIMIT || type==OP_SELLSTOP) mult*=-1; double sl=0,tp=0; if(slpips > 0) sl = price-slpips*Point*mult; if(tppips > 0) tp = price+tppips*Point*mult; return(MyOrderSend(type, lots, price, slippage, sl, tp, comment, magic)); } //+------------------------------------------------------------------+ //最後にエクジットした時刻を取得する void orderCheck() { bool isLastSucceededBuy=false; bool isLastFailedBuy=false; bool isLastSucceededSell=false; bool isLastFailedSell=false; for(int i=OrdersHistoryTotal()-1; i>=0; i--) { if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)==false) break; if(OrderMagicNumber()!=MAGIC) continue; if(OrderSymbol()!=Symbol()) continue; // 目的のポジションが選択された状態 if(OrderType()==OP_BUY && OrderProfit()>0 && !isLastSucceededBuy) { _lastSucceededBuyExitTime=OrderCloseTime(); isLastSucceededBuy=true; } if(OrderType()==OP_BUY && OrderProfit()<0 && !isLastFailedBuy) { _lastFailedBuyExitTime=OrderCloseTime(); isLastFailedBuy=true; } if(OrderType()==OP_SELL && OrderProfit()>0 && !isLastSucceededSell) { _lastSucceededSellExitTime=OrderCloseTime(); isLastSucceededSell=true; } if(OrderType()==OP_SELL && OrderProfit()<0 && !isLastFailedSell) { _lastFailedSellExitTime=OrderCloseTime(); isLastFailedSell=true; } if(isLastSucceededBuy && isLastFailedBuy && isLastSucceededSell && isLastFailedSell) { break; } } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ double OffsetPrice() { int mult=1; if(Digits==3 || Digits==5) mult=10; return OffsetPips*mult/MathPow(10,Digits); } //+------------------------------------------------------------------+ |
結果
結果考察
一定の利益が上がっているので、前日の値段のブレイクアウトを狙う手法は優位性があることがわかります。
ここで注意していただきたいのは、今回のバックテストで、スプレッドは5ポイント(0.5Pips)に設定しています。
一般的には10ポイント(1Pips)以上でバックテストを行うべきだとされています。
スプレッドの幅が小さいほど、テスト結果は良くなります。
もしもスプレッド幅を10ポイント(1Pips)にしてバックテストを行ったら、結果は悪くなります。
以上のことから、このトレードルールに優位性はあるが、スプレッドも考慮すると、実際の取引に耐えられるものではありません。
(正直、このEAを自分の資金で運用したいかと問われたら、答えはNOです。)
改良すれば、実際の取引に耐えうるトレードルールを作成できるとは思います。
(あるいは、裁量トレードをして、負けそうなエントリーはしないと判断する)
問題点
以下のような場合、前日の高値・安値がラインとして機能しないことがあります。
(1)前日の値動きが小さい
→高値・安値ライン付近で値段が動くとその分損切が増えます。
(例)7/30日は足のサイズが小さく、7/31に余計なエントリーを多くしているのがわかります。
(2)トレンドがある(一本調子で上がっている、または下がっている)
→日をまたいで、すぐにエントリーしてしまいます。
(例)2/19から2/20の切り替わりと2/20から2/21の切り替わりのタイミングで、すぐエントリーをしています。以下の例は、利益をあげていますが、そうでない場合もあります。
パラメータを動かす
高値・安値ラインピッタリでなく、高値・安値ラインから数Pips離れた箇所でエントリーした場合どうなるか考察します。
例えば、高値ラインでなく、高値+1Pipsでエントリーした場合に結果が改善するか検証を行います。
※よく損切ラインや、エントリーするラインに数Pips余裕を持たせるが、その行為に意味があるのか確認したいためです。
ソースコードでは、OffsetPipsという変数で管理しています。
OffsetPipsを0~3まで動かします。
※上から順番に0~3Pipsに対応しています。
つまり、1番上の結果がOffsetPipsが0の場合で、4番目の結果がOffsetPipsが3の場合に対応しています。
高値(安値)ラインでエントリーした場合のプロフィットファクターは1.15で、高値+3Pips(安値-3Pips)でエントリーした場合のプロフィットファクターは1.03です。
この結果を見る限り、エントリーするラインに数Pips余裕を持たせる行為は利益を損なっているように思えます。
ただし、この結果だけで、数Pips余裕を持たせる行為が損失を生む行為だと断言できません。
利確と損切のタイミングを変えたら、結果が変わる可能性があるためです。
改良ポイント
・利確と損切の値段を変更する。
(利確を20Pips。損切を10Pipsとしていますが、最適化の余地はあります)
・無駄なエントリーを減らす。
※何かしらのフィルターを用意する(効果があるかわかりませんが、前日の足の形を見て、エントリーを変えるなど)
まとめ
・前日の高値・安値のブレイクアウトには一定に優位性があります
(ただし、今のルールだと実際の取引に耐えうるものではありません)
・エントリーするラインに数Pips余裕を持たせる行為は損失につながる可能性があります
~FXを始めてみませんか?~
XMは、口座を開設するだけで、3000円のボーナスが無料でもらえます。
資金はないけど、FXを試しに挑戦してみたい方でも大丈夫です。
(サイト主もXMを使用しています)