Ошибки, баги, вопросы - страница 2963

 
fxsaber:

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

Очень сложное решение выйдет.

зачем им синхронизироваться? это за них сделает user32.dll.
Им главное правильно пронумероваться, чтобы каждый имел уникальный номер и этот номер был индексом массива данных. 
Это можно в крайнем случае сделать в ручную. А можно и автоматом. Кстати я недавно что-то подобное публиковал в КБ (Indicator Сopies), правда для одного окна, но не сложно переделать под весь терминал.
А чем не нравятся ресурсы? По-моему оптимально в границах одного терминала. В том варианте, который я предлагаю через user32.dll (реализовал этот вариант лет 10 назад, когда по-молодости баловался арбитражем), время доступа и парсинга данных окого 50 микросекунд (думаю, что можно убыстрить в 1.5-2 раза). Неужели с ресурсами медленее?

 
Nikolai Semko:

зачем им синхронизироваться? это за них сделает user32.dll.

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

А чем не нравятся ресурсы? По-моему оптимально в границах одного терминала. В том варианте, который я предлагаю через user32.dll (реализовал этот вариант лет 10 назад, когда по-молодости баловался арбитражем), время доступа и парсинга данных окого 50 микросекунд (думаю, что можно убыстрить в 1.5-2 раза). Неужели с ресурсами медленее?

100 микросекунд на чтение уходит на домашней машине в идеальных условиях. Советник на одном тике может вызвать чтение сотню раз. Медленно выходит.

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

 
fxsaber:

Это HistoryTicks - ловля всех тиков для советников. Поэтому EventChartCustom не подходит, там своя очередь. С буфером аналогично.

У меня работает на EventChartCustom. 99.8% тиков поступают в течении 0.15 мс

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

EventChartCustom => indicator is too slow

Andrey Khatimlianskii, 2019.12.12 09:27

Вот статистика за 9 часов работы на 5 инструментах:

Windows 8.1 (build 9600) x64, IE 11, UAC, Intel Core i5-3570  @ 3.40GHz, Memory: 6979 / 16346 Mb, Disk: 341 / 499 Gb, GMT+2
[USDCHF]: 22784 of 22833 (99.8 %) ticks were processed (0.14 ms delay in average), 49 (0.2 %) ticks were skipped (103.4 ms delay in average)
[EURUSD]: 22944 of 22974 (99.9 %) ticks were processed (0.16 ms delay in average), 30 (0.1 %) ticks were skipped (115.6 ms delay in average)
[USDCAD]: 15331 of 15347 (99.9 %) ticks were processed (0.13 ms delay in average), 16 (0.1 %) ticks were skipped (104.6 ms delay in average)
[EURCHF]: 22516 of 22571 (99.8 %) ticks were processed (0.13 ms delay in average), 55 (0.2 %) ticks were skipped (127.8 ms delay in average)
[EURAUD]: 66842 of 66924 (99.9 %) ticks were processed (0.13 ms delay in average), 82 (0.1 %) ticks were skipped (117.8 ms delay in average)
[GBPUSD]: 41393 of 41393 (100.0 %) ticks were processed (0.00 ms delay in average)
Total trade requests time: 4.280 sec

Советник стоял на GBPUSD, поэтому для него работал родной OnTick.

Ошибок "indicator is too slow" не было.


А вот на ВПС от MQ и процент пропущенных тиков и средняя задержка сильно выше (чуть позже выложу статистику).
И ошибок "indicator is too slow" достаточно много.

Не понятна природа переполнения очереди, ведь советник обрабатывает накопившиеся события моментально (просто return-ится).
Кто-то еще ее обрабатывает?


 
Andrey Khatimlianskii:

У меня работает на EventChartCustom. 99.8% тиков поступают в течении 0.15 мс

Тики из индикатора отправляю через это: sparam содержит MqlTick, lparam - номер тика.

Советник в OnChartEvent ловит эти тики. И ему надо понять, сейчас пойманный тик - это самый актуальный или нет? Т.е. есть ли очередь из тиков или она пустая?

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


Ну и по ходу работы OnTick после всяких тормозных OrderSend нужно удостовериться, а не отправил ли индикатор еще тиков. Для этого снова нужно прочесть число от индикатора. И вот таких проверок за выполнение одного OnTick может быть за сотню. Поэтому и нужно быстро читать.

 

В пределах 1 терминала самое быстрое в винапи будет выделение памяти (глобальное в пределах процесса) и работа через интерлокед функции типа https://docs.microsoft.com/ru-ru/windows/win32/api/winnt/nf-winnt-interlockedexchange

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

InterlockedExchange function (winnt.h) - Win32 apps
InterlockedExchange function (winnt.h) - Win32 apps
  • 2018.12.05
  • lastnameholiu
  • docs.microsoft.com
Sets a 32-bit variable to the specified value as an atomic operation.
 
traveller00:

В пределах 1 терминала самое быстрое в винапи будет выделение памяти (глобальное в пределах процесса) и работа через интерлокед функции типа https://docs.microsoft.com/ru-ru/windows/win32/api/winnt/nf-winnt-interlockedexchange

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

Без примера не обойдусь.

 
fxsaber:

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

Ну и по ходу работы OnTick после всяких тормозных OrderSend нужно удостовериться, а не отправил ли индикатор еще тиков. Для этого снова нужно прочесть число от индикатора. И вот таких проверок за выполнение одного OnTick может быть за сотню. Поэтому и нужно быстро читать.

Инициализация.

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

2. В нужные потоки (читающие) переслать адрес этой памяти.

Основная работа.

3. Пишущий поток дёргает InterlockedExchange или InterlockedExchange64 в зависимости от размерности переменной для записи в неё.

4. Читающий поток дёргает например InterlockedCompareExchange для чтения.

Завершение.

5. Освободить выделенную память, желательно в том же потоке, кто и выделял её.


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


Работать будет в пределах 1 процесса, память общая для потоков 1 процесса. Если надо, есть и другие интерлокед функции типа InterlockedDecrement, InterlockedAdd и тд.

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


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

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

 
fxsaber:

Эта схема видится нерабочей. Покажите элементарный пример, пожалуйста.

Почему не рабочей? Как раз мне кажется под задачу. Принцип геттера сеттора.
Получение значения скрытой переменной через функцию.
Если передаёшь структуру MqlTick, то определи свою структуру с набором полей как у MqlTick, и добавь в структуру своё поле счётчика.
И возвращай из export функции эту структуру.
Элементарный пример для индикатора. То что пример приведён в скрипте, не обращайте внимания.

struct myMqlTick 
{ 
   datetime     time;          // Время последнего обновления цен 
   double       bid;           // Текущая цена Bid 
   double       ask;           // Текущая цена Ask 
   double       last;          // Текущая цена последней сделки (Last) 
   ulong        volume;        // Объем для текущей цены Last 
   ulong        count;  //Свой счётчик
   
}myStruct;

//--------------------------------------------------
myMqlTick GetTickStruct() export
{
   
   return(myStruct);
}

//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
{
   myStruct.time   = 0.0;
   myStruct.bid    = 0.0;
   myStruct.ask    = 0.0;
   myStruct.last   = 0.0;
   myStruct.volume = 0;
   myStruct.count  = 1;  //свой счётчик  
  
}
//+------------------------------------------------------------------+

В эксперте вызываешь GetTickStruct, и получаешь всю структуру, с своим счётчиком.

Документация по MQL5: Константы, перечисления и структуры / Структуры данных / Структура для получения текущих цен
Документация по MQL5: Константы, перечисления и структуры / Структуры данных / Структура для получения текущих цен
  • www.mql5.com
Структура для получения текущих цен - Структуры данных - Константы, перечисления и структуры - Справочник MQL5 - Справочник по языку алгоритмического/автоматического трейдинга для MetaTrader 5
 
Roman:

В эксперте вызываешь GetTickStruct, получаешь всю структуру, с своим счётчиком.

Элементарную передачу числа из индикатора в советника напишите, пожалуйста.

 
fxsaber:

Элементарную передачу числа из индикатора в советника напишите, пожалуйста.

Замени структуру на одну переменную ))

Причина обращения: