MT5 и скорость в боевом исполнении - страница 18

 
Renat Fatkhullin:

У вас только два состояния 5000 и анлим?

Вы сами кузнец своего счастья.

Да, нужен или полный контроль или поверхностный. В промежуточных вариантах не вижу смысла.
 
Renat Fatkhullin:

Теоретически, да.

Не забывайте про процессы синхронизации. Огромное количество процессов в платформе асинхронные.

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

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

Большинство интеграционных API такие безграмотные и нефункциональные, что почти начисто лишают возможности делать гарантированные шлюзы. Хотя есть мнение, что это продукт осознанного саботажа их разработчиков.

Может, дать право выбора? Кому нужны физические снепы и кому достаточно работать с индексами с соответствующими рисками.

 
Комментарии, не относящиеся к этой теме, были перенесены в "Вопросы от начинающих MQL5 MT5 MetaTrader 5".
 
fxsaber:

Может, дать право выбора? Кому нужны физические снепы и кому достаточно работать с индексами с соответствующими рисками.

А в чем проблема держать локальный кэш на советнике и делать выборку относительно последнего времени обновления? Я так и делаю и тормозов никогда не возникало с этим. У меня сетевые функции подтормаживают весь интерфейс из-за их синхронной реализации, было бы здорово иметь WebRequestAsync из коробки, хотя уже сильно смотрю в сторону DLL или даже связки питона с C++ врапперами, т.к. на питоне есть торговый API :)

Но работа с большими объемами данных без локального кэширования - это очень странно.

PS. Вообще в мультивалютнике очень востребованы хэш мапы и кеширование и поэтому просил выше в этой ветке нормальные (читайте быстрые) хэш мапы из коробке.
Документация по MQL5: Сетевые функции / WebRequest
Документация по MQL5: Сетевые функции / WebRequest
  • www.mql5.com
Для использования функции WebRequest() следует добавить адреса серверов в список разрешенных URL во вкладке "Советники" окна "Настройки". Порт сервера выбирается автоматически на основе указанного протокола - 80 для "http://" и 443 для "https://". Функция WebRequest() является синхронной, это означает, что она приостанавливает выполнение...
 
Andrey Pogoreltsev:

А в чем проблема держать локальный кэш на советнике и делать выборку относительно последнего времени обновления?

Скрипт это и делает.

Что касается локального кэша, то в MT4Orders так и реализована история.

 
fxsaber:

Что касается локального кэша, то в MT4Orders так и реализована история.

Не ожидал, что скрипт, которому два года

Forum on trading, automated trading systems and testing trading strategies

OrderCloseTime Expert Advisor MQL5

fxsaber, 2018.07.06 00:49

#include <MT4Orders.mqh> // https://www.mql5.com/en/code/16006

void LastTimeMQL4( datetime &OpenTime, datetime &CloseTime )
{
  for (int i = OrdersHistoryTotal() - 1; i >= 0; i--)
    if (OrderSelect(i, SELECT_BY_POS, MODE_HISTORY) && (OrderType() <= OP_SELL))
    {
      OpenTime = OrderOpenTime();
      CloseTime = OrderCloseTime();
      
      break;
    }
}

void LastTimeMQL5( datetime &OpenTime, datetime &CloseTime )
{
  if (HistorySelect(0, INT_MAX))
  {
    for (int i = HistoryDealsTotal() - 1; i >= 0; i--)
    {
      const ulong Ticket = HistoryDealGetTicket(i);
  
      if (HistoryDealGetInteger(Ticket, DEAL_ENTRY) == DEAL_ENTRY_OUT)
      {
        CloseTime = (datetime)HistoryDealGetInteger(Ticket, DEAL_TIME);

        if (HistorySelectByPosition(HistoryDealGetInteger(Ticket, DEAL_POSITION_ID)))
          OpenTime = (datetime)HistoryDealGetInteger(HistoryDealGetTicket(0), DEAL_TIME);
          
        break;
      }
    }
  }
}

typedef void (*GetLastTime)( datetime&, datetime& );

void Bench( GetLastTime LastTime, const int Amount = 10000 )
{
  datetime OpenTime, CloseTime;
  datetime Tmp = 0;

  for (int i = 0; i < Amount; i++)
  {
    LastTime(OpenTime, CloseTime);
    
    Tmp += CloseTime - OpenTime;        
  }
  
  Print(Tmp);
}

#define BENCH(A)                                                              \
{                                                                             \
  const ulong StartTime = GetMicrosecondCount();                              \
  A;                                                                          \
  Print("Time[" + #A + "] = " + (string)(GetMicrosecondCount() - StartTime)); \
}

#define PRINT(A) Print(#A + " = " + (string)(A))

void OnStart()
{  
  if (HistorySelect(0, INT_MAX))
    PRINT(HistoryDealsTotal());

  BENCH(Bench(LastTimeMQL4))
  BENCH(Bench(LastTimeMQL5))  
}


покажет такие тормоза!

// Первый запуск
2020.08.28 22:01:12.941 HistoryDealsTotal() = 9435
2020.08.28 22:01:13.198 2046.04.30 00:13:20
2020.08.28 22:01:13.198 Time[Bench(LastTimeMQL4)] = 257277
2020.08.28 22:01:43.982 2046.04.30 00:13:20
2020.08.28 22:01:43.982 Time[Bench(LastTimeMQL5)] = 30783493

// Второй запуск
2020.08.28 22:03:31.474 HistoryDealsTotal() = 9435
2020.08.28 22:03:31.724 2046.04.30 00:13:20
2020.08.28 22:03:31.724 Time[Bench(LastTimeMQL4)] = 250491
2020.08.28 22:04:02.011 2046.04.30 00:13:20
2020.08.28 22:04:02.011 Time[Bench(LastTimeMQL5)] = 30286258

Чистый MQL5 в 100 раз медленнее частичного (только HistorySelectByPosition) кеширования.

 
Тест вообще неприемлемый.

Вы же для MQL5 стиля тестировали специально 10 000 выборок HistorySelect на всю глубину. Да еще и циклов дополнительно накрутили.

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

За такую грязную игру с волчьим билетом выставляют.
 
Renat Fatkhullin:
Тест вообще неприемлемый.

Вы же для MQL5 стиля тестировали специально 10 000 выборок HistorySelect на всю глубину. Да еще и циклов дополнительно накрутили.

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

За такую грязную игру с волчьим билетом выставляют.

Ну так восприятие у Вас неправильное. Показано, что правильно самому кешировать, чтобы не было торомозов.

Если правильно понимаю, то после этой реализации

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

MT5 и скорость в боевом исполнении

Renat Fatkhullin, 2020.08.27 22:58

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

То есть, если не будете специально рандомизировать пределы выборок, то кеш будет показывать попадания, близкие к 100%.

Скорее всего на следующей неделе уже будет эффективное решение.


этот пример станет выполняться гораздо быстрее.


ЗЫ Скрипт вычисляет время открытия/закрытия последней позиции в истории торгов.

 
fxsaber:

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

Если вот так "закешировать", то будет супер-быстро.

void LastTimeMQL5( datetime &OpenTime, datetime &CloseTime )
{
  static ulong PrevTicketIn = 0;  // Хранит тикет входа позиции с последнего вызова.
  static ulong PrevTicketOut = 0; // Хранит тикет выхода позиции с последнего вызова.
  
  if (HistorySelect(0, INT_MAX))
  {
    for (int i = HistoryDealsTotal() - 1; i >= 0; i--)
    {
      const ulong Ticket = HistoryDealGetTicket(i);
      
      if (Ticket == PrevTicketOut)            
      {
        OpenTime = (datetime)HistoryDealGetInteger(PrevTicketIn, DEAL_TIME);
        CloseTime = (datetime)HistoryDealGetInteger(PrevTicketOut, DEAL_TIME);        
        
        break;
      }
      else if (HistoryDealGetInteger(Ticket, DEAL_ENTRY) == DEAL_ENTRY_OUT)
      {
        PrevTicketOut = Ticket;
        
        CloseTime = (datetime)HistoryDealGetInteger(Ticket, DEAL_TIME);

        if (HistorySelectByPosition(HistoryDealGetInteger(Ticket, DEAL_POSITION_ID)))
        {
          PrevTicketIn = HistoryDealGetTicket(0);
          OpenTime = (datetime)HistoryDealGetInteger(PrevTicketIn, DEAL_TIME);
        }
          
        break;
      }
    }
  }
}

Кто так пишет?

 
fxsaber:

Если вот так "закешировать", то будет супер-быстро.

Кто так пишет?

Си программисты.