Возможно ли в OnTransReply получение номера снимаемой/передвигаемой заявки?, при использовании Move/Kill order
Пользователь
Сообщений: Регистрация: 27.01.2017
16.11.2020 18:11:44
Чтобы снять ордер надо знать его номер, а если он известен, то зачем его получать в колбеке?
Изменения в работе с колбеками LUA в новой версии
Пользователь
Сообщений: Регистрация: 27.01.2017
06.11.2020 15:03:35
А с чего вообще что-то должно поменяться для "наблюдателя" скрипта? С его точки зрения каким был колбек таким и остался. На то он и колбек, назание само за себя говорит.
Не думаю что пойдут на изменение синтаксиса. Я бы больше ожидал стабильности и предсказуемости в вызовах. Сейчас только несколько колбеков типа подключения-отключения-ответ транзакции можно использовать. Остальные не вызывают доверия и надежней баз них. А то когда у тебя колблек от событий прошедших часы назад прилетает после перезапуска терминала, то проще не смотреть на них.
Обсудим диалог на Lua?
Пользователь
Сообщений: Регистрация: 27.01.2017
05.11.2020 20:13:03
Здесь я с Владимиром согласен, не очень понятно зачем вносить лишние сущности в виде сторонних библиотек, если почти все что надо от скрипта можно сделать на qlua. Да, нельзя показать картинки, не очень удобно выводить многострочный текст и т.д., но бантики не имеют отношения к тому что надо от интерфейса скрипта.
Писали же как-то программы раньше. Даже некое подобие 3-х мерного изображения выводили до Open GL. И ничего, научная работа велась.
Если уж интерфейс такой сложный, что он должен определять поведение скрипта, то проще написать весь скрипт на плюсах (QScalp), зачем мучить LUA, да еще VCLua на турбо паскале, которое притянет за собой свои зависимости и проблемы синхронизации. Не говоря уже про то, что она, мягко говоря, устарела.
Обсудим диалог на Lua?
Пользователь
Сообщений: Регистрация: 27.01.2017
05.11.2020 09:49:11
Владимир, а в чем, собственно, проблема?
И команды и переключатели, и поля ввода, горячие клавиши прекрасно делаются на qlua. Просто к таблице надо подойти как к объекту, наполнив его методами, обратными вызовами. Я бы даже сказал, что надо написать свой DSL. Тогда, вызывая конструктор окна с настройками, получим уже готовый объект. В частности, у меня окно рисуется через таблицу настроек, все остальное уже заложено в объект. Надо добавить переключатель или что-то другое - одна строка таблице настроек.
Как к этому подойти - ну явно не надо писать простыню в main. Придется использовать очереди событий, сообщений и др. Также не советую использовать номера колонок, строк как идентификатор ячейки - это затрудняет модификацию окна. Часто просят переставить местами что-то. Это не должно приводить к переписыванию всего кода. Надо просто в одном месте поменять описание поля (колонки) таблицы.
Добавление Индикаторов.
Пользователь
Сообщений: Регистрация: 27.01.2017
03.11.2020 19:53:14
Ну код индикатора не оптимален. Это влияет на производительность, особенно если запущено на склейке графика, с очень большим количеством баров.
Добавление Индикаторов.
Пользователь
Сообщений: Регистрация: 27.01.2017
03.11.2020 18:58:50
Вот исправленное. Прогнал через линтер, помимо кавычек еще вместо минус было тире. Явно хранили текст в Word или в чем-то подобном.
Код
Settings = {
Name = "*StohRSI",
round = "off",
Period = 5,
Per_K = 9,
PeriodSO = 5,
Shift = 3,
VType = "Close", --Open, High, Low, Close, Volume, Median, Typical, Weighted, Difference
line = {
{Name = "RSI", Type = TYPE_LINE, Color = RGB(255, 255, 128)},
{Name = "SO", Type = TYPE_LINE, Color = RGB(255, 0, 0)},
{Name = "Sign", Type = TYPE_LINE, Color = RGB(128, 255, 128)},
{Name = "line 20", Type = TYPE_LINE, Color = RGB(0, 128, 255)},
{Name = "line 80", Type = TYPE_LINE, Color = RGB(0, 128, 255)}
}
}
function Init()
func = RSI()
return #Settings.line
end
function OnCalculate(Index)
if not CandleExist(Index) then
return nil
end
return func(Index, Settings)
end
function RSI() --Relative Strength I("RSI")
local Up = {}
local Down = {}
local val_Up = {}
local val_Down = {}
local K_MA1=MA()
local K_MA2=MA()
local D_MA=MA()
local proSO={}
local Out = {}
return function (I, Fsettings, ds)
local Fsettings=(Fsettings or {})
local P = (Fsettings.Period or 14)
local PK = (Fsettings.Per_K or 5)
local PerSO = (Fsettings.PeriodSO or 5)
local S = (Fsettings.Shift or 3)
local PD = (Fsettings.Period_D or 3)
local VT = (Fsettings.VType or "Close")
local R = (Fsettings.round or "off")
local MD = (Fsettings.Metod_D or "SMA")
local M = (Fsettings.Metod or "SMA")
if I <=PerSO then
Up[I] = 0
Down[I] = 0
end
if I>PerSO then
local Val = Value(I,"T",ds)
local ValPrev = Value(I-1,VT,ds)
if ValPrev < Val then
Up[I] = Val - ValPrev
else
Up[I] = 0
end
if ValPrev > Val then
Down[I] = ValPrev - Val
else
Down[I] = 0
end
if (I == P) or (I == P+1) then
local sumU = 0
local sumD = 0
for i = I-P+1, I do
sumU = sumU + Up[i]
sumD = sumD + Down[i]
end
val_Up[I] = sumU/P
val_Down[I] = sumD/P
end
if I > P+1 then
val_Up[I] = (val_Up[I-1] * (P-1) + Up[I]) / P
val_Down[I] = (val_Down[I-1] * (P-1) + Down[I]) / P
Out[I] = 100 / (1 + (val_Down[I] / val_Up[I]))
end
end
if I > PK*2 then
RsiOut=D_MA(I,{Period=PK, Metod = M, VType="Any", round=R}, Out)
end
_,_,proSO[I]= MaxMin(I,5,ds,3)
if I>=(PK+3-1) then
SignSO=D_MA(I, {Period=3, Metod = "SMA", VType="Any", round="off"}, proSO)
end
return rounding(RsiOut, 4),rounding(proSO[I], 4),rounding(SignSO, 4),rounding(Out[I], 4)
end
end
-------------------------------------------------------
-------------------------------------------------------
function MA() --Moving Average ("MA")
local t_SMA = F_SMA()
local t_EMA = F_EMA()
return function(I, Fsettings, ds)
local Out = nil
local Fsettings=(Fsettings or {})
local P = (Fsettings.Period or 9)
local M = (Fsettings.Metod or "EMA")
local VT = (Fsettings.VType or "Close")
local R = (Fsettings.round or "off")
if M == "SMA" then
Out = t_SMA(I, P, VT, ds, R)
elseif M == "EMA" then
Out = t_EMA(I, P, VT, ds, R)
else
Out = nil
end
return rounding(Out, R)
end
end
------------------------------------------------------
function MaxMin(ind,Pk,ds,Sk)
if ind < Pk+Sk then
return nil
else
local suCM=0
local suMM=0
for i = ind - Sk+1, ind do
MAX = Value(i-Pk+1,"High",ds)
MIN = Value(i-Pk+1,"Low",ds)
for k = 0, Pk-1 do
MAX=math.max(MAX,Value(i-k,"High",ds))
MIN=math.min(MIN,Value(i-k,"Low",ds))
end
--message('тран:'..OutWR,1)
suCM=suCM+(Value(i, "Close", ds)-MIN)
suMM=suMM+(MAX-MIN)
end
local TenKu=(MAX+MIN)/2
local OutWR=100*(Value(ind,"Close", ds)-MIN)/(MAX-MIN)
local proKol =100*suCM/suMM
local wpr = ((MAX - Value(ind,"Close", ds)) / (MAX - MIN)) * (-100)
return rounding(TenKu, 6),rounding(OutWR, 6),rounding(proKol, 6)
end
end
------------------------------------------------------------------
function F_SMA()
return function (I, Period, VType, ds, R)
local Out = nil
if I >= Period then
local sum = 0
for i = I-Period+1, I do
sum = sum +Value(i, VType, ds)
end
Out = sum/Period
end
return rounding(Out,R)
end
end
---------------------------------------------------------
function F_EMA()
local EMA_TMP={}
return function(I, Period, VType, ds, R)
local Out = nil
if I == 1 then
EMA_TMP[I]=rounding(Value(I, VType, ds),R)
else
EMA_TMP[I]=rounding((EMA_TMP[I-1]*(Period-1)+2*Value(I, VType, ds)) / (Period+1),R)
end
if I >= Period then
Out = EMA_TMP[I]
end
return rounding(Out,R)
end
end
-------------------------------------------------------
function Value(I,VType,ds)
local Out = nil
VType=(VType and string.upper(string.sub(VType,1,1))) or "A"
if VType == "O" then --Open
Out = (O and O(I)) or (ds and ds:O(I))
elseif VType == "H" then --High
Out = (H and H(I)) or (ds and ds:H(I))
elseif VType == "L" then --Low
Out = (L and L(I)) or (ds and ds:L(I))
elseif VType == "C" then --Close
Out = (C and C(I)) or (ds and ds:C(I))
elseif VType == "V" then --Volume
Out = (V and V(I)) or (ds and ds:V(I))
elseif VType == "M" then --Median
Out = ((Value(I,"H",ds) + Value(I,"L",ds)) / 2)
elseif VType == "T" then --Typical
Out = ((Value(I,"M",ds) * 2 + Value(I,"C",ds))/3)
elseif VType == "W" then --Weighted
Out = ((Value(I,"T",ds) * 3 + Value(I,"O",ds))/4)
elseif VType == "D" then --Difference
Out = (Value(I,"H",ds) - Value(I,"L",ds))
elseif VType == "A" then --Any
if ds then Out = ds[I] else Out = nil end
end
return Out
end
function rounding(num, round)
if round and string.upper(round)== "ON" then round=0 end
if num and tonumber(round) then
local mult = 10^round
if num >= 0 then return math.floor(num * mult + 0.5) / mult
else return math.ceil(num * mult - 0.5) / mult end
else return num end
end
Одновременная работа двух Торговых систем с одним инструментом, подкиньте идей
Пользователь
Сообщений: Регистрация: 27.01.2017
28.10.2020 09:42:24
Владимир, это же написано в документации к расширению языка от разработчика, документ Использование Lua в Рабочем месте QUIK Простая схема передачи данных через очередь из колбека в дополнительный поток скрипта.
Одновременная работа двух Торговых систем с одним инструментом, подкиньте идей
Пользователь
Сообщений: Регистрация: 27.01.2017
27.10.2020 19:55:31
Хранить надо не потому что инструменты или алгоритмы разные, а потому, что при рестарте скрипта (а это нормальное, очень частое явление) надо восстановить и актуализировать свое состояние. Это просто некий state. Выключите скрипт (или Квик упал) - потеряете.
Одновременная работа двух Торговых систем с одним инструментом, подкиньте идей
Пользователь
Сообщений: Регистрация: 27.01.2017
27.10.2020 19:10:37
Да, такое просят иногда сделать. К примеру, один алгоритм торгует один тайм-фрейм, другой - второй. На длительном периоде работы, фин рез "как-бы" сходится. Такая задача обязательно требует хранения текущего состояния каждого алгоритма, т.к. чтение данных таблиц Квика уже не даст результат. Впрочем, это стоит итак делать. Также не лишним будет помечать сделки комментарием, чтобы понимать, что это сделка этого алгоритма.
Такая задача имеет и проблемы. Т.к. позицию мы можем получить только из сделок, то важно, чтобы не было перерывов в работе, т.к. Квик удаляет сделки на следующие сутки.
Код
т.е. придерживаться правила - один скрипт - один инструмент?
Это никак не соотносится с вопросом. Ведь можно сделать один скрипт на 100 разных инструментов, торгующих одним и тем же алгоритмом, или разными.
Предложение к разработчикам
Пользователь
Сообщений: Регистрация: 27.01.2017
27.10.2020 13:22:55
Вы, как обычно, не изучив язык, начинаете осуждать. Про goto во всех руководствах по языку сказано, что он не работает в блоках (намек - есть область видимости переменных). ФУНКЦИОНАЛЬНОСТЬ программы не влияет на сложность. Кода больше, да. А вот сложность алгоритма - это вопрос методики, либо сам алгоритм, как таковой сложный.
Не умеете без goto, пишите с ним. Но я уже забыл когда последний раз его использовал, лет 25 назад возможно.
внутрь блока if, while - серьезно?
На демо сервере junior quik не передается таблица firms при смене пользователя
Пользователь
Сообщений: Регистрация: 27.01.2017
26.10.2020 15:37:55
Ну да, я поэтому и спросил про другой способ. Проверим как это будет жить.
В целом, ответы типовые - все к брокеру. Может, все же, мы вернемся к вопросу старта Квика и к понятию "Я все с сервера загрузил после очистки таблиц". Тогда и вопросы все отпадут. А то ведь у своего брокера я могу еще спросить, а чужого уже никак.
isConnected и пара неприятных моментов
Пользователь
Сообщений: Регистрация: 27.01.2017
25.10.2020 09:58:11
Все же волновая функция - это про вероятность. У нас же есть пакеты данных и, теоретически, каждый пакет обладает информацией, что он несет. Как накладная на груз. Поэтому мы могли бы понимать, что последнее, что мы получили - это такие-то данные. Либо мы просто ждали бы пакет с таким типом данных, фильтруя другие. Да, мы не знаем последние ли это данные, справедливо. Но и понятие "последние" не применимо здесь. я бы назвал их текущие. Но они бы были не обезличенные. Также пакет мог бы нести данные о смысле этих данных - справочник, очистка таблицы, заполнение таблицы, информация о цене сделки и т.д., и, скорее всего, несет. Часть этого есть в колбеках, но явно недостаточная.
А вот с точки зрения времени - да, у нас полная неопределенность. Но, как мне кажется, обладай бы мы полной информацией о смысле полученных данных, ошибках сервера (читай больше колбеков) в данный момент - это было бы не столь критично.
В соседней ветке написал про открытие рынка с утра, когда вдруг позиция становится 0, а тут же опять корректная. Т.е. явно идет либо очистка данных (был вызван CleanUp), чтобы далее получить новые, либо некий пакет данных, содержащий неполную, либо "технологическую" информацию, а скрипт в этот момент времени измерил состояние. Я к сожалению не выводил в лог полную таблицу future_client_holding, так бы было ясно что-то: пустая она, неполная и т.д.
Предложение к разработчикам
Пользователь
Сообщений: Регистрация: 27.01.2017
24.10.2020 10:14:22
А зачем "рекомендованное", если есть книга от автора языка. Купите или "купите" уже книгу Роберту Иерузалимски "Программирование на языке lua", если уж на сайте языка никак не получается.
В ней есть все, чтобы начать писать на lua. А вот даже примеры решения заданий из книги
На демо сервере junior quik не передается таблица firms при смене пользователя
Пользователь
Сообщений: Регистрация: 27.01.2017
23.10.2020 17:38:40
В продолжении вопрос: Если у клиента подключен счет для срочной секции (в том числе единый счет) можно ли утверждать, что таблица futures_client_limits всегда заполнена (по аналогии с money_limits для фондовой секции)?
На демо сервере junior quik не передается таблица firms при смене пользователя
Пользователь
Сообщений: Регистрация: 27.01.2017
23.10.2020 15:13:20
Подниму вопрос. Терминал работает круглые сутки, не выключаясь. У одного брокера регулярно утром происходит какая-то...
После OnConnected проверяем позицию по инструменту - она 0. И через несколько секунд уже корректная.
Раз уж мы поняли, что актуальность данных мы не можем получить:
Я вижу колбек OnCleanUp (судя по описанию и времени это смена сессии), но только потом OnConnected. Как-то странно для смены сессии. По какому признаку мне понять, что пока рано идти и смотреть позицию в таблице futures_client_holding?
Кроме идеи дождаться первого OnFuturesClientHolding в голову ничего не приходит.
debugview - где его взять и как им пользоваться?
Пользователь
Сообщений: Регистрация: 27.01.2017
23.10.2020 09:11:11
Отладка - это хорошо. Но писать тесты на свой код лучше и надежней. Там где без отладочной информации не обойтись методика "print debug" помогает (я предпочитаю лог файлы). Если Вы пишите скрипты для себя, то, конечно, можете и отлаживать, а если для внешних клиентов, то как Вы будете у них отлаживать?
А если уже сравнивать с MT, то там отладка идет на исторических данных. Но и странно было бы ожидать отладку в реальном времени. Остановите поток данных? Я не говорю, что если бы отладка была в Квике, то это не надо, но ее ценность не так велика. Плюс никто не мешает написать wrapper функций Квика и подкидывать данные из файлов для эмуляции потока, запуская на чистом lua. Тогда тесты станут еще более предсказуемыми.
Как узнать текущие чистые позиции?
Пользователь
Сообщений: Регистрация: 27.01.2017
23.10.2020 08:59:00
Не проверять в клиринг. Т.е. надо проверить статус сессии и контролировать позицию только в торговое время. Плюс, если Вы делаете это из колбека OnFuturesClientHolding, то он дергается по любому поводу, связанному с изменением в таблице (вар. маржа и т.д.). А позиция та же самая. В клиринг особенно. Т.е. это не самый удачный колбек, в плане получения только позиции.
Предложение к разработчикам
Пользователь
Сообщений: Регистрация: 27.01.2017
21.10.2020 13:33:38
Не ясно только одно: что мешает прямо сейчас писать на с/с++ используя lua-api?
Вот, для примера, неплохая библиотека обертка методов Квика - Пишите на здоровье.
Как все это время другим удается писать на чистом lua, загадка, наверно. Надеюсь разработчики даже не будут рассматривать это пожелание.
Функции onInit, onStop, onClose
Пользователь
Сообщений: Регистрация: 27.01.2017
16.10.2020 10:50:45
Странно, как мы все эти годы пишем на языке. И на других языках. И как-то все пишется. И строки из таблиц удаляются. Да, есть проблемы с переходом на новую версию, но они не столь критичны.
Может, все же, надо изучить язык прежде чем мысли озвучивать, да и другим советовать.
Владимир, к сведению, если хотите чтобы в таблице были только числовые индексы (и даже целочисленные), то это не сложно сделать.
Вот несложный конструктор:
Код
local typedT = function(key_type, value_type, allow_nil)
local val_t = {}
local proxy = {}
if allow_nil == nil then allow_nil = true end
local check_type = function(value, c_type)
if (c_type or '') == '' then return true end
if (('integer|float'):find(c_type)) then
return math.type(value) == c_type
end
return type(value) == c_type
end
local mt = {
__index = val_t,
__newindex = function (_, k, v)
if not check_type(k, key_type) then
error("attempt to index with "..(type(k) == 'number' and math.type(k) or type(k)).. " type", 2)
end
if (not allow_nil and v == nil) or (v ~= nil and not check_type(v, value_type)) then
error("attempt to set a value "..(type(v) == 'number' and math.type(v) or type(v)).. " type", 2)
end
val_t[k] = v
end
}
setmetatable(proxy, mt)
return proxy
end
local t = typedT('number')
Также можно сделать только readonly объекты, можно сделать и объекты заданного типа, просто с ними придется работать не как с переменными, а через getter и setter. Было бы желание.
Странная дата сервера
Пользователь
Сообщений: Регистрация: 27.01.2017
15.10.2020 19:09:21
Что это за формат времени в поле Дата торгов? Как, спрашивается, понять, что здесь что?
Функции onInit, onStop, onClose
Пользователь
Сообщений: Регистрация: 27.01.2017
15.10.2020 15:25:33
А спецификацию языка недосуг прочитать:
Цитата
Приведения типов
Lua обеспечивает автоматическое преобразование между числами и строками во время выполнения программ. Любая числовая операция, примененная к строке, пытается преобразовать эту строку в число:
Lua применяет подобные преобразования не только в арифметических операциях, но и в других местах, где ожидается число, таких как аргумент math.sin. Верно и обратное — каждый раз, когда Lua находит число там, где ожидает строку, он преобразует это число в строку:
print(10 .. 20) --> 1020
(Операция .. служит в Lua для конкатенации строк. Когда вы записываете ее сразу после числа, вы должны отделить их друг от друга при помощи пробела; иначе Lua решит, что первая точка — это десятичная точка числа.)
Сегодня мы не уверены, что эти автоматические приведения типов были хорошей идеей в дизайне Lua. Как правило, лучше на них не рассчитывать. Они удобны в некоторых местах; но добавляют сложности как языку, так и программам, которые их используют. В конце концов, строки и числа — это разные вещи, несмотря на все эти преобразования. Сравнение вроде 10="10" дает в результате false, поскольку 10 — это число, а "10" — это строка.
Если вам нужно явно преобразовать строку в число, то вы можете воспользоваться функцией tonumber, которая возвращает nil, если строка не является правильным числом Lua:
line = io.read() -- читает строку n = tonumber(line) -- пытается преобразовать ее в число if n == nil then error(line .. " is not a valid number") else print(n*2) end
Для преобразования числа в строку вы можете использовать функцию tostring или конкатенировать число с пустой строкой: print(tostring(10) == "10") --> true print(10 .. "" == "10") --> true Эти преобразования всегда работают.
Отрывок из книги: Роберту Иерузалимски. «Программирование на языке Lua».
Возможно Вы привыкли, что компилятор вам дает безопасность типов. Но в lua это не так.
Функции onInit, onStop, onClose
Пользователь
Сообщений: Регистрация: 27.01.2017
15.10.2020 13:00:44
Ну и какой тип у a[i][1][1] Вы через message не увидите. Добавьте в вывод хотя бы message(i..": type(a[i][1][1]) "..type(a[i][1][1]))
Функции onInit, onStop, onClose
Пользователь
Сообщений: Регистрация: 27.01.2017
15.10.2020 12:48:08
Я вам говорю не про то, что надо тип индекса менять, приведя его к числу. А про то, что лучше складывать строки со строками, хоть lua и динамический язык. А то что индекс 2 и индекс "2" - это разные вещи, это уже вопрос дизайна. Хотите использовать нечитаемые конструкции типа a[b[1][c[2]]] - пожалуйста.
Функции onInit, onStop, onClose
Пользователь
Сообщений: Регистрация: 27.01.2017
15.10.2020 12:33:09
Возьмите за правило, что при сложении строк надо приводить значения к типу строка. lua умеет динамически преобразовать выражение вид: "a"..5 Но не умеет такое: "a"..nil Зато сможет так: "a"..tostring(nil)
Если у Вас в SP[a[i][1][1]] ничего нет, т.е. nil, то и будет ошибка.
get candle
Пользователь
Сообщений: Регистрация: 27.01.2017
15.10.2020 11:53:37
Кстати, такое поведение возникает и при заказе данных через CreateDataSource. Новый индекс бара уже есть, а время не заполнено. В результате попытка представить время через os.date дает ошибку "time result cannot be represented in this installation". Приходится добавлять проверки.
Более быстрый способ, all_trades
Пользователь
Сообщений: Регистрация: 27.01.2017
13.10.2020 15:00:33
Так, естественно, надо всегда запоминать последний прочитанный индекс. Какой смысл читать повторно, если один раз уже прочитал.
Функции onInit, onStop, onClose
Пользователь
Сообщений: Регистрация: 27.01.2017
13.10.2020 12:03:48
Видимо уже ничего... Смените инструмент на тот, по которому у Вас есть поток данных, раз SRZ0 нет. Но Вам уже разработчики ответили, так что просто добавьте параметры при вызове.
Функции onInit, onStop, onClose
Пользователь
Сообщений: Регистрация: 27.01.2017
13.10.2020 11:46:45
Ну вот Вам простой пример. Для одной ячейки функция вызывается со всеми аргументами, для другой нет
Код
local sec_code = 'SRZ0'
local class_code = 'SPBFUT'
local sleep = _G.sleep
local isRun = true
local t_id = nil
local SeaGreen = _G.RGB(193, 255, 193)
local RosyBrown = _G.RGB(255, 193, 193)
local getParamEx = _G.getParamEx
local GetCell = _G.GetCell
local SetCell = _G.SetCell
local SetColor = _G.SetColor
local ds
local def_c = _G.QTABLE_DEFAULT_COLOR
function _G.OnParam(class, sec)
if isRun and t_id and sec == sec_code and class == class_code then
local last_price = tonumber((getParamEx(class_code, sec_code, 'LAST') or {}).param_value) or 0
local last_vol = tonumber((getParamEx(class_code, sec_code, 'VALTODAY') or {}).param_value) or 0
local lp = GetCell(t_id, 1, 0).value or last_price
SetCell(t_id, 1, 1, tostring(last_vol), last_vol)
SetCell(t_id, 1, 0, tostring(last_price), last_price)
if lp < last_price then
SetColor(t_id, 1, 0, SeaGreen, def_c, SeaGreen, def_c)
SetColor(t_id, 1, 1, SeaGreen, def_c)
elseif lp > last_price then
SetColor(t_id, 1, 0, RosyBrown, def_c, RosyBrown, def_c)
SetColor(t_id, 1, 1, RosyBrown, def_c)
end
end
end
local function CreateTable()
t_id = _G.AllocTable()
_G.AddColumn(t_id, 0, "price", true, _G.QTABLE_DOUBLE_TYPE, 15)
_G.AddColumn(t_id, 1, "vol", true, _G.QTABLE_DOUBLE_TYPE, 15)
_G.CreateWindow(t_id)
_G.SetWindowPos(t_id, 90, 120, 270, 100)
_G.InsertRow(t_id, 1)
end
local function event_callback(_, msg)
if (msg == _G.QTABLE_CLOSE) then
isRun = false
end
end
function _G.OnInit()
CreateTable()
_G.SetTableNotificationCallback(t_id, event_callback)
end
function _G.main()
ds = _G.CreateDataSource(class_code, sec_code, 1)
isRun = ds ~= nil
if ds then
ds:SetEmptyCallback()
end
while isRun and ds do
sleep(500)
end
end
function _G.OnStop()
isRun = false
ds:Close()
ds = nil
if t_id and not _G.IsWindowClosed(t_id) then
_G.DestroyTable(t_id)
end
end
Функции onInit, onStop, onClose
Пользователь
Сообщений: Регистрация: 27.01.2017
13.10.2020 11:17:43
SetColor (iT, 1, 2, 255, 0)
Вы типы параметров этой функции в документации смотрели? 255 - это не цвет. Используйте либо функцию RGB, либо число hue цвета. Плюс надо не забывать передавать цвета выделеннной ячейки.
Более быстрый способ, all_trades
Пользователь
Сообщений: Регистрация: 27.01.2017
13.10.2020 11:11:15
Ну вот Вам пример.Их уже столько на просторах:
Код
---@param class_code string
---@param sec_code string
local function FilterTableLine(class_code, sec_code)
return class_code == Params.CLASS_CODE and
sec_code == Params.SEC_CODE
end
local t1 = SearchItems("all_trades", 0, getNumberOf("all_trades")-1, FilterTableLine, 'class_code,sec_code')
if t1 then
for i = 1, #t1 do
local trade = getItem("all_trades", t1[i])
if trade then
--- Сделать что-то
end
end
end
Более быстрый способ, all_trades
Пользователь
Сообщений: Регистрация: 27.01.2017
12.10.2020 18:51:14
Чтобы что-то ответить надо смотреть в исходники этой библиотеки. Не факт, что она поддерживает все глобальное окружение qlua.
Получение значения индикатора не открывая данных графика
Пользователь
Сообщений: Регистрация: 27.01.2017
12.10.2020 18:46:55
Нет. Так делать нельзя. При этом Вы опять пытаетесь совместить CreateDataSource и getCandlesByIndex. Эти функции предназначены для разных целей.
Получение значения индикатора не открывая данных графика
Пользователь
Сообщений: Регистрация: 27.01.2017
12.10.2020 12:01:41
Функция CreateDataSource заказывает данные баров, не данные индикатора по ним. Его же надо рассчитать. А кто его рассчитает, если график с индикатором не открыт. Если не хотите считать индикатор, то только считывать его с графика, который должен быть открыт. С другой стороны, MACD - это просто две скользящих. Что его считать...
Более быстрый способ, all_trades
Пользователь
Сообщений: Регистрация: 27.01.2017
12.10.2020 11:54:58
Используйте функцию SearchItems, чтобы не получать данные по каждой строке. Это даст уже фильтрованный массив индексов строк по нужному инструменту.
Далее, не надо использовать table.insert. Если необходимо просто увеличивать массив, то быстрее будет сделать как t[#t+1] = value.
Так Вы просто добавляете в конец массива новый элемент.
Кто как решил вопрос уведомления о сделках?
Пользователь
Сообщений: Регистрация: 27.01.2017
10.10.2020 17:00:20
Передача данных быстрая, да. А вот подключение...
Вот чистый lua, библиотека socket, никакого ssl, никакого Квика.
clock 0.007 Attempting connection to host 'localhost' and port 8005... clock 2.06 Connected! clock 2.06 strin = test clock 2.06 End
Не было желания постоянно держать открытое соединение.
Предложение к разработчикам
Пользователь
Сообщений: Регистрация: 27.01.2017
10.10.2020 09:59:51
Те, кто совершают такие сделки, да и большинство других "денег" не пользуются терминалом Квик. Да и зачем, если можно встать в стойку у ядра биржи.
Для всех есть регламент подачи заявок. Там и ограничения прописаны. Хочешь много - плати. И платят.
Как раз физ. лица часто просят добавить задержки в скрипты, чтобы их алгоритм не пытался бороться с заведомо более быстрыми алгоритмами, иначе приходит счет за чрезмерную активность.
Предложение к разработчикам
Пользователь
Сообщений: Регистрация: 27.01.2017
09.10.2020 20:14:41
Владимир, Вас опять куда-то в сторону уводит. Причем здесь разработчики терминала. Биржа, как и ее электронная площадка - это место и для спекулянтов, и для инвесторов, и для физ. лиц., и для юр. лиц и т.д.
Правила устанавливает частная коммерческая организация ПАО Мосбиржа или NASDAQ, или другая, под контролем соответствующих контролирующих органов, например SEC.
Возможно Вы только недавно для себя открыли этот новый мир, но он уже давно существует в таком виде.
Возможно ли запустить в индикаторе функцию из dll которая подключается в другом lua-скрипте?
Пользователь
Сообщений: Регистрация: 27.01.2017
08.10.2020 19:31:38
Вот пример такого решения, библиотека lua_share.
Кто как решил вопрос уведомления о сделках?
Пользователь
Сообщений: Регистрация: 27.01.2017
08.10.2020 19:03:44
Сделал небольшое решение для отправки сообщений в чат бота телеграма (Telrgram Bot Api).
Основа - это некое C# консольное приложение (многопоточный сервер), принимающее данные от lua скрипта и отправляющее уже сообщения в чат телеграм. Я предпочитаю делать так, дабы не связываться с проблемами совместимости библиотек lua.
Сначала сделал передачу данных на внутренний сервер через сокеты, но медленно оказалось. Переделал на Named Pipes, быстрее намного. Пришлось написать библиотеку Named Pipe клиента для lua.
Пока сделал только отправку сообщений, т.к. это самая частая просьба.
неужели OnParam самый быстрый?
Пользователь
Сообщений: Регистрация: 27.01.2017
05.10.2020 10:21:50
Вот я и не знаю. Лога получения нет, пытаюсь смоделировать. Надо ждать сильных движений а рынке, чтобы брокеры нагрузились. Может и у меня проблема, но эта часть кода уже столько времени работает...
Написал тестовый скрипт, чтобы отловить это. Раз было сказано, что TIME соответствует LAST, то, по идее, время не может стать меньше. Если поймается ошибка, то будет очевидно где проблема.
неужели OnParam самый быстрый?
Пользователь
Сообщений: Регистрация: 27.01.2017
05.10.2020 09:42:54
Да, конечно, OnParam это просто сигнал. Котировка получается через параметр LAST внутри колбека. Я не добавлял логирование в этом месте, по понятным причинам. Но реакция на значение была отмечена в другом месте.
Долгое исполнение сделки, Сделка на демо счете отработала более чем за 30 сек.
Пользователь
Сообщений: Регистрация: 27.01.2017
02.10.2020 13:48:57
Цитата
Олег написал: Идея хорошая, а можно показать краткий пример?
Это сложный вопрос. В самом lua нет многопоточности, поэтому надо организовать некие сущности, хранящие состояния и ждущие ответа. Проще всего это сделать на хеш-таблицах, т.е. на обычных таблицах.
Вы можете при подаче транзакции записать данные в некую таблицу по ключу, допустим код инструмента + номер транзакции. А далее организовать ожидание когда в этой таблице появится ответная информация. Ответ может туда записаться, в частности колбеком, или сами, опрашивая сделки, ордера, запишете.
Как только ответ получен, делаете что-то дальше. Нет ответа - пропускаете этот инструмент, ждете дальше. Тогда вы не будете зависеть от того как приходят ответы. В какие-то дни быстро, в какие-то очень медленно. Бывало до 10 минут доходило. Вы не можете предсказать когда он придет, поэтому и не можете поставить некое значение переменной ожидания в простом цикле. Как организовать ожидание, и саму подачу транзакции, здесь уже как удобнее. Можно через corutine, запуская их и проверяя в них состояние транзакции. Если нет ответа приостанавливаете ее и переходите к следующей.
Можно самому сделать некую сущность "Задача" и периодически опрашивая пул текущих задач, закрывать завершенные. А можно просто сделать таблицу транзакций, опрашивать ее и проверять состояние самой транзакции (допустим, записанное колбеком onTransReply), ордера, записанное другим колбеком и т.д.
Как прочитать таблицу Текущие торги?
Пользователь
Сообщений: Регистрация: 27.01.2017
02.10.2020 10:16:32
Имелось в виду, наверно, что функция loadstring вернет функцию, которую надо выполнить, т.е. вызвать через ().
Долгое исполнение сделки, Сделка на демо счете отработала более чем за 30 сек.
Пользователь
Сообщений: Регистрация: 27.01.2017
02.10.2020 10:10:21
Как правильно заметил Anton, сначала надо определиться что за заявку отправляете. Если цена "рыночная", то да, можно ожидать исполнения.
Что касается ожиданий, здесь вопрос организации этих циклов. Корректно не делать их в колбеках. Т.е. отправил транзакцию из main, там же циклы. А колбеки - это просто семафоры, что есть что-то. Также советую не делать циклы ожидания на транзакции. Если, допустим, скрипт работает с несколькими инструментами, то пока Вы ждете по одному, другие не смогут свои сигналы отработать. Лучше сделать так, чтобы ответный сигнал вызывал реакцию, но не простой всего алгоритма. Т.е. пока идет сигнал можно было бы выполнять что-то другое.
Долгое исполнение сделки, Сделка на демо счете отработала более чем за 30 сек.
Пользователь
Сообщений: Регистрация: 27.01.2017
02.10.2020 09:36:23
Зависит от схемы написания Вашего скрипта. Можете использовать колбек, как сигнал, что сделка прошла. Можете, наоборот, сами читать таблицу сделок, запоминая, допустим, последний индекс, для уменьшения последующих выборок.
Что касается времени срабатывания, то здесь нет понятия "нормально". Можно было бы сказать среднеожидаемое, и оно, действительно, будет небольшим, до 1 сек. Но сервер брокера может быть загружен, канал связи может плохим и т.д. Так что время может вырастать до минут.
Впрочем, еще есть один вариант, что некорректно производится ожидание сигнала, допустим, цикл ожидания в колбеке.
Как прочитать таблицу Текущие торги?
Пользователь
Сообщений: Регистрация: 27.01.2017
02.10.2020 09:28:13
И да, loadstring помимо того, что медленная, еще depricated.
Как прочитать таблицу Текущие торги?
Пользователь
Сообщений: Регистрация: 27.01.2017
02.10.2020 09:25:30
Странно... Ну да ладно. assert в С появился так давно, что даже не помню. В 90-х уже был.
А что касается документации, то:
Роботы всякие и прочие глупости
Пользователь
Сообщений: Регистрация: 27.01.2017
30.09.2020 19:17:11
Зачем спорить, тем более что аргументы как в детском саду. Это был просто пример. Пишите дальше. Для себя. Единственно что, хотелось бы на данном форуме не видеть комментариев не по теме.
Роботы всякие и прочие глупости
Пользователь
Сообщений: Регистрация: 27.01.2017
30.09.2020 18:39:55
Наговорили...
Владимир, года при выполнении такой простой команды getSecurityInfo('TQBR', 'SBER') получите nil, хотя у Вас будет подписка на поток данных по этому инструменту, то, возможно, вернетесь к этому вопросу.
неужели OnParam самый быстрый?
Пользователь
Сообщений: Регистрация: 27.01.2017
30.09.2020 10:51:27
То что обезличенные сделки будут самыми надежными это понятно.
Но все же, параметры TIME и LAST синхронизированы? Т.е. если мне брокер прислал в колбеке цену по времени пол часа назад, то параметр TIME укажет это?