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

 
fxsaber:

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

1. Ваш тест реально учитывает микро долю процента итераций благодаря условию 

if (Interval##A > 100)

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

И даже если вы поставите условие >0, то всё равно никакой объективности.

2. Замер времени подобных быстрых операций необходимо выполнять только как время полного цикла, а не одной итерации.

3. Но так как цикл в Вашем примере лимитирован 10 секундами ( Зачем! Для тиков думаю вполне хватит 0.1 сек. Ведь вполне возможно, что за секунду придут 3 тика, и все три тика будут отрабатыватся по 10 секунд, причем параллельно), то и замера времени никакого не требуется. А проще посчитать сколько выполнится итераций за заданное время. Чем больше, тем больше производительность.

Я "слегка" модифицировал Ваш код. Думаю, мой вариант больше отражает реальность.

Расчет производится по очереди, чтобы не смешивать два варианта. Четные тики для SYMBOL_BID, нечетные для GetBid().

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

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

#define Ask SymbolInfoDouble(_Symbol, SYMBOL_ASK)
#define TimeLoop 125  // 15.625*8  

bool GetPosition(const int Type = OP_BUY)
  {
   bool Res = false;
   for(int i = PositionsTotal() - 1; (i >= 0) && !Res; i--)
      Res = PositionGetTicket(i) && (PositionGetInteger(POSITION_TYPE) == Type) &&
            (PositionGetString(POSITION_SYMBOL) == _Symbol);
   return(Res);
  }

// Альтернативный способ получения Bid-цены текущего символа.
// Запускать только на демо-счетах.
double GetBid()
  {
   static const TICKET_TYPE Ticket = GetPosition() ? PositionGetInteger(POSITION_TICKET) : OrderSend(_Symbol, OP_BUY, 0.1, Ask, 0, 0, 0);
   return(PositionSelectByTicket(Ticket) ? PositionGetDouble(POSITION_PRICE_CURRENT) : 0);
  }

#define TOSTRING(A) ", "#A + " = " + (string)(A)


long N1=0;
long N2=0;
long n=0;
double sum1=0;
double sum2=0;

const bool Init = EventSetTimer(10) && GetBid(); // Будем выводить статистику каждый 10 секунд.

//+------------------------------------------------------------------+

void OnTick()
  {
//  return;
   const uint StartTime = GetTickCount();
   if(n%2==0)
      while(!IsStopped() && (GetTickCount() - StartTime < TimeLoop))
        {
         sum1+=SymbolInfoDouble(_Symbol, SYMBOL_BID);
         N1++;
        }
   else
      while(!IsStopped() && (GetTickCount() - StartTime < TimeLoop))
        {
         sum2+=GetBid();
         N2++;
        }
   if(n%2==0 && n>1)
      if (N1>N2) Print(_Symbol+": SYMBOL_BID быстрее GetBid() в " + DoubleToString(double(N1)/N2,2) + " раза. Среднее время одной итерации: SYMBOL_BID - " + DoubleToString((TimeLoop*1000000.0*n/2)/N1,2) + " ns, GetBid() - " + DoubleToString((TimeLoop*1000000.0*n/2)/N2,2) + " ns" + TOSTRING(sum1) + TOSTRING(sum2));
      else       Print(_Symbol+": GetBid() быстрее SYMBOL_BID в " + DoubleToString(double(N2)/N1,2) + " раза. Среднее время одной итерации: SYMBOL_BID - " + DoubleToString((TimeLoop*1000000.0*n/2)/N1,2) + " ns, GetBid() - " + DoubleToString((TimeLoop*1000000.0*n/2)/N2,2) + " ns" + TOSTRING(sum1) + TOSTRING(sum2));
      n++;
  }
//+------------------------------------------------------------------+

мой результат:

2020.10.26 19:26:46.193 FxSaberBidSpeed (USDCAD,M1)     USDCAD: SYMBOL_BID быстрее GetBid() в 2.97 раза. Среднее время одной итерации: SYMBOL_BID - 45.80 ns, GetBid() - 135.80 ns, sum1 = 106706334.7283292, sum2 = 35987491.50911281
2020.10.26 19:26:46.193 FxSaberBidSpeed (EURUSD,M1)     EURUSD: SYMBOL_BID быстрее GetBid() в 2.90 раза. Среднее время одной итерации: SYMBOL_BID - 45.10 ns, GetBid() - 130.82 ns, sum1 = 34042649.2788716,  sum2 = 11735304.45101236
2020.10.26 19:26:47.085 FxSaberBidSpeed (USDCAD,M1)     USDCAD: SYMBOL_BID быстрее GetBid() в 2.95 раза. Среднее время одной итерации: SYMBOL_BID - 45.57 ns, GetBid() - 134.55 ns, sum1 = 110131593.3516681, sum2 = 37303001.98488424
2020.10.26 19:26:52.397 FxSaberBidSpeed (USDCAD,M1)     USDCAD: SYMBOL_BID быстрее GetBid() в 2.99 раза. Среднее время одной итерации: SYMBOL_BID - 45.48 ns, GetBid() - 135.90 ns, sum1 = 113269505.1945728, sum2 = 37903458.6724181
2020.10.26 19:26:59.412 FxSaberBidSpeed (EURUSD,M1)     EURUSD: SYMBOL_BID быстрее GetBid() в 2.85 раза. Среднее время одной итерации: SYMBOL_BID - 45.16 ns, GetBid() - 128.57 ns, sum1 = 36611618.7279973,  sum2 = 12858907.51985167
2020.10.26 19:27:00.131 FxSaberBidSpeed (BTCUSD,M1)     BTCUSD: SYMBOL_BID быстрее GetBid() в 2.78 раза. Среднее время одной итерации: SYMBOL_BID - 47.10 ns, GetBid() - 130.88 ns, sum1 = 305215291120.0239, sum2 = 109832697267.1495
2020.10.26 19:27:03.303 FxSaberBidSpeed (USDCAD,M1)     USDCAD: SYMBOL_BID быстрее GetBid() в 2.96 раза. Среднее время одной итерации: SYMBOL_BID - 45.44 ns, GetBid() - 134.61 ns, sum1 = 116279675.0471961, sum2 = 39248002.75579567
2020.10.26 19:27:06.318 FxSaberBidSpeed (USDCAD,M1)     USDCAD: SYMBOL_BID быстрее GetBid() в 3.01 раза. Среднее время одной итерации: SYMBOL_BID - 45.17 ns, GetBid() - 135.96 ns, sum1 = 119877506.6663743, sum2 = 39829996.08171722
2020.10.26 19:27:06.709 FxSaberBidSpeed (USDCAD,M1)     USDCAD: SYMBOL_BID быстрее GetBid() в 3.01 раза. Среднее время одной итерации: SYMBOL_BID - 44.92 ns, GetBid() - 135.42 ns, sum1 = 123505976.1123297, sum2 = 40965170.16304104
2020.10.26 19:27:07.803 FxSaberBidSpeed (USDCAD,M1)     USDCAD: SYMBOL_BID быстрее GetBid() в 2.99 раза. Среднее время одной итерации: SYMBOL_BID - 44.84 ns, GetBid() - 134.00 ns, sum1 = 126664503.6443297, sum2 = 42385980.37108831
Как видно разница в производительности в три раза в пользу штатного варианта.
 
Nikolai Semko:


Как видно разница в производительности в три раза в пользу штатного варианта.

А оригинальный вариант от fxsaber показывает преимущество GetBid, или дело в более мощном/менее нагруженном ПК?

 
Andrey Khatimlianskii:

А оригинальный вариант от fxsaber показывает преимущество GetBid, или дело в более мощном/менее нагруженном ПК?

Его вариант у меня тоже показывал преимущество GetBid при полной загрузке процессора. Но при этом мой вариант показывает при той же загрузке показывает трехкратное преимущество штатной функции.
Это происходит потому, что мой вариант учитывает среднее время всех итераций получения цены Bid, а его только лишь мизерной части с аномальным зависанием.
Кто ж его знает по какой причине процессор в трудную для него "минуту" забивает именно на штатную функцию (когда задержка более 100 µ). Но все равно среднее время в три раза меньше для штатной функции

Ну и вот, например при if (Interval##A > 100) у меня такая картина:  

тогда как при if (Interval##A > 0)  уже совсем другая, показывающая случайные распределение аномальных задержек между штатным и альтернативным вариантом получения цены Bid

при этом мой тест при той же загрузки процессора показывает:

2020.10.26 22:16:10.569 FxSaberBidSpeed (USDCAD,M1)     USDCAD: SYMBOL_BID быстрее GetBid() в 2.79 раза. Среднее время одной итерации: SYMBOL_BID - 57.95 ns, GetBid() - 161.43 ns, sum1 = 108105265.450882, sum2 = 38804020.20301527
2020.10.26 22:16:12.146 FxSaberBidSpeed (USDCAD,M1)     USDCAD: SYMBOL_BID быстрее GetBid() в 2.79 раза. Среднее время одной итерации: SYMBOL_BID - 57.81 ns, GetBid() - 161.06 ns, sum1 = 111212159.8857315, sum2 = 39917412.88663763
2020.10.26 22:16:13.741 FxSaberBidSpeed (USDCAD,M1)     USDCAD: SYMBOL_BID быстрее GetBid() в 2.79 раза. Среднее время одной итерации: SYMBOL_BID - 57.37 ns, GetBid() - 159.91 ns, sum1 = 114942034.0034028, sum2 = 41233865.03452455
2020.10.26 22:16:14.740 FxSaberBidSpeed (EURUSD,M1)     EURUSD: SYMBOL_BID быстрее GetBid() в 3.18 раза. Среднее время одной итерации: SYMBOL_BID - 52.88 ns, GetBid() - 167.92 ns, sum1 = 75470423.51597476, sum2 = 23764764.64380601
2020.10.26 22:16:15.756 FxSaberBidSpeed (USDCAD,M1)     USDCAD: SYMBOL_BID быстрее GetBid() в 2.78 раза. Среднее время одной итерации: SYMBOL_BID - 57.30 ns, GetBid() - 159.06 ns, sum1 = 117956798.0483066, sum2 = 42491447.24894404
2020.10.26 22:16:17.646 FxSaberBidSpeed (USDCAD,M1)     USDCAD: SYMBOL_BID быстрее GetBid() в 2.77 раза. Среднее время одной итерации: SYMBOL_BID - 57.19 ns, GetBid() - 158.36 ns, sum1 = 121056970.4066543, sum2 = 43721243.0341278
2020.10.26 22:16:20.146 FxSaberBidSpeed (USDCAD,M1)     USDCAD: SYMBOL_BID быстрее GetBid() в 2.76 раза. Среднее время одной итерации: SYMBOL_BID - 57.14 ns, GetBid() - 157.85 ns, sum1 = 124053724.3725583, sum2 = 44907061.11418578
2020.10.26 22:16:21.553 FxSaberBidSpeed (EURUSD,M1)     EURUSD: SYMBOL_BID быстрее GetBid() в 3.15 раза. Среднее время одной итерации: SYMBOL_BID - 52.80 ns, GetBid() - 166.11 ns, sum1 = 78375839.87008552, sum2 = 24913626.42960918
2020.10.26 22:16:24.865 FxSaberBidSpeed (USDCAD,M1)     USDCAD: SYMBOL_BID быстрее GetBid() в 2.77 раза. Среднее время одной итерации: SYMBOL_BID - 56.94 ns, GetBid() - 157.50 ns, sum1 = 127392085.5933389, sum2 = 46051851.71182434
2020.10.26 22:16:27.678 FxSaberBidSpeed (USDCAD,M1)     USDCAD: SYMBOL_BID быстрее GetBid() в 2.77 раза. Среднее время одной итерации: SYMBOL_BID - 57.13 ns, GetBid() - 158.30 ns, sum1 = 129851046.9417646, sum2 = 46862113.16739535

Поэтому, считаю, что вариант теста fxsaber далек от объективности.

Процессор загружал не агентами, а этим скриптом. Получалось более эффективно.

Файлы:
LSD.mq5  6 kb
 

после небольшой модификации теста fxsaber, чтобы наглядно продемонстрировать, какой процент итераций учитывается в расчетах:

2020.10.26 22:45:03.679 FxSaberBidSpeed (USDCAD,M1)     Alert: , TimeBid1-TimeBid2 = 2142416 mcs., TimeBid1 = 2858669, TimeBid2 = 716253,  Всего итераций - 31456223, из них принято во внимание, NBid1 = 3015, NBid2 = 1714
2020.10.26 22:45:05.739 FxSaberBidSpeed (BTCUSD,M1)     Alert: , TimeBid1-TimeBid2 = 1521696 mcs., TimeBid1 = 2282285, TimeBid2 = 760589,  Всего итераций - 31417549, из них принято во внимание, NBid1 = 1794, NBid2 = 1418
2020.10.26 22:45:06.006 FxSaberBidSpeed (USDJPY,M1)     Alert: , TimeBid1-TimeBid2 = 2241890 mcs., TimeBid1 = 3204507, TimeBid2 = 962617,  Всего итераций - 54138004, из них принято во внимание, NBid1 = 4401, NBid2 = 2083
2020.10.26 22:45:09.099 FxSaberBidSpeed (EURUSD,M1)     Alert: , TimeBid1-TimeBid2 = 1000828 mcs., TimeBid1 = 1496646, TimeBid2 = 495818,  Всего итераций - 10037824, из них принято во внимание, NBid1 = 2429, NBid2 = 1711
2020.10.26 22:45:14.803 FxSaberBidSpeed (USDCAD,M1)     Alert: , TimeBid1-TimeBid2 = 2676273 mcs., TimeBid1 = 3916168, TimeBid2 = 1239895, Всего итераций - 41606744, из них принято во внимание, NBid1 = 4935, NBid2 = 3790
2020.10.26 22:45:15.745 FxSaberBidSpeed (BTCUSD,M1)     Alert: , TimeBid1-TimeBid2 = 1521696 mcs., TimeBid1 = 2282285, TimeBid2 = 760589,  Всего итераций - 31417549, из них принято во внимание, NBid1 = 1794, NBid2 = 1418
2020.10.26 22:45:16.115 FxSaberBidSpeed (USDJPY,M1)     Alert: , TimeBid1-TimeBid2 = 2653810 mcs., TimeBid1 = 4195095, TimeBid2 = 1541285, Всего итераций - 64310228, из них принято во внимание, NBid1 = 6486, NBid2 = 3879
2020.10.26 22:45:19.834 FxSaberBidSpeed (EURUSD,M1)     Alert: , TimeBid1-TimeBid2 = 1949809 mcs., TimeBid1 = 3091755, TimeBid2 = 1141946, Всего итераций - 19435170, из них принято во внимание, NBid1 = 4724, NBid2 = 3547

т.е. примерно 0.01%  

еще бы. 
Если при среднем времени выполнения SymbolInfoDouble(_Symbol, SYMBOL_BID) около 50 наносекунд, учитываются только те, выполнение которых более 100 000 наносекунд.

Файлы:
 
Nikolai Semko:

после небольшой модификации теста fxsaber, чтобы наглядно продемонстрировать, какой процент итераций учитывается в расчетах:

т.е. примерно 0.01%  

еще бы. 
Если при среднем времени выполнения SymbolInfoDouble(_Symbol, SYMBOL_BID) около 50 наносекунд, учитываются только те, выполнение которых более 100 000 наносекунд.

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

Вообще торговля при загрузке более 70% железа это не правильно. Это почти критическое исполнение. Загрузка железа на боевых советниках должна быть не более 60%. 

 
Буду у компа ещё нескоро, поэтому пишу кратко.

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

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

Кодом доказал, что такой костыль существует. Хотите не нарываться на тормоза -используйте костыль.

Здесь ещё никто не смотрел код сравнения актуальности получаемых цен, когда работаем ещё и со стаканом. А там,мягко говоря, серьёзные вопросы.

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

Хотите HFT - пока забудьте даже про медленный миллисекундный уровень. 
 
а HFT-брокеры у вас уже есть?)
 
secret:
а HFT-брокеры у вас уже есть?)
Да.
 
Igor Makanu:

попробуйте протестировать SymbolInfoTick когда в обзоре рынка один символ и когда несколько десятков символов, но запрашивайте один инструмент - как в Вашем примере

высока вероятность, что с сервера идет сжатый трафик и эти периодические тормоза SymbolInfoTick появляются когда происходит распаковка данных

т.е. когда много символов будет еще более частые или глубокие провалы во времени теста

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

не вижу смысла в тестировании на 80% загруженном процессоре

А у него в тесте и не 80% даже. Там 6 агентов пашут на 4 ядрах, т.е. гарантировано 100%.

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

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

Закроем глаза, что даже в таких условиях это "примерно 0.01%" - к черту подробности! Достаточно заявить, что "средняя температура по больнице никого не волнует", "лаги создают проблемы во время торговли" и "хотим HFT".

Более того, конечно же, хотим чтобы HFT был в 20 экспертов на старом офисном десктопе или дохлой виртуалке.

PS PositionSelectByTicket() в своей реализации безусловно имеет доступ к разделяемому ресурсу с синхронизацией доступа. А если не селектить позицию на каждом вызове, то вы читаете старую цену. Проще было сделать "снепшот" через SymbolInfoDouble.

Ордерa, позиции и сделки в MetaTrader 5
Ордерa, позиции и сделки в MetaTrader 5
  • www.mql5.com
Конечной целью трейдера является извлечение прибыли посредством торговых операций на финансовых рынках. В этой статье дается описание терминов и процессов торговой платформы MetaTarder 5, знание которых необходимо для правильного понимания работы торговых функций языка MQL5. Ордера — это принятые торговым сервером запросы на совершение торговых...
 
реалтайм ядро может как то помочь?
Причина обращения: