goldtrap_replica (1).mq5
Сообщите нам, если считаете, что материал размещён без разрешения.
Сообщить о материале
Обращение по товару «goldtrap_replica (1).mq5» отправится на рассмотрение. Укажите контакт для ответа и опишите причину.
О программе
Советник для торговли XAUUSD на MetaTrader 5, реализующий стратегию динамической сетки восстановления. Работает в режиме хеджинга: размещает пару отложенных ордеров Buy Stop и Sell Stop, при срабатывании одной стороны открывает корзину позиций в этом направлении с прогрессивным увеличением лота. Цель — восстановить убытки и выйти в прибыль по заданному таргету на корзину.
Внутри используется конечный автомат с шестью состояниями: инициализация, ожидание триггера, активная корзина на покупку, активная корзина на продажу, закрытие корзины и сброс цикла. При запуске советник восстанавливает состояние по существующим позициям и ордерам, определяет направление активной корзины и при необходимости удаляет противоположные отложенные ордера. Обновляет стоп-лосс и тейк-профит на брокерском сервере для всех позиций корзины.
Советник включает фильтр спреда, фильтр торговой сессии, дневной лимит реализованной прибыли и фильтр новостей на основе встроенного календаря MQL5. Поддерживает защиту от максимальной просадки с аварийной ликвидацией всех позиций и ордеров. Требуется счёт с режимом хеджинга и брокерская поддержка модификации позиций.
Настройки программы
| Настройка | Описание |
|---|---|
| D1 | Шаг сетки — Расстояние в цене от средней цены для размещения начальных отложенных ордеров Buy Stop и Sell Stop. |
| V1 | Начальный лот — Базовый размер лота для первой сделки в корзине. |
| N | Макс. позиций в корзине — Максимальное количество позиций в одной направленной корзине (сетка). |
| S1 | Шаг сетки 1 — Расстояние между уровнями сетки для первых P2 добавлений. |
| S2 | Шаг сетки 2 — Расстояние между уровнями сетки для добавлений после P2. |
| T1 | Целевая прибыль на лот — Требуемая прибыль в долларах на один лот для закрытия корзины. |
| E1 | Множитель лота — Коэффициент умножения объёма лота при каждом новом уровне сетки. |
| R1 (1.0=100%, 0.2=20%) (R1) | Множитель начального лота — Коэффициент для корректировки начального лота (0 — без изменений). |
| P1 | Макс. спред — Максимально допустимый спред для входа в сделку. |
| P2 | Кол-во уровней с S1 — Число первых добавлений в корзину, для которых используется шаг S1. |
| H1 | Параметр H1 — Числовой параметр, объявленный во входных настройках. |
| M1 | Магик BUY — Магический номер для ордеров и позиций на покупку. |
| M2 | Магик SELL — Магический номер для ордеров и позиций на продажу. |
| F1 | Фильтр сессии — Включает фильтр торговой сессии по времени (F1). |
| T2 | Час начала сессии — Час начала торговой сессии для фильтра F1. |
| T3 | Минута начала сессии — Минута начала торговой сессии для фильтра F1. |
| T4 | Час окончания сессии — Час окончания торговой сессии для фильтра F1. |
| T5 | Минута окончания сессии — Минута окончания торговой сессии для фильтра F1. |
| F2 | Отмена ордеров при блокировке — Отмена всех отложенных ордеров при блокировке новостями или принудительно (F2). |
| F3 | Дневной таргет — Включает контроль дневной реализованной прибыли (F3). |
| DT1 | Дневной таргет сумма — Минимальная дневная реализованная прибыль в долларах для остановки торговли. |
| F4 | Фильтр новостей — Включает фильтрацию новостей через календарь MQL5 (F4). |
| N1 (InpNewsMode) | Режим новостей — Уровень важности новостей для блокировки: только высокие, средние и высокие, или все. |
| T6 | Защита до новости (мин) — За сколько минут до события начинать блокировку входов. |
| T7 | Защита после новости (мин) — Сколько минут после события продолжать блокировку входов. |
Поиск по коду файла
#property version "2.00"
#property description "Complete XAUUSD Dynamic Recovery Grid Expert Advisor for MT5"
#property description "Features dynamic lot optimization, one-side basket recovery, state reconstruction, and strict comment tagging."
#include <Trade\Trade.mqh>
#include <Trade\PositionInfo.mqh>
#include <Trade\OrderInfo.mqh>
const string EA_COMMENT = "Developed By @manoj8901";
enum ENUM_N1_MODE
{
N0 = 0, // All importance levels
N1 = 1, // Medium and High importance
N2 = 2 // High importance only
};
input group "=== A ==="
input string InpLicenseKey = ""; // License Key (GTXX-XXXX-XXXX-XXXX)
input group "=== B ==="
input double D1 = 1.00;
input double V1 = 0.01;
input group "=== C ==="
input int N = 2000;
input double S1 = 13.0;
input double S2 = 2.60;
input double T1 = 40.00;
input double E1 = 1.68;
input double R1 = 0.0; // R1 (1.0=100%, 0.2=20%)
input double P1 = 0.50;
input int P2 = 2;
input double H1 = 0.0;
input group "=== D ==="
input ulong M1 = 123456;
input ulong M2 = 123457;
input group "=== E ==="
input bool F1 = true;
input int T2 = 1;
input int T3 = 15;
input int T4 = 22;
input int T5 = 0;
input bool F2 = false;
input group "=== F ==="
input bool F3 = false;
input double DT1 = 0.0;
input group "=== G ==="
input bool F4 = false;
input ENUM_N1_MODE InpNewsMode = N2; // N1
input int T6 = 30;
input int T7 = 30;
const ulong InpSlippage = 30;
const double InpMaxLot = 1000.00;
const bool InpUpdateBrokerTP = true;
const int InpMinimumDelayBetweenOrders = 1;
const bool InpEnableLogs = true;
const int InpNewsLookAheadDays = 14;
const bool InpCancelPendingsForNews = true;
const int InpNewsRefreshSeconds = 30;
enum ENUM_AFTER_MAX_DD
{
DD_CONTINUE_TRADING = 0, // Continue Trading
DD_STOP_TRADING = 1 // Stop Trading
};
const bool InpEnableMaxDDProtection = false;
const double InpMaxDrawdownPercent = 20.0;
const ENUM_AFTER_MAX_DD InpAfterMaxDD = DD_STOP_TRADING;
enum ENUM_EA_STATE
{
STATE_INIT, // Initializing / Reconstructing state
STATE_WAITING_FOR_TRIGGER, // Waiting for Buy Stop or Sell Stop to trigger
STATE_BUY_BASKET_ACTIVE, // BUY basket active, managing recovery grid
STATE_SELL_BASKET_ACTIVE, // SELL basket active, managing recovery grid
STATE_CLOSING_BASKET, // Profit target reached, closing all positions
STATE_RESETTING_CYCLE // Resetting cycle after full closure
};
CTrade m_trade;
CPositionInfo m_position;
COrderInfo m_order;
ENUM_EA_STATE g_state = STATE_INIT;
datetime g_last_order_time = 0;
bool g_max_dd_emergency_active = false;
bool g_trading_stopped_by_max_dd = false;
bool g_news_blocked = false;
bool g_calendar_available = true;
datetime g_last_news_scan = 0;
datetime g_next_news_time = 0;
string g_next_news_name = "No scheduled high-impact USD news";
string g_active_news_name = "";
bool IsOurMagic(const long magic)
{
return ((ulong)magic == M1 || (ulong)magic == M2);
}
void SetTradeMagic(const ulong magic)
{
m_trade.SetExpertMagicNumber(magic);
}
int OnInit()
{
// код доступен только после оплаты
}
void OnDeinit(const int reason)
{
LogMessage(StringFormat("EA Deinitialized. Reason code: %d", reason));
}
void OnTick()
{
// код доступен только после оплаты
}
void OnTradeTransaction(const MqlTradeTransaction &trans,
const MqlTradeRequest &request,
const MqlTradeResult &result)
{
if(g_trading_stopped_by_max_dd) return;
if(g_max_dd_emergency_active)
{
ProcessMaxDDEmergency();
return;
}
if(IsMaxDrawdownReached())
{
TriggerMaxDDEmergency();
ProcessMaxDDEmergency();
return;
}
if(trans.type == TRADE_TRANSACTION_ORDER_ADD ||
trans.type == TRADE_TRANSACTION_ORDER_DELETE ||
trans.type == TRADE_TRANSACTION_HISTORY_ADD)
{
ReconstructState();
}
}
void ReconstructState()
{
int buy_pos_count = 0;
int sell_pos_count = 0;
int buy_stop_count = 0;
int sell_stop_count = 0;
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
if(m_position.SelectByIndex(i))
{
if(m_position.Symbol() == _Symbol && IsOurMagic(m_position.Magic()))
{
if(m_position.PositionType() == POSITION_TYPE_BUY)
buy_pos_count++;
else if(m_position.PositionType() == POSITION_TYPE_SELL)
sell_pos_count++;
}
}
}
for(int i = OrdersTotal() - 1; i >= 0; i--)
{
if(m_order.SelectByIndex(i))
{
if(m_order.Symbol() == _Symbol && IsOurMagic(m_order.Magic()))
{
if(m_order.OrderType() == ORDER_TYPE_BUY_STOP)
buy_stop_count++;
else if(m_order.OrderType() == ORDER_TYPE_SELL_STOP)
sell_stop_count++;
}
}
}
if(buy_pos_count > 0 && sell_pos_count == 0)
{
if(sell_stop_count > 0)
{
LogMessage("BUY Basket triggered. Deleting opposite Sell Stop order.");
CancelPendingOrders(ORDER_TYPE_SELL_STOP);
}
if(g_state != STATE_CLOSING_BASKET)
g_state = STATE_BUY_BASKET_ACTIVE;
UpdateBrokerBasketTP(POSITION_TYPE_BUY);
}
else if(sell_pos_count > 0 && buy_pos_count == 0)
{
if(buy_stop_count > 0)
{
LogMessage("SELL Basket triggered. Deleting opposite Buy Stop order.");
CancelPendingOrders(ORDER_TYPE_BUY_STOP);
}
if(g_state != STATE_CLOSING_BASKET)
g_state = STATE_SELL_BASKET_ACTIVE;
UpdateBrokerBasketTP(POSITION_TYPE_SELL);
}
else if(buy_pos_count == 0 && sell_pos_count == 0)
{
if(buy_stop_count > 0 || sell_stop_count > 0)
{
g_state = STATE_WAITING_FOR_TRIGGER;
}
else
{
g_state = STATE_RESETTING_CYCLE;
}
}
else if(buy_pos_count > 0 && sell_pos_count > 0)
{
Print("[EA WARNING] Hedging overlap detected (both BUY and SELL positions exist). Grid entries paused for safety.");
}
}
void ProcessWaitingForTriggerState()
{
int buy_stop_count = 0;
int sell_stop_count = 0;
for(int i = OrdersTotal() - 1; i >= 0; i--)
{
if(m_order.SelectByIndex(i))
{
if(m_order.Symbol() == _Symbol && IsOurMagic(m_order.Magic()))
{
if(m_order.OrderType() == ORDER_TYPE_BUY_STOP) buy_stop_count++;
if(m_order.OrderType() == ORDER_TYPE_SELL_STOP) sell_stop_count++;
}
}
}
bool news_blocked = IsNewsWindowBlocked();
bool entry_allowed = CanStartNewCycle();
if(!entry_allowed)
{
bool must_cancel_for_news = (news_blocked && InpCancelPendingsForNews);
if((must_cancel_for_news || F2) && GetPositionCount() == 0 && (buy_stop_count > 0 || sell_stop_count > 0))
CancelAllPendingOrders();
return;
}
if(buy_stop_count == 1 && sell_stop_count == 1)
return;
if(GetPositionCount() == 0)
{
PlaceInitialPendingOrders();
}
}
void PlaceInitialPendingOrders()
{
if(!CanStartNewCycle() || IsSpreadExceeded()) return;
CancelAllPendingOrders();
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
double ref_price = (ask + bid) / 2.0;
double buy_stop_price = NormalizePrice(ref_price + D1);
double sell_stop_price = NormalizePrice(ref_price - D1);
double initial_lot = GetConfiguredInitialLot();
double k_profit = GetProfitPerUnitPerLot();
if(k_profit <= 0.0) k_profit = 100.0;
double target_dist = T1 / k_profit;
double buy_tp = InpUpdateBrokerTP ? NormalizePrice(buy_stop_price + target_dist) : 0.0;
double sell_tp = InpUpdateBrokerTP ? NormalizePrice(sell_stop_price - target_dist) : 0.0;
LogMessage(StringFormat("Starting New Cycle. Ref Price: %.2f | Buy Stop: %.2f (TP: %.2f) | Sell Stop: %.2f (TP: %.2f) | Comment: %s",
ref_price, buy_stop_price, buy_tp, sell_stop_price, sell_tp, EA_COMMENT));
SetTradeMagic(M1);
if(!m_trade.BuyStop(initial_lot, buy_stop_price, _Symbol, 0.0, buy_tp, ORDER_TIME_GTC, 0, EA_COMMENT))
{
PrintFormat("[EA ERROR] Failed to place Buy Stop order at %.2f. Error: %d", buy_stop_price, GetLastError());
return;
}
SetTradeMagic(M2);
if(!m_trade.SellStop(initial_lot, sell_stop_price, _Symbol, 0.0, sell_tp, ORDER_TIME_GTC, 0, EA_COMMENT))
{
PrintFormat("[EA ERROR] Failed to place Sell Stop order at %.2f. Error: %d", sell_stop_price, GetLastError());
return;
}
g_state = STATE_WAITING_FOR_TRIGGER;
}
void ProcessBuyBasketState()
{
if(CheckBasketProfitTarget(POSITION_TYPE_BUY))
{
g_state = STATE_CLOSING_BASKET;
CloseActiveBasket();
return;
}
int buy_pos_count = GetPositionCount(POSITION_TYPE_BUY);
if(buy_pos_count < N)
{
double lowest_buy_price = GetLowestEntryPrice(POSITION_TYPE_BUY);
if(lowest_buy_price > 0.0)
{
double next_grid_price = NormalizePrice(lowest_buy_price - GetGridDistancePrice(buy_pos_count));
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
if(ask <= next_grid_price)
{
if(!IsSpreadExceeded() && (TimeCurrent() - g_last_order_time >= InpMinimumDelayBetweenOrders))
{
double next_lot = CalculateNextGridLot(POSITION_TYPE_BUY, next_grid_price);
if(next_lot > 0.0)
{
SetTradeMagic(M1);
if(m_trade.Buy(next_lot, _Symbol, 0.0, 0.0, 0.0, EA_COMMENT))
{
g_last_order_time = TimeCurrent();
UpdateBrokerBasketTP(POSITION_TYPE_BUY);
}
else
{
PrintFormat("[EA ERROR] Failed to open BUY grid trade. Error: %d", GetLastError());
}
}
else
{
Print("[EA WARNING] Next lot calculation returned 0.0 (MaxLot reached or invalid lot). Grid trade skipped.");
}
}
}
}
}
UpdateBrokerBasketTP(POSITION_TYPE_BUY);
}
void ProcessSellBasketState()
{
if(CheckBasketProfitTarget(POSITION_TYPE_SELL))
{
g_state = STATE_CLOSING_BASKET;
CloseActiveBasket();
return;
}
int sell_pos_count = GetPositionCount(POSITION_TYPE_SELL);
if(sell_pos_count < N)
{
double highest_sell_price = GetHighestEntryPrice(POSITION_TYPE_SELL);
if(highest_sell_price > 0.0)
{
double next_grid_price = NormalizePrice(highest_sell_price + GetGridDistancePrice(sell_pos_count));
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
if(bid >= next_grid_price)
{
if(!IsSpreadExceeded() && (TimeCurrent() - g_last_order_time >= InpMinimumDelayBetweenOrders))
{
double next_lot = CalculateNextGridLot(POSITION_TYPE_SELL, next_grid_price);
if(next_lot > 0.0)
{
SetTradeMagic(M2);
if(m_trade.Sell(next_lot, _Symbol, 0.0, 0.0, 0.0, EA_COMMENT))
{
g_last_order_time = TimeCurrent();
UpdateBrokerBasketTP(POSITION_TYPE_SELL);
}
else
{
PrintFormat("[EA ERROR] Failed to open SELL grid trade. Error: %d", GetLastError());
}
}
else
{
Print("[EA WARNING] Next lot calculation returned 0.0 (MaxLot reached or invalid lot). Grid trade skipped.");
}
}
}
}
}
UpdateBrokerBasketTP(POSITION_TYPE_SELL);
}
double CalculateNextGridLot(ENUM_POSITION_TYPE type, double grid_entry_price)
{
double last_lot = 0.0;
datetime latest_time = 0;
int pos_count = 0;
double total_basket_lots = 0.0;
double current_floating_profit = 0.0;
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
if(m_position.SelectByIndex(i))
{
if(m_position.Symbol() == _Symbol && IsOurMagic(m_position.Magic()) &&
m_position.PositionType() == type)
{
pos_count++;
double vol = m_position.Volume();
total_basket_lots += vol;
current_floating_profit += m_position.Profit() + m_position.Swap();
datetime pos_time = m_position.Time();
if(pos_time >= latest_time)
{
latest_time = pos_time;
last_lot = vol;
}
}
}
}
if(last_lot <= 0.0)
return GetConfiguredInitialLot();
double raw_next_lot = last_lot * E1;
double normalized_next_lot = NormalizeVolume(raw_next_lot);
double max_broker_vol = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);
if(normalized_next_lot > InpMaxLot || normalized_next_lot > max_broker_vol)
{
PrintFormat("[EA WARNING] Calculated lot (%.2f) exceeds MaxLot limit (%.2f). Grid trade blocked.",
normalized_next_lot, InpMaxLot);
return 0.0;
}
if(InpEnableLogs)
{
double basket_target_profit = (total_basket_lots + normalized_next_lot) * T1;
PrintFormat("---------------- GRID TRADE PROGRESSION (#%d) ----------------", pos_count + 1);
PrintFormat("Previous Lot: %.2f | Lot Multiplier: %.2f", last_lot, E1);
PrintFormat("Raw Next Lot: %.4f | Normalized Lot: %.2f", raw_next_lot, normalized_next_lot);
PrintFormat("Grid Entry: %.2f | Direction: %s", grid_entry_price, EnumToString(type));
PrintFormat("Total Basket Lots (After): %.2f | Basket Positions (After): %d",
total_basket_lots + normalized_next_lot, pos_count + 1);
PrintFormat("Current Floating Profit: $%.2f | Basket Target Profit: $%.2f",
current_floating_profit, basket_target_profit);
PrintFormat("---------------------------------------------------------------");
}
return normalized_next_lot;
}
double CalculateTheoreticalTPPrice(ENUM_POSITION_TYPE type, double new_entry_price, double candidate_lot, double k_profit)
{
double sum_volume_price = candidate_lot * new_entry_price;
double total_volume = candidate_lot;
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
if(m_position.SelectByIndex(i))
{
if(m_position.Symbol() == _Symbol && IsOurMagic(m_position.Magic()) &&
m_position.PositionType() == type)
{
sum_volume_price += m_position.Volume() * m_position.PriceOpenПоказано первые 50% кода (символов: 25221)
Открыть по тарифу
Купите тариф с пакетом открытий или войдите, если тариф уже есть. Открытый файл останется в вашем кабинете навсегда.
Разовая покупка файла
На этой странице откроется полный исходный код файла вместо ознакомительного фрагмента.
Зачем нужен email? После подтверждения оплаты файл сохранится в кабинете на этот email. Если аккаунта ещё нет, мы создадим его и пришлём ссылку для задания пароля. Если аккаунт уже есть, покупка добавится в него. Укажите адрес, к которому у вас есть доступ.
Чтобы оформить заказ, введите email и перейдите к оплате.