
Как интегрировать концепцию Smart Money (OB) в сочетании с индикатором Фибоначчи для оптимального входа в сделку
Введение
Концепции умных денег (Smart Money Concepts, SMC) и блоки ордеров (Order Blocks) - критические области на графике, где институциональные трейдеры обычно открывают крупные ордера на покупку или продажу. Эти зоны часто отмечают истоки значительных ценовых движений, что делает их жизненно важными для трейдеров, стремящихся согласовать свои стратегии с институциональной рыночной активностью. Понимание того, как эти ключевые уровни влияют на ценовое движение, может предоставить розничным трейдерам более глубокое представление о базовой динамике рынка, что позволит им предвидеть наиболее вероятные движения.
В сочетании с такими инструментами, как уровни Фибоначчи, трейдеры могут еще больше усовершенствовать свои стратегии входа. Коррекция Фибоначчи определяет потенциальные уровни отката между недавним максимумом и минимумом колебания, предлагая способ измерения того, насколько далеко цена может откатиться, прежде чем продолжить тренд. Такой подход помогает трейдерам определять оптимальные точки входа, согласовывая поток институциональных ордеров с областями рыночного интереса, что повышает точность сделок.
Логика советника
Бычий блок ордеров:
Блок бычьих ордеров можно определить на графиках, когда за медвежьей свечой следует бычья свеча, которая поглощает предыдущую медвежью свечу, отмечая начало значительного бычьего импульса. Чтобы образование считалась блоком бычьих ордеров, свечи, следующие за медвежьей свечой, должны состоять как минимум из двух бычьих свечей или серии бычьих свечей. Правильный подход к торговле блоком бычьих ордеров — дождаться, пока цена откатится и вернется в идентифицированную зону блока бычьих ордеров, после чего можно будет открыть позицию на покупку.
Бычья коррекция Фибоначчи:
Для поиска оптимальной точки входа в сделку после идентификации блока бычьих ордеров используется инструмент коррекции Фибоначчи. После обнаружения блока бычьих ордеров трейдер ищет связанные с ним недавние максимумы и минимумы колебаний. Затем на графике от минимума до максимума колебания проводится коррекция Фибоначчи. Коррекция помогает подтвердить, что блок бычьих ордеров находится на уровне 61,8% или ниже — ключевой зоне коррекции, которая указывает на потенциальную возможность покупки в соответствии с потоком институциональных ордеров.
Блок медвежьих ордеров:
Блок медвежьих ордеров определяется, когда за бычьей свечой следует медвежья свеча, которая поглощает предыдущую бычью свечу, сигнализируя о начале значительного медвежьего импульса. Чтобы модель считалась блоком медвежьих ордеров, за бычьей свечой должно следовать не менее двух медвежьих свечей или серии медвежьих свечей. Правильный способ торговли медвежьим блоком ордеров — дождаться возврата цены и повторного тестирования зоны медвежьего блока ордеров, после чего можно будет исполнить позицию на продажу.
Медвежья коррекция Фибоначчи:
Для блока медвежьих ордеров используется инструмент коррекции Фибоначчи для поиска оптимальных входов в торговлю. После определения блока медвежьих ордеров трейдер ищет недавние максимумы и минимумы колебаний. В этом случае коррекция Фибоначчи проводится от максимума колебания до минимума колебания, поскольку основное внимание уделяется ордеру на продажу. Коррекция подтверждает, что блок медвежьих ордеров находится на уровне 61,8% или выше, что указывает на наиболее вероятную точку входа для короткой позиции.
Приступаем к работе:
//+------------------------------------------------------------------+ //| FIB_OB.mq5 | //| Copyright 2024, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2024, MetaQuotes Ltd." #property link "https://www.mql5.com" #property version "1.00" #include <Trade/Trade.mqh> CTrade trade; #define BullOB clrLime #define BearOB clrRed
# include <Trade/Trade.mqh> - здесь мы подключаем библиотеку MQL5 Trade, которая предоставляет встроенные функции для управления сделками, ордерами и позициями. Файл Trade.mqh содержит предопределенные классы и функции, которые упрощают торговые операции, такие как открытие, закрытие и изменение ордеров. Мы создаем экземпляр CTrade с именем trade. Класс CTrade инкапсулирует торговые операции (такие как размещение ордеров на покупку/продажу, закрытие позиций и изменение сделок). Создав этот объект, вы сможете легко управлять сделками, используя объектно-ориентированный метод в вашем советнике.
Затем мы определяем две константы для цветов, которые будем использовать для визуализации блоков бычьих и медвежьих ордеров. BullOB присвоен цвет clrLime (зеленый) для блоков бычьих ордеров, указывающих на области, где покупатели могли выйти на рынок. BearOB присваивается цвет clrRed для блоков медвежьих ордеров, что указывает на области, где на рынок могли выйти продавцы.
//+------------------------------------------------------------------+ //| Global vars | //+------------------------------------------------------------------+ double Lots = 0.01; int takeProfit = 170; //int stopLoss = 200; int length = 100; input double stopLoss = 350; input double Mgtn = 00.85; bool isBullishOB = false; bool isBearishOB = false; input int Time1Hstrt = 3; input int Time1Hend = 4;
isBullishOB и isBearishOB — это логические флаги, которые мы используем для отслеживания обнаружения блоков ордеров (OB). Среди глобальных переменных у нас есть входные параметры Time1Hstrt и Time2Hend для настройки времени. Time1Hstrt представляет начальный час определенного торгового окна, в нашем случае это нью-йоркская торговая сессия. Time1Hend представляет конечный час данного временного окна.
class COrderBlock : public CObject { public: int direction; datetime time;//[] double high; double low; void draw(datetime tmS, datetime tmE, color clr){ string objOB = " OB REC" + TimeToString(time); ObjectCreate( 0, objOB, OBJ_RECTANGLE, 0, time, low, tmS, high); ObjectSetInteger( 0, objOB, OBJPROP_FILL, true); ObjectSetInteger( 0, objOB, OBJPROP_COLOR, clr); string objtrade = " OB trade" + TimeToString(time); ObjectCreate( 0, objtrade, OBJ_RECTANGLE, 0, tmS, high, tmE, low); // trnary operator ObjectSetInteger( 0, objtrade, OBJPROP_FILL, true); ObjectSetInteger( 0, objtrade, OBJPROP_COLOR, clr); } };
Мы определяем класс с именем COrderBlock, который будем использовать для моделирования блока ордеров (OB) на торговом графике. Он включает в себя свойства направления блока ордеров, времени, максимальных и минимальных значений, а также метод (draw) для рисования блока ордеров на графике. Класс COrderBlock наследуется от базового класса CObject, который является классом общего назначения в MQL5, используемым для создания объектов. Это дает COrderblock доступ к методам и свойствам CObject.
Переменная-члены (свойства) direction — тип данных int, представляющий направление блока ордеров. Мы используем его, чтобы указать, является ли блок ордеров бычьим (1) или медвежьим (-1). time - время формирования или обнаружения блока ордеров. Содержит временную метку события блока ордера. high - максимальная цена блока ордеров (верхняя граница зоны). low - минимальная цена блока ордеров (нижняя граница зоны). Эти четыре переменные являются ключевыми атрибутами блока ордеров (OB).
Затем мы создаем строковую переменную objOB для хранения уникального имени объекта-прямоугольника, который будет представлять блок ордеров на графике. Имя генерируется с использованием префикса OB REC, объединенного со временем блока ордеров (преобразованного в строку с помощью TimeToString()). ObjectCreate() - эта функция создает на графике прямоугольный объект(OBJ-RECTANGLE). 0 - идентификатор графика (0 - текущий график), а objOB - имя объекта-прямоугольника. time, low - координаты левого нижнего угла прямоугольника (начало блока ордеров на оси времени и минимальный уровень цены). tmS, high - Координаты правого верхнего угла прямоугольника (время окончания и максимальный уровень цены).
COrderBlock* OB; color OBClr; datetime T1; datetime T2;
- COrderBlock* OB - указатель на объект Order Block (блок ордеров), который мы будем использовать для отображения блока ордеров на графике и его управлением.
- color OBClr - цвет блока ордеров в зависимости от того, является ли блок ордеров бычьим или медвежьим.
- datetime T1 - время начала блока ордеров.
- datetime T2 - время окончания блока ордеров.
//+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit(){ trade.SetExpertMagicNumber(MagicNumber); return(INIT_SUCCEEDED); }
Функция OnInit() вызывается при первой загрузке советника на график. Мы просто устанавливаем магический номер советника, который является уникальным идентификатором сделок, совершаемых советником.
const int len = 5; int left_bars, right_bars; int bar_Now = len; bool isSwingH = true, isSwingL = true;
- len - количество баров (свечей) слева и справа, которые будут учитываться при определении того, является ли бар точкой колебания.
- left-bars, right-bars - индексы левого и правого баров относительно текущего (bar-Now).
- bar-Now = len - текущий анализируемый бар устанавливается на len (в данном случае 5 баров назад).
- isSwingH, isSwingL - эти логические переменные инициализируются значением true и будут использоваться для проверки того, является ли текущий бар максимумом или минимумом колебания.
for(int i = 1; i <= len; i++){ right_bars = bar_Now - i; left_bars = bar_Now + i;
Цикл for проходит по диапазону баров (len = 5), анализируя как левую, так и правую стороны текущего бара (bar-Now).
- right-bars = bar-Now - i - бары справа от текущего.
- left-bars = bar-Now + i - бары слева от текущего.
if((getHigh(bar_Now) <= getHigh(right_bars)) ||(getHigh(bar_Now) < getHigh(left_bars))){ isSwingH = false; }
Это условие проверяет, является ли максимум текущего бара (bar-Now) меньшим или равным максимуму окружающих баров (как левого, так и правого). Если какой-либо бар с любой стороны имеет более высокий или равный ему максимум, то текущий бар не является максимумом колебания, и isSwingH устанавливается на false.
if((getLow(bar_Now) >= getLow(right_bars)) || getLow(bar_Now) > getLow(left_bars)){ isSwingL = false; }
Подобно логике максимума колебания, это условие проверяет, является ли минимум текущего бара больше или равным минимуму окружающих баров. Если какой-либо бар с любой стороны имеет более низкий или равный ему минимум, то текущий бар не является минимумом колебания, и isSwingL устанавливается на false.
if(isSwingH){ Print("We have a swing high at index: ", bar_Now, "at price: ", getHigh(bar_Now)); fib_high = getHigh(bar_Now); fib_t1 = getTime(bar_Now); }
Если isSwingH равен true, это означает, что обнаружен максимум колебания. Функция выводит индекс бара и цену колебания. fib-high и fib-t1 - глобальные переменные, в которых хранятся максимальная цена колебания и соответствующее время. Эти значения будут переданы в качестве параметров в объект FIBO.
if(isSwingL){ Print("We have a swing low at index: ", bar_Now," at price: ", getLow(bar_Now)); fib_low = getLow(bar_Now); fib_t2 = getTime(bar_Now); }
Аналогично, для обработки обнаружения минимума колебания переменная isSwingL остается true, если обнаружен минимум колебания. Функция выводит индекс бара и минимальную цену колебания. fib-low и fib-t2 хранят цену и время минимума колебания. Эти значения будут переданы в качестве параметров в объект FIBO.
//+------------------------------------------------------------------+ //| Function to find OB | //+------------------------------------------------------------------+ void getOrderB(){ static int prevDay = 0; MqlDateTime structTime; TimeCurrent(structTime); structTime.min = 0; structTime.sec = 0; structTime.hour = Time1Hstrt; datetime timestrt = StructToTime(structTime); structTime.hour = Time1Hend; datetime timend = StructToTime(structTime); if(TimeCurrent() >= timestrt && TimeCurrent() < timend){ if(prevDay != structTime.day_of_year){ delete OB; for(int i = 1; i < 100; i++){ if(getOpen(i) < getClose(i)){ // index is i since the loop starts from i which is = 1 "for(int i = 1)..." if(getOpen(i + 2) < getClose(i + 2)){ if(getOpen(i + 3) > getClose(i + 3) && getOpen(i + 3) < getClose(i + 2)){ Print("Bullish Order Block confirmed at: ", TimeToString(getTime(i + 2), TIME_DATE||TIME_MINUTES)); //isBullishOB = true; OB = new COrderBlock(); OB.direction = 1; OB.time = getTime(i + 3); OB.high = getHigh(i + 3); OB.low = getLow(i + 3); isBullishOB = true; OBClr = isBullishOB ? BullOB : BearOB; // specify strt time T1 = OB.time; // reset BULL OB flag isBullishOB = false; prevDay = structTime.day_of_year; break; delete OB; } } } if(getOpen(i) > getClose(i)){ if(getOpen(i + 2) > getClose(i + 2)){ if(getOpen(i + 3) < getClose(i + 3) && getOpen(i + 3) < getClose(i + 2)){ Print("Bearish Order Block confirmed at: ", TimeToString(getTime(i + 2), TIME_DATE||TIME_MINUTES)); //isBearishOB = true; OB = new COrderBlock(); OB.direction = -1; OB.time = getTime(i + 3); OB.high = getHigh(i + 3); OB.low = getLow(i + 3); isBearishOB = true; OBClr = isBearishOB ? BearOB : BullOB; T1 = OB.time; // reset the BEAR OB flag isBearishOB = false; prevDay = structTime.day_of_year; break; delete OB; } } } } } } }
Функция ищет бычьи и медвежьи блоки одеров в ценовых данных в определенном временном диапазоне (в данном случае от Time1Hstrt до Time1end). После идентификации она создает объект Order Block (COrderBlock) с соответствующими атрибутами, такими как направление, время, максимальная и минимальная цены. Затем она устанавливает цвета и флаги для визуализации и обработки. prevDay — статическая переменная, сохраняющая свои значения между вызовами функций. Это гарантирует, что обнаружение блока ордеров выполняется только один раз в день.
Если функция уже обработала текущий день (prevDay), она пропускает обнаружение, чтобы избежать пересчета блоков ордеров. Она сбрасывается при смене дня. Функция проверяет ценовое поведение на наличие бычьих и медвежьих моделей блока ордеров.
- Условия: Поиск серии свечей, формирующих бычью модель. Первая свеча — бычья (цена открытия ниже цены закрытия). Вторая свеча также является бычьей и служит подтверждением. Третья свеча — медвежья, но цена ее открытия ниже цены закрытия второй свечи.
- Если все условия выполнены, подтверждается блок бычьих ордеров.
- Создается новый объект COrderBlock с такими свойствами, как направление (бычье), время, максимальная и минимальная цена.
- Аналогичная логика применяется для блока медвежьих ордеров. Первая свеча — медвежья (цена открытия выше цены закрытия). Вторая свеча также является медвежьей и служит подтверждением. Третья свеча — бычья, но цена ее открытия ниже цены закрытия второй свечи.
- При выполнении условий подтверждается блок медвежьих ордеров.
- После обработки объект OB удаляется для освобождения памяти.
- pervDay обновляется, чтобы гарантировать, что функция запускается только один раз в день.
bool isNewBar() { // Memorize the time of opening of the last bar in the static variable static datetime last_time = 0; // Get current time datetime lastbar_time = (datetime)SeriesInfoInteger(Symbol(), Period(), SERIES_LASTBAR_DATE); // First call if (last_time == 0) { last_time = lastbar_time; return false; } // If the time differs (new bar) if (last_time != lastbar_time) { last_time = lastbar_time; return true; } // If no new bar, return false return false; }
Функция проверяет, появился ли новый бар на графике, и выполняет некоторые функции один раз для каждого бара.
double getHigh(int index) { return iHigh(_Symbol, _Period, index); } double getLow(int index) { return iLow(_Symbol, _Period, index); } double getOpen(int index){ return iOpen(_Symbol, _Period, index); } double getClose(int index){ return iClose(_Symbol, _Period, index); } datetime getTime(int index) { return iTime(_Symbol, _Period, index); }
В этом разделе кода представлен набор служебных функций для извлечения определенных данных о ценах и информации о времени для заданного бара (или свечи) по указанному index. Каждая функция обращается к соответствующему значению цены или времени для символа и периода, используя встроенные функции MQL5, такие как iHigh(), iLow(), iOpen(), iClose() и iTime().
void OnTick(){ if(isNewBar()){ getOrderB(); getSwings(); double Bid = SymbolInfoDouble(_Symbol, SYMBOL_BID); double Ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK); if(CheckPointer(OB) != POINTER_INVALID && OB.direction > 0 && Ask < OB.high){ double entry = Ask; double tp = getHigh(iHighest(_Symbol, PERIOD_CURRENT, MODE_HIGH, iBarShift(_Symbol, PERIOD_CURRENT, OB.time))); double sl = NormalizeDouble(OB.low - Mgtn, _Digits); // double sl = getLow(iLowest(_Symbol, PERIOD_CURRENT, MODE_LOW, 2,iBarShift(_Symbol, PERIOD_CURRENT, OB.time))); ObjectCreate( 0, FIBO_OBJ, OBJ_FIBO, 0, fib_t1, fib_low, fib_t2, fib_high); double entLvl = fib_high - (fib_high - fib_low) * Fib_Trade_lvls / 100; // check this if non if(OB.high <= entLvl){ T2 = getTime(0); OB.draw(T1, T2, OBClr); trade.Buy(Lots, _Symbol, entry, sl, tp, "OB buy"); delete OB; }else{ delete OB; } } if(CheckPointer(OB) != POINTER_INVALID && OB.direction < 0 && Bid > OB.low){ double entry = Bid; double tp = getLow(iLowest(_Symbol, PERIOD_CURRENT, MODE_LOW, iBarShift(_Symbol, PERIOD_CURRENT, OB.time))); double sl = NormalizeDouble(OB.high + Mgtn, _Digits); // double sl = getHigh(iHighest(_Symbol, PERIOD_CURRENT, MODE_HIGH, iBarShift(_Symbol, PERIOD_CURRENT, OB.time))); ObjectCreate( 0, FIBO_OBJ, OBJ_FIBO, 0, fib_t2, fib_high, fib_t1, fib_low); double entLvl = fib_low + (fib_low - fib_high) * Fib_Trade_lvls / 100; if(OB.low >= entLvl){ T2 = getTime(0); OB.draw(T1, T2, OBClr); trade.Sell(Lots, _Symbol, entry, sl, tp, "OB sell"); delete OB; }else{ delete OB; } } ObjectSetInteger( 0, FIBO_OBJ, OBJPROP_COLOR, clrBlack); for(int i = 0; i < ObjectGetInteger( 0, FIBO_OBJ, OBJPROP_LEVELS); i++){ ObjectSetInteger( 0, FIBO_OBJ, OBJPROP_LEVELCOLOR, i, clrBlack); } } }
Поскольку OnTick() выполняется каждый раз, когда происходит новый тик (обновление цены), мы используем функцию isNewBar(), чтобы проверить, сформировался ли новый бар. Функция getOrderB() определяет потенциальные блоки бычьих или медвежьих ордеров (зоны, где институциональные трейдеры размещают крупные ордера на покупку/продажу). Функция getSwing() определяет точки колебания (максимумы и минимумы) в движении цены, используемые для построения уровней коррекции Фибоначчи.
Когда блок ордеров обнаружен и цена возвращается в зону блока ордеров, мы сначала проверяем, находится ли текущая цена в этой зоне. Если это так, то мы переходим к проверке параметров, проверяя, совпадает ли цена с уровнем коррекции Фибоначчи 61,8%. Этот уровень имеет решающее значение, поскольку он часто сигнализирует о серьезной точке разворота в институциональных торговых стратегиях. Только если выполняются оба условия — цена находится в пределах блока ордеров и совпадает с уровнем коррекции Фибоначчи 61,8%, — мы приступаем к исполнению позиции (покупка или продажа). В противном случае, если хотя бы одно из условий не выполняется, мы просто удаляем блок ордера и не входим в сделку.
Подтверждение бычьего блока ордеров:
Подтверждение медвежьего блока ордеров:
Логика системы построена на зависимости между блоком ордеров и уровнями коррекции Фибоначчи. При обнаружении блока ордеров система проверяет, совпадает ли он с уровнем коррекции Фибоначчи 61,8%. Для блока бычьих ордеров цена должна упасть ниже уровня коррекции 61,8%, а для блока медвежьих ордеров она должна быть выше уровня 61,8%. Если блок ордеров не соответствует этим условиям Фибоначчи, торговая позиция не исполняется. Однако объект Фибоначчи по-прежнему отображается на графике для визуализации уровня коррекции, помогая трейдеру отслеживать потенциальную ситуацию, не открывая позицию до тех пор, пока не будут выполнены нужные условия.
Заключение
Мы интегрировали ключевые концепции технического анализа, такие как блоки ордеров, колебания максимумов/минимумов и уровни коррекции Фибоначчи, для автоматизации принятия торговых решений. Мы создали функции для обнаружения блоков бычьих и медвежьих ордеров, которые представляют собой области, где институциональные трейдеры обычно размещают крупные ордера на покупку или продажу. Используя уровни Фибоначчи, советник подтверждает, совпадает ли откат цены с зонами высокой вероятности, прежде чем совершать сделки. Функция OnTick() постоянно отслеживает рынок на предмет появления новых баров и оценивает, выполняются ли условия для открытия позиций, автоматически устанавливая уровни входа, стоп-лосса и тейк-профита на основе ценового движения в реальном времени.
В заключение следует отметить, что советник призван помочь розничным трейдерам согласовывать свои сделки с потоком институциональных ордеров, предоставляя им системный подход к заключению сделок с высокой вероятностью успеха. Выявляя и реагируя на ключевые рыночные структуры, такие как блоки ордеров и откаты цен, советник позволяет трейдерам торговать с учетом стратегических действий крупных финансовых учреждений. Такое согласование может повысить точность торговли, снизить влияние эмоций и в конечном итоге повысить прибыльность розничных трейдеров.
Перевод с английского произведен MetaQuotes Ltd.
Оригинальная статья: https://www.mql5.com/en/articles/13396
Предупреждение: все права на данные материалы принадлежат MetaQuotes Ltd. Полная или частичная перепечатка запрещена.
Данная статья написана пользователем сайта и отражает его личную точку зрения. Компания MetaQuotes Ltd не несет ответственности за достоверность представленной информации, а также за возможные последствия использования описанных решений, стратегий или рекомендаций.





- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
Я думаю, что ваш zip-файл не работает так, как нужно, я не вижу графиков, но я вижу несколько отладочных сообщений о
о высоком или низком уровне колебаний.
"mgtn" используется в качестве ценового запаса или буфера для размещения стоп-лосса ниже минимума блока ордеров (для сделок на покупку) или выше максимума блока ордеров (для сделок на продажу).
Советник определяет максимумы и минимумы свинга, сравнивая текущий бар с заданным количеством баров слева и справа (в данном случае len = 5). Бар отмечается как свинг-хай, если его максимум больше, чем у окружающих баров, и как свинг-лоу, если его минимум меньше, чем у окружающих баров. Поскольку этот метод использует фиксированное количество баров, он в первую очередь обнаруживает крупные колебания структуры и может не всегда улавливать незначительные изменения структуры, если не уменьшить параметр len.