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? После подтверждения оплаты файл сохранится в кабинете на этот email. Если аккаунта ещё нет, мы создадим его и пришлём ссылку для задания пароля. Если аккаунт уже есть, покупка добавится в него. Укажите адрес, к которому у вас есть доступ.
Чтобы оформить заказ, введите email и перейдите к оплате.