Нужные функции

Здесь буду выкладывать функции, которые могут пригодиться:

math_round() -- Округляет число до указанной точности
GetServerDateTime() -- Возвращает текущую дату/время сервера в виде таблицы datetime
StrToTime() -- Приводит время из строкового формата ЧЧ:ММ к формату datetime
CheckDemo() -- Узнать является ли терминал демо от компании Arqa, или демо брокера Открытие
GetTotalnet() -- Получает текущую чистую позицию по инструменту
GetEffectivePosPrice() -- Получает эффективную цену позиции по инструменту
GetCorrectPrice() -- Приводит переданную цену к требуемому для транзакции по инструменту виду
GetPriceForMarketOrder() -- Возвращает корректную цену для рыночной заявки по текущему инструменту
SetOrder() -- Выставляет обычную лимитную заявку
SetMarketOrder() -- Выставляет рыночную (по сути) заявку
CheckOrder() -- Проверяет наличие в системе заявки с определенным ID транзакции
GetOrderNum() -- Возвращает номер заявки по ее ID транзакции
WaitOrderComplete () -- Ожидает исполнения заявки по ID транзакции
Set_SL() -- Выставляет 'Стоп лимит' заявку
SetTP() -- Выставляет 'Тейк профит' заявку
SetTP_SL() -- Выставляет 'Тейк профит и Стоп лимит' заявку
CheckStopOrder() -- Проверяет наличие в системе стоп-заявки с определенным ID транзакции
GetStopOrderNum() -- Возвращает номер стоп-заявки по ее ID транзакции
CheckStopOrderActive() -- Проверяет по номеру активна ли стоп-заявка
Kill_SO() -- Снимает стоп-заявку
StackFIFO() -- Создает объект стека FIFO(Первым вошел, первым вышел)

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

Нужные функции: 70 комментариев

  1. 1
    
    getClassInfo('SPBFUT').name

    - эта строка на демо от Арка выдает МБ Срочный рынок: Фьючерсы,
    а на реальных счетах разных брокеров не может быть такой же строки случайно?

      1. Я понял, вопрос в том что на реальном счете у кого нибудь может быть точно такая же строчка?
        Суть вопроса в том что мне железобетонно надо идентифицировать демо счет Арки от реального, может другой есть способ?

                    1. Я в info.chm ее нашел, не работает она что ли? Так IP то же не прочитать. Ну вроде как получается через акции тогда делать что ли
                      LUA]message(tostring(getClassInfo('QJSIM').name)) - Акции 1-го уровня (эмулятор). На реале то эмулятор уж точно не будет - наверно

                    1. Ага понял что через акции лучше, надежнее. Да, но функция которая выводит IP в Lua то же ведь должна быть - щас поищу

                    2. STRING getInfoParam (STRING param_name)
                      ой блин - щас вообще удалю эту info

                    3. 1
                      
                      message(tostring(getInfoParam("SERVER")))

                      - Информационно-торговая система ARQA. Это уж ни с чем не перепутать.

                    1. Ладно восстановил. Вот когда возникает определенная задача, то туда иду смотрю ищу - а так все изучать, запоминать не охота.

  2. Здравствуйте. Подскажите как сделать так чтобы при выполнении условия (например нужная цена) выставилась стоп-заявка в одном количестве? А у меня получается что при наступлении выставляется стоп заявки одна за одной.

      1. Этот вопрос относится не к QLua, в частности, а к программированию, в целом, Вам нужно поучиться программировать алгоритмы, научиться объяснять компьютеру на ему понятном языке что Вы от него хотите. Оставьте на время заявки со стоп-заявками, а поучитесь основам, циклам, условным операторам (раздел меню слева "QLua(Lua) основы"). Попробуйте посчитать в цикле сумму чисел от 1 до 10 и вывести после этого результат в message(). Если хотите, то я могу с Вами лично по Skype позаниматься, стоит относительно недорого, а времени себе уйму сэкономите и сможете потом все, что угодно запрограммировать.

  3. Подскажите как сделать правильно. Если пишу вот так, то заявка отправляется:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    
    t = {
       ["CLASSCODE"]="SPBFUT",
       ["SECCODE"]="SRU7",
       ["ACTION"]="NEW_ORDER",
       ["ACCOUNT"]=ACCOUNT,
       ["TYPE"]="M",
       ["OPERATION"]=OPERATION,
       ["QUANTITY"]=QUANTITY,
       ["PRICE"]="0",
       ["TRANS_ID"]="1"
    }
    sendTransaction(t)

    А если через функцию, то пишет " unexpected symbol near '='". Если во всех полях проставить ==, заявка все равно не будет выставляться:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    
    function Trade()
       local t = {
          ["CLASSCODE"]="SPBFUT",
          ["SECCODE"]="SRU7",
          ["ACTION"]="NEW_ORDER",
          ["ACCOUNT"]=ACCOUNT,      
          ["TYPE"]="M",
          ["OPERATION"]=OPERATION,
          ["QUANTITY"]=QUANTITY,
          ["PRICE"]="0",
          ["TRANS_ID"]="1"
       }
       sendTransaction(t)
    end

    Тоже самое со стопом и т.п.

        1. знак == используется при проверке на равенство, например:

          1
          2
          3
          4
          5
          6
          7
          8
          9
          10
          11
          
          A = 10   -- Присваиваем переменной A значение 10
          B = 10   -- Присваиваем переменной B значение 10
          -- ЕСЛИ A равно B ТО
          if A == B then
             -- Выводим сообщение
             message('A равно B')
          -- ИНАЧЕ
          else
             -- Выводим сообщение
             message('A не равно B')
          end

          Вам же нужно присвоить значение полям таблицы t, по этому, знак == использовать здесь некорректно.
          Покажите весь свой скрипт, у Вас просто ошибка какая-то синтаксическая, возможно блок какой-то не закрыт перед тем, как Вы функцию объявили. В общем, скорее всего, в понимании основ программирования у Вас где-то недоработка.

    1. Дмитрий , здравствуйте
      Подскажите пожалуйста
      В главном коде должно выполниться условие выполнение транзакции при наступлении условия :

      if A>B then send_order(operation, qty, price) , где send_order(operation, qty, price)- отправка транзакции

      Чтобы протестировать это условие, вывел эту часть кода в отдельный скрипт:

      Account = "NL0011100043" -- торговый счет
      Class_Code = "QJSIM" -- класс торгуемого инструмента
      Sec_Code = "MTSS"
      operation="S"
      qty="3"
      price="0"

      local send_order (operation, qty, price)
      function send_order(operation, qty, price)
      trans_id=trans_id+1
      T = {}
      T['TRANS_ID'] = tostring(trans_id) -- Номер транзакции
      T['ACCOUNT'] = Account -- Код счета
      T['CLASSCODE'] = Class_Code -- Код класса
      T['SECCODE'] = Sec_Code -- Код инструмента
      T['ACTION'] = "NEW_ORDER" -- Тип транзакции ('NEW_ORDER' - новая заявка)
      T['TYPE'] = "M" -- Тип ('L' - лимитированная, 'M' - рыночная)
      T['OPERATION'] = operation -- Операция ('B' - buy, или 'S' - sell)
      T['PRICE'] = price -- Цена
      T['QUANTITY'] = tostring(qty) -- Количество

      local res = sendTransaction(T)
      if string.len(res) ~= 0 then
      message('Error: '..res,3)
      return 0
      else
      return trans_id
      end
      end

      При запуске выводит ошибку:
      QUIK_VTB24\отправказаявки.lua:9: ')' expected near ','

      Подскажите пожалуйста как поправить .
      спасибо

      1. Здравствуйте! В тексте ошибки написано, что ожидается скобка рядом запятой в 9 строке. Вот такая строка вообще не имеет смысла: local send_order (operation, qty, price)
        Могу посоветовать Вам вот это https://quikluacsharp.ru/bez-rubriki/skype-obuchenie-programmirovaniyu-individualnoe/
        Потратить час на теорию, чтобы не совершать синтаксических ошибок, а писать код осознанно, если не согласны, то объясните что делает вот эта строка в Вашем коде:
        local send_order (operation, qty, price)

        1. Добрый вечер, Дмитрий
          согласен с Вами, что пытаемся самостоятельно чего то слепить, отрывками информация в интернете.
          Логика была такая:
          если выполняется условие, то ссылка на функцию, отвечающую за исполнение транзакции
          видимо чего то не так понял
          копаюсь потихоньку.
          спасибо, что не оставили без ответа)))

          1. Найдите ответы на следующие вопросы:
            Что такое переменные?
            Каких типов бывают?
            Как создаются (объявляются) ?
            Как, где и для чего применяются?

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

  4. Есть в роботе вот такая строка -

    1
    
     local Scale = tonumber(getSecurityInfo("SPBFUT", Fut).scale) -- Точность цены по инструменту

    - робот остается включенным до утра. В 9-05 МСК отключается из-за ошибки. Ругается именно на эту строку - пишет что то типа - попытка индексировать nil.

      1. Привет, рад тебя видеть, пробовал 3 дня по разному - зашел в тупик - ну вот спросил - ладно попробую в понедельник с другой темой - Спасибо. Нефть осваиваю.

        1. А так то проверял, всякие проверки делал - ну на nil то самая надежная наверное, к "гадалке не ходи" мозг я себе вынес так то, в очередной раз спасибо.

            1. 1
              
              CommFut = RtS(Comm_Fut * PS / SP)

              - я обратился к функции

              1
              2
              3
              4
              5
              6
              7
              8
              
              function RtS(price) -- Функция округляет значение price до шага цены инструмента
                 if getSecurityInfo("SPBFUT", Fut) ~= nil then
                    local Scale = tonumber(getSecurityInfo("SPBFUT", Fut).scale) -- Точность цены по инструменту
                    price = Round(price, Scale) -- Округляет число до необходимого количества знаков после запятой
                    price = Round(price / PS) * PS -- Корректирует на соответствие шагу цены
                    return price -- Возвращает результат
                 end
              end

              Вопрос, если в момент обращения в 9-05 МСК данных нет, значит CommFut присвоят nil или ни чего не произойдет?

                    1. ага проверил == nil, спасибо за наводку дальше сам, не сталкивался раньше, по этому и спрашиваю - вроде не сильно тебя нагрузил - Спасибо - с меня "магарыч" чуть позже.

  5. добрый вечер.
    в таблице состояние счета есть кнопка "закрыть все " закрывает позиции +снемает все стоп заявки.
    в Quik Lua есть что то подобное ?

  6. sCreator вообще, все что вы пишете на Луа в квик - квик уже 1 раз посчитал у себя на сервере, и поменял что нужно и послал в клиентское место, где опять сделал все то-же самое - распарсил байт-код в циферьки и букавки второй раз и отдал в QLua-машину, где вы начинаете считать уже по 3-му разу.
    И реализация типа "событийной модели" в квик отсутствует напрочь, кто-бы что ни говорил - ее нет. Квик получает пакет, а в ваш код отдает этот пакет построчно типа события идут, а они уже давным давно прошли - минус время, а если пакет толстый - то просто жесть. Вот отсюда и беруться 60-600 - пакет тоньше - толще до 1,8 секунды доходило (14 км от ЦОД мой ПК стоит - расстояние - что в метре что в 14 км - не играет роли никакой)

      1. QLUA.chm:
        "bit.test
        Функция проверяет состояние указанного бита в значении. Возвращает true, если бит равен «1», и false, если бит равен «0».
        BOOLEAN bit.test(NUMBER х, NUMBER n)
        где:
        х – значение;
        n – номер бита. Нумерация битов начинается с «0»."

        1. Ах вон что))
          А вы используете битовые флаги у себя в коде? Это дешевле, чем bolean (4 бита) и уж тем более дешевле, чем использование циферки или букавки (8 бит) в качестве флага. Только для квиК этот прирост по времени ничего не даст, потому как "не думай о секундах с высока..." и смело можно пользоваться и буковками и циферьками (даже целыми предложениями) в качестве установки своих флагов а не биты. Скорости все равно не прибавится. У меня все скрипты считают 1 раз в 1мс и чуть меньше 1 мс за итерацию цикла, а заявка на биржу попадает через 60 - 600 мс и толку от скорости расчета - никакой. Надеюсь, объяснил.

          1. А Вы смотрели что делает предложенная в разделе функция CheckBit() (смотрите 2 функцию с верху) которая повторяет функционал квиковской функциии bit.test
            или Вы вероятно именно ей проверяете флаги сделок (trade.flags) чтобы не экономить на битах?

            1. Я не использую функцию CheckBit() предложенную здесь - она медленная. Под конкретную таблицу сделана своя функция проверки флага, как-то статус заявки или операция обезличенной сделки.
              На второй пост - а я вас и не смешу. Время батенька - линейно, а не то, что вы там себе придумали. А в целях сэкономить память на битовых флагах - не смешите у вас 512 мб памяти стоит на ПК? Я вас умоляю...
              В квик - не целесообразно - раньше не было ни побитовых операций ни битовых флагов, и все работало прекрасно и по шустрее, чем сейчас. Если вы про экономию места в пакетах данных - да бросьте вы, никакого выигрыша от использования битовых флагов существенного нет, вернее - вообще нет. Какой-то идиот попросил Арку сделать, а они не поленились.
              А вот если вы используете битовый флаг для проверки своих условий - то прирост по времени будет, но тоже не существенный.

              1. Я прошу прощения, но я не говорил что я использую битовые флаги у себя. Вы высказали это предположение и доказываете мне прописные истины.
                Вернемся к первому моему вопросу.(расшифрую его подробнее)
                Среди предложенных здесь функций есть (вторая) функция CheckBit основанная на квиковской функции bit.band.
                Смена объявления функции на

                1
                2
                
                -- Функция проверяет установлен бит, или нет (возвращает true, или false)
                CheckBit = bit.test

                не изменит ее функционал. а проще вообще вместо нее использовать

                1
                
                bit.test(flags, _bit)

                И мой вопрос:
                в чем подвох, что не так с bit.test ?

                1. Подвоха нет никакого, возможно, вы имели в виду, что она выполняет те же действия что и функция из Qlua?
                  Если так, то CheckBit была написана раньше, чем появилась bit.test.
                  И они далеко не равны по своим действиям.

                  Если вы имели ввиду именно то, что вы написали - а написали вы переопределение bid.test в CheckBit:
                  CheckBit = bit.test, то разницы при вызове вашей CheckBit() и квиковской bit.test() не будет никакой и прироста по времени тоже никакого. Если цель переопределить функцию bit.test() все таки стоит с целью ускорения ее вызова, то сделать нужно так:
                  local CheckBit = bit.test
                  и далее спокойно пользоваться "ускоренной" CheckBit, которая ничем не будет отличатся от bit.test, только ускоренным доступом, потому как скорость доступа к локальным переменным в Луа быстрее, нежели к глобальным.
                  Без обид, правильно заданный вопрос 99,99% случаев быстрый и точный ответ. Не нужно думать что тут все телепаты)))

                  1. Спасибо за обстоятельный ответ. Я тоже уже для себя предположил что bit. test дописали потом.
                    Вы упомянули пугающую цифру 60 - 600 мс. Не поделитесь, такие колебания зависят от чего? Сервер, канал, клиент, луа? Активности торгов на бирже?

                    1. Нет дело не в Луа, Луа написан на чистом С и работает быстрее, чем C#. Ограниченный функционал - это да, это минус. Я повыше писал в цикле while is_run do sleep(1) end расчет торговой математики <<1мс.
                      Раньше у меня были боты на QPILE - беда в том, что он считал 1 раз в секунду, но и это я обошел, нагрузив 1 ядро на 100% бесконечным циклом. И скорость была 30-40 мс, чего вполне хватало.
                      Года 3-4 назад - моя заявка была первой, потом все остальные (и этот алгоритм до сих пор жив и зарабатывает). Потом биржа сказала - "ПостТрейдКонтроль!!!" и обязала брокеров его сделать, а это как раз, очень долгая функция. С другой стороны - на QPILE раза 3 - робот умудрялся купить в 2-3 раза больше, чем есть денег с маржой.
                      ПО брокера не успевало пересчитать лимиты.
                      Раньше я мучил провайдера, если вдруг пинг до сервера брокера был больше 1 мс. Протянул оптику до ПК, купил материнку с позолоченными контактами, короче вложился как следует. Скорость подросла до 20 мс от сигнала до заявки на бирже, а с этим пост-трейд-контролем все стало через ...опу.
                      Сейчас квик использую для просмотра сделок, ну и голосовой бот у меня сделан и говорит, профит или убыток, а торговый алгоритм - на C# перенес в ко-локацию(никогда не делайте! хфт на С# только С++ кроссплатформенный).
                      3 месяца тестов 4 - 20 мс через АСТС, сегодня еще "шаманил" - хочу завтра 1 мс выжать стабильно.
                      Винда - враг хфт №1, не даст наверное, придется свой сервак на Линуксе ставить в ко-локацию, потому как у брокера нету Линукса и вряд ли будет. Но пока и так хватит.

                    2. kalikazandr спасибо большое, есть над чем подумать.

  7. Все функции для округления цен до нужного шага цены сводятся в одну, вот так:
    function doStep (val, step)
    return math.floor(val/step + 0.5) * step
    end
    где step = getParamEx(CLASS_CODE, SEC_CODE, "SEC_PRICE_STEP").param_value)
    Можно применять для округления времени в формате POSIX, до текущего таймфрейма, H60 включительно,
    все, что выше H60 корректно округлятся не будет.