ss/XAUUSD_M5_Professional_Scalper_V3.mq5

733 lines
21 KiB
MQL5

2026-09-24 04:33:45 +00:00
//+------------------------------------------------------------------+
//| XAUUSD_M5_Professional_Scalper_V3.mq5 |
//| Professional-style XAUUSD M5 scalper with risk controls |
//| No Martingale / No Grid / No guaranteed-profit logic |
//+------------------------------------------------------------------+
#property strict
#property version "3.00"
#property description "XAUUSD M5 professional scalper. Test on DEMO before live use."
#include <Trade/Trade.mqh>
CTrade trade;
//--------------------------- Inputs ---------------------------------
input group "GENERAL"
input ulong InpMagic = 26092403;
input ENUM_TIMEFRAMES InpTF = PERIOD_M5;
input bool InpOnlyGold = true;
input bool InpOneTradePerBar = true;
input group "RISK"
input double InpRiskPercent = 1.00; // risk per trade
input double InpMaxDailyLossPercent = 5.00; // closed P/L + floating loss protection
input int InpMaxConsecutiveLosses = 3;
input int InpMaxPositions = 2;
input double InpMaxTotalRiskPercent = 2.00;
input group "ENTRY"
input int InpFastEMA = 20;
input int InpSlowEMA = 50;
input int InpRSIPeriod = 14;
input double InpBuyRSIMin = 52.0;
input double InpBuyRSIMax = 72.0;
input double InpSellRSIMin = 28.0;
input double InpSellRSIMax = 48.0;
input int InpADXPeriod = 14;
input double InpMinADX = 18.0;
input int InpATRPeriod = 14;
input double InpSL_ATR = 1.35;
input double InpMinBodyATR = 0.12;
input double InpBreakoutATR = 0.05;
input group "HIGHER TIMEFRAME FILTER"
input bool InpUseHTFFilter = true;
input int InpHTFFastEMA = 50;
input int InpHTFSlowEMA = 200;
input group "TRADE MANAGEMENT"
input double InpRR = 2.20;
input double InpBreakEvenR = 0.90;
input double InpBreakEvenOffsetR = 0.08;
input double InpTrailStartR = 1.25;
input double InpTrailATR = 1.00;
input bool InpPartialClose = true;
input double InpPartialAtR = 1.00;
input double InpPartialPercent = 50.0;
input group "MARKET FILTERS"
input int InpMaxSpreadPoints = 70;
input int InpMaxSlippagePoints = 30;
input bool InpUseSession = true;
input int InpSessionStartHour = 7;
input int InpSessionEndHour = 22;
input int InpCooldownMinutes = 5;
input int InpMaxTradesPerDay = 12;
input bool InpAvoidFridayLate = true;
input int InpFridayStopHour = 19;
input group "DASHBOARD"
input bool InpShowDashboard = true;
//------------------------- Indicator handles ------------------------
int hFastEMA = INVALID_HANDLE;
int hSlowEMA = INVALID_HANDLE;
int hRSI = INVALID_HANDLE;
int hATR = INVALID_HANDLE;
int hADX = INVALID_HANDLE;
int hHTFFast = INVALID_HANDLE;
int hHTFSlow = INVALID_HANDLE;
datetime g_lastBar = 0;
datetime g_lastEntry = 0;
int g_dayOfYear = -1;
int g_year = -1;
//------------------------- Utility ----------------------------------
bool IsGoldSymbol()
{
if(!InpOnlyGold) return true;
string s = _Symbol;
StringToUpper(s);
return (StringFind(s,"XAU") >= 0 || StringFind(s,"GOLD") >= 0);
}
bool GetTick(MqlTick &tick)
{
return SymbolInfoTick(_Symbol,tick);
}
double PointValue()
{
return SymbolInfoDouble(_Symbol,SYMBOL_POINT);
}
int DigitsValue()
{
return (int)SymbolInfoInteger(_Symbol,SYMBOL_DIGITS);
}
double NormalizePrice(double p)
{
return NormalizeDouble(p,DigitsValue());
}
double NormalizeVolumeDown(double vol)
{
double minv = SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN);
double maxv = SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MAX);
double step = SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_STEP);
if(step <= 0.0) return 0.0;
if(vol > maxv) vol = maxv;
double n = MathFloor(vol / step + 1e-9);
double out = n * step;
if(out < minv) return 0.0;
return NormalizeDouble(out,2);
}
bool GetBufferValue(int handle,int buffer,int shift,double &value)
{
double a[];
ArraySetAsSeries(a,true);
if(CopyBuffer(handle,buffer,shift,1,a) != 1)
return false;
value = a[0];
return true;
}
bool GetRates(MqlRates &r1,MqlRates &r2,MqlRates &r3)
{
MqlRates rates[];
ArraySetAsSeries(rates,true);
if(CopyRates(_Symbol,InpTF,0,4,rates) < 4)
return false;
r1=rates[1]; // completed candle
r2=rates[2];
r3=rates[3];
return true;
}
bool IsNewBar()
{
datetime t=iTime(_Symbol,InpTF,0);
if(t==0) return false;
if(t!=g_lastBar)
{
g_lastBar=t;
return true;
}
return false;
}
void ResetDayIfNeeded()
{
MqlDateTime dt;
TimeToStruct(TimeCurrent(),dt);
if(dt.day_of_year!=g_dayOfYear || dt.year!=g_year)
{
g_dayOfYear=dt.day_of_year;
g_year=dt.year;
}
}
bool InSession()
{
if(!InpUseSession) return true;
MqlDateTime dt;
TimeToStruct(TimeCurrent(),dt);
int h=dt.hour;
if(InpSessionStartHour <= InpSessionEndHour)
return (h>=InpSessionStartHour && h<InpSessionEndHour);
return (h>=InpSessionStartHour || h<InpSessionEndHour);
}
bool FridayLate()
{
if(!InpAvoidFridayLate) return false;
MqlDateTime dt;
TimeToStruct(TimeCurrent(),dt);
return (dt.day_of_week==5 && dt.hour>=InpFridayStopHour);
}
double CurrentSpreadPoints()
{
MqlTick tick;
if(!GetTick(tick)) return 999999.0;
double pt=PointValue();
if(pt<=0) return 999999.0;
return (tick.ask-tick.bid)/pt;
}
bool SpreadOK()
{
return CurrentSpreadPoints() <= InpMaxSpreadPoints;
}
int CountOpenPositions()
{
int count=0;
for(int i=PositionsTotal()-1;i>=0;i--)
{
ulong ticket=PositionGetTicket(i);
if(ticket==0) continue;
if(!PositionSelectByTicket(ticket)) continue;
if(PositionGetString(POSITION_SYMBOL)!=_Symbol) continue;
if((ulong)PositionGetInteger(POSITION_MAGIC)!=InpMagic) continue;
count++;
}
return count;
}
double CurrentOpenRiskMoney()
{
double total=0.0;
double tickSize=SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_SIZE);
double tickValue=SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_VALUE);
if(tickSize<=0 || tickValue<=0) return 0.0;
for(int i=PositionsTotal()-1;i>=0;i--)
{
ulong ticket=PositionGetTicket(i);
if(ticket==0) continue;
if(!PositionSelectByTicket(ticket)) continue;
if(PositionGetString(POSITION_SYMBOL)!=_Symbol) continue;
if((ulong)PositionGetInteger(POSITION_MAGIC)!=InpMagic) continue;
double open=PositionGetDouble(POSITION_PRICE_OPEN);
double sl=PositionGetDouble(POSITION_SL);
double vol=PositionGetDouble(POSITION_VOLUME);
if(sl<=0 || vol<=0) continue;
double dist=MathAbs(open-sl);
total += (dist/tickSize)*tickValue*vol;
}
return total;
}
datetime DayStart()
{
MqlDateTime dt;
TimeToStruct(TimeCurrent(),dt);
dt.hour=0; dt.min=0; dt.sec=0;
return StructToTime(dt);
}
double ClosedProfitToday()
{
datetime from=DayStart();
datetime to=TimeCurrent();
if(!HistorySelect(from,to)) return 0.0;
double result=0.0;
int deals=HistoryDealsTotal();
for(int i=0;i<deals;i++)
{
ulong ticket=HistoryDealGetTicket(i);
if(ticket==0) continue;
string sym=HistoryDealGetString(ticket,DEAL_SYMBOL);
long magic=HistoryDealGetInteger(ticket,DEAL_MAGIC);
long entry=HistoryDealGetInteger(ticket,DEAL_ENTRY);
if(sym!=_Symbol || (ulong)magic!=InpMagic) continue;
if(entry!=DEAL_ENTRY_OUT && entry!=DEAL_ENTRY_OUT_BY) continue;
result += HistoryDealGetDouble(ticket,DEAL_PROFIT);
result += HistoryDealGetDouble(ticket,DEAL_SWAP);
result += HistoryDealGetDouble(ticket,DEAL_COMMISSION);
}
return result;
}
double FloatingProfit()
{
double result=0.0;
for(int i=PositionsTotal()-1;i>=0;i--)
{
ulong ticket=PositionGetTicket(i);
if(ticket==0) continue;
if(!PositionSelectByTicket(ticket)) continue;
if(PositionGetString(POSITION_SYMBOL)!=_Symbol) continue;
if((ulong)PositionGetInteger(POSITION_MAGIC)!=InpMagic) continue;
result += PositionGetDouble(POSITION_PROFIT);
}
return result;
}
int TradesToday()
{
datetime from=DayStart();
if(!HistorySelect(from,TimeCurrent())) return 0;
int count=0;
int deals=HistoryDealsTotal();
for(int i=0;i<deals;i++)
{
ulong ticket=HistoryDealGetTicket(i);
if(ticket==0) continue;
if(HistoryDealGetString(ticket,DEAL_SYMBOL)!=_Symbol) continue;
if((ulong)HistoryDealGetInteger(ticket,DEAL_MAGIC)!=InpMagic) continue;
if(HistoryDealGetInteger(ticket,DEAL_ENTRY)==DEAL_ENTRY_IN)
count++;
}
return count;
}
int ConsecutiveLosses()
{
datetime from=DayStart();
if(!HistorySelect(from,TimeCurrent())) return 0;
int losses=0;
int total=HistoryDealsTotal();
for(int i=total-1;i>=0;i--)
{
ulong ticket=HistoryDealGetTicket(i);
if(ticket==0) continue;
if(HistoryDealGetString(ticket,DEAL_SYMBOL)!=_Symbol) continue;
if((ulong)HistoryDealGetInteger(ticket,DEAL_MAGIC)!=InpMagic) continue;
long entry=HistoryDealGetInteger(ticket,DEAL_ENTRY);
if(entry!=DEAL_ENTRY_OUT && entry!=DEAL_ENTRY_OUT_BY) continue;
double p=HistoryDealGetDouble(ticket,DEAL_PROFIT)
+HistoryDealGetDouble(ticket,DEAL_SWAP)
+HistoryDealGetDouble(ticket,DEAL_COMMISSION);
if(p < -0.01) losses++;
else if(p > 0.01) break;
}
return losses;
}
bool DailyLossReached()
{
double balance=AccountInfoDouble(ACCOUNT_BALANCE);
if(balance<=0) return true;
double closed=ClosedProfitToday();
double floating=FloatingProfit();
double lossMoney=-(closed+floating);
double maxLoss=balance*InpMaxDailyLossPercent/100.0;
return (lossMoney >= maxLoss);
}
double CalculateLot(double stopDistancePrice)
{
if(stopDistancePrice<=0) return 0.0;
double balance=AccountInfoDouble(ACCOUNT_BALANCE);
double riskMoney=balance*InpRiskPercent/100.0;
double tickSize=SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_SIZE);
double tickValue=SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_VALUE_LOSS);
if(tickValue<=0)
tickValue=SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_VALUE);
if(tickSize<=0 || tickValue<=0) return 0.0;
double lossPerLot=(stopDistancePrice/tickSize)*tickValue;
if(lossPerLot<=0) return 0.0;
double lots=riskMoney/lossPerLot;
return NormalizeVolumeDown(lots);
}
bool CooldownOK()
{
if(g_lastEntry==0) return true;
return (TimeCurrent()-g_lastEntry >= InpCooldownMinutes*60);
}
bool HTFTrendOK(bool buy)
{
if(!InpUseHTFFilter) return true;
double fast,slow;
if(!GetBufferValue(hHTFFast,0,1,fast)) return false;
if(!GetBufferValue(hHTFSlow,0,1,slow)) return false;
if(buy) return fast>slow;
return fast<slow;
}
bool EntrySignal(bool buy,double &atrOut)
{
MqlRates r1,r2,r3;
if(!GetRates(r1,r2,r3)) return false;
double emaFast,emaSlow,rsi,atr,adx;
if(!GetBufferValue(hFastEMA,0,1,emaFast)) return false;
if(!GetBufferValue(hSlowEMA,0,1,emaSlow)) return false;
if(!GetBufferValue(hRSI,0,1,rsi)) return false;
if(!GetBufferValue(hATR,0,1,atr)) return false;
if(!GetBufferValue(hADX,0,1,adx)) return false;
atrOut=atr;
if(atr<=0 || adx<InpMinADX) return false;
double body=MathAbs(r1.close-r1.open);
if(body < atr*InpMinBodyATR) return false;
bool bullish=r1.close>r1.open;
bool bearish=r1.close<r1.open;
if(buy)
{
if(!(emaFast>emaSlow)) return false;
if(!HTFTrendOK(true)) return false;
if(!bullish) return false;
if(rsi<InpBuyRSIMin || rsi>InpBuyRSIMax) return false;
if(r1.close <= r2.high + atr*InpBreakoutATR) return false;
return true;
}
else
{
if(!(emaFast<emaSlow)) return false;
if(!HTFTrendOK(false)) return false;
if(!bearish) return false;
if(rsi<InpSellRSIMin || rsi>InpSellRSIMax) return false;
if(r1.close >= r2.low - atr*InpBreakoutATR) return false;
return true;
}
}
bool ModifyPosition(ulong ticket,double sl,double tp)
{
if(!PositionSelectByTicket(ticket)) return false;
string sym=PositionGetString(POSITION_SYMBOL);
if(sym!=_Symbol) return false;
return trade.PositionModify(ticket,NormalizePrice(sl),NormalizePrice(tp));
}
bool PartialDone(ulong ticket)
{
string key="V3P_"+(string)ticket;
return GlobalVariableCheck(key);
}
void MarkPartialDone(ulong ticket)
{
string key="V3P_"+(string)ticket;
GlobalVariableSet(key,(double)TimeCurrent());
}
void ManagePositions()
{
double atr;
if(!GetBufferValue(hATR,0,1,atr)) return;
MqlTick tick;
if(!GetTick(tick)) return;
double pt=PointValue();
int stopsLevel=(int)SymbolInfoInteger(_Symbol,SYMBOL_TRADE_STOPS_LEVEL);
double minStop=stopsLevel*pt;
for(int i=PositionsTotal()-1;i>=0;i--)
{
ulong ticket=PositionGetTicket(i);
if(ticket==0) continue;
if(!PositionSelectByTicket(ticket)) continue;
if(PositionGetString(POSITION_SYMBOL)!=_Symbol) continue;
if((ulong)PositionGetInteger(POSITION_MAGIC)!=InpMagic) continue;
long type=PositionGetInteger(POSITION_TYPE);
double open=PositionGetDouble(POSITION_PRICE_OPEN);
double sl=PositionGetDouble(POSITION_SL);
double tp=PositionGetDouble(POSITION_TP);
double volume=PositionGetDouble(POSITION_VOLUME);
if(sl<=0) continue;
double current=(type==POSITION_TYPE_BUY ? tick.bid : tick.ask);
double initialRisk=MathAbs(open-sl);
// If SL has already moved beyond the original area, use a conservative
// proxy based on ATR for management.
if(initialRisk < pt*2) initialRisk=atr*InpSL_ATR;
double profitDist=(type==POSITION_TYPE_BUY ? current-open : open-current);
double R=profitDist/initialRisk;
// Partial close
if(InpPartialClose && !PartialDone(ticket) && R>=InpPartialAtR)
{
double closeVol=NormalizeVolumeDown(volume*InpPartialPercent/100.0);
double minv=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN);
if(closeVol>=minv && closeVol<volume)
{
if(trade.PositionClosePartial(ticket,closeVol))
MarkPartialDone(ticket);
}
else
{
MarkPartialDone(ticket);
}
}
// Break-even
if(R>=InpBreakEvenR)
{
double beOffset=initialRisk*InpBreakEvenOffsetR;
double newSL=(type==POSITION_TYPE_BUY ? open+beOffset : open-beOffset);
bool better=(type==POSITION_TYPE_BUY ? (sl<newSL) : (sl>newSL));
bool valid=(type==POSITION_TYPE_BUY ? (newSL<current-minStop) : (newSL>current+minStop));
if(better && valid)
ModifyPosition(ticket,newSL,tp);
}
// ATR trailing
if(R>=InpTrailStartR)
{
double trail=atr*InpTrailATR;
double newSL=(type==POSITION_TYPE_BUY ? current-trail : current+trail);
bool better=(type==POSITION_TYPE_BUY ? (newSL>sl) : (newSL<sl));
bool valid=(type==POSITION_TYPE_BUY ? (newSL<current-minStop) : (newSL>current+minStop));
if(better && valid)
ModifyPosition(ticket,newSL,tp);
}
}
}
bool CanTradeNow()
{
if(!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED)) return false;
if(!MQLInfoInteger(MQL_TRADE_ALLOWED)) return false;
if(!IsGoldSymbol()) return false;
if(!InSession()) return false;
if(FridayLate()) return false;
if(!SpreadOK()) return false;
if(DailyLossReached()) return false;
if(ConsecutiveLosses()>=InpMaxConsecutiveLosses) return false;
if(TradesToday()>=InpMaxTradesPerDay) return false;
if(CountOpenPositions()>=InpMaxPositions) return false;
if(!CooldownOK()) return false;
double balance=AccountInfoDouble(ACCOUNT_BALANCE);
if(balance<=0) return false;
double maxRiskMoney=balance*InpMaxTotalRiskPercent/100.0;
if(CurrentOpenRiskMoney()>=maxRiskMoney) return false;
return true;
}
void OpenTrade(bool buy,double atr)
{
MqlTick tick;
if(!GetTick(tick)) return;
double entry=(buy ? tick.ask : tick.bid);
double slDist=atr*InpSL_ATR;
double tpDist=slDist*InpRR;
int stopsLevel=(int)SymbolInfoInteger(_Symbol,SYMBOL_TRADE_STOPS_LEVEL);
double minStop=stopsLevel*PointValue();
if(slDist<minStop*1.2) slDist=minStop*1.2;
double lots=CalculateLot(slDist);
if(lots<=0) return;
double balance=AccountInfoDouble(ACCOUNT_BALANCE);
double currentRisk=CurrentOpenRiskMoney();
double newRisk=0.0;
double tickSize=SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_SIZE);
double tickValue=SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_VALUE_LOSS);
if(tickValue<=0) tickValue=SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_VALUE);
if(tickSize>0 && tickValue>0)
newRisk=(slDist/tickSize)*tickValue*lots;
double maxRiskMoney=balance*InpMaxTotalRiskPercent/100.0;
if(currentRisk+newRisk>maxRiskMoney+0.01) return;
double sl=(buy ? entry-slDist : entry+slDist);
double tp=(buy ? entry+tpDist : entry-tpDist);
sl=NormalizePrice(sl);
tp=NormalizePrice(tp);
trade.SetExpertMagicNumber(InpMagic);
trade.SetDeviationInPoints(InpMaxSlippagePoints);
trade.SetTypeFillingBySymbol(_Symbol);
bool ok=false;
if(buy)
ok=trade.Buy(lots,_Symbol,0.0,sl,tp,"V3_SCALP_BUY");
else
ok=trade.Sell(lots,_Symbol,0.0,sl,tp,"V3_SCALP_SELL");
if(ok)
g_lastEntry=TimeCurrent();
}
string StatusText()
{
if(!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED)) return "TERMINAL TRADE OFF";
if(!MQLInfoInteger(MQL_TRADE_ALLOWED)) return "EA TRADE OFF";
if(!IsGoldSymbol()) return "WRONG SYMBOL";
if(DailyLossReached()) return "DAILY STOP";
if(ConsecutiveLosses()>=InpMaxConsecutiveLosses) return "LOSS STOP";
if(!InSession()) return "OUT OF SESSION";
if(FridayLate()) return "FRIDAY STOP";
if(!SpreadOK()) return "HIGH SPREAD";
if(TradesToday()>=InpMaxTradesPerDay) return "DAILY TRADE LIMIT";
if(CountOpenPositions()>=InpMaxPositions) return "MAX POSITIONS";
return "READY";
}
void UpdateDashboard()
{
if(!InpShowDashboard) return;
double balance=AccountInfoDouble(ACCOUNT_BALANCE);
double equity=AccountInfoDouble(ACCOUNT_EQUITY);
double closed=ClosedProfitToday();
double floating=FloatingProfit();
double daily=closed+floating;
double dd=(balance>0 ? MathMax(0.0,(balance-equity)/balance*100.0) : 0.0);
string text=
"XAUUSD M5 SCALPER V3\n"+
"Status: "+StatusText()+"\n"+
"Balance: $"+DoubleToString(balance,2)+"\n"+
"Equity: $"+DoubleToString(equity,2)+"\n"+
"Daily P/L: $"+DoubleToString(daily,2)+"\n"+
"Drawdown: "+DoubleToString(dd,2)+"%\n"+
"Trades today: "+IntegerToString(TradesToday())+"\n"+
"Open positions: "+IntegerToString(CountOpenPositions())+"\n"+
"Loss streak: "+IntegerToString(ConsecutiveLosses())+"\n"+
"Spread: "+DoubleToString(CurrentSpreadPoints(),1)+" pts";
Comment(text);
}
//------------------------- Lifecycle --------------------------------
int OnInit()
{
if(!IsGoldSymbol())
Print("Warning: EA is designed for XAUUSD/GOLD symbols.");
hFastEMA=iMA(_Symbol,InpTF,InpFastEMA,0,MODE_EMA,PRICE_CLOSE);
hSlowEMA=iMA(_Symbol,InpTF,InpSlowEMA,0,MODE_EMA,PRICE_CLOSE);
hRSI=iRSI(_Symbol,InpTF,InpRSIPeriod,PRICE_CLOSE);
hATR=iATR(_Symbol,InpTF,InpATRPeriod);
hADX=iADX(_Symbol,InpTF,InpADXPeriod);
if(InpUseHTFFilter)
{
hHTFFast=iMA(_Symbol,PERIOD_M15,InpHTFFastEMA,0,MODE_EMA,PRICE_CLOSE);
hHTFSlow=iMA(_Symbol,PERIOD_M15,InpHTFSlowEMA,0,MODE_EMA,PRICE_CLOSE);
}
if(hFastEMA==INVALID_HANDLE || hSlowEMA==INVALID_HANDLE ||
hRSI==INVALID_HANDLE || hATR==INVALID_HANDLE || hADX==INVALID_HANDLE)
{
Print("Failed to create indicator handles.");
return INIT_FAILED;
}
if(InpUseHTFFilter && (hHTFFast==INVALID_HANDLE || hHTFSlow==INVALID_HANDLE))
{
Print("Failed to create HTF indicator handles.");
return INIT_FAILED;
}
ResetDayIfNeeded();
trade.SetExpertMagicNumber(InpMagic);
trade.SetDeviationInPoints(InpMaxSlippagePoints);
trade.SetTypeFillingBySymbol(_Symbol);
Print("XAUUSD M5 Professional Scalper V3 initialized.");
return INIT_SUCCEEDED;
}
void OnDeinit(const int reason)
{
if(hFastEMA!=INVALID_HANDLE) IndicatorRelease(hFastEMA);
if(hSlowEMA!=INVALID_HANDLE) IndicatorRelease(hSlowEMA);
if(hRSI!=INVALID_HANDLE) IndicatorRelease(hRSI);
if(hATR!=INVALID_HANDLE) IndicatorRelease(hATR);
if(hADX!=INVALID_HANDLE) IndicatorRelease(hADX);
if(hHTFFast!=INVALID_HANDLE) IndicatorRelease(hHTFFast);
if(hHTFSlow!=INVALID_HANDLE) IndicatorRelease(hHTFSlow);
Comment("");
}
void OnTick()
{
ResetDayIfNeeded();
ManagePositions();
UpdateDashboard();
if(!IsNewBar()) return;
if(!CanTradeNow()) return;
double atr=0.0;
if(EntrySignal(true,atr))
{
OpenTrade(true,atr);
return;
}
if(EntrySignal(false,atr))
{
OpenTrade(false,atr);
return;
}
}
//+------------------------------------------------------------------+