nikolz (Все сообщения пользователя)

Выбрать дату в календареВыбрать дату в календаре

Страницы: Пред. 1 ... 32 33 34 35 36 37 38 39 40 41 42 ... 72 След.
Прием данных и стаканов в различных потоках
 
Для тех, кому интересно.
----------------------
В результате тестов, получилось  следующее решение:
----------------------------
1)  стаканы и обезличенные сделки  принимаю в колбеках
-----------------------
2) свечи принимаю в main
-------------------------
3) индикаторы и алгоритмы решений реализую в отдельных потоках из пула потоков.
==================
Вот затраты времени на тестовом сервере:
Условие тестирование
220 инструментов
220 стаканов
обезличенные сделки по всем акциям на демо сервер.
=================
Код
SBER,i=829,len=0,SBER
SMLT,i=441,len=0,SMLT
VTBR,i=825,len=0,VTBR
VTBR,(us)=958.1
14,main(us)=11.2
QUote(us)=ALRS,62.4
QUote(us)=GMKN,62.1
QUote(us)=MTSS,59.7
QUote(us)=SBER,57.6
QUote(us)=VTBR,45.1
AllTrade(us)=3.1,GMKN,1293754
AllTrade(us)=1.8,GMKN,1293755
AllTrade(us)=1.5,SBER,1293756
AllTrade(us)=1.5,SBER,1293757
AllTrade(us)=1.4,SBER,1293758
AllTrade(us)=1.4,SBER,1293759
AllTrade(us)=1.3,SBER,1293760
AllTrade(us)=1.5,SBER,1293761
AllTrade(us)=1.4,GAZP,1293762
AllTrade(us)=1.3,POLY,1293763
AllTrade(us)=1.3,POLY,1293764
AllTrade(us)=1.3,POLY,1293765
AllTrade(us)=1.3,ALRS,1293766
AllTrade(us)=1.2,ALRS,1293767
AllTrade(us)=1.3,ALRS,1293768
AllTrade(us)=1.3,YNDX,1293769
AllTrade(us)=1.4,YNDX,1293770
AllTrade(us)=1.2,YNDX,1293771
AllTrade(us)=1.2,KZOSP,1293772
AllTrade(us)=1.3,GMKN,1293773
AllTrade(us)=1.3,ALRS,1293774
AllTrade(us)=1.3,ALRS,1293775
QUote(us)=RIM2,180.9
AllTrade(us)=3.4,SiM2,1293776
QUote(us)=RIM2,127.6
QUote(us)=RIM2,126.8
QUote(us)=RIM2,149.7
QUote(us)=RIM2,129.5
QUote(us)=RIM2,127.7
AllTrade(us)=2.2,RIM2,1293777
В AllTrade  последнее число это всего записей таблице обезличенных сделок примерно 1.3 млн.сделок
-----------
не все то золото, что блестит
 
Информация к размышлению.
Всем известна  рекомендация не делать ничего в колбеках, а переносить все в main.
--------------------------
Но не все то золото, что рекомендуют.
===============
проведем эксперимент.
Колбек AllTrade
обработка данных выполняется так:
Код
local clas=t.class_code;
local sec=t.sec_code;
local t1=Data[clas]; if t1==nil  then t1={}; Data=t1 end
local t2=t1[sec] if t2==nil then t2={} t1[sec]=t2 end
t2[#t2+1]={t.trade_num,t.flags,t.price,t.qty,t.value};
Рассмотрим два варианта
-----------------
В первом случае все делаем в колбеке.
-------------------
В результате получаем  время исполнения (мкс)
Код
AllTrade(us)=2.6,SiM2
AllTrade(us)=1.7,BRM2
AllTrade(us)=2.6,SiM2
AllTrade(us)=2.6,RIM2
AllTrade(us)=1.9,SiM2
AllTrade(us)=3.0,BRM2
Во втором случае те же действия делаем в main.
------------------
В результате получаем:
Код
AllTrade(us)=319.2,SBER
AllTrade(us)=318.0,SBER
AllTrade(us)=335.8,SBER
AllTrade(us)=319.8,ALRS
AllTrade(us)=280.9,SBER
AllTrade(us)=395.5,SiM2
AllTrade(us)=428.8,SiM2
Таким образом,
-------------------
в колбеке  3,
в main   430.

.
Последовательность функций обратного вызова
 
Цитата
Kolossi написал:
Всем добрый день!

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

sendTransaction(...)( задание TRANS_ID) --> OnTransReply(...)(получение номера заявки order_num )-->OnTrade(...)(обработка исполнения заявки с номером  order_num)
Функцию OnOrder() тут не использую благо до сих пор не было необходимости.

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

Прошу у знатоков совета по оформлению последовательности функций обратного вызова для этого типа заявок.
1)   OnTransReply   работает если заявку выставляете или снимаете скриптом.  
Если Выставляете или передвигаете руками, то работает лишь OnOrder.
Т е Ваш робот пропускает мимо ушей все что делает человек.
----------------  
2)  Аналогично OnStopOrder.
В получаемой  им информации есть
linkedorder NUMBER Номер заявки в торговой системе, зарегистрированной по наступлению условия  стоп-цены
Торговый робот для Quick на Delphi, Не работает вывод данные через DDE SERVER
 
Цитата
Артур написал:
Мне нужно именно ето  кто-то сможет помочь  
он под 32 битную версию и использует старую библиотеку
переписывать под 64 бит версию замучаетесь.
На луа будет и код проще и возни меньше.
------------------------
К телеге пристроить двигатель конечно интересно, но малоперспективно.
Бесплатно никто не будет его допиливать, а за плату он станет золотым.
Торговый робот для Quick на Delphi, Не работает вывод данные через DDE SERVER
 
Цитата
Артур написал:
Здравствуйте у меня есть шаблон для создания торгового робота на Delphi 7 когда питаюсь подключить к Qwik у выскочит окошка с ошибкой вот сам робот если вам не трудно исправте ошибку в коде    https://disk.yandex.ru/d/Yba1ln8qfGDBQQ
Выкиньте это  Г-но  ( с большой буквы)  13 летней давности  и пишите на  луа.
Прием данных и стаканов в различных потоках
 
Цитата
Незнайка написал:
Наверное, это можно проверить опытным путём.

Если обращение к хранилищу данных реализовано через одну дверь - основной поток, - то все остальные потоки, сколько бы их не было запущено, выстроятся в одну очередь у входа в дверь. И при запуске нескольких скриптов, "одновременно" запрашивающих, например, данные стаканов мы не увидим сколько-нибудь существенного ускорения по сравнению с одним скриптом, запрашивающим по очереди такое же количество стаканов.
Проверим:
Код
   function   main ()
   local  t  =   os.clock ()
   for  _  =   1 ,  100000   do 
     getQuoteLevel2 (class, sec)
   end 
   message (tostring( os.clock ()  -  t))
 end   
Проведём несколько тестов с 1-м, 2-мя, 3-мя, 4-мя одновременно запущенными скриптами.

Результаты:
1 скрипт: 6.5 сек
2 скрипта: по 15.2 сек каждый
3 скрипта: по 23.1 сек каждый
4 скрипта: по 30.4 сек каждый

При этом, во всех случаях было загружено только одно ядро процессора, что как бы намекает на использование только одного потока для доступа к данным.
Относительно приема с сервера данных в одном потоке я уже писал ранее и приводил тест аналогично вашему.
----------------------------
это связано с тем, что для реализации приема в майн используется общий глобальный стек луа - т е единственная область памяти и следовательно доступ к ней сделан с блокировкой.
================
Относительно приема данных в различных потоках есть разница в получении данных по свечам и по стаканам.
--------------
История Стаканов  очевидно не хранится в архиве, поэтому прием стакана выполняется в основном потоке и изменяет образ стакана в архиве.
----------------
Со свечами дело иначе.  
Закрытые свечи - это история и она накапливается в архиве. Прием же выполняется лишь по незакрытой свече.
Поэтому чтение свечи из истории вполне допустимо в различных потоках одновременно.
------------------
Но чтобы это было возможно, надо реализовать в QLUA механизм работы с глобальным стеком Один пишет -все читают. А это очевидно разработчики делать не стали.
Поэтому и не выходит каменная чаша.
=============
Но даже в этом случае , прием в различных потоках пусть и последовательно позволяет ускорить вычисления по сравнению с приемом в одном потоке.
----------------
Приняв на грудь стакан, поток приступает к его обработке, а следующий поток примет свой стакан и начнет его обрабатывать параллельно с первым.
-------------
Таким образом, даже в случае последовательного приема потоками  стаканов,  обработку их содержимого потоки будут делать параллельно .
------------------
Так как основное время  умный робот тратит не на прием стаканов, а на анализ их содержимого и беседу с товарищами, которые тоже приняли по стакану,
то прием даже по очереди стаканов  актуален и перспективен.
Прием данных и стаканов в различных потоках
 
Цитата
Незнайка написал:
Цитата
nikolz написал:
Прием данных от источника и стаканов реализуется  в main.
-----------------
Все работает замечательно.   Но узким местом  является прием данных всех инструментов в одном потоке main.
-----------------------
Хочу принимать данные и стаканы в  отдельном потоке   каждого  инструментов.

А разве приём данных идёт не через основной поток? Хоть тысячу отдельных потоков сделай, они все встанут в очередь при обращении к хранилищу.
Или вы располагаете другой информацией?
Как сделали разработчики, знают лишь они.
---------------
Могу предположить, что есть как минимум два слоя приема данных.
-----------------------
Первый - это прием по каналу  связи данных с сервера и запись их в архив терминала.
-------------------------
Возможно, что на этом этапе мы можем данные получать через колбек источника.
---------------------
Второй - это чтение уже принятых данных из хранилища терминала - это делают функции O,H,L,C,V,T.
=================
Для многопоточного получения этих данных важным фактом является то, что нам не надо писать эти данные в архив.
---------------------------
Так как в потоках мы лишь читаем из архива уже размещенные там банные  , то никакой синхронизации потоков нам не требуется.
-------------------
Т е в данном случае потоки работают по принципу один пишет - остальные читают.
==============
Поэтому прием данных лишь в основном потоке реализуется в худшем случае лишь в первом слое.
=================
Я не использую колбек  источника данных для приема ,
поэтому предполагаю возможность одновременно ходить в архив любому количеству потоков.
Отладка QUIK 8.13
 
и еще в тесте с выставление заявок загрузка процессора не превышала 5%.
Отладка QUIK 8.13
 
Цитата
TGB написал:
Цитата
nikolz написал:
Так что HFT робот вполне  реально, но должен быть в дата центре.
   Дата центр вам не поможет. Вам надо арендовать для вашего QUIK специальный сервер на бирже с прямыми каналами доступа к торгам.
  Но и это вам не поможет при использовании стандартного рабочего места QUIK, так как API взаимодействия QLua с QUIK выполняется в среде Lua, в которой автоматическое управление памятью, и в произвольные моменты времени может запускаться сборка мусора. Сборка мусора может вносить заметные задержки (не исключено миллисекундные) при взаимодействии вашей программы с QUIK. Вы, конечно, можете отключить сборку мусора, но тогда флаг вам в руки :: . Попробуйте.
----------
  Вообще, надо заниматься тем, о чем есть хоть какое-то понятие.  HFT роботы не "манна небесная" и о проблемах их использования (как технических так и алгоритмических) достаточно информации в интернете.
объясняю почему у меня сборщик не мешает.
Тестировал своего робота на выставлении и снятии заявок по 200 инструментам. При этом осуществлялся прием данных по каждому из инструментов по таймам 1,3,30 мин.
Работал примерно 4 часа. выставил и снял  150 тысяч заявок.
Размер памяти скрипта составил 5 Мбайт. При работе моих скриптов практически нет мусора.
Если сборщик будет мешать, то я его могу отключить от слова навсегда.
При этом размер матрицы -маппинг фалов на диске открывался по 2 Мбайта на инструмент. т е 400 Мбайт.
-------------------  
Прием данных и стаканов в различных потоках
 
Цитата
swerg написал:
Цитата
В функции main для каждого инструмента запускается свой поток.  Потоки берутся из пула.

Без иллюстрации кодом вот этого момента, сказать что-то предметное - невозможно.
Ибо не понятно чем ваши потоки (где не работает) отличаются от потока main (где работает).
У меня в потоках запускаются скрипты, но в них нет библиотеки QLUA.
Как ее туда включит пока не разобрался.
---------------------
Относительно main.
Возможно  ошибаюсь,  Но как я понял, в main и основной программе скрипта используется общий глобальный стек.
Делал так, и вроде бы работает получение данных, но неустойчиво.  
===============
В настоящее время я принимаю данные для всех инструментов в main.
----------
А в скриптах других потоков использую  матрицу данных, которая реализована через мапинг.  
Через эту матрицу все скрипты получают доступ к любым данным любого потока.
При этом нет дублирования данных, но могу работать с векторами  данных до 2 миллиардов элементов  и таким же числом векторов.
--------------------
Так как реализую принцип - один пишет - все читают, то никакой  синхронизации не требуется , так как нет конфликтов потоков.
--------------------
Синхронизацию требуется между колбеком, main и вызовом потока для конкретного инструмента.
-----------------------
Так как возможна ситуация, когда в очереди уже есть инструмент, либо для этого инструмента уже запущен поток.
--------------
Тут я использую  синхронизацию колбека и майн через  системный event, а синхронизацию потока и очереди через атомарные операции.
-----------------
Все работает просто замечательно.  
===============
Провел тест  максимального числа потоков,.
В результате получилось,  что в пуле было открыто 11 потоков.
------------------
Причем  первый поток  запускался 23 тысячи раз, а одиннадцатый - 2 раза.
------------------
Потоки и прием данных активировались по колбеку  onParam по 200 инструментам на тестовом сервере.
--------------------
Время вызова колбека составляло в основном 10 мкс.  
-----------------------
Понятно, что данные на самом деле приходили пакетом и в данном случае это время реакции на очередную запись в пакете данных.
================  
В итоге, пока не получилось разнести прием данных по различным потокам, чтобы работало устойчиво.
------------------
Причину не знаю.
-------------------------
Если что-то подскажите, буду признателен.
 
Отладка QUIK 8.13
 
и еще...
-------------------  
вам только кажется, что скрипт в main у Вас на чистом луа.
---------------
На самом деле вы используете в main QLUA А она на СИ.
============
Кроме того, есть срытый от Вас тормоз, который заложен в основание main.
=================
Дело в том, что все функции колбека объявляются как глобальные .
все функции библиотеки QLUA тоже являются глобальными.
--------------------------
Т е  скрипт в основном потоке и в потоке main  имеют общий глобальный стек.
Это значит, что main и колбеки не могут одновременно как минимум записывать данные в глобальные переменные.
А как максимум, вообще  обращаются к глобальному стеку последовательно.
=================
Т е поставьте тормоз в колбеке на глобальной функции и функция main начнет глючить и тормозить либо пропускать обработку
Можно сделать и наоборот.
===============
Поэтому периодически и вылетают непонятки, которые особо пытливые ловят и выкладывают  на форуме.
Но прикольно то, что разработчики такие глюки не поймают от слова никогда, так как им для этого надо весь глючный скрипт и соответствующий поток данных.
==============  
В итоге, так как проблема в концепции построения скриптов, то бороться с ней Вы будете вечно.
Желаю успехов.
Отладка QUIK 8.13
 
Цитата
Владимир написал:
nikolz, Ни секунды не было сомнений, что "робот с любым числом алгоритмов и любым числом инструментов должен работать  в одном скрипте QUIK"

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

Любой алгоритм для работы робота пишется в виде скрипта на чистом луа, без QLUA и выполняется в потоке main для всех инструментов.

Параметры по инструменту или портфелю хранятся в одной глобальной переменной (таблице Lua) и никуда не передаются.

И никаких индикаторов!

Тестировал  данную реализацию на разном количестве инструментов - обычно до двух тысяч (пробовал и на 20000, но притормаживает).

Ну очень нравится как оно работает в любой из версии Lua и QUIK.

Всё это работает вообще без каких-либо библиотек.

Очень быстро у меня исчезли любые пожелания по допиливанию QUIK. Я их просто боюсь - не все ещё глупости сделаны.

А насчёт HFT на QUIK согласен: это диагноз. ::  
Так  тоже делал.
----------------------------
Но узкое место в таком решении - это один поток main для всех инструментов.
--------------------
Если тестировали, то хорошо бы увидеть конкретное затраченное время на обработку  изменений всех инструментов в потоке main.
------------------  
Возможно, что вас устраивает такое решение, а мне интересно  иное.
------------------
Мое решение позволяет масштабировать робота  по алгоритмам , инструментам и приложениям.
---------------
К сожалению, не видел пока каких-либо подробных тестов по быстродействию сторонних решений ,  в том числе и Ваших .
===========
В моем варианте реакция робота на заявку и изменение цены составляет не более 100 мкс.
------------------------
Это время вполне соизмеримо с реакцией существующих HFT роботов.
-----------------------------
А уж в сравнении с человеком, который играет в стакане с реакцией в 1000 раз медленнее, чем мое решение Вообще говорить не серьезно.
-------------------------
Так что HFT робот вполне  реально, но должен быть в дата центре.
============  
Кроме того мое решение универсально и позволяет делать скрипты на луа многопоточные,.  
=============
Следующим  этапом моего решения будет самообучающийся робот.
-------------------
Следите за новостями.
 
Отладка QUIK 8.13
 
Цитата
TGB написал:
Цитата
Roman Azarov написал:
Данные пожелания еще не были рассмотрены. Как только появится какая-то новая информация, мы сообщим об этом в данной ветке форума.
Мое предложение от  22.04.2021 15:59:54
https://forum.quik.ru/messages/forum10/message55019/topic6356/#message55019  
Прошел год.
-----------------
 Напомню описание ситуации и вариант ее устранения.
---
 Бывают ситуации зависания в QLua, когда основной поток обслуживания колбеков всех скриптов пользователя, а также таблиц QUIK (это не таблицы Lua), блокируется выполнением  длинного цикла пользовательской программы на «чистом» Lua, в котором нет ни вызова seep ни вызова дру-гих C-функций.
Это может порождать ошибки, которые для многих пользователей QLua (использующих несколько запускаемых скриптов)  являются неожиданными и труднообъяснимыми. Блокируются выполнения колбеков всех скриптов из-за выполнения длинного цикла пользовательской программы на «чистом» Lua в каком-то из запущенных пользователем скриптов.  При этом зависает рабочее место QUIK. Это системная ошибка QLua.
----
  Есть простой вариант реализации пожелания (далее список изменений, реализующих этот вариант в тексте исходников QLua ):
1. В файле   lstate.h  после строки:  lu_byte allowhook;
добавить: int Счетчик_для_переключения_State;
2. В файле   lstate.с  после строки:  L->errfunc = 0;
добавить:  L->Счетчик_для_переключения_State = 0;
3. В файле   lstate.с  после строки:  L1->stacksize = BASIC_STACK_SIZE;
добавить:  L1->Счетчик_для_переключения_State = 0;
4. В файле   lvm.с  после строки:  StkId ra;
добавить:  
if (++L->Счетчик_для_переключения_State > 1000) {   //  1000  надо задать кон-стантой  
 L->Счетчик_для_переключения_State = 0;
 lua_unlock(L); lua_lock(L);
}
-----------------------
В чем проблема реализации этого пожелания?
Таких проблем не существует, если делать как у меня.
---------------------------
Робот с любым числом алгоритмов и любым числом инструментов  работает  в одном скрипте QUIK.
-------------------------
Каждый колбек существует лишь в одном экземпляре.
------------------------
Любой алгоритм для работы робота пишется в виде  скрипта на чистом луа, без QLUA
и загружается в отдельный поток для конкретного инструмента  функцией main скрипта QUIK.
------------------------
Параметры по инструменту или портфелю передаются как параметры функции в скрипт алгоритма,
а данные и индикаторы - в виде mapping матрицы.
----------------------------
Тестировал  данную реализацию  на двух сотнях инструментах.
=================
Ну очень нравится как оно работает на версии 9.4.  
----------------------------
Можно делать HFT, чего раньше даже не думал, что на LUA в квике будет так быстро работать.
-------------------------------
Правда все это работает с моей библиотекой на СИ.
---------------------
В итоге ,
В настоящее время Вообще нет никаких пожеланий по допиливанию QUIK.


 
Прием данных и стаканов в различных потоках
 
Добрый день,
Ищу решение следующей проблемы.
----------------  
Сейчас у меня реализовано так:
--------------------
В функции main для каждого инструмента запускается свой поток.  Потоки берутся из пула.  Если свободного нет, то создается новый.
------------------
Данные передаются в поток через параметры скрипта и мапинг-файлы.
------------------
Прием данных от источника и стаканов реализуется  в main.
-----------------
Все работает замечательно.   Но узким местом  является прием данных всех инструментов в одном потоке main.
-----------------------
Хочу принимать данные и стаканы в  отдельном потоке   каждого  инструментов.
------------------
Применение общего глобального стека не дает результата.
----------------------  
Если кто-то решил данную проблему, просьба сказать каким методом.
------------
Спасибо
=================  
Отдельная пожелание разработчикам.
Реализовать указанные функции для приема данных и стаканов для произвольного потока.
Проблема с макросом после вывода из Квика по DDE в Excel.
 
Цитата
Denis написал:
Цитата
nikolz написал:
 
Цитата
Denis  написал:
В смысле как обозначаются эти параметры у Квика при экспорте по DDE?
 сделайте вывод по DDE в excel c флагом  формальные заголовки
и получите все имена столбцов таблицы.
Вы видимо не поняли, вопрос совершенно в другом. Заголовки вывести не проблема.
В настройке работы макроса с выводом по DDE необходимо указать следующие данные:
DDEInitiate (App, Topic)
DDERequest (Channel, Item).
то что напишите в окошке  "вывод через DDE" "Рабочая книга" и "Лист"
OnTransReply для опционов, OnTransReply для опционов не вызывается
 
Цитата
Дмитрий написал:
Напрочь отказывается вызываться функция OnTransReply для опционов. Один в один написан код для заявки на фьючерс и опцион, по факту обе заявки системой выставляются, по итогу  OnTransReply для фьючерса вызывается, а для опциона нет. Пробовал и вместе, и отдельно опцион запускать - ни фига.
p.s. подскажите, а есть на форуме поисковик по ключевым словам? может этот вопрос был в другим темах, но при отсутствии поисковика очень трудоемко все листать  
если колбек на транзакцию не вызывается то ошибка в тексте заявки.
эту ошибку  можно прочитать а   ответе  sendTransaction (см документацию)
Проблема с макросом после вывода из Квика по DDE в Excel.
 
Цитата
Denis написал:
В смысле как обозначаются эти параметры у Квика при экспорте по DDE?
сделайте вывод по DDE в excel c флагом  формальные заголовки
и получите все имена столбцов таблицы.
# и table.getn, # и table.getn - косячно
 
Цитата
Владимир написал:
Nikolay, Это если их инициализировать прямо в коде. У меня большинство массивов начинаются с нуля, а за дырками (в тех массивах, где они возможны) и размерами массивов слежу сам. Например, в стеках (заявок, сделок, прерываний) длина массива (она же ID последнего элемента) хранится как раз в его нулевом элементе. Очень удобно и очень надёжно, и плевать, что там "оператор #" по этому поводу думает - им я вообще не пользуюсь. Не говоря уже про "переопределенные метаметоды".
почти как у меня, тоже в нулевом - максимальный размер таблиц сделок и стопов, но храню не стеком.а таблицей.
Стек - это кипа -  LIFO.
В этом случае у Вас последний обрабатывается первым, а до первого очередь может никогда не дойти.
Должна быть либо очередь либо таблица.  
Проблема с макросом после вывода из Квика по DDE в Excel.
 
Цитата
Denis написал:
Добрый день!
Описание проблемы ниже, буду благодарен за помощь. В работе множество таблиц, поэтому
переносить данные в ручном режиме каждый день не очень удобно.

Проблема:
Есть макрос в Эксель, который сортирует данные из Квика. Макрос работает отлично,
если данные в него добавить руками через "копи-паст". Эти же данные, точно так же
экспортированные в Эксель через DDE макрос не видит.

Погуглив вопрос, узнал, что такая проблема имеет место быть. Для корректной работы
макроса нужно сообщить, что данные поступают по DDE. Cудя по справке Excel нужно знать
приложение ведущее вещание по dde и что-то типа "имени документа" этого приложения.
Прилагаю два скриншота.  
возможно поможет.
При экспорте по DDE таблиц надо отключить все фильтры таблицы.
KILL_ORDERS, KILL_ORDERS не отрабатывает
 
Цитата
Дмитрий написал:
sendTransaction (transaction_kill)
так как нет колбека, то ошибка вероятно в транзакции.
--------------------------------
сделайте так:
---------------
s=sendTransaction (transaction_kill)
message( tostring(s))
KILL_ORDERS, KILL_ORDERS не отрабатывает
 
и еще
t.status
KILL_ORDERS, KILL_ORDERS не отрабатывает
 
Цитата
Дмитрий написал:
Такой простенький код:

function transaction_stock_kill ()
   message('transaction_stock_kill poshlo '..Num_Z [j])
   t_kill = tostring (os.time())
   transaction_kill = {
       CLASSCODE = ClassCodeSt,
       SECCODE = "GAZP",
       ACTION = 'KILL_ORDERS',
       ORDER_KEY = tostring (Num_Z [j]),
       TRANS_ID = t_kill
                                  }
  sendTransaction (transaction_kill)
  message('TRANS_ID '..transaction_kill.TRANS_ID)
end

Номер заявки совпадает с табличным в QUIKе (первое сообщение в коде). Транзакции на снятие заявки проходит - второе сообщение в конце с TRANS_ID выходит (т.е. транзакция прошла), а по факту снятие активной заявки не происходит, почему так? чего не хватает?  
1) отобоазите сообщение которое возвращает sendTransaction;
2) если  колбек OnTransReply(t)  принимает ответ сервера, то выведите сообщения
t.result_msg;
а также
t.error_code , t.error_source
--------------------
и будет понятно что и где.
Количество активных заявок одной командой, Количество активных заявок одной командой
 
Цитата
just написал:
Цитата
nikolz написал:
исправил опечатку:  
Код
      local   S  =   "orders" ;   local   t  =    SearchItems  (S,  0  ,  getNumberOf  (S)  -    1  ,  function  (flag)   if     bit.band  (flag,  3  )~  =    1      then     return     false     end     return     true     end  ,  "flags" )   -- #t -число активных заявок  
    
 
Спасибо.
1. А меняет ли что-то именно такая процедура в сравнении с простым перебором в цикле?

2. Для проверки активной заявки у Вас используется кроме бита активной заявки еще и бит "заявка снята", это же, не обязательно?

3. А вообще в моем случае вопрос можно решить очень просто. Ответ можно найти, просто внимательно изучив вопрос... :) Большое спасибо ВСЕМ за участие и советы...

tonumber(getFuturesHolding(fClass, Account, fFirst, 0).openbuys)+tonumber(getFuturesHolding(fClass, Account, fFirst, 0).opensells)
1.  быстрее.
2. бывает так, что приходит заявка с установленными 0 и вторым битом.   такая заявка снята. Но бит активности есть. Проверка исключает эту ситуацию.  
Количество активных заявок одной командой, Количество активных заявок одной командой
 
Цитата
Старатель написал:
Постоянно сканировать таблицу orders - не лучшая затея: при большом числе заявок гарантированы тормоза.
Самый простой вариант - работать с колбеками OnOrder и OnCleanup.
В OnOrder проверяете статус заявки, если активна добавляете в таблицу. Если заявка исполнена или снята (в т.ч. в клиринг), вы получите об этом OnOrder и удалите из таблицы активных.
После смены сессии при получении OnCleanup таблицы активных полностью очищаете.
Все возможные варианты (разрыв соединения, исполнение заявки пока терминал находился офлайн, восстановление соединения через день, месяц, год, задержка ответа по заявке на 10 мин и пр.) будут полность покрыты этими двумя колбеками.
Если заявки выставлены до запуска скрипта, то колбек на них не реагирует, пока  они не изменятся.
------------------
Количество активных заявок одной командой, Количество активных заявок одной командой
 
Цитата
Владимир написал:
Nikolay,  
Цитата
Может быть так, что терминал упал вчера, а восстановился только сегодня.
Убей, не понимаю, зачем нужно искать на свою жопу приключений.  Посмотрим на постулаты (ну или гипотезы):
1. Скрипт непрерывно работает часами (или даже днями, неделями).
2. Всё время, пока он работает, он мониторит состояние рынка, портфеля, кошелька и т.п.
3. В любой момент своей работы он может послать заявку на совершение сделки - с тем тикером и по такой цене, которая его устраивает здесь и сейчас.
4. Количество сделок, которые скрипт совершает в сутки, может варьироваться от единиц (при такой частоте, собссно, скрипт вообще не нужен) до десятков тысяч (при сотнях Квик наверняка сдохнет, да и при десятках спорный вопрос), т.е. допустимый диапазон десятки-сотни-тысячи сделок в сутки.
5. Количество ошибок при сделках в сутки (по любым причинам) может исчисляться ну никак не больше, чем единицами (иначе такой софт нужно просто выбросить на помойку), а потому интервалы между процедурами выявления таких ошибок должны составлять минуты, десятки минут, часы, но никак не секунды.
6. Чем позже принимается решение о сделке, тем (потенциально) у скрипта больше информации для его принятия.
7. Чем позже исполняется принятое решение о сделке, тем больше вероятность, что ситуация изменилась, и это решение уже устарело, что оно не было бы принято в тот момент, когда заявка исполнилась.
Вопрос: ТАК ЗА КАКИМ ХЕРОМ заниматься всем этим онанизмом? Что, трудно сбросить к чертям собачьим все открытые заявки при остановке или включении скрипта? Или посылать заявки именно тогда, когда скрипт посчитает нужным их совершить? У меня 90% заявок исполняются в течение нескольких секунд, а не исполненные снимаются через 3 минуты активности - всё, поезд ушёл, решение устарело! Зачем искать на свою жопу приключений? НЕ ПОНИМАЮ!
сегодня на тесте скрипт  по 36 акциям за час выставил и снял 64 тысячи заявок.
мог бы и больше, то тестовый сервер обновляет данные раз в секунду.
И КВИК не сдох.
----------------------  
Сейчас на бирже несколько тысяч инструментов.
----------------------  
Есть различные стратегии торговли.
Одна из них - на основе сканирования рынка и обнаружения начала тренда.
В этом случае надо просматривать быстро эти тысячи.
Поэтому скорость работы скрипта имеет значение.
-----------------------  
Кроме того, на КВИКЕ можно даже HFT робота сделать,
но его надо  размещать в дата центре.
--------------------------------  
Поэтому запас скорости никому не помешает.
=======================  
Но есть и любители ехать на телеге.  
Каждому-свое.
Количество активных заявок одной командой, Количество активных заявок одной командой
 
исправил опечатку:
Код
local S="orders"; local t=SearchItems(S,0,getNumberOf(S)-1,function(flag) if bit.band(flag,3)~=1  then return false end return true end, "flags") -- #t -число активных заявок
Количество активных заявок одной командой, Количество активных заявок одной командой
 
Цитата
just написал:
Здравствуйте.

Подскажите, пожалуйста, а можно как-то покороче получить число активных заявок, не перебирая всю таблицу orders?

Что-то типа tonumber(getFuturesHolding(fClass, Account, fFirst, 0).totalnet) - для получения текущей позиции по инструменту?
можно так :
Код
local t=SearchItems(S,0,getNumberOf("orders")-1,function(flag) if bit.band(flag,3)~=1  then return false end return true end, "flags") -- #t -число активных заявок
Количество активных заявок одной командой, Количество активных заявок одной командой
 
поправлю на запись о регистрации или снятии (исполнении) заявки уходит не более 10 мкс
---------------
на формирование и отсылки транзакции на снятие заявки уходит до  300 мкс
----------------------------
на формирование  и отсылку транзакции на новую заявку уходит 400 мкс
Количество активных заявок одной командой, Количество активных заявок одной командой
 
в итоге на регистрацию или снятие заявки уходит не более 10 мкс.  
Количество активных заявок одной командой, Количество активных заявок одной командой
 
я например сканирую таблицу лишь при включении скрипта.
после этого к таблицам квика заявок и стоп заявок  скрипт не обращается вообще.  
Количество активных заявок одной командой, Количество активных заявок одной командой
 
Цитата
Nikolay написал:
Вы, конечно, можете постоянно не сканировать активные заявки по таблице. При первичной постановке ордера необходимо один раз найти ордер в таблице ордеров и запомнить индекс таблицы. Тогда последующие обращения уже будут простые, без поиска.
Если же речь про то, чтобы вообще не искать ордера, то для лимитных ордеров - это не лучшая затея, т.к. в клиринг их снимут и необходимо предпринять какие-то действия. Да, можете по колбеку получить новое состояние ордера и отреагировать, но это если этот колбек не был пропущен.
не все так просто.
Например,  уже есть активные заявки до включения скрипта.
либо произошел разрыв соединения и восстановление через несколько минут и часть активных заявок сработали.
Ну и т д
Запуск скрипта из примера подвешивает терминал Quik
 
поправил
работает быстро
Код
function main()
   while is_run do
      while #MAIN_QUEUE > 0 do
         ProcessingCallbakc(MAIN_QUEUE[1])
         table.sremove(MAIN_QUEUE, 1)
      end
      sleep(100)
   end
end

function ProcessingCallbakc(value)
   message(string.format("Обработка события %s начата", value.callback))
   message(string.format("Обработка события %s завершена", value.callback))
end
Запуск скрипта из примера подвешивает терминал Quik
 
можно сделать main  так:
Код
  
function main()
   while is_run do
      while #MAIN_QUEUE > 0 then
         ProcessingCallbakc(MAIN_QUEUE[1])
      table.sremove(MAIN_QUEUE, 1)   
      end
            sleep(100)
   end
end

function ProcessingCallbakc(value)
   message(string.format("Обработка события %s начата", value.callback))
   message(string.format("Обработка события %s завершена", value.callback))
end    
Запуск скрипта из примера подвешивает терминал Quik
 
В этом примере куча алгоритмических и смысловых ошибок и заблуждений.
----------------------
Например, зачем в очередь записывать множество изменений цены инструмента , полученные onParam?
Если main  не успело обработать 999 изменений из 1000, то 999 устарели и важно лишь последнее.  
Запуск скрипта из примера подвешивает терминал Quik
 
В этом примере куда алгоритмических и смысловых ошибок и заблуждений.
----------------------
Например, зачем в очередь записывать множество изменений цены инструмента , полученные onParam?
Если main  не успело обработать 999 изменений из 1000, то 999 устарели и важно лишь последнее.  
Запуск скрипта из примера подвешивает терминал Quik
 
В этом примере куда алгоритмических и смысловых ошибок и заблуждений.
----------------------
Например, зачем в очередь записывать множество изменений цены инструмента , полученные onParam?
Если main  
Запуск скрипта из примера подвешивает терминал Quik
 
В этом примере куда алгоритмических и смысловых ошибок и заблуждений.
----------------------
Например, зачем в очередь записывать множество изменений цены инструмента , полученные onParam?
Если main  
Запуск скрипта из примера подвешивает терминал Quik
 
Цитата
Konstantin написал:
Вот  этот пример  из PDF "Использование Lua в Рабочем месте Quik" (пункт 2 "Взаимодействие потоков Lua скрипта") вешает терминал.
Что я делаю не так
поясню в чем проблема.
В данном примере все колбеки записывают свою информацию в таблицу.
Функция main обрабатывает первую  запись этой таблицы в функции  ProcessingCallbakc
потом удаляет эту запись и обрабатывает следующую
При этом в функции   ProcessingCallbakc есть sleep(3000) т е после обработки каждой записи спим 3 секунды
Выше я привел данные по скорости работы колшбеков
примерно 3 мкс
за время сна 3 секунды в таблицу которую орабатывает main успеет записаться 1000 строк из колбеков
Поэтому и зависает
-------------------  
Это очень плохой пример.
в нем не только плохо сделана работа с колбеками
но и используется удаление строк ирз таблицы что вызывает сдвиг всех строк - это очень медленно так как у Вас в этой таблице уже строк 1000
--------------------
Короче это пример как нельзя писать скрипт.
Какой-то дебил  написал этот примаер.
Запуск скрипта из примера подвешивает терминал Quik
 
Цитата
Владимир написал:
nikolz, Использование sleep - ЛУЧШЕЕ решение! Простое, отлаженное, работающее, эффективное. Не sleep (1), конечно, а sleep (500). Использовать меньшие задержки в скриптах для торговли не вижу ни малейшего смысла. А если нет диалога, то и вообще sleep (1000).
Владимир,
Сможете как-то обосновать Ваше решение лучшего выбора sleep и и величины 500 ms?
------------------------
Раньше Вы писали, что торгуете по 1000 инструментам.
Тогда поясните сколько времени уйдет на обработку  изменений цены инструмента,
если на один инструмент Вы тратите не менее 0.5 секунды сна + время обработки?
------------------------
Запуск скрипта из примера подвешивает терминал Quik
 
относительно sleep.
-------------------------------------
например
вот время реакции колбеков и main.
колбеки вызываются   каждые 2- 5 мкс.
Sleep (1)   даст задержку на 1000 и более мкс.
Вот и посчитайте сколько сигналов изменения цены инструмента Вы пропустите с таким сном.
Код
15,_____(us)=1.8
OnParam(us)=4.2
SBER,kil(us)=1.7 0>0
SBER,ds(us)=3122.7
SBER,set(us)=295.4
14,_____(us)=3506.6
TransReply t(us)=7.2
moneyLimit t(us)=0.5
DepoLimit,SBER,set(us)=0.6
3,_____(us)=153.4
OnParam(us)=46.2
SBER,kil(us)=210.5 1>0
SBER,ds(us)=4.4
SBER,set(us)=179.7
14,_____(us)=603.8
Order t(us)=2.3
Order t(us)=1.4
TransReply t(us)=2.4
Order t(us)=2.0
OnParam(us)=4.5
AFKS,kil(us)=204.9 1>0
AFKS,ds(us)=3187.4
AFKS,set(us)=50.8
14,_____(us)=3676.0
OnParam(us)=4.6
SBER,kil(us)=2.6 0>0
SBER,ds(us)=2.5
SBER,set(us)=508.2
14,_____(us)=1055.1
Order t(us)=2.1
moneyLimit t(us)=0.4
DepoLimit,SBER,set(us)=0.7
3,_____(us)=155.7
TransReply t(us)=1.4
Order t(us)=1.7
TransReply t(us)=4.5
moneyLimit t(us)=0.6
DepoLimit,SBER,set(us)=0.7
3,_____(us)=157.9
DepoLimit,SBER,set(us)=0.5
Работа терминала QUIK с отдельным монитором
 
Цитата
k4rkpin написал:
Цитата
Kalmar написал:
Я спросил что значит "мониторы не связаны в единое пространство"?
чтобы второй монитор не был продолжением  рабочего стола (пространства) первого монитора , то есть, чтобы на 2-й не могли попадать окна от программ, за исключением терминала Quik..Пусть Quik выводит излбражение только на 2-й монитор, а остальные программы только на 1-й

возможно так в Windows?.

А для манипулятора мышь,  желательна возможность работы с мониторами 1 и 2.
У меня так и работает уже лет ...дцать.
Поместите окно квика на второй монитор и щелкните в правом углу окна терминала - во весь экран
Будет ровно на весь второй монитор.
На первом также делайте для программ на тервом.
Запуск скрипта из примера подвешивает терминал Quik
 
Цитата
Anton Belonogov написал:
Konstantin, добрый день.
Такое поведение связано с особенностями работы Lua-машины: при использовании бесконечных циклов в скрипте необходимо вносить небольшую задержку, иначе возникают зависания.
Таким образом, для корректной работы данного скрипта в цикл  while  в теле функции  main  нужно добавить функцию  sleep :
Код
   function   main ()
     while  is_run  do 
         if   # MAIN_QUEUE  >   0   then 
            ProcessingCallbakc(MAIN_QUEUE[ 1 ])
             table.sremove (MAIN_QUEUE,  1 )
             message ( "Размер очереди "   ..  tostring( # MAIN_QUEUE))
         end 
         sleep ( 1 )
     end 
 end   
В примере уже есть sleep на 3 секунды
куда еще и зачем?
Запуск скрипта из примера подвешивает терминал Quik
 
если  комп с несколькими ядрами, то ничего не вешает.
---------------------
Я использую системные события для синхронизации потоков.
-------------------------
Без синхронизации загрузка процессора 33%
с синхронизацией  1-5%.
---------------------
Использование sleep не лучшее решение.
--------------------------
Проще и лучше, если не используете системное событие , использовать флаги.
Сдвиг массива без цикла for или while, Возможно ли сдвинуть массив без цикла for или while, если количество строк массива может изменяться?
 
Цитата
Айдар написал:
Подскажите, пожалуйста, для понимания вот полный код:
Например так:
---------------------------
table.remove(t,1)  
не все то золото, что блестит
 
таблица не очень
поэтому повторю ее еще раз:
Код
_tk(us)=1.2
SBER(us)=3089.9
__tk(us)=3124.1
TransReply t(us)=2.3
Order t(us)=6.3
TransReply t(us)=0.9
Order t(us)=5.0
SBER(us)=165.5
__tk(us)=199.4
Order t(us)=3.3
Order t(us)=2.6
__tk(us)=1.4
__tk(us)=1.3
__tk(us)=11.1
SBER(us)=182.7
__tk(us)=221.2
FLOT(us)=3879.5
__tk(us)=3916.3
TransReply t(us)=7.2
__tk(us)=119.8
FLOT(us)=547.5
__tk(us)=587.2
Order t(us)=11.5
Order t(us)=9.0
LKOH(us)=4958.5
__tk(us)=3586.8
__tk(us)=2.1
__tk(us)=0.9
TransReply t(us)=7.2
TransReply t(us)=1.1
Order t(us)=3.4
FLOT(us)=224.7
__tk(us)=397.8
LKOH(us)=540.6
__tk(us)=687.2
Order t(us)=6.2
Order t(us)=2.7
Order t(us)=2.4
__tk(us)=1.6
__tk(us)=1.4
SBER(us)=190.5
__tk(us)=223.0
__tk(us)=0.9
SBER(us)=199.9
__tk(us)=344.4
__tk(us)=0.9
SBER(us)=224.4
__tk(us)=268.7
SBER(us)=217.0
__tk(us)=255.2
SBER(us)=223.6
__tk(us)=263.0
__tk(us)=1.1
LKOH(us)=362.7
__tk(us)=406.7
SBER(us)=216.2
__tk(us)=236.4
__tk(us)=1.0
CHMF(us)=4883.2
__tk(us)=4917.7
TransReply t(us)=7.9
__tk(us)=2.1
__tk(us)=1.6
CHMF(us)=733.1
__tk(us)=774.4
SBER(us)=169.0
__tk(us)=185.8
Order t(us)=3.3
Order t(us)=2.4
TransReply t(us)=2.7
Order t(us)=3.8
CHMF(us)=614.0
__tk(us)=834.3
RNFT(us)=3410.1
__tk(us)=3447.4
Order t(us)=8.0
__tk(us)=1.8
__tk(us)=11.0
TransReply t(us)=10.4
TransReply t(us)=2.3
__tk(us)=2.3
__tk(us)=1.6
__tk(us)=1.4
__tk(us)=1.4
CHMF(us)=482.3
__tk(us)=660.0
RNFT(us)=441.2
__tk(us)=459.7
__tk(us)=0.9
Order t(us)=3.6
Order t(us)=2.9
Order t(us)=2.8
Order t(us)=2.8
TransReply t(us)=2.9
__tk(us)=1.8
TransReply t(us)=1.6
Order t(us)=3.3
CHMF(us)=620.0
__tk(us)=797.2
SBER(us)=187.0
__tk(us)=208.0
__tk(us)=1.0
Order t(us)=3.8
Order t(us)=3.1
Order t(us)=2.9
__tk(us)=1.9
__tk(us)=1.6
TransReply t(us)=6.9
__tk(us)=2.4
__tk(us)=1.8
AFKS(us)=3926.4
__tk(us)=3960.6
Order t(us)=5.9
Order t(us)=2.4
TransReply t(us)=8.5
__tk(us)=1.8
AFKS(us)=501.9
__tk(us)=538.4
LKOH(us)=163.5
__tk(us)=183.6
SBER(us)=159.5
__tk(us)=180.2
__tk(us)=1.1
Order t(us)=4.2
Order t(us)=3.2
TransReply t(us)=3.7
Order t(us)=4.2
AFKS(us)=348.4
__tk(us)=524.3
Order t(us)=5.0
SGZH(us)=4205.9
__tk(us)=3090.5
__tk(us)=1.9
__tk(us)=0.7
TransReply t(us)=5.9
TransReply t(us)=2.2
Order t(us)=4.3
AFKS(us)=503.0
__tk(us)=605.1
MRKV(us)=1123.5
__tk(us)=1239.7
__tk(us)=1.0
Order t(us)=3.7
Order t(us)=3.1
Order t(us)=2.7
__tk(us)=1.9
__tk(us)=1.6
__tk(us)=1.8
TransReply t(us)=11.4
TransReply t(us)=1.7
__tk(us)=2.3
__tk(us)=1.4
AFKS(us)=440.4
__tk(us)=600.9
SBER(us)=138.8
__tk(us)=158.4
__tk(us)=0.9
Order t(us)=6.9
Order t(us)=3.1
Order t(us)=2.8
Order t(us)=2.7
__tk(us)=2.2
TransReply t(us)=11.2
AFKS(us)=629.5
__tk(us)=663.4
SBER(us)=131.6
__tk(us)=214.6
Order t(us)=3.3
Order t(us)=2.5
TransReply t(us)=3.8
Order t(us)=3.6
AFKS(us)=498.4
__tk(us)=624.5
SBER(us)=99.7
__tk(us)=111.3
Order t(us)=8.7
SNGS(us)=3741.5
__tk(us)=2769.7
TransReply t(us)=8.1
TransReply t(us)=1.1
__tk(us)=1.8
__tk(us)=1.3
__tk(us)=1.3
AFKS(us)=582.5
__tk(us)=733.9
Order t(us)=4.7
Order t(us)=5.1
Order t(us)=4.0
SNGS(us)=2139.4
Order t(us)=3.8
__tk(us)=19.6
TransReply t(us)=3.8
__tk(us)=2.4
TransReply t(us)=1.9
Order t(us)=6.5
AFKS(us)=458.8
__tk(us)=650.8
ROSN(us)=4161.7
__tk(us)=4191.7
Order t(us)=8.0
Order t(us)=4.3
Order t(us)=3.2
__tk(us)=2.2
TransReply t(us)=2.5
__tk(us)=2.5
TransReply t(us)=2.0
Order t(us)=4.2
AFKS(us)=642.0
__tk(us)=825.9
__tk(us)=1.3
Order t(us)=3.3
Order t(us)=3.0
Order t(us)=2.6
__tk(us)=1.7
__tk(us)=1.3
TransReply t(us)=11.8
__tk(us)=2.9
AFKS(us)=584.2
__tk(us)=623.6
SBER(us)=140.5
__tk(us)=154.1
Order t(us)=4.2
Order t(us)=3.0
TransReply t(us)=4.7
Order t(us)=6.7
не все то золото, что блестит
 
В качестве информации и для сравнения,
выкладываю время работы колбеков и main скрипта на тестовом сервере QUIK.
---------------------
В данном тесте  роботу задана работа по 36 инструментам.
----------------------------------
При получении колбека onParam по инструменту,
робот вычисляет свечи 4 таймов,
снимает ранее выставленную заявку
и выставляет новую.
и так далее
----------------------------
В приведенной ниже таблице результата обозначено:
_tk -время main ;
если указан инструмент,
то это время получения свечей 1 минута и формирование на их основе свечей 5 мин 30 мин и 1 день.
Время колбеков содержит их имя.

--------------------------------
Скрытый текст
Время сервера, время последней сделки., Разное время передаваемое с сервера.
 
Цитата
Nikolay написал:
Прямо сейчас наблюдаю такую картину. Время сервера отстает на минуту от текущего времени (оно синхронизировано и корректно).
При  этом время последней сделки на минуту впереди времени сервера и близко к  правильному текущему времени, т.е. тоже опережает время сервера.

Я  могу понять, что это проблема брокера (Сбербанк), но с какой стати  время сделки в будущем относительно времени сервера брокера и времени  пакета?
Т.е. я понимаю, что время сделки просто транслирует биржа, но  серверная часть должна же не просто транслировать, но и как-то  контролировать, что она транслирует.
сервер брокера никак не контролирует то, что транслирует с биржи.
его задача работать со заявками клиентов, проверять достаточность средств и формат заявок и отправлять их на сервер биржи.
время сервера иногда гуляет относительно времени биржи.
не все то золото, что блестит
 
Расскажу Вам об одном заблуждении,
которое бытует не столько у чайников, как  у  профи, ваяющих роботов на луа.
--------------  
Постановка задачи :
---------------------
Есть инструмент X и его параметр  P.
Надо сделать таблицу инструментов и их параметров.
Периодически надо искать параметры конкретного инструмента  X в этой таблице.
------------------
Вопрос:
Как  быстрее сделать поиск нужного элемента таблицы.
-----------------------
есть как минимум два способа организации таблицы
-------------
Вариант 1 использовании хэш индексов.
В этом случае для записи параметра P  инструмента X  таблицу  T,  пишем  T[X]=P , чтобы прочитать параметр P надо записать P=T[X]
----------------------------------
Вариант 2  -любимый тех писателей роботов, которые плохо  знают  луа, но писали на других языках программирования.
В этом случае используем два индексных массива  T1 и T2, в которых под одинаковыми номерами j пишем T1[j]=X; T2[j]=P
=============
Теперь для поиска параметра P элемента X во втором варианте надо перебрать в цикле по индексу массив T1 и найти X
потом по этому индексу прочитать параметр из массива T2
===========
Какой вариант быстрее?
Давайте сравним на следующем тесте:
------------
заполняем три массива
Код
local t,t1,t2={},{},{}
local N=1000
for i=1,N do local x="a"..i; local x1="b"..i; t[i]=x; t1[i]=x1;   t2[x]=x1 end
считаем время по первому варианту:
Код
 local Tm1=0;
for i=1,N do local x="a"..i;
nklib.startA();
local s=t2[x];
 Tm1=Tm1+nklib.stopA();
 end
 print(0.1*Tm1);
считаем время по второму варианту :
Код
local Tm2=0;
for i=1,N do local j; local x="a"..i;
nklib.startA();
 for n=1,N do if t[n]==x then j=i; break end end
 local s=t1[j];
 Tm2=Tm2+nklib.stopA();
 end
  print(0.1*Tm2);
print(Tm2/Tm1)
Результат:

Вариант 1:  58 мкс
Вариант 2: 8027 мкс
------------------  
Резюме:    Вариант 2 в 138 раз медленнее, чем Вариант 1.
не все то золото, что блестит
 
Цитата
Владимир написал:
nikolz, Чушь полная.

1. Вероятность того, что все клиенты одновременно выставляют заявки РАВНА нулю.

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

3. Заявка клиента будет стоять в очереди до тех пор, пока не будет исполнена или снята, а никакие не "8 секунд". Если же под "заявкой" подразумевается любая транзакция, то время её обработки наверняка будет зависеть от её вида.

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

5. В любом случае "реальное время" у робота на клиенте нужно измерять В СЕКУНДАХ, а не в МИЛЛИсекундах и не в МИКРОсекундах. Dixi.
Владимир,
----------------  
Я хотя бы привожу свое со ссылкой на числовые данные доступные на отчетах конференций разработчиков QUIK.
Вы же голословно рассуждаете.
-----------------------
Все Ваши домыслы полная хрень.
-------------------------
Вот лишь доказательство  этого  п.4:
----------------
По существу замечу следующее (читайте ФЗ "о рынке ЦБ" и ГК РФ)
----------------  
Брокер не имеет право замыкать сделки между клиентами, если они не дали согласие на внебиржевые сделки.
Но и в этом случае  клиенты должны подать соответствующие поручения.
-----------------
Остальные пункты даже критиковать не буду. Мало ли что на заборе пишут.
Как получить значение индикатора на предыдущей свече
 
пишите значения индикатора в массив и читайте со смещением
------------------
Пример:
local t={ }
-----
local x=indicator(i)
----------------------
if x then t[i]=x else if #t>0 then t[i]=t[i-1] end end   -- если значения нет, то пишем предыдущее значение
-------------------
local M=#t;
local x1;  if M>0 then x1=t[M-1] end  --читаем  предыдущее значение
-------------------
local x2;  if M>01 then x1=tM-2] end  --читаем  предпредыдущее значение
Страницы: Пред. 1 ... 32 33 34 35 36 37 38 39 40 41 42 ... 72 След.
Наверх