Расстановка ордеров по уровням Фибоначчи
Особой популярностью среди трейдеров пользуется такой инструмент МТ4 как «линии Фибоначчи». Используют его абсолютно для разных целей. Волновики (приверженцы волнового анализа) пользуются этим инструментом для расчета волн, другие – для простого расчета канала, в котором можно быстро найти середину или другие части от ширины канала.
Во многих случаях после построения линий Фибоначчи трейдерам требуется установить отложенные ордера на ключевые уровни. Для этого приходится вручную произвести несколько операций установки ордеров подряд. При этом нужно каждую цену уровня ввести в окошко цены открытия ордера. Когда уровней Фибоначчи 2-3, то дискомфорта трейдер не чувствует, а вот с большим количеством уровней можно даже запутаться. Здесь и придет на помощь скрипт SetOrdersOnFibo.
Задачей скрипта является поиск последнего наброшенного на график инструмента «линии Фибоначчи» и установка отложенных ордеров по всем его уровням. Причем тип ордеров скрипт определит автоматически. Если уровень «0%» инструмента «линии Фибоначчи» ниже уровня «100%», то скрипт будет устанавливать BUY-ордера (Buy Stop или Buy Limit в зависимости от нахождения текущей цены). А если уровень «0%» выше уровня «100%», то будут устанавливаться SELL-ордера (Sell Stop или Sell Limit).
Рассмотрим, как решены в коде все эти задачи.
Сначала скрипт должен найти инструмент «линии Фибоначчи»:
bool FindFibo()
{
if (ObjectsTotal(OBJ_FIBO) > 0)
{
// — 1 — ========== Нахождение первой по счету сетки Фибо ==============
for (int i = ObjectsTotal()-1; i >= 0; i—)
if (ObjectType(ObjectName(i)) == OBJ_FIBO)
break;
// — 1 — ========== Окончание блока =============================
// — 2 — ========== Определение цены каждого из уровней ===============
string Name = ObjectName(i);
double ZeroLevel = ObjectGet(Name, OBJPROP_PRICE2);
double Level100 = ObjectGet(Name, OBJPROP_PRICE1);
CountLevels = ObjectGet(Name, OBJPROP_FIBOLEVELS);
if (ZeroLevel > Level100)
Direction = False;
else
Direction = True;
for (i = 0; i < CountLevels; i++)
{
double Level = ObjectGet(Name, OBJPROP_FIRSTLEVEL+i);
if (!Direction)
OpenPrice[i] = ZeroLevel — (ZeroLevel — Level100)*Level;
else
OpenPrice[i] = ZeroLevel + (Level100 — ZeroLevel)*Level;
}
return(True);
// — 2 — ========== Окончание блока =============================
}
else
{
Alert(«Ни одна Фибо сетка не найдена!»);
return(False);
}
}
В самом начале функции определяется, есть ли вообще на графике, к которому прикреплен эксперт, инструмент «линии Фибоначчи». Если таких инструментов не найдено, то скрипт закончит работу выдачей звукового сообщения об ошибке.
В случае обнаружения хотя бы одного инструмента, выполнение программы переместится в блок 1, где из всех присутствующих на графике объектов будет найден последний инструмент «линии Фибоначчи». Таким образом, решается проблема присутствия на графике нескольких подобных инструментов. То есть в любом случае за основу будет взят последний присоединенный к графику инструмент.
Далее выполняется блок 2, где сначала определяются уровни «0%» и «100%». Эти уровни соответствуют точкам, по которым построен инструмент. При сравнении значений уровней нуля и 100%, определяется направление установки отложенных ордеров. В результате переменная Direction принимает значение False, если необходимо устанавливать SELL-ордера, и значение True, если будут устанавливаться BUY-ордера. Здесь же подсчитывается общее количество уровней, которое сохраняется в переменной CountLevels.
Когда определены базовые уровни и выбрано направление, производится расчет всех остальных уровней объекта «линии Фибоначчи». Вычисленные значения сохраняются в массиве OpenPrice. Этот массив состоит из 32 элементов – по максимальному количеству уровней, разрешенных для «линий Фибоначчи».
Вызов функции FindFibo производится из функции start скрипта. Если ее (функции FindFibo) работа завершилась успешно, то ордера будут установлены:
if (FindFibo())
for (int i = 0; i < CountLevels; i++)
{
// — 2 — == Расчет для BUY-ордеров =================================
int Type = -1; // по умолчанию ордеров не устанавливаем
if (Direction)
{
RefreshRates();
if (OpenPrice[i] > Ask + StopLevel) // если цена выше Ask, то ставим BuyStop
if (UseStopOrders)
{
Type = OP_BUYSTOP;
double Price = NP(OpenPrice[i] + Spread);
double SL = NP(IF(StopLoss == 0, 0, Price — StopLoss*Tick));
double TP = NP(IF(TakeProfit == 0, 0, Price + TakeProfit*Tick));
}
if (OpenPrice[i] < Ask — StopLevel) // если цена ниже Ask, то ставим BuyLimit
if (UseLimitOrders)
{
Type = OP_BUYLIMIT;
Price = NP(OpenPrice[i] + Spread);
SL = NP(IF(StopLoss == 0, 0, Price — StopLoss*Tick));
TP = NP(IF(TakeProfit == 0, 0, Price + TakeProfit*Tick));
}
}
// — 2 — == Окончание блока =====================================
// — 3 — == Расчет для SELL-ордеров ================================
else
{
RefreshRates();
if (OpenPrice[i] < Bid — StopLevel) // если цена ниже Bid, то ставим SellStop
if (UseStopOrders)
{
Type = OP_SELLSTOP;
Price = NP(OpenPrice[i]);
SL = NP(IF(StopLoss == 0, 0, Price + StopLoss*Tick));
TP = NP(IF(TakeProfit == 0, 0, Price — TakeProfit*Tick));
}
if (OpenPrice[i] > Bid + StopLevel) // если цена выше Bid, то ставим SellLimit
if (UseLimitOrders)
{
Type = OP_SELLLIMIT;
Price = NP(OpenPrice[i]);
SL = NP(IF(StopLoss == 0, 0, Price + StopLoss*Tick));
TP = NP(IF(TakeProfit == 0, 0, Price — TakeProfit*Tick));
}
}
// — 3 — == Окончание блока =====================================
// — 4 — == Установка одного ордера ================================
if (Type != -1) // если ордер определен, то устанавливаем
OpenOrderCorrect(Type, Price, SL, TP);
// — 4 — == Окончание блока =====================================
Для установки ордера на каждом найденном уровне используется цикл, исполняющийся CountLevels раз. Это цикл разделен на три блока (номера блоков от 2 до 4).
Во втором блоке команды выполняются, если значение Direction, ранее определенное в функции FindFibo, равно True. Сам блок, в свою очередь, разделен на две части. В первой значение цены найденного уровня OpenPrice сравнивается с ценой Ask, к которой прибавлен минимальный уровень стопов StopLevel. Если уровень выше этой цены, то проверяется значение входного параметра эксперта UseStopOrders, при помощи которого пользователь может разрешать или запрещать установку стоповых ордеров (BuyStop и SellStop), и переменной Type присваивается тип ордера OP_BUYSTOP, а переменные Price, SL и TP получают соответствующие значения. Далее уровень сравнивается с ценой Ask, из которой вычтено значение StopLevel. Если уровень ниже этой цены, то проверяется значение входного параметра эксперта UseLimitOrders (разрешение/запрет ордеров BuyLimit и SellLimit), и переменной Type присваивается значение OP_BUYLIMIT. Переменные Price, SL и TP также получают свои значения.
Третий блок является зеркальной копией второго. Он выполняется при значении Direction, равного False. Уровень OpenPrice сравнивается с ценой Bid, в зависимости от которой устанавливается стоповый или лимитный SELL-ордер.
В четвертом блоке сначала проверяется изменение значения переменной Type и, если ее значение больше или равно нулю, то производится вызов функции OpenOrderCorrect, которая и устанавливает очередной ордер.
Для работы со скриптом необходимо установить на графике объект «линии Фибоначчи», у которого настроить все нужные уровни (ненужные — удалить). Только после этого можно присоединять скрипт.
При запуске скрипта можно установить значения входных параметров:
— Lots = 0.01 – объем каждого из отложенных ордеров;
— TakeProfit = 50 — уровень профита в пунктах от цены открытия (для пятизначных котировок умножить на 10);
— StopLoss = 100 — уровень стоп-приказа в пунктах (для пятизначных котировок умножить на 10);
— UseStopOrders = True – разрешать (True) или запрещать (False) установку ордеров BuyStop и SellStop;
— UseLimitOrders = True – разрешать (True) или запрещать (False) установку ордеров BuyLimit и SellLimit;
— MagicNumber = 900 – уникальный идентификатор ордеров, установленных скриптом. Самим скриптом это значение только устанавливается, но нигде не проверяется. Используется для последующих действий пользователя с ордерами.