Nikolay (Все сообщения пользователя)

Выбрать дату в календареВыбрать дату в календаре

Страницы: Пред. 1 ... 9 10 11 12 13 14 15 16 17 18 19
Проработка стратегии на виртуальной торговле, Формирование стратегии, виртуальная торговля
 
На нашем рынке, данный виртуальный режим реализован в TigerTrade и SBPro. Второй правда только на срочном рынке, но думаю, что в основном это и надо только на срочке. Данные платформы имеют демо, где можно все посмотреть.

Реализация данного режима - это запуск экземпляра приложения с последовательным чтением данных из истории (не только сохраненной, но и загрузка с сервера). Что важно, реализовано это все с поддержкой склейки контрактов. Также важно, что даные режимы для ручной торговли. Т.е. сделки на истории вы будете совершать руками.

Я для себя сделал робот с возможностью вирутальной торговли, который позволяет совершать сделки, ориентируясь на текущий стакан. Что, естественно, имеет некие допущения, т.к. при вирутальной торговле объем из стакана не исчезает. Поэтому можно говорить, что данное мое решение допустимо рассматривать только для малых объемов.

А для истории написан тестер алгоритмов. Сделать в Квике ручную торговлю на истории пока невозможно, но, с дургой стороны, это не такой уж большой недостаток получается, если можно симулироать торговлю в реале.

Единственное замечание - я не очень верю в торговлю по инерционным индикаторам, поэтому решение по написанию конструктора стратегии псевдоязыком (что реализовано в MT5, WealthLab и др.) видится сомнительным занятием. Но здесь, как говориться, вопрос про деньги. Если бы платформа Квик была платной для конечного пользователя, то возможно можно  бы реализовать такую функциональность для завлечения новых "инвесторов", заявив, что теперь наша платформа позволяет обучаться "трейдингу" и вы легко можете написать своего робота.
Обновление пользовательской таблицы/окна
 
Здесь, скорее всего, проблема скорости выполнения цикла.
У меня есть сложный скрипт, выполняющий много расчетов в main. В нем все работает без задержек. А простейшие скрипты, которые делают мало действий в main, не обнолвяют таблицу. Возможно, идет переполнение стека вызовов обновления окна.

Хотя разработчки выше писали, что проблема не воспроизводится.
Обновление пользовательской таблицы/окна
 
Можешь попробовать найти окно как это делают в автологине
https://smart-lab.ru/blog/444805.php

и подергать окно.

Я плюнул искать причины. Перенес отрисовку части вещей в колбеки, хоть это и не самый лучший вариант.
Динамическое количество линий индикатора
 
А вот сделав такие изменения в цикл вывода строк, все работает.
Код
        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
Динамическое количество линий индикатора
 
Инициализация производится на полные 150 линий

вот же
Код
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
Индекс бара
 
Цитата
Виктория написал:
Перезвоните мне пожалуйста     8(904)628-97-40 Виктория
Добрый день.

Не очень понятно кому адресовано данное сообщение.
Индекс бара
 
Цитата
s_mike@rambler.ru написал:
Можно написать простейший индикатор:

function OnCalculate(indx)
return indx
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
Пришел OnTransReply с пустым brokerref
 
Добрый день.

Правильно ли я понимаю, что поле COMMENT при отправке заявки не сохраняется в таблице заявок. Я по крайней мере не вижу его.
Получается, что невозможно решить простую задачу поиска своих заявок без промежуточного хранилища.

Да, можно хранить отправленные номера и ID в временной таблице, но иногда происходят ситуации когда происходит перезапуск скрипта и надо перечитать заявки и отобрать нужные по параметрам. Поле BROKERREF не подходит совершенно, т.к. на фондовой секции брокер запрещает писать туда что либо отличное от кода клиента. Ка же так? Приходится сейчас городить внешнюю базу данных, чтобы понять, что эта заявка была выставлена роботом и у нее такие-то праметры.
Установка данных индикатора из скрипта
 
Цитата
Алексей Дуванов написал:
Цитата
Nikolay   написал:
Добрый день.

Получение данных индикатора из скрипта возможно. А обратно?

У меня скрипт считает даные, хранит в таблице. Я хотел бы вывести их как значения индикатора. Т.е. сам индикатор будет пустой, возвращающий nil. А вот скриптом хотелось поставить значения, по примеру функции SetValue.
попробуйте прикрутить  https://quik2dde.ru/viewtopic.php?id=61  может поможет?
Спасибо за ссылку. У меня уже была мысль самому написать key-value in memory чтобы в нее писать, а индикатор бы считывал. Этакий буфер обмена.
Но разработчикам Квика пора уже заняться поддержкой управления графическими инструментами из скриптов: Трендовые линии, объекты, управление графиками.  
Установка данных индикатора из скрипта
 
Цитата
Sergey Gorokhov написал:
Из обычного Lua скрипта нельзя ставить значения на индикаторах. Это возможно только в коде самого индикатора
Печально. Приходится городить огород - сохранять данные в файл, а считывать индикатором. При этом интерактивности уже никакой. Т.к. невозможно интерактивно, без переприменения индикатора, считать новые данные.

Напрашивается функция SetValue по индентификатору графика.
Установка данных индикатора из скрипта
 
Добрый день.

Получение данных индикатора из скрипта возможно. А обратно?

У меня скрипт считает даные, хранит в таблице. Я хотел бы вывести их как значения индикатора. Т.е. сам индикатор будет пустой, возвращающий nil. А вот скриптом хотелось поставить значения, по примеру функции SetValue.
Обращение к внешним сервисам
 
Добрый день.

Кто-нибудь пробовал обращаться к внешним сервисам типа Twitter из qlua?
Есть у меня желание добавить себе в скрипт чтение ленты по ключевым словам.
Я нашел библиотеки Lua для подключения к тому же Twitter, вопрос только - заработет ли из Квика?
Может проще написать того же бота на питоне.
Двойное OnDepoLimit, Два раза вызывается функция.
 
Добрый день.

Подниму совсем старое обсуждение.

Но вот на тестовом сервере (и на реальном) я получаю не просто один коллбэк.

Вот только что сегодня купил один лот Себрбанка и тут же продал.
Получил вот столько коллбэков.  Да лимиты разные, но они повторяются. 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 ?
 
Проверил еще раз. На фондовой секции приходит OnTransReply. Вопрос снимается. Это уже вопрос организации алгоритма как обрабатывать событие.
Цитата
Sergey Gorokhov написал:
Больше интересует вопрос что именно "работает"? Т.е. заявка по факту ставится или нет?
В качестве примера, сообщите точное время (по МСК) когда была попытка выставить такую заявку.
Что приходит в OnTransReply ?
 
Сам же себе и отвечу.

Если пишем систему в реальном времени, то функция main должна просто что-то инициализировать и все.
Далее все должно выполняться в коллбэках. Если их нет, то и нечего анализировать получается.
Пришла свечка - отвечаем на событие, решили, что надо сделать транзакцию, отправили ее. Ждем ответа о ее завершении.

А вот в функции main, видимо, надо как раз анализировать ситуации когда ответа нет. Скажем, нет ответа на транзакцию, значит перебери ордера, чтобы понять, может она прошла. Видимо, так. Я пока не все еще продумал, т.к. не очень знаком с организацие вызовов в qlua, но, наверно, есть ситуации неуловимые коллбэками.

А вот если система не реального времени, а по расписанию, то, как я понимаю, все надо реализовывать в бесконечном цикле main.
Скажем, цикл, перебирающий список бумаг каждые 15 минут и рассчитывающий что-то. Правда в этом месте возникает вопрос, а нельзя ли при инициализации скрипта назначить один и тот же коллбэк на получение данных разных инструментов, разных интервалов? Тогда и здесь можно было бы все в этом одном коллбэке делать не утилизируя функцию main. Судя по описанию нельзя. Т.е. я вынужден каждые 15 минут заново перибирать список инструментов, получать данные, считать. А если бы в коллбэк приходил не только индекс, но признак чей это индекс, то можно было бы сохранив ранее DS каждого инструмента, отреагировать именно на него.
CreateDataSource, не грузятся данные при формир. через CreateDataSource
 
Цитата
Николай Камынин написал:
можно попробовать так.
=============================
в main ставите однократную подписку на данные:
if DS==nil then    DS = CreateDataSource(CLASS_CODE, SEC_CODE, INTERVAL) end
==============================
там, где используете эти данные ставите условие:
if DS and DS:Size() ~= 0 then
-- обработка данных
end
------------------------
При этом нет надобности в каких-либо задержках, все будет работать без тормозов.

У меня при инициализации происходит проверка на количество. Если пусто, то идет заказ данных.

А у уже в main идет обработка данных. Там я тоже поставил на проверку, но уже без задержек, т.к. данные не приходят, сразу. Возможно перезаказывать бессмысленно, а надо просто ждать.
Что приходит в OnTransReply ?
 
Цитата
Полагаю, что у Вас  неправильное представление о работе с колбеками.
При использовании  колбеков нет надобности ждать.
Колбеки для этого и создаются.
Т е все события у нас асинхронные, поэтому их не надо ждать, а надо на них реагировать.
Если событий нет, то система бездельничает и ничего не ждет, так как нам заранее неизвесно когда и какое событие будет.
Подумайте над этим и смените логику скриптов.
--------------------------
В качестве совета.
Не надо делать кучу скриптов, пишите свои торговые стратегии в одном, так как все колбеки вызываются последовательно и им передается одно и тоже, то нет смысла множить копии колбеков в разных скриптах.
Добрый день. Списибо за ответ.

Как работет асинхронный коллбэк в других языках мне знакомо.
Я посмотрел примеры написания скриптов. Там я увидел такого рода ожидания. Что меня смутило, но они сплошь и рядом.

Да, конечно, предсказать когда придет ответ невозможно. Тем более, что сервер может быть загружен.

У меня в данном случае возникает вопрос по логике работы функции main.
Скажем я выставил заявку, далее я должен отреагировать на ее выполнение. Т.к. я ограничен потоком функции main, там у меня бесконечный цикл.
Если я его прерву, то прервется скрипт. Получается мне надо именно в функии main делать отдельную проверку прихода колбэка или некой переменной записанной в коллбэк. Не важно где написана обработка коллбэка. Именно из-за этого бесконечного потока логика скрипта становится несколько извращенной.

Если я правильно понимаю, более менее правильный вариант - это в функции main делать проверку, если она не пришла, направлять код на очередныю итерацию, пока не придет ответ. Правда придется все же ограничивать время такого ожидания, т.к. можно проверять бесконечно.
CreateDataSource, не грузятся данные при формир. через CreateDataSource
 
Если я уберу if, то у меня будет задержка на каждой бумге. У меня код перебирает бумаги в цикле.
Также и ожидание до 15 секунд несколько неприемлимо, т.к. все зависнет.

Хотелось бы при инициализации скрипта проверить на наличие данных, поставить заказ оных, если нет и уже идти по данным.
Что приходит в OnTransReply ?
 
Цитата
Sergey Gorokhov написал:
Nikolay  ,

Проверьте в таблице транзакций терминала QUIK нет ли ошибки при отправке транзакций.
Дело в том что рыночные заявки на покупку могут быть запрещены.
Если так то в таблице транзакций Вы увидите сообщение об этом.
Сообщите Ваш UID чтобы мы могли проверить права.
Добрый день.
ID U0120866

Не уверен, что есть ошибки, т.к. если убрать обработку ожидания  while trans_Status == nil do sleep(1) end, то все работает.
Получается, что если ждать когда придет OnTransReply - зависает скрипт, т.к. ответа нет.
Убираю ожидание все проходит без ошибок.

Как я и говорил выше, на срочной сеции этот же код работает нормально.
Что приходит в OnTransReply ?
 
Добрый день.

Подниму старую тему.

Есть тестовый сервере (подключал тестовый период через заявку на доступ к учебному серверу QUIK компании ARQA Technologies сроком на один месяц). Т.е. это не брокер, как я понимаю.

Проблема в том, что на фондовой секции, заявки типа BUY по рынку (price = 0) не вызывают OnTransReply. Те же заявки на SELLнормально возвращают колбек.

Еще проблема в очень долгом появлении отправленных заявок в таблице заявок и сделок.
Отлаживать алгоритм становится невозможным.

На срочной секции таких проблем не наблюдается.
CreateDataSource, не грузятся данные при формир. через CreateDataSource
 
Добрый день.

Подниму тему. Тоже столкнулся с пустым набром данных, если не открыт график.
Вызов SetEmptyCallback() и задержка не помогают.

Правда иногда запущу скрипт - данные появились. В другой раз нет. Закономерности нет.

Пробовал увеличить время ожидания sleep до 1000 - все одно не помогает.

Вызов данных типовой:
           
Код
DS = CreateDataSource(CLASS_CODE, SEC_CODE, INTERVAL)
if DS:Size() == 0 then 
  DS:SetEmptyCallback()
  sleep(200)
end
Отметки на графике QUIK средствами QLUA
 
Цитата
Sergey Gorokhov написал:
Nikolay  ,

Падения не должно происходить.
приведите полный код скрипта индикатора и сообщите версию терминала 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

Падение происходит не каждый раз. Иногда на третий раз применения параметров. Иногда на первый.
Отметки на графике QUIK средствами QLUA
 
Цитата
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
Отметки на графике QUIK средствами QLUA
 
Подниму тему.

А такое банальное действо как вывод текста в рамках индикатора недоступно?
Простой пример - текущий ATR. Я не хочу выводить линию или что-то еще. Нужно вывести просто текст.

Добавление меткаи есть в скрипте, а в индикаторе? Так много информации надо выводить в рамках индикаора, где нет проблемы идентификации окна.
Я в WLab писал индиктор зиг-заг с выводом процентов каждого движения и поиска моделей. Пости все было текстом в виде меток над свечками. Линий минимум.

Неужели нет этого?  
Возвращаемые данные для отрисовки индикатора
 
Добрый день.

Пишется индикатор с динамическим количеством линий.
Можно ли вместо данных типа ruturn out1, out2, out3 вернуть массив {}. Соответственно, данные линий - это индексные данные массива.

Уж больно некрасиво приходится делать большое количество переменных с запасом.

Есть еще вариант динамического описания кода. Есть ли в интерпретаторе qlua execute("Текст выполняемого кода")?
Открытие заявки
 
Если уж пошла речь про заявки, то, как мне кажется, самая важная функция отсутствует - ввод стопа одновременно с самой заявкой.
В окне ввода заявки просто добавить раздел стопа. При торговле фьючерсами и другими высокорисковыми инструментами можно попасть на ситуации когда просто не успевашеь ввести стоп. Карман транзакций - это, конечно, хорошо, но почему же не сделать удобно. Как я понимаю, эту возможность просят столько людей и столько времени, что становится несколько неудобно за разработчиков. Я понимаю что монопольное положение на рынке позволяет, но все же...
Вилы Эндрюса, уровни Фибоначчи, веер Ганна.
 
Добрый день.

Очень бы хотелось иметь достаточной простой интрумент как вилы Эндрюса.
Также очень хочется существующие уровни Фибоначчи строить не только горизонтально, но и под любым углом. Тем самым получая наклонные уровни.
А уж для полноты картины - веер Ганна был бы очень кстати.

Спасибо.
INDICATORS.ZIP
 
Цитата
Николай Камынин написал:
Быстрее будет, если вместо поиска свечки назад, просто запоминать индекс последней существующей свечки.
При отсутствии свечки брать сохраненный индекс.
Возможно, но не всегда надо именно прошлую свечку. Часто надо -3, -2. Так что просто запоминать будет та еще конструкция. А эта функция универсальна, получив индекс бери любое значение свечи.

Хотелось бы иметь "железную" функцию получения ближайшей существующей свечи к идексу вниз и вверх.
INDICATORS.ZIP
 
Ме помогли данные конструкции.

Нет свечки, тогда значению массива текущей даем предудыщее значение.
Код
if not CandleExist(index) then
CC[index] = CC[index-1] 
return nil
end

Если надо получить значение пршлой свечки, то сначала находим ближайшую существующую прошлую, через эту функцию
Код
function FindExistCandle(I)
   local out = I
   
   while not CandleExist(out) do
   out = out -1
   end   
   
   return out
 
end
Код
local previous = index-1
      
if not CandleExist(previous) then
   previous = FindExistCandle(previous)
end
      
if C(index) > C(previous) then
Страницы: Пред. 1 ... 9 10 11 12 13 14 15 16 17 18 19
Наверх