XMC EA 1.02 d_Grid_v1
Похожие материалы по тегам
Сообщите нам, если считаете, что материал размещён без разрешения.
Сообщить о материале
Обращение по товару «xmc ea 1.02 d_grid_v1.mq4» отправится на рассмотрение. Укажите контакт для ответа и опишите причину.
О программе
XMC EA 1.02 d_Grid_v1 — торговый советник для MetaTrader 4, работающий по принципу сетки (grid) в направлении текущего тренда. Советник открывает несколько слоёв в одном направлении и закрывает всю корзину при достижении заданного уровня плавающего дохода, после чего запускается цикл ожидания и повторного входа. Торгуется только символ графика, к которому прикреплён советник, хеджирование запрещено — корзины BUY и SELL не работают одновременно.
Советник включает комплекс фильтров для контроля входов: тренд на старшем таймфрейме (EMA), режим бокового рынка (Choppiness), исчерпание тренда (RSI), новостные окна (автоматическая блокировка NFP и CSV-события), временные фильтры (дни недели, сессионные часы, пятничный отсчёт, ролловер) и фильтр спреда. Сеточный шаг может рассчитываться через ATR или задаваться фиксированным значением в пунктах.
Встроена система телеметрии, записывающая данные о состояниях корзин, сделках и диагностике в CSV-файлы. Также реализована система восстановления состояния при перезапуске советника — существующие позиции на символе регистрируются в телеметрии. Имеется защитный трейлинг-бэкстоп, срабатывающий при достижении заданного уровня дохода и последующем откатывании.
Настройки программы
| Настройка | Описание |
|---|---|
| TradeCooldown | Минимальное количество секунд между последовательными торговыми операциями (открытием слоёв). |
| Lookback | Период в барах для расчёта импульса (ROC) — разница цен между текущей ценой и ценой N баров назад, используется для телеметрии и диагностики. |
| basket_tp_amount | Уровень плавающего дохода в валюте счёта, при достижении которого вся корзина закрывается и запускается цикл ожидания перед повторным входом. |
| reentry_cooldown | Количество секунд ожидания после закрытия корзины перед возможностью открытия новой корзины (на подтверждённом направлении). |
| use_exhaustion_filter | Переключатель фильтра исчерпания тренда: блокирует входы BUY при RSI >= заданного уровня и входы SELL при RSI <= заданного уровня. |
| exhaustion_rsi_period | Период расчёта RSI для фильтра исчерпания тренда. |
| exhaustion_buy_level | Уровень RSI, при достижении которого входы BUY блокируются как исчерпанный тренд. |
| exhaustion_sell_level | Уровень RSI, при достижении которого входы SELL блокируются как исчерпанный тренд. |
| use_news_filter | Главный переключатель новостного фильтра: при включении блокируются входы в окне NFP и/или CSV-событий. |
| news_buffer_min | Количество минут до и после новостного события, в течение которых входы блокируются. |
| news_auto_nfp | Автоматическая блокировка входов в первую пятницу месяца в момент публикации данных NFP (Non-Farm Payroll). |
| nfp_hour_gmt | Час публикации NFP по GMT (например, 13:30 GMT = 8:30 ET). |
| nfp_minute_gmt | Минута публикации NFP по GMT. |
| news_use_csv | Включает чтение файла MQL4\Files\news_events.csv для дополнительной блокировки входов по датам FOMC/CPI и других событий. Формат строк: дата-время; минуты_до;минуты_после. |
| news_csv_name | Имя CSV-файла в папке MQL4\Files для ручного добавления дат новостных событий (FOMC, CPI и др.). |
| use_time_filter | Главный переключатель временного фильтра: при включении входы разрешены только в торговые дни, в рамках торговой сессии, с учётом пятничного отсчёта и ролловера. |
| trade_sunday | Переключатель: разрешает ли торговлю в воскресенье. |
| trade_monday | Переключатель: разрешает ли торговлю в понедельник. |
| trade_tuesday | Переключатель: разрешает ли торговлю во вторник. |
| trade_wednesday | Переключатель: разрешает ли торговлю в среду. |
| trade_thursday | Переключатель: разрешает ли торговлю в четверг. |
| trade_friday | Переключатель: разрешает ли торговлю в пятницу. |
| session_start_hour | Серверный час начала торговой сессии (включительно), с которого разрешено открытие новых корзин. |
| session_end_hour | Серверный час окончания торговой сессии (включительно). Если начало больше конца — сессия оборачивает полночь. |
| friday_no_new_hour | Серверный час, начиная с которого в пятницу запрещено открытие новых корзин. |
| skip_rollover | Переключатель блокировки всех входов в окне ролловера (переключение серверных позиций). |
| rollover_start_hour | Серверный час начала окна ролловера (оборачивает полночь). Входы в этом окне блокируются. |
| rollover_end_hour | Серверный час окончания окна ролловера (включительно). Входы в этом окне блокируются. |
| use_spread_filter | Переключатель фильтра спреда: блокирует входы, когда текущий спред превышает заданный максимум в пунктах. |
| max_spread_points | Максимально допустимый спред в пунктах, при превышении которого входы блокируются. |
| use_htf_filter | Переключатель фильтра старшего таймфрейма: входы разрешаются только при совпадении направления тренда на старшем ТФ (EMA быстрая/медленная). |
| htf_tf | Таймфрейм для фильтра тренда старшего таймфрейма (EMA быстрая/медленная). |
| use_chop_filter | Переключатель фильтра бокового рынка: блокирует входы, когда индекс Choppiness превышает заданный порог. |
| chop_period | Период расчёта индекса Choppiness для определения режима рынка (тренд или диапазон). |
| chop_max | Пороговое значение индекса Choppiness, при превышении которого входы блокируются как боковой рынок. |
| max_layers | Максимальное количество слоёв (позиций) в одной корзине. |
| ema_fast_period | Период быстрой скользящей средней EMA, используемой для определения направления тренда. |
| ema_slow_period | Период медленной скользящей средней EMA, используемой для определения направления тренда. |
| adx_period | Период расчёта индикатора ADX для оценки силы тренда. |
| adx_trend_strength | Пороговое значение ADX, при превышении которого система считает, что тренд достаточно силён для перехода в состояние TREND. |
| use_atr_distance | Переключатель: использовать ли ATR-адаптивное расстояние между слоями сетки вместо фиксированного значения в пунктах. |
| atr_period | Период расчёта индикатора ATR для определения волатильности. |
| atr_smoothing | Период сглаживания ATR для расчёта среднего значения волатильности (используется для определения состояния системы). |
| atr_multiplier | Множитель ATR для расчёта адаптивного расстояния сетки (шаг между уровнями открытия слоёв). |
| fallback_distance_pts | Фиксированное расстояние сетки в пунктах, используемое как запасной вариант при отключённом ATR-расстоянии. |
| max_volatility_factor | Коэффициент волатильности: если текущий ATR превышает средний ATR более чем в указанное число раз, система переходит в состояние LOCKDOWN и входы блокируются. |
| fixed_lot | Фиксированный объём лота для первого слоя корзины. |
| lot_multiplier | Множитель для расчёта объёма последующих слоёв (1.0 — плоские лоты, каждый следующий слой увеличивается в указанное число раз). |
| trail_start_amount | Уровень плавающего дохода (в единицах валюты счёта), при достижении которого активируется защитный трейлинг-бэкстоп. |
| trail_dist_amount | Расстояние отката плавающего дохода (в единицах валюты счёта), при котором срабатывает защитный трейлинг и закрывается вся корзина. |
| initial_magic | Магический номер для идентификации ордеров, открытых данным советником. |
| trade_comment | Комментарий, присваиваемый каждой сделке советником. |
Поиск по коду файла
#property strict
#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 "Original Code: Anton Trefolev (a************v*@gmail.com)"
input int TradeCooldown = 30; // min seconds between opening layers
input int Lookback = 60; // ROC lookback (momentum telemetry)
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 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 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 (most: +2 winter / +3 summer)
input bool news_use_csv = true; // also read MQL4\Files\news_events.csv (FOMC/CPI dates)
input string news_csv_name = "news_events.csv";
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 bool use_spread_filter = true;
input int max_spread_points = 120; // block new entries above this spread (points)
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 int max_layers = 89;
input int ema_fast_period = 3;
input int ema_slow_period = 20;
input int adx_period = 10;
input int adx_trend_strength = 20;
input bool use_atr_distance = true;
input int atr_period = 14;
input int atr_smoothing = 20;
input double atr_multiplier = 0.5;
input double fallback_distance_pts = 90.0;
input double max_volatility_factor = 2.5;
input double fixed_lot = 0.01;
input double lot_multiplier = 1.3; // 1.0 = flat lots
input double trail_start_amount = 50.0;
input double trail_dist_amount = 10.0;
input int initial_magic = 202609011;
input string trade_comment = "XMC_Grid_v1";
string TradeSymbol = ""; // set to chart symbol in OnInit
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_avg_buy_price = 0;
double g_avg_sell_price = 0;
double g_current_profit = 0;
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; // OP_BUY / OP_SELL / -1
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 };
string tly_ea_name = "";
int 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;
int OnInit() {
// код доступен только после оплаты
}
void OnDeinit(const int reason) {
TelemetryShutdown();
Comment("");
}
void OnTick() {
// код доступен только после оплаты
}
void CalculateMomentum() {
for(int j=5; j>0; j--) {
g_roc_hist[j] = g_roc_hist[j-1];
}
g_roc = 0;
if(iBars(TradeSymbol, 0) > Lookback) {
double cur = iClose(TradeSymbol, 0, 0);
double prev = iClose(TradeSymbol, 0, 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(iBars(TradeSymbol, 0) < period + 2) return 100.0;
double sum_tr = 0;
for(int i = 1; i <= period; i++) sum_tr += iATR(TradeSymbol, 0, 1, i);
int hi = iHighest(TradeSymbol, 0, MODE_HIGH, period, 1);
int lo = iLowest (TradeSymbol, 0, MODE_LOW, period, 1);
if(hi < 0 || lo < 0) return 100.0;
double range = iHigh(TradeSymbol, 0, hi) - iLow(TradeSymbol, 0, lo);
if(range <= 0 || sum_tr <= 0) return 100.0;
return 100.0 * MathLog10(sum_tr / range) / MathLog10((double)period);
}
int GetHTFTrend() {
double hf = iMA(TradeSymbol, htf_tf, ema_fast_period, 0, MODE_EMA, PRICE_CLOSE, 0);
double hs = iMA(TradeSymbol, htf_tf, ema_slow_period, 0, MODE_EMA, PRICE_CLOSE, 0);
if(hf > hs) return OP_BUY;
if(hf < hs) return OP_SELL;
return -1;
}
datetime FirstFridayOfMonthGMT(int year, int month) {
for(int d = 1; d <= 7; d++) {
datetime dt = StringToTime(StringFormat("%04d.%02d.%02d", year, month, d));
if(TimeDayOfWeek(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 = TimeYear(now_gmt);
int m = TimeMonth(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(StringGetChar(line, 0) == '#') continue;
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(TimeDayOfWeek(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 = TimeHour(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(TimeDayOfWeek(TimeCurrent()) != 5) return false;
return (TimeHour(TimeCurrent()) >= friday_no_new_hour);
}
bool InRolloverWindow() {
int h = TimeHour(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(MarketInfo(TradeSymbol, MODE_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 == OP_BUY && g_exhaustion_rsi >= exhaustion_buy_level) return false;
if(dir == OP_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 = iRSI(TradeSymbol, 0, exhaustion_rsi_period, PRICE_CLOSE, 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 == OP_BUY ? "BULLISH (buys allowed)" :
g_htf_trend == OP_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 == OP_BUY && g_htf_trend != OP_BUY) return false;
if(dir == OP_SELL && g_htf_trend != OP_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 ===\n";
s += "Trades THIS chart's symbol: " + TradeSymbol + "\n";
s += "Basket: " + (layers > 0 ? dir + " " + IntegerToString(layers) + " layers "
+ DoubleToString(g_total_lots, 2) + " lots" : "none") + "\n";
s += "Floating P/L: $" + DoubleToString(g_current_profit, 2)
+ " (basket TP $" + DoubleToString(basket_tp_amount, 2) + ")\n";
if(layers == 0 && g_last_basket_close_time > 0) {
int wait = (int)(reentry_cooldown - (TimeCurrent() - g_last_basket_close_time));
if(wait > 0) s += "Re-entry cooldown: " + IntegerToString(wait) + "s left\n";
}
s += "CHOP " + DoubleToString(g_choppiness, 1)
+ (use_chop_filter && g_choppiness > chop_max ? " BLOCK" : "")
+ " | HTF " + (g_htf_trend == OP_BUY ? "BULL" : (g_htf_trend == OP_SELL ? "BEAR" : "FLAT"))
+ " | RSI " + DoubleToString(g_exhaustion_rsi, 1)
+ (use_exhaustion_filter &&
(g_exhaustion_rsi >= exhaustion_buy_level || g_exhaustion_rsi <= exhaustion_sell_level)
? " EXHAUSTED" : "") + "\n";
if(use_news_filter && g_news_blocked)
s += "NEWS WINDOW ACTIVE - entries paused (" + g_news_source + ")\n";
if(use_spread_filter) {
double sp = MarketInfo(TradeSymbol, MODE_SPREAD);
s += "Spread " + DoubleToString(sp, 0) + " pts"
+ (sp > max_spread_points ? " BLOCK" : "") + "\n";
}
Comment(s);
}
void RefreshBasketState() {
g_buy_layers=0; g_sell_layers=0; g_last_buy_price=0; g_last_sell_price=0;
g_avg_buy_price=0; g_avg_sell_price=0;
g_current_profit=0;
g_total_lots=0;
double bCost=0, bLots=0, sCost=0, sLots=0;
datetime tB=0, tS=0;
for(int i=OrdersTotal()-1; i>=0; i--) {
if(OrderSelect(i, SELECT_BY_POS) && OrderSymbol() == TradeSymbol && OrderMagicNumber() == initial_magic) {
double prof = OrderProfit()+OrderSwap()+OrderCommission();
g_current_profit += prof;
g_total_lots += OrderLots();
if(OrderType()==OP_BUY) {
Показано первые 50% кода (символов: 31563)
Открыть по тарифу
Купите тариф с пакетом открытий или войдите, если тариф уже есть. Открытый файл останется в вашем кабинете навсегда.
Разовая покупка файла
На этой странице откроется полный исходный код файла вместо ознакомительного фрагмента.
Зачем нужен email? После подтверждения оплаты файл сохранится в кабинете на этот email. Если аккаунта ещё нет, мы создадим его и пришлём ссылку для задания пароля. Если аккаунт уже есть, покупка добавится в него. Укажите адрес, к которому у вас есть доступ.
Чтобы оформить заказ, введите email и перейдите к оплате.