Извечный вопрос: повторные вызовы OnTrade

Страницы: 1
RSS
Извечный вопрос: повторные вызовы OnTrade, Даже при заявке на одну акцию
 
Создаю заявку из lua-скрипта на покупку ровно одной акции. Т.е. никаких финтов с частичным исполнением не может быть. При исполнении происходят два вызова функции OnTrade. Сделал полную распечатку всей таблицы от обоих вызовов. Отличие только в трёх полях: uid, on_behalf_of_uid, trans_id. При первом вызове все три нулевые, при втором все три - ненулевые.

Вопросы следующие:
1. Гарантируется ли, что вызов OnTrade, в котором эти поля нулевые, является не последним, т.е. я могу его игнорировать, т.к. после него будет следующий?
2. Гарантируется ли, что вызов, в котором эти поля ненулевые, является последним?
3. Являются ли эти три поля синхронными всегда? (Т.е. либо все три равны 0, либо все три не равны 0?) Т.е. можно ли проверять только одно из них, а не все три вместе?
 
Цитата
User12501 написал:
Гарантируется ли, что вызов OnTrade, в котором эти поля нулевые, является не последним
Нет.
trans_id и uid в некоторых ситуациях могут иметь и нулевые значения.
 
Цитата
User12501 написал:
Являются ли эти три поля синхронными всегда? (Т.е. либо все три равны 0, либо все три не равны 0?)
Нет
 
Цитата
User12501 написал:
Создаю заявку из lua-скрипта на покупку ровно одной акции. Т.е. никаких финтов с частичным исполнением не может быть. При исполнении происходят два вызова функции OnTrade. Сделал полную распечатку всей таблицы от обоих вызовов. Отличие только в трёх полях: uid, on_behalf_of_uid, trans_id. При первом вызове все три нулевые, при втором все три - ненулевые.

Вопросы следующие:
1. Гарантируется ли, что вызов OnTrade, в котором эти поля нулевые, является не последним, т.е. я могу его игнорировать, т.к. после него будет следующий?
2. Гарантируется ли, что вызов, в котором эти поля ненулевые, является последним?
3. Являются ли эти три поля синхронными всегда? (Т.е. либо все три равны 0, либо все три не равны 0?) Т.е. можно ли проверять только одно из них, а не все три вместе?
Если заявка, по которой пройдет сделка выставлена не скриптом Lua, то trans_id будет нулевой .
-------------------------------------------
Должны быть не нулевые , так как определяют клиента на сервере брокера.
-----------------------------
Полагаю , что первый раз приходит с биржи, второй - с сервера брокера.
 
 
 
Два других должны быть не нулевые , так как определяют клиента на сервере брокера.
 
Опять отловил два повторных OnTrade, на этот раз совпадали все поля кроме broker_comission и broker_comission_currency (в первом они были 0 и пусто, во втором правильные). Можно ли как-то конкретно определить полный набор полей, которые я должен проверить, чтобы уверенно знать, что данный вызов OnTrade является последним по данной заявке?
Речь только про заявки из скрипта qlua, строго на один лот.  
 
Цитата
User12501 написал:
Опять отловил два повторных OnTrade, на этот раз совпадали все поля кроме broker_comission и broker_comission_currency (в первом они были 0 и пусто, во втором правильные). Можно ли как-то конкретно определить полный набор полей, которые я должен проверить, чтобы уверенно знать, что данный вызов OnTrade является последним по данной заявке?
Речь только про заявки из скрипта qlua, строго на один лот.  
Нельзя ответить на этот вопрос. Например, если поля broker_comission и broker_comission_currency не важны, то этот второй вызов бесполезен, а если важны, то уже нет. Хотя, если говорить о комиссиях брокера, то они их может не транслировать вовсе и можно ждать вечно.

Т.е. все зависит от того, что необходимо. Явно поля количества и суммы важны, и, наверно, brokerref. Остальное уже решать Вам.

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

Речь о том, как проигнорировать бесполезный вызов и не посчитать дважды то, что нужно? Например если в момент OnTrade мне нужно знать общее количество оставшихся акций, стандартные get-функции не работают (спрашивал об этом вот здесь: https://forum.quik.ru/forum10/topic9409/ ). Значит нужно вводить отдельную переменную - количество акций, и при каждом OnTrade обновлять. Но тогда при повторном OnTrade происходит повторное обновление, и пожалуйста - ошибка.  
 
Цитата
User12501 написал:

Речь о том, как проигнорировать бесполезный вызов и не посчитать дважды то, что нужно? Например если в момент OnTrade мне нужно знать общее количество оставшихся акций, стандартные get-функции не работают (спрашивал об этом вот здесь:  https://forum.quik.ru/forum10/topic9409/  ). Значит нужно вводить отдельную переменную - количество акций, и при каждом OnTrade обновлять. Но тогда при повторном OnTrade происходит повторное обновление, и пожалуйста - ошибка.  
Ошибка т.к. обработка наивная:

pos = pos + sign*traded.qty

Естественно при таком подходе повторный вызов даст искажение данных. А если обработка более сложная, то не будет ошибки. Это уже вопрос реализации, зависящий от конкретной задачи.
 
Цитата
User12501 написал:
Например если в момент OnTrade мне нужно знать общее количество оставшихся акций, стандартные get-функции не работают
Вы подняли очень важный вопрос. Он касается широкого круга пользователей, и широко обсуждался на форуме и приводились различные боевые подходы. На Ваш вопрос выше, ответ нужно организовывать внутренний учет, не только количества но и других параметров зависящих от конкретной сделки сделки (допустим усреднялись). Вот пример подхода которым, часто пользуюсь на скоростных скриптах:
Код
function OnTrade(trade)

    if not WORKING_FLAG then return end

    local key = trade.trans_id
    local i = tonumber(sdelka[0]); 
    
  if working 
  and key and key>0
  and (i==0 and key~=sdelka.id) or (i>0 and sdelka[i][1]~=key)
  --and trade.sec_code==symbol --and trade.class_code==class 
  then
    
    i=i+1;  
    sdelka[0]=i;                         
    sdelka[i]={};                     
    sdelka[i][0]=sdelka[0];
    sdelka[i][1]=trade.trans_id;      
    sdelka[i][2]=get_date(trade.datetime)
    sdelka[i][3]=get_time(trade.datetime)
    
    sdelka[i][4]="B"; if bit.band(trade.flags,4)~=0 then sdelka[i][4]="S"; end;
    local dir = sdelka[i][4]=="B" and 1 or sdelka[i][4]=="S" and -1 or 0;
    sdelka[i][5]=trade.qty*dir;       
    sdelka[i][6]=trade.price;         
    ----- comission 
    sdelka[i][7]=trade.clearing_comission+trade.exchange_comission+trade.tech_center_comission;
    
    sdelka[i][8]=trade.order_num;    
    sdelka[i][9]=trade.trade_num;  
    sdelka[i][10]=trade.sec_code;     
                        
    sdelka.id=trade.trans_id;
    
    Log:info("OnTrade! sdelka "..i .."; "
                                  .."; trans_id="..sdelka[i][1] 
                                  .."; "..sdelka[i][2]
                                  .."; "..sdelka[i][3]
                                  .."; "..sdelka[i][4]
                                  .."; "..sdelka[i][5]
                                  .."; "..sdelka[i][6]
                                  .."; comission="..sdelka[i][7]
                                  .."; onum="..sdelka[i][8]
                                  .."; tnum="..sdelka[i][9]
                                  .."; "..sdelka[i][10]
                                  .."\n"
                                  );
    --local a,v; for a,v in pairs(sdelka[i) do Log:trace( 'OnTrade! sdelka['..i..']['..tostring(a)..'] = '.. tostring(v) ) end;
  end
end;
 
Цитата
VPM написал:
Цитата
User12501 написал:
Например если в момент OnTrade мне нужно знать общее количество оставшихся акций, стандартные get-функции не работают
Вы подняли очень важный вопрос. Он касается широкого круга пользователей, и широко обсуждался на форуме и приводились различные боевые подходы. На Ваш вопрос выше, ответ нужно организовывать внутренний учет, не только количества но и других параметров зависящих от конкретной сделки сделки (допустим усреднялись). Вот пример подхода которым, часто пользуюсь на скоростных скриптах:
Код
     

Спасибо. Принцип такого костыля понятен, но очень надеялся, что можно как-то проще. Видимо нельзя.  
 
User12501,  И это еще не вся проблематика, ведь нужно данные периодически синхронизировать с данными QUIK.  
 
Цитата
VPM написал:
Цитата
User12501 написал:
Например если в момент OnTrade мне нужно знать общее количество оставшихся акций, стандартные get-функции не работают
Вы подняли очень важный вопрос. Он касается широкого круга пользователей, и широко обсуждался на форуме и приводились различные боевые подходы. На Ваш вопрос выше, ответ нужно организовывать внутренний учет, не только количества но и других параметров зависящих от конкретной сделки сделки (допустим усреднялись). Вот пример подхода которым, часто пользуюсь на скоростных скриптах:
Код
   
     ----- comission  
    sdelka[i][ 7 ] = trade.clearing_comission + trade.exchange_comission + trade.tech_center_comission;
   
Кстати раз уж вы выложили код, есть вопрос по вот этой строке. Сейчас проверил в тех сделках, которые у себя отлавливал: там есть поле broker_comission, которое я воспринимал как итоговую сумму всех комиссий. И оно больше, чем написанная вами сумма. Например для одного лота MOEX:
tech_center_comission = 0
clearing_comission = 0.22
exchange_comission = 0.3
broker_comission = 1.57

Проверка по остатку на счёте показывает, что 1.57 - точное значение итоговой комиссии, т.е. уже включает в себя всё остальное (и ещё что-то).  
 
Привел Вам просто базовую свою заготовку, в качестве примера не более. Если вы пишите на луа 5.4, то нужно отказаться от bit.band в пользу продвинутого метода. Что там точно за комиссии, подсказать  тоже не могу так как на каждом рынке есть особенности. Для Фондового API QUIK предлагает предварительный расчет через стандартную функцию. Для оценки можно ее воспользоваться. На срочном есть зависимость от гарантийного обеспечения и курсов ... Что касается моего подхода, то я применяю подход  Ральфа Винса, а именно, торговый капитал делю изначально на две части: пассивный и активный. Так как в процессе торговле всегда присутствует пассивная часть, нет необходимости вести четкий учет комиссий, сверяю по клирингу. Здесь более важен учет количества и цены, так как на прямую влияют на управление позицией.  
 
Цитата
User12501 написал:

Например если в момент OnTrade мне нужно знать общее количество оставшихся акций
Для этого надо ловить это:
  • OnDepoLimit - изменение позиции по инструментам
 
openbal NUMBER Входящий остаток
openlimit NUMBER Входящий лимит
currentbal NUMBER Текущий остаток
currentlimit NUMBER Текущий лимит
locked_sell NUMBER В продаже. Количество инструментов, заблокированное под исполнение заявок  клиента на продажу
locked_buy NUMBER В покупке. Количество инструментов в активных заявках клиента на  покупку
locked_buy_value NUMBER Стоимость инструментов, заблокированных под покупку
locked_sell_value NUMBER Стоимость инструментов, заблокированных под продажу
 
Цитата
VPM написал:
И это еще не вся проблематика, ведь нужно данные периодически синхронизировать с данными QUIK.
   Зачем синхронизировать с данными QUIK, когда можно их использовать всегда? Зачем обрабатывать "сырые" коллбеки, когда можно проверять циклически, по изменению их размеров, нужные вам таблицы QUIK (таблицы заявок, стоп-заявок, сделок и т.д.)? Вы же в своих стратегиях, наверное, учитываете состояние вашего портфеля, а не занимаетесь подсчетом коллбеков :smile: .  Коллбеки имеет смысл использовать только там, где без них не обойтись (например, OnTransReply, в которых может быть информация о причине невыполнения транзакции).
 
Добрый день TGB,  то что Вы описываете в определённых стратегиях конечно надежней, но задача далеко не тривиальна, особенно в скоростных алгоритмах. Да и автор вопроса применяет событийный подход. А вопрос звучит так:
Цитата
User12501 написал:
Речь о том, как проигнорировать бесполезный вызов и не посчитать дважды то, что нужно? Например если в момент OnTrade мне нужно знать общее количество оставшихся акций, стандартные get-функции не работают (спрашивал об этом вот здесь:  https://forum.quik.ru/forum10/topic9409/  ). Значит нужно вводить отдельную переменную - количество акций, и при каждом OnTrade обновлять. Но тогда при повторном OnTrade происходит повторное обновление, и пожалуйста - ошибка.  
Плюс учет различных комиссий в принятии решений, насколько помню точность в учете QUIK до шестого знака. Как же тут не сверять свою вторую бухгалтерию?
 
 
Цитата
TGB написал:
можно проверять циклически, по изменению их размеров, нужные вам таблицы QUIK (таблицы заявок, стоп-заявок, сделок и т.д.)?
Думаю такой подход сложнее, чем обработка колбеков.
На примере данной ситуации: если пришедший колбек не содержит значения нужных мне параметров, то я его пропускаю и жду колбек, который их содержит.
В случае же обработки таблиц вместо колбеков, нужно хранить не просто индекс последней обработанной строки таблицы, а индексы всех обработанных строк либо общее количество строк и индексы необработанных строк (пропущенных по причине отсутствия в них значений нужных параметров). И циклически проверять, не появились ли новые значения в пропущенных строках.
 
Учет комиссий не решается колбеками и данными из таблиц. Решается же он через обработку отчетов брокера. Комиссия биржи транслируется вместе с сделкой, поэтому её условно можно считать. Брокера же чаще всего транслирует "ерунду". И только в отчете за день будут точные цифры, т.к. они могу зависеть от оборота за день, типа инструмента и др, и в момент сделки точных банально нет. Так что гораздо проще в алгоритм вбить процент либо величину комиссии и учитывать её. А корректировать через разбор отчета брокера.
 
Цитата
Nikolay написал:
Учет комиссий не решается колбеками и данными из таблиц. Решается же он через обработку отчетов брокера. Комиссия биржи транслируется вместе с сделкой, поэтому её условно можно считать. Брокера же чаще всего транслирует "ерунду". И только в отчете за день будут точные цифры, т.к. они могу зависеть от оборота за день, типа инструмента и др, и в момент сделки точных банально нет. Так что гораздо проще в алгоритм вбить процент либо величину комиссии и учитывать её. А корректировать через разбор отчета брокера.
Комиссия брокера считается в конце дня, так как реально сделки урегулируются лишь после сессии клиринговыми компаниями.
Только эти компании могут списывать и зачислять денежные средства в оплату сделок.
После получения их отчета, брокер соответственно списывает деньги у клиентов и начисляет свою комиссию.
 
Цитата
Йцукен написал:
Думаю такой подход сложнее, чем обработка колбеков.
   Обработка перезапусков скрипта по любой неконтролируемой вами причине у вас не предусмотрена? Пока он перезапускается заявки на бирже могут быть выполнены, а коллбеки пропущены.  Вы предполагаете что и коллбеки в работающем скрипте не теряются?
 
Цитата
VPM написал:
особенно в скоростных алгоритмах
   Какие скоростные алгоритмы? Когда есть ограничение архитектуры QUIK. Факторами возможных задержек в нем являются <Реализация скрипта>  ->  <Реализация QUIK>  ->  <Используемая аппаратура ПК>  -> <Канал связи с брокером> -> <Сервер брокера> ->  -> <Канал связи брокера с биржей> -> <Биржа>.
 
Цитата
TGB написал:
Обработка перезапусков скрипта по любой неконтролируемой вами причине у вас не предусмотрена? Пока он перезапускается заявки на бирже могут быть выполнены, а коллбеки пропущены.
При запуске скрипта обработка таблиц происходит в OnInit. Соответственно, все новые колбеки будут получены и обработаны после выхода из OnInit.

Цитата
TGB написал:
Вы предполагаете что и коллбеки в работающем скрипте не теряются?
Если колбеки потеряются, то и данные в таблицах квика не будут заполняться.
 
Цитата
Йцукен написал:
Цитата
TGB написал:
Обработка перезапусков скрипта по любой неконтролируемой вами причине у вас не предусмотрена? Пока он перезапускается заявки на бирже могут быть выполнены, а коллбеки пропущены.
При запуске скрипта обработка таблиц происходит в OnInit. Соответственно, все новые колбеки будут получены и обработаны после выхода из OnInit.

Цитата
TGB написал:
Вы предполагаете что и коллбеки в работающем скрипте не теряются?
Если колбеки потеряются, то и данные в таблицах квика не будут заполняться.
Как много чудесных открытий Вас ждет. Если скрипт был остановлен, например по ошибке, терминал же работает. А во время простоя исполнились ордера, то колбеки пропущены, т.к. событие прошло. Колбек же - это реакция на событие. Иногда брокер может разорвать соединение, вызвать OnClenUp и тогда приедут ВСЕ колбеки с начала сессии. Но это исключение.

OnInit - это событие запуска скрипта, ни коим образом не связанное с таблицами. Если только при запуске Вы сами не проверите что изменилось в таблицах с прошлого запуска.
 
Цитата
Nikolay написал:
А во время простоя исполнились ордера, то колбеки пропущены
Ещё раз:
Цитата
Йцукен написал:
При запуске скрипта обработка таблиц происходит в OnInit.

Цитата
Nikolay написал:
Если только при запуске Вы сами не проверите что изменилось в таблицах с прошлого запуска.
Скрипт сохраняет, допустим, номер своей активной заявки или id транзакции в файл. И при запуске он в состоянии проверить результат транзакции/заявки, пробежав однократно по соответствующим таблицам.

Цитата
Nikolay написал:
брокер может разорвать соединение, вызвать OnClenUp и тогда приедут ВСЕ колбеки с начала сессии
Да и пофиг: скрипт запомнил, какие заявки/сделки (в т.ч. и те, что были в таблицах при запуске скрипта) он обработал и дубли проигнорирует.
 
Цитата
TGB написал:
Цитата
VPM написал:
особенно в скоростных алгоритмах
    Какие скоростные алгоритмы? Когда есть ограничение архитектуры QUIK. Факторами возможных задержек в нем являются <Реализация скрипта>  ->  <Реализация QUIK>  ->  <Используемая аппаратура ПК>  -> <Канал связи с брокером> -> <Сервер брокера> ->  -> <Канал связи брокера с биржей> -> <Биржа>.
Я не очень понимаю, что Вы хотите донести, и о чем спорите? И  при этой архитектуре можно строить торговлю спредом, с выставление огромного количества ордеров, а следовательно нужна обработка как ордеров так и сделок. Например, мой алгоритм оставленный мной без присмотра, поймал какую то  ошибку (уже и не припомню причину) наделал столько заявок, что брокер заблокировал канал, а затем выставил штраф. Это я к тому что все возможно!
 
Цитата
VPM написал:
мой алгоритм оставленный мной без присмотра, поймал какую то  ошибку (уже и не припомню причину) наделал столько заявок, что брокер заблокировал канал, а затем выставил штраф.
Я думаю, тут надо какую-то защиту "от дурака" реализовывать: типа, при превышении заданного порога количества ошибочных транзакций подряд, останавливать скрипт до выяснения причин.
 
Йцукен,
А как Вам это:

3 февраля 2010 года ошибка в алгоритме HFT-робота компании Infinium Capital Management, торговавшего нефтяными контрактами, привела к неконтролируемому росту заявок и скачку цены на нефть на 1,3% прямо перед закрытием биржи. Примерно за секунду работы робот сгенерировал убытков на $1 млн. kommersant.ru
------------------------
С HFT-трейдингом связывают обвал на американском фондовом рынке 6 мая 2010 года. За пять минут индекс DJIA, и без того снижавшийся весь день, потерял около 7%, чтобы ещё через 15 минут отыграть большую часть падения. Многие трейдеры сочли это естественным результатом насыщения рынка роботами: реагируя на продажи, те драматически усилили уже наметившееся движение. kommersant.ruru.wikipedia.org*

23 марта 2012 года компьютерный HFT-алгоритм, запущенный с терминалов неопознанного трейдера, «убил» попытку американской компании BATS Global Markets провести IPO. Попытка вывести акции на биржу продолжалась ровно 9 секунд, в течение которых бумаги компании обесценились практически до нуля, торги по ним были приостановлены, а через некоторое время руководство компании заявило о полном отказе выходить на биржу в обозримом будущем.  
 
Цитата
nikolz написал:
А как Вам это
Бывает.
Сбой в работе алгоритмической системы одного из участников торгов фьючерсами на доллар/рубль на бирже ММВБ-РТС мог принести владельцу максимальный убыток в $4,3 миллиона.
Один из программистов этого робота по секрету поделился, что они не успели протестировать алгоритм, но начальник приказал его запускать в бой. Сказано - сделано.
Страницы: 1
Читают тему
Наверх