XMC EA 1.02 d_Grid_v1
Похожие материалы по тегам
Сообщите нам, если считаете, что материал размещён без разрешения.
Сообщить о материале
Обращение по товару «xmc ea 1.02 d_grid_v1.mq5» отправится на рассмотрение. Укажите контакт для ответа и опишите причину.
О программе
XMC EA 1.02 d_Grid_v1 — торговый советник для MetaTrader 5, реализующий сеточную торговлю в направлении тренда с циклами фиксации прибыли по корзине. Советник работает на символе текущего графика и открывает сетку из лимитов (слоёв) в выбранном направлении; при достижении целевого плавающего дохода вся корзина закрывается, после чего запускается пауза перед повторным входом.
Система включает комплекс фильтров: проверку тренда на старшем таймфрейме (EMA), определение флэт-режима (Choppiness), фильтр истощения тренда по RSI, новостной фильтр (NFP и CSV-события), а также временные ограничения по сессии, дням недели и окну ролловера. Фильтр спреда блокирует вход при чрезмерно широком спреде.
Шаг сетки может адаптироваться к волатильности через ATR или использоваться фиксированный в пунктах. Управление лотами предусматривает множитель на каждый уровень сетки. Встроен trailing-стоп как резервный механизм выхода. Советник требует хеджинговый счёт и не допускает одновременной работы покупательской и продавческой корзин.
Встроена система телеметрии с логированием в CSV-файлы (heartbeat, diagnostics, baskets, trades) для детального анализа торговой активности.
Настройки программы
| Настройка | Описание |
|---|---|
| TradeCooldown | Минимальное количество секунд между открытием новых лиментов (слоёв) внутри работающей корзины. |
| Lookback | Период (в барах) для расчёта импульса ценового изменения (ROC), используемого в телеметрии и диагностике. |
| basket_tp_amount | Размер плавающего дохода (в валюте счёта), при достижении которого вся корзина закрывается и запускается цикл реэнтри. |
| reentry_cooldown | Количество секунд ожидания после закрытия корзины перед открытием новой. |
| use_exhaustion_filter | Включает фильтр истощения тренда по RSI: входы в перегретую сторону блокируются. |
| exhaustion_rsi_period | Период расчёта RSI для фильтра истощения тренда. |
| exhaustion_buy_level | Порог RSI, при достижении которого входы в направлении BUY блокируются (истощение тренда). |
| exhaustion_sell_level | Порог RSI, при достижении которого входы в направлении SELL блокируются (истощение тренда). |
| use_news_filter | Главный переключатель новостного фильтра: блокирует входы вокруг новостных событий. |
| news_buffer_min | Количество минут до и после новостного события, в течение которых входы блокируются. |
| news_auto_nfp | Автоматическая блокировка входов в первую пятницу месяца в момент публикации данных NFP. |
| nfp_hour_gmt | Час публикации NFP по GMT, используемый для автоматической блокировки входов. |
| nfp_minute_gmt | Минута публикации NFP по GMT, используемая для автоматической блокировки входов. |
| news_use_csv | Включает чтение дат новостных событий из CSV-файла (FOMC/CPI) в дополнение к автоматическому NFP-фильтру. |
| news_csv_name | Имя CSV-файла в MQL5\Files для загрузки дат дополнительных новостных событий (FOMC, CPI и др.). |
| use_time_filter | Включает временной фильтр: открытие новых корзин ограничено по дням недели и часам сессии. |
| trade_sunday | Включает торговлю в воскресенье (серверный день). |
| trade_monday | Включает торговлю в понедельник (серверный день). |
| trade_tuesday | Включает торговлю во вторник (серверный день). |
| trade_wednesday | Включает торговлю в среду (серверный день). |
| trade_thursday | Включает торговлю в четверг (серверный день). |
| trade_friday | Включает торговлю в пятницу (серверный день). |
| session_start_hour | Начальный серверный час (включительно), с которого разрешено открытие новых корзин. При start > end окно переходит через полночь. |
| session_end_hour | Конечный серверный час (включительно), до которого разрешено открытие новых корзин. При start > end окно переходит через полночь. |
| friday_no_new_hour | Серверный час, начиная с которого в пятницу не разрешается открытие новых корзин. |
| skip_rollover | Включает блокировку всех входов в окно ролловера. |
| rollover_start_hour | Начальный серверный час (с учётом перехода через полночь) окна ролловера, в которое блокируются все входы. |
| rollover_end_hour | Конечный серверный час (включительно) окна ролловера, в которое блокируются все входы. |
| use_spread_filter | Включает фильтр спреда: входы блокируются при превышении максимально допустимого спреда. |
| max_spread_points | Максимально допустимый спред в пунктах, при превышении которого входы блокируются. |
| use_htf_filter | Включает фильтр старшего таймфрейма: EMA на HTF должна совпадать с направлением корзины. |
| htf_tf | Старший таймфрейм для фильтра тренда: EMA на этом таймфрейме должна совпадать с направлением текущей корзины. |
| use_chop_filter | Включает фильтр флэт-режима (Choppiness): при превышении порога все входы блокируются. |
| chop_period | Период расчёта индекса Choppiness для определения режима рынка (тренд/флэт). |
| chop_max | Пороговое значение индекса Choppiness, выше которого рынок считается флэтовым и входы блокируются. |
| max_layers | Максимальное количество слоёв (лиментов) в одной корзине. При достижении лимита система переходит в состояние LOCKDOWN. |
| ema_fast_period | Период быстрой EMA для определения направления тренда на текущем таймфрейме. |
| ema_slow_period | Период медленной EMA для определения направления тренда на текущем таймфрейме. |
| adx_period | Период расчёта индекса ADX для оценки силы тренда. |
| adx_trend_strength | Пороговое значение ADX, выше которого считается, что тренд достаточно силён для перехода в состояние TRENД. |
| use_atr_distance | Включает адаптивный шаг сетки на основе ATR вместо фиксированного значения в пунктах. |
| atr_period | Период расчёта индикатора ATR для определения волатильности и шага сетки. |
| atr_smoothing | Период сглаживания ATR, используемого для определения средней волатильности и состояния системы. |
| atr_multiplier | Множитель ATR, определяющий шаг сетки как произведение ATR на это значение (при включённой адаптации по ATR). |
| fallback_distance_pts | Шаг сетки в пунктах, используемый как резервный при недоступности ATR. |
| max_volatility_factor | Множитель волатильности: если текущий ATR превышает средний ATR на это значение, система переходит в состояние LOCKDOWN. |
| fixed_lot | Базовый размер лота для первого слоя сетки. |
| lot_multiplier | Множитель увеличения лота на каждый следующий уровень сетки (1.0 означает постоянный размер лота). |
| trail_start_amount | Размер плавающего дохода корзины, при достижении которого активируется trailing-стоп. |
| trail_dist_amount | Величина отката от пика прибыли, при достижении которой корзина закрывается (trailing-стоп). |
| initial_magic | Магический номер для идентификации позиций, открытых данным советником. |
| trade_comment | Текстовый комментарий, добавляемый к каждой открытой позиции для идентификации. |
Поиск по коду файла
#property version "1.02"
#property description "XMC EA 1.02 d_Grid_v1: trend-direction grid with basket TP cycles."
#property description "Filters: HTF trend, Choppiness regime, RSI exhaustion, news (NFP/CSV),"
#property description "session/day/Friday-cutoff/rollover time windows, spread."
#property description "No hedging: a buy and sell basket never run at the same time."
#property description "REQUIRES a HEDGING account (multiple positions per symbol)."
#property description "Modded by Prof. Morris"
#include <Trade\Trade.mqh>
CTrade trade;
input group "=== ENTRY RULES ==="
input int TradeCooldown = 30; // min seconds between opening layers
input int Lookback = 60; // ROC lookback (momentum telemetry)
input group "=== BASKET TP CYCLE ==="
input double basket_tp_amount = 15.0; // close whole basket at this floating profit (account currency)
input int reentry_cooldown = 300; // seconds to wait after basket close before re-entering
input group "=== TREND EXHAUSTION FILTER ==="
input bool use_exhaustion_filter = true; // block entries when trend is exhausted (RSI)
input int exhaustion_rsi_period = 14;
input double exhaustion_buy_level = 70.0; // block BUY entries when RSI >= this
input double exhaustion_sell_level = 30.0; // block SELL entries when RSI <= this
input group "=== NEWS FILTER (pause new layers around events) ==="
input bool use_news_filter = true; // master switch
input int news_buffer_min = 30; // minutes before/after event to block entries
input bool news_auto_nfp = true; // auto-block first Friday of month (NFP)
input int nfp_hour_gmt = 13; // NFP release hour (GMT) - 13:30 GMT = 8:30 ET
input int nfp_minute_gmt = 30;
input int news_server_gmt_offset = 2; // broker server hours ahead of GMT (+2 winter / +3 summer)
input bool news_use_csv = true; // also read MQL5\Files\news_events.csv (FOMC/CPI dates)
input string news_csv_name = "news_events.csv";
input group "=== TIME FILTER ==="
input bool use_time_filter = true;
input bool trade_sunday = false; // day toggles (server days)
input bool trade_monday = true;
input bool trade_tuesday = true;
input bool trade_wednesday = true;
input bool trade_thursday = true;
input bool trade_friday = true;
input int session_start_hour = 0; // server hour: new baskets allowed from (inclusive)
input int session_end_hour = 23; // server hour: until (inclusive; wraps if start > end)
input int friday_no_new_hour = 20; // on Friday: no NEW baskets from this server hour on
input bool skip_rollover = true; // block ALL new entries in rollover window
input int rollover_start_hour = 23; // window start (server hour, wraps midnight)
input int rollover_end_hour = 0; // window end (server hour, inclusive)
input group "=== SPREAD FILTER ==="
input bool use_spread_filter = true;
input int max_spread_points = 120; // block new entries above this spread (points)
input group "=== TREND FILTERS ==="
input bool use_htf_filter = true; // Filter 1: higher-TF EMA trend must agree
input ENUM_TIMEFRAMES htf_tf = PERIOD_H4;
input bool use_chop_filter = true; // Filter 2: block entries in ranging markets
input int chop_period = 14;
input double chop_max = 61.8;
input group "=== GRID ENGINE ==="
input int max_layers = 89;
input int ema_fast_period = 3; // trend direction: fast EMA
input int ema_slow_period = 20; // trend direction: slow EMA
input int adx_period = 10;
input int adx_trend_strength = 20;
input bool use_atr_distance = true; // grid step adapts to ATR
input int atr_period = 14;
input int atr_smoothing = 20;
input double atr_multiplier = 0.5; // grid step = ATR * this
input double fallback_distance_pts = 90.0; // grid step if ATR unavailable
input double max_volatility_factor = 2.5;
input group "=== LOT SIZING ==="
input double fixed_lot = 0.01;
input double lot_multiplier = 1.3; // lot growth per grid level (1.0 = flat lots)
input group "=== TRAILING BACKSTOP ==="
input double trail_start_amount = 50.0; // trailing exit arms at this basket profit
input double trail_dist_amount = 10.0; // giveback from peak that closes the basket
input group "=== IDENTIFICATION ==="
input long initial_magic = 202609011;
input string trade_comment = "XMC_Grid_v1";
string TradeSymbol = "";
datetime g_last_trade_time = 0;
datetime g_last_basket_close_time = 0; // when the last basket closed (starts re-entry cooldown)
int g_buy_layers = 0;
int g_sell_layers = 0;
double g_last_buy_price = 0;
double g_last_sell_price = 0;
double g_current_profit = 0; // floating basket profit (profit + swap)
double g_peak_profit = 0;
bool g_trailing_active = false;
datetime g_last_bar_time = 0;
double g_roc = 0;
double g_roc_hist[6];
int g_roc_hist_bars = 0;
double g_total_lots = 0;
bool g_new_bar_flag = false;
bool g_telemetry_basket_active = false;
int g_close_reason = 0;
double g_choppiness = 0; // 0..100 (high = ranging)
int g_htf_trend = -1; // ORDER_TYPE_BUY / ORDER_TYPE_SELL / -1 (flat)
double g_exhaustion_rsi = 50.0; // cached RSI for exhaustion filter
bool g_news_blocked = false; // true while inside a news window
string g_news_source = ""; // which event is blocking (NFP/CSV)
#define CLOSE_REASON_TRAILING 1
#define CLOSE_REASON_BASKET_TP 2
#define CLOSE_REASON_STOPOUT 3
enum ENUM_SYSTEM_STATE { STATE_SCOUT, STATE_TREND, STATE_RECOVERY, STATE_LOCKDOWN };
int hEmaFast = INVALID_HANDLE;
int hEmaSlow = INVALID_HANDLE;
int hEmaFastHTF = INVALID_HANDLE;
int hEmaSlowHTF = INVALID_HANDLE;
int hAtr = INVALID_HANDLE;
int hAtrAvg = INVALID_HANDLE;
int hAdx = INVALID_HANDLE;
int hTr = INVALID_HANDLE; // ATR(1) = true range, for Choppiness
int hRsi = INVALID_HANDLE; // RSI for exhaustion filter
string tly_ea_name = "";
long tly_magic = 0;
bool tly_ready = false;
string tly_dir = "";
datetime tly_last_beat = 0;
int tly_beat_interval = 60;
int tly_ticks = 0;
string tly_basket_symbol = "";
int tly_basket_trades = 0;
double tly_basket_peak = 0;
datetime tly_basket_opened = 0;
datetime tly_last_upd_write = 0;
int tly_last_upd_layers = -1;
int tly_upd_interval = 5;
double Ind(int handle, int buffer, int shift) {
double tmp[1];
if(handle == INVALID_HANDLE) return 0.0;
if(CopyBuffer(handle, buffer, shift, 1, tmp) != 1) return 0.0;
return tmp[0];
}
int DayOfWeek(datetime t) { MqlDateTime st; TimeToStruct(t, st); return st.day_of_week; } // 0=Sunday
int HourOf(datetime t) { MqlDateTime st; TimeToStruct(t, st); return st.hour; }
int YearOf(datetime t) { MqlDateTime st; TimeToStruct(t, st); return st.year; }
int MonthOf(datetime t) { MqlDateTime st; TimeToStruct(t, st); return st.mon; }
int OnInit() {
// код доступен только после оплаты
}
void OnDeinit(const int reason) {
TelemetryShutdown();
Comment("");
if(hEmaFast != INVALID_HANDLE) IndicatorRelease(hEmaFast);
if(hEmaSlow != INVALID_HANDLE) IndicatorRelease(hEmaSlow);
if(hEmaFastHTF != INVALID_HANDLE) IndicatorRelease(hEmaFastHTF);
if(hEmaSlowHTF != INVALID_HANDLE) IndicatorRelease(hEmaSlowHTF);
if(hAtr != INVALID_HANDLE) IndicatorRelease(hAtr);
if(hAtrAvg != INVALID_HANDLE) IndicatorRelease(hAtrAvg);
if(hAdx != INVALID_HANDLE) IndicatorRelease(hAdx);
if(hTr != INVALID_HANDLE) IndicatorRelease(hTr);
if(hRsi != INVALID_HANDLE) IndicatorRelease(hRsi);
}
void OnTick() {
// код доступен только после оплаты
}
void CalculateMomentum() {
for(int j=5; j>0; j--) {
g_roc_hist[j] = g_roc_hist[j-1];
}
g_roc = 0;
if(Bars(TradeSymbol, PERIOD_CURRENT) > Lookback) {
double cur = iClose(TradeSymbol, PERIOD_CURRENT, 0);
double prev = iClose(TradeSymbol, PERIOD_CURRENT, Lookback);
if(prev != 0) {
g_roc = (cur - prev) / prev * 100.0;
}
}
g_roc_hist[0] = g_roc;
if(g_roc_hist_bars < 6) g_roc_hist_bars++;
}
double Choppiness(int period) {
if(Bars(TradeSymbol, PERIOD_CURRENT) < period + 2) return 100.0; // not enough data -> ranging (safe)
double sum_tr = 0;
for(int i = 1; i <= period; i++) {
double tr = Ind(hTr, 0, i); // ATR(1) at shift i = true range of bar i
if(tr <= 0) return 100.0;
sum_tr += tr;
}
double highs[], lows[];
if(CopyHigh(TradeSymbol, PERIOD_CURRENT, 1, period, highs) != period) return 100.0;
if(CopyLow (TradeSymbol, PERIOD_CURRENT, 1, period, lows ) != period) return 100.0;
double hh = highs[ArrayMaximum(highs)];
double ll = lows [ArrayMinimum(lows )];
double range = hh - ll;
if(range <= 0 || sum_tr <= 0) return 100.0;
return 100.0 * MathLog10(sum_tr / range) / MathLog10((double)period);
}
int GetHTFTrend() {
double hf = Ind(hEmaFastHTF, 0, 0);
double hs = Ind(hEmaSlowHTF, 0, 0);
if(hf > hs) return ORDER_TYPE_BUY;
if(hf < hs) return ORDER_TYPE_SELL;
return -1; // flat, or HTF history still downloading -> block entries (safe)
}
datetime FirstFridayOfMonthGMT(int year, int month) {
for(int d = 1; d <= 7; d++) {
datetime dt = StringToTime(StringFormat("%04d.%02d.%02d", year, month, d));
if(DayOfWeek(dt) == 5) return dt;
}
return 0;
}
bool NewsWindowActive() {
if(!use_news_filter) return false;
datetime now_srv = TimeCurrent();
datetime now_gmt = now_srv - news_server_gmt_offset * 3600;
if(news_auto_nfp) {
int y = YearOf(now_gmt);
int m = MonthOf(now_gmt);
datetime ff = FirstFridayOfMonthGMT(y, m);
if(ff > 0) {
datetime event = ff + nfp_hour_gmt * 3600 + nfp_minute_gmt * 60;
if(now_gmt >= event - news_buffer_min * 60 &&
now_gmt <= event + news_buffer_min * 60)
{
g_news_source = "NFP " + TimeToString(event, TIME_DATE|TIME_MINUTES) + " GMT";
return true;
}
}
}
if(news_use_csv && FileIsExist(news_csv_name)) {
int fh = FileOpen(news_csv_name, FILE_READ|FILE_TXT|FILE_ANSI);
if(fh != INVALID_HANDLE) {
while(!FileIsEnding(fh)) {
string line = FileReadString(fh);
StringTrimLeft(line);
StringTrimRight(line);
if(StringLen(line) == 0) continue;
if(StringFind(line, "#") == 0) continue; // comment line
string parts[];
if(StringSplit(line, ';', parts) < 1) continue;
datetime ev = StringToTime(parts[0]);
if(ev <= 0) continue;
int before = (ArraySize(parts) > 1) ? (int)StringToInteger(parts[1]) : news_buffer_min;
int after = (ArraySize(parts) > 2) ? (int)StringToInteger(parts[2]) : before;
if(now_srv >= ev - before * 60 && now_srv <= ev + after * 60) {
g_news_source = "CSV " + parts[0];
FileClose(fh);
return true;
}
}
FileClose(fh);
}
}
g_news_source = "";
return false;
}
bool IsTradingDay() {
switch(DayOfWeek(TimeCurrent())) {
case 0: return trade_sunday;
case 1: return trade_monday;
case 2: return trade_tuesday;
case 3: return trade_wednesday;
case 4: return trade_thursday;
case 5: return trade_friday;
default: return false; // Saturday
}
}
bool InSession() {
int h = HourOf(TimeCurrent());
if(session_start_hour <= session_end_hour)
return (h >= session_start_hour && h <= session_end_hour);
return (h >= session_start_hour || h <= session_end_hour); // wraps midnight
}
bool IsLateFriday() {
if(friday_no_new_hour < 0) return false;
if(DayOfWeek(TimeCurrent()) != 5) return false;
return (HourOf(TimeCurrent()) >= friday_no_new_hour);
}
bool InRolloverWindow() {
int h = HourOf(TimeCurrent());
if(rollover_start_hour <= rollover_end_hour)
return (h >= rollover_start_hour && h <= rollover_end_hour);
return (h >= rollover_start_hour || h <= rollover_end_hour); // wraps midnight (23->0)
}
bool EntryAllowed(bool new_basket, int dir) {
if(use_spread_filter) {
if((int)SymbolInfoInteger(TradeSymbol, SYMBOL_SPREAD) > max_spread_points) return false;
}
if(skip_rollover && InRolloverWindow()) return false;
if(use_news_filter && g_news_blocked) return false;
if(use_exhaustion_filter) {
if(dir == ORDER_TYPE_BUY && g_exhaustion_rsi >= exhaustion_buy_level) return false;
if(dir == ORDER_TYPE_SELL && g_exhaustion_rsi <= exhaustion_sell_level) return false;
}
if(new_basket && use_time_filter) {
if(!IsTradingDay()) return false;
if(!InSession()) return false;
if(IsLateFriday()) return false;
}
return true;
}
void UpdateFilters() {
g_choppiness = Choppiness(chop_period);
g_htf_trend = GetHTFTrend();
g_exhaustion_rsi = Ind(hRsi, 0, 0);
g_news_blocked = NewsWindowActive();
static bool was_chop_block = false;
static int was_htf_trend = -999;
static bool was_news = false;
bool chop_block = (use_chop_filter && g_choppiness > chop_max);
if(chop_block != was_chop_block) {
Print("FILTER: Choppiness ", DoubleToString(g_choppiness, 1),
(chop_block ? " > " : " <= "), DoubleToString(chop_max, 1),
(chop_block ? " -> RANGE regime, new entries BLOCKED"
: " -> trend regime, new entries ALLOWED"));
was_chop_block = chop_block;
}
if(g_htf_trend != was_htf_trend) {
Print("FILTER: ", EnumToString(htf_tf), " trend -> ",
(g_htf_trend == ORDER_TYPE_BUY ? "BULLISH (buys allowed)" :
g_htf_trend == ORDER_TYPE_SELL ? "BEARISH (sells allowed)" : "FLAT (no HTF agreement)"));
was_htf_trend = g_htf_trend;
}
if(g_news_blocked != was_news) {
if(g_news_blocked)
Print("FILTER: NEWS window ACTIVE - new entries paused (", g_news_source, ")");
else
Print("FILTER: News window ended - entries allowed");
was_news = g_news_blocked;
}
}
bool ConfirmTrend(int dir) {
if(use_chop_filter && g_choppiness > chop_max) return false;
if(use_htf_filter) {
if(dir == ORDER_TYPE_BUY && g_htf_trend != ORDER_TYPE_BUY) return false;
if(dir == ORDER_TYPE_SELL && g_htf_trend != ORDER_TYPE_SELL) return false;
}
return true;
}
void UpdateHUD() {
int layers = g_buy_layers + g_sell_layers;
string dir = (g_buy_layers > 0) ? "BUY" : (g_sell_layers > 0 ? "SELL" : "flat");
string s = "=== XMC EA 1.02 d_Grid_v1 (MT5) ===\n";
s += "Trades THIS chart's symbol: " + TradeSymbol + "\n";
s += "Basket: " + (layers > 0 ? dir + " " + IntegerToStrinПоказано первые 50% кода (символов: 35745)
Открыть по тарифу
Купите тариф с пакетом открытий или войдите, если тариф уже есть. Открытый файл останется в вашем кабинете навсегда.
Разовая покупка файла
На этой странице откроется полный исходный код файла вместо ознакомительного фрагмента.
Зачем нужен email? После подтверждения оплаты файл сохранится в кабинете на этот email. Если аккаунта ещё нет, мы создадим его и пришлём ссылку для задания пароля. Если аккаунт уже есть, покупка добавится в него. Укажите адрес, к которому у вас есть доступ.
Чтобы оформить заказ, введите email и перейдите к оплате.