//+------------------------------------------------------------------+ //| MT5ProBot.mq5 | //| Multi-strategy EA: EMA/ATR trend, session breakout, | //| RSI/Bollinger mean-reversion, ADX-regime RSI | //+------------------------------------------------------------------+ #property copyright "jamesta361" #property link "https://www.mql5.com" #property version "1.00" #property description "Multi-strategy Expert Advisor with a fixed stop-loss on every trade." #property description "Risk-based position sizing, daily and overall loss limits, prop-firm mode." #property description "No martingale. No grid. No averaging down." #property description "Trading involves risk. Past performance does not guarantee future results." #include CTrade trade; //--- General ------------------------------------------------------- input group "=== General ===" input ulong InpMagic = 240601; // Magic number input ENUM_TIMEFRAMES InpTF = PERIOD_M15; // Signal timeframe input int InpDeviation = 20; // Max slippage (points) input int InpAtrPeriod = 14; // ATR period //--- Strategies ---------------------------------------------------- input group "=== Strategy 1: EMA cross + ATR ===" input bool InpUseEmaAtr = true; // Enable input int InpEmaFast = 20; // Fast EMA input int InpEmaSlow = 50; // Slow EMA input int InpEmaTrend = 200; // Trend EMA (filter) input double InpEmaSlAtr = 1.5; // SL = x ATR input double InpEmaTpAtr = 3.0; // TP = x ATR input group "=== Strategy 2: Session breakout (server time) ===" input bool InpUseBreakout = true; // Enable input int InpBrkRangeStart= 0; // Range start hour input int InpBrkRangeEnd = 7; // Range end hour (breakout window opens) input int InpBrkUntil = 11; // Breakout window closes (hour) input double InpBrkSlAtr = 1.5; // SL = x ATR input double InpBrkRR = 2.0; // TP = RR x SL input group "=== Strategy 3: RSI + Bollinger mean-reversion ===" input bool InpUseRsiMr = true; // Enable input int InpMrRsiPeriod = 14; // RSI period input double InpMrRsiLow = 30.0; // Oversold level input double InpMrRsiHigh = 70.0; // Overbought level input int InpMrBbPeriod = 20; // Bollinger period input double InpMrBbDev = 2.0; // Bollinger deviation input double InpMrSlAtr = 1.5; // SL = x ATR input double InpMrTpAtr = 2.0; // TP = x ATR input group "=== Strategy 4: ADX-regime RSI ===" input bool InpUseRegime = true; // Enable input int InpRgFast = 13; // Fast EMA input int InpRgSlow = 34; // Slow EMA input int InpRgRsiPeriod = 14; // RSI period input double InpRgAdxThr = 25.0; // ADX: range / trend threshold input double InpRgAdxMax = 60.0; // ADX: no entry above this input double InpRgBuyRange = 48.0; // Range: buy if RSI below input double InpRgSellRange = 52.0; // Range: sell if RSI above input double InpRgOb = 70.0; // Trend: max RSI for buys input double InpRgOs = 30.0; // Trend: min RSI for sells input double InpRgSlAtr = 1.5; // SL = x ATR input double InpRgTpAtr = 2.5; // TP = x ATR //--- Risk ---------------------------------------------------------- input group "=== Risk management ===" input double InpRiskPct = 0.5; // Risk per trade (% of equity) input double InpMaxRiskMult = 3.0; // Skip trade if min lot risks more than x target input int InpMaxOpen = 4; // Max open trades (all symbols, same magic) input double InpDailyLossPct = 4.0; // Daily loss limit (%) input double InpMaxDDPct = 9.0; // Max drawdown from peak equity (%) input double InpBreakEvenAtr = 1.0; // Break-even after x ATR profit (0 = off) input double InpTrailAtr = 1.5; // Trailing distance x ATR (0 = off) input group "=== Prop firm mode ===" input bool InpPropMode = false; // Enable prop firm mode input double InpPropInitial = 100000; // Initial account size input double InpPropDaily = 4.5; // Daily loss limit (%) input double InpPropDD = 9.0; // Max drawdown from initial balance (%) //--- Filters ------------------------------------------------------- input group "=== Filters (server time) ===" input bool InpUseSession = true; // Trade only inside session input int InpSessStart = 7; // Session start hour input int InpSessEnd = 20; // Session end hour input double InpMaxSpreadAtr = 20.0; // Max spread (% of ATR) input int InpMaxSpreadPts = 0; // Max spread in points (0 = off) input bool InpUseVolFilter = true; // Skip very low volatility input double InpMinAtrRatio = 0.6; // Min ATR / average ATR(100) input bool InpUseNews = false; // Pause around high-impact news (live only) input int InpNewsBefore = 15; // Minutes before news input int InpNewsAfter = 30; // Minutes after news //--- Notifications ------------------------------------------------- input group "=== Notifications ===" input bool InpPush = false; // Mobile push notifications input string InpTgToken = ""; // Telegram bot token (optional) input string InpTgChat = ""; // Telegram chat id (optional) //+------------------------------------------------------------------+ //| Globals | //+------------------------------------------------------------------+ struct Sig { int dir; // 1 buy, -1 sell, 0 none double slDist; // price distance double tpDist; // price distance string tag; // short strategy tag datetime day; // used by the breakout strategy }; ENUM_TIMEFRAMES g_tf; datetime g_lastBar = 0; datetime g_brkDay = 0; bool g_paused = false; long g_tgOffset = 0; int g_hAtr = INVALID_HANDLE; int g_hEmaF = INVALID_HANDLE; int g_hEmaS = INVALID_HANDLE; int g_hEmaT = INVALID_HANDLE; int g_hRsiMr = INVALID_HANDLE; int g_hBb = INVALID_HANDLE; int g_hRgF = INVALID_HANDLE; int g_hRgS = INVALID_HANDLE; int g_hRgRsi = INVALID_HANDLE; int g_hAdx = INVALID_HANDLE; //+------------------------------------------------------------------+ //| Helpers | //+------------------------------------------------------------------+ bool Bad(const double v) { return(v==EMPTY_VALUE || !MathIsValidNumber(v)); } double Buf(const int handle, const int buffer, const int shift) { double a[1]; if(handle==INVALID_HANDLE) return(EMPTY_VALUE); if(CopyBuffer(handle,buffer,shift,1,a)!=1) return(EMPTY_VALUE); return(a[0]); } string GV(const string key) { return("MPB_"+(string)AccountInfoInteger(ACCOUNT_LOGIN)+"_"+(string)InpMagic+"_"+key); } datetime DayStart(const datetime t) { MqlDateTime d; TimeToStruct(t,d); d.hour=0; d.min=0; d.sec=0; return(StructToTime(d)); } int CountPositions(const bool onlyThisSymbol) { int n=0; for(int i=PositionsTotal()-1;i>=0;i--) { ulong tk=PositionGetTicket(i); if(tk==0) continue; if((ulong)PositionGetInteger(POSITION_MAGIC)!=InpMagic) continue; if(onlyThisSymbol && PositionGetString(POSITION_SYMBOL)!=_Symbol) continue; n++; } return(n); } void CloseAll() { for(int i=PositionsTotal()-1;i>=0;i--) { ulong tk=PositionGetTicket(i); if(tk==0) continue; if((ulong)PositionGetInteger(POSITION_MAGIC)!=InpMagic) continue; trade.PositionClose(tk); } } string UrlEncode(const string text) { uchar b[]; int n=StringToCharArray(text,b,0,WHOLE_ARRAY,CP_UTF8)-1; string out=""; for(int i=0;i='0' && c<='9')||(c>='A' && c<='Z')||(c>='a' && c<='z')||c=='-'||c=='_'||c=='.'||c=='~') out+=CharToString(c); else out+=StringFormat("%%%02X",c); } return(out); } void TgSend(const string text) { if(InpTgToken=="" || InpTgChat=="" || MQLInfoInteger(MQL_TESTER)) return; string url="https://api.telegram.org/bot"+InpTgToken+"/sendMessage"; string body="chat_id="+InpTgChat+"&text="+UrlEncode(text); char post[], res[]; string hdr="Content-Type: application/x-www-form-urlencoded\r\n", rh; StringToCharArray(body,post,0,StringLen(body)); ResetLastError(); if(WebRequest("POST",url,hdr,5000,post,res,rh)==-1) Print("Telegram: add https://api.telegram.org to Tools > Options > Expert Advisors > Allow WebRequest. Error ",GetLastError()); } void Notify(const string msg) { Print(msg); if(MQLInfoInteger(MQL_TESTER)) return; if(InpPush) SendNotification(msg); TgSend(msg); } //+------------------------------------------------------------------+ //| Daily / drawdown tracking (shared between charts via globals) | //+------------------------------------------------------------------+ bool IsHalted() { if(!GlobalVariableCheck(GV("haltDay"))) return(false); return((datetime)GlobalVariableGet(GV("haltDay"))==DayStart(TimeCurrent())); } void UpdateDay() { double bal=AccountInfoDouble(ACCOUNT_BALANCE); double eq =AccountInfoDouble(ACCOUNT_EQUITY); datetime today=DayStart(TimeCurrent()); datetime stored=0; if(GlobalVariableCheck(GV("day"))) stored=(datetime)GlobalVariableGet(GV("day")); if(stored!=today) { GlobalVariableSet(GV("day"),(double)today); GlobalVariableSet(GV("dayEq"),MathMax(bal,eq)); if(!InpPropMode) GlobalVariableSet(GV("peak"),eq); // peak resets each day (non-prop) } if(!GlobalVariableCheck(GV("peak"))) GlobalVariableSet(GV("peak"),eq); if(!GlobalVariableCheck(GV("dayEq"))) GlobalVariableSet(GV("dayEq"),MathMax(bal,eq)); double peak=GlobalVariableGet(GV("peak")); if(eq>peak) GlobalVariableSet(GV("peak"),eq); } double DailyLossPct() { double dayEq=GlobalVariableGet(GV("dayEq")); if(dayEq<=0) return(0.0); return((dayEq-AccountInfoDouble(ACCOUNT_EQUITY))/dayEq*100.0); } double DrawdownPct() { double ref=(InpPropMode && InpPropInitial>0) ? InpPropInitial : GlobalVariableGet(GV("peak")); if(ref<=0) return(0.0); return((ref-AccountInfoDouble(ACCOUNT_EQUITY))/ref*100.0); } bool RiskOk(string &why) { double dailyLim=InpPropMode ? InpPropDaily : InpDailyLossPct; double ddLim =InpPropMode ? InpPropDD : InpMaxDDPct; double dl=DailyLossPct(); double dd=DrawdownPct(); if(dl>=dailyLim){ why=StringFormat("Daily loss %.2f%% >= %.2f%%",dl,dailyLim); return(false); } if(dd>=ddLim) { why=StringFormat("Drawdown %.2f%% >= %.2f%%",dd,ddLim); return(false); } return(true); } void CheckKillSwitch() { if(IsHalted()) return; string why; if(RiskOk(why)) return; GlobalVariableSet(GV("haltDay"),(double)DayStart(TimeCurrent())); CloseAll(); Notify("KILL-SWITCH: "+why+". Positions closed, trading stopped until next day."); } //+------------------------------------------------------------------+ //| Strategies (closed bars only: shift 1 = last closed bar) | //+------------------------------------------------------------------+ bool SigEmaAtr(Sig &sg) { double f1=Buf(g_hEmaF,0,1), f2=Buf(g_hEmaF,0,2); double s1=Buf(g_hEmaS,0,1), s2=Buf(g_hEmaS,0,2); double t1=Buf(g_hEmaT,0,1), a=Buf(g_hAtr,0,1); if(Bad(f1)||Bad(f2)||Bad(s1)||Bad(s2)||Bad(t1)||Bad(a)||a<=0) return(false); double c1=iClose(_Symbol,g_tf,1); bool up=(f2<=s2 && f1>s1 && c1>t1); bool dn=(f2>=s2 && f1=InpBrkUntil) return(false); datetime dayStart=DayStart(t1); if(g_brkDay==dayStart) return(false); int maxBars=(int)(86400/PeriodSeconds(g_tf))+5; MqlRates r[]; ArraySetAsSeries(r,true); int got=CopyRates(_Symbol,g_tf,1,maxBars,r); if(got<=0) return(false); double hi=-DBL_MAX, lo=DBL_MAX; int cnt=0; for(int i=0;i=InpBrkRangeStart && x.hourhi) hi=r[i].high; if(r[i].lowhi) dir=1; else if(c1InpMrRsiHigh && c1>up) dir=-1; if(dir==0) return(false); sg.dir=dir; sg.slDist=InpMrSlAtr*a; sg.tpDist=InpMrTpAtr*a; sg.tag="RSI"; sg.day=0; return(true); } bool SigRegime(Sig &sg) { double ef=Buf(g_hRgF,0,1), es=Buf(g_hRgS,0,1); double r1=Buf(g_hRgRsi,0,1), r0=Buf(g_hRgRsi,0,2); double adx=Buf(g_hAdx,0,1), a=Buf(g_hAtr,0,1); if(Bad(ef)||Bad(es)||Bad(r1)||Bad(r0)||Bad(adx)||Bad(a)||a<=0) return(false); if(adx>InpRgAdxMax) return(false); bool up=(ef>es); bool buy=false, sell=false; if(adxr0); sell=(!up && r1>InpRgSellRange && r1=50.0 && r150.0 && r1<=50.0 && r1>InpRgOs); } if(!buy && !sell) return(false); sg.dir=buy?1:-1; sg.slDist=InpRgSlAtr*a; sg.tpDist=InpRgTpAtr*a; sg.tag="REG"; sg.day=0; return(true); } bool FindSignal(Sig &sg) { if(InpUseEmaAtr && SigEmaAtr(sg)) return(true); if(InpUseBreakout && SigBreakout(sg)) return(true); if(InpUseRsiMr && SigRsiMr(sg)) return(true); if(InpUseRegime && SigRegime(sg)) return(true); return(false); } //+------------------------------------------------------------------+ //| Filters | //+------------------------------------------------------------------+ bool NewsBlocked() { if(!InpUseNews || MQLInfoInteger(MQL_TESTER)) return(false); static datetime lastCheck=0; static bool lastRes=false; datetime now=TimeCurrent(); if(now-lastCheck<60) return(lastRes); lastCheck=now; lastRes=false; string cur[2]; cur[0]=SymbolInfoString(_Symbol,SYMBOL_CURRENCY_BASE); cur[1]=SymbolInfoString(_Symbol,SYMBOL_CURRENCY_PROFIT); datetime from=now-InpNewsAfter*60, to=now+InpNewsBefore*60; for(int k=0;k<2;k++) { if(cur[k]=="") continue; MqlCalendarValue v[]; int n=CalendarValueHistory(v,from,to,NULL,cur[k]); for(int i=0;i=InpSessStart && d.hour=InpSessStart || d.hour0 && spread>a*InpMaxSpreadAtr/100.0) return(false); if(InpMaxSpreadPts>0 && spread/_Point>InpMaxSpreadPts) return(false); if(InpUseVolFilter) { double arr[]; ArraySetAsSeries(arr,true); if(CopyBuffer(g_hAtr,0,1,100,arr)==100) { double sum=0; for(int i=0;i<100;i++) sum+=arr[i]; double mean=sum/100.0; if(mean>0 && arr[0]/mean=1) return(false); if(CountPositions(false)>=InpMaxOpen) return(false); return(true); } //+------------------------------------------------------------------+ //| Position sizing and order sending | //+------------------------------------------------------------------+ double CalcLots(const double slDist, const ENUM_ORDER_TYPE type, const double price) { double riskMoney=AccountInfoDouble(ACCOUNT_EQUITY)*InpRiskPct/100.0; if(riskMoney<=0) return(0.0); double slPrice=(type==ORDER_TYPE_BUY) ? price-slDist : price+slDist; double profit=0.0; if(!OrderCalcProfit(type,_Symbol,1.0,price,slPrice,profit) || profit>=0.0) return(0.0); double lossPerLot=-profit; double step=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_STEP); double vmin=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN); double vmax=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MAX); if(step<=0) return(0.0); double lots=MathFloor(riskMoney/lossPerLot/step)*step; if(lotsriskMoney*InpMaxRiskMult) return(0.0); // min lot too risky for this account lots=vmin; } if(lots>vmax) lots=vmax; double vlim=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_LIMIT); // max total volume per symbol (0 = none) if(vlim>0.0 && lots>vlim) lots=MathFloor(vlim/step)*step; if(lotsAccountInfoDouble(ACCOUNT_MARGIN_FREE)*0.9) return(0.0); return(lots); } bool OpenTrade(const Sig &sg) { MqlTick tk; if(!SymbolInfoTick(_Symbol,tk)) return(false); bool buy=(sg.dir>0); double price=buy ? tk.ask : tk.bid; double minDist=((double)SymbolInfoInteger(_Symbol,SYMBOL_TRADE_STOPS_LEVEL)+2.0)*_Point; double slD=MathMax(sg.slDist,minDist); double tpD=MathMax(sg.tpDist,minDist); double sl=NormalizeDouble(buy ? price-slD : price+slD,_Digits); double tp=NormalizeDouble(buy ? price+tpD : price-tpD,_Digits); ENUM_ORDER_TYPE ot=buy ? ORDER_TYPE_BUY : ORDER_TYPE_SELL; double lots=CalcLots(slD,ot,price); if(lots<=0.0) return(false); string comment="MPB_"+sg.tag; bool ok=buy ? trade.Buy(lots,_Symbol,price,sl,tp,comment) : trade.Sell(lots,_Symbol,price,sl,tp,comment); uint rc=trade.ResultRetcode(); if(ok && (rc==TRADE_RETCODE_DONE || rc==TRADE_RETCODE_PLACED)) { Notify(StringFormat("%s %s %.2f lots | %s | SL %s TP %s",buy?"BUY":"SELL",_Symbol,lots,sg.tag, DoubleToString(sl,_Digits),DoubleToString(tp,_Digits))); return(true); } Print("Order failed: ",rc," ",trade.ResultRetcodeDescription()); return(false); } //+------------------------------------------------------------------+ //| Break-even and ATR trailing | //+------------------------------------------------------------------+ void ManagePositions() { if(InpBreakEvenAtr<=0 && InpTrailAtr<=0) return; double atr=Buf(g_hAtr,0,1); if(Bad(atr)||atr<=0) return; double stopLvl=(double)SymbolInfoInteger(_Symbol,SYMBOL_TRADE_STOPS_LEVEL)*_Point; double frz=(double)SymbolInfoInteger(_Symbol,SYMBOL_TRADE_FREEZE_LEVEL)*_Point; for(int i=PositionsTotal()-1;i>=0;i--) { ulong tk=PositionGetTicket(i); if(tk==0) continue; if(PositionGetString(POSITION_SYMBOL)!=_Symbol) continue; if((ulong)PositionGetInteger(POSITION_MAGIC)!=InpMagic) continue; bool buy=(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY); double open=PositionGetDouble(POSITION_PRICE_OPEN); double sl =PositionGetDouble(POSITION_SL); double tp =PositionGetDouble(POSITION_TP); double price=buy ? SymbolInfoDouble(_Symbol,SYMBOL_BID) : SymbolInfoDouble(_Symbol,SYMBOL_ASK); double profit=buy ? price-open : open-price; double cand=0.0; bool have=false; if(InpBreakEvenAtr>0 && profit>=InpBreakEvenAtr*atr){ cand=open; have=true; } if(InpTrailAtr>0 && profit>=InpTrailAtr*atr) { double t=buy ? price-InpTrailAtr*atr : price+InpTrailAtr*atr; if(!have) cand=t; else cand=buy ? MathMax(cand,t) : MathMin(cand,t); have=true; } if(!have) continue; cand=NormalizeDouble(cand,_Digits); bool better=buy ? (sl==0.0 || cand>sl+_Point*0.5) : (sl==0.0 || candprice-stopLvl) continue; if(!buy && cand0 && ((sl>0 && MathAbs(price-sl)<=frz) || (tp>0 && MathAbs(price-tp)<=frz))) continue; trade.PositionModify(tk,cand,tp); } } //+------------------------------------------------------------------+ //| Status panel and Telegram commands | //+------------------------------------------------------------------+ string StatusText() { int n=CountPositions(false); double pnl=0.0; for(int i=PositionsTotal()-1;i>=0;i--) { ulong tk=PositionGetTicket(i); if(tk==0) continue; if((ulong)PositionGetInteger(POSITION_MAGIC)!=InpMagic) continue; pnl+=PositionGetDouble(POSITION_PROFIT)+PositionGetDouble(POSITION_SWAP); } string state="ACTIVE"; if(IsHalted()) state="HALTED (risk limit)"; else if(g_paused) state="PAUSED"; return(StringFormat("MT5ProBot | %s\nBalance %.2f | Equity %.2f\nDaily loss %.2f%% | Drawdown %.2f%%\nOpen trades %d | Floating P/L %.2f", state,AccountInfoDouble(ACCOUNT_BALANCE),AccountInfoDouble(ACCOUNT_EQUITY), DailyLossPct(),DrawdownPct(),n,pnl)); } void TgPoll() { if(InpTgToken=="" || InpTgChat=="" || MQLInfoInteger(MQL_TESTER)) return; string url="https://api.telegram.org/bot"+InpTgToken+"/getUpdates?timeout=0&offset="+(string)g_tgOffset; char post[], res[]; string rh; ResetLastError(); if(WebRequest("GET",url,"",4000,post,res,rh)==-1) return; string js=CharArrayToString(res,0,WHOLE_ARRAY,CP_UTF8); string key="\"update_id\":"; int pos=0; while((pos=StringFind(js,key,pos))>=0) { int st=pos+StringLen(key); int en=StringFind(js,",",st); if(en<0) break; long uid=StringToInteger(StringSubstr(js,st,en-st)); int nxt=StringFind(js,key,en); string seg=(nxt>=0) ? StringSubstr(js,pos,nxt-pos) : StringSubstr(js,pos); if(uid>=g_tgOffset) g_tgOffset=uid+1; if(StringFind(seg,"\"chat\":{\"id\":"+InpTgChat+",")>=0) { if(StringFind(seg,"\"text\":\"/status")>=0) TgSend(StatusText()); else if(StringFind(seg,"\"text\":\"/pause")>=0) { g_paused=true; TgSend("Paused: no new trades."); } else if(StringFind(seg,"\"text\":\"/resume")>=0) { g_paused=false; TgSend("Resumed."); } else if(StringFind(seg,"\"text\":\"/closeall")>=0){ CloseAll(); g_paused=true; TgSend("All positions closed. Bot paused."); } } pos=en; } } //+------------------------------------------------------------------+ //| Events | //+------------------------------------------------------------------+ int OnInit() { g_tf=(InpTF==PERIOD_CURRENT) ? (ENUM_TIMEFRAMES)Period() : InpTF; g_hAtr =iATR(_Symbol,g_tf,InpAtrPeriod); g_hEmaF =iMA(_Symbol,g_tf,InpEmaFast,0,MODE_EMA,PRICE_CLOSE); g_hEmaS =iMA(_Symbol,g_tf,InpEmaSlow,0,MODE_EMA,PRICE_CLOSE); g_hEmaT =iMA(_Symbol,g_tf,InpEmaTrend,0,MODE_EMA,PRICE_CLOSE); g_hRsiMr=iRSI(_Symbol,g_tf,InpMrRsiPeriod,PRICE_CLOSE); g_hBb =iBands(_Symbol,g_tf,InpMrBbPeriod,0,InpMrBbDev,PRICE_CLOSE); g_hRgF =iMA(_Symbol,g_tf,InpRgFast,0,MODE_EMA,PRICE_CLOSE); g_hRgS =iMA(_Symbol,g_tf,InpRgSlow,0,MODE_EMA,PRICE_CLOSE); g_hRgRsi=iRSI(_Symbol,g_tf,InpRgRsiPeriod,PRICE_CLOSE); g_hAdx =iADX(_Symbol,g_tf,14); if(g_hAtr==INVALID_HANDLE||g_hEmaF==INVALID_HANDLE||g_hEmaS==INVALID_HANDLE||g_hEmaT==INVALID_HANDLE|| g_hRsiMr==INVALID_HANDLE||g_hBb==INVALID_HANDLE||g_hRgF==INVALID_HANDLE||g_hRgS==INVALID_HANDLE|| g_hRgRsi==INVALID_HANDLE||g_hAdx==INVALID_HANDLE) { Print("Indicator initialisation failed. Error ",GetLastError()); return(INIT_FAILED); } if(InpRiskPct<=0 || InpRiskPct>10) { Print("Risk per trade must be between 0 and 10 percent."); return(INIT_PARAMETERS_INCORRECT); } trade.SetExpertMagicNumber(InpMagic); trade.SetDeviationInPoints(InpDeviation); trade.SetTypeFillingBySymbol(_Symbol); trade.SetAsyncMode(false); EventSetTimer(5); UpdateDay(); return(INIT_SUCCEEDED); } void OnDeinit(const int reason) { EventKillTimer(); Comment(""); if(g_hAtr !=INVALID_HANDLE) IndicatorRelease(g_hAtr); if(g_hEmaF !=INVALID_HANDLE) IndicatorRelease(g_hEmaF); if(g_hEmaS !=INVALID_HANDLE) IndicatorRelease(g_hEmaS); if(g_hEmaT !=INVALID_HANDLE) IndicatorRelease(g_hEmaT); if(g_hRsiMr!=INVALID_HANDLE) IndicatorRelease(g_hRsiMr); if(g_hBb !=INVALID_HANDLE) IndicatorRelease(g_hBb); if(g_hRgF !=INVALID_HANDLE) IndicatorRelease(g_hRgF); if(g_hRgS !=INVALID_HANDLE) IndicatorRelease(g_hRgS); if(g_hRgRsi!=INVALID_HANDLE) IndicatorRelease(g_hRgRsi); if(g_hAdx !=INVALID_HANDLE) IndicatorRelease(g_hAdx); } void OnTimer() { TgPoll(); if(!MQLInfoInteger(MQL_TESTER)) Comment(StatusText()); } void OnTick() { UpdateDay(); CheckKillSwitch(); if(CountPositions(true)>0) ManagePositions(); datetime bt=iTime(_Symbol,g_tf,0); if(bt==0 || bt==g_lastBar) return; g_lastBar=bt; if(!CanTrade()) return; Sig sg; sg.dir=0; sg.slDist=0; sg.tpDist=0; sg.tag=""; sg.day=0; if(!FindSignal(sg)) return; if(!FiltersOk()) return; if(OpenTrade(sg) && sg.tag=="BRK") g_brkDay=sg.day; } //+------------------------------------------------------------------+