Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 27.01.2017
18.11.2025 18:59:46
Цитата
nikolz написал: он дергается основным потоком ровно тогда когда тот запихивает данные в хранилище. Если нам не надо реагировать на незакрытую свечу, то в колбеке просто ее игнорируем.
Я же написал, что для меня - это лишние телодвижения. Нет желания разбираться какой это вызов колбека, холостой на истории или по закрытию бара, или по сделкам внутри бара. Я точно также одним if сравню последний размер выборки с текущим. Плюс уже просто личные субъективные предпочтения - не использую колбеки основного потока. Это уже дело вкуса. Но как говорится, кому-то подавай ООП со всеми излишествами, мне же простой C - лучший выбор.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 27.01.2017
18.11.2025 17:59:48
Цитата
nikolz написал: А если поставить колбек то и тыкать не надо. Тратим время лишь когда приди данные. Что не так?
Не так, что этот колбек будет вызываться на всех барах истории, начиная с 1. Также он будет дергаться на каждую сделку. Это все лишние телодвижения. По крайней мере мне необходимо пройтись по последним, скажем 100 барам, а далее один раз на новый бар. Но да, можно и так, если организовать доп. проверки в этом колбеке.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 27.01.2017
18.11.2025 16:59:33
Цитата
VPM написал: Так и в нашем упрощённом варианте предусмотрен выход из цикла подписки.
Может я, конечно, невнимательно смотрел примеры, но все одни предполагали ожидание через цикл. Т.е. заказали - и тут же ждем. В итоге заказ 100 источников растягивается во времени, т.к. последний будет заказан только через 100*время ожидания. Что долго. Подход заказали все сразу в цикле и потом ждем все в цикле лучше, но тоже заблокирует скрипт пока ждем циклом. Здесь же заказ всех сразу. И периодически просто атомарно "тыкаем палочкой" на предмет данных. Пришли - можем делать что-то с данными. Нет - переходим к другим задачам, а эта пока путь остается. Т.е. ожидание не мешает другим задачам не связанным с данными, коих может быть много в скрипте.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 27.01.2017
18.11.2025 16:26:56
Цикл for i = 1, #sec_list do - это просто пример организации заказа данных. Он выполняется однократно и ничего не блокирует. С тем же успехом можно было бы вставить где-то в другом месте вызов заказа данных.
Единственно, что можно изменить - это более ранний выход из процедуры обработки задач, чтобы проход по очереди задач был однократный за вызов.
count=count+1 ifcount>#task_queuethen if#task_queue==0thenprint('Очередь задач пуста') end return end
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 27.01.2017
18.11.2025 16:11:38
Я не понял комментарий. Есть контекст. В нем открываем ds и запускаем задачу. У ds есть признак done_request. В очередь задач кидаем функцию проверки размера. Эта задача ничего не блокирует, т.е. можно в рамках контекста выполнять другие задачи, например, обработать сделки, совершенные пользователем, команды интерфейса и т.д. А процедура, которая зависит от ds, просто ждет когда признак done_request изменится.
Код
В Вашем подходе будет все висеть пока все тикеры не подпишутся
Что будет висеть? Вызов Dispatch() - это один из методов main, коих может быть бесчисленно число. Т.е. обработали задачи, какие-то завершились, а какие-то нет. Но это не значит, что висит, просто переходим к дальнейшему выполнению main, после возврата из Dispatch(), т.к. он не блокирующий. В нем просто перебираем накопившиеся задачи и выходим после прохода по очереди.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Подпиской создали таблицу интерфейса для получения данных, а дальше в потоке луа получаем ds:O(I).
Вы так восторгались корутинами, что подход запрос -> чтение ответа через вызов-проверка должен быть очевиден. Самое главное - у нас нет понятия сколько времени займет приход ответа. Может 100 млс, а может 5 минут. Поэтому нельзя использовать любые подходы с циклами ожидания с какой-то заданной величиной. Да, необходима какая-то отсечка по времени, чтобы отсекать проблемные запросы.
Вот наивная реализация такого подхода. Специально добавил счетчики как задачи из прошлого примера, чтобы было видно, что можно переключаться между разного рода задачами. Наивная реализация потому что в реальности необходимо учитывать, что задачи могут быть вытесняющие, с приоритетами, последовательными, с многими внутренними шагами и т.д.
Также стоит учитывать, что простая проверка размера ds:Size() - это слишколм просто. Я проверяю время последнего бара и время последней сделки, чтобы избежать порционного получения данных, когда размер уже не 0, но он еще не последний.
Код
local is_run = true
if _G.message then
print = function(...) _G.message(table.concat({...}, ", ")) end
end
local task_queue = {}
local function AddActionResult(task, is_done, is_error, mes)
if not task then return end
if is_done then
task.done = true
task.error = false
task.response_mes = tostring(mes or '')
elseif is_error then
task.done = false
task.error = true
task.response_mes = tostring(mes or '')
end
end
local function Process(task)
if not task then return end
if not task.process then return end
if not task.in_progress then task.in_progress = true end
AddActionResult(task, task.process())
end
local function Dispatch()
if not is_run then return end
local count = 1
while is_run and #task_queue > 0 do
local task = task_queue[count]
if task and not (task.done or task.error or task.stop) then
Process(task)
end
if task and (task.done or task.error or task.stop) then
task.in_progress = false
local response_mes = ''
if not task.silent or not task.done then
if task.done then
response_mes = 'Задача выполнена успешно: '..tostring(task.description)
elseif task.error then
response_mes = 'Задача не выполнена: '..tostring(task.description)..', по причине: '
elseif task.stop then
response_mes = 'Задача остановлена: '..tostring(task.description)
end
print(response_mes)
if (task.response_mes or '')~= '' then print('\t'..(task.response_mes or ''))
end
if type(task.done_callback) == 'function' then task.done_callback(task) end
if type(task.err_callback) == 'function' then task.err_callback(task) end
end
table.sremove(task_queue, count)
count = count - 1
end
if count + 1 >= #task_queue then
if #task_queue == 0 then print('Очередь задач пуста') end
return
end
count = count >= #task_queue and 1 or count + 1
end
end
local function create_ds(ctx, done_callback, err_callback, wait_time)
if not ctx then return end
local ds, err = _G.CreateDataSource(ctx.class_code, ctx.sec_code, ctx.interval)
if not ds then
print(err, 3)
return
end
ds.interval = ctx.interval
ds.class_code = ctx.class_code
ds.sec_code = ctx.sec_code
ds.description = ctx.class_code..'|'..ctx.sec_code..', интервал '..tostring(ds.interval)
ds.done_request = false
ctx.ds = ds
print('Заказ данных '..ds.description)
wait_time = wait_time or 60
local lt = os.time()
local task = {description = 'Заказ данных '..ds.description, ctx = ctx}
task.process = function()
if os.time() - lt >= wait_time then return false, true, 'Не удалось инициализировать инструменты за время '..tostring(wait_time)..'сек.' end
local size = ds:Size()
if size == 0 then return end
ds.done_request = true
return true, false, 'Получены бары '..ds.description..', размер: '..tostring(size)
end
task.done_callback = done_callback
task.err_callback = err_callback
task_queue[#task_queue+1] = task
end
local function counter(i, limit)
local x = 0
local task = {description = 'Счетчик до '..tostring(limit)}
task.process = function()
x = x + 1
if x >= limit then
return true, false, string.format('%i: Счетчик до %i завершен', i, limit)
end
end
task_queue[#task_queue+1] = task
end
local sec_list = {}
sec_list[#sec_list+1] = {class_code = 'QJSIM', sec_code = 'SBER', interval = 1}
sec_list[#sec_list+1] = {class_code = 'QJSIM', sec_code = 'SBER', interval = 2}
sec_list[#sec_list+1] = {class_code = 'QJSIM', sec_code = 'SBER', interval = 5}
sec_list[#sec_list+1] = {class_code = 'QJSIM', sec_code = 'SBER', interval = 10}
sec_list[#sec_list+1] = {class_code = 'QJSIM', sec_code = 'SBER', interval = 20}
sec_list[#sec_list+1] = {class_code = 'QJSIM', sec_code = 'GAZP', interval = 10}
sec_list[#sec_list+1] = {class_code = 'QJSIM', sec_code = 'GAZP', interval = 2}
sec_list[#sec_list+1] = {class_code = 'QJSIM', sec_code = 'GAZP', interval = 5}
sec_list[#sec_list+1] = {class_code = 'QJSIM', sec_code = 'LKOH', interval = 5}
sec_list[#sec_list+1] = {class_code = 'QJSIM', sec_code = 'FEES', interval = 5}
sec_list[#sec_list+1] = {class_code = 'SPBFUT', sec_code = 'SiZ5', interval = 5}
sec_list[#sec_list+1] = {class_code = 'SPBFUT', sec_code = 'RIZ5', interval = 5}
sec_list[#sec_list+1] = {class_code = 'SPBFUT', sec_code = 'RIZ5', interval = 15}
sec_list[#sec_list+1] = {class_code = 'SPBFUT', sec_code = 'SRZ5', interval = 30}
function main()
for i = 1, #sec_list do
counter(i, i*2)
create_ds(sec_list[i])
end
while is_run do
Dispatch()
sleep(100)
end
end
function OnStop()
is_run = false
end
В итоге можно заказать много потоков, но пока не принято решение, что данные получены, есть задача проверки. И не важно сколько времени это займет. Также и с транзакциями. Например, сегодя с утра один из брокеров обрабатывал транзакции 2 минуты, хотя обычно менее секунды. Но т.к. нельзя сказать сколько времени займет процедура запрос-ответ, то и просто ждать 30 секунд нельзя. Да и 2 минуты нельзя, т.к. завтра может придется ждать 5 минут.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Да причем здесь безопасность. Вы работаете а терминале - это клиент для сервера. Его задача показать данные, приходящие с сервера. И отправлять запросы на сервер. Все.
Можно абстрагироваться и сказать - есть база данных где-то в сети и есть клиент (браузер), показывающий данные. Задача показать данные из 1000 таблиц. Одна таблица - один запрос. Данные могут приехать за 10 млс., а могут за пару минут. Время не угадать.
Поэтому такого рода задачи решаются через запрос, запрос, запрос.... Ответ, ответ, ответ, таймаут, ответ... А не запрос-ждем, запрос-ждем... и последний запрос будет через бесконечность.
Т.е. кидаем запросы атомарно, создаем задачу для проверки ответа. В других языках можно было бы организовать AsynсAwait для ожидания ответа в фоне, пусть приходит ответ когда придет, а пока будем выполнять другие задачи. В Luа же проверяем ответ опросом созданных задач. Пришли данные - фиксируем, переходим к следующему. Не пришли - выполняем другую задачу. И так пока не придут все данные и мы не очистим очередь задач, опрашивая их. Вы же только что сами писали про магию корутин, а здесь забыли про это.
Т.е. атомароно запрос -> задача ответа. Проверка ответа тоже атомарно. Транзакцию мы также отправляем - команда транзакции -> задача проверки транзакции. Т.е. скрипт это по сути конечный автомат, создающий задачи разного рода. Мы их опрашиваем, проверяем что они выполнены, переходим по состояниям задачи. Переключаемся между ними. При этом запросы на данные могут быть параллельно с задачами на транзакции. Поэтому любое ожидание - это вред.
Такое ощущение, что все забыли как работала связь в 90-х. Тогда речи не было о млс. Минуты.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 27.01.2017
17.11.2025 15:28:20
Цитата
TGB написал: Ее легко изменить для запроса данных по многим тикерам: Параметром при этом может быть таблица со списком class_code, sec_code, tf. В цикле запрашиваются ds, а затем в цикле выполняется проверки поступления данных (как это делается в выложенной функции) и выдается результат в виде таблицы параметра с добавленным полем ds.
Это все равно будет блокирующая реализация, т.к. просто будете ждать в цикле. Закажете сразу, да. Но выйдете из метода только после ожидания. А по хорошему, заказ - это атомарное действие и проверка - это атомарное действие. Не пришли данные - переходим к другим действиям, может по какому-то инструменту надо транзакцию отправить.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 27.01.2017
17.11.2025 14:59:17
Цитата
TGB написал: Функция запроса данных свечей по тикеру с учетом возможных задержек
Просто к слову - это блокирующая реализация. По опыту, данные могут приходить долго. Поэтому я предпочитаю подход через неблокирующие задачи. Сразу заказывается много потоков, хоть 1000. А потом просто проверяем, что данные приехали, опрашивая задачи.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 27.01.2017
17.11.2025 13:05:01
Цитата
VPM написал: Следовательно ds:Size() = 0, есть показатель того что брокер не отдает данные?
К сожалению нет, т.к. это просто признак, что данных пока нет. Но они могут появится. В этом плане Квик очень скуден в плане определения статусов серверных запросов.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 27.01.2017
17.11.2025 12:27:27
Цитата
VPM написал: Моя идея была получать разные параметры единообразным способом, в формате свечей, что в свою очередь позволило обрабатывать их едиными способами. Использовать единые фильтры, индикаторы, паттерны. Следовательно формировать единую логику, не только для цены, но и для OI, количества на покупку / продажу и так далее.
По этому поводу я не могу ничего сказать, т.к. чтобы делать такие аггрегации необходимо доказать, что они имеют смысл. Единообразие - это хорошо, но не всегда.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 27.01.2017
17.11.2025 12:05:55
Практика нормальная если предполагать, что она работает всегда. Но т.к. это не так, то значит - не лучшая идея. У меня, например, один брокер отдает такие потоки, но только за прошлые сессии, а за текущую уже нет. И зачем такой поток, спрашивается.
Здесь важно понимать, что брокер и биржа - это коммерческие организации. А данные - это их продукт. Хотите данных - покупайте. У биржи напрямую, через брокера - не важно. Соответственно свечи по истории изменения быстроизменющихся данных - это доп. нагрузка на инфраструктуру. Кто-то дает и так, кто-то нет. Не готовы мириться с качеством - готовьте сами. Данные есть - аггрегируйте сами, хоть по ТФ = 33 секунды. Если есть хоть какой-то смысл в этом действии. А если видите, что есть пропуски данных (а это будет точно) и это очень важно, то следующий шаг - заказать прямой доступ к серверам брокера через API. Но писать уже будете явно не на Lua. Если и этой скорости мало, то прямо к бирже и аренда серверов с прямым доступом к бирже.
Другой вопрос - а готовы ли к расходам. И стоит ли это вообще делать, т.к. обычно такие скорости нужны для HFT где нужны объемы, которые очень редко доступны для физ. лиц.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 27.01.2017
17.11.2025 11:47:09
Цитата
VPM написал: А что брокер под каждого клиента подстраивает сервер? Или как?
Нет, просто не включает многое. Сервера и каналы не резиновые. Тем более, что сейчас уже не модно сидеть перед монитором. А для экранов 5 дюймов много не надо, там и данные можно отдавать раз в секунду - никто не заметит.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 27.01.2017
17.11.2025 11:41:59
Если Вы просто хотели обычный поток баров-свечей, то не надо указывать имя доп. параметра ТТТ 'last' при создании потока.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 27.01.2017
17.11.2025 11:30:57
Возможность создания источника данных по данным ТТТ должна быть поддержана брокером. Многие брокеры не включают избыточные потоки данных по умолчанию. Например, те же обезличенные сделки, т.е. тиковые данные только по запросу. Также и для баров по данным ТТТ. Обычному пользователю это не надо. А кому надо запросит.
Индекс запсииси в таблице ордеров
Пользователь
Сообщений: Регистрация: 27.01.2017
13.11.2025 11:54:46
Думаю, что смело можно сказать, что в серверной части Квик есть какой-то "гуляющий" баг. Начиная с 12-ой версии происходят регулярные отключения с последующим вызовом OnCleanUp.
Если бы это был только один брокер, то, возможно, можно было бы списать на его настройки. Но это происходит у разных брокеров с разной периодичностью. Хотя у брокера Альфа пока не было таких случаев вовсе. Но т.к. у него Квик не особо доступен, то, возможно, данное поведение связано с нагрузкой на сервера.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 27.01.2017
06.11.2025 16:33:20
Код
if self.loaded[cache_key] then
return self.data[cache_key] -- Возвращаем из кэша
end
Т.к. я вижу в данных таблицы, которые постоянно изменяются, то не очень понятно о каком кеше идет речь. Кеш нужен для условно постоянно информации, а не для той, что изменяется каждую секунду. Эти данные нужны для совершения торговых операций, например, проверить, что там с доступными средствами. Обращаться постоянно к ним особой нужды нет. Также есть данные изменяемые при изменении статуса сессии, завершении клиринга - вот их можно помещать в кеш, и обновлять оный по этим событиям.
И да, делать для этого объекты - так себе затея.
Входящие параметры для скрипта - это код инструмента, торговый счет, субсчет (код клиента) если их несколько. Все. Остальное получается из терминала. Впрочем даже счет и субсчет можно подставить из данных для класса инструмента. Зачастую они и нужны.
Если Вы пишите скрипты для себя, то, конечно, делайте как хотите. Но если уже для других, то всегда отталкивайтесь, что максимум что может сделать пользователь - это изменить файл настроек, где все максимально просто и понятно. Не надо искать информацию в служебных окнах терминала. Либо делать интерфейс, через который тоже просто задаются параметры.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 27.01.2017
05.11.2025 13:34:59
Цитата
VPM написал: мета табличный доступ через "__index"
Это медленно. Объекты нужны там где это действительно надо. А надо это редко.
Как бы вы не обернули и назвали процедуру получения данных из терминала - это все равно будет через один из методов qlua. В данном случае через getParamEx. Можно дополнить кешированием по времени пакета, хотя чтобы его получить тоже придется обратиться к данным терминала.
Квик, к сожалению, не предоставляет удобных методов, позволяющих отслеживать изменение параметров в реальном времени. Точнее - их нет. Есть событие, что что-то изменилось. А что - уже нет. Поэтому вы просто вынуждены читать их сами. И если цикл алгоритма длинный (сам алгоритм или много бумаг), то за время последнего обращения к параметру в алгоритме (именно в нем), сам параметр мог изменится уже 10 раз. Поэтому и чтение последней цены надо организовывать сложнее чем просто в момент принятия решения. Хотя это все зависит от алгоритма, и может достаточно понять что есть именно сейчас.
И опять про асинхронно. Да не выйдет у вас сделать это полноценно хорошо, т.к. эту корутину все равно надо самому вызвать, чтобы она прочитала данные. Сама она, без вызова, ничего не сделает. Поэтому данные обновятся тогда, когда вернетесь в эту корутину. Сколько раз вызовете, столько раз и обновятся.
Можно использовать колбек OnParam и в нем читать данные, обновляя некую таблицу. А алгоритм уже будет ее читать. И это без всяких корутин. И будет условно "асинхронно", т.к. колбек приходит от терминала, а не по вызову из кода.
Можно написать скрипт, читающий данные, только это. И, например, сохраняющий в in_memorу database или как-то иначе. А других скрипты уже читают это. Т.о. будет действительно некое подобие распараллеливания. Думать о чтении данных не надо - они есть. Хотя это мало чем отличается от прямого чтения через getParamEx, если принимать решение только на базе текущих данных, а не за историю.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 27.01.2017
05.11.2025 12:53:15
Большого это сколько в граммах? Скрипты без интерфейса без проблем обрабатывают тысячу и более инструментов. С интерфейсом 500. Правда здесь стоит учитывать, что для интерфейса желательно задать задержку 50 млс.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 27.01.2017
05.11.2025 11:05:05
Цитата
VPM написал: Если их дергать часто, они начинают “затыкать” поток исполнения и могут даже вызывать таймауты при большом количестве бумаг?
Откуда эта информация? Я как-то писал скрипт записи в базу данных состояние стакана. А другой скрипт читал из нее. Для проверки были запущены два скрипта с окнами этого стакана и выведен сам стакан терминала, что банально сравнить визуально данные. Так вот на глаз между тремя окнами очень трудно было заметить различия.
Цитата
VPM написал: Можно делать yield-циклы с sleep(1000) без потери отзывчивости терминала.
Как только Вы вставите в любое место задержку на 1 секунду, цикл main встанет. Не важно где это будет - в самом main или в функции, корутине из этого main. И самое главное - зачем эта задержка аж целую секунду. Чтобы что?
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Как это придет в терминал не детерминировано. Зато известно за что отвечает колбек OnOrder - за изменение информации о ордере. Информация записывается в таблицу ордеров и вызывается колбек. Я пока еще не видел сообщений от разработчиков о том, что колбек всегда приходит раннее информации о ордере в таблице ордеров. Допускаю что это приходит в одном информационном пакете. Как его разберет терминал тоже неизвестно. Т.е. вероятно, что может прийти ранее. А может и нет.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 27.01.2017
03.11.2025 13:00:37
Я не навязываю никаких решений. Боле того, не использую термин "фоновое", т.к. такого нет в Lua.
Задачи с ожиданием решаются через переключение. Как это делать - вопрос второй, хотите корутины - делайте. Дискуссия была про то, что корутины это не единственное, и уж те более не идеальное решение. Не более.
Если есть ожидание, то просто переключаетесь на другую подзадачу и она становится активной. Прошлая не становится фоновой, а просто на стеке запоминается ее состояние, чтобы при переключении на неё, можно было бы выполнять её не с самого начала заново. Но это не делает её фоновой, т.к. она ничего не делает, как только мы вышли из неё.
Если у Вас уже есть решение по обработки серверных данных, то и используйте его. Речь была про то, что это решение должно быть независимым от реализации алгоритма. Это просто набор методов, предоставляющий интерфейс. Соответственно скрипт должен просто дергать его методы, принимать решения по ответам.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 27.01.2017
03.11.2025 11:21:28
Забудьте про слова асинхронность, потоки и т.д. Для начала необходимо зафиксировать все ситуации, которые могут привести к проблемам. А потому же решать вопросы про архитектуру. У Вас же все наоборот.
Представьте, что Вы в начале 90-ых, когда почти все писалось синхронно. Задачи же решались.
Цитата
Ожидание ответа в цикле main приводит к проблеме - зависанию
Потому что так делать нельзя. Любой блокирующий цикл - это зло.
OnTransReply - это колбек, ответ на отправку транзакции. Это не результат, а все лишь ответ. Он нужен чтобы прочитать ошибку отправки, чтобы не ждать ордер далее, т.к. он уже не появится. Все. В этом плане - это единственный колбек, который не вызывает вопросов. Поэтому если отправили транзакцию на ордер, то результат - это не колбек OnTransReply, а появление записи по этому ордеру в таблице ордеров. Колбек же OnOrder - это уже следствие появления этой записи, а не наоборот. Любители обработки колбеков вынуждены решать вопросы с их приходом: гарантированность, последовательность, многократный приход, пропуск колбека за время простоя. Т.е. если Вы решили их использовать, то сначала решите все эти вопросы на бумаге, потом уже в коде.
И подход решения этих проблем не связан с асинхронность. Я подозреваю, что Вы за этим термином понимаете просто "непоследовательность". Но это не решает вопрос, тем более, если пишите скрипт для одного инструмента. Вот когда их много, тогда уже необходимо задумываться о разбивке одной задачи на подзадачи. Например, установить 100 ордеров при старте торговой сессии.
Задача сведется к подзадачам:
- Отправить транзакцию, с учетом лимита на число транзакций в секунду.
- Прочитать ответ транзакции. Найти ордер по транзакции. Это одна задача, т.к. ордер может появится раньше. Если ответ транзакции первый и там ошибка, то вернуться к пункту один или прекратить выполнение, в зависимости от алгоритма.
- Если это ордер с ожиданием сделок (рыночный), то если есть флаг исполнения ордера ожидать сделки по ордеру до исполнения количества. Но можно и не ждать, если алгоритм позволяет игнорировать это.
- Попутно проверять состояние ордера, т.к. он может быть снят и, возможно, его необходимо восстановить.
-- и т.д.
Т.о. выполнение задачи может быть долгим, но смысл разбиения в том, чтобы пока одна подзадача ждет результат (ждет не в блокирующем цикле), другая начала выполнение. И этот подход - это просто оптимизация. Как Вы это будете решать - дело ваше. Можете ждать колбек, может сами сканировать флаги, таблицы на новые записи.
Если вернуться к "Ожидание ответа в цикле main приводит к проблеме - зависанию", то решение - это по приходу колбека OnTransReply записать в некую таблицу результат по номеру транзакции. А уже подзадача проверки просто проверит в этой таблице на наличие записи. И сделает она это тогда, когда к этой подзадаче вернетесь, т.е. никакого ожидания с циклом. Тем более, что совершенно не понятно какое время ожидания указать. Много видел примеров с ожиданием 30 секунд. Всегда было интересно откуда эта цифра, а почему не 45? А если ордер пришел раньше ответа транзакции, то и проверка будет уже не особо нужна.
Что касается перезапуска скрипта, то здесь все очевидно - сохранение состояния скрипта, чтение при запуске, актуализация состояния по текущим данным после запуска. За время простоя ордера могли исполнится, быть сняты, руками закрыта, открыта позиция и т.д. Т.о. задача проверить все сохраненные данные и принять решения по выявленным расхождениям. Без решения этой задачи скрипт становится достаточно опасным для использования.
Т.о. рабочий скрипт будет 80% времени заниматься служебными задачами - контролем соединения; состоянием сессии; статусом торгов по инструменту; обслуживать интерфейс, если он есть; обновлять данные с сервера; проверять статусы ордеров, если не используются колбеки; проверять изменения позиции, баланса по деньгам и т.д. А так называемый алгоритм, который всего лишь автоматизирует торговые команды - это не самая большая часть скрипта. Поэтому складывается впечатление, что Вы начинаете не с того. Уж тем более не столь важно как технически реализован алгоритм, если скрипт не позволяет пользователю себя остановит и продолжить с того же места, не умеет останавливаться когда торговая сессия не идет и т.д.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
OnTransReply может не вернуть номер ордера. Более того, он может прийти после первого OnOrder.
Так что он нужен только для проверки ошибка транзакции. Для получения номера ордера необходимо обращаться к таблице ордеров по номер транзакции.
С таймоутами тоже аккуратней, т.к. время ответа на транзакцию вполне может достигать минут. Все зависит от того, как работает сервер брокера. Отправили транзакцию, а ответы и записи в таблице ордеров появляются через 10 минут. Понятно, что это редкое явление, но достаточно одного такого случая, чтобы алгоритм наставил дублей ордеров, если нет проверок.
Ну и главное - колбек дело хорошее, но он не гарантирован.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 27.01.2017
02.11.2025 14:07:05
Ожидания - это просто проверка флагов. Например, ожидание появления ордера в таблице ордеров - это проверка, что пока еще ордер на найден. А если не найден, то ищем. нашли - переходим к следующему шагу. Пока не найден - остаемся в этом же состоянии.
Также и с любыми ожиданиями. В этом же примере есть ожидание получения текущей цены (хоть и тривиальное). Пока не получено остаемся там же.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 27.01.2017
02.11.2025 11:01:16
Цитата
VPM написал: Я своей целью ставил демонстрацию возможного применения корутин, и максимально сложного написания аналога с помощью подхода использования замыканий на луа без сторонних библиотек
Какая-то странная позиция по процедурному подходу. Я бы сказал, что подход корутин сложен, т.к. написан с большой вложенностью, не очевидные выходы и входы. банально понятьт в каком месте сейчас находится алгоритм сложно.
Вот банальная реализация на базе процедур, простейшего замыкания и конечного автомата для шагов стратегии (по текущему шагу легко понять где находимся). Просто взял код и вынес в процедуры. Я бы сказал, что у этого подхода гораздо больше возможностей к адаптации. Взял код и быстро переработал. Ничего особо не проверял, просто переделал. В итоге есть базовые процедуры, которые можно использовать вне стратегии, в других стратегиях. Т.е. убираем дублирование кода. Также можно и нужно вынести в процедуры сам вход в позицию, т.к. явно же его можно и нужно использовать универсально. Код стал с меньшей вложенностью, проще поддерживать, изменять стратегию, т.к. нет сложных вложенных циклов.
В итоге, если говорить о каком-то системном подходе, то все базовые процедуры и методы, такие как инициализация инструмента, получение данных с сервера, обработка транзакций, работа с таблицами терминала - должно быть вынесено в библиотеки, не должно зависеть от стратегии.
Сама же стратегия должна быть независима от базовых вещей и должно представлять собой алгоритм последовательного принятия решения на базе анализируемых данных. Для реакций используются уже базовые методы.
localfunctioncheck_chng(ctx, cur) if (curor0) <=0thenreturnend if (ctx.base_price or0) ==0thenreturnend localdrop= (cur-ctx.base_price) /ctx.base_price ifdrop<=-ctx.drop_trigger then returndrop end ifdrop>=ctx.drop_trigger then returndrop end end
localfunctionprocess_chng(ctx) localcur=tonumber(getParamEx(ctx.class, ctx.sec, "LAST").param_value) if (curor0) <=0thenreturnend localdrop=check_chng(ctx, cur) ifdrop<0then log(string.format("[%s] v Падение %.2f%% > Покупка", ctx.sec, drop*100)) cur=fit(cur, ctx.step, ctx.scale) send_order(ctx.class, ctx.sec, "B", cur) ctx.entry =cur returntrue end end
steps[1] =function() localprice=tonumber(getParamEx(class, sec, "LAST").param_value) ifnotpriceorprice<=0then return end ifnotctx.base_price then ctx.base_price =price log(string.format("[%s] Базовая цена: %.2f", sec, price)) step=step+1 end end
steps[2] =function() ifnotctx.base_price then step=step-1 return end ifprocess_chng(ctx) then step=step+1 end end
steps[3] =function() ifprocess_close(ctx) then log(string.format("[%s] Позиция закрыта, возвращаемся к ожиданию.", ctx.sec)) step=step-1 end end
returnfunction()
ifnotsteps[step] then log(string.format("[%s] x Стратегия завершена", sec)) return0 end
steps[step]()
end end
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 27.01.2017
01.11.2025 11:36:46
Такое запускать только с надписью - "на свой страх и риск, понимая, что вероятность потери 99.5%"
Для начала, есть секции, где разрешены отрицательные цены. Потом нет нигде предупреждения, что необходимо закрывать позицию после остановки скрипта, т.к. нигде не видно контроля ранее открытой позиции, при прошлом запуске.
Контроль текущей цены необходимо организовывать сложнее и аккуратнее, т.к. многие брокеры в период клиринга, транслируют цену 0. А т.к. я не вижу вообще никакого контроля статуса сессии, то можно предположить, что он где-то есть. Но очень вероятна ситуация, когда статус сессии уже "открыта", а текущая цена еще 0 - по причине, например, что ещё не прошла ни одна сделка, просто не пришли еще пакеты с данными о ценах. Впрочем, т.к. в этом примере разрешены только положительные цены, то эта проблема нивелируется. Но для инструментов с отрицательными ценами (и с нулевыми) - это важно.
Также приход пакетов данных нигде не гарантируются последовательно. Так что вполне может прийти пропущенный пакет данных из прошлого. В пакете данных есть время, и не мешало бы его контролировать.
Далее, что еще более настораживает - это как организованы сделки. Почему-то отправка транзакции приравнивается к сделке. При этом транзакция лимитная, что никак не гарантирует исполнение. Она может быть отвергнута, может не исполнится, цена банально убежит от неё. Также, если за время отправки транзакции, цена ушла от цены внутрь, то ордер исполнится не по цене отправки. А в примере нет контроля сделок по ордеру, т.е. нет реальной цены исполнения. Также стоит учитывать, что исполнение транзакций может быть долгим. Отправили транзакцию, а ответ и сам ордер появились через минуты. За это время цена сходит десять раз туда и обратно. Т.е. организация работы с транзакциями должна быть транзакционной. Собственно поэтому она так и называется. Да и любое взаимодействие клиент-сервер должно быть таким: Запрос->ответ->принятие решения.
Это просто что первое бросилось в глаза. Напоминает пакеты для торговли через Web - интерфейс к командам, контроля работы ноль, К реальности малоприменимо.
Я могу понять, что это пример, показывающий работу корутин. Ок. Но к реальной торговле он малоприменим. Как это выглядит - дело вкуса. Как по мне - элегантности здесь нет, т.к. приходится сооружать длинные конструкции с большой вложенностью. Если вложенность кода больше 3-4 (а я здесь вижу аж 8), то уже стоит задуматься, что явно что-то не так.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 27.01.2017
31.10.2025 17:15:10
Ну так в индикаторах замыкания используются не зря. Это позволяет хранить стек между вызовами OnCalculate. Сделки смогут проходит раз в час. И вызовы будут помнить все, что было час назад. И не надо городить глобальных переменных, ничего передавать не надо (в этом плане примеры от ARQA некорректны, т.к. передают каждый раз настройки). Т.е. это конструктор некого алгоритма расчета. Да, это можно реализовать через корутины, а кто-то будет упорно доказывать, что это надо решать через классы, они ведь тоже помнят контекст. Тем более, что целое поколение всем вдалбливали, что ООП - это основа, основ. Но как все в истории повторяется, теперь уже не так активно стали это говорить, и даже больше, ООП - это не очень удачная затея в целом.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 27.01.2017
31.10.2025 16:44:33
Цитата
VPM написал: В подходе с корутинами. Никаких ручных "этапов" — код читается как обычный последовательный сценарий. Можно использовать yield где угодно, чтобы "заморозить" выполнение. Можно легко добавить ожидание событий, сетевые операции и т.д. Логика выглядит линейно, но выполняется асинхронно.
Да нет ничего сложного писать такие же легкие функции и без корутин. Если под легкостью подразумевается "загнать в корутину длинную портянку с множественными yield", то это спорный вопрос, насколько это легко воспринимается.
Цитата
Да, но в подходе с замыканиями - приходится вручную хранить состояние "этапа" в цикле "подожди, пока".
Ничего хранить вне замыкания не надо, оно само хранит на стеке свое состояние. Просто вызываете метод и он помнит окружение. Это кстати один из базовых методов организации своих колбеков, помещенных в очередь исполнения. Создали окружение, запихнули в очередь. И выполняете. Когда закончится выполнение, он сам вызовет колбек, который помнит все, чтобы отработать. Никаких дополнительных действий.
Думаю, что спорить дальше не стоит. Как уже писал, я корутины использую только для своих итераторов (hack-trade, кстати, и есть бесконечный итератор) или если надо пробросить varargs ... на следующий уровень. Более нужды нет. Любая длительная операция, требующую ожидания неопределенное время, выполняется через очередь задач, построенную на простых функциях, где-то замыканиях.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 27.01.2017
31.10.2025 12:33:31
Любая процедура, вызванная из main не блокирует QUIK. Любая. Хоть завернутая в корутину, хоть вызванная напрямую, хоть в замыкании. Также любая процедура сама принимает решение когда выйти из неё. Для этого есть оператор return. В корутине для этого используется yield. return тоже просто возвращает управление в точку вызова процедуры, тоже не останавливая скрипт.
Любое действие через корутины может быть формализовано через процедуры, с точно такой же последовательностью выполнения и получения результатов. Любое.
Автозапуск скрипта LUA при старте QUIK
Пользователь
Сообщений: Регистрация: 27.01.2017
30.10.2025 15:02:04
Ошибку надо в main сделать. Разработчики скажут, что такое поведение. Методов по управлению сейчас нет и вряд ли в обозримом будущем появятся. Окно запуска скриптов до сих пор не масштабируется.
Автозапуск скрипта LUA при старте QUIK
Пользователь
Сообщений: Регистрация: 27.01.2017
30.10.2025 13:06:23
Идея, судя по всему, чтобы не бегать по скриптам при запуске терминала, которые работали в момент закрытия терминала. События же разные, одно - остановка скрипта, другое - закрытие терминала. При закрытии терминала нет ручной остановки скрипта, а значит при рестарте он будет запущен, т.к. работал.
Для тех, кто вечером выключает терминал, а утром запускает - это вполне ожидаемое, рабочее поведение.
Так что если хотите, чтобы не запускался, просто сделайте ошибку исполнения при остановке. Он тогда не стартует сам.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 27.01.2017
29.10.2025 18:46:28
Нет. Это все не так. Корутина точно также работает. Где в корутине yield, в процедуре return. Где коде coroutine.resume - просто вызов процедуры. Все с точностью до стоки кода. Никаких чудес. Полная аналогия.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 27.01.2017
29.10.2025 17:39:52
Нет такого. Я просто переделал Ваш пример. У Вас там есть задержка. Уберите, если хотите и не будет никаких задержек.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 27.01.2017
29.10.2025 17:17:43
Тогда давайте еще раз, на пальцах. Берем этот пример и "брюки превращаются":
localis_run=true -- "Лёгкий поток" для фоновой задачи localfunctioncreate_task() localcount=0 returnfunction() count=count+1 message("Фоновая задача: шаг " ..count) return-- уступаем управление end end functionmain() localco=create_task() message("Запуск фонового лёгкого потока...") whileis_rundo co() -- возобновляем поток sleep(1000) -- имитация "асинхронного" поведения end end functionOnStop() is_run=false message("Остановка фонового потока.") end
Как говорится - найдите десять отличий.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 27.01.2017
29.10.2025 16:42:53
Цитата
VPM написал: Вы не поняли сути hacktrade, как раз он как пример такой асинхронности.
Я на него смотрел еще в году так 16-ом. Как он работает предельно понятно. Подход далеко не новый, да и с чего ему быть новым если корутины в Lua появились в далеком 5.0 от 2003
Цитата
А main() — просто планировщик, который возобновляет корутины
Правильно. А значит с тем же успехом можно планировать и вызовы процедур, созданных иначе. Какая разница что вызывать - корутину или процедуру. Вызывается из одного и того же места, с тем же ритмом и скоростью. Отличия только в обертке одних в корутины, а другие нет.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 27.01.2017
29.10.2025 15:17:22
Вам, наверно, стоит все же внимательней изучить работу корутин. По крайней мере создается такое ощущение. Нет ничего асинхронного в операторе yield. Это просто выход из процедуры в этой точке. При повторном вызове вернетесь в нее же. Сама корутина ничего не делает после выхода по yield. А значит выполняться она может тоже только через вызовы в основном цикле mian. И тоже частота вызовов регулируется задержкой цикла main.
Собственно ваш любимый hacktrade так и работает.
--[[ MAIN LOOP ]]-- working = true function main() --create_table() log:trace("Robot started") if Start ~= nil then Start() end if Robot ~= nil then
--Создаем корутину, заворяаивая в неё процедуру Robot local routine = coroutine.create(Robot) while working do
--Выполняем корутину в бесконечном основном цикле скрипта local res, errmsg = coroutine.resume(routine) if res == false then log:fatal("Broken coroutine: " .. errmsg) end if coroutine.status(routine) == "dead" then log:trace("Robot routine finished") break end -- Orders processing calls after every coroutine iteration for trans_id, smartorder in pairs(SmartOrder.pool) do smartorder:process() end end end log:trace("Robot stopped") if Stop ~= nil then Stop() end io.close(log.logfile) end
function Robot()
-- Вынуждены создавать еще один бесконечный цикл, чтобы корутина жила. Иначе при втором вызове она умрет. while true do if feed.last > ind[-1] then order:update(feed.last, size) else order:update(feed.last, -size) end Trade() - это просто замаскированный yield end end
Логика проста - создали корутину и дергаём ее в цикле постоянно пока она жива. При этом процедура Robot тоже предельно проста - в ней создается бесконечный цикл (еще один), внутри которого есть yield. Т.е. приходится сооружать корутину, внутри которой городить цикл, чтобы она не умерла. Все это накладывается на работу с глобальными переменными....
Чем это отличается от того же вызова, в том же цикле main созданных исполняющих процедур, помнящих свое локальное состояние (что очень важно). Точно также вызывайте когда это необходимо, создавайте очереди вызовов, чтобы создавать иллюзию ассинхронности.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 27.01.2017
29.10.2025 14:14:20
Ну так и в примере, что я показал, все можно сделать не прямолинейно. А колбек сам вызовется по исполнению. Это мало чем отличается от использования тех же корутин. Пишите менеджер вызова исполняемых процедур, а что он вызывает - не важно. Важно чтобы процедура исполнялась столько сколько надо. Если бы корутина работала сама, без менеджера, то это было бы совсем другая среда. Но такого в lua нет.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 27.01.2017
29.10.2025 13:39:34
Если цель помнить состояние, то это прекрасно делают замыкания. Я, например, так пишу таймеры. Можно и счетчик.
Вот ваш счетчик с колбеком по достижению через замыкание
Код
local function counter(i, limit, call_back)
local x = 0
return function(...)
x = x + 1
if x >= limit then
if call_back then call_back(i, ': reach', x, ...) end
return true
end
return false
end
end
if _G.message then
print = function(...) _G.message(table.concat({...}, ", ")) end
end
local is_run = true
function main()
local worker1 = counter(1, 5, print)
local worker2 = counter(2, 20, print)
local worker3 = counter(3, 10, print)
while is_run do
if worker1 and worker1() then worker1 = nil end
if worker2 and worker2() then worker2 = nil end
if worker3 and worker3() then worker3 = nil end
sleep(100)
end
end
function OnStop()
is_run = false
end
Это просто пример с прямолинейной реализацией.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 27.01.2017
29.10.2025 12:18:34
Ну так и функция - это код, который выполняется тогда, когда вызываешь, а не иначе. Т.е. если надо периодически вызывать какой-то расчет, то почему просто не функция. Корутина с остановкой удобна, если надо запомнить состояние и вернуться к выполнению, не передавая заново весь набор параметров. Например, итераторы. Но это далеко не единственный способ так делать. Сделали набор функций и вызывает их в цикле main, пока он крутится.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 27.01.2017
29.10.2025 11:46:40
Код
сделать фоновый поток в QUIK с использованием корутины, без блокировки терминала и с периодическим выводом результата.
main в скриптах - это уже дополнительный поток, выполняющийся отдельно от потока терминала. Создавать внутри него псевдо-потоки можно, но это уже не имеет никакого отношения к фоновому исполнению, т.к. все внутри main выполняется фоново к терминалу, если использовать эту терминологию.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 27.01.2017
29.10.2025 11:15:51
Не вижу смысла. Тем более, что приведенный код выглядит нагроможденным. Если цель проверить какое время необходимо для вычисления c = c + 1 N раз с остановкой на каждую итерацию, то зачем такое количество кода.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 27.01.2017
29.10.2025 10:56:00
К сожалению, это не так. Корутины в Lua - это просто один из инструментов, далеко не идеальный. Я уже говорил, что это же можно сделать через замыкание и через очередь вызовов их. Т.к. они не обеспечивают ничего нового, уникального, то это просто дело вкуса. Если бы это был другой язык, например Go, то это был бы другой разговор.
Так что если нравится использовать корутины - на здоровье. Но сказать, что без них никак, точно нет. Я бы сказал, что к ним стоит прибегать в очень редких случаях - например, создание своего итератора (хотя и здесь можно обойтись без них). Или, например, завернуть некий вызов в корутину, отправить в очередь и потом вызвать.
Индекс запсииси в таблице ордеров
Пользователь
Сообщений: Регистрация: 27.01.2017
26.10.2025 16:40:59
Это уже не дает ошибку, т.к. после OnCleanUp внутри сессии происходит сброс индексов таблицы ордеров и заново ищем ордера по номеру, когда они появятся. Некорректные индексы появились с выходом 12 версии, ранее такого никогда не было.
Сейчас уже вопрос в том - зачем. Скорость загрузки данных - это уже дело десятое, хотя появление записей в таблице ордеров после восстановления подключения через минуты - это не сказать, что хорошо.
[INFO 2025-10-22 11:35:41] : OnConnected flag true
Все же возникает вопрос - зачем в середине торговой сессии вызывать OnCleanUp?
При этом данные после такой чистки загружаются минуты.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 27.01.2017
24.10.2025 11:50:38
Не важно какой подход используется - важно как он работает и работает ли он надежно. Если Вы делаете решение для себя и готовы постоянно заниматься отладкой пограничных ситуаций, то делайте как угодно. Хотя уже здесь корутины начинают привносить излишнюю сложность. Те же замыкания прекрасно справляются с запоминанием окружения и позволяют решать ту же задачу. Далее, что самое важное - это воспроизводимость результатов, обработка ошибок. И здесь колбеки - это не лучшее решение, т.к. они не гарантированы, приходят в случайном порядке. Для задач реального времени - это приговор.
Представьте, что датчик выдает данные. Вы решаете использовать "модную" библиотеку с колбеками. Но начиная использовать её, получаете данные с пропусками, данные могут приходить из прошлого. Во многих отраслях - это просто недопустимое поведение.
Так что нет, я уж как нибудь сам организую чтение данных, как эти делали последние лет 50.
Я понимаю, что есть соблазн использовать подход со слугой - сказал ему, что делать, он сообщит когда будет результат. Но такой подход всегда требует надсмотрщика, проверки. Так что самому подойти к кастрюле и проверить как там каша - надежней.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 27.01.2017
22.10.2025 11:54:13
Это не так.
trans_id - это просто некий ключ, задаваемый при подаче транзакции. При этом, что важно, он не обязательно уникальный. Т.е. необходимо обеспечить уникальность trans_id для нескольких скриптов, если они есть. Иначе очень вероятна ситуация когда trans_id будет одинаковый у разных скриптов. Более того, если отправите транзакцию через команды интерфейса терминала, то trans_id будет пустой. Т.о. trans_id - это ваш ключ. Его необходимо использовать только для понимания, что транзакция принята сервером брокера, ядром биржи. Читая ответ транзакции по нему можете увидеть причину отказа.
Если же транзакция прошла, то наступает следующий этап - получить ключ в ядре биржи, и это order_num. Он будет уникальным. Какой там был ключ транзакции бирже не важно, она получает запрос, отправляет ответ. Сервер брокера перенаправляет ответ биржи клиенту.
Если ошибок при отправки транзакции нет, то после регистрации ордера в ядре бирже, в таблице ордеров появится новая запись, в которой будет order_num и trans_id. При этом trans_id может появится не с первого колбека, а, скажем, со второго. Задача - отслеживать записи в таблице ордеров, и по trans_id найти номер ордера - order_num. После его получения про trans_id уже не столь важен. Почему - все просто, ордер может жить дольше чем одна торговая сессия.
Запоминая номер ордера уже можно отслеживать его состояние. Кто-то предпочитает колбеки, т.к. именно так показано в большинстве примеров на просторах ...., я же предпочитаю читать состояние прямо из таблицы ордеров, в реальном времени. Это делать не так и сложно, т.к. всегда можно запомнить номер индекса записи в таблице ордеров. Т.о. order_num будет ключом для скрипта, по которому он всегда может понять что случилось с его ордером. И скрипт при этом должен уметь отличать свои ордера от чужих.
Поэтому нельзя использовать один ключ при клиент-серверном взаимодействии. Есть ключ запроса, есть ключ ответа. Запрос - это просто действие "сейчас". Ответ же может содержать информацию, которая имеет смысл более длительный промежуток времени.
Не работает getDataSourceInfo в индикаторе
Пользователь
Сообщений: Регистрация: 27.01.2017
13.10.2025 15:19:02
Т.к. с 7-ой версии, кажется, разрешены пропуски на графике, то в теории первый бар может иметь не индекс 1.
Не работает getDataSourceInfo в индикаторе
Пользователь
Сообщений: Регистрация: 27.01.2017
13.10.2025 11:55:13
Только учитывайте, что этот подход рассчитан на то, что будет вызван OnCalculate для индекса 1. Что в большинстве случаев верно, конечно. Но, судя по сему - не гарантировано. Но предпочитаю более надежный подход через инициализацию переменных в замыкании и проверке первого вызова для любого индекса.
Не работает getDataSourceInfo в индикаторе
Пользователь
Сообщений: Регистрация: 27.01.2017
12.10.2025 16:43:20
Его не стоит применять в Init. Запуск индикаторов у Квика устроены очень странно. Вызывайте на первом вызове колбека OnCalculate.