static input double Entry_Amount = 0.01; // Entry lots static input int Base_Magic_Number = 100; // Base Magic Number #define TRADE_RETRY_COUNT 4 #define TRADE_RETRY_WAIT 100 #define OP_FLAT -1 // Session time is set in seconds from 00:00 const int sessionSundayOpen = 0; // 00:00 const int sessionSundayClose = 86400; // 24:00 const int sessionMondayThursdayOpen = 0; // 00:00 const int sessionMondayThursdayClose = 86400; // 24:00 const int sessionFridayOpen = 0; // 00:00 const int sessionFridayClose = 86400; // 24:00 const bool sessionIgnoreSunday = false; const bool sessionCloseAtSessionClose = true; const bool sessionCloseAtFridayClose = true; const int strategiesCount = 2; const double sigma = 0.000001; datetime barTime; int digits; double stopLevel; double pip; bool setProtectionSeparately = false; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ enum OrderScope { ORDER_SCOPE_UNDEFINED, ORDER_SCOPE_ENTRY, ORDER_SCOPE_EXIT }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ enum OrderDirection { ORDER_DIRECTION_NONE, ORDER_DIRECTION_BUY, ORDER_DIRECTION_SELL, ORDER_DIRECTION_BOTH }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ struct Position { int Type; int Ticket; int MagicNumber; double Lots; double Price; double StopLoss; double TakeProfit; }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ struct Signal { int MagicNumber; OrderScope Scope; OrderDirection Direction; int StopLossPips; int TakeProfitPips; bool IsTrailingStop; }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ int OnInit() { barTime = Time[0]; digits = (int) MarketInfo(_Symbol, MODE_DIGITS); stopLevel = MarketInfo(_Symbol, MODE_STOPLEVEL); pip = GetPipValue(); const ENUM_INIT_RETCODE initRetcode = ValidateInit(); return (initRetcode); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void OnTick() { if(IsForceSessionClose()) { CloseAllPositions(); return; } if(Time[0]>barTime) { barTime=Time[0]; OnBar(); } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void OnBar() { if(IsOutOfSession()) return; Signal signalList[]; SetSignals(signalList); int signalsCount=ArraySize(signalList); for(int i=0;i=0; pos--) { if(OrderSelect(pos,SELECT_BY_POS,MODE_TRADES) && OrderSymbol() == _Symbol && OrderMagicNumber() == magicNumber && OrderCloseTime() == 0) { position.Type = OrderType(); position.Lots = OrderLots(); position.Ticket = OrderTicket(); position.Price = OrderOpenPrice(); position.StopLoss = OrderStopLoss(); position.TakeProfit = OrderTakeProfit(); break; } } return (position); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ Signal CreateEntrySignal(const int strategyIndex,const bool canOpenLong,const bool canOpenShort,const int stopLossPips,const int takeProfitPips, const bool isTrailingStop) { Signal signal; signal.MagicNumber = GetMagicNumber(strategyIndex); signal.Scope = ORDER_SCOPE_ENTRY; signal.Direction = canOpenLong&&canOpenShort ? ORDER_DIRECTION_BOTH : canOpenLong ? ORDER_DIRECTION_BUY : canOpenShort ? ORDER_DIRECTION_SELL : ORDER_DIRECTION_NONE; signal.StopLossPips = stopLossPips; signal.TakeProfitPips = takeProfitPips; signal.IsTrailingStop = isTrailingStop; return (signal); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ Signal CreateExitSignal(const int strategyIndex,const bool canCloseLong,const bool canCloseShorts,const int stopLossPips,const int takeProfitPips, const bool isTrailingStop) { Signal signal; signal.MagicNumber = GetMagicNumber(strategyIndex); signal.Scope = ORDER_SCOPE_EXIT; signal.Direction = canCloseLong&&canCloseShorts ? ORDER_DIRECTION_BOTH : canCloseLong ? ORDER_DIRECTION_SELL : canCloseShorts ? ORDER_DIRECTION_BUY : ORDER_DIRECTION_NONE; signal.StopLossPips = stopLossPips; signal.TakeProfitPips = takeProfitPips; signal.IsTrailingStop = isTrailingStop; return (signal); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void OpenPosition(Signal &signal) { for(int attempt=0; attempt0 ? GetStopLoss(command, signal.StopLossPips) : 0; double takeProfit = signal.TakeProfitPips>0 ? GetTakeProfit(command, signal.TakeProfitPips) : 0; string comment = IntegerToString(signal.MagicNumber); color arrowColor = command==OP_BUY ? clrGreen : clrRed; if(IsTradeContextFree()) { double price=MarketInfo(_Symbol,command==OP_BUY ? MODE_ASK : MODE_BID); if(setProtectionSeparately) { ticket=OrderSend(_Symbol,command,amount,price,10,0,0,comment,signal.MagicNumber,0,arrowColor); if(ticket>0 && (signal.StopLossPips>0 || signal.TakeProfitPips>0)) modified=OrderModify(ticket,0,stopLoss,takeProfit,0,clrBlue); } else { ticket=OrderSend(_Symbol,command,amount,price,10,stopLoss,takeProfit,comment,signal.MagicNumber,0,arrowColor); lastError=GetLastError(); if(ticket<=0 && lastError==130) { ticket=OrderSend(_Symbol,command,amount,price,10,0,0,comment,signal.MagicNumber,0,arrowColor); if(ticket>0 && (signal.StopLossPips>0 || signal.TakeProfitPips>0)) modified=OrderModify(ticket,0,stopLoss,takeProfit,0,clrBlue); if(ticket>0 && modified) { setProtectionSeparately=true; Print("Detected ECN type position protection."); } } } } if(ticket>0) break; lastError=GetLastError(); if(lastError!=135 && lastError!=136 && lastError!=137 && lastError!=138) break; Sleep(TRADE_RETRY_WAIT); Print("Open Position retry no: "+IntegerToString(attempt+2)); } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void ClosePosition(Position &position) { for(int attempt=0; attempt=bid-stopLevelPoints) return (bid - stopLevelPoints); else return (stopLossPrice); } else { return (bid); } } } else if(position.Type==OP_SELL) { double stopLossPrice=Low[1]+stopLossPoints; if(position.StopLoss>stopLossPrice+pip) { if(stopLossPrice>ask) { if(stopLossPrice<=ask+stopLevelPoints) return (ask + stopLevelPoints); else return (stopLossPrice); } else { return (ask); } } } return (position.StopLoss); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void ManageTrailingStop(Position &position, double trailingStop) { double bid=MarketInfo(_Symbol,MODE_BID); double ask=MarketInfo(_Symbol,MODE_ASK); if(position.Type==OP_BUY && MathAbs(trailingStop-bid)<_Point) { ClosePosition(position); } else if(position.Type==OP_SELL && MathAbs(trailingStop-ask)<_Point) { ClosePosition(position); } else if(MathAbs(trailingStop-position.StopLoss)>_Point) { position.StopLoss=NormalizeDouble(trailingStop,digits); ModifyPosition(position); } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool IsTradeContextFree() { if(IsTradeAllowed()) return (true); uint startWait=GetTickCount(); Print("Trade context is busy! Waiting..."); while(true) { if(IsStopped()) return (false); uint diff=GetTickCount()-startWait; if(diff>30*1000) { Print("The waiting limit exceeded!"); return (false); } if(IsTradeAllowed()) { RefreshRates(); return (true); } Sleep(TRADE_RETRY_WAIT); } return (true); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool IsOutOfSession() { MqlDateTime time0; TimeToStruct(Time[0],time0); int weekDay = time0.day_of_week; long timeFromMidnight = Time[0]%86400; int periodLength = PeriodSeconds(_Period); bool skipTrade = false; if(weekDay==0) { if(sessionIgnoreSunday) return true; int lastBarFix=sessionCloseAtSessionClose ? periodLength : 0; skipTrade=timeFromMidnightsessionSundayClose; } else if(weekDay<5) { int lastBarFix=sessionCloseAtSessionClose ? periodLength : 0; skipTrade=timeFromMidnightsessionMondayThursdayClose; } else { int lastBarFix=sessionCloseAtFridayClose || sessionCloseAtSessionClose ? periodLength : 0; skipTrade=timeFromMidnightsessionFridayClose; } return (skipTrade); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool IsForceSessionClose() { if(!sessionCloseAtFridayClose && !sessionCloseAtSessionClose) return (false); MqlDateTime time0; TimeToStruct(Time[0],time0); int weekDay = time0.day_of_week; long timeFromMidnight = Time[0]%86400; int periodLength = PeriodSeconds(_Period); bool forceExit=false; if(weekDay==0 && sessionCloseAtSessionClose) { forceExit=timeFromMidnight+periodLength>sessionSundayClose; } else if(weekDay<5 && sessionCloseAtSessionClose) { forceExit=timeFromMidnight+periodLength>sessionMondayThursdayClose; } else if(weekDay==5) { forceExit=timeFromMidnight+periodLength>sessionFridayClose; } return (forceExit); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ datetime Time(int bar) { return Time[bar]; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ double Open(int bar) { return Open[bar]; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ double High(int bar) { return High[bar]; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ double Low(int bar) { return Low[bar]; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ double Close(int bar) { return Close[bar]; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ double GetPipValue() { switch((int) MarketInfo(_Symbol,MODE_DIGITS)) { case 5: case 4: return (0.0001); case 3: case 2: return (0.01); case 1: return (0.1); } return (1); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ int GetMagicNumber(int strategyIndex) { int magic=1000*Base_Magic_Number+strategyIndex; return (magic); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ int OrderDirectionToCommand(OrderDirection dir) { if(dir==ORDER_DIRECTION_BUY) return (OP_BUY); if(dir==ORDER_DIRECTION_SELL) return (OP_SELL); return (OP_FLAT); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void SetSignals(Signal &signalList[]) { int i=0; ArrayResize(signalList,2*strategiesCount); HideTestIndicators(true); /*STRATEGY CODE {"properties":{"entryLots":0.1,"stopLoss":100,"takeProfit":100,"useStopLoss":false,"useTakeProfit":false,"isTrailingStop":false},"openFilters":[{"name":"MACD Signal","listIndexes":[0,3,0,0,0],"numValues":[19,21,16,0,0,0]}],"closeFilters":[{"name":"Bollinger Bands","listIndexes":[0,3,0,0,0],"numValues":[14,3.15,0,0,0,0]}]} */ signalList[i++] = GetExitSignal_00(); signalList[i++] = GetEntrySignal_00(); /*STRATEGY CODE {"properties":{"entryLots":0.1,"stopLoss":100,"takeProfit":100,"useStopLoss":false,"useTakeProfit":false,"isTrailingStop":false},"openFilters":[{"name":"MACD","listIndexes":[5,3,0,0,0],"numValues":[5,23,9,0,0,0]},{"name":"Momentum","listIndexes":[0,3,0,0,0],"numValues":[23,100,0,0,0,0]}],"closeFilters":[{"name":"MACD Signal","listIndexes":[0,3,0,0,0],"numValues":[19,20,2,0,0,0]}]} */ signalList[i++] = GetExitSignal_01(); signalList[i++] = GetEntrySignal_01(); HideTestIndicators(false); if(i!=2*strategiesCount) ArrayResize(signalList,i); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ Signal GetEntrySignal_00() { double ind0val1 = iMACD(NULL,0,19,21,16,PRICE_CLOSE,MODE_MAIN,1) - iMACD(NULL,0,19,21,16,PRICE_CLOSE,MODE_SIGNAL,1); double ind0val2 = iMACD(NULL,0,19,21,16,PRICE_CLOSE,MODE_MAIN,2) - iMACD(NULL,0,19,21,16,PRICE_CLOSE,MODE_SIGNAL,2); bool ind0long = ind0val1 > 0 + sigma && ind0val2 < 0 - sigma; bool ind0short = ind0val1 < 0 - sigma && ind0val2 > 0 + sigma; Signal signal = CreateEntrySignal(0, ind0long, ind0short, 0, 0, false); return (signal); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ Signal GetExitSignal_00() { double ind1upBand1 = iBands(NULL,0,14,3.15,0,PRICE_CLOSE,MODE_UPPER,1); double ind1dnBand1 = iBands(NULL,0,14,3.15,0,PRICE_CLOSE,MODE_LOWER,1); bool ind1long = Open(0) > ind1upBand1 + sigma; bool ind1short = Open(0) < ind1dnBand1 - sigma; Signal signal = CreateExitSignal(0, ind1long, ind1short, 0, 0, false); return (signal); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ Signal GetEntrySignal_01() { double ind0val1 = iMACD(NULL,0,5,23,9,PRICE_CLOSE,MODE_MAIN,1); double ind0val2 = iMACD(NULL,0,5,23,9,PRICE_CLOSE,MODE_MAIN,2); bool ind0long = ind0val1 < 0 - sigma && ind0val2 > 0 + sigma; bool ind0short = ind0val1 > 0 + sigma && ind0val2 < 0 - sigma; double ind1val1 = iMomentum(NULL,0,23,PRICE_CLOSE,1); double ind1val2 = iMomentum(NULL,0,23,PRICE_CLOSE,2); bool ind1long = ind1val1 > ind1val2 + sigma; bool ind1short = ind1val1 < ind1val2 - sigma; Signal signal = CreateEntrySignal(1, ind0long && ind1long, ind0short && ind1short, 0, 0, false); return (signal); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ Signal GetExitSignal_01() { double ind2val1 = iMACD(NULL,0,19,20,2,PRICE_CLOSE,MODE_MAIN,1) - iMACD(NULL,0,19,20,2,PRICE_CLOSE,MODE_SIGNAL,1); double ind2val2 = iMACD(NULL,0,19,20,2,PRICE_CLOSE,MODE_MAIN,2) - iMACD(NULL,0,19,20,2,PRICE_CLOSE,MODE_SIGNAL,2); bool ind2long = ind2val1 > 0 + sigma && ind2val2 < 0 - sigma; bool ind2short = ind2val1 < 0 - sigma && ind2val2 > 0 + sigma; Signal signal = CreateExitSignal(1, ind2long, ind2short, 0, 0, false); return (signal); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ ENUM_INIT_RETCODE ValidateInit() { return (INIT_SUCCEEDED); } //+------------------------------------------------------------------+ /*STRATEGY MARKET PepperstoneUK-Demo03; EURUSD; M5 */