+321 123 4567
info@test.com
My Account
Forex Lab
  • Главная
  • Софт
  • Стратегии
  • Брокер
  • Блог
  • Item A
    • Sub item A1
    • Sub item A2
  • Item B
    • Sub item B1
    • Sub item B2
  • Item C
    • Sub item C1
    • Sub item C2

Написание советника для торговли

В программировании советников как и в любом деле главное идея, а реализация может быть разной.
На каком-то форуме просили сделать советника для торговли на новостях, что бы он в определенное время выставлял два стоп ордера на заданном от цены расстоянии. После срабатывания одного второй удаляется. Если за 30 минут после открытия не сработал ни один ордер, удаляем оба. Это будет техзадание на разработку советника.

Открываем MetaEditor, редактор языка MetaQuotes Language 4 (MQL4).

В меню жмем Файл/создать, выбираем советник. В следующем окне даем нашему Граалю имя, «автор» и «ссылка» это что бы все знали кто сотворил это чудо и где вас можно найти. Ниже можно выставить переменные которые будут входными параметрами вашего советника. Зададим несколько свойств, Delta – расстояние от цены для выставления стоп ордеров, стоплос и тейкпрофит. Кнопка добавить, имя Delta (в MQL4 регистр имеет значение, Delta и delta это разные переменные), тип int – целые числа и параметр который эксперт будет иметь по умолчанию.

Написание советника для торговли
//+------------------------------------------------------------------+
//| TradeOnNews.mq4                                                  |
//| Copyright © 2008, MetaQuotes Software Corp.                      |
//|                                         |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2008, MetaQuotes Software Corp."
#property link "http://www.metaquotes.net"

//---- input parameters
extern int Delta=15;
extern int StopLoss=20;
extern int TakeProfit=30;
//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
 {
//----

//----
  return(0); 
 }
//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
 {
//----

//----
  return(0);
 }
//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
 {
//----

//----
  return(0);
 }
//+------------------------------------------------------------------+

Тело функции находится между открывающей и закрывающей скобками {}.

А вот код советника сделанного по нашему техзаданию.

//+------------------------------------------------------------------+
//|                                                  TradeOnNews.mq4 |
//|                      Copyright © 2008, MetaQuotes Software Corp. |
//|                                         |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2008, MetaQuotes Software Corp."
#property link      "http://www.metaquotes.net"

//---- input parameters
extern string StartTime      = "15:30";  // время открытия маркет ордера (по времени MetaTrader)
extern string CloseTime      = "16:00";  // Время закрытия ордеров
extern int    Delta          = 15;  // расстояние от цены для выставления стоп ордеров
extern int    StopLoss       = 20;
extern int    TakeProfit     = 30;
extern double Lot            = 0.1;

int day, EP;
string Symb;

double   Mas_Ord[31][13];   // Массив ордеров
int      Mas_Tip[6];            // Массив колич. ордеров всех типов // [] тип орд: 0=B,1=S,2=BL,3=SL,4=BS,5=SS
int      Mas_Tip_T[6];          // Массив колич. ордеров всех типов - открытых сегодня
//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
  {
   Symb = Symbol();    // Название фин.инстр.
   return(0);
  }
//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
  {
   int total = OrdersTotal(); // сколько всего ордеров открыто
   Orders(); // вызываем функцию учета ордеров
   if(total > 1) // если ордеров больше одного - в нашем случае два
    {
     for(int i = 0; i < total; i ++)
      {
       if(OrderSelect(i, SELECT_BY_POS) == false) continue; // если ордер не выбран, возвращаемся в начало цыкла
       if(Mas_Tip[0] > 0                 // если ордеров бай больше нуля - есть бай ордер
          && OrderType() == OP_SELLSTOP) // и есть селстоп
          OrderDelete(OrderTicket());    // удаляем селстоп

       if(Mas_Tip[1] > 0                // если ордеров сел больше нуля - есть сел ордер
          && OrderType() == OP_BUYSTOP) // и есть байстоп
          OrderDelete(OrderTicket());   // удаляем байстоп
      }
    }
   if(total == 1 && Mas_Tip[4] > 0) // если открыт один ордер и этот ордер байстоп
    {
     Expiration(); // вызываем функцию Expiration для расчета продолжительности жизни отложеного ордера
     OrderSend(Symb,OP_SELLSTOP,Lot,Bid-Delta*Point,3,Bid-Delta*Point + StopLoss*Point,Bid-Delta*Point - TakeProfit*Point,NULL,0,EP,Red); // открываем селстоп
    }
   if((total == 0) && (TimeCurrent() > StrToTime(StartTime)) && (TimeCurrent() < StrToTime(StartTime) + 60))
    { // если нет ни одного открытого ордера и текущее время перевалило за время открытия и текущее время меньше за время открытия плюс 60 секунд
     Expiration(); // вызываем функцию Expiration для расчета продолжительности жизни отложеного ордера
     OrderSend(Symb,OP_BUYSTOP,Lot,Ask+Delta*Point,3,Ask+Delta*Point - StopLoss*Point,Ask+Delta*Point + TakeProfit*Point,NULL,0,EP,Blue); //открываем байстоп
    }
   return(0);
  }
//+------------------------------------------------------------------+
// заполняем масив даными об ордерах - сколько, каких и тд.          |
//+------------------------------------------------------------------+
int Orders()//Інформація про ордера... сколько, каких, цена открытия, стоплос и тд.
 {
  int Qnt = 0;                          // Счётчик количества ордеров
  Qnt = 0;                              // Обнуление счётчика ордеров
  ArrayInitialize(Mas_Ord,0);           // Обнуление массива
  ArrayInitialize(Mas_Tip,0);           // Обнуление массива
  ArrayInitialize(Mas_Tip_T,0);         // Обнуление массива
  for(int i = 0; i < OrdersTotal(); i++)// По рыночн. и отлож. ордерам
   {
    if((OrderSelect(i,SELECT_BY_POS) == true) && (OrderSymbol() == Symb))//Если есть следующ.  //.. и наша вал.пара
     {
      Qnt++;                                        // Колич. ордеров
      Mas_Ord[Qnt][1] = OrderOpenPrice();           // Курс открытия орд
      Mas_Ord[Qnt][2] = OrderStopLoss();            // Курс SL
      Mas_Ord[Qnt][3] = OrderTakeProfit();          // Курс ТР
      Mas_Ord[Qnt][4] = OrderTicket();              // Номер ордера
      Mas_Ord[Qnt][5] = OrderLots();                // Количество лотов
      Mas_Tip[OrderType()]++;                       // Кол. ордеров типа
      Mas_Ord[Qnt][6] = OrderType();                // Тип ордера
      Mas_Ord[Qnt][7] = OrderMagicNumber();         // Магическое число
      if(OrderComment() == "") Mas_Ord[Qnt][8] = 0; // Если нет коммент
       else Mas_Ord[Qnt][8] = 1;                    // Если есть коммент
      Mas_Ord[Qnt][9] = OrderOpenTime();            // Время открвтия ордера
      Mas_Ord[Qnt][10] = OrderCloseTime();          // Время закрытия ордера
      Mas_Ord[Qnt][11] = OrderExpiration();         // Возвращает дату истечения для выбранного отложенного ордера.
      if(day == TimeDayOfYear(OrderOpenTime()))     // работа с ордером ...
       {
        Mas_Tip_T[OrderType()]++;                   // Кол. ордеров типа... открытых сегодня
       }
     }
   }
  Mas_Ord[0][0] = Qnt;                         // Колич. ордеров
  return;
 }
//+------------------------------------------------------------------+
//                                                                   |
//+------------------------------------------------------------------+
int Expiration()
 { // если время открытия больше чем время закрытия - додаем одни сутки в секундах(60*60*24)
  if(StrToTime(StartTime) > StrToTime(CloseTime)) EP = 60*60*24 + StrToTime(CloseTime);
   else EP = StrToTime(CloseTime); // если время открытия не больше чем время закрытия - не додаем
 }
//+------------------------------------------------------------------+

Рассмотрим код эксперта подробнее.
Добавим еще пару переменных.

extern string    StartTime    = "15:30";  // время открытия маркет ордера (по времени MetaTrader)
extern string   CloseTime    = "16:00";  // Время закрытия ордеров
extern int       Delta=15;
extern int       StopLoss=20;
extern int       TakeProfit=30;
extern double Lot            = 0.1;  //размер лота

Зарезервированное слово «extern» означает что эта будет видна в настройках советника. string – значение строкового типа, строки всегда берутся в двойные кавычки. Переменные типа double – числа с дробью.
Ниже объявим несколько глобальных переменных, так как они объявлены вне функций, их можно использовать в любой функции. При вызове функции данные в этих переменных сохраняются.

int day, EP;
string Symb;

double   Mas_Ord[31][13];   // Массив ордеров
int      Mas_Tip[6];            // Массив колич. ордеров всех типов // [] тип орд: 0=B,1=S,2=BL,3=SL,4=BS,5=SS
int      Mas_Tip_T[6];          // Массив колич. ордеров всех типов - открытых сегодня

Если переменная объявлена внутри функции, использовать ее можно только в ней и при вызове функции данная переменная обнуляется.
В функции init() – узнаем на какой график кинули советника(какая валютная пара) и запоминаем в переменой Symb.

Symb = Symbol();// Название фин.инстр. в переменой Symb запоминаем валютную пару по которой будем торговать.

Алгоритм функции start() я строю по принципу реальной торговли. Сначала проверяем есть ли открытые ордера и если пора закрывать, то закрываем. Потом смотрим нет ли чего модифицировать. Если все что нужно закрыть, закрыто. Все что нужно модифицировать, модифицировано. Проверяем нет ли условий по нашей ТС для покупки или продажи.
Узнаем сколько у нас открытых ордеров – вызываем функцию OrdersTotal(). OrdersTotal() возвращает общее количество открытых ордеров всех типов.

int total = OrdersTotal(); // сколько всего ордеров открыто

Запоминаем в переменой total количество открытых ордеров.

Немного теории.
Операции отношения: == — равно, != — не равно, > — больше, < — меньше, >= — больше или равно, <= — меньше или равно.
Логические отношения: ! – не, || — или, && — и.

Оператор if (если): if(total == 0) action; – если(ордеров = 0) действие; — если(выражение) { действие 1; действие 2; действие n;}. Если (выражение истинно) выполняется первый оператор после прямых скобок (), если (выражение ложно) оператор после прямых скобок() пропускается и выполняется следующий. Если нужно выполнить больше одного оператора помещаем их в фигурные скобки {}. К оператору if можно добавить часть else:
if(total == 0) action 1; — если (выражение истинно) выполняется действие 1; — если (выражение ложно)
else action 2; — выполняется действие 2;
вариант с несколькими операторами:

if(выражение)
 {   // если истинно
  действие 1;
  действие 2;
 действие n;
}
 else
  {  // если ложно
    действие 3;
    действие 4;
    действие n;
  }

Вернемся к советнику: если еще не открыт ни один ордер и наступило время торговли

Написание советника для торговли

TimeCurrent() – возвращает последнее известное время сервера (время последней котировки) в виде количества секунд прошедших после 00:00 1 января 1970 года.
StrToTime(string) – преобразование строки, содержащей время или дату в формате ”yyyy.mm.dd[hh:mi]”, в число типа datetime (количество секунд, прошедших с 01.01.1970).
Если все условия истинны – выполняется тело оператора if.

 Expiration(); // вызываем функцию Expiration для расчета продолжительности жизни отложеного ордера

int Expiration()
 { // если время открытия больше чем время закрытия - додаем одни сутки в секундах(60*60*24)
  if(StrToTime(StartTime) > StrToTime(CloseTime)) EP = 60*60*24 + StrToTime(CloseTime);
    else EP = StrToTime(CloseTime); // если время открытия не больше чем время закрытия - не додаем
 }

Функция Expiration() записывает в переменную ЕР время закрытия отложенного ордера. После отработки кода функции Expiration(), нас возвращает назад в функцию start(), в тот же место строкой ниже. И запускается торговая функция OrderSend которая выставляет ордер байстоп.

Написание советника для торговли

Point – размер пункта текущей валютной пары (например EUR/USD 0.0001). Delta*Point = 15*0.0001 = 0.0015.
Ордер выставлен, конец функции start(). С приходом нового тика функция start() запускается сначала. Снова узнаем сколько открытых ордеров.
int total = OrdersTotal();
в переменную total теперь записывается 1 (есть один открытый ордер).
Вызывается функция Orders();. В которой всевозможная информация об открытых ордерах заносится в массив.
Массив – набор переменных одного типа, имеющих общее название.

Написание советника для торговли

Одномерный массив Mas_Tip[6] содержит 7 ячеек. Индекс первого элемента массива 0, если в массиве 7 элементов – индекс остатнего элемента будет 6.

Написание советника для торговли

Двухмерный массив Mas[9][9]. При обращении к двухмерному массиву (помещению или извлечению данных), указывается два индекса. На пересечении этих двух индексов находится нужная нам ячейка.

i++  // это значит i увеличить на 1, это выражение можно записать и так i = i + 1;
i--  // уменьшить на 1, тот же результат получим если запишем i = i – 1;

for(выражение1; выражение2; выражение3) оператор; // for – оператор цикла.
for(int i = 0; i < 5; i++) «оператор»;
выражение1 выполняется один раз при старте цикла, переменой i задается начальное значение. Проверяется выражение2 если оно ложно (равно или больше 5), «оператор» не выполняется цикл заканчивается и управление передается следующему оператору.
Если выражение2 истинно (i меньше 5), выполняется «оператор» и выражение3. Снова проверяется выражение2, цикл повторяется до тех пор пока выражение2 не станет ложно. Нужно быть внимательным при написании кода цикла, может быть ситуация когда выражение2 никогда не станет ложным, тогда цикл никогда не закончится (вечный цикл) и программа зависнет.

Написание советника для торговли

Вернемся в советник, функция Orders(). С помощью цикла перебираем все наши открытые ордера и заносим их данные в массив. Что бы получить информацию о ордере нужно сначала его выбрать с помощью функции OrderSelect.
После окончании работы функции Orders(), возвращаемся в start(). У нас был открыт один байстоп ордер, проверяем условия для открытия второго ордера.

Написание советника для торговли

Если открыт только один ордер (total == 1) и этот ордер байстоп (Mas_Tip[4] > 0), открываем второй (селстоп).
И остатний этап. Теперь имеем два ордера (total > 1). С каждым тиком проверяем не сработал ли отложенный ордер. Если сработал байстоп и преобразовался в бай (Mas_Tip[0] > 0), удаляем селстоп — OrderDelete(OrderTicket());.
Если сработал селстоп и преобразовался в сел (Mas_Tip[1] > 0), удаляем байстоп — OrderDelete(OrderTicket());.

Исходник: TradeOnNews 0

Важно! Этот советник не годится для торговле на реале. В нем много «подводных камней», которые необходимо устранить.

Написание элементарного индикатора — https://forexlab.ru/mql-writing-basic-indicator/

Предыдущая запись
Написание элементарного индикатора
Следующая запись
Волшебство в MQL4

Свежие записи

  • Как работают биржи: классификация, виды, особенности
  • Moving Average: описание, настройка, стратегии
  • Что такое Non farm payrolls
  • HQBroker: мошенники или честный брокер
  • Торговля на бирже для начинающих: полный гайд

Рубрики

  • CFD (2)
  • FOREX (14)
  • Meta Trader 5 (6)
  • MetaTrader 4 (13)
  • Price Action (9)
  • QUIK (2)
  • Акции (9)
  • Бинарные опционы (11)
  • Биржи (1)
  • Брокеры (5)
  • Волновой анализ (7)
  • Графический анализ (28)
  • Индикаторный анализ (36)
  • Криптовалюты (2)
  • Методы управления капиталом (11)
  • Новости проекта Forex Lab (2)
  • Объемы (10)
  • Основы торговли (7)
  • Подкаст (7)
  • Полезное (3)
  • Программирование (20)
  • Психология трейдинга (25)
  • Свечной анализ (2)
  • Скальпинг (1)
  • Технический анализ (19)
  • Торговые платформы (26)
  • Торговые стратегии и системы (73)
  • Фибо (11)
  • Фондовый рынок (27)
  • Фракталы (4)
  • Фундаментальный анализ (19)
  • Фьючерсы (20)

Представленная информация не является индивидуальной инвестиционной рекомендацией, ни при каких условиях, в том числе при внешнем совпадении ее содержания с требованиями нормативно-правовых актов, предъявляемых к индивидуальной инвестиционной рекомендации. Любое сходство представленной информации с индивидуальной инвестиционной рекомендацией является случайным.
Какие либо из указанных финансовых инструментов или операций могут не соответствовать Вашему инвестиционному профилю.
Упомянутые в представленном сообщении операции и (или) финансовые инструменты ни при каких обстоятельствах не гарантируют доход, на который Вы возможно рассчитываете при условии использования предоставленной информации для принятия инвестиционных решений.
Информационный портал ForexLab не несет ответственности за возможные убытки инвестора в случае совершения операций, либо инвестирования в финансовые инструменты, упомянутые в представленной информации.
Во всех случаях определение соответствия финансового инструмента либо операции инвестиционным целям, инвестиционному горизонту и толерантности к риску является задачей инвестора.
Не является образовательной деятельностью. Не сопровождается выдачей документов об образовании и (или) квалификации. При полном или частичном использовании материалов сайта ссылка на https://forexlab.ru/ обязательна.

© 2008-2020 Forex Lab

  • Главная
  • Политика
  • Авторские права
  • Согласие
  • Риски
  • Оферта