← К каталогу
Исходный код · ID 3885

ARIN2-X

arin2-x 3.06 with sl and tp.mq4
Вы автор или правообладатель?

Сообщите нам, если считаете, что материал размещён без разрешения.

Краткий обзор

О программе

ARIN2-X — торговый советник для платформы MetaTrader 4, предназначенный для управления корзиной рыночных ордеров на одном инструменте. Советник анализирует ценовые данные и технические индикаторы для принятия решений о входе в позицию, закрытии и перераспределении объёмов. Он поддерживает автоматическое управление прибылью и дневными лимитами, а также сохраняет состояние между перезапусками терминала.

Настройки программы

НастройкаОписание
MagicNumber Магический номер — Уникальный идентификатор ордеров советника, используемый для фильтрации и управления позициями.
Profit Target % (ProfitTargetPct) Цель по прибыли в процентах — Процент от текущего баланса, при достижении плавающей прибыли по корзине советник закрывает все ордера.
Daily Profit Target % (DailyTargetPct) Дневная цель по прибыли в процентах — Процент от баланса, который советник пытается заработать за торговый день; при достижении цели торговля блокируется до следующего дня.
Получить полный код

Поиск по коду файла

#property version   "3.08"
#property strict
#property description "ATR-Distance Layering System + Auto-Netting + Trend Filters + Trend Recovery."
#property description "Includes Cooldown Persistence on Restart."
#property description " "
#property description "Risk Warning! Test this EA on Demo account first. Understand how this EA operates. Trading is risky and not suitable for every investor."

input int      MagicNumber       = 202510121;
input double   ProfitTargetPct   = 15.0; // Profit Target %
input double   DailyTargetPct    = 50.0; // Daily Profit Target %

input const double   BaseLotSize       = 0.01;
input const int      MaxSpreadPips     = 120;

input const int      EMAPeriod         = 4;       // 4MA (SMA) used for Price comparison

input const int      TREND_MA_PERIOD   = 4;       // H1 Trend Filter Period (Hardcoded)
input const double   MIN_CANDLE_BODY   = 0.5;     // Minimum Candle Body % of ATR (Hardcoded: 50%)
input const bool     ENABLE_NETTING    = true;    // Enable Auto Netting (Hardcoded: True)
input const int      NETTING_MIN_ORDERS = 20;      // Min orders to trigger netting (Hardcoded: 20)
input const double   NETTING_ATR_LIMIT = 0.002;   // Low Volatility Threshold (Hardcoded: 0.002)

int LastHistoryTotal = 0;

int logFileHandle = -1;
string lastLogDate = ""; // Track the last date for log file creation

datetime lastDailyAlertTime = 0;

datetime lastBasketCloseTime = 0;

int openOrdersCount = 0;
double openOrdersTotalLots = 0;
double openOrdersProfit = 0; // Net floating P/L
bool hasOpenOrders = false;

int    RecoveryLayer      = 1;          // Current Layer (1 = 0.01, 2 = 0.02, etc.)

datetime lastCandleTime = 0;

datetime lastPruneCandleTime = 0;

datetime lastNettingTime = 0;

datetime nextCooldownLogTime = 0;
bool    cooldownStateActive = false;

bool IsARIN2Order(int ticket)
{
   if(OrderSelect(ticket, SELECT_BY_TICKET, MODE_TRADES) == false && OrderSelect(ticket, SELECT_BY_TICKET, MODE_HISTORY) == false)
      return false;

   return(OrderMagicNumber() == MagicNumber && StringFind(OrderComment(), "ARIN2-X") >= 0);
}

int OnInit()
{
      // код доступен только после оплаты
   }

void OnDeinit(const int reason)
{

   CleanupLoggingSystem();
}

void OnTick()
{
      // код доступен только после оплаты
   }

bool CloseByTicket(int ticket)
{
   if(OrderSelect(ticket, SELECT_BY_TICKET, MODE_TRADES) == true)
   {
      double closePrice = (OrderType() == OP_BUY) ? Bid : Ask;
      bool result = OrderClose(ticket, OrderLots(), closePrice, 3, clrWhite);
      if(!result) 
      {
         Print("Failed to close order #", ticket, ". Error: ", GetLastError());
      }
      return result;
   }
   return false;
}

void MonitorCooldown()
{

   bool currentlyBlocked = (Time[0] == lastPruneCandleTime);

   int secondsLeft = (int)((Time[0] + PeriodSeconds()) - TimeCurrent());
   if(secondsLeft < 0) secondsLeft = 0;

   if(currentlyBlocked)
   {

      if(TimeCurrent() >= nextCooldownLogTime)
      {
         Print("COOLDOWN MONITOR: Profit Protection logic BLOCKED (Pruning active). Time remaining: ", secondsLeft, "s.");
         nextCooldownLogTime = TimeCurrent() + 5;
      }
      cooldownStateActive = true;
   }
   else
   {

      if(cooldownStateActive)
      {
         Print("COOLDOWN MONITOR: Profit Protection logic RESUMED. Next candle opened.");
         cooldownStateActive = false;
      }
   }
}

void CheckAutoNetting()
{
   if(Time[0] == lastNettingTime) return; // Only run once per candle

   if(openOrdersCount < NETTING_MIN_ORDERS) return; // Not enough trades to constitute a "grid trap"

   double atr = iATR(Symbol(), 0, 20, 0);
   if(atr > NETTING_ATR_LIMIT) return; // Volatility is still high, let the market run

   int buyCount = 0;
   int sellCount = 0;

   int ticketsToClose[];
   double profitsToClose[];

   for(int i = 0; i < OrdersTotal(); i++)
   {
      if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
      {
         if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber && StringFind(OrderComment(), "ARIN2-X") >= 0)
         {
            if(OrderType() == OP_BUY) buyCount++;
            else sellCount++;
         }
      }
   }

   if(buyCount == sellCount) return;

   int diff = 0;
   int typeToClose = -1; // OP_BUY or OP_SELL
   string closeTypeStr = "";

   if(buyCount > sellCount)
   {
      diff = buyCount - sellCount;
      typeToClose = OP_BUY;
      closeTypeStr = "BUY";
   }
   else
   {
      diff = sellCount - buyCount;
      typeToClose = OP_SELL;
      closeTypeStr = "SELL";
   }

   if(diff < 3) return;

   ArrayResize(ticketsToClose, 0);
   ArrayResize(profitsToClose, 0);

   for(int i = 0; i < OrdersTotal(); i++)
   {
      if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
      {
         if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber && StringFind(OrderComment(), "ARIN2-X") >= 0)
         {
            if(OrderType() == typeToClose)
            {
               int sz = ArraySize(ticketsToClose);
               ArrayResize(ticketsToClose, sz + 1);
               ArrayResize(profitsToClose, sz + 1);

               ticketsToClose[sz] = OrderTicket();
               profitsToClose[sz] = OrderProfit(); 
            }
         }
      }
   }

   for(int i = 0; i < ArraySize(ticketsToClose) - 1; i++)
   {
      for(int j = i + 1; j < ArraySize(ticketsToClose); j++)
      {
         if(profitsToClose[i] > profitsToClose[j]) // Swap if i is worse (more negative) than j
         {
            double tempProf = profitsToClose[i];
            profitsToClose[i] = profitsToClose[j];
            profitsToClose[j] = tempProf;

            int tempTicket = ticketsToClose[i];
            ticketsToClose[i] = ticketsToClose[j];
            ticketsToClose[j] = tempTicket;
         }
      }
   }

   int closeCounter = 0;
   for(int i = ArraySize(ticketsToClose) - 1; i >= 0; i--)
   {
      if(closeCounter >= diff) break;

      if(OrderSelect(ticketsToClose[i], SELECT_BY_TICKET, MODE_TRADES))
      {
         Print("AUTO-NETTING: Closing ", closeTypeStr, " #", ticketsToClose[i], " (Profit: $", profitsToClose[i], ") to balance grid.");
         WriteToLog("NETTING", "Closing " + closeTypeStr + " #" + IntegerToString(ticketsToClose[i]) + " P/L: $" + DoubleToStr(profitsToClose[i], 2));
         CloseByTicket(ticketsToClose[i]);
         closeCounter++;
      }
   }

   if(closeCounter > 0)
   {
      lastNettingTime = Time[0];
      WriteToLog("NETTING", "Basket Netted. Closed " + IntegerToString(closeCounter) + " orders. Grid is now neutral.");
   }
}

void CheckRecoveryLayers()
{
   double atr = iATR(Symbol(), 0, 20, 0);

   double sma_current = iMA(NULL, 0, EMAPeriod, 0, MODE_SMA, PRICE_CLOSE, 0);
   bool trendIsUp = (Bid > sma_current);

   double maxDistance = 0;

   if(trendIsUp)
   {

      double farthestSellPrice = 0;
      bool hasSell = false;

      for(int i = 0; i < OrdersTotal(); i++)
      {
         if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
         {
            if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
            {
               if(OrderType() == OP_SELL)
               {
                  if(!hasSell || OrderOpenPrice() > farthestSellPrice)
                  {
                     farthestSellPrice = OrderOpenPrice();
                     hasSell = true;
                  }
               }
            }
         }
      }

      if(hasSell)
      {
         maxDistance = Ask - farthestSellPrice;
      }
   }
   else
   {

      double farthestBuyPrice = 0;
      bool hasBuy = false;

      for(int i = 0; i < OrdersTotal(); i++)
      {
         if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
         {
            if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
            {
               if(OrderType() == OP_BUY)
               {
                  if(!hasBuy || OrderOpenPrice() < farthestBuyPrice)
                  {
                     farthestBuyPrice = OrderOpenPrice();
                     hasBuy = true;
                  }
               }
            }
         }
      }

      if(hasBuy)
      {
         maxDistance = farthestBuyPrice - Bid;
      }
   }

   if(maxDistance > 0 && maxDistance >= (RecoveryLayer * atr))
   {
      RecoveryLayer++;
      Print("RECOVERY LAYER INCREASED: Level ", RecoveryLayer, ". Drawdown Detected (Opposite Side). Recovery size: ", BaseLotSize * RecoveryLayer);
      WriteToLog("RECOVERY", "Layer Increased to " + IntegerToString(RecoveryLayer) + " via Drawdown Calculation.");
   }
}

void CheckTrendPruning()
{
   if(!hasOpenOrders) return;

   double open0 = iOpen(Symbol(), 0, 0);
   double close0 = iClose(Symbol(), 0, 0);
   double open1 = iOpen(Symbol(), 0, 1);
   double close1 = iClose(Symbol(), 0, 1);

   bool isBullishRun = (close0 > open0) && (close1 > open1); 
   bool isBearishRun = (close0 < open0) && (close1 < open1); 

   if(!isBullishRun && !isBearishRun) return;

   int targetTypeToClose = -1; 

   if(isBullishRun) targetTypeToClose = OP_SELL; 
   else if(isBearishRun) targetTypeToClose = OP_BUY; 

   bool pairFound = false;

   do 
   {
      pairFound = false;
      int bestBadTicket = -1;
      int bestGoodTicket = -1;
      double bestBadProfit = 0;
      double bestGoodProfit = 0;
      double maxCombinedProfit = -999999; 

      for(int i = 0; i < OrdersTotal(); i++)
      {
         if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES) == true)
         {
            if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber && StringFind(OrderComment(), "ARIN2-X") >= 0)
            {
               if(OrderType() == targetTypeToClose)
               {
                  double badProfit = OrderProfit() + OrderSwap() + OrderCommission();

                  for(int j = 0; j < OrdersTotal(); j++)
                  {
                     if(i == j) continue;
                     if(OrderSelect(j, SELECT_BY_POS, MODE_TRADES) == true)
                     {
                        if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber && StringFind(OrderComment(), "ARIN2-X") >= 0)
                        {
                           if(OrderType() != targetTypeToClose)
                           {
                              double goodProfit = OrderProfit() + OrderSwap() + OrderCommission();

                              if(goodProfit > 0)
                              {
                                 double totalProfit = goodProfit + badProfit;

                                 if(totalProfit >= 1.0)
                                 {
                                    if(totalProfit > maxCombinedProfit)
                                    {
                                       maxCombinedProfit = totalProfit;
                                       if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) 
                                       {
                                       bestBadTicket = OrderTicket();
                                       bestBadProfit = badProfit;
                                       }
                                       if(OrderSelect(j, SELECT_BY_POS, MODE_TRADES))
                                       {
                                          bestGoodTicket = OrderTicket();
                                          bestGoodProfit = goodProfit;
                                       }
                                    }
                                 }
                              }
                           }
                        }
                     }
                  }
               }
            }
         }
      }

      if(bestBadTicket != -1 && bestGoodTicket != -1)
      {
         string trendStr = isBullishRun ? "Bullish Run" : "Bearish Run";
         Print("Pruning: ", trendStr, ". Pairing Good #", bestGoodTicket, " ($", bestGoodProfit, ") with Bad #", bestBadTicket, " ($", bestBadProfit, ") -> Total: $", maxCombinedProfit);
         WriteToLog("PRUNE", trendStr + " closing pair. Profit: $" + DoubleToStr(maxCombinedProfit, 2));

         bool res1 = CloseByTicket(bestGoodTicket);
         bool res2 = CloseByTicket(bestBadTicket);

         if(res1 && res2)
         {
            pairFound = true;
            lastPruneCandleTime = Time[0]; // ACTIVATE COOLDOWN

            int remainingOrders = 0;
            for(int k=0; k<OrdersTotal(); k++) {
               if(OrderSelect(k, SELECT_BY_POS, MODE_TRADES)) {
                  if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber) remainingOrders++;
               }
            }
            if(remainingOrders == 0)
            {
                RecoveryLayer = 1;
                hasOpenOrders = false;
                Print("Basket Empty. Recovery Layer Reset to 1.");
            }
         }
         else
         {
            pairFound = false; 
         }
      }

   } while(pairFound); 
}

void CheckTrendReversal()
{
   if(!hasOpenOrders) return;

   if(Time[0] == lastPruneCandleTime) return; // CHECK COOLDOWN

   if(openOrdersProfit <= 0) return;

   double sma_current = iMA(NULL, 0, EMAPeriod, 0, MODE_SMA, PRICE_CLOSE, 0);
   double currentPrice = Bid; 

   int buyCount = 0;
   int sellCount = 0;

   for(int i = 0; i < OrdersTotal(); i++)
   {
      if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES) == true)
      {
         if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber && StringFind(OrderComment(), "ARIN2-X") >= 0)
         {
            if(Order

Показано первые 50% кода (символов: 19450)

Открыть по тарифу

Купите тариф с пакетом открытий или войдите, если тариф уже есть. Открытый файл останется в вашем кабинете навсегда.

Разовая покупка файла

На этой странице откроется полный исходный код файла вместо ознакомительного фрагмента.

Чтобы оформить заказ, введите email и перейдите к оплате.

Стоимость полного кода
1 945₽ ≈ $23.77