NAIF APEX ALGO

Expert Advisor type
NAIF APEX ALGO
Type
EA
Platform
Not specified
Version
Not specified
Category
Expert Advisor type
Date
10/18/2026
Pricing
100 Coins

Description

//+------------------------------------------------------------------+
//|  NAIF_Gold_Pro_Lite.mq5 - NAIF APEX ALGO (@najran2015)            |
//|  Two trend-following engines in one light file:                   |
//|   1) SWING : breakouts of multi-day H4 highs/lows (4 slots),      |
//|              SL % of price, TP x R, trailing, max 7 days          |
//|   2) ASIA  : night range breakout at London open (1 per day)      |
//|  Same logic as InpSwOn + InpNDaily in The_Gold_Reaper_v4.3_NAIF.  |
//+------------------------------------------------------------------+
#property copyright "NAIF APEX ALGO"
#property version   "1.00"
#include <Trade/Trade.mqh>

input group "--- Lot ---"
input double InpSwLotPer1000 = 0.005;  // SWING lot per 1000 of balance, EACH slot (0.005 -> 20000 = 0.10)
input double InpAsLotPer1000 = 0.005;  // ASIA lot per 1000 of balance (0.005 -> 20000 = 0.10)
input double InpMaxLot       = 1.0;    // max lot per order

input group "--- SWING engine ---"
input bool   InpSwOn     = true;       // SWING engine on
input string InpSwSlots  = "30,1.0,4.0,0.3,0.6;60,1.0,4.0,0.3,0.6;100,1.5,2.0,0.6,0.3;30,1.0,2.0,0.3,0.3"; // N H4 bars, SL % of price, TP x R, trail start R, trail dist R
input int    InpSwMaxDays = 7;         // close a swing trade after N days

input group "--- ASIA engine (server time, Exness = GMT) ---"
input bool   InpAsOn       = true;     // ASIA engine on
input int    InpAsStartH   = 0;        // range start hour
input int    InpAsEndH     = 8;        // range end hour = orders placed
input int    InpAsCloseH   = 20;       // close trades / cancel orders hour
input double InpAsMinAtr   = 0.2;      // skip day if range < x * ATR(D1)
input double InpAsMaxAtr   = 9;        // skip day if range > x * ATR(D1)
input double InpAsBuf      = 2;        // entry buffer (x spread)
input double InpAsTpR      = 2.0;      // TP = R multiple

input long   InpMagicBase  = 778000;   // magic: ASIA = base, SWING slots = base+1..base+8

#define SWMAX 8
CTrade   trade;
int      gSwN = 0;
int      gSwBars[SWMAX];
double   gSwSl[SWMAX], gSwTp[SWMAX], gSwTs[SWMAX], gSwTd[SWMAX], gSwPk[SWMAX];
datetime gSwBar[SWMAX];
ulong    gSwTk[SWMAX];
int      hAtrD1 = INVALID_HANDLE;
datetime gAsDay = 0; bool gAsValid = false, gAsPlaced = false; double gAsHi = 0, gAsLo = 0;
bool     gTester = false, gVisual = false;
uint     gLastComment = 0;

double Bid() { return SymbolInfoDouble(_Symbol, SYMBOL_BID); }
double Ask() { return SymbolInfoDouble(_Symbol, SYMBOL_ASK); }
long   SwMagic(int i) { return InpMagicBase + 1 + i; }

double NormLot(double lot)
{
   double st = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP), mn = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN), mx = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);
   if(st <= 0) st = 0.01;
   lot = MathFloor(lot / st + 1e-9) * st;
   lot = MathMax(mn, MathMin(lot, MathMin(mx, InpMaxLot)));
   int d = (int)MathMax(0, MathRound(-MathLog10(st)));
   return NormalizeDouble(lot, d);
}

ulong FindPos(long mg)
{
   for(int i = PositionsTotal() - 1; i >= 0; i--)
   {
      ulong t = PositionGetTicket(i);
      if(t != 0 && PositionGetInteger(POSITION_MAGIC) == mg && PositionGetString(POSITION_SYMBOL) == _Symbol) return t;
   }
   return 0;
}

bool HasOrders(long mg)
{
   for(int i = OrdersTotal() - 1; i >= 0; i--)
   {
      ulong t = OrderGetTicket(i);
      if(t != 0 && OrderGetInteger(ORDER_MAGIC) == mg && OrderGetString(ORDER_SYMBOL) == _Symbol) return true;
   }
   return false;
}

void DelOrders(long mg)
{
   trade.SetExpertMagicNumber(mg);
   for(int i = OrdersTotal() - 1; i >= 0; i--)
   {
      ulong t = OrderGetTicket(i);
      if(t != 0 && OrderGetInteger(ORDER_MAGIC) == mg && OrderGetString(ORDER_SYMBOL) == _Symbol) trade.OrderDelete(t);
   }
}

void ParseSlots()
{
   gSwN = 0;
   string slots[]; int ns = StringSplit(InpSwSlots, ';', slots);
   for(int i = 0; i < ns && gSwN < SWMAX; i++)
   {
      string p[]; StringTrimLeft(slots[i]); StringTrimRight(slots[i]);
      if(StringSplit(slots[i], ',', p) < 5) continue;
      gSwBars[gSwN] = (int)StringToInteger(p[0]); gSwSl[gSwN] = StringToDouble(p[1]); gSwTp[gSwN] = StringToDouble(p[2]);
      gSwTs[gSwN] = StringToDouble(p[3]); gSwTd[gSwN] = StringToDouble(p[4]);
      if(gSwBars[gSwN] < 2 || gSwSl[gSwN] <= 0) continue;
      gSwBar[gSwN] = 0; gSwTk[gSwN] = 0; gSwPk[gSwN] = 0; gSwN++;
   }
   Print("SWING: ", gSwN, " slots loaded");
}

//------------------------------------------------------------------ SWING engine
void Swing(const MqlDateTime &dt)
{
   bool weekend = (dt.day_of_week == 0 || dt.day_of_week == 6);
   datetime h4 = iTime(_Symbol, PERIOD_H4, 0);
   double stopLvl = (double)SymbolInfoInteger(_Symbol, SYMBOL_TRADE_STOPS_LEVEL) * _Point;
   for(int i = 0; i < gSwN; i++)
   {
      long mg = SwMagic(i);
      trade.SetExpertMagicNumber(mg);
      ulong pt = FindPos(mg);
      if(pt != 0)
      {
         if(HasOrders(mg)) DelOrders(mg);                   // OCO
         if(!PositionSelectByTicket(pt)) continue;
         if(gSwTk[i] != pt) { gSwTk[i] = pt; gSwPk[i] = 0; }
         double op = PositionGetDouble(POSITION_PRICE_OPEN), sl = PositionGetDouble(POSITION_SL), tp = PositionGetDouble(POSITION_TP);
         bool isBuy = ((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY);
         if(InpSwMaxDays > 0 && TimeCurrent() - (datetime)PositionGetInteger(POSITION_TIME) >= InpSwMaxDays * 86400) { trade.PositionClose(pt); continue; }
         double R = op * gSwSl[i] / 100.0;
         double fav = isBuy ? Bid() - op : op - Ask();
         if(fav > gSwPk[i]) gSwPk[i] = fav;
         if(gSwTs[i] > 0 && R > 0 && gSwPk[i] >= gSwTs[i] * R)
         {
            double nsl = NormalizeDouble(isBuy ? op + gSwPk[i] - gSwTd[i] * R : op - gSwPk[i] + gSwTd[i] * R, _Digits);
            bool better = isBuy ? (nsl > sl + _Point) : (sl <= 0 || nsl < sl - _Point);
            bool valid  = isBuy ? (nsl < Bid() - stopLvl) : (nsl > Ask() + stopLvl);
            if(better && valid) trade.PositionModify(pt, nsl, tp);
         }
         continue;
      }
      if(weekend) { if(HasOrders(mg)) DelOrders(mg); continue; }
      bool has = HasOrders(mg);
      if(has && gSwBar[i] == h4) continue;
      if(has) DelOrders(mg);                                  // new H4 candle -> refresh levels
      if(!gTester && (!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED) || !MQLInfoInteger(MQL_TRADE_ALLOWED))) continue;
      int ih = iHighest(_Symbol, PERIOD_H4, MODE_HIGH, gSwBars[i], 1), il = iLowest(_Symbol, PERIOD_H4, MODE_LOW, gSwBars[i], 1);
      if(ih < 0 || il < 0) continue;
      double hi = iHigh(_Symbol, PERIOD_H4, ih), lo = iLow(_Symbol, PERIOD_H4, il);
      gSwBar[i] = h4;
      double lot = NormLot(AccountInfoDouble(ACCOUNT_BALANCE) / 1000.0 * InpSwLotPer1000);
      string cm = "SWING" + IntegerToString(i + 1);
      double Rb = hi * gSwSl[i] / 100.0, Rs = lo * gSwSl[i] / 100.0;
      trade.SetExpertMagicNumber(mg);
      if(hi > Ask() + stopLvl)
         trade.BuyStop(lot, NormalizeDouble(hi, _Digits), _Symbol, NormalizeDouble(hi - Rb, _Digits), NormalizeDouble(hi + Rb * gSwTp[i], _Digits), ORDER_TIME_GTC, 0, cm);
      if(lo < Bid() - stopLvl)
         trade.SellStop(lot, NormalizeDouble(lo, _Digits), _Symbol, NormalizeDouble(lo + Rs, _Digits), NormalizeDouble(lo - Rs * gSwTp[i], _Digits), ORDER_TIME_GTC, 0, cm);
   }
}

//------------------------------------------------------------------ ASIA engine
void Asia(const MqlDateTime &dt)
{
   long mg = InpMagicBase;
   trade.SetExpertMagicNumber(mg);
   datetime today = TimeCurrent() - (dt.hour * 3600 + dt.min * 60 + dt.sec);
   ulong pt = FindPos(mg);
   if(dt.hour >= InpAsCloseH)
   {
      if(HasOrders(mg)) DelOrders(mg);
      if(pt != 0) { trade.SetExpertMagicNumber(mg); trade.PositionClose(pt, 100); }
      return;
   }
   if(pt != 0 && HasOrders(mg)) DelOrders(mg);                // OCO
   if(dt.day_of_week == 0 || dt.day_of_week == 6 || dt.hour < InpAsEndH) return;
   if(gAsDay != today)
   {
      gAsDay = today; gAsValid = false; gAsPlaced = false;
      MqlRates r[];
      int n = CopyRates(_Symbol, PERIOD_M5, today + InpAsStartH * 3600, today + InpAsEndH * 3600 - 1, r);
      if(n < 12) return;
      double hi = r[0].high, lo = r[0].low;
      for(int i = 1; i < n; i++) { hi = MathMax(hi, r[i].high); lo = MathMin(lo, r[i].low); }
      double a[], atrD = 0;
      if(hAtrD1 != INVALID_HANDLE && CopyBuffer(hAtrD1, 0, 1, 1, a) == 1) atrD = a[0];
      if(atrD > 0 && (hi - lo < atrD * InpAsMinAtr || hi - lo > atrD * InpAsMaxAtr)) return;
      gAsHi = hi; gAsLo = lo; gAsValid = true;
   }
   if(!gAsValid || gAsPlaced || pt != 0 || HasOrders(mg)) return;
   if(!gTester && (!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED) || !MQLInfoInteger(MQL_TRADE_ALLOWED))) return;
   gAsPlaced = true;
   double buf = InpAsBuf * (Ask() - Bid());
   double stopLvl = (double)SymbolInfoInteger(_Symbol, SYMBOL_TRADE_STOPS_LEVEL) * _Point;
   double lot = NormLot(AccountInfoDouble(ACCOUNT_BALANCE) / 1000.0 * InpAsLotPer1000);
   double buyP = NormalizeDouble(gAsHi + buf, _Digits), buySL = NormalizeDouble(gAsLo - buf, _Digits);
   double sellP = NormalizeDouble(gAsLo - buf, _Digits), sellSL = NormalizeDouble(gAsHi + buf, _Digits);
   double R = buyP - buySL;
   if(R <= 0) return;
   trade.SetExpertMagicNumber(mg);
   if(buyP > Ask() + stopLvl)  trade.BuyStop(lot, buyP, _Symbol, buySL, NormalizeDouble(buyP + R * InpAsTpR, _Digits), ORDER_TIME_GTC, 0, "ASIA_BUY");
   if(sellP < Bid() - stopLvl) trade.SellStop(lot, sellP, _Symbol, sellSL, NormalizeDouble(sellP - R * InpAsTpR, _Digits), ORDER_TIME_GTC, 0, "ASIA_SELL");
}

void Status()
{
   if(gTester && !gVisual) return;
   uint now = GetTickCount();
   if(now - gLastComment < 1000) return;
   gLastComment = now;
   int sp = 0, so = 0;
   for(int i = 0; i < gSwN; i++) { if(FindPos(SwMagic(i)) != 0) sp++; if(HasOrders(SwMagic(i))) so++; }
   Comment("NAIF Gold Pro Lite\n",
           "SWING: ", sp, " trades | ", so, " slots waiting\n",
           "ASIA : ", (FindPos(InpMagicBase) != 0 ? "trade running" : (HasOrders(InpMagicBase) ? "orders waiting" : "waiting for " + IntegerToString(InpAsEndH) + ":00")),
           "  range ", DoubleToString(gAsLo, _Digits), " - ", DoubleToString(gAsHi, _Digits),
           (!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED) ? "\nALGO TRADING OFF" : ""));
}

int OnInit()
{
   hAtrD1 = iATR(_Symbol, PERIOD_D1, 14);
   trade.SetDeviationInPoints(100);
   trade.SetTypeFillingBySymbol(_Symbol);
   trade.LogLevel(LOG_LEVEL_ERRORS);
   gTester = (bool)MQLInfoInteger(MQL_TESTER);
   gVisual = (bool)MQLInfoInteger(MQL_VISUAL_MODE);
   ParseSlots();
   return INIT_SUCCEEDED;
}

void OnDeinit(const int reason)
{
   if(hAtrD1 != INVALID_HANDLE) IndicatorRelease(hAtrD1);
   Comment("");
}

void OnTick()
{
   MqlDateTime dt; TimeToStruct(TimeCurrent(), dt);
   if(InpSwOn) Swing(dt);
   if(InpAsOn) Asia(dt);
   Status();
}
//+------------------------------------------------------------------+

Tags

Expert Advisor type
Reviews

to write a review

No reviews yet. Be the first to review!
100 Coins
Instant download
6 months support
Free updates

to purchase

More by naifhouf_4805