Данный движок не предоставляет полный функционал для разработки скриптов на QLua(Lua), но показывает на сколько проще и эффективней становится разработка при таком подходе.
В примере движка реализован следующий функционал:
- Движок предоставляет одну функцию для выставления лимитированной заявки
1 2 3 4 5 6 7 8
SE_SetLimitOrder( account, -- Код счета class_code, -- Код класса sec_code, -- Код инструмента operation, -- Операция ('B' - buy, 'S' - sell) price, -- Цена qty -- Количество )
SE_SetLimitOrder( account, -- Код счета class_code, -- Код класса sec_code, -- Код инструмента operation, -- Операция ('B' - buy, 'S' - sell) price, -- Цена qty -- Количество )
- Движок реализует собственные функции обратного вызова, которые можно использовать в скрипте после подключения движка. Чтобы не путаться, все функции и переменные движка имеют префикс "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()
-- Функция выполняется при каждой итерации цикла 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()
- Движок записывает в соответствующие массивы ответы по транзакциям, заявки и сделки, но не все, а только те, которые появились благодаря транзакциям, отправленным движком, анализирует их и вызывает соответствующие функции обратного вызова (если они определены в скрипте) при наступлении определенного события. Движок удаляет из массивов старые (обработанные) данные, таким образом не засоряя память.
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 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 | -- SimpleEngine.lua -- ПРОСТОЙ ТОРГОВЫЙ ДВИЖОК "Simple Engine" ДЛЯ QLua SE_Run = true -- Флаг работы цикла while в функции main SE_trans_id = os.time() -- Текущие дата и время в секундах хорошо подходят для уникальных номеров транзакций SE_TransReplies = {} -- Массив для хранения ответов по транзакциям SE_LastTransID = 0 -- Последний ID транзакции, ответ по которой был обработан и удален из массива SE_Orders = {} -- Массив для хранения информации о заявках SE_LastOrderNum = 0 -- Последний номер заявки, которая была обработана и удалена из массива SE_Trades = {} -- Массив для хранения информации о сделках SE_LastTradeNum = 0 -- Последний номер сделки, которая была обработана и удалена из массива -- ========================================================= -- === МЕХАНИЗМ ДВИЖКА =================================== -- ========================================================= -- Основная функция скрипта, пока работает эта функция, работает скрипт function main() -- Пока работает данный цикл, работает функция main, следовательно, работает скрипт while SE_Run do -- Выполняет предопределенную функцию итераций, если она объявлена if SE_OnMainLoop ~= nil then SE_OnMainLoop() end -- МОНИТОРИТ ИЗМЕНЕНИЯ -- Перебирает ОТВЕТЫ ПО ТРАНЗАКЦИЯМ for i,TransReplie in ipairs(SE_TransReplies) do -- Если ответ еще не был учтен if SE_TransReplies[i].checked == nil then -- Проверяет на наличие ошибок по транзакции if SE_TransReplies[i].status > 1 and SE_TransReplies[i].status ~= 3 then -- Вызывает функцию обратного вызова (если она объявлена) if SE_OnTransExecutionError ~= nil then SE_OnTransExecutionError(SE_TransReplies[i]) end -- Запоминает, что ответ был учтен SE_TransReplies[i].checked = true -- Если транзакция выполнена elseif SE_TransReplies[i].status == 3 then -- Вызывает функцию обратного вызова (если она объявлена) if SE_OnTransOK ~= nil then SE_OnTransOK(SE_TransReplies[i]) end -- Запоминает, что ответ был учтен SE_TransReplies[i].checked = true end end end -- Перебирает ЗАЯВКИ for i,Order in ipairs(SE_Orders) do -- Если выставление заявки еще не было учтено if SE_Orders[i].checked == nil then -- Вызывает функцию обратного вызова (если она объявлена) if SE_OnNewOrder ~= nil then SE_OnNewOrder(SE_Orders[i]) end SE_Orders[i].checked = true end -- Проверяет какое количество в заявке исполнено local ExecutionCount = SE_Orders[i].qty - SE_Orders[i].balance -- Если это первая проверка, или с предыдущей проверки количество изменилось и заявка частично, или полностью исполнена if (SE_Orders[i].last_execution_count == nil or SE_Orders[i].last_execution_count ~= ExecutionCount) and ExecutionCount > 0 then -- Вызывает функцию обратного вызова (если она объявлена) if SE_OnExecutionOrder ~= nil then SE_OnExecutionOrder(SE_Orders[i]) -- Запоминает исполненное количество для последующего сравнения SE_Orders[i].last_execution_count = ExecutionCount end end end -- Перебирает СДЕЛКИ for i,Trade in ipairs(SE_Trades) do -- Если в сделке уже появилось поле с номером заявки, по которой она была совершена if SE_Trades[i].order_num ~= nil then -- Перебирает заявки for j,Order in ipairs(SE_Orders) do -- Если найдена заявка, по которой совершена сделка if SE_Trades[i].order_num == SE_Orders[j].order_num then -- Добавляет таблице сделки номер транзакции, которая инициировала данную сделку SE_Trades[i].trans_id = SE_Orders[j].trans_id -- Вызывает функцию обратного вызова (если она объявлена) if SE_OnNewTrade ~= nil then SE_OnNewTrade(SE_Trades[i]) end -- Запоминает номер последней обработанной сделки SE_LastTradeNum = SE_Trades[i].trade_num -- Удаляет сделку из массива, чтобы больше ее не обрабатывать table.sremove(SE_Trades, i) -- Если заявка сделки полностью исполнена и обработана if SE_Orders[j].last_execution_count ~= nil and SE_Orders[j].last_execution_count == SE_Orders[j].qty then -- Запоминает номер последней обработанной транзакции 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 -- Запоминает номер последней обработанной заявки SE_LastOrderNum = SE_Orders[j].order_num -- Удаляет заявку из массива, чтобы больше ее не обрабатывать table.sremove(SE_Orders, j) -- Прерывает цикл по заявкам break end end end end end sleep(1) end end -- Срабатывает при остановке скрипта function OnStop() SE_Run = false if SE_OnStop ~= nil then SE_OnStop() end end -- ======================================== -- === Функции, собирающие информацию === -- Функция вызывается терминалом когда с сервера приходит ответ по транзакции function OnTransReply(trans_reply) -- Если не относится к движку, выходит из функции if trans_reply.brokerref:find('SE_'..SEC_CODE) == nil then return end -- Перебирает массив ответов по транзакциям for i,TransReplie in ipairs(SE_TransReplies) do -- Если если ответ по данной транзакции уже занесен в массив if SE_TransReplies[i].trans_id == trans_reply.trans_id then -- Если появление ответа уже было учтено, сохраняет эту информацию if SE_TransReplies[i].checked ~= nil then trans_reply.checked = true end -- Заменяет его в массиве table.sremove(SE_TransReplies, i) table.sinsert(SE_TransReplies, trans_reply) -- Выходит из функции return end end -- Ответ еще не был добавлен в массив, добавляет if SE_LastTransID < trans_reply.trans_id then table.sinsert(SE_TransReplies, trans_reply) end end -- Функция вызывается терминалом когда с сервера приходит информация по заявке function OnOrder(order) -- Если не относится к движку, выходит из функции if order.brokerref:find('SE_'..SEC_CODE) == nil then return end -- Перебирает массив заявок for i,Order in ipairs(SE_Orders) do -- Если заявка уже занесена в массив if SE_Orders[i].trans_id == order.trans_id then -- Если появление заявки уже было учтено, сохраняет эту информацию if SE_Orders[i].checked ~= nil then order.checked = true end -- Если исполненное количество уже учитывалось, сохраняет эту информацию if SE_Orders[i].last_execution_count ~= nil then order.last_execution_count = SE_Orders[i].last_execution_count end -- Заменяет ее table.sremove(SE_Orders, i) table.sinsert(SE_Orders, order) -- Выходит из функции return end end -- Заявка еще не была добавлена в массив, добавляет if SE_LastOrderNum < order.order_num then table.sinsert(SE_Orders, order) end end -- Функция вызывается терминалом когда с сервера приходит информация по сделке function OnTrade(trade) -- Если не относится к движку, выходит из функции if trade.brokerref:find('SE_'..SEC_CODE) == nil then return end -- Перебирает массив сделок for i,Trade in ipairs(SE_Trades) do -- Если данная сделка уже занесена в массив if SE_Trades[i].trade_num == trade.trade_num then -- Если появление сделки уже было учтено, сохраняет эту информацию if SE_Trades[i].checked ~= nil then trade.checked = true end -- Заменяет ее table.sremove(SE_Trades, i) table.sinsert(SE_Trades, trade) -- Выходит из функции return end end -- Сделка еще не была добавлена в массив, добавляет if SE_LastTradeNum < trade.trade_num then table.sinsert(SE_Trades, trade) end end -- ======================================== -- ========================================================= -- ========================================================= -- === ФУНКЦИИ ДВИЖКА ==================================== -- ========================================================= -- Выставляет лимитированную заявку function SE_SetLimitOrder( account, -- Код счета class_code, -- Код класса sec_code, -- Код инструмента operation, -- Операция ('B' - buy, 'S' - sell) price, -- Цена qty -- Количество ) -- Выставляет лимитированную заявку -- Получает ID для следующей транзакции SE_trans_id = SE_trans_id + 1 -- Заполняет структуру для отправки транзакции local Transaction={ ['TRANS_ID'] = tostring(SE_trans_id),-- Номер транзакции ['ACCOUNT'] = account, -- Код счета ['CLASSCODE'] = class_code, -- Код класса ['SECCODE'] = sec_code, -- Код инструмента ['ACTION'] = 'NEW_ORDER', -- Тип транзакции ('NEW_ORDER' - новая заявка) ['TYPE'] = 'L', -- Тип ('L' - лимитированная, 'M' - рыночная) ['OPERATION'] = operation, -- Операция ('B' - buy, или 'S' - sell) ['PRICE'] = tostring(price), -- Цена ['QUANTITY'] = tostring(qty), -- Количество ['CLIENT_CODE']= 'SE_'..sec_code -- Комментарий к транзакции, который будет виден в транзакциях, заявках и сделках в поле brokerref } -- Отправляет транзакцию local Res = sendTransaction(Transaction) -- Если при отправке транзакции возникла ошибка if Res ~= '' then -- Вызывает функцию обратного вызова (если она объявлена) if SE_OnTransSendError ~= nil then local trans = {} trans.trans_id = SE_trans_id trans.transaction = Transaction trans.result_msg = Res SE_OnTransSendError(trans) end -- Возвращает номер транзакции и сообщение об ошибке return SE_trans_id, Res end -- Если транзакция отправлена, возвращает ее номер return SE_trans_id end -- ========================================================= |
-- SimpleEngine.lua -- ПРОСТОЙ ТОРГОВЫЙ ДВИЖОК "Simple Engine" ДЛЯ QLua SE_Run = true -- Флаг работы цикла while в функции main SE_trans_id = os.time() -- Текущие дата и время в секундах хорошо подходят для уникальных номеров транзакций SE_TransReplies = {} -- Массив для хранения ответов по транзакциям SE_LastTransID = 0 -- Последний ID транзакции, ответ по которой был обработан и удален из массива SE_Orders = {} -- Массив для хранения информации о заявках SE_LastOrderNum = 0 -- Последний номер заявки, которая была обработана и удалена из массива SE_Trades = {} -- Массив для хранения информации о сделках SE_LastTradeNum = 0 -- Последний номер сделки, которая была обработана и удалена из массива -- ========================================================= -- === МЕХАНИЗМ ДВИЖКА =================================== -- ========================================================= -- Основная функция скрипта, пока работает эта функция, работает скрипт function main() -- Пока работает данный цикл, работает функция main, следовательно, работает скрипт while SE_Run do -- Выполняет предопределенную функцию итераций, если она объявлена if SE_OnMainLoop ~= nil then SE_OnMainLoop() end -- МОНИТОРИТ ИЗМЕНЕНИЯ -- Перебирает ОТВЕТЫ ПО ТРАНЗАКЦИЯМ for i,TransReplie in ipairs(SE_TransReplies) do -- Если ответ еще не был учтен if SE_TransReplies[i].checked == nil then -- Проверяет на наличие ошибок по транзакции if SE_TransReplies[i].status > 1 and SE_TransReplies[i].status ~= 3 then -- Вызывает функцию обратного вызова (если она объявлена) if SE_OnTransExecutionError ~= nil then SE_OnTransExecutionError(SE_TransReplies[i]) end -- Запоминает, что ответ был учтен SE_TransReplies[i].checked = true -- Если транзакция выполнена elseif SE_TransReplies[i].status == 3 then -- Вызывает функцию обратного вызова (если она объявлена) if SE_OnTransOK ~= nil then SE_OnTransOK(SE_TransReplies[i]) end -- Запоминает, что ответ был учтен SE_TransReplies[i].checked = true end end end -- Перебирает ЗАЯВКИ for i,Order in ipairs(SE_Orders) do -- Если выставление заявки еще не было учтено if SE_Orders[i].checked == nil then -- Вызывает функцию обратного вызова (если она объявлена) if SE_OnNewOrder ~= nil then SE_OnNewOrder(SE_Orders[i]) end SE_Orders[i].checked = true end -- Проверяет какое количество в заявке исполнено local ExecutionCount = SE_Orders[i].qty - SE_Orders[i].balance -- Если это первая проверка, или с предыдущей проверки количество изменилось и заявка частично, или полностью исполнена if (SE_Orders[i].last_execution_count == nil or SE_Orders[i].last_execution_count ~= ExecutionCount) and ExecutionCount > 0 then -- Вызывает функцию обратного вызова (если она объявлена) if SE_OnExecutionOrder ~= nil then SE_OnExecutionOrder(SE_Orders[i]) -- Запоминает исполненное количество для последующего сравнения SE_Orders[i].last_execution_count = ExecutionCount end end end -- Перебирает СДЕЛКИ for i,Trade in ipairs(SE_Trades) do -- Если в сделке уже появилось поле с номером заявки, по которой она была совершена if SE_Trades[i].order_num ~= nil then -- Перебирает заявки for j,Order in ipairs(SE_Orders) do -- Если найдена заявка, по которой совершена сделка if SE_Trades[i].order_num == SE_Orders[j].order_num then -- Добавляет таблице сделки номер транзакции, которая инициировала данную сделку SE_Trades[i].trans_id = SE_Orders[j].trans_id -- Вызывает функцию обратного вызова (если она объявлена) if SE_OnNewTrade ~= nil then SE_OnNewTrade(SE_Trades[i]) end -- Запоминает номер последней обработанной сделки SE_LastTradeNum = SE_Trades[i].trade_num -- Удаляет сделку из массива, чтобы больше ее не обрабатывать table.sremove(SE_Trades, i) -- Если заявка сделки полностью исполнена и обработана if SE_Orders[j].last_execution_count ~= nil and SE_Orders[j].last_execution_count == SE_Orders[j].qty then -- Запоминает номер последней обработанной транзакции 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 -- Запоминает номер последней обработанной заявки SE_LastOrderNum = SE_Orders[j].order_num -- Удаляет заявку из массива, чтобы больше ее не обрабатывать table.sremove(SE_Orders, j) -- Прерывает цикл по заявкам break end end end end end sleep(1) end end -- Срабатывает при остановке скрипта function OnStop() SE_Run = false if SE_OnStop ~= nil then SE_OnStop() end end -- ======================================== -- === Функции, собирающие информацию === -- Функция вызывается терминалом когда с сервера приходит ответ по транзакции function OnTransReply(trans_reply) -- Если не относится к движку, выходит из функции if trans_reply.brokerref:find('SE_'..SEC_CODE) == nil then return end -- Перебирает массив ответов по транзакциям for i,TransReplie in ipairs(SE_TransReplies) do -- Если если ответ по данной транзакции уже занесен в массив if SE_TransReplies[i].trans_id == trans_reply.trans_id then -- Если появление ответа уже было учтено, сохраняет эту информацию if SE_TransReplies[i].checked ~= nil then trans_reply.checked = true end -- Заменяет его в массиве table.sremove(SE_TransReplies, i) table.sinsert(SE_TransReplies, trans_reply) -- Выходит из функции return end end -- Ответ еще не был добавлен в массив, добавляет if SE_LastTransID < trans_reply.trans_id then table.sinsert(SE_TransReplies, trans_reply) end end -- Функция вызывается терминалом когда с сервера приходит информация по заявке function OnOrder(order) -- Если не относится к движку, выходит из функции if order.brokerref:find('SE_'..SEC_CODE) == nil then return end -- Перебирает массив заявок for i,Order in ipairs(SE_Orders) do -- Если заявка уже занесена в массив if SE_Orders[i].trans_id == order.trans_id then -- Если появление заявки уже было учтено, сохраняет эту информацию if SE_Orders[i].checked ~= nil then order.checked = true end -- Если исполненное количество уже учитывалось, сохраняет эту информацию if SE_Orders[i].last_execution_count ~= nil then order.last_execution_count = SE_Orders[i].last_execution_count end -- Заменяет ее table.sremove(SE_Orders, i) table.sinsert(SE_Orders, order) -- Выходит из функции return end end -- Заявка еще не была добавлена в массив, добавляет if SE_LastOrderNum < order.order_num then table.sinsert(SE_Orders, order) end end -- Функция вызывается терминалом когда с сервера приходит информация по сделке function OnTrade(trade) -- Если не относится к движку, выходит из функции if trade.brokerref:find('SE_'..SEC_CODE) == nil then return end -- Перебирает массив сделок for i,Trade in ipairs(SE_Trades) do -- Если данная сделка уже занесена в массив if SE_Trades[i].trade_num == trade.trade_num then -- Если появление сделки уже было учтено, сохраняет эту информацию if SE_Trades[i].checked ~= nil then trade.checked = true end -- Заменяет ее table.sremove(SE_Trades, i) table.sinsert(SE_Trades, trade) -- Выходит из функции return end end -- Сделка еще не была добавлена в массив, добавляет if SE_LastTradeNum < trade.trade_num then table.sinsert(SE_Trades, trade) end end -- ======================================== -- ========================================================= -- ========================================================= -- === ФУНКЦИИ ДВИЖКА ==================================== -- ========================================================= -- Выставляет лимитированную заявку function SE_SetLimitOrder( account, -- Код счета class_code, -- Код класса sec_code, -- Код инструмента operation, -- Операция ('B' - buy, 'S' - sell) price, -- Цена qty -- Количество ) -- Выставляет лимитированную заявку -- Получает ID для следующей транзакции SE_trans_id = SE_trans_id + 1 -- Заполняет структуру для отправки транзакции local Transaction={ ['TRANS_ID'] = tostring(SE_trans_id),-- Номер транзакции ['ACCOUNT'] = account, -- Код счета ['CLASSCODE'] = class_code, -- Код класса ['SECCODE'] = sec_code, -- Код инструмента ['ACTION'] = 'NEW_ORDER', -- Тип транзакции ('NEW_ORDER' - новая заявка) ['TYPE'] = 'L', -- Тип ('L' - лимитированная, 'M' - рыночная) ['OPERATION'] = operation, -- Операция ('B' - buy, или 'S' - sell) ['PRICE'] = tostring(price), -- Цена ['QUANTITY'] = tostring(qty), -- Количество ['CLIENT_CODE']= 'SE_'..sec_code -- Комментарий к транзакции, который будет виден в транзакциях, заявках и сделках в поле brokerref } -- Отправляет транзакцию local Res = sendTransaction(Transaction) -- Если при отправке транзакции возникла ошибка if Res ~= '' then -- Вызывает функцию обратного вызова (если она объявлена) if SE_OnTransSendError ~= nil then local trans = {} trans.trans_id = SE_trans_id trans.transaction = Transaction trans.result_msg = Res SE_OnTransSendError(trans) end -- Возвращает номер транзакции и сообщение об ошибке return SE_trans_id, Res end -- Если транзакция отправлена, возвращает ее номер return SE_trans_id end -- =========================================================
SE_OnMainLoop()
SE_OnTransSendError(trans)
SE_OnTransExecutionError(trans)
SE_OnNewTrade(trade)
При использовании движка, не используйте в своих скриптах следующие стандартные функции QLua:
main()
OnTransReply()
OnOrder()
OnTrade()
OnStop()
потому что они уже используются в движке !
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 77 78 79 80 81 82 83 84 85 86 87 | -- SimpleEngineExample.lua -- ПРИМЕР ИСПОЛЬЗОВАНИЯ ДВИЖКА -- для примера отправляется транзакция на выставление лимитированной заявки на покупку по определенной цене require('SimpleEngine') -- Подключение движка ACCOUNT = "SPBFUT00k59" -- Код счета CLASS_CODE = "SPBFUT" -- Код класса SEC_CODE = "RIH6" -- Код инструмента MyTransactionSended = false -- Флаг, что транзакция отправлена -- ========================================================= -- === ФУНКЦИИ ОБРАТНОГО ВЫЗОВА (вызываются движком) ===== -- ========================================================= -- Функция выполняется при каждой итерации цикла while в функции main function SE_OnMainLoop() -- Здесь можно выполнять какой-то свой код -- ... -- ПРИМЕР -- Если тестовая транзакция еще не отправлена if not MyTransactionSended then -- Выставляет лимитированную заявку local trans_id, Res = SE_SetLimitOrder( ACCOUNT, -- Код счета CLASS_CODE, -- Код класса SEC_CODE, -- Код инструмента 'B', -- Операция ('B' - buy, 'S' - sell) 77000, -- Цена 1 -- Количество ) -- Запоминает, что транзакция отправлена, чтобы отправлена ее при каждой итерации цикла в main MyTransactionSended = true end end -- Вызывается движком при ОШИБКЕ отправки ТРАНЗАКЦИИ function SE_OnTransSendError(trans) -- Здесь Ваш код для действий при ошибке отправки транзакции (возможно повторная отправка транзакции) -- ... -- Выводит сообщение message('SE_OnTransSendError() ОШИБКА отправки транзакции №'..trans.trans_id..': '..trans.result_msg) end -- Вызывается движком при ОШИБКЕ выполнения ТРАНЗАКЦИИ function SE_OnTransExecutionError(trans) -- Здесь Ваш код для действий при ошибке выполнения транзакции (возможно повторная отправка транзакции) -- ... -- Выводит сообщение message('SE_OnTransExecutionError() ОШИБКА выполнения транзакции №'..trans.trans_id..': '..trans.result_msg) end -- Вызывается движком при успешном ВЫПОЛНЕНИИ ТРАНЗАКЦИИ function SE_OnTransOK(trans) -- Здесь Ваш код для действий при успешном выполнении транзакции -- ... -- Выводит сообщение message('SE_OnTransOK() Транзакция №'..trans.trans_id..' УСПЕШНО выполнена') end -- Вызывается движком при появлении НОВОЙ ЗАЯВКИ function SE_OnNewOrder(order) -- Здесь Ваш код для действий при появлении новой заявки -- ... -- Выводит сообщение message('SE_OnNewOrder() Выставлена новая заявка №'..order.order_num..' по транзакции №'..order.trans_id..', инструменту '..order.sec_code..', цене '..order.price..', на объем '..order.qty) end -- Вызывается движком при полном, или частичном ИСПОЛНЕНИИ ЗАЯВКИ function SE_OnExecutionOrder(order) -- Здесь Ваш код для действий при полном, или частичном исполнении заявки -- ... -- Выводит сообщение message('SE_OnExecutionOrder() БАЛАНС заявки №'..order.order_num..' изменился с '..(order.qty - (order.last_execution_count or 0))..' на '..order.balance) end -- Вызывается движком при появлении НОВОЙ СДЕЛКИ function SE_OnNewTrade(trade) -- Здесь Ваш код для действий при появлении новой сделки -- ... -- Выводит сообщение message('SE_OnNewTrade() Новая СДЕЛКА №'..trade.trade_num..' по транзакции №'..trade.trans_id..' по цене '..trade.price..' объемом '..trade.qty) end -- Вызывается движком при остановке скрипта function SE_OnStop() end -- ========================================================= |
-- SimpleEngineExample.lua -- ПРИМЕР ИСПОЛЬЗОВАНИЯ ДВИЖКА -- для примера отправляется транзакция на выставление лимитированной заявки на покупку по определенной цене require('SimpleEngine') -- Подключение движка ACCOUNT = "SPBFUT00k59" -- Код счета CLASS_CODE = "SPBFUT" -- Код класса SEC_CODE = "RIH6" -- Код инструмента MyTransactionSended = false -- Флаг, что транзакция отправлена -- ========================================================= -- === ФУНКЦИИ ОБРАТНОГО ВЫЗОВА (вызываются движком) ===== -- ========================================================= -- Функция выполняется при каждой итерации цикла while в функции main function SE_OnMainLoop() -- Здесь можно выполнять какой-то свой код -- ... -- ПРИМЕР -- Если тестовая транзакция еще не отправлена if not MyTransactionSended then -- Выставляет лимитированную заявку local trans_id, Res = SE_SetLimitOrder( ACCOUNT, -- Код счета CLASS_CODE, -- Код класса SEC_CODE, -- Код инструмента 'B', -- Операция ('B' - buy, 'S' - sell) 77000, -- Цена 1 -- Количество ) -- Запоминает, что транзакция отправлена, чтобы отправлена ее при каждой итерации цикла в main MyTransactionSended = true end end -- Вызывается движком при ОШИБКЕ отправки ТРАНЗАКЦИИ function SE_OnTransSendError(trans) -- Здесь Ваш код для действий при ошибке отправки транзакции (возможно повторная отправка транзакции) -- ... -- Выводит сообщение message('SE_OnTransSendError() ОШИБКА отправки транзакции №'..trans.trans_id..': '..trans.result_msg) end -- Вызывается движком при ОШИБКЕ выполнения ТРАНЗАКЦИИ function SE_OnTransExecutionError(trans) -- Здесь Ваш код для действий при ошибке выполнения транзакции (возможно повторная отправка транзакции) -- ... -- Выводит сообщение message('SE_OnTransExecutionError() ОШИБКА выполнения транзакции №'..trans.trans_id..': '..trans.result_msg) end -- Вызывается движком при успешном ВЫПОЛНЕНИИ ТРАНЗАКЦИИ function SE_OnTransOK(trans) -- Здесь Ваш код для действий при успешном выполнении транзакции -- ... -- Выводит сообщение message('SE_OnTransOK() Транзакция №'..trans.trans_id..' УСПЕШНО выполнена') end -- Вызывается движком при появлении НОВОЙ ЗАЯВКИ function SE_OnNewOrder(order) -- Здесь Ваш код для действий при появлении новой заявки -- ... -- Выводит сообщение message('SE_OnNewOrder() Выставлена новая заявка №'..order.order_num..' по транзакции №'..order.trans_id..', инструменту '..order.sec_code..', цене '..order.price..', на объем '..order.qty) end -- Вызывается движком при полном, или частичном ИСПОЛНЕНИИ ЗАЯВКИ function SE_OnExecutionOrder(order) -- Здесь Ваш код для действий при полном, или частичном исполнении заявки -- ... -- Выводит сообщение message('SE_OnExecutionOrder() БАЛАНС заявки №'..order.order_num..' изменился с '..(order.qty - (order.last_execution_count or 0))..' на '..order.balance) end -- Вызывается движком при появлении НОВОЙ СДЕЛКИ function SE_OnNewTrade(trade) -- Здесь Ваш код для действий при появлении новой сделки -- ... -- Выводит сообщение message('SE_OnNewTrade() Новая СДЕЛКА №'..trade.trade_num..' по транзакции №'..trade.trans_id..' по цене '..trade.price..' объемом '..trade.qty) end -- Вызывается движком при остановке скрипта function SE_OnStop() end -- =========================================================
Если у Вас появились какие-то вопросы, задайте их в комментариях под статьей !!!
Так же, напишите, пожалуйста, в комментариях свое мнению о таком подходе и нужен ли, по Вашему мнению, полноценный торговый движок для QLua.
И еще, напишите, пожалуйста, кто из Вас, при появлении первой версии полноценного движка, готов был бы помочь с его тестированием и выявлением багов, и кому было бы интересно писать новый код, расширяя тем самым его возможности.
Чтобы в результате получилось готовое решение, которое каждый из нас мог бы использовать для написания как вспомогательных для торговли скриптов, так и полноценных торговых роботов, тратя время на реализацию в коде своей торговой стратегии, а не на подстраивание под особенности работы терминала QUIK !