Библиотеки: Virtual - страница 48

 
fxsaber #:

Нет такой функции. Более того, непонятно, зачем она может быть нужна.

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


Добавил код расчета свопов и проверил время - потребляет примерно 0,3 секунды или 3%. Расчет можно ускорить, если не для каждого ордера считывать эти переменные из терминала, а где то один раз их  считать и потом использовать из переменных.  Нужен какой то VIRTUAL::OnInit() для этого

             datetime RolloverTime=((datetime)ORDER_SWAP % 86400);//86400 sec in day
             double SwapShort=::SymbolInfoDouble(this.Orders[i].GetSymbol(), SYMBOL_SWAP_SHORT), SwapLong=::SymbolInfoDouble(this.Orders[i].GetSymbol(), SYMBOL_SWAP_LONG);
             int Rollover3Days = (int)::SymbolInfoInteger(this.Orders[i].GetSymbol(), SYMBOL_SWAP_ROLLOVER3DAYS);
Расчет комиссий примерно 0,25 сек или 2,5%.
 
Forester #:

потребляет примерно 0,3 секунды или 3%.

Расчет комиссий примерно 0,25 сек или 2,5%.

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

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

fxsaber, 2023.11.23 16:43

Оставляю на будущее советник для замера производительности.

Надо будет посмотреть. Вопрос лишь в целесообразности. Используют в качестве тестера один-два человека.
 
Forester #:

Есть предложение по ускорению.

Свежая история про ускорение. 20 ядер делали оптимизацию. Все агенты посчитали свою пакет заданий и ждут только одного, который выполнил 87/88 заданий и висит долго. Надо было разобраться, почему висит.


Пока висел, скопировал opt-файл. Когда отвис - снова скопировал. Получил два opt-файла. Второй оказался на 233 (а не 88) прохода длиннее. Вытащил оттуда настройки этих проходов и посмотрел на домашней машине, будут ли тормозить в одиночных прогонах. Взял на пробу самый последний в записи, и он оказался тормозным: половину тиков прогнал за 20 секунд, а вторую половину тиков не дождаться, замедление с каждым тиком происходит.


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

Сделал такую замену.

  void AddHistoryOrder( const ORDER_BASE &Order )
  {
    if (this.AmountHistoryOrders == this.ReserveHistoryOrders)
//      this.ReserveHistoryOrders = ::ArrayResize(this.HistoryOrders, this.ReserveHistoryOrders + RESERVE_HISTORY_ORDERS);
      this.ReserveHistoryOrders = ::ArrayResize(this.HistoryOrders, ::MathMax(RESERVE_HISTORY_ORDERS, this.ReserveHistoryOrders << 1));

И сразу исчезли тормоза. Как оказалось, было 2.5 миллиона закрытых позиций. Virtual их быстро проглотил после этой замены. Рекомендую подправить у себя.

 
Чаще всего даже не подозреваем, сколько советник чего вызывает. Поэтому вставил счетчик. Такой результат получил.
       [Count]                                   [Name]
[ 0]         2 "VIRTUAL::VirtualAccountInfoDouble"     
[ 1]   6921742 "STRING::operator="                     
[ 2]  27253504 "ORDERS::NewTick"                       
[ 3]  44722712 "ORDERS::Check"                         
[ 4]  48183581 "ORDERS::IsChange"                      
[ 5]   3460870 "ORDER::ToClose"                        
[ 6] 292123692 "ORDER::IsClosed"                       
[ 7]  24390951 "ORDER_BASE::IsPosition"                
[ 8]   3460870 "ORDER::IsNotNull"                      
[ 9]   3460870 "ORDER::ToHistory"                      
[10]         2 "VIRTUAL::SelectByHandle"               
[11]        32 "VIRTUAL::GetHandle"                    
[12]         2 "VIRTUAL::VirtualTimeCurrent"           
[13]         3 "VIRTUAL::VirtualSymbolInfoInteger"     
[14]         3 "ORDERS::SymbolInfoInteger"             
[15]         3 "VIRTUAL::VirtualSymbolInfoDouble"      
[16]         3 "ORDERS::SymbolInfoDouble"              
[17]         1 "VIRTUAL::VirtualAccountInfoInteger"    
[18]  27253503 "VIRTUAL::NewTick"                      
[19]  27253503 "VIRTUAL::VirtualSymbolInfoTick"        
[20]  27253503 "ORDERS::SymbolInfoTick"                
[21]  68374848 "VIRTUAL::VirtualOrdersTotal"           
[22]   3460869 "VIRTUAL::VirtualOrderSend"             
[23]   3460869 "ORDERS::OrderSend"                     
[24]  18265283 "ORDER::Check"                          
[25]  92760074 "ORDER::GetCalcClosePrice"              
[26]  96220939 "ORDER::GetCalcProfit"                  
[27]  33069699 "ORDER_BASE::GetTicket"                 
[28]  92760072 "ORDER::IsChange"                       
[29]  99681806 "ORDER_BASE::GetProfit"                 
[30]  99681805 "ORDER_BASE::GetCommission"             
[31]  96220936 "ORDER_BASE::GetSwap"                   
[32] 140213253 "VIRTUAL::VirtualOrderSelect"           
[33] 140213253 "ORDERS::OrderSelect"                   
[34] 129830641 "ORDERS::SelectByPos"                   
[35] 212241536 "VIRTUAL::VirtualOrderType"             
[36] 212241536 "ORDERS::OrderType"                     
[37] 215702404 "ORDER_BASE::GetType"                   
[38]  76200768 "VIRTUAL::VirtualOrderOpenPrice"        
[39]  76200768 "ORDERS::OrderOpenPrice"                
[40]  76200768 "ORDER_BASE::GetOpenPrice"              
[41]  58221959 "VIRTUAL::VirtualOrderTakeProfit"       
[42]  58221959 "ORDERS::OrderTakeProfit"               
[43]  58221959 "ORDER_BASE::GetTakeProfit"             
[44]  14804384 "VIRTUAL::VirtualOrderStopLoss"         
[45]  14804384 "ORDERS::OrderStopLoss"                 
[46]  14804384 "ORDER_BASE::GetStopLoss"               
[47]  14804384 "VIRTUAL::VirtualOrderExpiration"       
[48]  14804384 "ORDERS::OrderExpiration"               
[49]  14804415 "VIRTUAL::VirtualOrderTicket"           
[50]  14804415 "ORDERS::OrderTicket"                   
[51]  14804414 "VIRTUAL::VirtualOrderModify"           
[52]  14804414 "ORDERS::OrderModify"                   
[53]  14804415 "ORDERS::GetIndex"                      
[54]  14804414 "ORDER::Modify"                         
[55]  10382569 "VIRTUAL::VirtualOrderClosePrice"       
[56]  10382569 "ORDERS::OrderClosePrice"               
[57]  10382569 "ORDER_BASE::GetClosePrice"             
[58]         1 "VIRTUAL::VirtualOrderDelete"           
[59]         1 "ORDERS::OrderDelete"                   
[60]         3 "ORDER::Delete"                         
[61]         1 "ORDER::Close"                          
[62]         3 "VIRTUAL::VirtualOrdersHistoryTotal"    
[63]  10382612 "ORDERS::SelectByPosHistory"            
[64]   6921738 "VIRTUAL::VirtualOrderOpenTime"         
[65]   6921738 "ORDERS::OrderOpenTime"                 
[66]   3460867 "VIRTUAL::VirtualOrderProfit"           
[67]   3460867 "ORDERS::OrderProfit"                   
[68]   3460867 "VIRTUAL::VirtualOrderCommission"       
[69]   3460867 "ORDERS::OrderCommission"               
[70]   3460867 "VIRTUAL::VirtualOrderSwap"             
[71]   3460867 "ORDERS::OrderSwap"                     
[72]   6921734 "VIRTUAL::VirtualOrderLots"             
[73]   6921734 "ORDERS::OrderLots"                     
[74]   6921734 "ORDER_BASE::GetLots"                   
[75]   3460868 "VIRTUAL::VirtualOrderCloseTime"        
[76]   3460868 "ORDERS::OrderCloseTime"                
[77]   6921734 "VIRTUAL::VirtualOrderCloseReason"      
[78]   6921734 "ORDERS::OrderCloseReason"              
[79]   6921734 "ORDER_BASE::GetCloseReason"            
[80]   6921672 "VIRTUAL::VirtualOrderClosePriceRequest"
[81]   6921672 "ORDERS::OrderClosePriceRequest"        

На каждый тик в среднем приходится 2.5 OrdersTotal(), 0.5 OrderModify(), 7.8 OrderType(), 5.1 OrderSelect() и т.д. Это позволяет примерно понимать, сколь сильно идет злоупотребление вызовами.

Таким способом можно свои советники сделать экономнее, даже если виртуалка не используется. Ну и по ускорению виртуалки есть над чем подумать. Например, ORDER::IsChange вызывается 3.4 раза на тик, что много.

 
fxsaber #:

Сделал такую замену.

И сразу исчезли тормоза. Как оказалось, было 2.5 миллиона закрытых позиций. Virtual их быстро проглотил после этой замены. Рекомендую подправить у себя.

Да, я тоже заметил то, что время расчетов не росло линейно. Неделя 10 сек, 5 недель около 4 минут. Тоже подумал про ресайз массива, но занимался свопами. Сделал эту правку и себе, теперь увеличение с 1 до 5 недель увеличивает время расчета в 5,5 раз, т.е. примерно линейно (не ровно в 5 раз м.б. потому, что тиков там больше, и ресайз все таки делается иногда). Спасибо! Если уж такими огромными шагами стали увеличивать массив,  то может и для активных ордеров задать 1000 по умолчанию? Памяти сейчас у всех много, скорость важнее.

fxsaber #:
Надо будет посмотреть. Вопрос лишь в целесообразности. Используют в качестве тестера один-два человека.

Возможно так мало используют, что не видят точного совпадения с тестером MQ.
Добавил в VIRTUAL функции для контроля открытости рынка для торговли, как вы советовали делать это в своем OnTick(). Но надо и там, чтобы ТП/СЛ/Лимитки не срабатывали при закрытом рынке. Так же сделал проброс последнего тика в конце теста, для закрытия сделок в конце теста по последней цене на 59 минуте, а не по последней цене торговой сессии на 54 минуте (отличались профиты по этим сделкам). Еще поменял порядок их закрытия, чтобы совпадало с тестером MQ.
Добавил расчет комиссий в % от лота. На моем ДЦ 0,0016% за лот и берется 2 раза, на входе и выходе. Раньше там было указано, что берется в двойном размере на входе. Проверил эту версию, не совпало с тестером. Ф-я которая была у меня раньше всегда рассчитывала по Bid цене - тоже не совпало, примерно 1% сделок имели комиссию больше на 1 цент. Попробовал расчитывать комиссию за покупку при входе по Ask, а при выходе по Bid и наоборот при продаже на входе. Результат комиссий стал абсолютно точно совпадать с тестером MQ.

В итоге получил полное совпадение по всем параметрам: комиссии, свопы, и итоговый профит.
Вот анимированный Гиф: (прикрепил, если в сайт не покажет)

Правок много. Могу скинуть код вам, чтобы вы добавили его в свой и обновили библиотеку. Видимо придется сделать совместимость с MQL4, я его не знаю и делал чисто под MQL5. Может что-то еще проверить, я не все функции знаю и для чего они. Смотреть отличия где я что добавил можно в Notepad++ с плагином Compare.
Если такой GIF разместить в описании библиотеки и пример запуска, чтобы каждый мог проверить, то пользователей может стать больше. Но и вопросов по библиотеке станет больше от новичков))

Я вот теперь убедился в точности работы и могу спокойно продолжать работу над советником используя виртуальный тестер. Спасибо Вам! Огромная работа.

Файлы:
 

По скорости, какие расчеты насколько замедляют самую быструю версию без свопов, комиссий и контроля тиков: (уже с новым ресайзом массива истории)

5 недель на вашем последнем примере, чтобы не миллисекунды сравнивать.

без контроля без свопов без комиссий - быстрая версия
OnTester result 2231715
2927398 ticks, 7477 bars generated. Environment synchronized in 0:00:00.023. Test passed in 0:00:09.896 (including ticks preprocessing 0:00:00.312).
2927398 ticks, 7477 bars generated. Test passed in 0:00:09.451.
2927398 ticks, 7477 bars generated. Test passed in 0:00:09.521.
2927398 ticks, 7477 bars generated. Environment synchronized in 0:00:00.022. Test passed in 0:00:09.933 (including ticks preprocessing 0:00:00.312).
2927398 ticks, 7477 bars generated. Test passed in 0:00:09.463.
2927398 ticks, 7477 bars generated. Test passed in 0:00:09.481.
в среднем 9,5 сек

 комис в %
OnTester result -5615401.2
2927398 ticks, 7477 bars generated. Environment synchronized in 0:00:00.023. Test passed in 0:00:17.969 (including ticks preprocessing 0:00:00.328).
2927398 ticks, 7477 bars generated. Test passed in 0:00:17.354.
2927398 ticks, 7477 bars generated. Test passed in 0:00:17.796.
в среднем 17,5 сек медленне на 84%

комис в пунктах
OnTester result -7047933
ticks, 7477 bars generated. Environment synchronized in 0:00:00.023. Test passed in 0:00:10.178 (including ticks preprocessing 0:00:00.312).
2927398 ticks, 7477 bars generated. Test passed in 0:00:09.751.
2927398 ticks, 7477 bars generated. Test passed in 0:00:09.766.
в среднем 9,8 сек медленне на 3%

своп
OnTester result 2230654.96
2927398 ticks, 7477 bars generated. Environment synchronized in 0:00:00.022. Test passed in 0:00:09.501 (including ticks preprocessing 0:00:00.312).
2927398 ticks, 7477 bars generated. Test passed in 0:00:08.846.
2927398 ticks, 7477 bars generated. Test passed in 0:00:08.841.
2927398 ticks, 7477 bars generated. Environment synchronized in 0:00:00.022. Test passed in 0:00:09.283 (including ticks preprocessing 0:00:00.312).
2927398 ticks, 7477 bars generated. Test passed in 0:00:08.853.
2927398 ticks, 7477 bars generated. Test passed in 0:00:08.840.
странно, что быстрее, возможно редактор лучше оптимизировал код при компиляции, иногда он 3-4 сек компилирует, а иногда 7-8 сек.
в среднем 8,9 сек быстрее на 6%

контроль тиков
OnTester result 2754428
2927398 ticks, 7477 bars generated. Environment synchronized in 0:00:00.023. Test passed in 0:00:10.344 (including ticks preprocessing 0:00:00.312).
2927398 ticks, 7477 bars generated. Test passed in 0:00:10.026.
2927398 ticks, 7477 bars generated. Test passed in 0:00:10.001.
2927398 ticks, 7477 bars generated. Test passed in 0:00:09.943.
2927398 ticks, 7477 bars generated. Test passed in 0:00:09.901.
в среднем 10 сек  медленне на 5%


своп , комис в пт, контроль тиков
OnTester result -6461417
2927398 ticks, 7477 bars generated. Environment synchronized in 0:00:00.023. Test passed in 0:00:09.715 (including ticks preprocessing 0:00:00.312).
2927398 ticks, 7477 bars generated. Test passed in 0:00:09.299.
2927398 ticks, 7477 bars generated. Test passed in 0:00:09.403.
ticks, 7477 bars generated. Test passed in 0:00:09.305.
в среднем 9,4 сек быстрее на 1%


своп, комис в %, контроль тиков
OnTester result -5038568.32
2927398 ticks, 7477 bars generated. Test passed in 0:00:18.092 (including ticks preprocessing 0:00:00.359).
2927398 ticks, 7477 bars generated. Test passed in 0:00:17.375.
2927398 ticks, 7477 bars generated. Test passed in 0:00:17.367.
в среднем 17,5 сек  медленне на 84%

своп, комис в %
OnTester result -5616461.24
2927398 ticks, 7477 bars generated. Environment synchronized in 0:00:00.021. Test passed in 0:00:18.642 (including ticks preprocessing 0:00:00.312).
2927398 ticks, 7477 bars generated. Test passed in 0:00:17.880.
2927398 ticks, 7477 bars generated. Test passed in 0:00:17.429.
в среднем 17,7 сек  медленне на 86%

В общем самый лучший/точный вариант комиссии в % замедляет расчеты на 85% примерно. Это конечно много, но для демонстрации тем, кто хочет своими глазами увидеть абсолютное совпадение с тестером MQ, это может быть нужно.
А свопы действительно часто меняются, сегодня опять поменяли.

 
Forester #:

Добавил в VIRTUAL функции для контроля открытости рынка для торговли, как вы советовали делать это в своем OnTick(). Но надо и там, чтобы ТП/СЛ/Лимитки не срабатывали при закрытом рынке.

Достаточно OnTick.
bool IsSessionTrade( const MqlTick &Tick )
{
  return(true);
}

void OnTick()
{
  MqlTick Tick;
  
  if (_V(0, SymbolInfoTick(_Symbol, Tick) && IsSessionTrade(Tick)))
    VIRTUAL::NewTick(Tick);
    
  // ...      
}

Так же сделал проброс последнего тика в конце теста, для закрытия сделок в конце теста по последней цене на 59 минуте, а не по последней цене торговой сессии на 54 минуте (отличались профиты по этим сделкам).

Так это неправильно! Анимированая гифка даже показывает фиолетовым цветом выход за пределы торговой сессии Тестером.

Forester #:

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

...

Если такой GIF разместить в описании библиотеки и пример запуска, чтобы каждый мог проверить, то пользователей может стать больше.

Думаю, проще - возможностей Тестера хватает.

 
fxsaber #:
Достаточно OnTick.

Да -для советников с вирт. тестером созданным по VIRTUAL::Create();
Внутренний контроль нужен для версий советника с #define VIRTUAL_TESTER , как в вашем последнем примере. Там мой  OnTick уже вторичный, и вызывается из виртуального тестера через #define OnTick OldOnTick2. Т.е. мой OnTick не может остановить виртуальный, он срабатывает позже. Я так понял. Могу и ошибаться.

fxsaber #:

Так это неправильно! Анимированая гифка даже показывает фиолетовым цветом выход за пределы торговой сессии Тестером.

Сделал так, для точного соответствия MQ тестеру. В реальной торговле закрыться сделки при закрытой сессии не смогут конечно. Видимо это просто фиксация эквити на момент конца теста. Для своих целей вообще не буду учитывать незакрытые сделки.

fxsaber #:
Думаю, проще - возможностей Тестера хватает.

Хорошо.
Моя доработка и скриншот покажут сомневающимся, что тестер работает правильно, вплоть до абсолютного совпадения с MQ тестером, если считать комиссии по % и свопы.

Возможно я и сам не буду с реальной комиссией по % считать, из за значительного замедления. Хотя попробую ускорить, там можно часть переменных предварительно рассчитать, в т.ч. самые медленные строковые.

 
fxsaber #:
Чаще всего даже не подозреваем, сколько советник чего вызывает. Поэтому вставил счетчик. Такой результат получил.

На каждый тик в среднем приходится 2.5 OrdersTotal(), 0.5 OrderModify(), 7.8 OrderType(), 5.1 OrderSelect() и т.д. Это позволяет примерно понимать, сколь сильно идет злоупотребление вызовами.

Таким способом можно свои советники сделать экономнее, даже если виртуалка не используется. Ну и по ускорению виртуалки есть над чем подумать. Например, ORDER::IsChange вызывается 3.4 раза на тик, что много.

по тому и просится, вернуть обычный режим профилирования

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

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

 

как вообще соотносится в профайлере, когда ты точно знаешь что посчиталось и нашел лишние(прошлый вариант). И - функция работает медленно..., это ведь обычно будет не добывательство Pi в последней степени, а если затуп просто системной функции, или ее обычная работа.

ощущение что Терминал лет 5 назад начал не в том направлении развиваться, и давно пора искать в чем причина

Разработчики могут тут гордиться что они тут всю жизнь вложили, а раз в 1000 больше не вложили жизнь?? Если Ренат так и не хочет понимать это...