Через файлы это хорошо, сам пользую. Как для передачи, так и для сохранения для последующего запуска. Вот только бэкапится приходится т.к. при коллизиях и вывыливании терминала в дамп файлы частенько бьются. А поскольку в файл писать приходится часто это становится проблемой.
function main()
message("Script's start local time: "..os.date("%d-%b-%Y %X"))
SessionDate=getTradeDate().date
message("Session date "..SessionDate)
ParamRequest(p_classcode,ticker,"TRADINGSTATUS")
--
while is_run==true do
t_status=tonumber(getParamEx2("TQBR",ticker, "TRADINGSTATUS").param_value) -- текущий статус
if status~=t_status then -- изменение статуса сессии
status=t_status
if status==3 or status==1 then
if not ds or type(ds)~="table" then
ds,error_desc=CreateDataSource("TQBR", ticker, INTERVAL_TICK)
if error_desc~=nil and error_desc~="" then message(" Source error==>" .. error_desc) end
local nn=0
while ds:Size()<5 and nn<100 do
sleep(100) nn=nn+1
end
ds:SetEmptyCallback()
message(os.date(" %X").." Ready. Session status:"..tostring(status).." Data size:"..tostring(ds:Size()))
end
while n<10 and status==1 do
local size=ds:Size()
if size~=old_size then
message(tostring(n)..os.date(" %X").." Get data. Session status:"..tostring(status).." Data size:"..tostring(ds:Size()))
old_size=size
n=n+1
end
sleep(50)
end
end
end
sleep(100)
end
end
Ничего не изменилось, данные поступают только после перезапуска скрипта.
nikolz написал: То что тики подписываются со второго пинка было указано давно, но воз и ныне там.
Наткнулся на интересную фишку: если тики не едут после подписки при открытой сессии, то подписка на другой тикер даже в другом скрипте толкает все подписки и они приходят в чувство.
В итоге я таки поймал этот баг за хвост. Вот скрипт, который его ловит:
Код
-- Скрипт проверки корректности получения данных обезличенных сделок.
-- Терминал запускается вместе со скриптом ДО начала сессии.
-- Таблица обезличенных сделок не открыта
-- Тикера нет в Таблице текущих торгов.
--
ticker="MAGN"
status,t_status=0,0
old_size=0
n=0
is_run=true
SessionDate=""
function main()
message("Script's start local time: "..os.date("%d-%b-%Y %X"))
SessionDate=getTradeDate().date
message("Session date "..SessionDate)
ParamRequest(p_classcode,ticker,"TRADINGSTATUS")
--
while is_run==true do
if SessionDate~=getTradeDate().date and status==1 then -- новая сессия
SessionDate=getTradeDate().date
message("New session date "..SessionDate)
n=0
end
t_status=tonumber(getParamEx2("TQBR",ticker, "TRADINGSTATUS").param_value) -- текущий статус
if status~=t_status then -- изменение статуса сессии
status=t_status
if status==3 or status==1 then
if not ds or type(ds)~="table" then
ds,error_desc=CreateDataSource("TQBR", ticker, INTERVAL_TICK)
if error_desc~=nil and error_desc~="" then message(" Source error==>" .. error_desc) end
local nn=0
while ds:Size()<5 and nn<100 do
sleep(100) nn=nn+1
end
ds:SetEmptyCallback()
message(os.date(" %X").." Ready. Session status:"..tostring(status).." Data size:"..tostring(ds:Size()))
while n<10 and status==1 do
local size=ds:Size()
if size~=old_size then
message(tostring(n)..os.date(" %X").." Get data. Session status:"..tostring(status).." Data size:"..tostring(ds:Size()))
old_size=size
n=n+1
end
sleep(50)
end
end
end
end
sleep(100)
end
end
function OnStop(stop_flag)
message("Script's stop local time(MSK-1): "..os.date("%d-%b-%Y %X"))
if ds then ds:Close() end
is_run=false
end
Скрипт был запущен вместе с терминалом до начала сессии (status==0), после открытия предторговой (status==3) отработали функции CreateDataSource и SetEmptyCallback. После открытия основной сессии (status==1) должны были начать поступать данные по обезличенным сделкам и показаны первые 10 изменений базы. Однако данные по сделкам в терминал НЕ поступали:
20.12.2023 08:00:10 Script's start local time: 20-Dec-2023 08:00:10 20.12.2023 08:00:10 Session date 20.12.2023 20.12.2023 08:00:34 Соединение установлено. Предыдущий вход был 20.12.2023 07:57:31 с адреса 92.62.58.114. 20.12.2023 09:50:10 09:50:10 Ready. Session status:3.0 Data size:0 20.12.2023 10:05:35 Script's stop local time: 20-Dec-2023 10:05:35
В 10-05 скрипт был перезапущен и отработал корректно:
20.12.2023 10:06:05 Script's start local time: 20-Dec-2023 10:06:05 20.12.2023 10:06:05 Session date 20.12.2023 20.12.2023 10:06:05 10:06:05 Ready. Session status:1.0 Data size:406 (406 записей базы было пропущено при первом запуске) 20.12.2023 10:06:05 0 10:06:05 Get data. Session status:1.0 Data size:406 20.12.2023 10:06:05 1 10:06:05 Get data. Session status:1.0 Data size:418 20.12.2023 10:06:05 2 10:06:05 Get data. Session status:1.0 Data size:421 20.12.2023 10:06:06 3 10:06:06 Get data. Session status:1.0 Data size:424 20.12.2023 10:06:12 4 10:06:12 Get data. Session status:1.0 Data size:425 20.12.2023 10:06:14 5 10:06:14 Get data. Session status:1.0 Data size:426 20.12.2023 10:06:16 6 10:06:16 Get data. Session status:1.0 Data size:428 20.12.2023 10:06:20 7 10:06:20 Get data. Session status:1.0 Data size:429 20.12.2023 10:06:20 8 10:06:20 Get data. Session status:1.0 Data size:430 20.12.2023 10:06:24 9 10:06:24 Get data. Session status:1.0 Data size:431
Не знаю насколько важно - терминал запускался на "тихоходном" компе c Intel Core i5
Полагаю что при получении нуля по одному из двух параметров просто проверяется второй и его ненулевое значение однозначно говорит о том, что данные получены.
В общем, как не искал, ничего не нашел. Все работает как надо за исключением отписки. Полагаю в последних версиях (у меня 11.0.0.92) эта проблема пофиксилась с чем-то вместе "за компанию". Либо я не учел какой-то дополнительный фактор. В любом случае дальше искать черную кошку в темной комнате смысла нет. Проявится снова, продолжу.
- ничего не появляется в фильтре таблицы обезличенных сделок
Если речь идет о том, что инструмент не добавляется в фильтр отдельной Таблицы обезличенных сделок, такое поведение корректно.
Цитата
- убрать эту подписку можно только вручную после похода в меню настроек.
Воспроизвели данное поведение при условии, что в терминале присутствует открытая Таблица обезличенных сделок. Проблема изучается. Постараемся в ближайшее время дать ответ.
Цитата
1. Достаточно ли такой подписки для корректной работы в скрипте колбэка OnAllTrade и выборки SearchItems("all_trades", .....) не имея этого инструмента в таблице обезличенных сделок?
Достаточно, наличие инструмента в открытой Таблице обезличенных сделок не обязательно.
Цитата
2. Как отписаться от этого счастья средствами Qlua при следующей смене иструмента?
Если в терминале нет открытых Таблиц обезличенных сделок, при вызове ds:Close() исключается получение обезличенных сделок по инструменту.
Антон, спасибо за ответ! Раз уж вы решили разобраться то посмотрите пожалуйста этот баг когда данные по обезличенным сделкам не получаются после запуска терминала со скриптом при закрытой сессии. Т.е. потом, когда сессия открывается, данные не поступают. При смене даты то же самое. Это при условии, что подписка оформлена в Настройках, но таблица обезличенных сделок не открыта. Если ТОС открыта и там прописан инструмент, то все работает корректно. Т.е. надо либо пофиксить этот баг, либо дать возможность CreateDataSource(..... INTERVAL_TICK) одновременно с внесением выбранного тикера в заказ данных вносить его и в открытую таблицу обезличенных сделок. В этом случае мы бы просто держали ТОС открытой и туда добавлялся бы и убирался тикер по CreateDataSource и Close(). Сейчас, для корректной работы скриптов, приходится после CreateDataSource(..... INTERVAL_TICK) руками вносить тикер в ТОС и потом после Close() руками же его убирать из Настроек и ТОС
nikolz написал: Еще есть такой глюк. Если Вы запустите КВИК и потом запустите скрипт, в котором есть подписка на обезличенные сделки, то ничего не получите. Если скрипт снять и снова запустить, то все заработает . Раньше уже про это писали, но воз вроде и ныне там.
Nikolay написал: В теории да, я так тоже делаю. Правда не советую так ждать прихода данных. Тиковые данные могут приходить долго, очень долго. В прошлых версиях данные приходили и без открытой таблицы обезличенных сделок. В текущих - уже нет, по крайней мере, по моим наблюдениям. Отписаться как и от обычного потока данных - закрыть. Собственно Вы это и делаете OnStop. Хотя, если говорите, что не убирается (как я понял), то, возможно, что-то опять изменилось между версиями. В последнее время мажорные релизы выходят как кролики.
Субъективно вроде работает, затыки появляются при смене даты торговой сессии на следующий день. Close() из меню подписку не убирает.
При возникновении стандартной ситуации смены рабочего тикера для робота довольно просто подписатся/отписатся на/от свечных баз данных. В случае же с обезличенными сделками ситуация выглядит иначе. Я предположил, что подписка на тиковую базу при помощи CreateDataSource решает эту проблему. Тестовый скрипт:
Код
is_run=true
function main()
ds,error_desc=CreateDataSource("TQBR", "GAZP", INTERVAL_TICK)
if error_desc~=nil and error_desc~="" then message(" Source error==>" .. error_desc) end
local nn=0
while ds:Size()<5 and nn<100 do
sleep(100) nn=nn+1
end
message("Data "..tostring(ds:Size()))
ds:SetEmptyCallback()
while is_run do
sleep(100)
end
end
function OnStop(stop_flag)
ds:Close()
is_run=false
end
Запускаю скрипт и , о чудо(!), в фильтре Основные_настройки/Программа/Получение_данных/Обезличенные_сделки появляется Газпром. Т.е. задача подписки на ленту сделок успешно решена и данные заказаны. Но... - ничего не появляется в фильтре таблицы обезличенных сделок - убрать эту подписку можно только вручную после похода в меню настроек.
В связи с вышеописанным имею два вопроса:
1. Достаточно ли такой подписки для корректной работы в скрипте колбэка OnAllTrade и выборки SearchItems("all_trades", .....) не имея этого инструмента в таблице обезличенных сделок? 2. Как отписаться от этого счастья средствами Qlua при следующей смене иструмента?
Vladimir spb написал: А если создать копию ТТТ, то ее можно изменять (удалять, добавлять строки) ?
Если абстрагироваться от того, зачем вам это счастье, то вы можете создать пользовательскую таблицу и заполнять ее в цикле теми же данными. Получите точную копию ТТТ с динамически меняющимися данными и возможностью менять строки как вам заблагорассудится в том числе добавлять строки тикеров и удалять их средствами Qlua. В этом случае выводить ТТТ в терминале вам как бы и не к чему.
Считаю это ошибками терминологии при составлении документации. Словом "таблица" обозначено все, что имеет табличную структуру. Данные, выводимая в терминал информация, создаваемые пользовательские структуры - все в кучу. Не удивительно появление таких вопросов.
Kolossi написал: Как всегда, хороший вопрос перевели в срач. В продолжение темы: насколько реально когда-нибудь объем свечи ds:V(n) получать в виде V(n).maker+V(n).taker?
Так это и 10 лет назад можно было, ещё на Qpile такое писали. Пишете скрипт, который ТОС обрабатывает, и выводите результат в таблицу или метками на график.
И как я не догадался :). Только вот как-то не хочется держать открытыми тиковые базы по всем нужным тикерам и шуршать фильтрами когда мне нужны такие данные по часовым свечам. На сервере брокера при подготовки свечной базы по любому периоду это сделать гораздо проще и логичнее.
Я просто сделал проверку на то, что каждый получаемый trade_num , был больше предыдущего и дубли исчезли.
Код
function OnTrade(trade) -- обработчик события сделки
if trade.client_code~=p_clientcode or trade.sec_code~=trw.p_seccode then return end -- чужая заявка
local tnord=trade.trade_num --номер сделки
local on ord=trade.order_num --номер заявки
local price=trade.price --цена сделки
local dir="" if bit.test(trade.flags,2)==true then dir="S" else dir="B" end -- направление сделки
if tnord>last_trade then --в обработку
last_trade=tnord
...
...
...
end
end
Как всегда, хороший вопрос перевели в срач. В продолжение темы: насколько реально когда-нибудь объем свечи ds:V(n) получать в виде V(n).maker+V(n).taker?
Подскажите по какой причине может быть расхождение позиции по одному из инструментов (в моем случае MAGN) ? В таблице "Состояние счета" --> "Позиция" --> -240 (T1) - правильное значение В таблице "Позиции по инструментам" --> "Текущий остаток" --> -2400 (Т1) В указаных таблицах еще четыре инструмента, по ним все ровно
Если у вас не открыта таблица текущих торгов, то можно оформить подписку на параметр ParamRequest(classcode,seccode,"LAST") и потом его получать c_price=tonumber(getParamEx2(classcode,seccode, "LAST").param_value)
Ну если вам нравится так называть текущую цену и получать ее таким способом то почему бы нет. Если что, для получения текущего прайса совсем не обязательно создавать базу. Можно, например, использовать getParamEx( class_code, sec_code, LAST)
"Кроме мордобития никаких чудес". В базе только свечи, их параметы, ну и размер самой базы. В тиковой чуть больше, но тоже без фантазий. Так сказали японцы и в своей религии "Японские свечи" и разработчики их адепты.
Наткнулся на то, что иногда значения param_value совсем не соответствуют значениям param_image Например: -- local aaa=getParamEx(p_classcode,"GMKN","EV_SESS_ALLOWED").param_value local bbb=getParamEx(p_classcode,"LSRG","EV_SESS_ALLOWED").param_value message(aaa.."/"..bbb)
--> 0.0000/0.0000 -- тоже с param_image : -- local aaa=getParamEx(p_classcode,"GMKN","EV_SESS_ALLOWED").param_image local bbb=getParamEx(p_classcode,"LSRG","EV_SESS_ALLOWED").param_image message(aaa.."/"..bbb)
local tt={name={},score={}} for x=1,10 do tt.name[x]=tostring(x) tt.score[x]=10-x end table.sort(tt, function(a,b) return a.score < b.score end) for x=1,10 do message(tt.name[x]..":"..tostring(tt.score[x])) end
Nikolay написал: Ну, у окна доступные скрипты до сих пор нельзя изменить размер, древнейшая кодировка ANSI - и это не критически важная часть, явно только клиент. А Вы на святое замахнулись, сервер.
Это да, на эту проблему "ваше пожелание принято" не так давно отпраздновало десятилетний юбилей. Но все же предлагаю добавить параметры сделок для каждой свечи любого интервала.
Sergey Gorokhov написал: Это не так. Cвечи формирует сервер QUIK, а не биржа. Но свечи формируются по сделкам полученным с биржи.
Если я правильно понимаю, свечи формируются из тиковой базы сделок. Так в чем проблема передавать в свечи не только те кастрированные параметры которые придумали японцы сто лет назад? Там ведь добавить всего ничего.
Подскажите возможно ли каким-то образом получение данных для свечи с интервалом от 1 мин или более с разбивкой объема сделок V на "покупка" и "продажа" как это сделано в ленте сделок? Выбирать это из тиковой базы уж очень затратно по ресурсам, особенно если не по одному инструменту.
nikolz написал: на самом деле это не так реально это не поможет экономить деньги. Так как комиссия брокера остается, а она всегда существенно больше биржевой. Если заявка не пассивная, то она просто отклоняется и правило это лишь к лимитированным заявкам.
Я тут пользую визуальный индикатор работы скрипта который показывает его замедление или затык при выполнении. Веселенький такой крутилок в крайней ячейке таблицы. Может кому пригодится. С Новым Годом!
Код
function cyrcle(c) -- крутилок
local t=os.time()
if c=="|" then
return "/", t
elseif c=="/" then
return "--", t
elseif c=="--" then
return "\\", t
elseif c=="\\" then
return "|", t
else
return "" ,t
end
end
-- Пример (цветовые функции здесь не привожу)
go,gt="",0
...
...
function main()
is_run=true
...
while is_run do
go,gt=cyrcle(go)
...
...
...
...
SetCell(kt_id,x,y,go) -- вывод в ячейку таблицы
--раскраска крутилка
if go=="/" or go=="\\" then
color(x,y,kt_id,"Lemon")
else
color(x,y,kt_id,"Salad")
end
if os.time()-gt>60 then color(x,y,kt_id,"Red") end
...
sleep(50)
end
end
Ваши пожелания зарегистрированы. Мы постараемся рассмотреть их и сообщить Вам результаты анализа. Впоследствии, по результатам анализа, будет приниматься решение о реализации пожеланий в будущих версиях ПО.
Есть одна тонкая разница между подпиской и открытой таблицей. При подписке тиковые данные начинают тянуть историю после запуска скрипта c подпиской. При открытой таблице в работающем терминале скрипт просто получает сразу готовую тиковую базу. Я держу и открытую таблицу и подписываю скрипт.
Ну сделайте наконец возможность изменения размера окна "Доступные скрипты"! Достало уже забавляться целый день прокруткой после изменения шрифтов. У вас что, все экраны 15 дюймов ?
Заодно поставьте уже кнопку запуска этого окна рядом с веселиньким паровозиком.
Известная фича. Каждый фильтрует по своему. У меня проблема была забыта после того, как поставил условие что каждый trade_num должен быть больше предыдущего.
А с чего вы взяли, что этот параметр обязательный? Ответ на транзакцию вы получаете от сервера брокера. Если он настроил его так, что поле ACCOUNT необходимо для обработки, то оно обязано быть. Точно так же как, допустим, в таблице текущих торгов моего брокера нет поля с датой дивотсечки, а в альфе есть. В этой ситуации смысла наезжать на разработчиков никакого нет. Вот если бы этот параметр требовал ваш терминал перед отправкой на сервер то он был было обязательным. В общем смысла поднимать фоновый шум в данной ситуации нет.