Если не будете использовать TSL (SSL), то можно прямо из скрипта, используя socket библиотеку. Примеров достаточно как это сделать. Либо, если есть собранная библиотека luasec под версию lua и разрядность, то можно тоже прямо из скрипта по защищенным каналам. А если нет, то написать внешнюю программу чтения почты, сохранения содержимого в файлы. В скрипте их читать и разбирать. Вариантов достаточно. А раз уж поднят веб сервер, то можно и web аппликацию написать и развернуть для webhook.
Для этого Вам необходимо поднять Web server, который будет слушать и принимать POST запрос от TW. После этого этот ваш сервер должен оповестить тем или иным способом скрипт. По мне, почта в данном случае - самый надежный и простой способ. Побочный положительный эффект - можете сами отправлять письма на ящик, а скрипт будет их обрабатывать. Такая удаленная ручка для терминала.
Брать данные с графика - это крайний вариант, когда неизвестен алгоритм построения. А когда известно, то зачем. Тем более, что приведенный пример - очень неаккуратный. При этом очень неэффективен по памяти.
А Вы используете этот код как индикатор или как скрипт?
Если как скрипт, то не забывайте передавать поток данных, для которого даже есть переменная ds. Или, возможно, Вы просто переопределили глобальную переменную C, например С = 5. Что делать в индикаторе нельзя. Да и в скрипте тоже, если используете этот код, т.к. (C and C(I))просто проверяет на nil, а уж число там или нет уже не проверяет.
Да делайте как Вам угодно. Я не наблюдаю проблем сортировки для числовых колонок таблиц. Если хотите сортировать как строки, то да, тип строка, как число - число. И проблем с добавлением и тем более удалением строк не наблюдается.
Boris написал: отсортируте массив массивов со СТРОКОВЫМИ ключами в lua - по значению одному из столбцов вложенных массивов.вот может тогда поймёте в чём вывих мозга lua
В чем проблема - пишите свою анонимную функцию и сортируете.
Цитата
Boris написал: У меня есть большой массив данных, который выводится в ВИЗУАЛЬНУЮ таблицу и мог бы быть интерактивно и удобно для пользователя отсортирован в этой таблице - вообще без обращения к функциям lua - чисто уже имеющимся функционалом quik
И это сортируется. Но, как я понимаю, Вас не устраивает как сортируется строковое представление чисел. Так делайте тип колонок числовой (QTABLE_DOUBLE_TYPE или QTABLE_INT_TYPE) и выводите числа, а не строки.
Что-то я не понял про "привыкшего к стройному Си-синтаксису". Lua для сравнения строк использует С функцию strcoll. Ничего не выдумывая http://www.lua.org/source/5.3/lvm.c.html#l_strcmp. Сравнение строк - это всегда, не то чтобы проблема, но, как минимум, повод подумать. Кроме Вас никто не знает что и как Вы хотите от символов 1, 10, 11, 2.
Здесь возникает вопрос о целесообразности хранения чисел как строк. Или необходимости визуализации постоянно сортируемых данных. Впрочем, периодическая сортировка таблицы на 10 тыс. строк. не вызывала какого-то существенного замедления работы.
А если это будет таблица как внутренний объект lua типа 'table', то просто реализовать один из алгоритмов сортировки, удовлетворяющий задаче. Благо сейчас их много есть.
Я понимаю, что штатно терминал эти данные уже потерял, но хотелось бы услышать, что за все эти годы была написана некая утилита, осуществляющая это. HEX редактор как-то неохота привлекать.
Подниму тему. Есть папка archive, в ней есть данные минутного ТФ по контракту RIZ1, т.е. 2021 год. На графике этих данных нет. Как склеить данные и вывести их на график?
Администрация, а это нормально когда движок форума дает авторизироваться по тому же логину, что уже есть (даже если использовали символы другой раскладки)?
Автору: дело в том, что bid_count - это строка. И поэтому ее необходимо привести к числу.
Зачем так усердно бороться с колбеками, когда проще и, главное, надежней самому обрабатывать записи в таблице trades. Хотя, возможно, каждый должен пройти этот путь сам. Мне хватило одного раза, в самом начале, получив все колбеки за день, после восстановления соединения с брокером.
Технология Event-Driven, Asynchronous Callbacks хороша, когда поведение предсказуемо. А когда нет, то я уже как-нибудь сам, по старинке, найду новую запись в таблице.
Плохая затея. Вызов методов только в момент получения данных. Нет вызова - ничего сделать не можем. А как проверить, что все корректно после отправки транзакции вообще загадка, т.к. будет вызов OnCalculate или нет - неизвестно. Т.е. мы закладываем что все всегда хорошо, быстро и исполняется. Но это, как показывает практика, почти всегда не так.
Чем не устраивает файл с списком кодов инструментов и списком параметров для считывания. Читаете файл при старте, а дальше читаете данные по ним. И не надо заполнять ненужные мелькающие таблицы в терминале.
OnQuote - это и есть доступный колбек. Объявленная глобально такая функция будет вызываться на каждый чих в стакане. Т.к. таких изменение очень, очень много, и на каждое изменение вызывается getQuoteLevel2, то память и забивается, т.к. getQuoteLevel2 возвращает две таблицы, две строки. А это не так и мало. И делается это так часто, что сборщик мусора просто не успевает.
Если Вам не нужны данные стакана в каждом срезе без пропусков, то в колбеке надо просто установить флаг, что есть новый стакан по инструменту, а в потоке main его прочитать.
Чистый Lua синхронный, максимум что есть - это корутины. Можно попробовать использовать внешние библиотеки, обеспечивающие асинхронность.
Можете попробовать корутины, вот классчический пример для HTTP, который сразу находится по запросу "Lua socket asynchronous calls": Хотя, наверно, уже пробовали.
Код
function download (host, file, port)
port = port or 80
print (host, file, port)
local connectStatus, myConnection = pcall (socket.connect,host,port)
if (connectStatus) then
myConnection:settimeout(0.01) -- do not block you can play with this value
local count = 0 -- counts number of bytes read
-- May be easier to do this LuaSocket's HTTP functions
myConnection:send("GET " .. file .. " HTTP/1.0\r\n\r\n")
local lastStatus = nil
while true do
local buffer, status, overflow = receive(myConnection, lastStatus)
-- If buffer is not null the call was a success (changed in LuaSocket 2.0)
if (buffer ~= nil) then
io.write("+")
io.flush()
count = count + string.len(buffer)
else
print ("\n\"" .. status .. "\" with " .. string.len(overflow) .. " bytes of " .. file)
io.flush()
count = count + string.len(overflow)
end
if status == "closed" then break end
lastStatus=status
end
myConnection:close()
print(file, count)
else
print("Connection failed with error : " .. myConnection)
io.flush()
end
end
threads = {} -- list of all live threads
function get (host, file, port)
-- create coroutine
local co = coroutine.create(
function ()
download(host, file, port)
end)
-- insert it in the
table.insert(threads, co)
end
function receive (myConnection, status)
if status == "timeout" then
print (myConnection, "Yielding to dispatcher")
io.flush()
coroutine.yield(myConnection)
end
return myConnection:receive(1024)
end
function dispatcher ()
while true do
local n = table.getn(threads)
if n == 0 then break end -- no more threads to run
local connections = {}
for i=1,n do
print (threads[i], "Resuming")
io.flush()
local status, res = coroutine.resume(threads[i])
if not res then -- thread finished its task?
table.remove(threads, i)
break
else -- timeout
table.insert(connections, res)
end
end
if table.getn(connections) == n then
socket.select(connections)
end
end
end
host = "www.w3.org"
get(host, "/TR/html401/html40.txt")
get(host,"/TR/2002/REC-xhtml1-20020801/xhtml1.pdf")
get(host,"/TR/REC-html32.html")
get(host,"/TR/2000/REC-DOM-Level-2-Core-20001113/DOM2-Core.txt")
dispatcher()
Подниму. Сам часто забываю зажимать Ctrl. Кажется, что лучше добавить тип установки цены исполнения: абсолютный и относительный. При выборе относительного задается отступ в указанной величине (шаги, пункты, проценты). Тогда при сдвиге отступ будет рассчитываться при активации.
Сейчас же, забудешь зажать и цена легко уйдет за границы допустимого ценового коридора или выйдет за проскальзывание и стоп ордер становится, по сути, бессмысленным. А пользователь, если не обратит внимание, узнает об этом когда увидит странное - он исполнен, а лимитный ордер висит или отвергнут.
Если Вы не указали rocks какой интерпретатор использовать при установке, то по умолчанию он использует то что найдет. Если не прописаны пути к lua, то возьмет встроенный. Он, кажется 32 бита.
Если сам скрипт и отправляет транзакции, то Вы можете дополнить транзакцию комментарием, который будет записан в поле brokerref. Соответственно сделки с контролируемым комментарием - это сделки, требующие учета. Далее уже в этих сделках ждете появления trans_id и разбираете по идентификатору транзакции (если это вообще необходимо).
Т.к. записи в таблице формируются не за один раз, т.о. первичное появление записи о сделке, возможно, было просто как фиксация факта. Потом уже было дополнено идентификатором транзакции. Если обратите внимание на колбек OnTrade, то он приходит три раза на сделку. Каждый раз - это какое-то изменение в записи таблицы.
Владимир, Вы правы только в том, что обрабатывать тиковые данные через proxy терминал Квик - это не лучшая затея. Хотя обрабатывать обезличенные сделки, т.е. каждый тик, вполне можно. Все зависит от задачи и скорости принятия решений. Для примера, задача: определить был ли реализован видимый объем в стакане сделками или снят - решается довольно просто, с достаточной точностью.
В остальном же, как обычно - не надо мне, не надо никому. Но мир не вращается вокруг Вас.
Скрипт простой: ставим метку и потом читаем данные. После установки метки берем и перетаскиваем ее на графике, желательно быстро. Терминал зависает. На таком простом скрипте это происходит не сразу, поэтому можно просто двигать метку до выявления эффекта. Частично помогает избежать проблемы увеличение sleep до 500.
На версиях 8.* - сколько не двигал не получается эффект зависания, даже на sleep 55.
На самом деле - серьезная проблема, т.к. считывание данных с меток - это единственный способ взаимодействия пользователя с скриптом через график.
local sleep = _G.sleep
local isRun = true
local AddLabel = _G.AddLabel
local GetLabelParams = _G.GetLabelParams
function _G.OnStop()
isRun = false
end
function _G.main()
local tag = 'virt_test'
local label_params = {}
label_params.YVALUE = 119.5
label_params.TEXT = 'TEST |||||||||||||||||||||||||||||||||||||||||||||'
label_params.HINT = 'Еще текст'
label_params.DATE = 20220611
label_params.TIME = 152000
label_params.FONT_FACE_NAME = 'Arial'
label_params.ALIGNMENT = 'RIGHT'
label_params.FONT_HEIGHT = 10
label_params.TRANSPARENT_BACKGROUND = 1
local l_id = AddLabel(tag, label_params)
sleep(1000)
while isRun do
label_params = GetLabelParams(tag, l_id)
if label_params then
_G.message(tostring(label_params.yvalue))
end
sleep(100)
end
end
Это значит что при попытке вывода линий они выводятся не на своих местах. Для примера, в Settings.line три линии. В Init добавили еще две линии - их стало пять. Вернули из функции Init 5. При отрисовке линий 4, 5 они выводятся поверх линий 1-3.
Код, снимающий заявки у Вас написан, какой бы он ни был.
А далее есть вопросы организации последовательности вызовов методов. Необходимо учитывать, что скрипт работает на клиенте, а ответы приходят с сервера. Т.е. время ответа неизвестно. Далее, если используете колбеки, то необходимо учитывать, что последовательность их прихода не гарантирована. Также, раз у нас клиент-сервер, то изменение состояния ордера после отправки транзакции на снятие, не придет мгновенно. Т.е. если транзакция на снятие ушла без ошибок, то пока не придет ответ или не прочитаете новое состояние ордера, отправлять новую транзакцию нельзя. Иначе возникнет ситуация когда отправили транзакцию на снятие, не дождались ответа и отправили новую.
Владимир написал: Nikolay, Не совсем так: торгую как раз ТОЛЬКО я - это я "купил 5 штук по цене X, потом еще 3 по цене Y, потом продал 2 по цене Z". Я их купил, это моя собственность, и только я могу знать, какие именно из них я продаю (хочу ли я это знать - это другой вопрос). Но ни брокер, ни кто-либо ещё этого знать в принципе не могут, и потому вынуждены считать по FIFO.
Так поэтому в Квике так и транслируется. Не нравится - считай сам.
Возникает встречный вопрос - Вы пробовали посмотреть что хранится в указанных таблицах?
Что же касается стоимости, то вот купили Вы 5 штук по цене X, потом еще 3 по цене Y, потом продали 2 по цене Z. Какая стоимость приобретения? Т.к. торгуете не только Вы, то приняты соглашения о методике расчета.
Alex написал: Пытался запустить Ваш скрипт, выдает. ошибку. attempt to index a nil value (local 'pipe')
Правильно. Lua умеет писать (читать) в существующий "именованый файл". Поэтому на другой стороне его надо создать. Т.е. нужен сервер (служба), обслуживающий каналы. Вот его и надо на стороне питона делать
local pipe = io.open("\\\\.\\PIPE\\"..pipe_name, "w+b")
if not pipe then
return
end
pipe:write('BlaBla') -- записываем команду в канал
--Читаем
local rd = ''
local ct = os.time()
-- Для примера: Т.к. время ожидания ответа может быть не мгновенным, то ожидаем 2 секунды, читая из канала ответ.
while os.time() - ct < 2 and rd == '' do
rd = pipe:read('*a')
end
tele_pipe:close() -- закрываем канал
А python - это же такая "помойка". Неужели нет готовой библиотеки сервера named pipes? Поиск выдает тонны вариантов.
срабатывания условий тэйка сервером выставляется новая заявка с новым номером order_num который нужно как-то отфильтровать и получить
При срабатывании стоп ордера происходит отправка транзакции сервером брокера. В случае успеха отправки (может не пройти), в стоп ордере, точнее в таблице stop_orders для записи вашего ордера, будет заполнено поле linked_order. Это и есть тот номер лимитного ордера, который отправлен по факту активации стоп ордера. По нему и ищите, фильтруйте. Правда, как и всегда при клиент-серверном взаимодействии, событие смены статуса стоп ордера и событие заполнения linked_order, и появление его в таблице orders, не мгновенные. И необходимо организовать методы ожидания.
Описанная в данном инциденте проблема была устранена в версии 7.23.0 терминала QUIK. Данная версия была разослана всем брокерам системы QUIK в рамках стандартной процедуры обновления версии 23.11.2018. По поводу получения обновления рекомендуем вам обратиться к своему брокеру.
Приносим извинения за причиненные неудобства.
Подниму..
Вроде работало, не следил. Но теперь в 9-ой версии не работает.
Если при первичной инициализации индикатора было x линий (добавление на график). А уже при повторной (после изменения настроек) линий больше x, то отрисовка линий происходит некорректно.