Мультисоветник. Лучший способ получения данных - страница 2

 
Владимир, забыл указать эпический вариант "Зацикливание While(IsStoped() == false)";))
 

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

З.Ы. У меня вот мысль, если индикатор определения нового тика вызывать прямо из эксперта, так, что бы он сам на нужный символ этот индикатор набросил, то будет ли этот индикатор запущенный из эксперта получать новые тики также как и обычный индикатор, размещенный в отдельном окне символа?

 
В ближайшее время самым логичным станет вариант через сервисы

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

Не могу найти в справке про "Указатели на функции"

Renat Fatkhullin, 2017.01.06 21:12

Кстати, мы через некоторое время введем понятие сервисов.

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

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

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

Тесты на вычисление числа Pi для mql4, mql5, MSVC, Intel compilators

Renat Fatkhullin, 2017.01.07 23:21

Да, появится из важного:

  1. Расширенный OpenCL со штатной расчетной математической библиотекой на OpenCL. Конечно, с ограниченным набором функций, который поддается распараллеливанию.
  2. Новый тип программ в виде постоянных сервисов и функций взаимодействия между программами
  3. Кастомные датафиды и синтетические инструменты

Ну и конечно десятки других вещей, которые будут описаны в релизах.

 
Vasiliy Sokolov:

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

З.Ы. У меня вот мысль, если индикатор определения нового тика вызывать прямо из эксперта, так, что бы он сам на нужный символ этот индикатор набросил, то будет ли этот индикатор запущенный из эксперта получать новые тики также как и обычный индикатор, размещенный в отдельном окне символа?

Нужно проверить, вот только как лучше визуализировать данные от индикатора наброшенного вручную и от индикатора наброшенного из эксперта?

 

Добавлено: накидывать предварительно на график две текстовые метки OBJ_LABEL - и в настройках индикатора вводить имя метки в которую осуществлять вывод. 

 
Vladimir Karputov:

Нужно проверить, вот только как лучше визуализировать данные от индикатора наброшенного вручную и от индикатора наброшенного из эксперта?

Добавлено: накидывать предварительно на график две текстовые метки OBJ_LABEL - и в настройках индикатора вводить имя метки в которую осуществлять вывод. 

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

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

Где мы находимся в потребности и в возможности быстро реагировать на изменения курсов в терминале? В частности, речь о секундах или микросекундах?


   Сначала - а сколько надо?

   Для потока тиков по одному инструменту у меня давно отложилась в голове величина - в среднем по одному тику каждые 2-3 секунды. С переходом на 5-разрядное котирование эта частота увеличилась, но ненамного. Мультивалютный советник должен реагировать на каждое изменение любого из учитываемых инструментов. Если их 10, то, вроде бы, частота событий их изменения должна вырасти в 10 раз. То есть каждые 200-300 миллисекунд. Выясняю, так ли это. Оцениваю частоту сверху.

   За пятницу 30.12.2016 у меня есть тики по 25 инструментам от 35 компаний. Из компаний выбрал Blackwell Global Investments Limited, у которой общее число тиков почти самое большое, 13588449 за 385716 секунд их поставки (за неполную, без католического рождества, неделю), причем котировались все 25 пар. Если бы тики шли пакетами по одному, то событий прихода тиков было бы 13588449/385716 = 35.2 в секунду в среднем (каждые 28 мс). Чаще всего шли тики по EURJPY, их было 927262, или по 2.4 тика в секунду (417 мс).
   Однако тики обычно идут по нескольку штук в одном интернет-пакете, "пачками". Для уточнения выбираю час с 18 до 19 МСК, где число пришедших тиков почти наибольшее по сравнению с другими часами этой пятницы, то есть шли они чаще среднего. От всех компаний пришло за час 4246746 изменений курсов в 1231278 "пачках", или в среднем по 3.45 инструмента в каждой "пачке". От Blackwell за час пришло 45927 пачек, в среднем по одной за каждые 78.4 миллисекунды.
   Это в среднем по часу, иногда чаще, иногда реже. Но понятно, что с ростом числа инструментов в мультивалютном советнике требуемая скорость реакции на приход "пачки" растет.

   
  Теперь - а как быстро можем?

   Оцениваем затраты времени на выяснение того, у каких инструментов из 25 нужных произошли изменения. В подавляющем большинстве случаев изменений нет, в этом смысл отлавливания прихода котировок. 02.01.2017 утром запустил скрипт, работавшая часть которого показана ниже. Котировки не изменялись, но "лишнюю" для этого случая обработку времен не убрал, она нужна, если изменение было. Все экспериментальные оценки сделаны на том же счете Blackwell, так что это MQL4.

iSteps=0;
while (true) { // Сам бесконечный цикл
  S = "";
  SrvT=TimeCurrent();
  LocT=TimeLocal();
  if ((SrvT>=TSrv) && (LocT>=TLoc)) {
    // Оба эти времени могут уменьшиться по сравнению с предыдущими значениями
    // из-за синхронизации времени на сервере или еще по каким-то причинам,
    // в советники такие тики не приходят. 3-е время не проверяем, оно у каждой пары свое
    // NewT = MarketInfo(Sy[k],MODE_TIME); //MODE_TIME=5 Время поступления последней котировки по этой паре
    iSteps++; if (iSteps>10000000) {Finish(); return;}
    for (k=0;k<=Nsy;k++) {
      Symb = Sy[k]; // MarketInfo возвращает уже нормализованное число
      NewBid = MarketInfo(Symb,MODE_BID); k1 = iErr();
      if (k1!=0) ToProt (StringConcatenate("^98 Сбой MarketInfo(",Symb,"), err=",k1));
      NewAsk = MarketInfo(Symb,MODE_ASK); k1 = iErr();
      if (k1!=0) ToProt (StringConcatenate("^98 Сбой MarketInfo(",Symb,"), err=",k1));
      if ((NewBid==Bids[k]) && (NewAsk==Asks[k])) continue; // Нет изменений

   Миллион циклов выполнился за 79 секунд, то есть по 79 микросекунд на 25 инструментов. Работали еще 34 терминала плюс Internet Explorer. 8 процессоров по 4 ГГц позволяют думать, что поток этого скрипта работал почти непрерывно, как будто с приоритетом "real time". Остальные 7 процессоров справлялись с работой других потоков.
   79 мкс по сравнению с 78.4 мс вроде бы хорошо, реакция очень быстрая. Но если процессоров меньше, или их загрузка выше - что будет? Такой скрипт будет мешать работать другим потокам. Собственно, и тем, в которых осуществляется прием тиков. Необходимо уступать процессорное время другим потокам. Варианты:
1 - Sleep
2 - работать не подряд, а только по событиям (сообщениям) от других потоков
   По поводу Sleep прилагаю в текстовом файле Sleep1.txt результат работы строчки, где задержка задана в 1 миллисекунду.

for (k=0;k<=100;k++) {Print((int)TimeLocal()); Sleep(1);}

  За сто шагов время выросло с 07:33:15.226 до 07:33:18.751, то есть в среднем шаг составил 35 миллисекунд. Большинство шагов по 10 мс, и есть скачки по 200 и даже 500 мс. Так сработали в паре системный таймер и планировщик
потоков. Скачки, думаю, из-за того, что в очереди планировщика потоков оказались такие, что требуют столько времени. Единственный способ бороться с ними - управлять приоритетами выполнения приложения (терминала) и его потоков.
При высоком приоритете 10 мс будет постоянным шагом опроса курсов. Тоже ничего по сравнению с 78.4 мс.
   Однако есть известная опасность - если на однопроцессорном компьютере выставить своему приложению самый высокий приоритет, могут перестать работать некоторые службы и сервисы ОС и компьютер повалится, несмотря на все кольца защиты. С другой стороны, по снижению приоритетов у меня есть такой опыт: одна программа работает в фоновом режиме, с приоритетом чуть ниже среднего. Она обрабатывает часовые куски тиковой истории. Были случаи, что накапливала необработанные часы за сутки и дольше, ее не допускали к процессорам другие потоки.
   Мне представляется, что при освобождении процессорного времени по Sleep реальным будет все же просто Sleep(1) без управления приоритетами.
   Такой подход проверил в ситуации не только "мультивалютной", но и "мультиДЦшной", когда принимаются до полутора тысяч котировочных потоков. Ничего, работает. И в случае споров с ДЦ, когда разбор шел по тикам, пропусков не было. Повышать разрешающую способность системного таймера не стал, это тоже чревато неприятностями, а компьютеру нужно работать подряд 120 часов, в том числе в мое отсутствие.
   Проверял еще несколько раз по сто шагов, как ни странно, среднее время стало стабильным - 10 мс. Выяснять подробнее не стал.

  Дальше надо оценивать задержки при работе по событиям. Наверное, самый простой - по событиям от таймера, где можно заранее дать какие-то количественные оценки. Однако у меня есть сильное внутреннее предубеждение против переключения контекстов в случаях, когда не надо принимать сигналы от пользователя. Стараюсь их число минимизировать. Сообщения таймера (прерывания) ставятся в общую очередь сообщений ОС Windows, вместе с сообщениями от клавиатуры, от мыши. Не лежит у меня к этому душа.
   Есть события, не попадающие в эту очередь. Они проходят внутри одного приложения. Как в Metatrader реализована передача событий советникам, сведений у меня нет. Однако обязательность привязки скриптов и советников к окну графика заставляет подозревать, что все же используется та же очередь сообщений окнам.

   В http://stump-workshop.blogspot.ru/2008/01/threadsleep-threadspinwait.html есть оценка: "Ведь, согласно утверждению Джо Даффи, только переключение контекста потоков занимает 4000+ процессорных тактов." То есть 1 микросекунда.

   Извините за незавершенность. Может быть, кто-то заинтересуется и выяснит задержки при работе от таймера или от событий, высылаемых индикаторами. Было бы интересно.

В чем отличие Thread.Sleep() и Thread.SpinWait()
  • 2008.01.24
  • Sergey Rozovik
  • stump-workshop.blogspot.nl
В чем отличие Thread.Sleep() и Thread.SpinWait()? Оба метода позволяют приостановить исполнение текущего потока. MSDN немногословна: Thread.Sleep Blocks the current thread for the specified number of milliseconds. Thread.SpinWait Causes a thread to wait the number of times defined by the iterations parameter. После таких описаний, ИМХО...
Файлы:
Sleep1.txt  6 kb