MQL для тебя

MQL для чайников, программирование на MQL4, MQL5

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

Рекомендуемый ДЦ - Alpari !

На предыдущих уроках по изучению языка 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

Если Вы хотите изучать язык MQL или вам понравилась данная публикация - Вы можете подписаться на получение новых материалов сайта mql4you.ru по RSS или по e-mail:

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

  1. Язык MQL - Урок 6 “эксперт Hedge Hog” | MQL для тебя 12.01.2010 в 14:24 1

    [...] форекс и добавляем параметры аналогичные нашему скрипту MT4, написанному [...]

  2. Дмитрий 12.03.2010 в 12:53 2

    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);

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

  3. Амир 16.03.2010 в 14:55 3

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

  4. palt 16.03.2010 в 20:23 4

    Для простоты можно воспользоваться классом CTrade из Trade\Trade.mqh

    Пример: OrderOpen.mq5

  5. palt 16.03.2010 в 20:48 5

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

  6. Амир 12.05.2010 в 14:22 6

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

    if(TakeProfit>0)

    {buyTP=Ask+TakeProfit*Point;

    sellTP=Bid-TakeProfit*Point;}

  7. Anton 19.06.2010 в 0:13 7

    Спасибо за этот блог. Очень интересно.

    Вопрос:

    Что значит двойное равно == ? Например:

    if(Lot==0)

  8. leo52 05.08.2010 в 16:52 8

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

  9. palt 20.08.2010 в 8:57 9

    Anton

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

  10. palt 20.08.2010 в 9:45 10

    Амир

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

  11. palt 20.08.2010 в 10:40 11

    leo52

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

  12. Night 10.10.2010 в 3:12 12

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

  13. Антон 11.10.2010 в 12:50 13

    Здравствуйте спасибо за ресурс очень необходимый, у меня возникла проблема подскажите пожалуйста как ее решить:

    "«,0,0,CLR_NONE);' — double quotes needed

    ",0,0,CLR_NONE);' — double quotes needed эти две ошибки появляются при компиляции. И еще у нас была команда алерт, куда она делась? или невнимательно что то прочитал???

  14. Антон 11.10.2010 в 16:52 14

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

  15. palt 12.10.2010 в 10:11 15

    Night

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

  16. palt 12.10.2010 в 10:19 16

    Антон

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

  17. palt 12.10.2010 в 10:23 17

    Антон

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

  18. anvar 15.10.2010 в 0:46 18

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

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

    для проверки составил простейший скрипт

    while(!IsTradeAllowed()) {Sleep(1000);Alert(IsTradeAllowed());}

    выдает каждую секунду 0

    Пожалуйста подскажите в чем дело?

  19. anvar 15.10.2010 в 1:15 19

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

  20. Pavel 06.12.2010 в 18:30 20

    Спасибо.Всё понятно и доступно!Респект!

  21. Igor 14.01.2011 в 16:23 21

    Если я не хочу устанавливать takeprofit и stopLoss

    мне нужно обнулить эти переменнные

    buyTP=0

    sellTP=0

    или ничего им не присваивать?

  22. palt 09.04.2011 в 19:54 22

    0 — это как раз и значит не устанавливать значение

  23. Григорий 25.04.2011 в 18:22 23

    Автору не просто спасибо, ему СПАСИБО!!! доходчиво, понятно, переделал немного скрипт и получил то, что нужно. На ручном скальпинге просто безумно необходимо повесить на горячую клавишу скрипт, которые делает рыночный моментальный ордер с выставленным ТР. Я в программировании полный ноль, но разобрался с ходу по объяснениям. Если кто такой же немощный, то вот упрощенный до нельзя скрипт на продажу:

    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);

    }

    //±-----------------------------------------------------------------+

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

    Счастье есть)

  24. Вячеслав 26.05.2011 в 12:26 24

    Здравствуйте! И во-первых хочу поблагодарить за всю работу по созданию и поддержанию этого замечательного сайта.

    А во-вторых такой вопрос: скрипт после того как он выполнил то что требуется — закрывается. Чтобы снова запустился автоматически на тех же условиях что и открывался изначально — что нужно сделать?

    Очень жду Вашего ответа

    С Уважением, Вячеслав

  25. palt 26.05.2011 в 20:09 25

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

  26. Вячеслав 27.05.2011 в 4:03 26

    Благодарю за ответ !

  27. Ryan 27.05.2011 в 20:03 27

    '\end_of_program' — unbalanced left parenthesis C:\Program Files\Alpari MT4\experts\scripts\test.mq4 (47, 1)

    что это означает? вылезает при компилировании

  28. palt 27.05.2011 в 20:39 28

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

  29. Grig 16.06.2011 в 13:25 29

    при компиляции выдает

    'BuySL' — variable not defined

    'BuyTP' — variable not defined

    'SellSL' — variable not defined

    'SellTP' — variable not defined

    что надо изменить в коде?

  30. Алексей 17.06.2011 в 0:38 30

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

  31. Сергей 08.07.2011 в 18:38 31

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

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

    //±-----------------------------------------------------------------+

    //| test.mq4 |

    //| Copyright © 2009, MetaQuotes Software Corp. |

    //| 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 секунд.

    Спасибо!

  32. Андрей 25.07.2011 в 23:16 32

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

  33. palt 12.08.2011 в 9:48 33

    Grig

    Компилятор сообщает что отсутствует описание переменных. Прежде чем использовать переменные их необходимо определить. Например как в статье:

    double buyTP=0; //тейкпрофит для покупки

    double sellTP=0; //тейкпрофит для продажи

    double buySL=0; //стоплосс для покупки

    double sellSL=0; //стоплосс для продажи

  34. palt 12.08.2011 в 9:51 34

    Алексей

    Вызвать функцию открытия ордера 5 раз.

  35. palt 12.08.2011 в 10:07 35

    Сергей

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

    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);

  36. palt 12.08.2011 в 10:22 36

    Андрей

    В справке по языку. Вызывается по клавише F1 в редакторе.


Оставьте отзыв


Другие публикации рубрики "MQL Школа":

  • В рубриках: MQL Школа

  • 
      Всего подписчиков:

    Рекомендуемый видеокурс форекс

    Рекомендуемые Советники Форекс для MetaTrader 4