fix: Compilation errors in MetaEditor.

This commit is contained in:
Naji El Chemaly
2026-06-02 22:13:09 +03:00
parent 3115a21e36
commit ea5efd1d9b
+145 -117
View File
@@ -450,23 +450,22 @@ void UpdateORBSessions()
for(int s = 0; s < g_SessionCount; s++)
{
SSession *sess = &g_Sessions[s];
if(!sess.enabled) continue;
if(!g_Sessions[s].enabled) continue;
// Session open bar starts accumulation
if(IsSessionOpenBar(*sess, barTime))
if(IsSessionOpenBar(g_Sessions[s], barTime))
{
// Reset session state for new day's ORB
sess.orbHigh = barHigh;
sess.orbLow = barLow;
sess.orbBarCount = 1;
sess.orbStartTime= barTime;
sess.orbComplete = (g_OrbBarsNeeded == 1); // M15: complete immediately
sess.breakoutDir = 0;
sess.inBreakout = false;
sess.inRetest = false;
sess.breakoutBarsAgo = 0;
sess.tradesThisSession = 0;
g_Sessions[s].orbHigh = barHigh;
g_Sessions[s].orbLow = barLow;
g_Sessions[s].orbBarCount = 1;
g_Sessions[s].orbStartTime = barTime;
g_Sessions[s].orbComplete = (g_OrbBarsNeeded == 1);
g_Sessions[s].breakoutDir = 0;
g_Sessions[s].inBreakout = false;
g_Sessions[s].inRetest = false;
g_Sessions[s].breakoutBarsAgo = 0;
g_Sessions[s].tradesThisSession= 0;
if(InpShowORBLines)
DrawORBLines(s);
@@ -474,23 +473,25 @@ void UpdateORBSessions()
}
// Still accumulating (M5 or M1)
if(!sess.orbComplete && sess.orbBarCount > 0 && IsWithinOrbWindow(*sess, barTime))
if(!g_Sessions[s].orbComplete && g_Sessions[s].orbBarCount > 0
&& IsWithinOrbWindow(g_Sessions[s], barTime))
{
sess.orbHigh = MathMax(sess.orbHigh, barHigh);
sess.orbLow = MathMin(sess.orbLow, barLow);
sess.orbBarCount++;
if(sess.orbBarCount >= g_OrbBarsNeeded)
g_Sessions[s].orbHigh = MathMax(g_Sessions[s].orbHigh, barHigh);
g_Sessions[s].orbLow = MathMin(g_Sessions[s].orbLow, barLow);
g_Sessions[s].orbBarCount++;
if(g_Sessions[s].orbBarCount >= g_OrbBarsNeeded)
{
sess.orbComplete = true;
PrintFormat("NANDR EA: [%s] ORB complete. High=%.2f Low=%.2f", sess.name, sess.orbHigh, sess.orbLow);
g_Sessions[s].orbComplete = true;
PrintFormat("NANDR EA: [%s] ORB complete. High=%.2f Low=%.2f",
g_Sessions[s].name, g_Sessions[s].orbHigh, g_Sessions[s].orbLow);
}
if(InpShowORBLines)
DrawORBLines(s);
}
// Track breakout bar age
if(sess.inBreakout)
sess.breakoutBarsAgo++;
if(g_Sessions[s].inBreakout)
g_Sessions[s].breakoutBarsAgo++;
}
}
@@ -553,31 +554,32 @@ void DetectBreakouts()
{
for(int s = 0; s < g_SessionCount; s++)
{
SSession *sess = &g_Sessions[s];
if(!sess.enabled || !sess.orbComplete) continue;
if(sess.orbHigh <= 0 || sess.orbLow >= DBL_MAX) continue;
if(sess.inBreakout || sess.inRetest) continue; // already tracking one
if(!g_Sessions[s].enabled || !g_Sessions[s].orbComplete) continue;
if(g_Sessions[s].orbHigh <= 0 || g_Sessions[s].orbLow >= DBL_MAX) continue;
if(g_Sessions[s].inBreakout || g_Sessions[s].inRetest) continue;
bool bullBO = InpUseStrictFilter
? CheckStrictBreakout( 1, sess.orbHigh)
: CheckSimpleBreakout( 1, sess.orbHigh);
? CheckStrictBreakout( 1, g_Sessions[s].orbHigh)
: CheckSimpleBreakout( 1, g_Sessions[s].orbHigh);
bool bearBO = InpUseStrictFilter
? CheckStrictBreakout(-1, sess.orbLow)
: CheckSimpleBreakout(-1, sess.orbLow);
? CheckStrictBreakout(-1, g_Sessions[s].orbLow)
: CheckSimpleBreakout(-1, g_Sessions[s].orbLow);
if(bullBO)
{
sess.breakoutDir = 1;
sess.inBreakout = true;
sess.breakoutBarsAgo = 0;
PrintFormat("NANDR EA: [%s] Bullish ORB breakout at %.2f", sess.name, sess.orbHigh);
g_Sessions[s].breakoutDir = 1;
g_Sessions[s].inBreakout = true;
g_Sessions[s].breakoutBarsAgo= 0;
PrintFormat("NANDR EA: [%s] Bullish ORB breakout at %.2f",
g_Sessions[s].name, g_Sessions[s].orbHigh);
}
else if(bearBO)
{
sess.breakoutDir = -1;
sess.inBreakout = true;
sess.breakoutBarsAgo = 0;
PrintFormat("NANDR EA: [%s] Bearish ORB breakout at %.2f", sess.name, sess.orbLow);
g_Sessions[s].breakoutDir = -1;
g_Sessions[s].inBreakout = true;
g_Sessions[s].breakoutBarsAgo= 0;
PrintFormat("NANDR EA: [%s] Bearish ORB breakout at %.2f",
g_Sessions[s].name, g_Sessions[s].orbLow);
}
}
}
@@ -587,8 +589,7 @@ void DetectBreakouts()
//+------------------------------------------------------------------+
bool DetectRetest(int sessIdx, int &dir)
{
SSession *sess = &g_Sessions[sessIdx];
if(!sess.inBreakout) return false;
if(!g_Sessions[sessIdx].inBreakout) return false;
double c0 = iClose(g_Symbol, PERIOD_CURRENT, 0);
double c1 = iClose(g_Symbol, PERIOD_CURRENT, 1);
@@ -596,28 +597,36 @@ bool DetectRetest(int sessIdx, int &dir)
double l0 = iLow(g_Symbol, PERIOD_CURRENT, 0);
// Bullish retest: previous bar was above ORB, this bar touched it and closed back above
if(sess.breakoutDir == 1)
if(g_Sessions[sessIdx].breakoutDir == 1)
{
bool retest = (c1 > sess.orbHigh) && (l0 <= sess.orbHigh) && (c0 >= sess.orbHigh);
bool retest = (c1 > g_Sessions[sessIdx].orbHigh)
&& (l0 <= g_Sessions[sessIdx].orbHigh)
&& (c0 >= g_Sessions[sessIdx].orbHigh);
if(retest) { dir = 1; return true; }
}
// Bearish retest: previous bar was below ORB, this bar touched it and closed back below
else if(sess.breakoutDir == -1)
else if(g_Sessions[sessIdx].breakoutDir == -1)
{
bool retest = (c1 < sess.orbLow) && (h0 >= sess.orbLow) && (c0 <= sess.orbLow);
bool retest = (c1 < g_Sessions[sessIdx].orbLow)
&& (h0 >= g_Sessions[sessIdx].orbLow)
&& (c0 <= g_Sessions[sessIdx].orbLow);
if(retest) { dir = -1; return true; }
}
// Failed retest
if(sess.breakoutDir == 1 && c0 < sess.orbHigh && c1 > sess.orbHigh)
if(g_Sessions[sessIdx].breakoutDir == 1
&& c0 < g_Sessions[sessIdx].orbHigh && c1 > g_Sessions[sessIdx].orbHigh)
{
PrintFormat("NANDR EA: [%s] Failed bullish retest", sess.name);
sess.inBreakout = false; sess.breakoutDir = 0;
PrintFormat("NANDR EA: [%s] Failed bullish retest", g_Sessions[sessIdx].name);
g_Sessions[sessIdx].inBreakout = false;
g_Sessions[sessIdx].breakoutDir = 0;
}
else if(sess.breakoutDir == -1 && c0 > sess.orbLow && c1 < sess.orbLow)
else if(g_Sessions[sessIdx].breakoutDir == -1
&& c0 > g_Sessions[sessIdx].orbLow && c1 < g_Sessions[sessIdx].orbLow)
{
PrintFormat("NANDR EA: [%s] Failed bearish retest", sess.name);
sess.inBreakout = false; sess.breakoutDir = 0;
PrintFormat("NANDR EA: [%s] Failed bearish retest", g_Sessions[sessIdx].name);
g_Sessions[sessIdx].inBreakout = false;
g_Sessions[sessIdx].breakoutDir = 0;
}
return false;
@@ -634,7 +643,7 @@ void ScanOrderBlocks()
// Check for volume pivot at bar[length]
// Volume at bar[length] must be highest in [0..2*length]
double pivotVol = iVolume(g_Symbol, PERIOD_CURRENT, length);
long pivotVol = iVolume(g_Symbol, PERIOD_CURRENT, length);
bool isVolPivot = true;
for(int i = 0; i < length * 2 + 1; i++)
{
@@ -911,22 +920,21 @@ void CheckEntrySignals()
{
for(int s = 0; s < g_SessionCount; s++)
{
SSession *sess = &g_Sessions[s];
if(!sess.enabled || !sess.orbComplete) continue;
if(sess.tradesThisSession >= InpMaxPosPerSession) continue;
if(!g_Sessions[s].enabled || !g_Sessions[s].orbComplete) continue;
if(g_Sessions[s].tradesThisSession >= InpMaxPosPerSession) continue;
int dir = 0;
if(!DetectRetest(s, dir)) continue;
double obTop = 0, obBottom = 0;
bool obFound = IsOBNearLevel(
(dir > 0) ? sess.orbHigh : sess.orbLow,
(dir > 0) ? g_Sessions[s].orbHigh : g_Sessions[s].orbLow,
dir, obTop, obBottom);
// If OB required and not found, skip
if(InpOBRequireConf && !obFound) continue;
double orbLevel = (dir > 0) ? sess.orbHigh : sess.orbLow;
double orbLevel = (dir > 0) ? g_Sessions[s].orbHigh : g_Sessions[s].orbLow;
OpenTrade(dir, s, orbLevel, obTop, obBottom);
}
}
@@ -946,7 +954,7 @@ void ManageOpenTrades()
double sl = g_Position.StopLoss();
double currentSL= sl;
double price = g_Position.PriceCurrent();
long ticket = g_Position.Ticket();
ulong ticket = g_Position.Ticket();
int posDir = (g_Position.PositionType() == POSITION_TYPE_BUY) ? 1 : -1;
// Breakeven
@@ -1083,46 +1091,51 @@ void UpdateClosedTrades()
void DrawORBLines(int sessIdx)
{
if(sessIdx < 0 || sessIdx >= g_SessionCount) return;
SSession *sess = &g_Sessions[sessIdx];
color lineColor = clrWhite;
if(sess.name == "Tokyo") lineColor = clrDodgerBlue;
else if(sess.name == "London") lineColor = clrTomato;
else if(sess.name == "NY" || sess.name == "NYORB") lineColor = clrGold;
else if(sess.name == "DailyOpen") lineColor = clrSilver;
if(g_Sessions[sessIdx].name == "Tokyo") lineColor = clrDodgerBlue;
else if(g_Sessions[sessIdx].name == "London") lineColor = clrTomato;
else if(g_Sessions[sessIdx].name == "NY"
|| g_Sessions[sessIdx].name == "NYORB") lineColor = clrGold;
else if(g_Sessions[sessIdx].name == "DailyOpen") lineColor = clrSilver;
string prefix = "NANDR_ORB_" + sess.name + "_";
string prefix = "NANDR_ORB_" + g_Sessions[sessIdx].name + "_";
// High line
string hName = prefix + "High";
ObjectDelete(0, hName);
if(sess.orbHigh > 0)
if(g_Sessions[sessIdx].orbHigh > 0)
{
ObjectCreate(0, hName, OBJ_HLINE, 0, 0, sess.orbHigh);
ObjectCreate(0, hName, OBJ_HLINE, 0, 0, g_Sessions[sessIdx].orbHigh);
ObjectSetInteger(0, hName, OBJPROP_COLOR, lineColor);
ObjectSetInteger(0, hName, OBJPROP_STYLE, STYLE_SOLID);
ObjectSetInteger(0, hName, OBJPROP_WIDTH, 1);
ObjectSetString(0, hName, OBJPROP_TOOLTIP, sess.name + " ORB High: " + DoubleToString(sess.orbHigh, 2));
ObjectSetString(0, hName, OBJPROP_TOOLTIP,
g_Sessions[sessIdx].name + " ORB High: " +
DoubleToString(g_Sessions[sessIdx].orbHigh, 2));
}
// Low line
string lName = prefix + "Low";
ObjectDelete(0, lName);
if(sess.orbLow < DBL_MAX && sess.orbLow > 0)
if(g_Sessions[sessIdx].orbLow < DBL_MAX && g_Sessions[sessIdx].orbLow > 0)
{
ObjectCreate(0, lName, OBJ_HLINE, 0, 0, sess.orbLow);
ObjectCreate(0, lName, OBJ_HLINE, 0, 0, g_Sessions[sessIdx].orbLow);
ObjectSetInteger(0, lName, OBJPROP_COLOR, lineColor);
ObjectSetInteger(0, lName, OBJPROP_STYLE, STYLE_SOLID);
ObjectSetInteger(0, lName, OBJPROP_WIDTH, 1);
ObjectSetString(0, lName, OBJPROP_TOOLTIP, sess.name + " ORB Low: " + DoubleToString(sess.orbLow, 2));
ObjectSetString(0, lName, OBJPROP_TOOLTIP,
g_Sessions[sessIdx].name + " ORB Low: " +
DoubleToString(g_Sessions[sessIdx].orbLow, 2));
}
// Mid line (dotted)
if(sess.orbHigh > 0 && sess.orbLow < DBL_MAX && sess.orbLow > 0)
if(g_Sessions[sessIdx].orbHigh > 0
&& g_Sessions[sessIdx].orbLow < DBL_MAX && g_Sessions[sessIdx].orbLow > 0)
{
string mName = prefix + "Mid";
ObjectDelete(0, mName);
double mid = (sess.orbHigh + sess.orbLow) / 2.0;
double mid = (g_Sessions[sessIdx].orbHigh + g_Sessions[sessIdx].orbLow) / 2.0;
ObjectCreate(0, mName, OBJ_HLINE, 0, 0, mid);
ObjectSetInteger(0, mName, OBJPROP_COLOR, lineColor);
ObjectSetInteger(0, mName, OBJPROP_STYLE, STYLE_DOT);
@@ -1137,7 +1150,9 @@ void DrawORBLines(int sessIdx)
//+------------------------------------------------------------------+
void DrawOBZone(int idx, bool isBull)
{
SOrderBlock *ob = isBull ? &g_BullOBs[idx] : &g_BearOBs[idx];
SOrderBlock ob;
if(isBull) ob = g_BullOBs[idx];
else ob = g_BearOBs[idx];
if(!ob.active) return;
color bgColor = isBull ? (color)ColorToARGB(clrGreen, 40) : (color)ColorToARGB(clrRed, 40);
@@ -1207,6 +1222,28 @@ void DrawTradeLabel(int dir, double entry, double sl, double tp)
ChartRedraw(0);
}
// Dashboard helper — module-level state set by DrawDashboard before each call
string g_DBPrefix = "NANDR_DB_";
int g_DBX = 15;
int g_DBY = 30;
int g_DBDY = 18;
int g_DBLine = 0;
void DBLine(string txt, color col, int fontSize = 9)
{
string name = g_DBPrefix + IntegerToString(g_DBLine);
ObjectDelete(0, name);
ObjectCreate(0, name, OBJ_LABEL, 0, 0, 0);
ObjectSetInteger(0, name, OBJPROP_CORNER, CORNER_LEFT_UPPER);
ObjectSetInteger(0, name, OBJPROP_XDISTANCE, g_DBX);
ObjectSetInteger(0, name, OBJPROP_YDISTANCE, g_DBY + g_DBLine * g_DBDY);
ObjectSetInteger(0, name, OBJPROP_COLOR, col);
ObjectSetInteger(0, name, OBJPROP_FONTSIZE, fontSize);
ObjectSetString(0, name, OBJPROP_FONT, "Consolas");
ObjectSetString(0, name, OBJPROP_TEXT, txt);
g_DBLine++;
}
//+------------------------------------------------------------------+
//| Draw dashboard |
//+------------------------------------------------------------------+
@@ -1214,72 +1251,63 @@ void DrawDashboard()
{
if(!InpShowDashboard) return;
string prefix = "NANDR_DB_";
int x = 15;
int y = 30;
int dy = 18;
int line = 0;
color title = clrGold;
color normal = clrSilver;
color good = clrLimeGreen;
color bad = clrTomato;
auto DrawText = [&](string txt, color col, int fontSize = 9)
{
string name = prefix + IntegerToString(line);
ObjectDelete(0, name);
ObjectCreate(0, name, OBJ_LABEL, 0, 0, 0);
ObjectSetInteger(0, name, OBJPROP_CORNER, CORNER_LEFT_UPPER);
ObjectSetInteger(0, name, OBJPROP_XDISTANCE, x);
ObjectSetInteger(0, name, OBJPROP_YDISTANCE, y + line * dy);
ObjectSetInteger(0, name, OBJPROP_COLOR, col);
ObjectSetInteger(0, name, OBJPROP_FONTSIZE, fontSize);
ObjectSetString(0, name, OBJPROP_FONT, "Consolas");
ObjectSetString(0, name, OBJPROP_TEXT, txt);
line++;
};
g_DBPrefix = "NANDR_DB_";
g_DBX = 15;
g_DBY = 30;
g_DBDY = 18;
g_DBLine = 0;
DrawText("▌ NANDR ORB+OB EA", title, 10);
DrawText("─────────────────────────", normal);
DrawText(StringFormat("Symbol : %s TF: %s", g_Symbol, EnumToString(Period())), normal);
DrawText(StringFormat("OrbTF : M%d BarsNeeded: %d", (int)InpOrbTimeframe, g_OrbBarsNeeded), normal);
DrawText("─────────────────────────", normal);
DBLine("== NANDR ORB+OB EA ==", title, 10);
DBLine("-------------------------", normal);
DBLine(StringFormat("Symbol : %s TF: %s", g_Symbol, EnumToString(Period())), normal);
DBLine(StringFormat("OrbTF : M%d BarsNeeded: %d", (int)InpOrbTimeframe, g_OrbBarsNeeded), normal);
DBLine("-------------------------", normal);
// Sessions
for(int s = 0; s < g_SessionCount; s++)
{
SSession *sess = &g_Sessions[s];
string status = sess.orbComplete ? "ARMED" : (sess.orbBarCount > 0 ? "ACCUM" : "WAIT ");
if(sess.inBreakout) status = (sess.breakoutDir > 0 ? "BULL↑" : "BEAR↓");
color sc = sess.orbComplete ? good : normal;
string status;
if(g_Sessions[s].orbComplete)
status = "ARMED";
else if(g_Sessions[s].orbBarCount > 0)
status = "ACCUM";
else
status = "WAIT ";
if(g_Sessions[s].inBreakout)
status = (g_Sessions[s].breakoutDir > 0 ? "BULL+" : "BEAR-");
color sc = g_Sessions[s].orbComplete ? good : normal;
if(g_TradingHalted) sc = bad;
DrawText(StringFormat("%-8s H:%.2f L:%.2f [%s]",
sess.name, sess.orbHigh > 0 ? sess.orbHigh : 0,
sess.orbLow < DBL_MAX ? sess.orbLow : 0, status), sc);
DBLine(StringFormat("%-8s H:%.2f L:%.2f [%s]",
g_Sessions[s].name,
g_Sessions[s].orbHigh > 0 ? g_Sessions[s].orbHigh : 0,
g_Sessions[s].orbLow < DBL_MAX ? g_Sessions[s].orbLow : 0,
status), sc);
}
DrawText("─────────────────────────", normal);
// OB counts
DrawText(StringFormat("BullOBs: %d BearOBs: %d", g_BullOBCount, g_BearOBCount), normal);
DrawText("─────────────────────────", normal);
DBLine("-------------------------", normal);
DBLine(StringFormat("BullOBs: %d BearOBs: %d", g_BullOBCount, g_BearOBCount), normal);
DBLine("-------------------------", normal);
// Daily stats
double wr = (g_TodayWins + g_TodayLosses > 0)
? (double)g_TodayWins / (g_TodayWins + g_TodayLosses) * 100.0 : 0;
DrawText(StringFormat("Trades : %d / %d", g_TodayTrades, InpMaxTradesPerDay), normal);
DrawText(StringFormat("W/L : %d / %d WR: %.0f%%", g_TodayWins, g_TodayLosses, wr),
g_TodayWins >= g_TodayLosses ? good : normal);
DrawText(StringFormat("Today PnL: %+.2f USD", g_TodayPnL),
g_TodayPnL >= 0 ? good : bad);
DrawText(StringFormat("Equity : %.2f", AccountInfoDouble(ACCOUNT_EQUITY)), normal);
DBLine(StringFormat("Trades : %d / %d", g_TodayTrades, InpMaxTradesPerDay), normal);
DBLine(StringFormat("W/L : %d / %d WR: %.0f%%", g_TodayWins, g_TodayLosses, wr),
g_TodayWins >= g_TodayLosses ? good : normal);
DBLine(StringFormat("Today PnL: %+.2f USD", g_TodayPnL),
g_TodayPnL >= 0 ? good : bad);
DBLine(StringFormat("Equity : %.2f", AccountInfoDouble(ACCOUNT_EQUITY)), normal);
if(g_TradingHalted)
DrawText("⚠ TRADING HALTED Daily limit", bad, 10);
DBLine("! TRADING HALTED - Daily limit", bad, 10);
else if(g_SessionCount == 0)
DrawText("⚠ No sessions enabled", bad);
DBLine("! No sessions enabled", bad);
ChartRedraw(0);
}