Библиотеки: Symbol - страница 2

 
Stanislav Korotky:

Надо бы добавить что-то типа:

А то иногда нужны только свойства, а бары - нет.

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

 

Библиотека и пример использования обновлены.

Пример

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


Однако, почти всегда такая точность является излишней. Поэтому хочется обойти эту навязчивость/несовершенство MetaTrader 5 тестера. В MetaTrader 4 это сделать легко - там есть возможность поменять валюту счета прямо в тестере. MetaTrader 5 же лишен такой возможности.

Демонстрационный скрипт показывает способ обойти данное ограничение тестера - убрать ненужные вычисления. Для этого создается копия символа для бэктеста, но валюта прибыли/маржи задается равной валюте счета. Т.е. переконвертация результатов торговли не потребуется. И прибыль, фактически, будет вычисляться в пипсах, что может быть очень наглядно в некоторых ситуациях.

// Создание копии символа для ускорения Тестера
#property script_show_inputs

#include <Symbol.mqh>

void OnStart()
{
  const SYMBOL Symb("TESTER_" + _Symbol); // Создали символ

  if (Symb.IsExist()) // Если символ создан
  {
    Symb = _Symbol; // Скопировали с основного символа все свойства и баровую историю (+ тиковую, если кастомный) - клон

    // Сделали валюты символа валютой счета
    Symb.SetProperty(SYMBOL_CURRENCY_PROFIT, AccountInfoString(ACCOUNT_CURRENCY));
    Symb.SetProperty(SYMBOL_CURRENCY_MARGIN, AccountInfoString(ACCOUNT_CURRENCY));

    if (Symb.On()) // Включили в Обзор рынка
      ChartOpen(Symb.Name, PERIOD_CURRENT); // Открыли график нового символа
  }
}


Результат


Таким образом достигается бесплатное ускорение Тестера/Оптимизатора.


ЗЫ Замерил досконально на EURGBP. Выигрыш по времени получается в ~2 раза. Сделки полностью совпадают. Действительно, бесплатно!

 

Следующее замечание касается не только библиотеки.


Если нужно поменять некоторые свойства кастомного символа, то в некоторых случаях это нужно делать ДО импорта котировок.

Поэтому для надежности результата настоятельно рекомендую сначала устанавливать все свойства символа, а только потом производить импорт.

Например, если Вы хотите задать SYMBOL_TRADE_TICK_VALUE и SYMBOL_TRADE_TICK_SIZE, то это обязательно нужно сделать до импорта тиков/баров.

 

В MT5-тестере, как правило (форекс, например), лимитные ордера имеют положительное проскальзывание, что приводит к самообману (иногда даже в виде тестерных граалей на реальных тиках!)



Но есть возможность обойти эту особенность Тестера. Ниже подробная инструкция, как это сделать.


1. Если исходный символ (открытого графика) не кастомный или счет хеджевый, запустить на графике символа этот скрипт

#include <Symbol.mqh>

void OnStart()
{
  const SYMBOL Symb(_Symbol + "_Custom"); // Создали символ

  if (Symb.IsExist()) // Если символ создан
  {
    Symb = _Symbol;   // Скопировали с основного символа все свойства и баровую историю (+ тиковую, если кастомный) - клон

    if (Symb.On())    // Включили в Обзор рынка
      ChartOpen(Symb.Name, PERIOD_CURRENT); // Открыли график нового символа
  }
}


Получится такая картина



2. Если счет хеджевый (присутствует слово Hedge в заголовке окна Терминала), зайти на любой неттинговый счет (например, MetaQuotes-Demo) и перезагрузить Терминал.

3. На текущем чарте запустить уже этот скрипт

// Создание копии символа для ускорения Тестера с возможностью отключения проскальзывания лимитных ордеров
#property script_show_inputs

#include <Symbol.mqh>

input bool OrderLimitSlippage = false;

void OnStart()
{
  const SYMBOL Symb("TESTER_" + _Symbol); // Создали символ

  if (Symb.IsExist()) // Если символ создан
  {
    // https://www.mql5.com/ru/forum/212096/page2#comment_7017794
//    Symb = _Symbol; // Скопировали с основного символа все свойства и баровую историю (+ тиковую, если кастомный) - клон

    Symb.CloneProperties(); // Скопировали с основного символа все свойства

    // Сделали валюты символа валютой счета
    Symb.SetProperty(SYMBOL_CURRENCY_PROFIT, AccountInfoString(ACCOUNT_CURRENCY));
    Symb.SetProperty(SYMBOL_CURRENCY_MARGIN, AccountInfoString(ACCOUNT_CURRENCY));
    Symb.SetProperty(SYMBOL_CURRENCY_BASE, AccountInfoString(ACCOUNT_CURRENCY));
    
    int Answer = IDNO;
    
    // Убираем проскальзывания лимитных ордеров
    // https://www.mql5.com/ru/forum/212096/page2#comment_7018318
    if (!OrderLimitSlippage &&
        (((ENUM_ACCOUNT_MARGIN_MODE)AccountInfoInteger(ACCOUNT_MARGIN_MODE) != ACCOUNT_MARGIN_MODE_RETAIL_HEDGING) ||
        ((Answer = MessageBox("You will need to change the account type to netting.\nDo you agree to disable limit order slips?", __FILE__, MB_YESNOCANCEL | MB_ICONQUESTION)) == IDYES)))
    {
      Symb.SetProperty(SYMBOL_TRADE_EXEMODE, SYMBOL_TRADE_EXECUTION_EXCHANGE);
      Symb.SetProperty(SYMBOL_TRADE_CALC_MODE, SYMBOL_CALC_MODE_EXCH_FUTURES);
      
      // Для расчета профита
      Symb.SetProperty(SYMBOL_TRADE_TICK_VALUE, 1);
      Symb.SetProperty(SYMBOL_TRADE_TICK_SIZE, Symb.GetProperty(SYMBOL_POINT));
    }
    
    if ((Answer != IDCANCEL) && (Symb.CloneHistory() > 0) && Symb.On()) // Скопировали с основного символа баровую историю (+ тиковую, если кастомный)
      ChartOpen(Symb.Name, PERIOD_CURRENT); // Открыли график нового символа      
  }
}



3. Выбираем в Тестере полученный кастомный символ


Теперь лимитные ордера скользить не будут!

 

Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий

Ошибки, баги, вопросы

fxsaber, 2018.02.14 14:41

Гадкий баг не Терминала, а Платформы MT5
#include <MT4Orders.mqh> // https://www.mql5.com/ru/code/16006

#define Bid SymbolInfoDouble(_Symbol, SYMBOL_BID)
#define Ask SymbolInfoDouble(_Symbol, SYMBOL_ASK)

void OnStart()
{
  OrderSend(_Symbol, OP_BUY, 1, Ask, 100, 0, Bid);
  
//  OrderSend(_Symbol, OP_BUYLIMIT, 1, Ask, 100, 0, 0);
}

Запускаем на MQ-Demo на каком-нибудь медленно двигающемся символе. Например, EURHUF.

Скрипт открывает BUY-позицию с TP = Bid. Т.е. позиция должна сразу закрыться. Но TP будет проверяться на соответствие условию акцептирования только на следующем тике!

Никакого мгновенного закрытия позиции не произойдет, пока не придет новый тик. Более того, если следующий у следующего тика будет Bid < TP, то TP так и останется без акцепта.


Это же касается и лимитных ордеров (закомментированная строка). В Тестере - аналогичная ситуация.

По выделенному нужно сказать, т.к. в предыдущем посте есть такое

Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий

Библиотеки: Symbol

fxsaber, 2018.04.06 09:21

2. Если счет хеджевый (присутствует слово Hedge в заголовке окна Терминала), зайти на любой неттинговый счет (например, MetaQuotes-Demo) и перезагрузить Терминал.

и не все заметят, что лимитные ордера по текущей цене на биржевых символах Неттинг-счетов будут исполняться (и в Тестере) сразу, не дожидаясь следующего тика.


Обратите внимание, важен не просто биржевой символ, но и  неттинговый счет. Например, можно взять MOEX-символ на Hedge-MQ-Demo, но он не будет исполняться так (и в Тестере), как на том же Netting-MQ-Demo.

Это одна из причин, почему бэктесты на тех же полностью идентичных MOEX-символах могут отличаться, в зависимости от типа счета.


ЗЫ Сам с собой разговариваю...

 
fxsaber:

ЗЫ Сам с собой разговариваю...

Да нет, просто дополнить нечего.

Жаль, что для реализации нормального срабатывания ордеров нужно плясать с бубнами.

 
Andrey Khatimlianskii:

Жаль, что для реализации нормального срабатывания ордеров нужно плясать с бубнами.

Изменил инструкцию, значительно упростив пляски. Например, на неттинге все делается в одно нажатие - запуск скрипта.

 

Применил простой фильтр к реальным тикам, который выбрасывает > 90% информации в самом легком варианте. Чем сильнее фильтр, тем грубее результат бэктеста.

Но было интересно, как самый слабый фильтр влияет на результат и скорость.


Качество.

Было

final balance 10007242.00 EUR
TESTER_Censored,M1: 6589567 ticks, 60353 bars generated. Environment synchronized in 0:00:00.031. Test passed in 0:00:05.101 (including ticks preprocessing 0:00:00.874).
TESTER_Censored,M1: total time from login to stop testing 0:00:05.132 (including 0:00:00.031 for history data synchronization)
476 Mb memory used including 27 Mb of history data, 192 Mb of tick data


Стало

final balance 10007246.00 EUR
FILTER_Censored,M1: 402622 ticks, 50887 bars generated. Environment synchronized in 0:00:00.030. Test passed in 0:00:00.516 (including ticks preprocessing 0:00:00.078).
FILTER_Censored,M1: total time from login to stop testing 0:00:00.546 (including 0:00:00.030 for history data synchronization)
314 Mb memory used including 27 Mb of history data, 64 Mb of tick data


Скорость

Было

OnTesterInit
i = 0 Pass = 0 OnTester = 3.881 s.: Count = 6589567, 1697904.4 unit/sec, Agent = C:\Program Files\Alpari Limited MT5\Tester\Agent-127.0.0.1-3000 build = 1795
i = 1 Pass = 1 OnTester = 3.893 s.: Count = 6589567, 1692670.7 unit/sec, Agent = C:\Program Files\Alpari Limited MT5\Tester\Agent-127.0.0.1-3000 build = 1795
i = 2 Pass = 2 OnTester = 3.898 s.: Count = 6589567, 1690499.5 unit/sec, Agent = C:\Program Files\Alpari Limited MT5\Tester\Agent-127.0.0.1-3000 build = 1795
i = 3 Pass = 3 OnTester = 3.842 s.: Count = 6589567, 1715139.8 unit/sec, Agent = C:\Program Files\Alpari Limited MT5\Tester\Agent-127.0.0.1-3000 build = 1795
i = 4 Pass = 4 OnTester = 3.912 s.: Count = 6589567, 1684449.6 unit/sec, Agent = C:\Program Files\Alpari Limited MT5\Tester\Agent-127.0.0.1-3000 build = 1795
iMin = 3 Results[iMin] = 3.842s.
iMax = 4 Results[iMax] = 3.912s.
Amount = 5 Mean = 3.885 s. - 84.80%
OnTesterDeinit


Стало

OnTesterInit
i = 0 Pass = 0 OnTester = 0.264 s.: Count = 402622, 1525083.3 unit/sec, Agent = C:\Program Files\Alpari Limited MT5\Tester\Agent-127.0.0.1-3000 build = 1795
i = 1 Pass = 1 OnTester = 0.264 s.: Count = 402622, 1525083.3 unit/sec, Agent = C:\Program Files\Alpari Limited MT5\Tester\Agent-127.0.0.1-3000 build = 1795
i = 2 Pass = 2 OnTester = 0.264 s.: Count = 402622, 1525083.3 unit/sec, Agent = C:\Program Files\Alpari Limited MT5\Tester\Agent-127.0.0.1-3000 build = 1795
i = 3 Pass = 3 OnTester = 0.266 s.: Count = 402622, 1513616.5 unit/sec, Agent = C:\Program Files\Alpari Limited MT5\Tester\Agent-127.0.0.1-3000 build = 1795
i = 4 Pass = 4 OnTester = 0.306 s.: Count = 402622, 1315758.2 unit/sec, Agent = C:\Program Files\Alpari Limited MT5\Tester\Agent-127.0.0.1-3000 build = 1795
iMin = 0 Results[iMin] = 0.264s.
iMax = 4 Results[iMax] = 0.306s.
Amount = 5 Mean = 0.273 s. - 29.28%
OnTesterDeinit


Итог

По реальным тикам количество тиков уменьшилось в 16 раз (самый легкий фильтр), скорость Оптимизации выросла в 14 раз, качество не пострадало совсем (анализ, что сюда не вошел). Конечно, подобное можно проделать только при написании ТС определенным образом. В частности, с отсутствием анализа баров.

Предыдущее бесплатное универсальное ускорение давало рост лишь в два раза. Текущее - тоже бесплатное (качество не страдает), но менее универсальное. Однако, отдача более, чем на порядок. Теперь Оптимизирую ТС только так. Не ошибся.


ЗЫ

Заодно короткая проверка и этой реализации (всего лишь баровый спред посчитал иначе)

Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий

Скрипты: ThirdPartyTicks

Automated-Trading, 2018.03.16 09:35

Баровая история создается с учетом минимальных потерь качества при переходе от режима тестирования "Каждый тик на основе реальных тиков" к "Только цены открытия" - ТС на лимитных ордерах;

Сравниваются два режима: "Все тики" и "OHLC M1".


Все тики

final balance 10006150.00 EUR
TESTER4_Censored,M1: 6576734 ticks, 60353 bars generated. Test passed in 0:00:04.587 (including ticks preprocessing 0:00:00.343).
394 Mb memory used including 27 Mb of history data, 128 Mb of tick data


OHLC M1

final balance 10006119.00 EUR
TESTER_Censored,M1: 240366 ticks, 60353 bars generated. Test passed in 0:00:00.359 (including ticks preprocessing 0:00:00.031).
306 Mb memory used including 27 Mb of history data, 64 Mb of tick data


Качество бэктеста одинаковое, производительность второго варианта в одиночном прогоне в 12 раз выше.

 

Для не программиста, эти скрипты нужно вписать в программу эксперта?

Очень заманчиво ускорить оптимизацию в 12 раз.

 Будет ли такое ускорение при оптимизации по точкам открытия?

 
Aleksey Panfilov:

Для не программиста, эти скрипты нужно вписать в программу эксперта?

Очень заманчиво ускорить оптимизацию в 12 раз.

Будет ли такое ускорение при оптимизации по точкам открытия?

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