Советники: Программирование на MQL5 для трейдеров — исходные коды из книги. Часть 7

 

Программирование на MQL5 для трейдеров — исходные коды из книги. Часть 7:

В заключительной седьмой части книги рассматриваются расширенные возможности MQL5 API, которые пригодятся при разработке программ для MetaTrader 5. Некоторые из них — пользовательские финансовые инструменты и встроенный экономический календарь, а другие — универсальные технологии, такие как сетевые функции, базы данных и криптография.

Программирование на MQL5 для трейдеров — исходные коды из книги. Часть 7

Автор: MetaQuotes

 
Хорошие учебные ресурсы
 
Узнать
 
Здесь представлены небольшие исправления и улучшения для кэша и фильтра календаря.
MQL5 Book: Advanced language tools / Economic calendar / Transferring calendar database to tester
MQL5 Book: Advanced language tools / Economic calendar / Transferring calendar database to tester
  • www.mql5.com
The calendar is available for MQL programs only online, and therefore testing news trading strategies poses some difficulties. One of the solutions...
Файлы:
 

Подскажите, это ошибка или я чего то не понимаю?

Файл MarginProfitMeter.mqh

// Convert amount of 'current' money into 'account' money
bool Convert(const string current, const string account,
             const bool ask, double &margin, const datetime moment = 0)
  {
   string rate;
   int dir = FindExchangeRate(current, account, rate);
   if(dir == +1)
     {
      margin *= moment == 0 ?
                SymbolInfoDouble(rate, ask ? SYMBOL_BID : SYMBOL_ASK) :
                GetHistoricPrice(rate, moment, ask);
     }
   else
      if(dir == -1)
        {
         margin /= moment == 0 ?
                   SymbolInfoDouble(rate, ask ? SYMBOL_ASK : SYMBOL_BID) :
                   GetHistoricPrice(rate, moment, ask);
        }
      else
        {
         static bool once = false;
         if(!once)
           {
            Print("Can't convert ", current, " -> ", account);
            once = true;
           }
        }
   return true;
  }

На ноль вроде нельзя делить?


Также, этот метод должен возвращать маржу, а возвращает цену. Я понимаю, что где то эту цену надо умножить на contract size, а где это правильнее сделать не пойму.

В этой функции дописать или там откуда мы эту функцию вызываем?

 
Aleksandr Slavskii #:

Подскажите, это ошибка или я чего то не понимаю?

Файл MarginProfitMeter.mqh

На ноль вроде нельзя делить?

Действительно, нельзя. 

margin /= moment == 0 ?
                   SymbolInfoDouble(rate, ask ? SYMBOL_ASK : SYMBOL_BID) :
                   GetHistoricPrice(rate, moment, ask);

Тут после символа деления с присваиванием "/=" идёт тернарный оператор. Т.е. если momet==0, то:

margin /= SymbolInfoDouble(rate, ask ? SYMBOL_ASK : SYMBOL_BID)

иначе:

margin /= GetHistoricPrice(rate, moment, ask)

Но всё равно добавил бы проверку на ноль от обеих функций...


Также, этот метод должен возвращать маржу, а возвращает цену. Я понимаю, что где то эту цену надо умножить на contract size, а где это правильнее сделать не пойму...

Судя по описанию

// Convert amount of 'current' money into 'account' money

метод конвертирует текущие деньги (валюту) в деньги (валюту) депозита. А судя по коду, метод конвертирует маржу в валюту депозита.

В случае успеха метод вовзращает true. И также рассчитает новый, скорректированный, размер маржи, сохранив её в переменную margin. Она идёт как параметр по ссылке:

double &margin

Поэтому можно получить её как результат вычисления.

 
Denis Kirichenko #:

Действительно, нельзя. 

Тут после символа деления с присваиванием "/=" идёт тернарный оператор. Т.е. если momet==0, то:

Ага. Точно, тернарный оператор. Притомился с утра, тупить начал.


Denis Kirichenko #:

Судя по описанию

метод конвертирует текущие деньги (валюту) в деньги (валюту) депозита. А судя по коду, метод конвертирует маржу в валюту депозита.

Нет, тут тоже теперь всё правильно.


Извиняюсь, это я немного напутал в коде.


Толку от этого всё равно мало, так как в итоге всё равно маржу считает не правильно, если объём больше трёх.

EURUSD; margin = 24668.8  //  OrderCalcMargin()
EURUSD; margin = 10889.599999999999 // MarginProfitMeter.mqh 

Расчет маржи для десяти контрактов.

 
Denis Kirichenko #:
margin /= moment == 0 ?                    SymbolInfoDouble(rate, ask ? SYMBOL_ASK : SYMBOL_BID) :                    GetHistoricPrice(rate, moment, ask);

Немного не так. Условие (margin /= moment)==0 и дальше тернарный оператор…

 
Alexey Viktorov #:

Немного не так. Условие (margin /= moment)==0 и дальше тернарный оператор…

Да вот как-то ни разу не согласен. Попробуйте для начала выполнить это условие:

double margin = 1.5;
datetime moment = 0;
margin /= moment;

Тут тогда делятся ужи на ежей, что само по себе уже сомнительно.

И у операций присваивания очень низкий приоритет, ниже только у зпт.

Ещё и компилятор злится:

possible loss of data due to type conversion from 'datetime' to 'double'

Да и логика функции - конвертация маржи. Насколько понимаю, moment = 0 - это сейчас.  Тогда:

margin /= moment == 0 ?
                SymbolInfoDouble(rate, ask ? SYMBOL_ASK : SYMBOL_BID) :
                GetHistoricPrice(rate, moment, ask);

означает, что если это сейчас, то запрашиваем текущую цену. А если это в прошлом, то обращаемся к историческим ценам. И получив нужную цену, в самом конце делим величину маржи на эту цену с присваиванием... а с Вашей логикой, получается, что при moment = 0, мы получим не конвертацию маржи, а просто рыночную цену или цену из прошлого...


Вообще для учебника конечно лучше было бы в скобках писать:

margin /= (moment == 0) ?
                   SymbolInfoDouble(rate, ask ? SYMBOL_ASK : SYMBOL_BID) :
                   GetHistoricPrice(rate, moment, ask);
 
Denis Kirichenko #:

Да вот как-то ни разу не согласен. Попробуйте для начала выполнить это условие:

Тут тогда делятся ужи на ежей, что само по себе уже сомнительно.

И у операций присваивания очень низкий приоритет, ниже только у зпт.

Ещё и компилятор злится:

Да и логика функции - конвертация маржи. Насколько понимаю, moment = 0 - это сейчас.  Тогда:

означает, что если это сейчас, то запрашиваем текущую цену. А если это в прошлом, то обращаемся к историческим ценам. И получив нужную цену, в самом конце делим величину маржи на эту цену с присваиванием... а с Вашей логикой, получается, что при moment = 0, мы получим не конвертацию маржи, а просто рыночную цену или цену из прошлого...


Вообще для учебника конечно лучше было бы в скобках писать:

Убедительно. Согласен, был невнимателен. Только если писать для учебника и так чтобы было понятно даже мне, то лучше так

margin /= (moment == 0 ?
                   SymbolInfoDouble(rate, ask ? SYMBOL_ASK : SYMBOL_BID) :
                   GetHistoricPrice(rate, moment, ask));