Добрый день. Я бился с подключением SSL библиотеки. Не подключалась никак из готовых библиотек. На стороне тоже все работало. В конечном итоге пришлось просто пересобрать конкретную версию библиотеки, которая в итоге заработала. Так что советую собрать luacurl через luarocks именно под lua 5.1.
Еще один момент важный, такого рода библиотеки в Квике работают, если они лежат в папке с библиотекой lua5.1, т.е. в папке установки Квика. В чем здесь особенность Квика не знаю, но пришлось так сделать, иначе никак не запускалось.
Проблему решил. Пришлось скомпилировать самому luaSec 0.8-1 под lua 5.1, используя Open SSL. Файлы libeay32 и ssleay32 обязаны быть рядом с файлом lua 5.1, т.е. в папке установки Quik.
У меня отправка почты совершается за секунду, две. Не более. Никаких задержек.
Теперь можно приступать к использованию библиотеки для интересных вещей, типа чтения Twitter и т.д.
А у меня такой строчки нету и все работает, короче у меня все прописано вот так:
Ну я хочу использовать эту библиотеку не для отправки почты. Для почты я написал на C# програмульку на 10 строк, вызываю ее из Квика и все. А вот для других целей хочется запустить. Ясно, что дело в путях, т.к. в другом месте работает. Будем копать...
Анатолий написал: Сложно так сказать не видя что у тебя в скрипте и в папках квика, покажи тогда свой кусок скрипта где обьявляются пути
package.cpath = ... package.path = ...
и идет подключение библиотек командой require
Так а что здесь такого при подключении... Я же говорю, что этот же скрипт ZeroBraneStudio в работает. Отличие в том, что у него свои пути к библиотекам. А здесь такие. Попытка поставить пути из ZeroBraneStudio для Квика приводит к аналогичной ошибке.
Nikolay написал: Я тоже подозреваю, что с интерпретатором lua в Квике не все ладно. У меня также из ZeroBraneStudio все работает.
С интерпретатором луа в квике все ладно, просто там есть нюансы, у меня были все эти проблемы и я их решил, помоему ты всетаки не все скопировал из окна ошибок, полностью все оттуда скопируй и вставь сюда, или лучше сделай скрин и выложи
Я скопировал все, кроме полного пути до файла ssl.dll. Больше ошибок нет. Выше по сообщениям этой темы были аналогичные сообщения.Если бы интерпретатор луа был чист, то типовая библиотека strict не приводила бы к падению терминала.
Анатолий написал: В момент выполнения строки registry = ctx: ctx= SSL context: 0D72EE88 тип - userdata s = SSL connection: 0D848F00 тип - userdatasock = tcp{client}:0D846E88 setfd=nilВообщем мне кажется что это связано с квиковским интерпретатором луа, т.к. операция registry это сохранение любых значений C кода в специальной общей таблице для всех выполняемых С кодов, вот тут в чем о и проблема, т.к. в других интерпретаторах, том же Zerobrane, такой проблемы нет
Я тоже подозреваю, что с интерпретатором lua в Квике не все ладно. У меня также из ZeroBraneStudio все работает. Также не все библиотеки можно подключить в Квике, для примера strict - Квик падает без слов. Также обнаружил, что внутри фунции SearchItems (в функции проверки) у меня почему-то проверка nil как false не срабатывает. Приходится явно писать ~= nil
Nikolay написал: Я подключил все библиотеки, socket подключается нормально. Но при подключении ssl, не находит ssl.core. ssl.lua, собственно, и пытается его включить local core = require("ssl.core")Т.е. нужна папка \ssl а в ней файл core.dll
Скопируй из квика из окна "Ошибки выполнения скрипта" то что там пишется при твоей попытке выполнить скрипт и выложи это сюда"
Ну так и пишется, что не может загрузить модуль. Все пути прописаны, библиотека рабочая, взята из поставки ZeroBraneStudio. Из нее все прекрасно работает. При этом просто socket загружается нормально.
Код
error loading module 'ssl.core' from file 'ssl.dll':
Не найден указанный модуль.
А тоже самое из ZeroBraneStudio работает. ssl.core - ошибку не дает, письма отправляются. А Квик ошибку выдает на local core = require("ssl.core") в ssl.lua
Я подключил все библиотеки, socket подключается нормально. Но при подключении ssl, не находит ssl.core. ssl.lua, собственно, и пытается его включить local core = require("ssl.core") Т.е. нужна папка \ssl а в ней файл core.dll
Попробовал взять сборку Телеграм бота, что здесь выкладывали, аналогичная проблема. Похоже какая-то библиотека все же отсутствует. Кто-то встречал похожую ошибку? Я нашел упоминания, то это связано с libeay32 и ssleay32, но они есть, путь к ним прописан. Плюс пробовал класть их в разные папки.
Что касается "стандартных стратегий", то я не верю в них, т.к. они основаны на предположеннии, что тенденция прошлого сохранятся и в будущем, что, естественно, не так. Да, есть решения, позволяющие минимизировать риски, но рынок меняет свои характеристики так, что требуется пересчет оптимальных параметров стратегии. Что, в свою очередь, приводит к проблеме переоптимизации. А это замкнутый круг.
Я же больше верю в стратегии с элементами количественнго анализа, основанные на потоке реальных данных. При этом, естественно, стратегия строится на выявлении закономерностей на истории, но не путем усреднения характеристик движения цены (скользящие, осцилляторы и др.), а на анализе абсолютных значений движения цены и их отношений друг к другу. Свечи же - это искусственное загрубление характеристик. Скажем, почему ТФ - минута, а если я хочу 25 секунд. Кто решил, что всем хватит минуты? Ведь, если хоть немнго сдвинуть ТФ, то картина может кардинально измениться, сменятся максимумы-минимумы, открытия-закрытия. Поэтому более важна характеристика сколько цена прошла за отведенный период. Период, при этом, не привязан к ТФ, хоть, зачастую, им и является.
Для примера, безумная стратегия: если цена в 13:00 выше открытия дня (или недели), то покупаем и наоборот Закрытие сделки по рассчитанному профиту или через 45 минут, что раньше. Это выдуманный пример выявленной закономерности. Такая стратегия живет месяц-два, а то и меньше. Также выявляются и другие закономерности вплоть до тикового уровня. При этом также находятся и закономерности типа гармонических фигур любого перирода, их последовательности, отношений.
Все это требует вычислительной мощности и постоянного анализа данных. Это, естественно, мало кто может себе позволить.
Спасибо Николай, но видимо так я и не дождался этой доработки. Пока ждал данный функционал был разработан уже, причем в веб интерфейсе, и ровно так как я его описывал год назад http://bit.ly/2TKazri
Николай так скажите, а Вы какого подхода придерживаетесь при работе с стратегиями, если "не очень верю в торговлю по инерционным индикаторам" немного поподробней??
На нашем рынке, данный виртуальный режим реализован в TigerTrade и SBPro. Второй правда только на срочном рынке, но думаю, что в основном это и надо только на срочке. Данные платформы имеют демо, где можно все посмотреть.
Реализация данного режима - это запуск экземпляра приложения с последовательным чтением данных из истории (не только сохраненной, но и загрузка с сервера). Что важно, реализовано это все с поддержкой склейки контрактов. Также важно, что даные режимы для ручной торговли. Т.е. сделки на истории вы будете совершать руками.
Я для себя сделал робот с возможностью вирутальной торговли, который позволяет совершать сделки, ориентируясь на текущий стакан. Что, естественно, имеет некие допущения, т.к. при вирутальной торговле объем из стакана не исчезает. Поэтому можно говорить, что данное мое решение допустимо рассматривать только для малых объемов.
А для истории написан тестер алгоритмов. Сделать в Квике ручную торговлю на истории пока невозможно, но, с дургой стороны, это не такой уж большой недостаток получается, если можно симулироать торговлю в реале.
Единственное замечание - я не очень верю в торговлю по инерционным индикаторам, поэтому решение по написанию конструктора стратегии псевдоязыком (что реализовано в MT5, WealthLab и др.) видится сомнительным занятием. Но здесь, как говориться, вопрос про деньги. Если бы платформа Квик была платной для конечного пользователя, то возможно можно бы реализовать такую функциональность для завлечения новых "инвесторов", заявив, что теперь наша платформа позволяет обучаться "трейдингу" и вы легко можете написать своего робота.
Здесь, скорее всего, проблема скорости выполнения цикла. У меня есть сложный скрипт, выполняющий много расчетов в main. В нем все работает без задержек. А простейшие скрипты, которые делают мало действий в main, не обнолвяют таблицу. Возможно, идет переполнение стека вызовов обновления окна.
Хотя разработчки выше писали, что проблема не воспроизводится.
А вот сделав такие изменения в цикл вывода строк, все работает.
Код
for i=1,lines do
outlines[i] = {index = index-shift+bars, val = maxPrice}
if sortedProfile[i]~=nil then
sortedProfile[i].vol=math.floor(sortedProfile[i].vol/MAXV*bars)
if sortedProfile[i].vol>0 then
outlines[i].index = index-shift+sortedProfile[i].vol
outlines[i].val = sortedProfile[i].price
end
end
SetValue(index-shift, i+1, outlines[i].val)
SetValue(outlines[i].index, i+1, outlines[i].val)
--WriteLog('line '..tostring(i).." price "..tostring(GetValue(index-shift, i)).." - "..tostring(GetValue(outlines[i].index, i)).." vol "..tostring(outlines[i].index-index+shift))
end
Код
--logfile=io.open(getWorkingFolder().."\\LuaIndicators\\priceAvgProfile.txt", "w")
Settings={}
Settings.period = 150
Settings.shift = 100
Settings.Name = "*priceAvgProfile"
Settings.weeks = 0 -- 1 - текущая, отрицательное число - сколько прошлых недель, включая текущую
Settings.fixShift = 1 -- 1 - всегда смещено на указанное количество shift, если 0, то будет смещено на дату начала неделеи расчета
Settings.showMaxLine = 1
---------------------------------------------------------------------------------------
lines = 100
scale = 2
min_price_step = 1
function Init()
Settings.line = {}
Settings.line[1] = {}
Settings.line[1] = {Name = 'maxVol', Color = RGB(255, 128, 64), Type = TYPE_LINE, Width = 2}
for i = 1, lines do
Settings.line[i+1] = {}
Settings.line[i+1] = {Color = RGB(185, 185, 185), Type = TYPE_LINE, Width = 2}
end
myFFF = FFF()
return lines
end
function OnCalculate(index)
if index == 1 then
DSInfo = getDataSourceInfo()
min_price_step = getParamEx(DSInfo.class_code, DSInfo.sec_code, "SEC_PRICE_STEP").param_value
scale = getSecurityInfo(DSInfo.class_code, DSInfo.sec_code).scale
end
return myFFF(index, Settings)
end
---------------------------------------------------------------------------------------
function FFF()
local cacheL={}
local cacheH={}
local cacheC={}
local weeksBegin={}
local maxPriceLine={}
local outlines = {}
local calculated_buffer={}
return function(ind, Fsettings)
local period = Fsettings.period or 150
local shift = Fsettings.shift or 150
local weeks = Fsettings.weeks or 0
local fixShift = Fsettings.fixShift or 0
local showMaxLine = Fsettings.showMaxLine or 0
local bars = 50
shift = math.max(bars+1, shift)
local index = ind
if index == 1 then
maxPriceLine = {}
weeksBegin = {}
cacheL = {}
cacheL[index] = 0
cacheH = {}
cacheH[index] = 0
cacheC = {}
cacheC[index] = 0
calculated_buffer = {}
outlines = {}
return nil
end
------------------------------
--maxPriceLine[index] = maxPriceLine[index-1]
cacheL[index] = cacheL[index-1]
cacheH[index] = cacheH[index-1]
cacheC[index] = cacheC[index-1]
if not CandleExist(index) then
return maxPriceLine[index]
end
cacheH[index] = H(index)
cacheL[index] = L(index)
cacheC[index] = C(index)
if T(index).week_day<T(index-1).week_day or T(index).year>T(index-1).year then
weeksBegin[#weeksBegin+1] = index
end
if index < Size() then return nil end
if calculated_buffer[index] ~= nil then
return maxPriceLine[index]
end
if showMaxLine==1 then
SetValue(index-shift-1, 1, nil)
SetValue(index-shift, 1, nil)
end
for i=1,#outlines do
SetValue(index-shift-1, i+1, nil)
SetValue(index-shift, i+1, nil)
SetValue(outlines[i].index, i+1, nil)
outlines[i].index = index-shift
outlines[i].val = nil
end
local beginIndex = index-period
if weeks == 1 then
beginIndex = weeksBegin[#weeksBegin] or beginIndex
end
if weeks < 0 then
beginIndex = weeksBegin[#weeksBegin+weeks] or beginIndex
end
if fixShift==0 then
shift = math.max(bars+1, index-beginIndex)
end
--WriteLog('weeks '..tostring(weeks)..' last '..tostring(weeksBegin[#weeksBegin])..' beginIndex '..tostring(beginIndex))
local maxPrice = math.max(unpack(cacheH,math.max(beginIndex, 1),index))
local minPrice = math.min(unpack(cacheL,math.max(beginIndex, 1),index))
----------------------------------------
local priceProfile = {}
--local clasterStep = math.max((maxPrice - minPrice)/lines, min_price_step)
--local clasterStep = (maxPrice - minPrice)/lines
local clasterStep = 10*min_price_step
--WriteLog('minPrice '..tostring(minPrice)..' maxPrice '..tostring(maxPrice)..' clasterStep '..tostring(clasterStep))
for i = 0, (index-beginIndex) do
if CandleExist(index-i) then
local barSteps = math.max(math.ceil((H(index-i) - L(index-i))/clasterStep),1)
for j=0,barSteps-1 do
local clasterPrice = math.floor((L(index-i) + j*clasterStep)/clasterStep)*clasterStep
local clasterIndex = clasterPrice*math.pow(10, scale)
if priceProfile[clasterIndex] == nil then
priceProfile[clasterIndex] = {price = clasterPrice, vol = 0}
end
priceProfile[clasterIndex].vol = priceProfile[clasterIndex].vol + V(index-i)/barSteps
end
end
end
--------------------
local MAXV = 0
local maxPrice = 0
local maxCount = 0
local sortedProfile = {}
for i, profileItem in pairs(priceProfile) do
MAXV=math.max(MAXV,profileItem.vol)
if MAXV == profileItem.vol then
maxPrice=profileItem.price
end
maxCount = maxCount + 1
sortedProfile[maxCount] = {price = profileItem.price, vol = profileItem.vol}
end
--WriteLog('maxV '..tostring(MAXV)..' tblMax '..tostring(sortedProfile[1].vol))
if maxPrice == 0 then
maxPrice = O(index)
end
table.sort(sortedProfile, function(a,b) return (a['vol'] or 0) > (b['vol'] or 0) end)
---------------------
for i=1,lines do
outlines[i] = {index = index-shift+bars, val = maxPrice}
if sortedProfile[i]~=nil then
sortedProfile[i].vol=math.floor(sortedProfile[i].vol/MAXV*bars)
if sortedProfile[i].vol>0 then
outlines[i].index = index-shift+sortedProfile[i].vol
outlines[i].val = sortedProfile[i].price
end
end
SetValue(index-shift, i+1, outlines[i].val)
SetValue(outlines[i].index, i+1, outlines[i].val)
--WriteLog('line '..tostring(i).." price "..tostring(GetValue(index-shift, i)).." - "..tostring(GetValue(outlines[i].index, i)).." vol "..tostring(outlines[i].index-index+shift))
end
if showMaxLine==1 then
SetValue(index-shift, 1, maxPrice)
maxPriceLine[index] = maxPrice
end
calculated_buffer[index] = true
return maxPriceLine[index]
end
end
function WriteLog(text)
logfile:write(tostring(os.date("%c",os.time())).." "..text.."\n");
logfile:flush();
LASTLOGSTRING = text;
end
Я привел весь код индикатора. Больше кода в нем нет.
Вы хотите увидеть ка формируется табоица algoResults? Но она получается из dll. Это простая таблица в которой накопленный объем по цене. Далее они просто выводятся.
В Вашем примере, данные не получаются онлайн. Вы их вывели по данным прошлых свечек. А значит, при первом вызове OnCalculate, все данные для линий получены. При установке индикатора OnCalculate вызывается же два раза. Хотя зачем?
Делаю предположение, что это как-то связано.
Вот, для примера, испорченный индикатор горизонтальных объемов. Он реализует такой же алгоритм, получая данные из свечек, а не из dll. В таком варианте он не работает как надо:
Код
--logfile=io.open(getWorkingFolder().."\\LuaIndicators\\priceAvgProfile.txt", "w")
Settings={}
Settings.period = 150
Settings.shift = 100
Settings.Name = "*priceAvgProfile"
Settings.weeks = 0 -- 1 - текущая, отрицательное число - сколько прошлых недель, включая текущую
Settings.fixShift = 1 -- 1 - всегда смещено на указанное количество shift, если 0, то будет смещено на дату начала неделеи расчета
Settings.showMaxLine = 1
---------------------------------------------------------------------------------------
lines = 100
scale = 2
min_price_step = 1
function Init()
Settings.line = {}
Settings.line[1] = {}
Settings.line[1] = {Name = 'maxVol', Color = RGB(255, 128, 64), Type = TYPE_LINE, Width = 2}
for i = 1, lines do
Settings.line[i+1] = {}
Settings.line[i+1] = {Color = RGB(185, 185, 185), Type = TYPE_LINE, Width = 2}
end
myFFF = FFF()
return lines
end
function OnCalculate(index)
if index == 1 then
DSInfo = getDataSourceInfo()
min_price_step = getParamEx(DSInfo.class_code, DSInfo.sec_code, "SEC_PRICE_STEP").param_value
scale = getSecurityInfo(DSInfo.class_code, DSInfo.sec_code).scale
end
return myFFF(index, Settings)
end
---------------------------------------------------------------------------------------
function FFF()
local cacheL={}
local cacheH={}
local cacheC={}
local weeksBegin={}
local maxPriceLine={}
local outlines = {}
local calculated_buffer={}
return function(ind, Fsettings)
local period = Fsettings.period or 150
local shift = Fsettings.shift or 150
local weeks = Fsettings.weeks or 0
local fixShift = Fsettings.fixShift or 0
local showMaxLine = Fsettings.showMaxLine or 0
local bars = 50
shift = math.max(bars+1, shift)
local index = ind
if index == 1 then
maxPriceLine = {}
weeksBegin = {}
cacheL = {}
cacheL[index] = 0
cacheH = {}
cacheH[index] = 0
cacheC = {}
cacheC[index] = 0
calculated_buffer = {}
outlines = {}
return nil
end
------------------------------
--maxPriceLine[index] = maxPriceLine[index-1]
cacheL[index] = cacheL[index-1]
cacheH[index] = cacheH[index-1]
cacheC[index] = cacheC[index-1]
if not CandleExist(index) then
return maxPriceLine[index]
end
cacheH[index] = H(index)
cacheL[index] = L(index)
cacheC[index] = C(index)
if T(index).week_day<T(index-1).week_day or T(index).year>T(index-1).year then
weeksBegin[#weeksBegin+1] = index
end
if index < Size() then return nil end
if calculated_buffer[index] ~= nil then
return maxPriceLine[index]
end
if showMaxLine==1 then
SetValue(index-shift-1, 1, nil)
SetValue(index-shift, 1, nil)
end
for i=1,#outlines do
SetValue(index-shift-1, i+1, nil)
SetValue(index-shift, i+1, nil)
SetValue(outlines[i].index, i+1, nil)
outlines[i].index = index-shift
outlines[i].val = nil
end
local beginIndex = index-period
if weeks == 1 then
beginIndex = weeksBegin[#weeksBegin] or beginIndex
end
if weeks < 0 then
beginIndex = weeksBegin[#weeksBegin+weeks] or beginIndex
end
if fixShift==0 then
shift = math.max(bars+1, index-beginIndex)
end
--WriteLog('weeks '..tostring(weeks)..' last '..tostring(weeksBegin[#weeksBegin])..' beginIndex '..tostring(beginIndex))
local maxPrice = math.max(unpack(cacheH,math.max(beginIndex, 1),index))
local minPrice = math.min(unpack(cacheL,math.max(beginIndex, 1),index))
----------------------------------------
local priceProfile = {}
--local clasterStep = math.max((maxPrice - minPrice)/lines, min_price_step)
--local clasterStep = (maxPrice - minPrice)/lines
local clasterStep = 10*min_price_step
--WriteLog('minPrice '..tostring(minPrice)..' maxPrice '..tostring(maxPrice)..' clasterStep '..tostring(clasterStep))
for i = 0, (index-beginIndex) do
if CandleExist(index-i) then
local barSteps = math.max(math.ceil((H(index-i) - L(index-i))/clasterStep),1)
for j=0,barSteps-1 do
local clasterPrice = math.floor((L(index-i) + j*clasterStep)/clasterStep)*clasterStep
local clasterIndex = clasterPrice*math.pow(10, scale)
if priceProfile[clasterIndex] == nil then
priceProfile[clasterIndex] = {price = clasterPrice, vol = 0}
end
priceProfile[clasterIndex].vol = priceProfile[clasterIndex].vol + V(index-i)/barSteps
end
end
end
--------------------
local MAXV = 0
local maxPrice = 0
local maxCount = 0
local sortedProfile = {}
for i, profileItem in pairs(priceProfile) do
MAXV=math.max(MAXV,profileItem.vol)
if MAXV == profileItem.vol then
maxPrice=profileItem.price
end
maxCount = maxCount + 1
sortedProfile[maxCount] = {price = profileItem.price, vol = profileItem.vol}
end
--WriteLog('maxV '..tostring(MAXV)..' tblMax '..tostring(sortedProfile[1].vol))
if maxPrice == 0 then
maxPrice = O(index)
end
table.sort(sortedProfile, function(a,b) return (a['vol'] or 0) > (b['vol'] or 0) end)
---------------------
for i=1,lines do
if sortedProfile[i]~=nil then
outlines[i] = {index = index-shift+bars, val = maxPrice}
sortedProfile[i].vol=math.floor(sortedProfile[i].vol/MAXV*bars)
if sortedProfile[i].vol>0 then
outlines[i].index = index-shift+sortedProfile[i].vol
outlines[i].val = sortedProfile[i].price
end
SetValue(index-shift, i+1, outlines[i].val)
SetValue(outlines[i].index, i+1, outlines[i].val)
end
--WriteLog('line '..tostring(i).." price "..tostring(GetValue(index-shift, i)).." - "..tostring(GetValue(outlines[i].index, i)).." vol "..tostring(outlines[i].index-index+shift))
end
if showMaxLine==1 then
SetValue(index-shift, 1, maxPrice)
maxPriceLine[index] = maxPrice
end
calculated_buffer[index] = true
return maxPriceLine[index]
end
end
function WriteLog(text)
logfile:write(tostring(os.date("%c",os.time())).." "..text.."\n");
logfile:flush();
LASTLOGSTRING = text;
end
lines = 150
min_price_step = 1
scale = 2
function Init()
Settings.line = {}
for i = 1, lines do
Settings.line[i] = {}
Settings.line[i] = {Color = RGB(185, 185, 185), Type = TYPE_LINE, Width = 2}
end
algoF = getResults()
return lines
end
Проблема именно в том, что если выводить линии не все сразу, они почему-то потом не показываются, а только те, что имели значение при запуске. Далее, по мере поступления новых данных (цена же двигается и торовый диапазон расширяется) в таблицу algoResults, надо выводить новые линии, но они не показываются. Именно визуально не видны, но при этом, что очень странно, GetValue возвращает значение.
Как написал выше, пришлось выводить ненулевые значения для каждой линии, накладывая одну на другую. Так работает.
Приходится выводить всегда столько линий, сколько определено, накладывая одну на другую, чтобы они слились в одну для пользователя. По мере поступления новых линий они будут тогда уже распределятся по уровням цены.
Если было выведено при инициализации 100 линий (т.е. когда происходит первый вызов OnCalculate), то больше не показывает индикатор. Далее линии вроде имеют значение, но не видны.
Sergey Gorokhov написал: Здравствуйте, Приведите полную версию кода.
Здравствуйте.
Код простой.
Код
require("StaticVar")
Settings ={
Name = "*priceProfile",
shift = 150,
ChartId = "Sheet11"
}
lines = 150
min_price_step = 1
scale = 2
function Init()
Settings.line = {}
for i = 1, lines do
Settings.line[i] = {}
Settings.line[i] = {Color = RGB(185, 185, 185), Type = TYPE_LINE, Width = 2}
end
algoF = getResults()
return lines
end
function getResults()
local outlines = {}
local priceProfile = {}
local tmpOutlines = {}
return function(index, Fsettings)
local shift = Fsettings.shift or 150
local bars = 50
if index == 1 then
outlines = {}
tmpOutlines = {}
for i=1,lines do --необходимо вывести все линии хотя бы один раз, чтобы потом они отображались без проблем
tmpOutlines[i] = O(Size())
end
return unpack(tmpOutlines)
end
if index == 2 then
for i=1,lines do
SetValue(1,i,nil)
end
return nil
end
if index == Size() then
stv.UseNameSpace(Fsettings.ChartId)
algoResults = stv.GetVar('priceProfile')
priceProfile = {}
if algoResults ~= nil and type(algoResults) == "table" then
for i=1,#outlines do
SetValue(index-shift-1, i, nil)
SetValue(index-shift, i, nil)
SetValue(outlines[i].index, i, nil)
outlines[i].index = index-shift
outlines[i].val = nil
end
local MAXV = 0
local maxCount = 0
for i, profileItem in pairs(algoResults) do
MAXV=math.max(MAXV,profileItem.vol)
maxCount = maxCount + 1
priceProfile[maxCount] = {price = profileItem.price, vol = profileItem.vol}
end
table.sort(priceProfile, function(a,b) return (a['vol'] or 0) > (b['vol'] or 0) end)
for i=1,math.min(#priceProfile, lines) do
if priceProfile[i]~=nil then
outlines[i] = {index = index-shift, val = nil}
priceProfile[i].vol=math.floor(priceProfile[i].vol/MAXV*bars)
if priceProfile[i].vol>0 then
outlines[i].index = index-shift+priceProfile[i].vol
outlines[i].val = priceProfile[i].price
end
SetValue(index-shift, i, outlines[i].val)
SetValue(outlines[i].index, i, outlines[i].val)
end
end
end
end
return nil
end
end
Т.к. в индикаторе необходимо при инициализации указывать количество возвращаемых линий, то написана такая конструкция в функции init:
Код
for i = 1, lines do
Settings.line[i] = {}
Settings.line[i] = {Color = RGB(185, 185, 185), Type = TYPE_LINE, Width = 2}
end
Алгоритм вводит линии по мере наполнения массива линий. Сначала их может быть 20, потом уже 100 и т.д. Для оптимизации линии выводятся только с не пустым значением.
Все бы хорошо, но заметил такую особенность (версия 7.19), если не вывести хотя бы один раз все линиий с не пустым значением, то потом они не отображаются на графике, хотя функция GetValue возвращает значение. Я долго не мог понять почему у меня линии не показываются с течением времени, а если заново инициализировать индикатор (через параметры графика), то все на месте.
Пришлось сделать такой странный костыль:
Код
if index == 1 then
tmpOutlines = {}
for i=1,lines do --необходимо вывести все линии хотя бы один раз, чтобы потом они отображались без проблем
tmpOutlines[i] = O(Size())
end
return unpack(tmpOutlines)
end
if index == 2 then
for i=1,lines do
SetValue(1,i,nil)
end
return nil
end
Есть пожелание по вводу индекса бара (свечи) в контекстной подсказке при наведении на бар. Сейчас выводится только дата, время и торговые параметры бара, но при отладе скриптов, да и просто для удобства задания диапазона, хотелось бы видеть индекс без костылей в виде доп. индикаторов.
Точнее, если в контекстном меню графика выбрать подменю удалить, то активна команда удалить метки. Но они не виды. Метки выводятся текстовые, с такими параметрами:
Код
FONT_FACE_NAME = "Arial",
FONT_HEIGHT = 4,
R = 64,
G = 200,
B = 64,
TRANSPARENT_BACKGROUND = 1,
ALIGNMENT = "RIGHT",
YVALUE = 0,
DATE = (tt.year*10000+tt.month*100+tt.day),
TIME = ((tt.hour)*10000+(tt.min-2)*100)
А еще вопрос - у меня почему-то метки, установленные из кода lua, исчезают при перезапуске Квика. Мне казалось, что они должны сохраняться. Это же метка.
Александр написал: хотя если sleep добавить в цикл побольше - перерисовывает.. интересно, какой sleep в цикле main оптимален, чтобы таблица успевала перерисовываться..
Возможно, но тормозить основной поток скрипта, только чтобы вывод был как-то не очень. У меня установлено 100 - все равно не хватает. А выше ставить уже слишком.
Возникла проблема. Выводятся текстовые метки друг над другом. Задется высота шрифта 10. А как перевести эту высоту в шаг цены? Сейчас приходится подбирать дельту цены, чтобы метки не накладывались.
Собственно очень не хватает процедур пересчета абсолютных координат окна (идеально еще бы иметь событие - "изменение масштаба") в ценовую и временную шкалы. Сразу бы решились многие проблемы. Сейчас просто невозможно рассчитать линию под определенным углом, или, наоборот, рассчитать угол линии.
Все же есть особенность обновления данных пользовательской таблицы.
Я заметил особенность, что если обновлять данные через SetCell в main, или в фунции вызванной из main, то обновляется таблица только если произвести действия с ней. Скажем, нажать правой клавишей мышки по полю таблицы или подвигать мышкой по шапке таблицы. Иначе данные обновляются с очень большим лагом - до минуты и более. А может и зависнуть совсем - даже остается цвет подсветки цвета от Highlight.
Вот простейший код скрипта. Вывод данных выведен в коллбэк. Все работает "на лету".
Код
CLASS_CODE = 'SPBFUT'
SEC_CODE = 'SiU8'
INTERVAL = INTERVAL_M1
t_id = nil
isRun = true
SeaGreen=12713921 -- RGB(193, 255, 193) нежно-зеленый
RosyBrown=12698111 -- RGB(255, 193, 193) нежно-розовый
function dsCallback()
local last_price = tonumber(getParamEx(CLASS_CODE,SEC_CODE,"last").param_value)
local lp = GetCell(t_id, 1, 0).value or last_price
if lp < last_price then
Highlight(t_id, 1, 0, SeaGreen, QTABLE_DEFAULT_COLOR,1000)
elseif lp > last_price then
Highlight(t_id, 1, 0, RosyBrown, QTABLE_DEFAULT_COLOR,1000)
end
SetCell(t_id, 1, 0, tostring(last_price), last_price)
end
function OnInit()
local Error = ''
DS,Error = CreateDataSource(CLASS_CODE, SEC_CODE, INTERVAL)
-- Проверка
if DS == nil then
message('ОШИБКА получения доступа к свечам! '..Error)
isRun = false
return
end
CreateTable()
local last_price = tonumber(getParamEx(CLASS_CODE,SEC_CODE,"last").param_value)
SetCell(t_id, 1, 0, tostring(last_price), last_price)
DS:SetUpdateCallback(function(...) dsCallback(...) end)
end
function main()
SetTableNotificationCallback(t_id, event_callback)
while isRun do
sleep(10)
end
end
function CreateTable() -- Функция создает таблицу
t_id = AllocTable()
AddColumn(t_id, 0, "price", true, QTABLE_DOUBLE_TYPE, 15)
tbl = CreateWindow(t_id)
SetWindowPos(t_id, 90, 120, 170, 100)
InsertRow(t_id, 1)
end
function event_callback(t_id, msg, par1, par2)
if (msg==QTABLE_CLOSE) then
isRun = false
end
end
function OnStop()
isRun = false
if t_id~= nil then
DestroyTable(t_id)
end
end
Но стоит изменить код на такой (обновление данных помещено внутрь цикла main), то все замирает, пока не "дернешь" окно.
Код
CLASS_CODE = 'SPBFUT'
SEC_CODE = 'SiU8'
INTERVAL = INTERVAL_M1
t_id = nil
isRun = true
SeaGreen=12713921 -- RGB(193, 255, 193) нежно-зеленый
RosyBrown=12698111 -- RGB(255, 193, 193) нежно-розовый
function dsCallback()
--[[
local last_price = tonumber(getParamEx(CLASS_CODE,SEC_CODE,"last").param_value)
local lp = GetCell(t_id, 1, 0).value or last_price
if lp < last_price then
Highlight(t_id, 1, 0, SeaGreen, QTABLE_DEFAULT_COLOR,1000)
elseif lp > last_price then
Highlight(t_id, 1, 0, RosyBrown, QTABLE_DEFAULT_COLOR,1000)
end
SetCell(t_id, 1, 0, tostring(last_price), last_price)
]]--
end
function OnInit()
local Error = ''
DS,Error = CreateDataSource(CLASS_CODE, SEC_CODE, INTERVAL)
-- Проверка
if DS == nil then
message('ОШИБКА получения доступа к свечам! '..Error)
isRun = false
return
end
CreateTable()
local last_price = tonumber(getParamEx(CLASS_CODE,SEC_CODE,"last").param_value)
SetCell(t_id, 1, 0, tostring(last_price), last_price)
DS:SetUpdateCallback(function(...) dsCallback(...) end)
end
function main()
SetTableNotificationCallback(t_id, event_callback)
while isRun do
local last_price = tonumber(getParamEx(CLASS_CODE,SEC_CODE,"last").param_value)
local lp = GetCell(t_id, 1, 0).value or last_price
if lp < last_price then
Highlight(t_id, 1, 0, SeaGreen, QTABLE_DEFAULT_COLOR,1000)
elseif lp > last_price then
Highlight(t_id, 1, 0, RosyBrown, QTABLE_DEFAULT_COLOR,1000)
end
SetCell(t_id, 1, 0, tostring(last_price), last_price)
sleep(10)
end
end
function CreateTable() -- Функция создает таблицу
t_id = AllocTable()
AddColumn(t_id, 0, "price", true, QTABLE_DOUBLE_TYPE, 15)
tbl = CreateWindow(t_id)
SetWindowPos(t_id, 90, 120, 170, 100)
InsertRow(t_id, 1)
end
function event_callback(t_id, msg, par1, par2)
if (msg==QTABLE_CLOSE) then
isRun = false
end
end
function OnStop()
isRun = false
if t_id~= nil then
DestroyTable(t_id)
end
end
Правильно ли я понимаю, что поле COMMENT при отправке заявки не сохраняется в таблице заявок. Я по крайней мере не вижу его. Получается, что невозможно решить простую задачу поиска своих заявок без промежуточного хранилища.
Да, можно хранить отправленные номера и ID в временной таблице, но иногда происходят ситуации когда происходит перезапуск скрипта и надо перечитать заявки и отобрать нужные по параметрам. Поле BROKERREF не подходит совершенно, т.к. на фондовой секции брокер запрещает писать туда что либо отличное от кода клиента. Ка же так? Приходится сейчас городить внешнюю базу данных, чтобы понять, что эта заявка была выставлена роботом и у нее такие-то праметры.
Получение данных индикатора из скрипта возможно. А обратно?
У меня скрипт считает даные, хранит в таблице. Я хотел бы вывести их как значения индикатора. Т.е. сам индикатор будет пустой, возвращающий nil. А вот скриптом хотелось поставить значения, по примеру функции SetValue.
Спасибо за ссылку. У меня уже была мысль самому написать key-value in memory чтобы в нее писать, а индикатор бы считывал. Этакий буфер обмена. Но разработчикам Квика пора уже заняться поддержкой управления графическими инструментами из скриптов: Трендовые линии, объекты, управление графиками.
Sergey Gorokhov написал: Из обычного Lua скрипта нельзя ставить значения на индикаторах. Это возможно только в коде самого индикатора
Печально. Приходится городить огород - сохранять данные в файл, а считывать индикатором. При этом интерактивности уже никакой. Т.к. невозможно интерактивно, без переприменения индикатора, считать новые данные.
Напрашивается функция SetValue по индентификатору графика.
Получение данных индикатора из скрипта возможно. А обратно?
У меня скрипт считает даные, хранит в таблице. Я хотел бы вывести их как значения индикатора. Т.е. сам индикатор будет пустой, возвращающий nil. А вот скриптом хотелось поставить значения, по примеру функции SetValue.
Кто-нибудь пробовал обращаться к внешним сервисам типа Twitter из qlua? Есть у меня желание добавить себе в скрипт чтение ленты по ключевым словам. Я нашел библиотеки Lua для подключения к тому же Twitter, вопрос только - заработет ли из Квика? Может проще написать того же бота на питоне.
Но вот на тестовом сервере (и на реальном) я получаю не просто один коллбэк.
Вот только что сегодня купил один лот Себрбанка и тут же продал. Получил вот столько коллбэков. Да лимиты разные, но они повторяются. 4 раза лимит 0, 4 раза лимит -3. Отличие в блокировке количества и средств. Но вот во всем этом многообразии только последний будет нужен. Как это отлавливать?
02/21/18 10:45:19; M Transaction BUY 0; --- это купил 02/21/18 10:45:19; OnTransReply 1519199113 (161) Заявка N 3616235401 зарегистрирована. Удовлетворено 1; 02/21/18 10:45:19; Изменения по счету: Код бумаги SBER; 02/21/18 10:45:19; Счет депо NL0011100043; 02/21/18 10:45:19; Код клиента 10118; 02/21/18 10:45:19; Входящий остаток по бумагам 0; 02/21/18 10:45:19; Входящий лимит по бумагам 0; 02/21/18 10:45:19; Текущий остаток по бумагам 0; 02/21/18 10:45:19; Текущий лимит по бумагам 0; 02/21/18 10:45:19; Заблокировано на продажу количества лотов 0; 02/21/18 10:45:19; Заблокированного на покупку количества лотов 1; 02/21/18 10:45:19; Стоимость ценных бумаг, заблокированных под покупку 2900.3; 02/21/18 10:45:19; Стоимость ценных бумаг, заблокированных под продажу 0; 02/21/18 10:45:19; Цена приобретения 0; 02/21/18 10:45:19; Тип лимита 0; 02/21/18 10:45:19; __________; 02/21/18 10:45:19; Изменения по счету: Код бумаги SBER; 02/21/18 10:45:19; Счет депо NL0011100043; 02/21/18 10:45:19; Код клиента 10118; 02/21/18 10:45:19; Входящий остаток по бумагам 0; 02/21/18 10:45:19; Входящий лимит по бумагам 0; 02/21/18 10:45:19; Текущий остаток по бумагам 0; 02/21/18 10:45:19; Текущий лимит по бумагам 0; 02/21/18 10:45:19; Заблокировано на продажу количества лотов 0; 02/21/18 10:45:19; Заблокированного на покупку количества лотов 0; 02/21/18 10:45:19; Стоимость ценных бумаг, заблокированных под покупку 290.03; 02/21/18 10:45:19; Стоимость ценных бумаг, заблокированных под продажу -1e+048; 02/21/18 10:45:19; Цена приобретения 0; 02/21/18 10:45:19; Тип лимита -3; 02/21/18 10:45:19; __________; 02/21/18 10:45:20; Изменения по счету: Код бумаги SBER; 02/21/18 10:45:20; Счет депо NL0011100043; 02/21/18 10:45:20; Код клиента 10118; 02/21/18 10:45:20; Входящий остаток по бумагам 0; 02/21/18 10:45:20; Входящий лимит по бумагам 0; 02/21/18 10:45:20; Текущий остаток по бумагам 0; 02/21/18 10:45:20; Текущий лимит по бумагам 0; 02/21/18 10:45:20; Заблокировано на продажу количества лотов 0; 02/21/18 10:45:20; Заблокированного на покупку количества лотов 0; 02/21/18 10:45:20; Стоимость ценных бумаг, заблокированных под покупку 0; 02/21/18 10:45:20; Стоимость ценных бумаг, заблокированных под продажу 0; 02/21/18 10:45:20; Цена приобретения 0; 02/21/18 10:45:20; Тип лимита 0; 02/21/18 10:45:20; __________; 02/21/18 10:45:20; Изменения по счету: Код бумаги SBER; 02/21/18 10:45:20; Счет депо NL0011100043; 02/21/18 10:45:20; Код клиента 10118; 02/21/18 10:45:20; Входящий остаток по бумагам 0; 02/21/18 10:45:20; Входящий лимит по бумагам 0; 02/21/18 10:45:20; Текущий остаток по бумагам 0; 02/21/18 10:45:20; Текущий лимит по бумагам 0; 02/21/18 10:45:20; Заблокировано на продажу количества лотов 0; 02/21/18 10:45:20; Заблокированного на покупку количества лотов 0; 02/21/18 10:45:20; Стоимость ценных бумаг, заблокированных под покупку 1e+048; 02/21/18 10:45:20; Стоимость ценных бумаг, заблокированных под продажу -1e+048; 02/21/18 10:45:20; Цена приобретения 0; 02/21/18 10:45:20; Тип лимита -3; 02/21/18 10:45:20; __________; 02/21/18 10:45:20; Изменения по счету: Код бумаги SBER; 02/21/18 10:45:20; Счет депо NL0011100043; 02/21/18 10:45:20; Код клиента 10118; 02/21/18 10:45:20; Входящий остаток по бумагам 0; 02/21/18 10:45:20; Входящий лимит по бумагам 0; 02/21/18 10:45:20; Текущий остаток по бумагам 0; 02/21/18 10:45:20; Текущий лимит по бумагам 0; 02/21/18 10:45:20; Заблокировано на продажу количества лотов 0; 02/21/18 10:45:20; Заблокированного на покупку количества лотов 1; 02/21/18 10:45:20; Стоимость ценных бумаг, заблокированных под покупку 2900.3; 02/21/18 10:45:20; Стоимость ценных бумаг, заблокированных под продажу 0; 02/21/18 10:45:20; Цена приобретения 0; 02/21/18 10:45:20; Тип лимита 0; 02/21/18 10:45:20; __________; 02/21/18 10:45:20; Изменения по счету: Код бумаги SBER; 02/21/18 10:45:20; Счет депо NL0011100043; 02/21/18 10:45:20; Код клиента 10118; 02/21/18 10:45:20; Входящий остаток по бумагам 0; 02/21/18 10:45:20; Входящий лимит по бумагам 0; 02/21/18 10:45:20; Текущий остаток по бумагам 0; 02/21/18 10:45:20; Текущий лимит по бумагам 0; 02/21/18 10:45:20; Заблокировано на продажу количества лотов 0; 02/21/18 10:45:20; Заблокированного на покупку количества лотов 0; 02/21/18 10:45:20; Стоимость ценных бумаг, заблокированных под покупку 290.03; 02/21/18 10:45:20; Стоимость ценных бумаг, заблокированных под продажу -1e+048; 02/21/18 10:45:20; Цена приобретения 0; 02/21/18 10:45:20; Тип лимита -3; 02/21/18 10:45:20; __________; 02/21/18 10:45:20; Изменения по счету: Код бумаги SBER; 02/21/18 10:45:20; Счет депо NL0011100043; 02/21/18 10:45:20; Код клиента 10118; 02/21/18 10:45:20; Входящий остаток по бумагам 0; 02/21/18 10:45:20; Входящий лимит по бумагам 0; 02/21/18 10:45:20; Текущий остаток по бумагам 1; 02/21/18 10:45:20; Текущий лимит по бумагам 0; 02/21/18 10:45:20; Заблокировано на продажу количества лотов 0; 02/21/18 10:45:20; Заблокированного на покупку количества лотов 0; 02/21/18 10:45:20; Стоимость ценных бумаг, заблокированных под покупку 0; 02/21/18 10:45:20; Стоимость ценных бумаг, заблокированных под продажу 0; 02/21/18 10:45:20; Цена приобретения 2.6608; 02/21/18 10:45:20; Тип лимита 0; 02/21/18 10:45:20; __________; 02/21/18 10:45:20; Изменения по счету: Код бумаги SBER; 02/21/18 10:45:20; Счет депо NL0011100043; 02/21/18 10:45:20; Код клиента 10118; 02/21/18 10:45:20; Входящий остаток по бумагам 0; 02/21/18 10:45:20; Входящий лимит по бумагам 0; 02/21/18 10:45:20; Текущий остаток по бумагам 0; 02/21/18 10:45:20; Текущий лимит по бумагам 0; 02/21/18 10:45:20; Заблокировано на продажу количества лотов 0; 02/21/18 10:45:20; Заблокированного на покупку количества лотов 0; 02/21/18 10:45:20; Стоимость ценных бумаг, заблокированных под покупку 1e+048; 02/21/18 10:45:20; Стоимость ценных бумаг, заблокированных под продажу -1e+048; 02/21/18 10:45:20; Цена приобретения 0; 02/21/18 10:45:20; Тип лимита -3; 02/21/18 10:45:20; __________;
02/21/18 10:45:30; M Transaction SELL 0; --- это продал 02/21/18 10:45:30; OnTransReply 1519199114 (161) Заявка N 3616235602 зарегистрирована. Удовлетворено 1; 02/21/18 10:45:30; Изменения по счету: Код бумаги SBER; 02/21/18 10:45:30; Счет депо NL0011100043; 02/21/18 10:45:30; Код клиента 10118; 02/21/18 10:45:30; Входящий остаток по бумагам 0; 02/21/18 10:45:30; Входящий лимит по бумагам 0; 02/21/18 10:45:30; Текущий остаток по бумагам 1; 02/21/18 10:45:30; Текущий лимит по бумагам 0; 02/21/18 10:45:30; Заблокировано на продажу количества лотов 1; 02/21/18 10:45:30; Заблокированного на покупку количества лотов 0; 02/21/18 10:45:30; Стоимость ценных бумаг, заблокированных под покупку 0; 02/21/18 10:45:30; Стоимость ценных бумаг, заблокированных под продажу 2659; 02/21/18 10:45:30; Цена приобретения 2.6608; 02/21/18 10:45:30; Тип лимита 0; 02/21/18 10:45:30; __________; 02/21/18 10:45:30; Изменения по счету: Код бумаги SBER; 02/21/18 10:45:30; Счет депо NL0011100043; 02/21/18 10:45:30; Код клиента 10118; 02/21/18 10:45:30; Входящий остаток по бумагам 0; 02/21/18 10:45:30; Входящий лимит по бумагам 0; 02/21/18 10:45:30; Текущий остаток по бумагам 0; 02/21/18 10:45:30; Текущий лимит по бумагам 0; 02/21/18 10:45:30; Заблокировано на продажу количества лотов 0; 02/21/18 10:45:30; Заблокированного на покупку количества лотов 0; 02/21/18 10:45:30; Стоимость ценных бумаг, заблокированных под покупку 1e+048; 02/21/18 10:45:30; Стоимость ценных бумаг, заблокированных под продажу 265.9; 02/21/18 10:45:30; Цена приобретения 0; 02/21/18 10:45:30; Тип лимита -3; 02/21/18 10:45:30; __________; 02/21/18 10:45:31; Изменения по счету: Код бумаги SBER; 02/21/18 10:45:31; Счет депо NL0011100043; 02/21/18 10:45:31; Код клиента 10118; 02/21/18 10:45:31; Входящий остаток по бумагам 0; 02/21/18 10:45:31; Входящий лимит по бумагам 0; 02/21/18 10:45:31; Текущий остаток по бумагам 1; 02/21/18 10:45:31; Текущий лимит по бумагам 0; 02/21/18 10:45:31; Заблокировано на продажу количества лотов 0; 02/21/18 10:45:31; Заблокированного на покупку количества лотов 0; 02/21/18 10:45:31; Стоимость ценных бумаг, заблокированных под покупку 0; 02/21/18 10:45:31; Стоимость ценных бумаг, заблокированных под продажу 0; 02/21/18 10:45:31; Цена приобретения 2.6608; 02/21/18 10:45:31; Тип лимита 0; 02/21/18 10:45:31; __________; 02/21/18 10:45:31; Изменения по счету: Код бумаги SBER; 02/21/18 10:45:31; Счет депо NL0011100043; 02/21/18 10:45:31; Код клиента 10118; 02/21/18 10:45:31; Входящий остаток по бумагам 0; 02/21/18 10:45:31; Входящий лимит по бумагам 0; 02/21/18 10:45:31; Текущий остаток по бумагам 0; 02/21/18 10:45:31; Текущий лимит по бумагам 0; 02/21/18 10:45:31; Заблокировано на продажу количества лотов 0; 02/21/18 10:45:31; Заблокированного на покупку количества лотов 0; 02/21/18 10:45:31; Стоимость ценных бумаг, заблокированных под покупку 1e+048; 02/21/18 10:45:31; Стоимость ценных бумаг, заблокированных под продажу -1e+048; 02/21/18 10:45:31; Цена приобретения 0; 02/21/18 10:45:31; Тип лимита -3; 02/21/18 10:45:31; __________; 02/21/18 10:45:31; Изменения по счету: Код бумаги SBER; 02/21/18 10:45:31; Счет депо NL0011100043; 02/21/18 10:45:31; Код клиента 10118; 02/21/18 10:45:31; Входящий остаток по бумагам 0; 02/21/18 10:45:31; Входящий лимит по бумагам 0; 02/21/18 10:45:31; Текущий остаток по бумагам 1; 02/21/18 10:45:31; Текущий лимит по бумагам 0; 02/21/18 10:45:31; Заблокировано на продажу количества лотов 1; 02/21/18 10:45:31; Заблокированного на покупку количества лотов 0; 02/21/18 10:45:31; Стоимость ценных бумаг, заблокированных под покупку 0; 02/21/18 10:45:31; Стоимость ценных бумаг, заблокированных под продажу 2659; 02/21/18 10:45:31; Цена приобретения 2.6608; 02/21/18 10:45:31; Тип лимита 0; 02/21/18 10:45:31; __________; 02/21/18 10:45:31; Изменения по счету: Код бумаги SBER; 02/21/18 10:45:31; Счет депо NL0011100043; 02/21/18 10:45:31; Код клиента 10118; 02/21/18 10:45:31; Входящий остаток по бумагам 0; 02/21/18 10:45:31; Входящий лимит по бумагам 0; 02/21/18 10:45:31; Текущий остаток по бумагам 0; 02/21/18 10:45:31; Текущий лимит по бумагам 0; 02/21/18 10:45:31; Заблокировано на продажу количества лотов 0; 02/21/18 10:45:31; Заблокированного на покупку количества лотов 0; 02/21/18 10:45:31; Стоимость ценных бумаг, заблокированных под покупку 1e+048; 02/21/18 10:45:31; Стоимость ценных бумаг, заблокированных под продажу 265.9; 02/21/18 10:45:31; Цена приобретения 0; 02/21/18 10:45:31; Тип лимита -3; 02/21/18 10:45:31; __________; 02/21/18 10:45:31; Изменения по счету: Код бумаги SBER; 02/21/18 10:45:31; Счет депо NL0011100043; 02/21/18 10:45:31; Код клиента 10118; 02/21/18 10:45:31; Входящий остаток по бумагам 0; 02/21/18 10:45:31; Входящий лимит по бумагам 0; 02/21/18 10:45:31; Текущий остаток по бумагам 0; 02/21/18 10:45:31; Текущий лимит по бумагам 0; 02/21/18 10:45:31; Заблокировано на продажу количества лотов 0; 02/21/18 10:45:31; Заблокированного на покупку количества лотов 0; 02/21/18 10:45:31; Стоимость ценных бумаг, заблокированных под покупку 0; 02/21/18 10:45:31; Стоимость ценных бумаг, заблокированных под продажу 0; 02/21/18 10:45:31; Цена приобретения 0; 02/21/18 10:45:31; Тип лимита 0; 02/21/18 10:45:31; __________; 02/21/18 10:45:31; Изменения по счету: Код бумаги SBER; 02/21/18 10:45:31; Счет депо NL0011100043; 02/21/18 10:45:31; Код клиента 10118; 02/21/18 10:45:31; Входящий остаток по бумагам 0; 02/21/18 10:45:31; Входящий лимит по бумагам 0; 02/21/18 10:45:31; Текущий остаток по бумагам 0; 02/21/18 10:45:31; Текущий лимит по бумагам 0; 02/21/18 10:45:31; Заблокировано на продажу количества лотов 0; 02/21/18 10:45:31; Заблокированного на покупку количества лотов 0; 02/21/18 10:45:31; Стоимость ценных бумаг, заблокированных под покупку 1e+048; 02/21/18 10:45:31; Стоимость ценных бумаг, заблокированных под продажу -1e+048; 02/21/18 10:45:31; Цена приобретения 0; 02/21/18 10:45:31; Тип лимита -3; 02/21/18 10:45:31; __________;
Проверил еще раз. На фондовой секции приходит OnTransReply. Вопрос снимается. Это уже вопрос организации алгоритма как обрабатывать событие.
Цитата
Sergey Gorokhov написал: Больше интересует вопрос что именно "работает"? Т.е. заявка по факту ставится или нет? В качестве примера, сообщите точное время (по МСК) когда была попытка выставить такую заявку.
Если пишем систему в реальном времени, то функция main должна просто что-то инициализировать и все. Далее все должно выполняться в коллбэках. Если их нет, то и нечего анализировать получается. Пришла свечка - отвечаем на событие, решили, что надо сделать транзакцию, отправили ее. Ждем ответа о ее завершении.
А вот в функции main, видимо, надо как раз анализировать ситуации когда ответа нет. Скажем, нет ответа на транзакцию, значит перебери ордера, чтобы понять, может она прошла. Видимо, так. Я пока не все еще продумал, т.к. не очень знаком с организацие вызовов в qlua, но, наверно, есть ситуации неуловимые коллбэками.
А вот если система не реального времени, а по расписанию, то, как я понимаю, все надо реализовывать в бесконечном цикле main. Скажем, цикл, перебирающий список бумаг каждые 15 минут и рассчитывающий что-то. Правда в этом месте возникает вопрос, а нельзя ли при инициализации скрипта назначить один и тот же коллбэк на получение данных разных инструментов, разных интервалов? Тогда и здесь можно было бы все в этом одном коллбэке делать не утилизируя функцию main. Судя по описанию нельзя. Т.е. я вынужден каждые 15 минут заново перибирать список инструментов, получать данные, считать. А если бы в коллбэк приходил не только индекс, но признак чей это индекс, то можно было бы сохранив ранее DS каждого инструмента, отреагировать именно на него.
Николай Камынин написал: можно попробовать так. ============================= в main ставите однократную подписку на данные: if DS==nil then DS = CreateDataSource(CLASS_CODE, SEC_CODE, INTERVAL) end ============================== там, где используете эти данные ставите условие: if DS and DS:Size() ~= 0 then -- обработка данных end ------------------------ При этом нет надобности в каких-либо задержках, все будет работать без тормозов.
У меня при инициализации происходит проверка на количество. Если пусто, то идет заказ данных.
А у уже в main идет обработка данных. Там я тоже поставил на проверку, но уже без задержек, т.к. данные не приходят, сразу. Возможно перезаказывать бессмысленно, а надо просто ждать.
Полагаю, что у Вас неправильное представление о работе с колбеками. При использовании колбеков нет надобности ждать. Колбеки для этого и создаются. Т е все события у нас асинхронные, поэтому их не надо ждать, а надо на них реагировать. Если событий нет, то система бездельничает и ничего не ждет, так как нам заранее неизвесно когда и какое событие будет. Подумайте над этим и смените логику скриптов. -------------------------- В качестве совета. Не надо делать кучу скриптов, пишите свои торговые стратегии в одном, так как все колбеки вызываются последовательно и им передается одно и тоже, то нет смысла множить копии колбеков в разных скриптах.
Добрый день. Списибо за ответ.
Как работет асинхронный коллбэк в других языках мне знакомо. Я посмотрел примеры написания скриптов. Там я увидел такого рода ожидания. Что меня смутило, но они сплошь и рядом.
Да, конечно, предсказать когда придет ответ невозможно. Тем более, что сервер может быть загружен.
У меня в данном случае возникает вопрос по логике работы функции main. Скажем я выставил заявку, далее я должен отреагировать на ее выполнение. Т.к. я ограничен потоком функции main, там у меня бесконечный цикл. Если я его прерву, то прервется скрипт. Получается мне надо именно в функии main делать отдельную проверку прихода колбэка или некой переменной записанной в коллбэк. Не важно где написана обработка коллбэка. Именно из-за этого бесконечного потока логика скрипта становится несколько извращенной.
Если я правильно понимаю, более менее правильный вариант - это в функции main делать проверку, если она не пришла, направлять код на очередныю итерацию, пока не придет ответ. Правда придется все же ограничивать время такого ожидания, т.к. можно проверять бесконечно.
Если я уберу if, то у меня будет задержка на каждой бумге. У меня код перебирает бумаги в цикле. Также и ожидание до 15 секунд несколько неприемлимо, т.к. все зависнет.
Хотелось бы при инициализации скрипта проверить на наличие данных, поставить заказ оных, если нет и уже идти по данным.
Проверьте в таблице транзакций терминала QUIK нет ли ошибки при отправке транзакций. Дело в том что рыночные заявки на покупку могут быть запрещены. Если так то в таблице транзакций Вы увидите сообщение об этом. Сообщите Ваш UID чтобы мы могли проверить права.
Добрый день. ID U0120866
Не уверен, что есть ошибки, т.к. если убрать обработку ожидания while trans_Status == nil do sleep(1) end, то все работает. Получается, что если ждать когда придет OnTransReply - зависает скрипт, т.к. ответа нет. Убираю ожидание все проходит без ошибок.
Как я и говорил выше, на срочной сеции этот же код работает нормально.
Есть тестовый сервере (подключал тестовый период через заявку на доступ к учебному серверу QUIK компании ARQA Technologies сроком на один месяц). Т.е. это не брокер, как я понимаю.
Проблема в том, что на фондовой секции, заявки типа BUY по рынку (price = 0) не вызывают OnTransReply. Те же заявки на SELLнормально возвращают колбек.
Еще проблема в очень долгом появлении отправленных заявок в таблице заявок и сделок. Отлаживать алгоритм становится невозможным.
Падения не должно происходить. приведите полный код скрипта индикатора и сообщите версию терминала QUIK
Версия 7.6.1.1 (Сбербанк выше не дает).
Собственно весь код работы с метками такой и есть
Код
function OnCalculate(index)
if index == 1 and Settings.ChartId ~= '' then
DelAllLabels(Settings.ChartId)
AddedLabels = {}
end
if index == 1 then
DSInfo = getDataSourceInfo()
min_price_step = getParamEx(DSInfo.class_code, DSInfo.sec_code, "SEC_PRICE_STEP").param_value
end
return myFunc(index, Settings, 37)
end
Внутри функции расчета данных выводится (обновляется) метка
Код
if AddedLabels[1] ~= nil then
SetLabelParams(Settings.ChartId, AddedLabels[1], label)
else
local LabelID = AddLabel(Settings.ChartId, label)
if LabelID ~=nil and LabelID ~= -1 then
AddedLabels[1] = LabelID
end
end
Код
if AddedLabels[2] ~= nil then
SetLabelParams(Settings.ChartId, AddedLabels[2], label)
else
local LabelID = AddLabel(Settings.ChartId, label)
if LabelID ~=nil and LabelID ~= -1 then
AddedLabels[2] = LabelID
end
end
Падение происходит не каждый раз. Иногда на третий раз применения параметров. Иногда на первый.
Sergey Gorokhov написал: Здравствуйте, Вы можете выводить текст через механизм меток. По другому возможности нет.
Хорошо. Вывел метки индикатором.
Но у меня падает Квик при изменении настроек индикатора. При смене инструмента в привязанном окне падения не происходит, а при нажатии ОК в окне редактрирования, да.
Возникает вопрос - какой метод удаления меток правильный.
У меня падение происходит после добавления такого кода в OnCalculate:
Код
if index == 1 and Settings.ChartId ~= '' then
DelAllLabels(Settings.ChartId)
AddedLabels = {}
end
Также добавлена процедура:
Код
function OnDestroy()
if Settings.ChartId ~= '' then
DelAllLabels(Settings.ChartId)
AddedLabels = {}
end
end
А такое банальное действо как вывод текста в рамках индикатора недоступно? Простой пример - текущий ATR. Я не хочу выводить линию или что-то еще. Нужно вывести просто текст.
Добавление меткаи есть в скрипте, а в индикаторе? Так много информации надо выводить в рамках индикаора, где нет проблемы идентификации окна. Я в WLab писал индиктор зиг-заг с выводом процентов каждого движения и поиска моделей. Пости все было текстом в виде меток над свечками. Линий минимум.