Александр Клименко написал: Здравствуйте. Столкнулся с проблемой отладки кода простенького индикатора. Без данных брокера отладить не представляю как. Quik - 10 Операционка - w7х64.
decoda не работает.
Кто и что может посоветовать толкового?
На демо счете все отлаживается без проблем используйте лог файл.
muyuyu написал: Робот должен усреднять позицию в 1,5 раза после покупки акции в случае снижения на 1% и продавать по ТП 33 (все цифры назначаются в параметрах). Вход авто или ручной.
Можно без бла-бла-бла выложить на форуме, или в личку или файлообменник тех задание, бюджет и сроки. ------------------------ Без обид, но угадывать Ваши хотелки бесплатно нет желания.
Добрый день, Для контроля реального времени прихода сделок с биржи синхронизирую компьютер с сервером точного времени. Не удается получить погрешность менее 20 ms.
Майкрософт декларирует возможность 1 ms. ---------------- Если кому-то это удалось, подскажите как Вы это достигли.
Добрый день, Неоднократно на форуме интересовались передачей данных из QUIK в другое приложение(процесс). Есть много способов. Наиболее универсальным является file mapping Этот метод позволяет обмениваться данными практически любого объема. Использую этот метод не только для QUIK ------------------ В названии метода есть слово файл. Уверен, что многие скривятся и скажут, что метод медленно работает. А вот и нет. . --------------------------------- Что нам рассказывает об этом методе Майкрософт: -------------------------- Это объединение содержимого файла с частью виртуального адресного пространства процесса. Система создает объект сопоставления файлов (также известный как объект раздела) для поддержания этой связи. Просмотр файла - это часть виртуального адресного пространства, которую процесс использует для доступа к содержимому файла. Сопоставление файлов позволяет процессу использовать как случайный ввод-вывод (I / O), так и последовательный ввод-вывод. Это также позволяет процессу эффективно работать с большим файлом данных, таким как база данных, без необходимости отображать весь файл в памяти. Несколько процессов также могут использовать файлы, сопоставленные с памятью, для обмена данными.
Процессы считывают данные и записывают в файловое представление, используя указатели, точно так же, как они делали бы с динамически выделяемой памятью.
Использование данного метода повышает эффективность, поскольку файл находится на диске, а представление файла - в памяти.
===========================
Тест для измерения задержки передачи данных из скрипта QUIK в приложение.
скрипт Теста в SciTe:
Код
paths = "D:/nkarray/"
package.cpath =paths.."?.dll;"
require"nkthread"
----------------------
local T=0; while true do local T1,dt,hms,s,num,HMS,ss=nkmx.gsm(0,T); if T1 then T=T1; print(0.1*dt,hms,s,num,HMS,ss); end end
фрагмент скрипта в QUIK:
Код
function OnAllTrade(t)
local c,s=t.class_code,t.sec_code; local z=ds[c..s]; local num=t.trade_num;
if z then local d=z[1]; local n=z[2]; local f=z[3];
local Ti=t.datetime; local HMS=(60*(60*Ti.hour+Ti.min)+Ti.sec)+0.001*Ti.ms;
local D=os.date("*t"); local hms=60*(60*(D.hour-shH)+D.min)+D.sec-shS;
local dt= hms-HMS+n;
local size=d:Size();
local T1=d:T(size); local HMS1=(60*(60*T1.hour+T1.min)+T1.sec)+0.001*T1.ms;
if HMS==HMS1 and z[4]~=num then
local dt1=0.01*math.floor(100*dt); if 0>dt then dt=0 end count=count+1; count1=count1+1;
local m=math.floor(dt)+1;
local ss=tostring(hms)..","..tostring(s)..",num="..tostring(num)..",size="..tostring(size)..",HMS="..tostring(HMS)..",dt="..tostring(dt1)..",n="..tostring(n)..",m="..tostring(m)..",clock="..(os.clock()-clockOS);
nkmx.ssm(0,hms,s,num,HMS,ss); -- Log:write(ss.."\n"); Log:flush();
if sts[m] then sts[m]=sts[m]+1; else sts[m]=1 end
end
z[4]=num;
end
end
первое число в стоке - задержка передачи параметров из QUIK в приложение в мкс. -------------------- Резюме: задержка передачи методом file mapping параметров из QUIK в другое приложение составляет 0.0000001 сек.
awkozlov написал: Пытаюсь получить из таблицы "Клиентский портфель [SUR]" данные из графы << Плечо >> по строке Т2 Использую для этого код:
Код
local PortfolioInfoExTable = getPortfolioInfo Ex (gFIRMID, gCLIENT_CODE, 2 ) -- https://luaq.ru/getPortfolioInfoEx.html
local zPortfolio_value = PortfolioInfoExTable.portfolio_value -- Стоимость портфеля
local zCash_leverage = PortfolioInfoExTable.cash_leverage -- Плечо
message (tostring(zPortfolio_value) .. '\n\n' .. tostring(zCash_leverage))
Но значение плеча zCash_leverage нулевое, хотя я вижу этот размер плеча явно в таблице "Клиентский портфель [SUR]" в строке Т2. При этом мне успешно показывается стоимость портфеля - zPortfolio_value. У меня такое ощущение, что в синтаксисе команды getPortfolioInfoEx должно быть ещё указание на валюту т.к. она указана в титуле окна. На самом деле мне нужна графа <<Прибыль/Убытки>>, но для упрощения вопроса спрашиваю про графу <<Плечо>>. Как мне получить размер Плеча или Прибыль/Убыток с начала дня по спотовому рынку?
В документации сказано: Функция возвращает таблицу Lua с параметрами таблицы «Клиентский портфель».
Дополнительно возвращаются следующие параметры:
№
Параметр
Тип
Описание
1
init_margin
STRING
Значение начальной маржи. Заполняется для клиентов типа «МД»
Нач.маржа
2
min_margin
STRING
Значение минимальной маржи. Заполняется для клиентов типа «МД»
Мин.маржа
3
corrected_margin
STRING
Значение скорректированной маржи. Заполняется для клиентов типа «МД»
Скор.маржа
4
client_type
STRING
Тип клиента
Тип клиента
5
portfolio_value
STRING
Стоимость портфеля. Для клиентов типа «МД» возвращается значение для строк с максимальным сроком расчётов limit_kind
Стоимость портфеля
6
*start_limit_open_pos
STRING
Лимит открытых позиций на начало дня
ЛимОткрПозНачДня
7
*total_limit_open_pos
STRING
Лимит открытых позиций
ЛимОткрПоз
8
*limit_open_pos
STRING
Планируемые чистые позиции
ПланЧистПоз
9
*used_lim_open_pos
STRING
Текущие чистые позиции
ТекЧистПоз
10
*acc_var_margin
STRING
Накопленная вариационная маржа
НакопВарМаржа
11
*cl_var_margin
STRING
Вариационная маржа по итогам промклиринга
ВарМаржаПромклир.
12
*opt_liquid_cost
STRING
Ликвидационная стоимость опционов
ЛиквСтоимОпционов
13
*fut_asset
STRING
Сумма оценки средств клиента на срочном рынке
СумАктивовНаСрчРынке
14
*fut_total_asset
STRING
Сумма оценки собственных средств клиента на фондовом и срочном рынках
ПолнСтоимостьПортфеля
15
*fut_debt
STRING
Текущая задолженность на срочном рынке
ТекЗадолжНаСрчРынке
16
*fut_rate_asset
STRING
Достаточность средств
Дост. Средств
17
*fut_rate_asset_open
STRING
Достаточность средств (под открытые позиции)
Дост. Средств (ОткрПоз)
18
*fut_rate_go
STRING
Коэффициент ликвидности ГО
КоэффЛикв ГО
19
*planed_rate_go
STRING
Ожидаемый коэффициент ликвидности ГО
Ожид. КоэффЛикв ГО
20
*cash_leverage
STRING
Cash Leverage
Cash Leverage
21
*fut_position_type
STRING
Тип позиции на срочном рынке. Возможные значения
«0» – нет позиции;
«1» – фьючерсы;
«2» – опционы;
«3» – фьючерсы и опционы
ТипПозНаСрчРынке
22
*fut_accured_int
STRING
Накопленный доход с учётом премии по опционам и биржевым сборам
НакопДоход
23
rcv1
STRING
Норматив покрытия риска 1. Рассчитывается как разница параметров «Стоимость портфеля» и «Начальная маржа». Для клиентов типа «МД» и «МД+»
НПР1
24
rcv2
STRING
Норматив покрытия риска 2. Рассчитывается как разница параметров «Стоимость портфеля» и «Минимальная маржа». Для клиентов типа «МД» и «МД+»
НПР2
* - параметр заполняется для клиентов с настроенной единой денежной позицией и для клиентов срочного рынка без единой денежной позиции
т е параметры с 6 по 20 заполняются лишь для клиентов с настроенной единой денежной позицией и для клиентов срочного рынка без единой денежной позиции если Вы не такой клиент, то будет ноль.
cudi написал: [img]file:///C:/Users/family/Desktop2.png[/img] теперь после повторного соединения его уже нет
Надо не прикреплять файл, загружать картинку с компьютера, иначе плохое качество ----------------------- Посмотрите внимательно у вас нет спроcа и предложения (bid, offer) по двум валютам 2 и 3 строка поэтому результат пустой. В ТТП нули, т е валюты либо не торгуются либо вы их не выбрали в заказе данных Нечем торговать.
nikolz написал: замечу два момента.1) если речь идет о фильтрации обезличенных сделок, то ваш вариант неправильный. Так как при большом числе сделок вы будете долго искать.На основе своих исследований данной проблемы могу сказать, что задача решается проще. Повторная сделка приходит всегда следом за первой сделкой.Но особенность в том, что следующая сделка по данному инструменту это не следующая сделка в потоке сделок после первой.-----------------------2) Вы зря не хотите реализовать через файлы. Это просто и быстро. Более того, такие методы как Pipe и mailslot тоже используют запись чтение файлов. Поэтому когда набьете руку (голову) на файлах ,то легко решите задачу с Pipe или mailslot и им подобным.
1. Я уже говорил что мне надо получать сделки которые прилетают в функцию OnTrade то есть они не обезличенные, так что с количеством проблем нет. Но это не главное... 2. Я не против сделать через файлы для начала, а может и навсегда. Но даже я понимаю что через память быстрее :) Но мне нужен внятный пример в C++ коде. Потому что сам я прогер слабенький, мягко говоря.
А тут столько блин специалистов и никто не может пример написать. Все жадные до кода :)
1) Для OnTrade, OnOrder,onStopOrder, OnTransReply вообще нет проблем с повторением. ------------------------------------ Но так как это колбеки, то У Вас проблема в алгоритме обработки. ----------------------------------- Если хотите конкретной помощи, то задавайте конкретные вопросы и выкладывайте совй скрипт. Иначе будете бла бла бла с Владимиром. Он Вам будет хвалится что все решил и уговаривать писать на "чистом" Луа, а сам тайно использует dll QLUA, которая написана на C. ____________________________ 2) Вот даже вы ошибаетесь. Файлы они в памяти, И реально Вы и будете передавать через память, если это короткие сообщения и разрешен параллельный доступ к файлам. Рекомендую Вам не гадать, а написать короткий тест и измерить скорость обмена через файлы. ----------------- Повторю еще раз. Хотите помощи - пишите сами получайте ошибки выкладывайте свое произведение и задавайте вопросы. Примеры как писать читать файлы на C вы найдете в интернете. Зачем вам C++, если для луа надо писать на С? С++ еще сложнее чем С. Вы хоть понимаете, что такое классы в программировании? Если нет или Вы пишите без них то Вам С++ не нужен.
Владимир, На форуме я выкладывал пример скрипта в котором любые функции из dll на СИ я вызываю буз использования C fo Lua. --------------- Для этого я написал очень маленькую dll . если Вы крутой программист то напишите аналогичную, а не рассказывайте байки
Владимир написал: повторная сделка не только не всегда приходит следом за первой сделкой, они ещё и приходят "крест-накрест собачьим шагом", особенно красиво это выглядит, если заявка реализуется в десяток-другой сделок. Но это не Ваш уровень - я уже задолбался советовать Вам заняться чем-нибудь кроме программирования - вдруг Вы в какой-то области деятельности и в самом деле что-то соображаете.
Полагаю Вы все путаете. Есть повторение обезличенных сделок в колбеке onAllTrade Именно об этом я и написал. Проблема решается сравнительно просто, но Вы ее не решите. --------------------------- Получение исполненных сделок в OnTrade меня вообще не волнует. ------------------------ Есть повторение заявок onOrder Это вообще не проблема. ================== И кончайте размазывать сопли по экрану. Если хотите сравнить Вашу писанину с моей, то предлагаю напишите передачу параметров между процессами. Я это давно уже написал во всех вариантах Когда напишите то сравним
У меня уже все работает через библиотеку trans2quik но мне необходим альтернативный вариант получения данных через lua скрипт. Поэтому вот мучаюсь. С дублями все просто, получил сделку, сравнил по номеру есть ли такая уже в текущей временной табличке в памяти, если нет добавил, если есть пропустил. А после уже из этой таблички делаю с ними что надо. Но вот как получать данные синхронно из библиотеки, по сути другой программы не связанной с моей, тут я в тупике.. и разобраться без примеров не могу потому как кодер я такой себе.. Кодю по тому что удается нагуглить в примерах. К сожалению варианты из книги которую посоветовал nikolz я не осилил.. там все очень сложно. А внятных примеров найти не получается пока :( В принципе уже нашел ( https://quikluacsharp.ru/qlua-c-cpp-csharp/vzaimodejstvie-lua-i-biblioteki-dll-napisannoj-na-c-c/com... ) как помещать данные в именованную память, но как их оттуда потом доставать в другой программе да еще и синхронно, на С++ пока не нашел примеров :(
замечу два момента. 1) если речь идет о фильтрации обезличенных сделок, то ваш вариант неправильный. Так как при большом числе сделок вы будете долго искать. На основе своих исследований данной проблемы могу сказать, что задача решается проще. Повторная сделка приходит всегда следом за первой сделкой. Но особенность в том, что следующая сделка по данному инструменту это не следующая сделка в потоке сделок после первой. ----------------------- 2) Вы зря не хотите реализовать через файлы. Это просто и быстро. Более того, такие методы как Pipe и mailslot тоже используют запись чтение файлов. Поэтому когда набьете руку (голову) на файлах ,то легко решите задачу с Pipe или mailslot и им подобным.
nikolz написал: проще всего передать данные через файл.-------------------------Для начала можете передавать в текстовом формате. Для этого нет надобности делать функцию на С for Lua. т е пишите в скрипте луа данные в файл, а в своей программе читаете эти данные. при этом Вам надо синхронизировать работу с файлом из приложений,
Этот вариант плох тем что программа не будет знать в какой момент в файле появились новые данные. То есть надо будет постоянно опрашивать файл что не есть хорошо. Надо чтобы все было по событиям, появились данные - программа их получила. Ну и скорость опять же.. Вот мне надо получать данные о сделках, а они могут прилетать в функцию OnTrade по несколько штук в секунду. Работа через файл тут явно не лучший вариант.
Я же Вам написал, что надо синхронизировать. Тогда программа будет знать когда банные изменились. ------------------------ Скорость будет нормальная, так как фалы хранятся в кеш в памяти, если Вы не выгружаете их сразу в файл. Если надо , то создавайте события. Все зависит от того, что напишите. --------------------- Но так как Вы как я понимаю не очень владеете вопросом, то рекомендую начать с простоя реализации. ---------------------- Рассказывать здесь другие Варианты большого смысла нет. Будут конкретные вопросы , отвечу конкретно. ---------------------- Если желаете изучить как сделать профессионально Ваши хотелки рекомендую изучить книгу:
Джеффри РИХТЕР
Создание эффективных WIN32-приложений
с учетом специфики 64-разрядной версии Windows.
В ней есть почти все, что Вам нужно знать и уметь.
paluke написал: Любой механизм ipc - сокеты, каналы, разделяемая память, сообщения, dde... И зачем вообще отдельная программа? Что мешает делать всё прямо в dll?
Нужно в отдельную программу. Там слишком много завязано на нее другого разного. А какой-нибудь наименее сложный механизм в виде примера в коде на C++ можно увидеть?
Что Вам мешает вызвать функцию из dll в своей программе на C++?
Не совсем понимаю как это реализовать, получается функция в DLL вызывается из LUA чтобы передать параметры, и функция в DLL вызывается из программы чтобы эти параметры получить, но как? У меня это не стыкуется в голове как это сделать :( И вообще допустимо ли одновременное подключение DLL и в сторонней программе и в LUA ? Я потому и прошу пример кода чтобы понять как это все реализовать. Пока что я только смог получить параметры в DLL из LUA.
проще всего передать данные через файл. ------------------------- Для начала можете передавать в текстовом формате. Для этого нет надобности делать функцию на С for Lua. т е пишите в скрипте луа данные в файл, а в своей программе читаете эти данные. при этом Вам надо синхронизировать работу с файлом из приложений,
paluke написал: Любой механизм ipc - сокеты, каналы, разделяемая память, сообщения, dde... И зачем вообще отдельная программа? Что мешает делать всё прямо в dll?
Нужно в отдельную программу. Там слишком много завязано на нее другого разного. А какой-нибудь наименее сложный механизм в виде примера в коде на C++ можно увидеть?
Что Вам мешает вызвать функцию из dll в своей программе на C++?
Просим прощения, немного поторопили Вас. На демо-доступе QUIK Junior идёт эмуляция торгов - так называемый игровой полигон, следовательно причины могут отличаться от таковых на реальных торгах.
Просим Вас всё же в аналогичном формате привести в пример: номер сделки, которая пришла с запозданием, её время и время её появления на терминале, но с реального рынка (подключаясь к Сбербанку). Также укажите обязательно дату и сервер (его адрес) к которому Вы подключались. Так мы сможем обратиться к Вашему брокеру и совместно с ним разобрать возможную задержку обезличенных сделок.
Добрый день, Понятно. Но хотел бы услышать Ваше объяснение применительно к Вашему демо серверу. Судя по данным , приведенным мною выше, Вы отправляете обезличенные сделки пакетом. Для демо сервера размер пакета получается в 1 минуту. Полагаю, что на рабочем сервере отправка пакетами остается но возможно, что интервал меньше. Это так? ---------------------------------- Кроме того, могу выложить задержки по свечам. На 1 минутных свечах на демо сервере у Вас задержки до 20 секунд. ====================== Для свечей я наблюдал аналогичные задержки и на рабочем сервере. Обычно это задержка до 10 секунд. ------------------------------- Поясните механизм возникновение этих задержек. ------------------------------- Задержка интернет и загрузка процессора исключаются, так как их величина на несколько порядков меньше. ------------------
Добрый день, по просьбе трудящихся выкладываю пример на QPILE
Код
PORTFOLIO_EX TEST;
DESCRIPTION TEST;
CLIENTS_LIST ALL_CLIENTS;
FIRMS_LIST FIRM_ID;
USE_CASE_SENSITIVE_CONSTANTS;
PROGRAM
NEW_GLOBAL("count",0)
NEW_GLOBAL("CLAS","CETS")
NEW_GLOBAL("List","USD000000TOD,EURUSD000TOD,EUR_RUB__TOD")
NEW_GLOBAL("com",0.000445)
i=1
dif=0
e=1-3*com
f=create_map()
z=create_map()
FOR SEC IN List
s=get_param_ex(CLAS,SEC,"SHORTNAME")
n=get_value(s,"PARAM_IMAGE")
s=get_param_ex(CLAS,SEC,"LAST")
p=get_value(s,"PARAM_IMAGE")+0
s=get_param_ex(CLAS,SEC,"OFFER")
po=get_value(s,"PARAM_IMAGE")+0
s=get_param_ex(CLAS,SEC,"BID")
pb=get_value(s,"PARAM_IMAGE")+0
s=get_param_ex(CLAS,SEC,"LOTSIZE")
q=get_value(s,"PARAM_IMAGE")+0
z=set_value(z,"Name",n)
z=set_value(z,"last",p)
z=set_value(z,"bid",pb)
z=set_value(z,"offer",po)
z=set_value(z,"lotsize",q)
IF count=0
add_item(i,z)
ELSE
MODIFY_ITEM(i,z)
END IF
IF i==3
IF pb>0
dif=e/pb-1
f=set_value(f,"lotsize",dif)
END IF
ELSE
e=e*po
END IF
i=i+1
END FOR
IF count=0
add_item(4,f)
ELSE
MODIFY_ITEM(4,f)
END IF
count=1
END_PROGRAM
PARAMETER Name;
PARAMETER_TITLE Name;
PARAMETER_DESCRIPTION here is Name;
PARAMETER_TYPE STRING(15);
END
PARAMETER last;
PARAMETER_TITLE last;
PARAMETER_DESCRIPTION good;
PARAMETER_TYPE STRING(10);
END
PARAMETER bid;
PARAMETER_TITLE bid;
PARAMETER_DESCRIPTION good;
PARAMETER_TYPE STRING(10);
END
PARAMETER offer;
PARAMETER_TITLE offer;
PARAMETER_DESCRIPTION good;
PARAMETER_TYPE STRING(10);
END
PARAMETER LOTSIZE;
PARAMETER_TITLE lotsize;
PARAMETER_DESCRIPTION good;
PARAMETER_TYPE STRING(10);
END
END_PORTFOLIO_EX
Юрий написал: Коллеги! А можно это все как-то в виде примера с кодом увидеть? Нужно получать в реалтайме данные о сделках и подробности по бумаге (шаг цены, стоимость, число знаков и т.д.) во внешней программе на C++ через некий lua скрипт и я никак этому не дам ума так как нет опыта :(
nikolz написал: В таблице запуска скриптов отображается память занимаемая скриптом. Посмотрите как она изменяется. Попробуйте отключить скрипты.
Согласно той таблице, скрипты занимают несколько мегабайт. А согласно таск менеджеру, квик занимает 3 гигабайта. Да в нём и раньше утечки памяти были, но вроде фиксили. Вот опять. Я пытался старую версию из бекапа восстановить, скопировав поверх текущих файлов, но не запустилось. Какая-то ошибка.
я три раза пытался ставить версию 9 но снес и работаю на 8.7 Но то что у Вас 3 ГБ это не проблема версии. посмотрите сколько у Вас выбрано инструментов и параметров в заказе данных. При смене версий установки могут встать по умолчанию. еще в настройках уберите восстанавливать пропущенные данные, если установлено.
nikolz написал: Возможно, это не утечка. В зависимости от настройки может сохранятся или нет история параметров и ТТП для построения индикаторов. Если история параметров сохраняется, то и затраты памяти растут.
Но у меня же нет никакой активности, кроме скриптов lua. В том числе никаких индикаторов. Вообще никаких таблиц и графиков не открыто. Если бы я каждую секунду менял настройки, то можно было бы понять гигабайт истории параметров. А так - навряд ли. Да и на предыдущей версии такого не было.
В таблице запуска скриптов отображается память занимаемая скриптом. Посмотрите как она изменяется. Попробуйте отключить скрипты.
У меня последняя версия quik (открытие) 10.0.1.18. При работе медленно растёт объём используемой памяти. Только вчера перезапускал (примерно 23 часа назад), и уже Task Manager показывает, что quik занимает 1945 MB. За несколько минут число вырастает на несколько мегабайт. Перезапустил, теперь quik потребляет всего 492 мегабайта. Такого не было на последней версии на дату 24.12.2022. После этого не обновлял до 16.04.2023, всё было хорошо - quik мог работать неделю без сильного роста используемой памяти. Как обновил, а потом ещё раз 18.04.2023, так пошли утечки. У меня постоянно запущены скрипты lua, кроме этого никакой активности.
Хотелось бы, чтобы устранили утечки памяти. Спасибо.
Возможно, это не утечка. В зависимости от настройки может сохранятся или нет история параметров и ТТП для построения индикаторов. Если история параметров сохраняется, то и затраты памяти растут.
Вам достаточно информации, что объяснить по данным Вашего демо сервера: ----------------------------- 1) повторение обезличенных сделок в onAllTrade ---------------------------------- 2) запаздывание прихода обезличенных сделок до 60 секунд по ликвидному инструменту SBER.
в итоге имеем это: 229:156066>64821,89358,916,70,5,18,2,11,3,3,7,11,7,9,22,6,23,13,4,13,30,23,16,10,1,6,8,4,25,8,9,11,41,47,1,18,43,10,4,10,4,9,13,6,22,9,4,15,22,7,44,13,10,3,22,2,2,4,6,10,7,6,3,2,2,10,1,2,1,4,8,6,
анализ результата: ---------------------- 1-я сделка 26361,SBER,num=4781728079,size=57343,HMS=26306.0,dt=55.0,n=0,m=56,clock=2.4609999999998 ------------------------------ последняя сделка 26361,SBER,num=4781729267,size=57604,HMS=26358.0,dt=3.0,n=0,m=4,clock=2.4740000000002 --------------------- Первое число 26361 - это время компьютера в секундах. Оно не изменилось ------------------------- Последнее число - это os.clock в секундах изменяется от 2.461 до 2.474 т е на 13 миллисекунд. ---------------------- HMS - время сделок в секундах изменилось от 26306 до 26358 т е на 52 секунды ---------------------- Таким образом , запаздывание прихода сделок самого ликвидного инструмента составило 52 секунду. ----------------------------------------- Причем, сделки почти за минуту получили за 13 миллисекунд ------------------------------ Все верно? ----------------------------- Можете объяснить?
Даниил Волошин написал: Нужен также номер сделки, по которому можно её отследить на всех этапах её следования.
Обнаружил, что в колбек onAllTrade сделки прилетают повторно!!!! ------------------- Написал для этого такой тест:
Код
local ds={}
local count=0;
function OnParam(c,s)
local z=ds[c..s] if z==nil then d,err=CreateDataSource (c,s,INTERVAL_TICK); if d then d:SetEmptyCallback(); ds[c..s]={d,0,0}; end end
end
function OnAllTrade(t)
count=count+1;
local c,s=t.class_code,t.sec_code; local z=ds[c..s]; local num=t.trade_num;
if z then
if z[2]==num then
Log:write(os.date()..","..tostring(s)..",num="..tostring(num)..","..tostring(count)..",повторение "..tostring(z[3]) .."\n"); Log:flush();
else
Log:write(os.date()..","..tostring(s)..",num="..tostring(num)..","..tostring(count).."\n"); Log:flush();
end
z[2]=num; z[3]=count;
end
end
function OnInit(pfile) local path = getScriptPath(); Log=io.open(path.."/test.log","w") end
function main() while true do sleep(1000); end end
Для того, чтобы можно было провести анализ, нам необходимо знать номер сделки, которая пришла с запозданием, время её исполнения и время её появления на Вашем терминале. Потому просим Вас привести примеры в указанном формате, это позволит нам начать разбор Вашей ситуации.
сделал тест с автоподстройкой времени выкладываю скрипт теста
Код
local tmp={}
local ds={}
local ns=0;
local shH=1 --сдвиг часового пояса
local shS=0 -- сдвиг секунд
local count,count1=0,0; local sts={} ;-- for i=1,100 do sts[i]=0; end
function main()
while true do
-- nkevent.wait(event); --ждем события
while #tmp>1 do
local t=tmp[1]; table.sremove(tmp,1);
if count>=1000 then count=0;
local s=""; for i=1,100 do if sts[i] then s=s..tostring(sts[i])..","; end end
Log:write(tostring(ns)..":"..tostring(count1)..">"..s.."\n"); Log:flush();
end
end
sleep(1);
end
end
function OnParam(c,s)
local z=ds[c..s]
if z==nil then
d,err=CreateDataSource (c,s,INTERVAL_TICK);
if d then d:SetEmptyCallback(); ns=ns+1; ds[c..s]={d,0,0}; end
else
table.sinsert(tmp,{1,c,s}); --nkevent.Set(event);
end
end
function OnAllTrade(t)
local c,s=t.class_code,t.sec_code; local z=ds[c..s];
if z then local d=z[1]; local n=z[2]; local f=z[3];
local Ti=t.datetime; local HMS=(60*(60*Ti.hour+Ti.min)+Ti.sec)+0.001*Ti.ms;
local D=os.date("*t"); local hms=60*(60*(D.hour-shH)+D.min)+D.sec-shS;
local dt= hms-HMS+n;
local size=d:Size();
local T1=d:T(size); local HMS1=(60*(60*T1.hour+T1.min)+T1.sec)+0.001*T1.ms;
-- if 0>dt then dt=0 end
if f==0 then
if 0>=dt then f=1 z[3]=f end
end
if f~=0 and HMS==HMS1 then
-- if 60>dt then
if 0>dt then
if -1>=dt then
local n1=math.floor(0-dt) dt=dt+n1 n=n+n1;
if n>100 then n=0; z[3]=0; dt=0; end
z[2]=n
end
end
-- Log:write(tostring(hms)..","..tostring(s)..",size="..tostring(size)..",HMS="..tostring(HMS)..",dt="..tostring(dt)..",n="..tostring(n).."\n"); Log:flush();
if f~=0 then
local dt1=dt; if 0>dt then dt=0 end count=count+1; count1=count1+1;
local m=math.floor(dt)+1;
if m==nil or sts[m]==nil then
Log:write(tostring(hms)..","..tostring(s)..",size="..tostring(size)..",HMS="..tostring(HMS)..",HMS1="..tostring(HMS1)..",dt="..tostring(dt1)..",n="..tostring(n)..",m="..tostring(m).."\n"); Log:flush();
end
-- if m and 99>m then
if sts[m] then sts[m]=sts[m]+1; else sts[m]=1 end
-- end
end
end
end
end
function OnInit(pfile)
local path = getScriptPath(); Log=io.open(path.."/test.log","w") --лог файл
end
Так как Вам лень запускать его на вашем демо сервере, то выкладываю последние результаты На печать выводится сделка, которая первая с данной задержкой. Время компьютера, код инструмента, size, время этой сделки, время сделки но номеру size, разница времен, автосмещение, индекс ячейки (запаздывание sec+1)
думал что ошибка в тесте, написал новый , но лучше не стало. в тесте надо установить смещение часового пояса и секунд
Код
local tmp={}
local ds={}
local ns=0;
local shH=1 --сдвиг часового пояса
local shS=10 -- сдвиг секунд
local count,count1=0,0; local sts={} for i=1,200 do sts[i]=0; end
function main()
while true do
while #tmp>0 do
local t=tmp[1]; table.sremove(tmp,1);
if count>=1000 then count=0;
local s=""; for i=1,60 do s=s..tostring(sts[i])..",";end
Log:write(tostring(ns)..":"..tostring(count1)..">"..s.."\n"); Log:flush();
end
end
sleep(1);
end
end
function OnParam(c,s)
local d=ds[c..s]
if d==nil then
d,err=CreateDataSource (c,s,INTERVAL_TICK);
if d then d:SetEmptyCallback(); ns=ns+1; ds[c..s]=d; end
else
table.sinsert(tmp,{1,c,s});
end
end
function OnAllTrade(t)
local c,s=t.class_code,t.sec_code; local d=ds[c..s];
if d then
local Ti=t.datetime; local HMS=(60*(60*Ti.hour+Ti.min)+Ti.sec);--+0.001*Ti.ms;
local D=os.date("*t"); local hms=60*(60*(D.hour-shH)+D.min)+D.sec-shS;
local dt= hms-HMS; local size=d:Size(); local T1=d:T(size);
local HMS1=(60*(60*T1.hour+T1.min)+T1.sec);--+0.001*T1.ms;
if HMS==HMS1 then
if 0>dt then dt=0 end
if 60>dt then
count=count+1; count1=count1+1; local m=math.floor(dt)+1; sts[m]=sts[m]+1;
end
end
end
end
function OnInit(pfile)
local path = getScriptPath(); Log=io.open(path.."/test.log","w") --лог файл
end
local tmp={}
local ds={}
local ns=0;
local count,count1=0,0; local sts={} for i=1,200 do sts[i]=0; end
function main()
while true do
-- nkevent.wait(event); --ждем события
while #tmp>0 do
local t=tmp[1]; table.sremove(tmp,1);
if count>=100 then count=0;
local s=""; for i=1,60 do s=s..tostring(sts[i])..",";end
Log:write(tostring(ns)..":"..tostring(count1)..">"..s.."\n"); Log:flush();
end
end
sleep(100);
end
end
function OnParam(c,s)
local d=ds[c..s]
if d==nil then
d,err=CreateDataSource (c,s,INTERVAL_TICK);
if d then ds[c..s]=d; d:SetEmptyCallback(); ns=ns+1; end
else
table.sinsert(tmp,{1,c,s});
end
end
function OnAllTrade(t)
local Ti=t.datetime; local HMS=(100*(100*Ti.hour+Ti.min)+Ti.sec)+0.001*Ti.ms;
local hms=string.sub(os.date(),12,19); hms=string.gsub(hms,':','')-10000;
local dt=hms-HMS; if 0>dt then dt=0 end
if 60>dt then
count=count+1; count1=count1+1; local m=math.floor(dt)+1; sts[m]=sts[m]+1;
end
end
function OnInit(pfile)
path = getScriptPath(); Log=io.open(path.."/test.log","w") --лог файл
end
результат помещается в лог файл test.log, который создается в каталоге , где размещается этот скрипт. в лог файл через каждые 100 обезличенных сделок записывается следующая строка:
77 - число инструментов 3554 - число обезличенных сделок далее количество сделок в интервале запаздывания с шагом 1 секунда 79 - в интервале запаздывания до 1 секунды 90 - в интервале запаздывания от 1 до 2 секунд 89 -в интервале запаздывания от 2 до 3 секунд
Назвать конкретную причину такого распределения в Вашей выборке без конкретных примеров и участия брокера не удастся. В данной ситуации замешано большое количество неопределённостей: эпизодические сетевые задержки, ситуативные задержки на сервере в расчете и обработке сделок, возможные задержки в обработке поступающей информации на Вашем ПК, задержки в трансляции данных из ТС на сервер QUIK и из сервера на терминал и т.д.
Для того, чтобы можно было анализировать большие задержки поступления обезличенных сделок необходимы конкретные примеры. Например зафиксировать конкретные номера сделок с временем их исполнения и временем получения их терминалом, далее приложить эти данные и архив терминала сделанный в момент проявления задержек к Вашему обращению в техническую поддержку Вашего брокера, в котором попросить помочь в выяснении причин таких задержек и в случае, если брокер не сможет помочь по данному вопросу, то инициировать его обращение к нам для совместного анализа данной ситуации.
примерно такое же можно наблюдать и на вашем демо сервере. относительно задержек в сети и на компьютере не логично. В сети задержка 30 мс, а на графике задержка десятки секунд Ядро процессора загружено примерно на 10% -------------- Возможно не знаете, но недавно я делал тест на скорость выставления снятие заявок на вашем демо сервере. Полагаю я нго либо положил либо очень нагрузил так как меня отключили. По тестам скорость выставления и снятия заявки без учета прохождения по сети составляет порядка 10-100 мкс. ------------------------- Если у Вас есть возможность, то сделайте подобный тест и покажите результат. -------------------------- Если покажете, что у вас задержка прихода обезличенной сделки через колбек onAllTrade в пределах разумного, то вопрос будет закрыт. -------------------- Я мог бы повторить Ваш тест, так как у сбербанка постоянно какие-то глюки. Например вчера пропал предыдущий торговый день и не вогсстановлися.
Ув, разработчики Просьба объяснить следующий феномен работы системы QUIK ----------------------- На реальном рынке вычисляю функцию распределения запаздывания времени прихода обезличенных сделок в терминал QUIK на моем компе с сервера брокера сбербанк. ---------------------- Алгоритм расчета следующий Вычисляем разницу текущего времени компа и времени обезличенной сделки и в добавляем 1 в ячейку массива с индексом равным разности. В результата по 24 000 обезличенных сделок получаем следующий график распределения запаздывания
Что получилось: 80% пришло с задержкой не более 1 секунды это при пинге до сервера 0.03 сек. 12% с задержкой от 1 до 2 секунд 8% с задержкой более 2 секунд 1% с задержкой 17 секунд 0.5% с задержкой 30 секунд --------------------- Что не так c сервером QUIK у брокера Сбербанк.
К тому же, я незнаю как работает вся эту луашная магия:
Цитата
function unrequire(m) package.loaded[m] = nil _G[m] = nil end
Я вижу тут зануление таблиц. Приводит ли это к выгрузке модулей - неизвестно.
Для этого не надо знать лушную магию . Достаточно знать Сишную и назначение функции DllMain. ---------------------------------- Но, боже упаси Вас, подумать что я Вас заставляю что-то изучать или проводить эксперименты. Не утруждайте себя. Пишите на форум жалобы. Время потратите столько-же, но зато не будете себя утруждать.
Alexander написал: Если имелось ввиду заменить MessageBox на MessageBoxA, так я так уже пробовал. По умолчанию да юникод в свойствах проекта и функция из макроса MessageBox подставляется MessageBoxW, я это знаю. Замена ничего не меняет абсолютно. MessageBox, что один, что другой вызываются из оконной процедуры у меня.
какой IDE используете? Могу посоветовать для написания dll для Lua(QUIK) использовать Pelles C. Очень хороший, простой в настройках, быстрый по сравнению с Visual Studio .
Alexander написал: Попробую поднять данную тему вновь. Вобщем всё что выше написано - не работает Библиотека не выгружается!. Библиотека на C++. Выше писали, что типа если на чистом C++ то выгружается нормально. Не выгружается. Есть ли ещё какой способ выгрузить свою же DLL, которую Lua выгружать почему-то не хочет. Странное вообще какое-то поведение Lua. Скрипт отработал, библиотека - осталась. Функций в Lua для выгрузки не нашёл, что тоже довольно таки странно. Загружать значит можно, выгружать нет. Приходится постоянно перезагружать QUIK, чтобы удалить файл DLL, поскольку система не даёт его удалить, пока библиотека используется Lua. А удалять файл надо, чтобы после перекомпиляции DLL, новый DLL-файл записать на место того, что надо удалить. Это сильно напрягает поскольку сам QUIK грузится не быстро. Сталкивался кто с таким? Как ещё можно решить пролему? Ведь библиотека же чисто моя, зачем она вообще удерживается Lua - не понятно. Закончился скрипт без ошибок - освободи, но нет. Уж не знаю как решить, думаю уже как-то искать ID библиотеки, ну или там хэндл какой и выгружать отдельно программой через API винды.
А причем здесь скрипт? Скрипт - это даже не программа, а все лишь байткод для луа машины. Вспомните, когда dll выгружается.
У меня есть dll на основе API C for Lua Результат будет такой же. Просто сделайте как я Вам написал и увидите результат. Либо измените опции в компиляторе
Alexander написал: nikolz , у Вас что за функции nkcf.defF и rfs ? Какой их код, что они вызывают API винды? И Вы их вызываете прямо из скрипта, а я API прямо из DLL на C.
Это мой аналог библиотеки FFI,, Эти функции позволяют вызывать в луа функции из dll, у которых интерфейс C. любые функции из системных библиотек и сторонних dll нет надобности городить что-то на API C for Lua. Я об это на форуме уже писал. ------------------------- правда я встроил LuaJIT в QUIK и могу использовать и FFI. Тоже об этом писал на форуме.
Alexander написал: Аааа, я ещё что-то сразу то не приметил. nikolz , Вы на скрине показываете окно сообщений самого квика. Мои скрипты в это окно пишут по-русски нормально. Я писал не про это окно. У меня DLL. Скрипт вызывает её функции. Эти функции например вызывают MessageBox виндовую для вызова окна сообщенй винды с русским текстом. И вот оно то пишет не по-русски. Вот в этом проблема. А с простым message в скрипте проблем нет - сохраняю с русскими сообщениями как ANSI и проблем нет. Вобщем сама винда перестаёт по-русски писать в своём же сообщении, хотя если вызывать не из библиотеки DLL под QUIK, а просто из программы под винду, то пишет по-русски как положено. И ещё. Из DLL в этом окне только само сообщение абракадаброй выводится, а вот кнопки "Да", "Нет" - они нормально по-русски подписаны.
У Вас по умолчанию подставляется MessageBoxW а надо прописать явно MessageBoxA ---------------------- Вот ваш вариант с MessageBoxW
Alexander написал: Аааа, я ещё что-то сразу то не приметил. nikolz , Вы на скрине показываете окно сообщений самого квика. Мои скрипты в это окно пишут по-русски нормально. Я писал не про это окно. У меня DLL. Скрипт вызывает её функции. Эти функции например вызывают MessageBox виндовую для вызова окна сообщенй винды с русским текстом. И вот оно то пишет не по-русски. Вот в этом проблема. А с простым message в скрипте проблем нет - сохраняю с русскими сообщениями как ANSI и проблем нет. Вобщем сама винда перестаёт по-русски писать в своём же сообщении, хотя если вызывать не из библиотеки DLL под QUIK, а просто из программы под винду, то пишет по-русски как положено. И ещё. Из DLL в этом окне только само сообщение абракадаброй выводится, а вот кнопки "Да", "Нет" - они нормально по-русски подписаны.
Net error "Удалённый хост принудительно разорвал существующее подключение", Такая ошибка ,как правило, возникает ближе к концу торгов.Подключиться после этой ошибки невозможно в этот день. На пк установлено ещё 2 квика,они при этом работают нормально. Подключение через USB-модем
NPlay написал: Причем если подключаешься по wi-fi (Intel® Wi-Fi 6 AX200 160MHz)он встроен в материнскую плату а сетевую карту отключаешь то никаких проблем, тут же логинится и работает.
На самом деле Вы все уже рассказали и что делать примерно понятно. Но полагаю, что знаете сами. Успехов в творчестве.
Net error "Удалённый хост принудительно разорвал существующее подключение", Такая ошибка ,как правило, возникает ближе к концу торгов.Подключиться после этой ошибки невозможно в этот день. На пк установлено ещё 2 квика,они при этом работают нормально. Подключение через USB-модем
NPlay написал: Автор тебе удалось решить проблему? У меня такие же симптомы при логине в квик происходит разрыв локального соединения и сеть отключается, брандмаузер, антивирь, все отрублено, папка квик в исключениях. Проблема возникает исключительно при коннекте с квиком! сетевая карта I-225v мат плата asus 550b-e gaming. Мучаюсь уже несколько месяцев, так и не смог победить. 1 из 10-15 раз все таки удается залогинится на сервер квика, но при этом приходится включать/выключать сетевое подключение.
сделайте пинг до сервера брокера (в квике есть IP адрес сервера) Если серверов несколько то попробуйте подключится к другому.
да нет никаких потерь, вообще, никаких, проблема исключительно при коннекте квика 10.0.1.18 на сервер брокера( рабочий у них только один (открытие). ни переустановка квика, ни переустановка винды(10) не помогает, все обновления, драйвера на сетевую свежие.
спасибо что почистить кулер не советуете, а то рукалицо.
у вас болезнь другая, поэтому кулер чистить бесполезно
Net error "Удалённый хост принудительно разорвал существующее подключение", Такая ошибка ,как правило, возникает ближе к концу торгов.Подключиться после этой ошибки невозможно в этот день. На пк установлено ещё 2 квика,они при этом работают нормально. Подключение через USB-модем
NPlay написал: Автор тебе удалось решить проблему? У меня такие же симптомы при логине в квик происходит разрыв локального соединения и сеть отключается, брандмаузер, антивирь, все отрублено, папка квик в исключениях. Проблема возникает исключительно при коннекте с квиком! сетевая карта I-225v мат плата asus 550b-e gaming. Мучаюсь уже несколько месяцев, так и не смог победить. 1 из 10-15 раз все таки удается залогинится на сервер квика, но при этом приходится включать/выключать сетевое подключение.
сделайте пинг до сервера брокера (в квике есть IP адрес сервера) Если серверов несколько то попробуйте подключится к другому.
Alexander написал: За столько времени так никто и не ответил. Поддержка может хоть что-нибудь подсказать в решении проблемы? Мой вывод : в контексте толи потока QUIK, толь в Lua, локаль меняется с ru-Ru на локаль C, а в ней видимо русских букв вообще нету. Поэтому хоть что ты пиши, хоть кодируй текст - всё равно толку не будет, так как его попросту в чарактер сет(кодировке) нет как такового. Но почему не получается сначала сохранить локаль C, потом установить родную локаль, вывести текст, потом локаь C вернуть обратно - не пойму.
никогда не было проблемы с русскими буквами. Полагаю кодировка, которая в системе установлена.