Пример простого торгового движка "Simple Engine" QLua(Lua)

Автор записи: Дмитрий (Admin)
1 звезда2 звезды3 звезды4 звезды5 звезд (Голосов 4, среднее: 5,00 из 5)
Загрузка...

Блоки кода
Данный движок не предоставляет полный функционал для разработки скриптов на QLua(Lua), но показывает на сколько проще и эффективней становится разработка при таком подходе.

В примере движка реализован следующий функционал:

  1. Движок предоставляет одну функцию для выставления лимитированной заявки
    1
    2
    3
    4
    5
    6
    7
    8
    
    SE_SetLimitOrder(
       account,    -- Код счета
       class_code, -- Код класса
       sec_code,   -- Код инструмента
       operation,  -- Операция ('B' - buy, 'S' - sell)
       price,      -- Цена
       qty         -- Количество 
    )
  2. Движок реализует собственные функции обратного вызова, которые можно использовать в скрипте после подключения движка. Чтобы не путаться, все функции и переменные движка имеют префикс "SE_" (от Simple Engine). Вы можете использовать в скрипте только те функции, которые Вам нужны, движок просто не будет вызывать функцию, если ее нет в Вашем скрипте, ошибки это не вызовет.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    
    -- Функция выполняется при каждой итерации цикла while в функции main
    SE_OnMainLoop()
    -- Вызывается движком при ОШИБКЕ отправки ТРАНЗАКЦИИ
    SE_OnTransSendError(trans)
    -- Вызывается движком при ОШИБКЕ выполнения ТРАНЗАКЦИИ
    SE_OnTransExecutionError(trans)
    -- Вызывается движком при успешном ВЫПОЛНЕНИИ ТРАНЗАКЦИИ
    SE_OnTransOK(trans)
    -- Вызывается движком при появлении НОВОЙ ЗАЯВКИ
    SE_OnNewOrder(order)
    -- Вызывается движком при полном, или частичном ИСПОЛНЕНИИ ЗАЯВКИ
    SE_OnExecutionOrder(order)
    -- Вызывается движком при появлении НОВОЙ СДЕЛКИ (у таблицы trade есть поле trans_id, в которое передается ID транзакции)
    SE_OnNewTrade(trade)
    -- Вызывается движком при остановке скрипта
    SE_OnStop()
  3. Движок записывает в соответствующие массивы ответы по транзакциям, заявки и сделки, но не все, а только те, которые появились благодаря транзакциям, отправленным движком, анализирует их и вызывает соответствующие функции обратного вызова (если они определены в скрипте) при наступлении определенного события. Движок удаляет из массивов старые (обработанные) данные, таким образом не засоряя память.
Код движка
В примере ниже специально задействованы все функции обратного вызова реализуемые движком для того, чтобы показать как их использовать. Хотя, для данного примера, хватило бы 4-х функций:
SE_OnMainLoop()
SE_OnTransSendError(trans)
SE_OnTransExecutionError(trans)
SE_OnNewTrade(trade)

При использовании движка, не используйте в своих скриптах следующие стандартные функции QLua:
main()
OnTransReply()
OnOrder()
OnTrade()
OnStop()
потому что они уже используются в движке !

Код примера

Если у Вас появились какие-то вопросы, задайте их в комментариях под статьей !!!

Так же, напишите, пожалуйста, в комментариях свое мнению о таком подходе и нужен ли, по Вашему мнению, полноценный торговый движок для QLua.

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

Чтобы в результате получилось готовое решение, которое каждый из нас мог бы использовать для написания как вспомогательных для торговли скриптов, так и полноценных торговых роботов, тратя время на реализацию в коде своей торговой стратегии, а не на подстраивание под особенности работы терминала QUIK !

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

Пример простого торгового движка "Simple Engine" QLua(Lua): 72 комментария

  1. Привет, иногда при использовании скрипта возникает ошибка, не подскажешь, как локализовать и исправить?
    .\SimpleEngine.lua:73: attempt to index field '?' (a nil value)

    Может это из-за удаления элемента массива внутри цикла?
    81 table.sremove(SE_Trades, i)

    1. Добрый день, да, там нужно по такой схеме делать:

      1
      2
      3
      4
      5
      
      local offset = 0
      for i = 1,#SE_TasksStack do
         table.sremove(SE_TasksStack, i - offset)
         offset = offset + 1
      end

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

    2. VictorVV, никогда не возникнет ошибки если обход этого цикла делать с конца с шагом "-1". Можете удалять любую строку, на прямую

      1
      2
      3
      4
      5
      6
      7
      8
      9
      
      --правильный "обратный" обход массива, в котором обработанная строка будет удалена:
      a = {1,2,3}
      for i = #a, 1, -1 do
      table.remove(a,i) end
      print (#a)-->0
      --не правильный "прямой" обход массива:
      a = {1,2,3}
      for i = 1, #a do
      table.remove(a,i) end
  2. Спасибо за код движка - стало понятно немного как использовать функции обратного вызова! Решил использовать код в своем роботе, но как обычно - после разбора возник ряд вопросов:

    Вопрос 1 - SE_Trades[i].checked нигде не задается, но используется в OnOrder! А надо ли его вообще использовать?

    Вопрос 2 - В чем смысл запоминания последних номеров обработанных сделок, заявок и транзакций?
    Мне кажется, что добавление информации в массивы сделок, заявок и транзакций можно делать независимо от значений этих номеров, так как условия типа if SE_LastTradeNum < trade.trade_num скорее всего всегда истинно, а больше нигде эти номера не используются. Сделки, заявки и транзакции, в общем случае могут обрабатываться (удаляться из массивов) в любом порядке, а не последовательно и поэтому особого смысла в сохранении этих номеров вообще не вижу.

    Вопрос 3 - Совсем не улавливаю логику этого кода:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
                      ...
                      -- Запоминает номер последней обработанной транзакции
                        SE_LastTransID = SE_Orders[j].trans_id
                        -- Удаляет ответ по транзакции из массива, чтобы больше ее не обрабатывать
                        for k,TransReplie in ipairs(SE_TransReplies) do
    						TransReplie.trans_id = SE_Orders[j].trans_id
    						table.sremove(SE_TransReplies, k)
    						break
    					end
                      ...

    - Какая-то путаница с перебором. Либо надо убрать цикл и просто удалить транзакцию с указанным id (но транзаций наверное может быть несколько под этим id? иначе зачем цикл?) либо тогда в цикле вместо непонятного присваивания id первой выданной циклом транзакции (и удаления этой транзакции) надо добавить проверку, что удаляем транзакцию с указанным id (и удалить её если это так).
    - Зачем запоминать номер id последней обработанной транзакции до перебора транзакций - вдруг при переборе она не найдется - мало ли?

    1. Здравствуйте, всегда пожалуйста.
      1. SE_Trades[i].checked задается в OnTrade
      2. После того, как движок обрабатывает сделку, он удаляет ее из массива, а функция OnTrade может вызываться по несколько раз для одной и той же сделки, чтобы ее повторно не занести в массив и не обработать как новую, используется данный механизм.
      3. Да, тут что-то не то, должно быть так, наверно:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      
      ...
      -- Запоминает номер последней обработанной транзакции
      SE_LastTransID = SE_Orders[j].trans_id
       -- Удаляет ответ по транзакции из массива, чтобы больше ее не обрабатывать
      for k,TransReplie in ipairs(SE_TransReplies) do
         if TransReplie.trans_id == SE_Orders[j].trans_id then
            table.sremove(SE_TransReplies, k)
            break
         end
      end
      ...

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

      1. 1 - тут я немного ошибся надо так - SE_Trades[i].checked нигде не задается, но используется в OnTrade (а не в OnOrder как я вначале написал) !
        эта строка if SE_Trades[i].checked ~= nil then trade.checked = true end в OnTrade никак не может задать SE_Trades[i].checked, так как условие всегда ложно ведь ранее SE_Trades[i].checked не задается, как оно может быть ~= nil , когда оно == nil !!!

        2 - Задумка понятна, но есть сомнения в том, что всегда работает правильно, так как сделки могут удаляться из массива произвольно, то если функция OnTrade вызываться несколько раз для одной и той же сделки, но если между вызовами втиснется вызов для другой сделки, то SE_LastTradeNum изменится и условие типа if SE_LastTradeNum < trade.trade_num может оказаться истинным там где это не надо ... такая мысль лезет, что в такой постановке SE_LastTradeNum можно менять только в сторону увеличения но никак не уменьшения ...

        3 - Вот и я подумал, что так должно быть, почему до меня никто этого не заметил - видимо никто еще не использовал на практике - только в теории ))) по поводу сохранения номера транзакции - думаю сохранять надо перед удалением. И аналогично вопросу 2 - всегда ли условие использующее этот номер будет работать правильно ...

        а где можно почитать в какой последовательности коллбеки приходят и т.п.? я так понял для указанного здесь кода разницы в последовательности нет - все равно все обработается.

        1. по первому вопросу - возможно тогда при переборе сделок не хватает строки в которой SE_Trades[i].checked будет задана (как это делается с транзакциями и заявками)

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

  3. Дмитрий,
    бегло просмотрел три разных скрипта, хотел узнать какой самый свежий. Они мало похожи друг на друга, в смысле повторного использования кода.
    Есть этот скрипт (выше).
    Есть с колл-опционами.
    Простой МА-робот.
    В каком больше всего учтено нюансов биржи? Как тут maxalexven писал ( защита от множественного выставления заявок, множественного срабатывания сигналов, перевыставление заявок после смены сессии, сохранения текущих показателей в любой момент, визуализация результатов и ошибок).

    1. Ну поскольку меня помянули, то могу ответить, что все перечисленные Дмитрием скрипты - это примеры работы. Они многое не учитывают, не даром Дмитрий писал, что это только для демонстрации возможностей.
      У Дмитрия есть рабочие наработки, которые уже даются не безвозмездно.
      У меня тоже есть каркас робота и роботы, которые уже работают в боевом режиме, так что можете обращаться или дерзать сами.

      1. Александр М, подскажите конкретнее о доведении робота до "боевого", если можно кратко по пунктам, чтобы понять ширину и глубину подготовки робота. Вообще напрашивается статья по словесному описанию некого уровня "боевого" робота. Можно положить начало статьи здесь 😉
        PS: может я чего-то не нашел, а оно уже есть...

        1. Leonid_sled, прошу прощения, что сразу не ответил, я был в отпуске. По Вашему вопросу: к сожалению руководство данного портала не позволяет напрямую общаться между пользователями, а также давать ссылки на внешние ресурсы.
          Надеюсь, что ссылка на официальный ресурс позволительна: https://forum.quik.ru/messages/forum10/message11805/topic1302/#message11805
          Почитайте, там 1 участник форума достаточно доходчиво расписал возможные проблемы при работе робота в боевом режиме.

          1. Спасибо, Александр, за ссылочку! Возможно Дмитрий в одной из статей просветит чайников о структуре и подводных камнях при создании боевого робота. А эта ссылка будет кратким руководством )

    2. Данный сайт предназначен для того, чтобы помочь Вам разобраться в тонкостях, но полностью готовых решений здесь нет. Если Вы пишите себе робота, то можете найти в примерах сайта как реализовать тот, или иной момент. Самый разумный подход показан в движке данной статьи, можете для начала взять его, а дальше прикручивать доп. функции. Вообще, стоит начинать разработку с создания блок-схемы, а потом каждый блок реализовывать в коде. Если Вы начнете с того, что будете в свой скрипт вставлять разные найденные куски кода, то в скором времени Вы потеряете понимание того, как все работает, вернее почему все работает не так, как Вы ожидали.

      1. Спасибо.
        На чём проще сделать работающий на срочном рынке робот на Lua или ATF?
        Робот напоминает известную "лесенку".
        Ни тот, ни другой язык не знаком. ATF кажется проще.
        На Велсе несколько лет назад делал скрипты.

          1. В этой ссылке есть пост про Велс. "Лично я использую коннектор Wealth-lab с Transaq connector. Заявки проходят без ошибок практически моментально, а контроль позиции провожу через торговый терминал Transaq." Несколько лет назад помню было тяжело поддерживать соответствие Велсе реальности на бирже. Сейчас лучше? Когда уже велса не хватает и нужен Lua?

            1. В моей точки зрения Wealth-lab нельзя использовать для реальной торговли на любой платформе. Он очень медленный для этого и он ориентирован на работу по закрытым свечам.
              Wealth-lab хорош для первичного анализа, тестирования на истории, оптимизации параметров и отбора стратегий, дальше лучше писать отдельного робота на LUA (или собирать, если каркас уже написан).
              Вообще выгрузка данных на внешнюю программу и загрузка в QUIK сигналов для открытия заявок - это лишняя прослойка, которая ведет к резкому снижению надежности программы. Вам придется учитывать в том числе и то, что данные в какой-то момент перестали поступать или, что еще хуже, до QUIK не дошли ваши сигналы (например на закрытие позиции).
              Да и скорость тут разная на порядок.

  4. Добрый день!

    Если у нас например есть 10 роботов, в каждом из которых мы вызываем Ваш движок

    1
    
    require('SimpleEngine')                -- Подключение движка

    1. Функция SE_OnMainLoop() в каждом роботе будет работать в своем потоке?
    2. Массивы транзакций, заявок и сделок независимо создаются и обрабатываются для каждого робота? Если да, то идет дублирование данных.
    3. Номер транзакции формируется независимо? Если да, то есть вероятность их совпадения.
    4. Он корректно работает под новую 7-ю версию Quik?
    5. Если мы хотим выставить несколько заявок, то сразу возникает проблема, т.к. функция SE_SetLimitOrder ничего не возвращает и мы не знаем, какая из заявок выставилась и с какой именно заявкой возникают проблемы в дальнейшем. Мне кажется, что как минимум надо возвращать номер транзакции, чтобы в остальных функциях по этому номеру уже отслеживать. Как это делать в существующем примере, я не совсем понимаю.
    6. В примере не показано отслеживание всего пути от транзакции к сделке. Как понять, что именно моя заявка полностью выполнена? В движке вы чистите массив транзакций и заявок, если КАКАЯ-ТО сделка выполнена.

    С уважением,
    Александр.

    1. Редактировать свои собственные комментарии у Вас нельзя?

      Хотел добавить в виде примера:
      1. В Вашем примере добавьте элементарное условие: выставить заявку, если текущая цена больше/меньше значения
      2. Запустите несколько Ваших примеров одновременно.

      В результате наступления события условия мы получаем одномоментное выставление нескольких транзакций (по числу запущенных программ). При этом:
      1. Поскольку номер транзакции назначается независимо, то очень большая вероятность, что номера транзакций совпадут
      2. Все ваши функции SE_On..., которые касаются транзакции, заявки, сделки не смогут показать, что они реагируют на транзакции, заявки, сделки именно того робота, где они прописаны и никак по существующему коду движка нельзя понять, что ошибки или выполнение транзакции, заявки, сделки относятся именно к тому роботу, откуда эта транзакция была запущена.

      1. 1. В Вашем примере добавьте элементарное условие: выставить заявку, если текущая цена больше/меньше значения

        Пример специально сделан простейший, в нем проверяется только условие if not MyTransactionSended then, вместо него можете проверять что угодно.

        На остальные вопросы уже ответил.

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

    2. Здравствуйте, Александр!
      1. Функция SE_OnMainLoop() в каждом роботе будет работать в своем потоке?

      Да

      2. Массивы транзакций, заявок и сделок независимо создаются и обрабатываются для каждого робота? Если да, то идет дублирование данных.

      В движке видно, что к каждой транзакции добавляется поле: ['CLIENT_CODE']= 'SE_'..sec_code, т.е. добавляется код инструмента, затем двидок отслеживает и записывает в массивы только те ответы по транзакциям, стоп-заявки, заявки и сделки, у которых в поле brokerref есть используемый им sec_code, это всего лишь простейший пример показан, если у Вас несколько роботов будут работать по одному инструменту, то Вы можете помимо sec_code указывать еще какое-то уникальное число, например, добавив эту проверку в движок.

      3. Номер транзакции формируется независимо? Если да, то есть вероятность их совпадения.

      Если Вы запустите несколько роботов одновременно, то есть, т.к. начальный номер это время в секундах. Тогда, возможно, есть смысл задействовать какой-то другой механизм генерации ID. Например, каждому роботу дать свой порядковый номер (RobotNum), начиная с 0, добавить в движок какую-то функцию инициализации, и при подключении движка передавать в этой функции этот номер, чтобы движок первый trans_id получал как-то так: SE_trans_id = os.time() - RobotNum * 1000000, и добавлял этот номер к каждой транзакции: ['CLIENT_CODE']= 'SE_'..sec_code..RobotNum и отслеживал потом и его: if trade.brokerref:find('SE_'..SEC_CODE..RobotNum ) == nil then return end

      4. Он корректно работает под новую 7-ю версию Quik?

      Да

      5. Если мы хотим выставить несколько заявок, то сразу возникает проблема, т.к. функция SE_SetLimitOrder ничего не возвращает и мы не знаем, какая из заявок выставилась и с какой именно заявкой возникают проблемы в дальнейшем. Мне кажется, что как минимум надо возвращать номер транзакции, чтобы в остальных функциях по этому номеру уже отслеживать. Как это делать в существующем примере, я не совсем понимаю.

      Добавил пару строк в функцию SE_SetLimitOrder, посмотрите. Только сейчас, наверно, нет больше смысла в функции SE_OnTransSendError().

      6. В примере не показано отслеживание всего пути от транзакции к сделке. Как понять, что именно моя заявка полностью выполнена? В движке вы чистите массив транзакций и заявок, если КАКАЯ-ТО сделка выполнена.

      Теперь можно по trans_id, получаемой из SE_SetLimitOrder отслеживать.

      1. Добрый день!
        Спасибо за подробный ответ. Логика понятна. Как я понял, Вы сейчас как раз разрабатываете универсальный движок. Надеюсь в нем отразятся и мои замечания по номеру транзакции.
        Что касается Ваших добавлений. Да это решает часть проблем, теперь мы может отследить по номеру транзакции саму транзакцию и заявку по ней (как я понял, тут идет отношение 1 к 1), а вот со сделками будет проблема.
        Вот по этой ссылке посмотрите: https://forum.quik.ru/forum10/topic1200/ Там представители разработчика подтвердили, что возможна ошибка, т.е. в сделках номер транзакции возвращается как 0. Как я понял они эту проблему пока не решили. И в нашем конкретном случае получается, что сделки (а их обычно больше 1 на 1 заявку) надо отслеживать по ID заявки, а не транзакции. Как вы планируете решить данную задачу? Как я понимаю, придется в обработке SE_OnNewOrder(order) по ID транзакции запоминать ID заявки.

        1. В движке как раз решена эта проблема, trans_id сам движок добавляет к сделке, предварительно отследив его.
          И в функции SE_OnNewTrade Вы получаете уже готовый результат.

          Я перестал разрабатывать движок в том виде, в котором планировал, решил еще более упростить задачи разработки и сейчас создаю другое решение, но рассказывать раньше времени подробности не буду 🙂

          1. Это будет чистый QLUA или гибрид с С++?
            Я сам пишу себе роботов (правда не в универсальном виде). У меня сами роботы все результаты кладут в файл, а отдельный скрипт эти результаты выкладывает в 3 таблицы: сделки, позиции, сообщения. Отдельно под каждый робот есть файл с текущими значениями стопов, флагов, уровней и т.д.
            Ваш движок натолкнул меня на пару мыслей, буду переписывать обработку сделки. Спасибо за идеи.
            Могу поделиться своими тоже. Написано коряво, но может тоже что-то поможет.

              1. Дмитрий, Вы для себя решили:
                1. Как и где будете хранить текущие значения позиции, сделок, уровней, стопов, профитов, флагов?
                2. Что вы считаете позицией и когда она закрывается и открывается новая (по 1 позиции может быть несколько сделок на открытие, дооткрытие, частичное закрытие, опять дооткрытие и т.д. до полного закрытия)?
                3. Как и где будете хранить историю по заявкам, сделкам, позициям и какие поля будете хранить.
                4. Как будете считать профит позиции
                5. Как будете защищать скрипт от дисконнекта от брокера, закрытия сессии (при открытых заявках), закрытия скрипта и т.д. При этом должны сохраниться последние актуальные значения (см. пункт 1), а также снятые брокером заявки переоткрыться заново (или не переоткрыться, если условия входа изменились)
                6. Как будете визуализировать информацию (на графике метками, в виде таблицы, в виде нескольких таблиц) и что именно будете показывать.
                7. Что будете делать, если заявка исполнилась только частично и сколько будете ждать ее исполнения.
                Все вышеперечисленное должно быть отражено в Вашем инжине, поэтому мне очень интересно, какая у Вас концепция. Ее обычно расписывают до написания кода.

                1. Забыл еще пункт:
                  8. Как будете синхронизировать робота с терминалом на предмет количества актуальных контрактов по позиции. Ведь всегда есть временной лаг, внезапное выключение или вылет скрипта, дисконнект с брокером и в результате например OnAllTrade не вернет событие по очередной сделке.

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

                2. 1. Как и где будете хранить текущие значения позиции, сделок, уровней, стопов, профитов, флагов?

                  по началу в массивах, потом, может быть, сделаю синхронизацию с файлом
                  2. Что вы считаете позицией и когда она закрывается и открывается новая (по 1 позиции может быть несколько сделок на открытие, дооткрытие, частичное закрытие, опять дооткрытие и т.д. до полного закрытия)?

                  то, что от 0 и до 0, это и есть позиция, пока последняя сделка не закрылась
                  3. Как и где будете хранить историю по заявкам, сделкам, позициям и какие поля будете хранить.

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

                  скорее всего стандартно с учетом комиссии, в последствии можно будет более тонкие рассчеты делать
                  5. Как будете защищать скрипт от дисконнекта от брокера, закрытия сессии (при открытых заявках), закрытия скрипта и т.д. При этом должны сохраниться последние актуальные значения (см. пункт 1), а также снятые брокером заявки переоткрыться заново (или не переоткрыться, если условия входа изменились)

                  на начальном этапе никак, потом создам какой-то модуль "службы спасения" 🙂
                  6. Как будете визуализировать информацию (на графике метками, в виде таблицы, в виде нескольких таблиц) и что именно будете показывать.

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

                  сколько будет указано в настройках скрипта

                  Все вышеперечисленное должно быть отражено в Вашем инжине, поэтому мне очень интересно, какая у Вас концепция. Ее обычно расписывают до написания кода.

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

                  1. По п1 и п3 это точно разные файлы. Сделки и позиции (п.3) - это по сути база истории, для дальнейшего анализа профита, рисования красивых кривых доходности и т.д. Он заполняется после каждой сделки (добавляется в конец).
                    А текущие значения крайней позиции+значения флагов и т.д. (п.1) - это маленький файл, который должен обновляться постоянно и мгновенно после каждого события (изменения значению любой переменной, входящей в перечень в этом файле), т.е. он может обновляться каждую секунду и должен быть максимально оптимизирован по размеру.
                    п.2 - Согласен, у меня так же.
                    п.4. Я считаю упрощенно по пунктам без учета комиссии. Если Вы будете считать корректно в рублях+комиссия (обе брокера и биржи с учетом всех нюансов на встречные сделки, учет обьемов по дню согласно тарифу), то очень хотелось бы это увидеть 🙂
                    п.5 Как минимум в самом скрипте на события по выходу, дисконнекту должен быть повешено сохранение текущих значений+периодически проверяться закрытие сессии
                    п.6.-7 С удовольствием посмотрю хотя бы концепцию этих блоков.

                    Готов поучаствовать в написании блоков или тестировании. Текст qlua я достаточно сносно читаю. Может незамыленный взгляд что-то зацепит 🙂

                    1. Это отлично, что Вы готовы поучаствовать! Я сейчас пишу пользовательский web-интерфейс, все будет в web, как доделаю, буду базовые блоки начинать делать, тогда буду рад Вашему участию.

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

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

                  2. По поводу Вашего IDE. Посмотрите вот тут есть хорошие примеры с автоподстановкой функций, дебагингом, проверкой и т.д.:

                    http://luaedit.sourceforge.net/media.html

                    https://www.eclipse.org/ldt/

                    IDE - это очень серьезная и ресурсоемкая по человекочасам вещь. Делать полноценную IDE вряд ли Вам будет по силам, а делать простенькую узкоспециализированную мало кто поймет. Или Вы что-то другое имеете в виду?

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

                  3. Тогда Вы хотите сделать что-то типа такого:

                    http://cofite.ru/products/#robotlab
                    http://www.tslab.ru/soft/about/
                    http://stocksharp.ru/products/designer/
                    и т.д.
                    А это еще более сложная задача, поскольку обязывает встраивать "защиту от дураков" изначально в код. Целые команды над ней работают годами и отлаживают.

                    Мне кажется, что на начальном этапе лучше сосредоточиться на чем то типа такого: http://www.kamynin.ru/archives/6145
                    Это поймут большинство трейдеров, а на IDE еще программировать надо уметь, а трейдеры ленивые, им проще получить готовое и желательно чужими руками и бесплатно. Людей, готовых писать самим (как мы с вами) - это доля процента. Собственно Аноним Вам об этом уже писал и я с ним согласен.

                    1. Чтобы из кубиков алгоритм создавать не нужно умение программировать, думаю многие с этим справятся. Мне кажется интересным собирать из кубиков скрипт на QLua, в дальнейшем можно будет расширять эти возможности другими технологиями. А т.к. изначально будут представлены простейшие элементы, то библиотека этих кубиков будет постоянно расти. Тут главное сам движок создания, добавления, установки связи кубиков сделать, научить его генерировать все это в виде кода, а потом наслаждаться простором для творчества. Мне кажется интересным решить эту задачу. Лично мне нужна такая IDE, думаю многие ее оценят, если все получится.

                    2. Дмитрий, как продвигается работа с кубиками?

                    3. Никак не продвигается, как-то не пошло в итоге и я забросил это дело.
                      Вы, кстати, данный комментарий написали как ответ не на мой комментарий 🙂

                    4. Я прошу прощения, но здесь нет рядом с вашим комментарием кнопки Ответить. Нажимаю первую близкую с ответом.

                      Скажите, а вы пробовать обратиться к stocksharp? Мне уже 2 письма упало о их новом продукте. У них есть кубики, у вас есть луа 🙂 Сделать вместе подобное создание луа через кубики. Для них будет это просто. А нам всем польза. Меня они не послушают, а вы как авторитетный представитель сайта можете их заинтересовать.

                    5. У стокшарпа и так есть коннектор к квику, зачем изобретать велосипед 🙂
                      Будете писать мне новый комментарий, пишите его как комментарии к самой статье просто.

                  4. Такая система всем нужна, вопрос только в том, насколько она будет гибкой, надежной, насколько в ней изначально будут заложены защита от множественного выставления заявок, множественного срабатывания сигналов, перевыставление заявок после смены сессии, сохранения текущих показателей в любой момент, визуализация результатов и ошибок. И конечно защита от вылетов, закрытия скрипта, дисконнекта и т.д.
                    Также не забудьте предусмотреть как минимум тестовый режим работы, как максимум тестовый режим по истории (получение и обработка исторических данных, отдельная песня). Лично я пока тестирую разные стратегии под Wealth-lab, а потом лучшие перевожу опять же на тест под qLua. Если тест совпадает с результатами Wealth-lab на реальной работе (с гэпами, проскальзованием и т.д.), то уже перевожу робота в работу на боевую.
                    Если вы такое сделаете и в результате будет генериться чистый и достаточно оптимальный qLua код (быстродействие работы очень важно, обычно универсальность влияет на скорость работы, поэтому я думаю, что у вас все-таки будет гибрид с dll-ми), который напрямую сможет быть запущен под QUIK, то это достойно всяческого уважения 🙂 Это громадная работа.

                    1. Смысл в том, что изначально будут все базовые элементы QLua(Lua), т.е. вплоть до условных операторов, циклов и т.п., так же функции обратного вызова, в общем, все, что есть в QLua сейчас. И вот уже из этих визуальных элементов можно будет создавать какие-то функциональные блоки, из которых, в свою очередь, можно будет создавать более сложные блоки. Т.е. насколько будет реализованы защиты от множественного выставления заявок и т.п. будет зависеть от того, что Вы соберете. Цель такова, чтобы из простых элементов создать какой-то функциональный блок, допилить его до качественной работы и сохранить в библиотеке для последующего использования. Т.е. здесь не будет какого-то навязанного готового базового функционала скрипта. Можно будет делать бесконечное количество разных движков, причем как с нуля, так и беря за основу уже кем-то созданные (если автор выложит его в свободный доступ).

                  5. Тогда это похоже на те системы (стокшарп, тслаб и т.д.), чьи ссылки я давал, только в результате код будет Lua генериться, все остальное, что Вы написали, там есть (и возможность сохранять шаблоны собранных кубиков и возможность выставлять в общую схему абстрактный кубик, внутри которого рисуется отдельная схема из простых кубиков).
                    Но даже на этих системах, которые делают целые команды я упирался в их возможности, когда пытался применить на себе. Например арбитраж, когда используется в с каждой стороны портфель инструментов с весовыми коэффициентами. Сложный случай и визуально я не мог брать одновременно данные из нескольких инструментов (они дают снимать показания только с 1, собственно там начало проектирования начинается с указания инструмента для работы).
                    Или были проблемы с сохранением (желательно вообще на полном автомате) слепка текущих показаний в файл. Это должно происходить автоматом и постоянно при любом изменении, а этого не было и при любом выключении скрипта логика системы предлагала пересчитать все показатели заново, а зачастую это сделать невозможно или сильно затруднительно, если следующий показатель считается на основе предыдущего.
                    При этом в самом коде вручную в lua я это достаточно легко предусматриваю (конечно есть форсмажор, типа внезапного взрыва компьютера 🙂 )

                    1. Я с теми же проблемами столкнулся в свое время, пробуя использовать перечисленные Вами инструменты, т.к. там есть какие-то рамки, я же хочу исключить какие-либо рамки в своем решении. Кодить хорошо, но когда проект стает более менее внушительного размера, "ворочать" его становится сложно, лично мне проще воспринимать образную информацию, чем текстовую, желание сделать что-то подобное давно вынашивал, и вот решился, надеюсь осилю 🙂

                  6. Тайны я как раз и не вытянул 🙂
                    У Вас идея замечательная и достойная, но я как бывший программист понимаю колоссальный обьем работы, чтобы результат действительно был таким, как Вы описали. Или я чего-то не догоняю. Сама основа среды очень ресурсоемкая по исполнению.

                    1. Я не говорю, что это несколько строчек кода, понимаю, что работы много 🙂 Но надеюсь, что осилю!

                  7. Кстати, давно хотел Вам написать. При написании примеров Вы не уделяете внимание оптимизации. Например большинство переменных у Вас становятся глобальными.

                    Есть хорошая статья http://www.bot4sale.ru/blog-menu/qlua/spisok-statej/454-lua-optimization.html
                    Я оттуда многое почерпнул. При написании Вашей среды данную оптимизацию надо в обязательном порядке сразу предусматривать в коде, иначе потом придется долго и упорно править весь код.

                    1. Вы решили мой сайт наполнить ссылками на другие ресурсы? 🙂
                      Где у меня переменные глобальными становятся?

                  8. Например здесь же в код примера переменные trans_id, Res в функции function SE_OnMainLoop() В самом движке trans_id (но тут Вы видимо ошиблись и имелось в виде SE_trans_id), в других примерах тоже есть, но в статье ведь не только про переменные, там и про работу с массивами тоже написано и про математические функции и т.д.
                    На разных форумах есть результаты тестирования и использование некоторых функций добавляет несколько десятков миллисекунд. А если эта функция используется часто, то скорость работы существенно падает.
                    Постараюсь в дальнейшем ссылки не давать.

                    1. В примере что-то я действительно забыл local поставить, спасибо, исправил. Хотя в примере эти переменные вообще не используются, можно их не указывать было, просто для примера показал, что функция возвращает.
                      А вообще я всегда стараюсь строго соблюдать видимость переменных.