Язык MQL — Урок 5 «открытие ордеров»

На предыдущих уроках по изучению языка MQL мы написали скрипт Metatrader4 — «test» для расчета лота. Теперь мы знаем сколько использовать средств для торговли и можем спокойно открывать ордера в Metatrader 4 автоматически.

Но зачем их открывать в ручную если это можно поручить компьютеру? Да и не удобно запускать скрипт на Metatrader 4, а потом еще открывать ордер. Опять же цена между этими действиями не стоит на месте, а постоянно меняется и мы можем потерять несколько пунктов прибыли.

Давайте научим наш скрипт открывать ордера автоматически. Для этого, нам нужно определиться какие ордера он должен открывать. В MetaTrader можно использовать как рыночные ордера (открываемые по текущей цене) так и отложенные(автоматически открываемые брокером при достижении цены заданного уровня).

В нашем тестовом скрипте на MQL4, мы будем открывать рыночные ордера так как мы обучаемся, а любое обучение идет от простого к сложному.

Все эти типы ордеров програмно открываются одной и той же функцией: OrderSend().

Кроме того ордера бывают на покупку и на продажу валюты. Значит скрипту надо указать эти сведения.

Введем в параметры нашего скрипта еще 2 параметра:
extern bool Buy=false; //для открытия ордера на покупку
extern bool Sell=false; //для открытия ордера на продажу

Оба параметра имеют логический (bool) тип. Значит они будут принимать только два значения: true (истина) и false (ложь). Мы установили их значение в false чтобы при запуске нашего скрипта в MT4 с параметрами по умолчанию ничего не происходило. Если бы мы установили их в true то при запуске с параметрами по умолчанию у нас открылось 2 ордера. Один на покупку, а второй на продажу. В большинстве случаев нам это не нужно. Будем при запуске говорить скрипту «какой ордер открыть».

Тип ордера мы теперь можем указать скрипту, но осталось непонятно как указать стоплосс и тейкпрофит. Согласитесь, что их тоже желательно указывать в параметрах. Например так:
extern int TakeProfit=100;
extern int StopLoss=100;
мы выбрали тип int (целое число), а скрипту поручим переводить их в пункты в зависимости от котировки валютной пары. Для этого достаточно их умножить на служебную переменную Point (размер пункта текущего инструмента в валюте котировки).

Но а как быть если наша стратегия не подразумевает установку тейкпрофита или стоплосса?
воспользуемся знакомой нам функцией проверки условия if:
double buyTP=0; //тейкпрофит для покупки
double sellTP=0; //тейкпрофит для продажи
double buySL=0; //стоплосс для покупки
double sellSL=0; //стоплосс для продажи
if(TakeProfit>0)
{buyTP=Ask+TakeProfit*Point;
sellTP=Bid-TakeProfit*Point;}
if(StopLoss>0)
{buySL=Ask-StopLoss*Point;
sellSL=Bid+StopLoss*Point;}

Здесь мы использовали фигурные скобки чтобы после проверки условия выполнялась не одна команда, а несколько.

Итак, наши команды для открытия ордеров будут выглядеть:
if(Buy) OrderSend(Symbol(),OP_BUY,Lot,Ask,3,buySL,buyTP,»»,0,0,CLR_NONE);
if(Sell) OrderSend(Symbol(),OP_SELL,Lot,Bid,3,sellSL,sellTP,»»,0,0,CLR_NONE);

С помощью функции if() мы проверяем какой ордер нужно открыть. А функцией OrderSend() открываем.
Функция OrderSend() достаточно сложная и требует много параметров.

Давайте разберемся с ними:1 — валюта по которой открывать ордер (мы использовали уже известную функцию Symbol() для указания текущей валюты)
2 — тип открываемого ордера (OP_BUY покупка по рыночной цене, OP_SELL продажа по рыночной цене)
3 — размер лота (у нас в скрипте уже лот рассчитан в переменной Lot, его и используем)
4 — цена (для покупки текущая рыночная цена содержится в служебной переменной Ask, а для продажи в Bid)
5 — проскальзывание (со времени отправки команды на сервер «открыть ордер» и ее исполнением цена может успеть изменится. Мы поставили 3 пункта. Этим мы сказали серверу брокера что если цена изменится максимум на 3 пункта — открыть ордер, а если больше — не открывать.)
6 — размер стоплосса (расчет надеюсь понятен?)
7 — размер тейкпрофита (если понятен расчет стоплосса то и тут все понятно)
8 — комментарий (каждому ордеру можно присвоить свой комментарий. Оставим этот параметр пустым)
9 — магический номер(зачем он нужен? Когда работают несколько советников — по этому номеру они находят «свои» ордера. Мы оставили 0, хотя сюда можно написать любое число.)
10- срок жизни отложенного ордера(пока нам не интересно, ведь мы используем рыночные ордера а не отложенные)
11- цвет стрелки (для наглядности можно указать цвет и тогда на графике будет нарисована стрелочка в том месте где открылся ордер.

Мы использовали служебную константу CLR_NONE — не рисовать)

С параметрами разобрались, но это еще не все (а вы думали будет легко?) Функция OrderSend() возвращает номер тикета (уникальный номер ордера) или -1 в случае ошибки. Если при расчете лота все действия выполнялись на компьютере, то здесь идет взаимодействие с сервером брокера форекс. А значит может возникнуть большое количество ошибок. По хорошему надо проверять — какую ошибку вернула функция и выполнять соответствующие действия. Но я покажу вам один простой способ как избежать большинства из них.

Для этого мы используем простую конструкцию:
while(!IsTradeAllowed()) Sleep(100);

Дословно означает «подождем пока сервер не будет готов принять от нас команду»
функция while() будет выполнять следующую за ней команду до бесконечности если условие переданное ей истенно. Это так называемый цикл. Условием мы передаем другую функцию IsTradeAllowed() — возвращается TRUE, если эксперту разрешено торговать и поток для выполнения торговых операций свободен, иначе возвращает FALSE. Но нам надо как раз наоборот: чтобы было TRUE когда терминал занят. Для этого перед функцией стоит восклицательный знак. Он интвертирует условие и мы получаем то что и хотели. Функция Sleep() — ничего не делает, но и не дает выполнятся программе указанное количество милисекунд.

В итоге мы получаем код нашего скрипта на языке MQL4:
//+——————————————————————+
//| test.mq4 |
//| Copyright c 2009, MetaQuotes Software Corp. |
//| http://www.metaquotes.net |
//+——————————————————————+
#property copyright «Copyright c 2009, MetaQuotes Software Corp.»
#property link «http://www.metaquotes.net»
#property show_inputs
extern int MaxRisk=2;
extern bool Buy=false; //для открытия ордера на покупку
extern bool Sell=false; //для открытия ордера на продажу
extern int TakeProfit=100;
extern int StopLoss=100;
//+——————————————————————+
//| script program start function |
//+——————————————————————+
int start()
{
//—-
double Free =AccountFreeMargin();
double One_Lot =MarketInfo(Symbol(),MODE_MARGINREQUIRED);
double Min_Lot =MarketInfo(Symbol(),MODE_MINLOT);
double Max_Lot =MarketInfo(Symbol(),MODE_MAXLOT);
double Step =MarketInfo(Symbol(),MODE_LOTSTEP);
double Lot =MathFloor(Free*MaxRisk/100/One_Lot/Step)*Step;
if(Lot<Min_Lot) Lot=Min_Lot;
if(Lot>Max_Lot) Lot=Max_Lot;
double buyTP=0; //тейкпрофит для покупки
double sellTP=0; //тейкпрофит для продажи
double buySL=0; //стоплосс для покупки
double sellSL=0; //стоплосс для продажи
if(TakeProfit>0)
{buyTP=Ask+TakeProfit*Point;
sellTP=Bid-TakeProfit*Point;}
if(StopLoss>0)
{buySL=Ask-StopLoss*Point;
sellSL=Bid+StopLoss*Point;}
while(!IsTradeAllowed()) Sleep(100);
if(Buy) OrderSend(Symbol(),OP_BUY,Lot,Ask,3,buySL,buyTP,»»,0,0,CLR_NONE);
while(!IsTradeAllowed()) Sleep(100);
if(Sell) OrderSend(Symbol(),OP_SELL,Lot,Bid,3,sellSL,sellTP,»»,0,0,CLR_NONE);
//—-
return(0);
}
//+——————————————————————+

Теперь этим скриптом, написанном на языке MQL4 удобно торговать. Например по стратегии Hedge Hog.

Однако есть одно «но» — не каждому удобно находится около терминала MT4 в 00:00 по GMT (как требует предложенная стратегия форекс). Поэтому на следующем уроке по изучению языка MQL, мы займемся написанием советника форекс (который торгует сам).

Скачать: скрипт test

Похожие статьи:

58 комментариев

  1. mql5. Попробовал открыть ордер вот таким образом:

    void OnStart()
    {
    double buyTP=0; //тейкпрофит для покупки
    double sellTP=0; //тейкпрофит для продажи
    double buySL=0; //стоплосс для покупки
    double sellSL=0; //стоплосс для продажи
    double Ask,Bid;
    MqlTradeRequest my_request;
    MqlTradeResult my_result;
    Ask=SymbolInfoDouble(Symbol(),SYMBOL_ASK);
    Bid=SymbolInfoDouble(Symbol(),SYMBOL_BID);
    string symbol=Symbol();
    if(TakeProfit>0)
    {
    buyTP=Ask+TakeProfit*_Point;
    sellTP=Bid-TakeProfit*_Point;
    }
    if(StopLoss>0)
    {
    buySL=Ask-StopLoss*_Point;
    sellSL=Bid+StopLoss*_Point;
    }
    my_request.action=TRADE_ACTION_DEAL;
    my_request.magic=1;
    my_request.deviation=0;
    my_request.order=1;
    my_request.sl=buySL;
    my_request.tp=buyTP;
    my_request.symbol=symbol;
    my_request.type=ORDER_TYPE_BUY;
    my_request.type_filling=ORDER_FILLING_AON;
    my_request.volume=0.1;
    my_request.type_time=ORDER_TIME_GTC;
    OrderSend(my_request,my_result);

    Не работает. Что надо сделать, чтобы было правильно?

  2. Что-то не получилось не сходятся коды написанные на сайте и в ссылке скрипт test Пожалуйста разъясните очень хочется научиться программировать Спасибо

  3. Все очень просто. В конце статьи можете скачать рабочий скрипт. А читая статью разобраться как он работает. Редактор изменяет некоторые символы при публикации. Это касается кавычек и знаков минус. Поэтому я и выкладываю исходные коды в конце статей.

  4. Добрый день! непонятна следующая строка можно подробнее?

    if(TakeProfit>0)
    {buyTP=Ask+TakeProfit*Point;
    sellTP=Bid-TakeProfit*Point;}

  5. Спасибо за этот блог. Очень интересно.
    Вопрос:
    Что значит двойное равно == ? Например:
    if(Lot==0)

  6. Александр, не могли бы Вы наглядно показать описание скрипта автоматического открытия отложенных ордеров STOP и LIMIT на основе скрипта test на определенном расстоянии от цены и друг от друга с TP и SL и определенным количеством ордеров и лотов?Заранее благодарен,Тимур.

  7. Anton
    В языке MQL двойное равно «==» означает проверку на равенство, в то время как одинарный знак равно «=» означает присваивание значения.

  8. Амир
    Здесь мы проверяем внешний параметр TakeProfit и если он задан (больше 0), то для открываемых ордеров рассчитываем значение тейкпрофита.

  9. leo52
    Здесь нет ничего сложного. Вместо OP_BUY пишем OP_BUYSTOP для STOP ордеров или OP_BUYLIMIT для LIMIT ордеров. А вместо Ask и Bid указываем необходимую нам цену. Количество устанавливаемых ордеров тоже не проблема. Нужно вызывать функцию OrderSend столько раз — сколько ордеров мы хотим установить.

  10. Подскажите пожалуйста, как прописать код, чтоб в параметрах ордера присутствовал трейлингстоп?

  11. Здравствуйте спасибо за ресурс очень необходимый, у меня возникла проблема подскажите пожалуйста как ее решить:
    ««,0,0,CLR_NONE);’ — double quotes needed
    «,0,0,CLR_NONE);’ — double quotes needed эти две ошибки появляются при компиляции. И еще у нас была команда алерт, куда она делась? или невнимательно что то прочитал???

  12. А все разобрался, у Вас не хватает кавычек ««», и.т.д. а как быть с алертом?

  13. Night
    Насколько я понял имеется ввиду встроенный в терминал тралл? Если он, то никак. Пишутся свои советники для трала. Если проблема написать, то в интернете полно их (как платных, так и бесплатных).

  14. Антон
    В конце каждого урока есть ссылка на скачивание уже готового советника, скрипта или индикатора. Я уже объяснял что при публикации некоторые символы искажаются. Поэтому и выкладываю в конце статей исходники.

  15. Антон
    Алерт нам был нужен для вывода на экран рассчитанного лота. А здесь мы открываем ордера с рассчитанным лотом (лот можно видеть в ордере). Поэтому я посчитал что он лишний и удалил. Если он Вам нужен — добавте в код.

  16. Спасибо за сайт.

    Возникла проблема не могу решить. Скачал скрипт test , откомпилировал. Запустил — ордер (на покупку) не выставляется. Скрипт ведет себя так словно торговый поток постоянно занят.

    для проверки составил простейший скрипт
    while(!IsTradeAllowed()) {Sleep(1000);Alert(IsTradeAllowed());}
    выдает каждую секунду 0
    Пожалуйста подскажите в чем дело?

  17. Извините. Все понял. В начальных установках не отметил «разрешить советнику торговать». Ещё раз спасибо за сайт

  18. Если я не хочу устанавливать takeprofit и stopLoss
    мне нужно обнулить эти переменнные
    buyTP=0
    sellTP=0
    или ничего им не присваивать?

  19. Автору не просто спасибо, ему СПАСИБО!!! доходчиво, понятно, переделал немного скрипт и получил то, что нужно. На ручном скальпинге просто безумно необходимо повесить на горячую клавишу скрипт, которые делает рыночный моментальный ордер с выставленным ТР. Я в программировании полный ноль, но разобрался с ходу по объяснениям. Если кто такой же немощный, то вот упрощенный до нельзя скрипт на продажу:
    extern bool Sell=true; //для открытия ордера на продажу
    extern int TakeProfit=1;
    //±——————————————————————+
    //| script program start function |
    //±——————————————————————+
    int start()
    {
    //—-
    double Lot =0.01;
    double sellTP=0; //тейкпрофит для продажи
    if(TakeProfit>0)
    {sellTP=Bid-TakeProfit*Point;}
    if(Sell) OrderSend(Symbol(),OP_SELL,Lot,Bid,3,0,sellTP,»продажа нах»,0,0,CLR_NONE);
    //—-
    return(0);
    }
    //±——————————————————————+

    на покупку выдергиваем нужные строки и подправляем)
    Счастье есть)

  20. Здравствуйте! И во-первых хочу поблагодарить за всю работу по созданию и поддержанию этого замечательного сайта.
    А во-вторых такой вопрос: скрипт после того как он выполнил то что требуется — закрывается. Чтобы снова запустился автоматически на тех же условиях что и открывался изначально — что нужно сделать?
    Очень жду Вашего ответа
    С Уважением, Вячеслав

  21. Скрипт выполняется 1 раз при его запуске. Если необходимо переодическое выполнение — пишется советник и в нем задаются условия для выполнения. Можно конечно и скрипт зациклить, но это не имеет смысла.

  22. ‘\end_of_program’ — unbalanced left parenthesis C:\Program Files\Alpari MT4\experts\scripts\test.mq4 (47, 1)
    что это означает? вылезает при компилировании

  23. Это означает что нехватает закрывающей скобки. Например: Alert(Symbol();

  24. при компиляции выдает
    ‘BuySL’ — variable not defined
    ‘BuyTP’ — variable not defined
    ‘SellSL’ — variable not defined
    ‘SellTP’ — variable not defined
    что надо изменить в коде?

  25. Скажите, пожалуйста, а как сделать так, чтобы открывалось, например, 5 ордеров одновременно, какую функцию надо открывать?

  26. Супер статья. Нашёл что искал! Спасибо!

    У меня есть ещё вопрос. Буду очень благодарен если ответите. Я немножко переделал скрипт, только не спрашивайте мне для чего он нужен 🙂 Т.е. он мне нужен точно, если захотите узнать я скажу.

    //+——————————————————————+
    //| test.mq4 |
    //| Copyright © 2009, MetaQuotes Software Corp. |
    //| http://www.metaquotes.net |
    //+——————————————————————+
    #property copyright «Copyright © 2009, MetaQuotes Software Corp.»
    #property link «http://www.metaquotes.net»
    #property show_inputs
    extern int TakeProfit=10;
    extern int StopLoss=0;
    //+——————————————————————+
    int start()
    {
    RefreshRates();
    NewOrder(OP_SELL,1);

    return(0);}
    //+——————————————————————+
    int NewOrder(int Cmd,double Lot)
    {double TP=0; //тейкпрофит
    double SL=0; //стоплосс
    double PR=0; //Цена
    while(!IsTradeAllowed()) Sleep(100);
    if(Cmd==OP_BUY)
    {PR=Ask;
    if(TakeProfit>0) TP=Ask+TakeProfit*Point;
    if(StopLoss>0) SL=Ask-StopLoss*Point;}
    if(Cmd==OP_SELL)
    {PR=Bid;
    if(TakeProfit>0) TP=Bid-TakeProfit*Point;
    if(StopLoss>0) SL=Bid+StopLoss*Point;}
    int tic=OrderSend(Symbol(),Cmd,Lot,PR,3,SL,TP,»»,0,0,CLR_NONE);
    if(tic<0) Print(«Ошибка открытия ордера: «,GetLastError());
    return(tic);}
    //+——————————————————————+

    Я так понял вот эта часть
    __________________________
    int start()
    {
    RefreshRates();
    NewOrder(OP_SELL,1);
    return(0);}
    __________________________

    будет выполняться постоянно через каждые Sleep(100);

    Мне же необходимо, чтобы открывался такой ордер сразу как только старый закрылся. Как мне лучше это всё организовать? Не хочется просто грузить процессор и сервер через каждые 10 секунд.
    Спасибо!

  27. и еще вопрос где можно посмотреть список всех команд, знаков, описание их значения?

  28. Grig
    Компилятор сообщает что отсутствует описание переменных. Прежде чем использовать переменные их необходимо определить. Например как в статье:
    double buyTP=0; //тейкпрофит для покупки
    double sellTP=0; //тейкпрофит для продажи
    double buySL=0; //стоплосс для покупки
    double sellSL=0; //стоплосс для продажи

  29. Сергей
    Это вопрос не по программированию, а на логику. Достаточно немного подумать и решение получается простейшим: проверять есть ли открытые ордера
    int Count=0;
    for(int i=OrdersTotal() −1;i>=0;i—)
    if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)) Count++;
    и если их нет, то открывать новый
    if(Count==0) NewOrder(OP_SELL,1);

  30. До 5го урока все было последовательно написано, а тут как-то в разброс. Или у меня логика нарушена.
    — после текста «Все эти типы ордеров програмно открываются одной и той же функцией: OrderSend().»
    Нужно было сразу ее и описывать, а не сбивать на параметры Bool, пункты, условия и тп.
    — И чесно говоря после написанного «Но а как быть если наша стратегия не подразумевает установку тейкпрофита или стоплосса?»
    предложение «воспользуемся знакомой нам функцией проверки условия if:» вводит в ступор.
    Обычно если не подразумевает, то и не указывают.
    Приходится читать до конца, чтобы потом вернуться уловить суть.

  31. Здравствуйте, подскажите, пожалуйста. Мне надо сделать так чтобы советник проверял есть ли открытые ордера и если они есть (скажем 5 по одной паре), то изменял начальные параметры. Буду очень благодарен если ответите, желательно на почту 🙂

  32. Здравствуйте, а у меня такая проблема: Скачал файл Тест, запускаю в БТ4 максимум чего я добился дак это того что он открывает мне окно «открытия ордеров» то есть как бы я не играл с настройками

    extern bool Buy=false;
    extern bool Sell=false;
    все равно в окне «открытия ордеров» приходится выбирать покупаю я или продаю. ну а до стоп лосов и профитов я не дошел. подскажите в чем может быть причина? почему ордер не открывается автоматически а лишь вызывает мне окно «открытия ордеров»? галочку «разрешить торговлю» я ставлю. ДЛЛ тоже разрешаю. Может МТ4 обновили и на нем уже этот скрипт не работает? Спасибо

  33. так , ну по галочку «ручное подтверждение мне уже сказали» но все равно ордер не отрывает. увеличиваю риск. Пишет недостаточно средств. уменьшаю риск — ни чего не происходит. Что делать?

  34. Подскажите пожалуйста скрипт который будет проверять открыл ли ордер по данной цене и в какую сторону.

  35. quote:»Сергей

    Это вопрос не по программированию, а на логику. Достаточно немного подумать и решение получается простейшим: проверять есть ли открытые ордера»

    И вот вопрос… а как можно найти необходимый ордер по мейджику?

    Просто у меня стратегия канальная с постоянным количеством ордеров и у каждого свой мэйджик. Так вот было бы замечательно при закрытии произвольного ордера по тп или лосю (без разницы)… какой именно ордер закрылся (номер magic)

  36. Получаю ошибку 130.
    И ордера не открываются аутоматычно.
    А если подтверждать вручную, все равно открываются без SL i TP.

  37. Скрипт не открывает ордера с заданными TP и SL ….но если ставлю 0 на TP и SL тогда открывает….объясните пожалуйса в чем дело..?

  38. Здравствуйте! Помогите решить вопрос с открытиями ордеров. Принцип такой:
    1. Открываем ордер на покупку (TP=20, SL=20).
    2. а) Если ордер закрывается по TP, то должен открыться снова такой же ордер на покупку.
    б) Если ордер закрылся по SL, то следующий ордер должен уже быть на продажу.
    3. Всё это дело зацикливаем (т.е. я как понимаю это должно всё работать по принципу: Если истина, то такое же действие, если ложь, то противоположное действие!

  39. Спасибо у вас прекрасная школа.
    Но я почемуто всё равно не могу открыть, серию из трёх отложенных ордеров, по какойто задонной цене.
    Кто может помогите, завтра тест…Пожалуйсто

  40. Ещё одна просьба, вапрос: Какие параметры для отложенных ордеров должны быть установлены, чтоб цена закрытия первого ордера , по ( стапу или профиту) == равнялась цене следующего ордера?

  41. Ещё одна просьба, вапрос: Какие параметры для отложенных ордеров должны быть установлены, чтоб цена закрытия первого ордера , по ( стапу или профиту) == равнялась цене, открытия следующего ордера?

    просто в предыдущем тксте пропустил слово» открытия»

  42. У меня скрипт не открывает ордера, а когда ставлю галочку с подтверждением, то просто открывается новый ордер без профита и лоса. Копировал ваш скрипт, компилировал, та же беда((( Никак не разберусь. И гугл не помогает((

Оставить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *