Вопрос-ответ

Автор записи: Дмитрий (Admin)
1 звезда2 звезды3 звезды4 звезды5 звезд (Голосов 10, среднее: 4,60 из 5)
Загрузка...
LogoNew
Если Ваш вопрос не имеет отношения к какой-то определенной статье на данном сайте, то, пожалуйста, задавайте его в комментариях здесь.

Добавить комментарий

Вопрос-ответ: 2 409 комментариев

  1. Здравствуйте, помогите разобраться почему код не возвращает ни каких значений и не выводит ошибки. Цель кода, отслеживать и заносить в массив t_Sys состояние процессов. А именно отслеживать касание линии из массива t_Lev. Всего три состояния: 1-коснулись нижней линии, 2 - не коснулись ни какой линии (при этом значении происходит возврат значения массива t_Lev), 3 -коснулись верхней линии.
    Возможно есть более лучший способ реализации, в таком случае прошу подскажите как лучше сделать

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    
     function Init()   f_LEVEL= LEVEL()
       return #Settings.line
    end
     
    function OnCalculate(Index)
    local S2Down, S1Down, L1Up, L2Up = f_LEVEL(Index)
       return S2Down, S1Down, L1Up, L2Up
    end
     
    function LEVEL()
       t_Sys={}
       t_Sys[1]=3
       t_Sys[2]=2
    return function (I)
    local S2Down, S1Down, L1Up, L2Up = nil, nil, nil, nil
     
    if I>2 then
       if t_Sys[#t_Sys]==3 then
          S2Down, S1Down, L1Up, L2Up = nil, nil, nil, nil
    --      t_Sys[#t_Sys+1]=2
       end
     
       if t_Sys[#t_Sys]==2 then --пока касание не произошло
          local t_Lev=LINE(I)
          S2Down, S1Down, L1Up, L2Up = t_Lev[1], t_Lev[2], t_Lev[3], t_Lev[4]
     
          if H(I)>=t_Lev[#t_Lev] then --произошло касание верхней линии
             t_Sys[#t_Sys+1]=3
          end
          if L(I)2 then
    if t_Sys[#t_Sys-1]==3 then
       for i=1, 2 do
          t_Lev[i]=C(I-i)*0.78
          t_Lev[i+2]=C(I-i)*1.22
       end
    end
     
    if t_Sys[#t_Sys-1]==1 then
       for i=1, 2 do
          t_Lev[i]=C(I-i)*0.78
          t_Lev[i+2]=C(I-i)*1.22
       end
    end
     
    if H(I)>=t_Lev[#t_Lev] then  -- здесь сравнение указанно как еще один вариант
    --   t_Sys[#t_Sys+1]=3
    end
    if L(I)<=t_Lev[1] then
    --   t_Sys[#t_Sys+1]=1;
    end
    end
    return t_Lev
    end
      1. Прошу прощения, это моя ошибка. Функция LINE возвращает массив t_Lev со значениями и имеет вид

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        
        function LINE(I)
        local t_Lev={}
        if I>2 then
        if t_Sys[#t_Sys-1]==3 then
           for i=1, 2 do
              t_Lev[i]=C(I-i)*0.78
              t_Lev[i+2]=C(I-i)*1.22
           end
        end
         
        if t_Sys[#t_Sys-1]==1 then
           for i=1, 2 do
              t_Lev[i]=C(I-i)*0.78
              t_Lev[i+2]=C(I-i)*1.22
           end
        end
        end
        return t_Lev
        end

        Переменная I принимает номер свечи и по замыслу программа должна проверять достижение одного из значений массива t_Lev. В данном коде происходит сравнение значение из массива t_Lev с максимальным или минимальным значением на графике Quik. И самое интересное почему это условие выполняется на первых свечах. Возможно я не до конца понимаю логику написания кода, прошу, помогите разобраться где моя ошибка?

        1. Смотрите, я расставил в Вашем коде табуляции, и в нем явно не хватает строк в конце функции LEVEL, Вы точно все выложили здесь?

          1
          2
          3
          4
          5
          6
          7
          8
          9
          10
          11
          12
          13
          14
          15
          16
          17
          18
          19
          20
          21
          22
          23
          24
          25
          26
          27
          28
          29
          30
          31
          32
          33
          34
          35
          36
          37
          38
          39
          40
          41
          42
          43
          44
          45
          46
          47
          48
          49
          50
          51
          52
          53
          54
          55
          56
          57
          58
          59
          60
          61
          62
          63
          64
          65
          66
          67
          68
          69
          70
          71
          72
          73
          74
          75
          76
          
          function Init()
             f_LEVEL= LEVEL()
             return #Settings.line
          end
           
          function OnCalculate(Index)
             local S2Down, S1Down, L1Up, L2Up = f_LEVEL(Index)
             return S2Down, S1Down, L1Up, L2Up
          end
           
          function LEVEL()
             t_Sys={}
             t_Sys[1]=3
             t_Sys[2]=2
             return function (I)
                local S2Down, S1Down, L1Up, L2Up = nil, nil, nil, nil
           
                if I>2 then
                   if t_Sys[#t_Sys]==3 then
                      S2Down, S1Down, L1Up, L2Up = nil, nil, nil, nil
                      -- t_Sys[#t_Sys+1]=2
                   end
           
                   if t_Sys[#t_Sys]==2 then --пока касание не произошло
                      local t_Lev=LINE(I)
                      S2Down, S1Down, L1Up, L2Up = t_Lev[1], t_Lev[2], t_Lev[3], t_Lev[4]
           
                      if H(I)>=t_Lev[#t_Lev] then --произошло касание верхней линии
                         t_Sys[#t_Sys+1]=3
                      end
                      if L(I)2 then
                         if t_Sys[#t_Sys-1]==3 then
                            for i=1, 2 do
                               t_Lev[i]=C(I-i)*0.78
                               t_Lev[i+2]=C(I-i)*1.22
                            end
                         end
           
                         if t_Sys[#t_Sys-1]==1 then
                            for i=1, 2 do
                               t_Lev[i]=C(I-i)*0.78
                               t_Lev[i+2]=C(I-i)*1.22
                            end
                         end
           
                         if H(I)>=t_Lev[#t_Lev] then  -- здесь сравнение указанно как еще один вариант
                         --   t_Sys[#t_Sys+1]=3
                         end
                         if L(I)<=t_Lev[1] then
                         --   t_Sys[#t_Sys+1]=1;
                         end
                      end
                      return t_Lev
                   end
          -- ???
           
           
          function LINE(I)
             local t_Lev={}
             if I>2 then
                if t_Sys[#t_Sys-1]==3 then
                   for i=1, 2 do
                      t_Lev[i]=C(I-i)*0.78
                      t_Lev[i+2]=C(I-i)*1.22
                   end
                end
           
                if t_Sys[#t_Sys-1]==1 then
                   for i=1, 2 do
                      t_Lev[i]=C(I-i)*0.78
                      t_Lev[i+2]=C(I-i)*1.22
                   end
                end
             end
             return t_Lev
          end
          1. Здравствуйте. По всей видимости при вставке мной кода была удалена середина. Действительно не хватает пары end'ов и функция LEVEL() должна возвращать S2Down, S1Down, L1Up, L2Up

  2. Здравствуйте. Если выходит ошибка в lua квик "possible unhandled exception" есть варианты как найти на какой строке. Просто интересно. Я то знаю где исправлял последний раз)

      1. Простой файл луа, без всяких подключаемых библиотек. И именно с описанной выше ошибкой не пишет номер строки. В других случаях пишет номер строки и подсказки.

  3. Здравствуйте!
    Может кто работал с метками. В справочнике QLUA есть функция AddLabel которая принимает таблицу параметров метки. В этой таблице есть параметр:
    TRANSPARENCY DOUBLE Прозрачность метки в процентах. Значение должно быть в промежутке [0; 100]
    Что то я не могу понять за что он отвечает, прозрачность метки он не устанавливает, пробовал разные варианты.
    Это я не могу понять принцип его работы, или данный параметр не работает?

    1. Ну в общем примерно разобрался.
      Этот параметр работает с картинкой, но прозрачной ее не делает все равно. Меняется цвет, при изменении данного параметра, но это не то что я хотел получить. Цель стоит нанести на график информацию, но что бы данная информация имела прозрачность, что бы бары были видны. Даже если установить прозрачность 99, тогда каринка становится цветом почти как фон графика, но бары то все равно под картинкой не видно.

      Хорошо. Тогда будет другой вопрос.
      А вообще возможно ли на языке C++ рисовать на графике?
      Вообще идея такая:
      1. Найти окно Квика
      2. В этом окне найти элементы.
      3. Отыскать среди найденных элементов нужный график
      4. Добавить \ внедрить еще один элемент, в элемент графика.
      Как это сделать программно не спрашиваю, пока не представляю, вопрос в том реально ли вообще такое. Ну допустим bitmap создать на c++ и разместить его на графике Квика.
      Как отыскать именно тот график который нужен, среди всех открытых, это уже потом буду решать...

    2. В общем вопрос отпал сам собой.
      Не нужна оказывается мне прозрачность, всего то нужно было слой с метками переместить и теперь и картинку видно и график на ней сверху расположился, то что я и хотел получить.

  4. Доброй ночи, такой вопрос: при совершении сделки, необходимо получать цену последней сделки (для использования ее в расчетах), но робот успевает взять старую цену, т.е. до обновления в таблице, так вот что нужно сделать добавить время ожидания, ил какую то проверку на то что таблица обновилась? Понимаю что коряво мысли излагаю))) просьба не бросаться тапками)))) Заранее спасибо.

    1. Откуда берете последнюю цену?
      Есть функция OnAllTrade - вызывается терминалом QUIK при получении обезличенной сделки. Это и есть цена последней сделки.
      Но не известно как устроен Ваш робот, Вы пишите "...до обновления в таблице", предполагаю что робот берет последнюю цену из какой то таблицы, а не использует OnAllTrade.
      В таком случае задержка не поможет. Последовательность будет такой:
      1. Начинает выполнятся код Вашего робота.
      2. Робот получает цену из таблицы и выполняет расчет.
      3. Робот завершает вычисление
      4. Квик отправляется обновлять таблицу
      Даже если Вы установите задержку в 100 000 сек, все равно цена не обновится в таблице.
      Скорее всего код робота и квик работают в одном потоке, по этому будет так:
      1. Начинает выполнятся код Вашего робота.
      2. Робот ждет 100 000 сек
      3. Робот получает цену из таблицы и выполняет расчет.
      4. Робот завершает вычисление
      5. Квик отправляется обновлять таблицу
      И как понимаете ни какие проверки тоже не помогут, Квик не пойдет обновлять таблицу, пока Вам робот не закончит вычисление.
      Так что нужно переписать алгоритм так, что бы робот производил вычисление в функции обратного вызова OnAllTrade.
      Тогда выполнение будет таким.
      1. Придет сделка в терминал
      2. Квик вызывает OnAllTrade и передает цену сделки
      3. Робот использует эту цену как цена последней сделки в своих расчетах.
      4. Функция OnAllTrade завершает свое выполнение.
      5. Квик отправляется обновлять таблицы и графики, но роботу это уже не важно, он все посчитал.

      1. Если робот и Квик работают в разных потоках, тогда задержка поможет. Пока робот ждет в одном потоке, квик обновит данные в таблице, находясь в другом потоке. Тогда действительно нужна проверка на то чтобы узнать обновилась ли цена в таблице.

          1. Хм, хотя сейчас alltrade.price и так использую, но после сигнала к сделки, сама сделка проходит по другой цене, а расчет идет по цене сигнала.
            function OnAllTrade(alltrade)
            P = tonumber(alltrade.price)
            if R and D and G then
            sena_bay = tonumber(P) и это неверная цена получается.
            Вот поэтому хотел последнюю цену получать в таблице, вроде бы пробовал через getParamEx(). Точно непомню, под рукой нет той части кода.

            1. А почему решили что цена не верная?
              Одно дело если Вы отправили заявку по цене 20450 на покупку, а сделка прошла по цене 20445. Так это нормально, просто пока заявка шла на биржу, появился продавец, который хотел продать по 20445, вот он Вам и продал, а Вам выгодно, Вы же дешевле купили.
              Вы посмотрите какую цену в заявке указываете, когда ее на рынок отправляете.
              Так же не забывайте что в Квике не совсем реальность находится.
              Сначала сделка происходит на бирже, потом информация об этой сделке приходит брокеру, потом брокер направляет информацию в терминал, а вот только потом терминал вызывает OnAllTrade, робот считает и формирует заявку с ценой XXX отправляет заявку брокеру, брокер отправляет заявку на биржу и биржа ее исполняет, или в очередь ставит, ну или отклоняет, завит от заявки.

      1. Здравствуйте, я ей редко пользуюсь, но подключается, как обычно при помощи require, в ней много разных модулей, например, если Вы хотите работать с модулем luacom, который позволяет взаимодействовать, например с Excel, то самый простой способ, это закинуть саму библиотеку luacom.dll (найти ее перед этим в LuaForWindows установленной) в папку со скриптом, или в корень терминала Quik и использовать ее примерно так в скрипте, еще желательно подключать библиотеку w32, она, вроде бы, на сайте quik2dde есть и оборачивать все вызовы luacom:

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        
        FPath = 'C:\\QuikExport.xlsx'
        Excel = nil
         
        main = function()   
           require('luacom')
           require('w32')
         
           w32.CoInitialize()
         
           Excel = luacom.CreateObject("Excel.Application")
           Excel.Visible = true
         
           Excel.Workbooks:Add()      
           local sheets = Excel.Worksheets
           local sheet = sheets:Add()
           sheet.Cells(1,1).Value2 = 'Какое-то значение'
         
           Excel.Workbooks(1).SaveAs(FPath, FPath) 
         
           Excel.DisplayAlerts = false
           Excel:Quit()
           Excel = nil
         
           w32.CoUninitialize()
        end
  5. Чтобы не быть голословным прилагаю часть кода:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    
    is_run = true
    Div = 1
    function main()
       while is_run do
            if (идет условие) then
                    Tradefunc()    -- вызывается функция выставления рыночной заявки
    	         Sleep(10000)   -- после проведенной транзакции выполнение должно перейти к этой строке и скрипт должен продолжиться, но происходит обрыв видимо до этого места....
           end
           sleep(500)
    end
     
    function Tradefunc()
       transaction = {
       		   ["ACCOUNT"] = Account,
    		   ["CLIENT_CODE"] = Clientcode,
    		   ["ACTION"] = "NEW_ORDER",
      		   ["CLASSCODE"] = Classcode,
    		   ["TYPE"] = "M",
      		   ["SECCODE"] = Seccode,
      		   ["OPERATION"] = Direction,
      		   ["PRICE"] = "0",
      		   ["QUANTITY"] = Quantity,
      		   ["TRANS_ID"] = "1"
    	         }
       for i = 1, Div do        --  цикл нужен для разрыва во времени выставления заявок в 2 сек, но т.к. Div = 1, то транзакция будет одна 
          Transaction = sendTransaction(transaction)
          sleep(2000)
          Tradetimefunc()     -- функция определения торгового времени
          if (Trade_time==false) then    -- если не торговое время, то больше не выставлять заявки
             break
          end
       end
    end
      1. Дмитрий, спасибо большое за обратную связь,
        обнаружил глупую ошибку (в 7 строке прилагаемого кода ошибка в регистре написания sleep).
        Надеюсь, что это решит возникшую проблему, несмотря на то, что компилятор quik не указывал на какие-либо ошибки.
        Обратные функции за исключением onStop() не использую. А все пользовательские функции вызываются из функции main(), соответственно не должны влиять на работоспособность системы quik.

          1. Я ориентируюсь на окно запуска скрипта (внизу есть дополнительное окно с выявленными ошибками выполнения скрипта). Вы, наверное, имеете в виду окно сообщений/оповещений? Она вроде пустая, попробую запустить перед запуском скрипта.

  6. Здравствуйте!
    Подскажите, пожалуйста, почему скрипт перестает работать. Запускаю в квике, все нормально работает, ошибок система никаких не выдает. Но как только открывается транзакция (неважно в каком направлении) , появляется сообщение в квике, что заявка успешно зарегистрирована, и скрипт почему-то останавливается, при этом никаких ошибок нет...
    Может ли это являться свидетельством допущенной ошибки в коде?

    1. Здравствуйте, если никаких ошибок, то это означает что допущена ошибка в логике, скрипт работает пока работает функция main, значит после отправки транзакции внутри функции main больше не остается никаких действий для выполнения, она завершает свою работу, соответственно скрипт тоже останавливается.

      1. Дмитрий,
        В том то и дело, что функция main зациклена, и пока не будет нажата кнопка остановить, скрипт должен работать.
        Единственное, что у меня вызывает сомнения, это то, что после выставления заявки, идет функция sleep() с длительностью в 10 секунд. Проверял, что если запустить простейший код и добавить в него sleep(10000), то квик виснет намертво. Хотя во время работы торгового скрипта, никаких провисаний не замечено, а остановка происходит сразу же после сообщения о выставлении заявки в квике. Складывается ощущение, что выполнение скиипта просто не доходит до функции sleep() и обрывается сразу после выполнения транзакции...

        1. Если sleep() поставить в main, то ничего не будет, а если в какой-нибудь коллбек, типа OnTrade, то квик повиснет на время паузы, все потому, что для функции main выделяется отдельный поток, который работает параллельно с потоком терминала, а все коллбеки работают в том же потоке, что и интерфейс терминала. Можете показать свой скрипт, так быстрее будет найти причину.

  7. здравствуйте
    подскажите как при удалении заявки определить что она не активна и её удалить не удастся, удаляю так
    function delete_order(class_code,sec_code,a_num)
    if a_num=="" then
    return
    end
    t = {
    ["CLASSCODE"]=class_code,
    ["SECCODE"]=sec_code,
    ["ACTION"]="KILL_ORDER",
    ["TRANS_ID"]="1",
    ["ORDER_KEY"]=tostring(a_num)
    }
    local res = sendTransaction(t)
    if res ~= '' then --если ошибка
    file:write(os.date()..'Поля отправляемой транзакции:\n')
    for key,value in pairs(t) do sd_file[i]:write(os.date()..key..':'..tostring(value).."\n")
    end
    file:write(os.date()..'ОШИБКА транзакции при удален заявк: '..res.."\n\n") --проверка что транзакция прошла
    message("Ошибка транзакции при удален заявк: "..res,1)
    file:write(" Выполнилась без ошибок функция delete_order"\n\n")
    end
    return
    end

    терминал пишет что заявку нельзя удалить, как эту ситуацию в программе определить?

      1. этот поиск замедлит работу функции и всего робота, а нельзя ли это проконтролировать через функции обратного вызова, например через OnTransReply или ещё как то?

          1. а как именно в OnTransReply отследить такую ситуацию? я там проверяю tranzakc.status, если он не равен 3 то произошла ошибка, например торговлю остановили, и если таких ошибок произошло несколько то ставлю робота на паузу

            и ещё вопрос :
            Как-то вы отдельно записываете логику программы, блок схема может, или в виде теста, что б через некоторое продолжительное время вспомнить что да как и почему именно так, что б не запутаться и в случаи ошибки быстрее найти причину?

                1. Не знаю что подсказать, ставить робота на паузу не лучший вариант, нужно понять какая конкретно ошибка и принимать меры по ее устранению, отсидеться, авось само пройдет, так себе решение 🙂

                  1. почему на паузу то, ни на какую паузу не ставлю. вот например выставилась заявка или нет я узнаю не через поиск этой заявки в таблице заявок, а через OnOrder. Так же хочу отловить ситуацию когда заявку не возможно снять, т.е. робот отсылает приказ на снятие заявки, далее ждём когда придёт сигнал от OnOrder что заявка снята, но если заявку нельзя снять то сигнал не придёт, вот эту ситуацию и хочу отловить через OnTransReply, но как именно не знаю, вот вас об этом и спрашиваю)

                    1. OnTransReply не вызывается, когда Вы пытаетесь снять неактивную заявку, вот такими простыми тестовыми скриптами такие вещи можно быстро проверять, чтобы не ждать ответа:

                      1
                      2
                      3
                      4
                      5
                      6
                      7
                      8
                      9
                      10
                      11
                      12
                      13
                      14
                      15
                      16
                      17
                      
                      main = function()
                         -- Заполняет структуру для отправки транзакции на снятие заявки
                         local T = {}
                         T['TRANS_ID']           = '1'
                         T['CLASSCODE']          = 'QJSIM'
                         T['SECCODE']            = 'SBER'
                         T['ACTION']             = 'KILL_ORDER'        -- Тип заявки 
                         T['ORDER_KEY']          = '4226141780'      -- Номер заявки, снимаемой из торговой системы
                       
                         -- Отправляет транзакцию
                         local Res = sendTransaction(T)
                         message('Res:'..Res)
                      end 
                       
                      OnTransReply = function(reply)
                         message('OnTransReply')
                      end

                      Следовательно, единственный вариант, это перед попыткой снятия заявки искать ее в таблице и смотреть активна она, или нет