MQL4を開発する際に、時間でCloseしたり、ストップロスでストップしたり、トレーリングストップしたりと色んなソースを組んでいましたが、毎回開発が面倒なので。汎用的に作ってしまえば、今後ずっと使えると思い、色んな取引条件に耐えられるテンプレートソースを作成しました。
ソースの説明
Judge1とJudge2の関数内に取引Openする条件を記載してもらえば、あとは外部変数で色んな条件を設定できます。(条件が2つよりも多いときにはJudge3,Judge4と関数を足してもらえば動きます)
ただし同時に持てるポジション数は1つまでです。要望が多ければポジションが複数持てるバージョンもそのうち作ります。
【外部変数で設定可能な内容】
TickTrade:True→処理単位をTick単位にする。
False→EAを動かしている対象足が変わったタイミングだけ処理する。
MagicNo:マジックNoを設定。
Lot:注文ロット数を設定(0.1で1万通貨)。
Spread_Limit:Spreadがこの値よりも大きいときはOpenしない。単位はPointなので、基本的はPipの10倍。
Order_interval:Closeしてから次のOpenまでに待つ秒数。
TimeoutClose:Ture→Open後に一定時間でCloseする
False→時間でCloseしない
Order_Sec:Open後に何秒でCloseするか(TimeoutCloseがTrueのときだけ動作する)
TrailClose:Ture→トレーリングストップを有効にする
False→トレーリングストップを利用しない
Trail_WinpipUnit:設定したPip利益が出るごとにストップを切りあげ
Trail_StoppipUnit:Trail_WinpipUnitの何Pip下にStopを入れるか
※例えばTrail_WinpipUnit=3、Trail_StoppipUnit=3にすると、
3pip利益が出るとStopを0pipに、6pip利益が出るとStopを3pipというようになる
StoplossClose:Ture→損切を有効にする
False→損切を利用しない
Stoploss_Pips:ストップロスのPip値をマイナスで設定
False→利確を利用しない
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 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 |
//--------------------------------------// // MQL4テンプレート // //--------------------------------------// #include <stdlib.mqh> //<-処理単位のパラメータ設定--------------- extern bool TickTrade=true; /*trueの場合はTick単位で処理、falseの場合には時間足が変わったタイミングで処理*/ //<-Open注文関連のパラメータ設定--------------- extern int MagicNo=2000; extern double Lot=0.1; /*注文ロット数*/ extern int Spread_Limit=5; /*スプレッドがこの値を超えたから取引しない(pipではなくpoint値)*/ extern int Order_interval=60; /*Closeから次のOderまで何秒待つか?*/ //<-Close注文関連のパラメータ設定--------------- extern bool TimeoutClose=true; /*タイムアウトを有効にするかどうか*/ extern int Order_Sec=1500; extern bool TrailClose=true; /*トライルを有効にするかどうか*/ extern double Trail_WinpipUnit=3; /*このPipに届く毎に切り上げ*/ extern double Trail_StoppipUnit=3; /*届いたレートから何Pip下にStopを入れるか*/ extern bool StoplossClose=true; /*Stoplossを有効にするかどうか*/ extern double Stoploss_Pips=-18; extern bool TakeprofitClose=true; /*Stopprofitを有効にするかどうか*/ extern double Takepofit_Pips=10; //<-共通変数定義--------------- int TicketNo=0; string last_timestamp = ""; static long pos_timestamp=0; static long close_timestamp=0; int TryCount; double trail_winpip_now=0; double trail_stoppip_now=-1000; //--------------------------------------// // 初期処理 // //--------------------------------------// int OnInit(){ //<-ポジション保持中にMT4を再起動した場合には、TicketNoを再取得--------------- for(int i=0; i<OrdersTotal(); i++){ if(OrderSelect(i, SELECT_BY_POS) == false) continue; if(OrderSymbol() != Symbol() || OrderMagicNumber() != MagicNo) continue; TicketNo = OrderTicket(); Print("Get ticketNo=",TicketNo); } return(INIT_SUCCEEDED); } void OnDeinit(const int reason){ ObjectsDeleteAll(); } //--------------------------------------// // Tickメイン処理 // //--------------------------------------// void OnTick() { int close=0; int err=0; int process_judge=0; int i=0; double profitpips=0; //<-(1)処理の単位を判断 Tick or 時間足が変わったタイミング--------------- if(TickTrade==false && last_timestamp != TimeToStr(Time[1], TIME_DATE|TIME_MINUTES)){ last_timestamp = TimeToStr(Time[1], TIME_DATE|TIME_MINUTES); process_judge=1; } else if(TickTrade) process_judge=1; else process_judge=0; /*0ならその後の判定に進まない*/ //<-(2)Spreadが大きすぎないかの判定--------------- if(process_judge>=1){ if(MarketInfo(Symbol(),MODE_SPREAD)<=Spread_Limit) process_judge=1; else process_judge=0; } //<-(3)前回のCloseからの経過時間の判定--------------- if(process_judge>=1 && TimeCurrent()-close_timestamp>Order_interval) process_judge=1; else process_judge=0; //<-(4-1)judge1:1つ目の判定条件--------------- if(process_judge>=1){ process_judge=judge1(); /*注文する条件でbuyなら1、Sellなら2、注文しない条件は0を返す*/ } //<-(4-2)judge2:2つ目の判定条件--------------- ★条件が2つで足りなければ、judge3,judge4・・・を足す if(process_judge>=1){ process_judge=judge2(process_judge); //注文する条件でbuyなら1、Sellなら2、注文しない条件は0を返す } //<-(5)order:全ての条件をクリアしたらポジションOpen--------------- if(Ordercheck()==0 && process_judge>=1){ if(process_judge==1) TicketNo = OrderSend(Symbol(),OP_BUY,Lot,Ask,0,0,0,WindowExpertName(),MagicNo,0,clrRed); else if(process_judge==2) TicketNo = OrderSend(Symbol(),OP_SELL,Lot,Bid,0,0,0,WindowExpertName(),MagicNo,0,clrRed); err = GetLastError(); Print("[OrderOpenError] : ", err, " ", ErrorDescription(err)); if(TicketNo > 0) { pos_timestamp = TimeCurrent(); trail_winpip_now=Trail_WinpipUnit; trail_stoppip_now=-1000; } } //<-(6-1)timeout Close:ポジションを保持していて、タイムアウトが有効な場合--------------- if(TimeoutClose==true && Ordercheck()!=0){ if( TimeCurrent() - pos_timestamp >= Order_Sec){ Print("Time Out Close"); close = OrderClose(TicketNo,Lot,Ask,1000,Green); err = GetLastError(); Print("[OrderSendError] : ", err, " ", ErrorDescription(err)); if(close >0 ) { close_timestamp = TimeCurrent(); } } } //<-(6-2)Trail Close:ポジションを保持していて、トレーリングストップが有効な場合--------------- if(TrailClose==true && Ordercheck()!=0){ profitpips = MyOrderProfitPips(MagicNo); if(profitpips>=trail_winpip_now) { trail_stoppip_now=trail_winpip_now-Trail_StoppipUnit; trail_winpip_now=trail_winpip_now+Trail_WinpipUnit; Print("trail_stoppip up=",trail_stoppip_now); } if(profitpips<=trail_stoppip_now) { Print("Trail STOP"); if(Ordercheck()==1){ close = OrderClose(TicketNo,Lot,Bid,1000,Green); err = GetLastError(); Print("[OrderSendError] : ", err, " ", ErrorDescription(err)); } else if(Ordercheck()==2){ close = OrderClose(TicketNo,Lot,Ask,1000,Green); err = GetLastError(); Print("[OrderSendError] : ", err, " ", ErrorDescription(err)); } if(close >0 ) close_timestamp = TimeCurrent(); } } //<-(6-3)stoploss Close:ポジションを保持していて、ストップロスが有効な場合--------------- if(StoplossClose==true && Ordercheck()!=0){ profitpips = MyOrderProfitPips(MagicNo); if(profitpips<=Stoploss_Pips) { Print("STOP LOSS"); if(Ordercheck()==1){ close = OrderClose(TicketNo,Lot,Bid,1000,Green); err = GetLastError(); Print("[OrderSendError] : ", err, " ", ErrorDescription(err)); } else if(Ordercheck()==2){ close = OrderClose(TicketNo,Lot,Ask,1000,Green); err = GetLastError(); Print("[OrderSendError] : ", err, " ", ErrorDescription(err)); } if(close >0 ) close_timestamp = TimeCurrent(); } } //<-(6-4)stopprofit Close:ポジションを保持していて、ストッププロフィットが有効な場合--------------- if(TakeprofitClose==true && Ordercheck()!=0){ profitpips = MyOrderProfitPips(MagicNo); if(profitpips>=Takepofit_Pips) { Print("STOP Profit"); if(Ordercheck()==1){ close = OrderClose(TicketNo,Lot,Bid,1000,Green); err = GetLastError(); Print("[OrderSendError] : ", err, " ", ErrorDescription(err)); } else if(Ordercheck()==2){ close = OrderClose(TicketNo,Lot,Ask,1000,Green); err = GetLastError(); Print("[OrderSendError] : ", err, " ", ErrorDescription(err)); } if(close >0 ) close_timestamp = TimeCurrent(); } } } //--------------------------------------// //ポジションを持っているかの判定 // //返値「0:ポジション無し、1:buyポジション有り、2:sellポジション有り」// //--------------------------------------// int Ordercheck() { if(OrdersTotal()>0) { for(int i=0; i<OrdersTotal(); i++){ if(OrderSelect(i, SELECT_BY_POS) == false) continue; if(OrderSymbol() != Symbol() || OrderMagicNumber() != MagicNo) continue; if(OrderType() == OP_BUY) return(1); if(OrderType() == OP_SELL) return(2); } } return(0); } //--------------------------------------// //ポジションを持っている場合に、現在の損益pip値を返す // //返値「損益pip値」 // //--------------------------------------// double MyOrderProfitPips(int pos_id=0) { double newprofit = 0; double profit = 0; int mult=1; if(Digits == 3 || Digits == 5) mult=10; /*通貨ペアの桁数を調整*/ for(int i=0; i<OrdersTotal(); i++){ { if(OrderSelect(i, SELECT_BY_POS) == false) break; if(OrderSymbol() != Symbol() || OrderMagicNumber() != pos_id) continue; newprofit = OrderClosePrice() - OrderOpenPrice(); /*現在のレートとOpenレートの差を計算*/ if(newprofit != 0) break; } if(OrderType() == OP_BUY) profit = newprofit; if(OrderType() == OP_SELL) profit = -newprofit; return profit/Point/mult; /*pipに変換*/ } //--------------------------------------// //Open注文判定条件1 // //返値「 0:注文しない、1:buyの条件を満たす、2:sellの条件を満たす」 // //--------------------------------------// int judge1() { //★★中身は自由に記載 //サンプルでは1つ前の1分足の開始値と今の1分足の開始値を比べて高ければBUY、低ければSELL if(iOpen(Symbol(), PERIOD_M1 , 0)-iOpen(Symbol(), PERIOD_M1 , 1)>0) return(1); else if(iOpen(Symbol(), PERIOD_M1 , 0)-iOpen(Symbol(), PERIOD_M1 , 1)<0) return(2); else return(0); } //--------------------------------------// //判定条件2 // //返値「 0:注文しない、1:buyの条件を満たす、2:sellの条件を満たす」 // //ただし、条件1と注文方向が一致しないときは0を返す //--------------------------------------// int judge2(int process_judge) { //★★中身は自由に記載 //サンプルでは1つ前の1時間足の開始値と今の1時間足の開始値を比べて高ければBUY、低ければSELL int judge=0; /*1:BUY, 2:SELL*/ if(iOpen(Symbol(), PERIOD_H1 , 0)-iOpen(Symbol(), PERIOD_H1 , 1)>0) judge=1; else if(iOpen(Symbol(), PERIOD_H1 , 0)-iOpen(Symbol(), PERIOD_H1 , 1)<0) judge=2; else judge=0; if(judge==process_judge) return(judge); /*judge1と一致するかの判定*/ else return(0); } |
一気にStop値を6pip切上げほうが一般的なのですが、値動きが激しいとはストップにかかりやすくなるので、あえて徐々にStop値を切り上げています。
AIを活用した自動売買EAの無料配布始めました。3年以上の年月をかけて大分安定してきましてので、よければ「機械学習EA(Aizack)とは」をご覧ください。