
Робот торгует по 2-м простым(simple) скользящим средним (MA), выставляет тэйк-профит и стоп-лимит.
1. Если нет открытых роботом позиций выполняется следующий алгоритм:
1. Если быстрая скользящая пересекает медленную снизу вверх и на текущей свече еще не открывались позиции, совершается покупка.
2. Если быстрая скользящая пересекает медленную сверху вниз и на текущей свече еще не открывались позиции, совершается продажа.
2. Если открылась позиция, выставляется "Тэйк-профит и Стоп-лимит"
3. Робот ждет, пока закроется позиция по Стоп-лоссу, либо Тэйк-профиту, после чего переходит к пункту №1
Особенности:
1. Робот выводит в текстовых сообщениях информацию о ключевых моментах алгоритма, у всех его сообщений префикс "Простой MA-робот:".
2. Робот всегда находится в 1-м из 2-х состояний(ROBOT_STATE):'В ПРОЦЕССЕ СДЕЛКИ', либо 'В ПОИСКЕ ТОЧКИ ВХОДА'.
3. Если при выставлении заявки на продажу робот узнает, что операции шорт запрещены по данному инструменту, он больше не будет открывать шорт, только лонг.
4. Когда робот получает сигнал на открытие сделки, он совершает 10 попыток с прмежутками в 100 мс открыть позицию, если этого не удается, останавливает скрипт.
5. После открытия позиции робот совершает 10 попыток с прмежутками в 100 мс выставить Тэйк-профит и Стоп-лимит, а затем дождаться закрытия позиции, если этого не удается, останавливает скрипт.
6. Если стоп-заявка сработала, но позиция не закрылась в течении 10 секунд, пытается за 10 попыток принудительно закрыть позицию встречной сделкой.
Если позицию удалось закрыть (даже принудительно), продолжает работать, иначе скрипт останавливается.
Если найдете какие-то ошибки, недочеты, или просто придумаете как сделать алгоритм более оптимальным, пишите в комментариях, или на почту reply@quikluacsharp.ru. Буду очень признателен!!!
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 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 | --[[ Простой MA-робот (c)QuikLuaCSharp.ru !!! ДЛЯ ИСПОЛЬЗОВАНИЯ ТОЛЬКО В ОБРАЗОВАТЕЛЬНЫХ ЦЕЛЯХ НА ДЕМО-СЧЕТЕ !!! Робот торгует по 2-м простым(simple) скользящим средним (MA). 1.Если нет открытых роботом позиций выполняется следующий алгоритм: 1.Если быстрая скользящая пересекает медленную снизу вверх и на текущей свече еще не открывались позиции, совершается покупка. 2.Если быстрая скользящая пересекает медленную сверху вниз и на текущей свече еще не открывались позиции, совершается продажа. 2.Если открылась позиция, выставляется "Тэйк-профит и Стоп-лимит" 3.Робот ждет, пока закроется позичия по Стоп-лоссу, либо Тэйк-профиту, после чего переходит к пункту №1 Особенности: 1.Робот выводит в текстовых сообщениях информацию о ключевых моментах алгоритма, у всех его сообщений префикс "Простой MA-робот:". 2.Робот всегда находится в 1-м из 2-х состояний(ROBOT_STATE):'В ПРОЦЕССЕ СДЕЛКИ', либо 'В ПОИСКЕ ТОЧКИ ВХОДА'. 3.Если при выставлении заявки на продажу робот узнает, что операции шорт запрещены по данному инструменту, он больше не будет открывать шорт, только лонг. 4.Когда робот получает сигнал на открытие сделки, он совершает 10 попыток с прмежутками в 100 мс открыть позицию, если этого не удается, останавливает скрипт. 5.После открытия позиции робот совершает 10 попыток с прмежутками в 100 мс выставить Тэйк-профит и Стоп-лимит, а затем дождаться закрытия позиции, если этого не удается, останавливает скрипт. 6.Если стоп-заявка сработала, но позиция не закрылась в течении 10 секунд, пытается за 10 попыток принудительно закрыть позицию встречной сделкой. Если позицию удалось закрыть (даже принудительно), продолжает работать, иначе скрипт останавливается. ]] --/*НАСТРАИВАЕМЫЕ ПАРАМЕТРЫ*/ --ACCOUNT = 'NL0011100043'; -- Идентификатор счета ACCOUNT = 'SPBFUT00506'; -- Идентификатор счета --CLASS_CODE = 'QJSIM'; -- Код класса CLASS_CODE = 'SPBFUT'; -- Код класса --SEC_CODE = 'SBER'; -- Код бумаги SEC_CODE = 'RIZ5'; -- Код бумаги INTERVAL = INTERVAL_M1; -- Таймфрейм графика (для построения скользящих) SLOW_MA_PERIOD = 12; -- ПЕРИОД МЕДЛЕННОЙ скользящей SLOW_MA_SOURCE = 'C'; -- ИСТОЧНИК МЕДЛЕННОЙ скользящей [O - open, C - close, H - hi, L - low] FAST_MA_PERIOD = 4; -- ПЕРИОД БЫСТРОЙ скользящей FAST_MA_SOURCE = 'C'; -- ИСТОЧНИК БЫСТРОЙ скользящей [O - open, C - close, H - hi, L - low] STOP_LOSS = 10; -- Размер СТОП-ЛОССА (в шагах цены) TAKE_PROFIT = 30; -- Размер ТЭЙК-ПРОФИТА (в шагах цены) --/*РАБОЧИЕ ПЕРЕМЕННЫЕ РОБОТА (менять не нужно)*/ SEC_PRICE_STEP = 0; -- ШАГ ЦЕНЫ ИНСТРУМЕНТА SEC_NO_SHORT = false; -- Флаг, что по данному инструменту запрещены операции шорт DS = nil; -- Источник данных графика (DataSource) ROBOT_STATE ='В ПОИСКЕ ТОЧКИ ВХОДА';-- СОСТОЯНИЕ робота ['В ПРОЦЕССЕ СДЕЛКИ', либо 'В ПОИСКЕ ТОЧКИ ВХОДА'] trans_id = os.time(); -- Задает начальный номер ID транзакций trans_Status = nil; -- Статус текущей транзакции из функции OnTransPeply trans_result_msg = ''; -- Сообщение по текущей транзакции из функции OnTransPeply CurrentDirect = 'BUY'; -- Текущее НАПРАВЛЕНИЕ ['BUY', или 'SELL'] LastOpenBarIndex = 0; -- Индекс свечи, на которой была открыта последняя позиция (нужен для того, чтобы после закрытия по стопу тут же не открыть еще одну позицию) Run = true; -- Флаг поддержания работы бесконечного цикла в main -- Функция первичной инициализации скрипта (ВЫЗЫВАЕТСЯ ТЕРМИНАЛОМ QUIK в самом начале) function OnInit() -- Получает доступ к свечам графика local Error = ''; DS,Error = CreateDataSource(CLASS_CODE, SEC_CODE, INTERVAL); -- Если график, к которому нужно подключиться не открыт в терминале, то данные заказываются с сервера, на их получение нужно время, -- по этому, рекомендуется добавлять вот такое ожидание, прежде, чем обращаться к DS: -- Ждет, пока данные будут получены с сервера (на случай, если такой график не открыт) while (Error == "" or Error == nil) and DS:Size() == 0 do sleep(1) end if Error ~= "" and Error ~= nil then message("Ошибка подключения к графику: "..Error) return end -- Подписывается на обновления графика DS:SetEmptyCallback() -- Получает ШАГ ЦЕНЫ ИНСТРУМЕНТА SEC_PRICE_STEP = getParamEx(CLASS_CODE, SEC_CODE, "SEC_PRICE_STEP").param_value; end; function main() -- Выводит сообщение message('Простой MA-робот: '..ROBOT_STATE); -- "Бесконечный" цикл while Run do --Если СОСТОЯНИЕ робота "В ПРОЦЕССЕ СДЕЛКИ" if ROBOT_STATE == 'В ПРОЦЕССЕ СДЕЛКИ' then -- Выводит сообщение message('Простой MA-робот: В ПРОЦЕССЕ СДЕЛКИ'); -- Делает 10 попыток открыть сделку local Price = false; -- Переменная для получения результата открытия позиции (цена, либо ошибка(false)) for i=1,10 do if not Run then return; end; -- Если скрипт останавливается, не затягивает процесс -- Если первый раз пытается открыть SELL, а операции шорт по данному инструменту запрещены if CurrentDirect == "SELL" and SEC_NO_SHORT then -- Прерывает цикл FOR break; end; -- Совершает СДЕЛКУ указанного типа ["BUY", или "SELL"] по рыночной(текущей) цене размером в 1 лот, --- возвращает цену открытой сделки, либо FALSE, если невозможно открыть сделку Price = Trade(CurrentDirect); -- Если сделка открылась if Price ~= false then -- Прерывает цикл FOR break; end; sleep(100); -- Пауза в 100 мс между попытками открыть сделку end; if not Run then return; end; -- Если скрипт останавливается, не затягивает процесс -- Если сделка открыта if Price ~= false then -- Запоминает индекс свечи, на которой была открыта последняя позиция (нужен для того, чтобы после закрытия по стопу тут же не открыть еще одну позицию) LastOpenBarIndex = DS:Size(); -- Выводит сообщение message('Простой MA-робот: Открыта сделка '..CurrentDirect..' по цене '..Price); -- Делает 10 попыток выставить СТОП-ЛОСС и ТЭЙК-ПРОФИТ, и дождаться закрытия сделки message('Простой MA-робот: Делает 10 попыток выставить СТОП-ЛОСС и ТЭЙК-ПРОФИТ, и дождаться закрытия сделки'); local Result = nil; -- Переменная для получения результата выставления и срабатывания СТОП-ЛОСС и ТЭЙК-ПРОФИТ for i=1,10 do if not Run then return; end; -- Если скрипт останавливается, не затягивает процесс -- Выставляет СТОП-ЛОСС и ТЭЙК-ПРОФИТ, ЖДЕТ пока он сработает, принимает ЦЕНУ и ТИП ["BUY", или "SELL"] открытой сделки, --- возвращает FALSE, если не удалось выставить СТОП-ЛОСС и ТЭЙК-ПРОФИТ, или TRUE, если сделка закрылась, --- либо NIL, если при ошибке за 10 попыток не удалось принудительно закрыть позицию Result = SL_TP(Price, CurrentDirect); -- Если сделка закрылась if Result == true then -- Прерывает цикл FOR break; end; end; -- Если за 10 попыток не удалось закрыть позицию if Result == nil or Result == false then -- Выводит сообщение message('Простой MA-робот: После 10-и попыток не удалось закрыть сделку!!! Завершение скрипта!!!'); -- Завершает выполнение скрипта Run = false; -- Прерывает основной цикл WHILE break; else -- УДАЛОСЬ ЗАКРЫТЬ СДЕЛКУ -- Выводит сообщение message('Простой MA-робот: Сделка закрыта по СТОП-ЛОССУ, либо ТЭЙК-ПРОФИТУ'); --Меняет СОСТОЯНИЕ робота на "В ПОИСКЕ ТОЧКИ ВХОДА" ROBOT_STATE = 'В ПОИСКЕ ТОЧКИ ВХОДА'; -- Выводит сообщение message('Простой MA-робот: В ПОИСКЕ ТОЧКИ ВХОДА'); end; else -- Сделку не удалось открыть -- Если первый раз пытался открыть SELL, а операции шорт по данному инструменту запрещены if CurrentDirect == "SELL" and SEC_NO_SHORT then -- Выводит сообщение message('Простой MA-робот: Была первая попытка совершить запрещенную операцию шорт! Больше этого не повторится:)'); --Меняет СОСТОЯНИЕ робота на "В ПОИСКЕ ТОЧКИ ВХОДА" ROBOT_STATE = 'В ПОИСКЕ ТОЧКИ ВХОДА'; -- Выводит сообщение message('Простой MA-робот: В ПОИСКЕ ТОЧКИ ВХОДА'); else -- Выводит сообщение message('Простой MA-робот: После 10-и попыток не удалось открыть сделку!!! Завершение скрипта!!!'); -- Завершает выполнение скрипта Run = false; end; end; else -- СОСТОЯНИЕ робота 'В ПОИСКЕ ТОЧКИ ВХОДА' -- Если на этой свече еще не было открыто позиций if DS:Size() > LastOpenBarIndex then -- Если быстрая пересекла медленную СНИЗУ ВВЕРХ if FastMA(DS:Size()-1) <= SlowMA(DS:Size()-1) and FastMA() > SlowMA() then -- Задает направление НА ПОКУПКУ CurrentDirect = 'BUY'; message('CurrentDirect = "BUY"'); -- Меняет СОСТОЯНИЕ робота на "В ПРОЦЕССЕ СДЕЛКИ" ROBOT_STATE = 'В ПРОЦЕССЕ СДЕЛКИ'; -- Если быстрая пересекла медленную СВЕРХУ ВНИЗ elseif FastMA(DS:Size()-1) >= SlowMA(DS:Size()-1) and FastMA() < SlowMA() then -- Если по данному инструменту не запрещены операции шорт if not SEC_NO_SHORT then -- Задает направление НА ПРОДАЖУ CurrentDirect = 'SELL'; message('CurrentDirect = "SELL"'); -- Меняет СОСТОЯНИЕ робота на "В ПРОЦЕССЕ СДЕЛКИ" ROBOT_STATE = 'В ПРОЦЕССЕ СДЕЛКИ'; end; end; end; end; sleep(10);--Пауза 10 мс, для того, чтобы не перегружать процессор компьютера end; end; -- Функция вызывается терминалом QUIK при получении ответа на транзакцию пользователя function OnTransReply(trans_reply) -- Если поступила информация по текущей транзакции if trans_reply.trans_id == trans_id then -- Передает статус в глобальную переменную trans_Status = trans_reply.status; -- Передает сообщение в глобальную переменную trans_result_msg = trans_reply.result_msg; end; end; -- Функция ВЫЗЫВАЕТСЯ ТЕРМИНАЛОМ QUIK при остановке скрипта function OnStop() Run = false; end; ----------------------------- -- ВСПОМОГАТЕЛЬНЫЕ ФУНКЦИИ -- ----------------------------- -- Совершает СДЕЛКУ указанного типа (Type) ["BUY", или "SELL"] по рыночной(текущей) цене размером в 1 лот, --- возвращает цену открытой сделки, либо FALSE, если невозможно открыть сделку function Trade(Type) --Получает ID транзакции trans_id = trans_id + 1; local Price = 0; local Operation = ''; --Устанавливает цену и операцию, в зависимости от типа сделки и от класса инструмента if Type == 'BUY' then if CLASS_CODE ~= 'QJSIM' and CLASS_CODE ~= 'TQBR' then Price = getParamEx(CLASS_CODE, SEC_CODE, 'offer').param_value + 10*SEC_PRICE_STEP;end; -- по цене, завышенной на 10 мин. шагов цены Operation = 'B'; else if CLASS_CODE ~= 'QJSIM' and CLASS_CODE ~= 'TQBR' then Price = getParamEx(CLASS_CODE, SEC_CODE, 'bid').param_value - 10*SEC_PRICE_STEP;end; -- по цене, заниженной на 10 мин. шагов цены Operation = 'S'; end; -- Заполняет структуру для отправки транзакции local Transaction={ ['TRANS_ID'] = tostring(trans_id), ['ACTION'] = 'NEW_ORDER', ['CLASSCODE'] = CLASS_CODE, ['SECCODE'] = SEC_CODE, ['OPERATION'] = Operation, -- операция ("B" - buy, или "S" - sell) ['TYPE'] = 'M', -- по рынку (MARKET) ['QUANTITY'] = '1', -- количество ['ACCOUNT'] = ACCOUNT, ['PRICE'] = tostring(Price), ['CLIENT_CODE']= 'Простой MA-робот' } -- Отправляет транзакцию sendTransaction(Transaction); -- Ждет, пока получит статус текущей транзакции (переменные "trans_Status" и "trans_result_msg" заполняются в функции OnTransReply()) while Run and trans_Status == nil do sleep(1); end; -- Запоминает значение local Status = trans_Status; -- Очищает глобальную переменную trans_Status = nil; -- Если транзакция не выполнена по какой-то причине if Status ~= 3 then -- Если данный инструмент запрещен для операции шорт if Status == 6 then -- Выводит сообщение message('Простой MA-робот: Данный инструмент запрещен для операции шорт!'); SEC_NO_SHORT = true; else -- Выводит сообщение с ошибкой message('Простой MA-робот: Транзакция не прошла!\nОШИБКА: '..trans_result_msg); end; -- Возвращает FALSE return false; else --Транзакция отправлена local OrderNum = nil; --ЖДЕТ пока ЗАЯВКА на ОТКРЫТИЕ сделки будет ИСПОЛНЕНА полностью --Запоминает время начала в секундах local BeginTime = os.time(); while Run and OrderNum == nil do --Перебирает ТАБЛИЦУ ЗАЯВОК for i=0,getNumberOf('orders')-1 do local order = getItem('orders', i); --Если заявка по отправленной транзакции ИСПОЛНЕНА ПОЛНОСТЬЮ if order.trans_id == trans_id and order.balance == 0 then --Запоминает номер заявки OrderNum = order.order_num; --Прерывает цикл FOR break; end; end; --Если прошло 10 секунд, а заявка не исполнена, значит произошла ошибка if os.time() - BeginTime > 9 then -- Выводит сообщение с ошибкой message('Простой MA-робот: Прошло 10 секунд, а заявка не исполнена, значит произошла ошибка'); -- Возвращает FALSE return false; end; sleep(10); -- Пауза 10 мс, чтобы не перегружать процессор компьютера end; --ЖДЕТ пока СДЕЛКА ОТКРЫТИЯ позиции будет СОВЕРШЕНА --Запоминает время начала в секундах BeginTime = os.time(); while Run do --Перебирает ТАБЛИЦУ СДЕЛОК for i=0,getNumberOf('trades')-1 do local trade = getItem('trades', i); --Если сделка по текущей заявке if trade.order_num == OrderNum then --Возвращает фАКТИЧЕСКУЮ ЦЕНУ открытой сделки return trade.price; end; end; --Если прошло 10 секунд, а сделка не совершена, значит на демо-счете произошла ошибка if os.time() - BeginTime > 9 then -- Выводит сообщение с ошибкой message('Простой MA-робот: Прошло 10 секунд, а сделка не совершена, значит на демо-счете произошла ошибка'); -- Возвращает FALSE return false; end; sleep(10); -- Пауза 10 мс, чтобы не перегружать процессор компьютера end; end; end; -- ПРИНУДИТЕЛЬНО ЗАКРЫВАЕТ ОТКРЫТУЮ ПОЗИЦИЮ переданного типа (Type) ["BUY", или "SELL"] function KillPos(Type) -- Дается 10 попыток local Count = 0; -- Счетчик попыток if Type == 'BUY' then -- Пока скрипт не остановлен и позиция не закрыта while Run and not Trade('SELL') do -- Открывает SELL, тем самым закрывая BUY, если Trade('SELL') вернет TRUE, цикл прекратится Count = Count + 1; -- Увеличивает счетчик -- Если за 10 попыток не удалось закрыть позицию if Count == 10 then -- Возвращает NIL return nil; end; sleep(100); -- Пауза 100 мс, чтобы изменилась ситуация на сервере end; else -- Пока скрипт не остановлен и позиция не закрыта while Run and not Trade('BUY') do -- Открывает BUY, тем самым закрывая SELL, если Trade('BUY') вернет TRUE, цикл прекратится Count = Count + 1; -- Увеличивает счетчик -- Если за 10 попыток не удалось закрыть позицию if Count == 10 then -- Возвращает NIL return nil; end; sleep(100); -- Пауза 100 мс, чтобы изменилась ситуация на сервере end; end; -- Возвращает TRUE, если удалось принудительно закрыть позицию return true; end; -- Выставляет СТОП-ЛОСС и ТЭЙК-ПРОФИТ, ЖДЕТ пока он сработает, принимает ЦЕНУ (Price) и ТИП (Type) ["BUY", или "SELL"] открытой сделки, --- возвращает FALSE, если не удалось выставить СТОП-ЛОСС и ТЭЙК-ПРОФИТ, либо TRUE, если сделка закрылась, --- либо NIL, если при ошибке за 10 попыток не удалось принудительно закрыть позицию function SL_TP(Price, Type) -- ID транзакции trans_id = trans_id + 1; -- Находит направление для заявки local operation = ""; local price = "0"; -- Цена, по которой выставится заявка при срабатывании Стоп-Лосса (для рыночной заявки по акциям должна быть 0) local stopprice = ""; -- Цена Тэйк-Профита local stopprice2 = ""; -- Цена Стоп-Лосса local market = "YES"; -- После срабатывания Тэйка, или Стопа, заявка сработает по рыночной цене -- Если открыт BUY, то направление стоп-лосса и тэйк-профита SELL, иначе направление стоп-лосса и тэйк-профита BUY if Type == 'BUY' then operation = "S"; -- Тэйк-профит и Стоп-лосс на продажу(чтобы закрыть BUY, нужно открыть SELL) -- Если не акции if CLASS_CODE ~= 'QJSIM' and CLASS_CODE ~= 'TQBR' then price = tostring(math.floor(getParamEx(CLASS_CODE, SEC_CODE, 'PRICEMIN').param_value)); -- Цена выставляемой заявки после страбатывания Стопа минимально возможная, чтобы не проскользнуло market = "NO"; -- После срабатывания Тэйка, или Стопа, заявка сработает НЕ по рыночной цене end; stopprice = tostring(Price + TAKE_PROFIT*SEC_PRICE_STEP); -- Уровень цены, когда активируется Тэйк-профит stopprice2 = tostring(Price - STOP_LOSS*SEC_PRICE_STEP); -- Уровень цены, когда активируется Стоп-лосс else -- открыт SELL operation = "B"; -- Тэйк-профит и Стоп-лосс на покупку(чтобы закрыть SELL, нужно открыть BUY) -- Если не акции if CLASS_CODE ~= 'QJSIM' and CLASS_CODE ~= 'TQBR' then price = tostring(math.floor(getParamEx(CLASS_CODE, SEC_CODE, 'PRICEMAX').param_value)); -- Цена выставляемой заявки после страбатывания Стопа максимально возможная, чтобы не проскользнуло market = "NO"; -- После срабатывания Тэйка, или Стопа, заявка сработает НЕ по рыночной цене end; stopprice = tostring(Price - TAKE_PROFIT*SEC_PRICE_STEP); -- Уровень цены, когда активируется Тэйк-профит stopprice2 = tostring(Price + STOP_LOSS*SEC_PRICE_STEP); -- Уровень цены, когда активируется Стоп-лосс end; -- Заполняет структуру для отправки транзакции на Стоп-лосс и Тэйк-профит local Transaction = { ["ACTION"] = "NEW_STOP_ORDER", -- Тип заявки ["TRANS_ID"] = tostring(trans_id), ["CLASSCODE"] = CLASS_CODE, ["SECCODE"] = SEC_CODE, ["ACCOUNT"] = ACCOUNT, ["OPERATION"] = operation, -- Операция ("B" - покупка(BUY), "S" - продажа(SELL)) ["QUANTITY"] = "1", -- Количество в лотах ["PRICE"] = price, -- Цена, по которой выставится заявка при срабатывании Стоп-Лосса (для рыночной заявки по акциям должна быть 0) ["STOPPRICE"] = stopprice, -- Цена Тэйк-Профита ["STOP_ORDER_KIND"] = "TAKE_PROFIT_AND_STOP_LIMIT_ORDER", -- Тип стоп-заявки ["EXPIRY_DATE"] = "TODAY", -- Срок действия стоп-заявки ("GTC" – до отмены,"TODAY" - до окончания текущей торговой сессии, Дата в формате "ГГММДД") -- "OFFSET" - (ОТСТУП)Если цена достигла Тэйк-профита и идет дальше в прибыль, -- то Тэйк-профит сработает только когда цена вернется минимум на 2 шага цены назад, -- это может потенциально увеличить прибыль ["OFFSET"] = tostring(2*SEC_PRICE_STEP), ["OFFSET_UNITS"] = "PRICE_UNITS", -- Единицы измерения отступа ("PRICE_UNITS" - шаг цены, или "PERCENTS" - проценты) -- "SPREAD" - Когда сработает Тэйк-профит, выставится заявка по цене хуже текущей на 100 шагов цены, -- которая АВТОМАТИЧЕСКИ УДОВЛЕТВОРИТСЯ ПО ТЕКУЩЕЙ ЛУЧШЕЙ ЦЕНЕ, -- но то, что цена значительно хуже, спасет от проскальзывания, -- иначе, сделка может просто не закрыться (заявка на закрытие будет выставлена, но цена к тому времени ее уже проскочит) ["SPREAD"] = tostring(100*SEC_PRICE_STEP), ["SPREAD_UNITS"] = "PRICE_UNITS", -- Единицы измерения защитного спрэда ("PRICE_UNITS" - шаг цены, или "PERCENTS" - проценты) -- "MARKET_TAKE_PROFIT" = ("YES", или "NO") должна ли выставится заявка по рыночной цене при срабатывании Тэйк-Профита. -- Для рынка FORTS рыночные заявки, как правило, запрещены, -- для лимитированной заявки на FORTS нужно указывать заведомо худшую цену, чтобы она сработала сразу же, как рыночная ["MARKET_TAKE_PROFIT"] = market, ["STOPPRICE2"] = stopprice2, -- Цена Стоп-Лосса ["IS_ACTIVE_IN_TIME"] = "NO", -- "MARKET_TAKE_PROFIT" = ("YES", или "NO") должна ли выставится заявка по рыночной цене при срабатывании Стоп-Лосса. -- Для рынка FORTS рыночные заявки, как правило, запрещены, -- для лимитированной заявки на FORTS нужно указывать заведомо худшую цену, чтобы она сработала сразу же, как рыночная ["MARKET_STOP_LIMIT"] = market, ["CLIENT_CODE"] = "Простой MA-робот ТЭЙК-ПРОФИТ и СТОП-ЛОСС" } -- Отправляет транзакцию на установку ТЭЙК-ПРОФИТ и СТОП-ЛОСС sendTransaction(Transaction); -- Ждет, пока не получит статус текущей транзакции (переменные "trans_Status" и "trans_result_msg" заполняются в функции OnTransReply()) while Run and trans_Status == nil do sleep(10); end; -- Запоминает значение local Status = trans_Status; -- Очищает глобальную переменную trans_Status = nil; -- Если транзакция не выполнена по какой-то причине if Status ~= 3 then -- Выводит сообщение с ошибкой message('Простой MA-робот: Установка ТЭЙК-ПРОФИТ и СТОП-ЛОСС не удалась!\nОШИБКА: '..trans_result_msg); -- Возвращает FALSE return false; else -- Выводит сообщение message('Простой MA-робот: ВЫСТАВЛЕНА заявка ТЭЙК-ПРОФИТ и СТОП-ЛОСС: '..trans_id); local OrderNum_CLOSE = nil; -- ЖДЕТ пока СТОП-ЗАЯВКА на СТОП-ЛОСС и ТЭЙК-ПРОФИТ будет ИСПОЛНЕНА полностью while Run and OrderNum_CLOSE == nil do -- Перебирает ТАБЛИЦУ СТОП-ЗАЯВОК for i=0,getNumberOf("stop_orders")-1 do local stop_order = getItem("stop_orders", i); -- Если заявка по текущей транзакции СТОП-ЛОСС и ТЭЙК-ПРОФИТ if stop_order.trans_id == trans_id then -- Если заявка по отправленной СТОП-ЛОСС и ТЭЙК-ПРОФИТ транзакции ИСПОЛНЕНА ПОЛНОСТЬЮ if stop_order.balance == 0 then -- Если по наступлению стоп-цены выставлена заявка if stop_order.linkedorder > 0 then -- Запоминает номер заявки, которая была создана при срабатывании СТОП-ЛОСС, или ТЭЙК-ПРОФИТ OrderNum_CLOSE = stop_order.linkedorder; -- Прерывает цикл FOR break; -- Стоп-заявка сработала, но была отвергнута торговой системой elseif CheckBit(stop_order.flags, 10) == 1 then -- ПРИНУДИТЕЛЬНО ЗАКРЫВАЕТ ОТКРЫТУЮ ПОЗИЦИЮ и выходит из функции return KillPos(Type); end; end; end; end; sleep(10); -- Пауза 10 мс, чтобы не перегружать процессор компьютера end; --ЖДЕТ пока СДЕЛКА ЗАКРЫТИЯ позиции будет СОВЕРШЕНА --Запоминает время начала в секундах BeginTime = os.time(); while Run do --Перебирает ТАБЛИЦУ СДЕЛОК for i=0,getNumberOf("trades")-1 do local trade = getItem("trades", i); --Если сделка по текущей заявке на СТОП-ЛОСС и ТЭЙК-ПРОФИТ if trade.order_num == OrderNum_CLOSE then -- Возвращает TRUE return true; end; end; --Если прошло 10 секунд, а сделка не совершена, значит на демо-счете произошла ошибка сервера "Обработка кросс-заявок блокирована" if os.time() - BeginTime > 9 then -- ПРИНУДИТЕЛЬНО ЗАКРЫВАЕТ ОТКРЫТУЮ ПОЗИЦИЮ и выходит из функции return KillPos(Type); end; sleep(1); end; end; end; -- Возвращает ЗНАЧЕНИЕ МЕДЛЕННОЙ скользящей по индексу свечи (по умолчанию: последняя) function SlowMA(Index) -- Если индекс свечи не указан, то устанавливает индекс последней свечи if Index == nil then Index = DS:Size(); end; -- Сумма значений SLOW_MA_SOURCE на SLOW_MA_PERIOD свечах local Sum = 0; -- Перебирает последние SLOW_MA_PERIOD свечей for i=Index, Index - (SLOW_MA_PERIOD - 1), -1 do -- Считает сумму, исходя из выбранного источника для медленной скользящей if SLOW_MA_SOURCE == 'O' then Sum = Sum + DS:O(i); elseif SLOW_MA_SOURCE == 'C' then Sum = Sum + DS:C(i); elseif SLOW_MA_SOURCE == 'H' then Sum = Sum + DS:H(i); elseif SLOW_MA_SOURCE == 'L' then Sum = Sum + DS:L(i); else message('Простой MA-робот:ОШИБКА! Не верно указан источник для медленной скользящей!'); -- Останавливает скрипт OnStop(); end; end; -- Возвращает значение return Sum/SLOW_MA_PERIOD; end; -- Возвращает ЗНАЧЕНИЕ БЫСТРОЙ скользящей по индексу свечи (по умолчанию: последняя) function FastMA(Index) -- Если индекс свечи не указан, то устанавливает индекс последней свечи if Index == nil then Index = DS:Size(); end; -- Сумма значений FAST_MA_SOURCE на FAST_MA_PERIOD свечах local Sum = 0; -- Перебирает последние FAST_MA_PERIOD свечей for i=Index, Index - (FAST_MA_PERIOD - 1), -1 do -- Считает сумму, исходя из выбранного источника для быстрой скользящей if FAST_MA_SOURCE == 'O' then Sum = Sum + DS:O(i); elseif FAST_MA_SOURCE == 'C' then Sum = Sum + DS:C(i); elseif FAST_MA_SOURCE == 'H' then Sum = Sum + DS:H(i); elseif FAST_MA_SOURCE == 'L' then Sum = Sum + DS:L(i); else message('Простой MA-робот:ОШИБКА! Не верно указан источник для быстрой скользящей!'); -- Останавливает скрипт OnStop(); end; end; -- Возвращает значение return Sum/FAST_MA_PERIOD; end; -- Функция возвращает значение бита (число 0, или 1) под номером bit (начинаются с 0) в числе flags, если такого бита нет, возвращает nil function CheckBit(flags, bit) -- Проверяет, что переданные аргументы являются числами if type(flags) ~= "number" then error("Предупреждение!!! Checkbit: 1-й аргумент не число!"); end; if type(bit) ~= "number" then error("Предупреждение!!! Checkbit: 2-й аргумент не число!"); end; local RevBitsStr = ""; -- Перевернутое (задом наперед) строковое представление двоичного представления переданного десятичного числа (flags) local Fmod = 0; -- Остаток от деления local Go = true; -- Флаг работы цикла while Go do Fmod = math.fmod(flags, 2); -- Остаток от деления flags = math.floor(flags/2); -- Оставляет для следующей итерации цикла только целую часть от деления RevBitsStr = RevBitsStr ..tostring(Fmod); -- Добавляет справа остаток от деления if flags == 0 then Go = false; end; -- Если был последний бит, завершает цикл end; -- Возвращает значение бита local Result = RevBitsStr :sub(bit+1,bit+1); if Result == "0" then return 0; elseif Result == "1" then return 1; else return nil; end; end; |
Если у Вас появились какие-то вопросы, задайте их в комментариях под статьей !!!
Надо поправить, если необходимо указать конкретную дату окончания заявки тэйк-профит, то дата должна быть в формате не "ГГММДД", а "ГГГГММДД".
["EXPIRY_DATE"] = ..... Дата в формате "ГГГГММДД")
Добрый день, может не совсем по теме. А как сделать так чтобы включение было по пересечению 2х одинаковых МАшек со смещением? Заранее спасибо!))
Добрый день, нужно менять формулу расчета в одной из функций SlowMA, или FastMA, а вообще, лучше не использовать этого робота, он какой-то перемудреный 🙂
Я понимаю, что нужно поменять формулу расчета, но как? Где прописывать шифт?
Вы знакомы с программированием?
Пока только изучаю. В МТ4 в параметрах МА прописывается просто сдвиг, а в LUA не пойму как...
Используйте стандартный индикатор МА, просто получайте в скрипте его значения, не обязательно индикаторы самостоятельно рассчитывать
https://quikluacsharp.ru/quik-qlua/poluchenie-v-qlua-lua-dannyh-iz-grafikov-i-indikatorov/
Спасибо, все получилось!))
Всегда пожалуйста! 🙂
Добрый день.
Я правльно понимаю, что в роботе не релизован вариант переворота позиции.
Нет ли простого примера для реализации оного?
Здравствуйте! Переворота в нем нет. Примера простого нет, к сожалению, но есть готовый набор вспомогательных функций (раздел меню "Нужные функции"), используя которые, можно любой алгоритм написать, при условии, что Вы научились уже получать информацию из таблиц, графиков и индикаторов, если нет, то раздел меню "Quik + QLua(Lua)" - "Обмен данными" Вам в помощь, так же, рекомендую изучить раздел "QLua основы" - "Работа с датой/временем".
Значения МА на графике и значение МА рассчитанное роботом иногда совпадают, а иногда разняться - кто правильно считает все таки.
Думаю в расчетах робота какой-то косяк
Код функцию МА в студию скину? посмотришь? Я сделал как у тебя - вроде все правильно - сегодня еще день посвятил тому что наблюдал и полазил по сайтам как кто что делает - все так делают - как написано. Других подходов по расчетам МА не нашел и не увидел. Кидаю часть кода?
Кидай, только я завтра посмотрю, вырубаюсь уже
Нормально, вроде, просто, конечно же, CreateDataSource вызывается один раз в начале скрипта и еще нужно подписаться на обновления графика при помощи SetEmptyCallback
SetEmptyCallback - а в коде у тебя нет такой подписки
Этот робот вообще кривой весь, надо вообще удалить уже эту статью 🙂
Вот: https://quikluacsharp.ru/quik-qlua/poluchenie-v-qlua-lua-dannyh-iz-grafikov-i-indikatorov/
Здравствуйте!
Задался вопросом, кроме непосредственно реализации торгового алгоритма какие составные ещё могут быть предусмотрены в роботе, что бы он был жизнеспособен как программа: не слетал, не зависал (если можно выразиться - модули, блоки, обеспечивающие корректность работы)? Может кто-то может поделиться своей точкой зрения, опытом? С уважением. Благодарю.
Здесь тоже подправил немного, на всякий случай 🙂 А, вообще, если график открыт в терминале, то можно и без SetEmptyCallback
Все понятно как всегда - щас подправлю у себя. Спасибо. Но в принципе то расчет же у меня верный, почему все таки данные разнятся - ну сейчас подписку сделаю может поможет.
Пожалуйста
Проверил - результат - разные, иногда одинаковые данные - сравнивал Квик индикаторы на графике с данными бота - разнобой.
Возможно параметры расчетов не совпадают.
Дмитрий, ты меня таким вопросом "оскорбил" - я че дебил по твоему, совпадают конечно (проверял и перепроверял не однократно). Говорю иногда значения один в один, но чаще всего разные в пунктов 5 примерно - на Si реал 1 минута. Я подозреваю может индикатор тот что в Квике по другому, более сложно высчитывает и более правильно (по графику то индюк хорошо показывает, а вот бот косячит) нежели чем расчет Lua (ну все так считают как у тебя написано). Но в принципе этот вопрос то же можно обойти поставить некий фильтр да и все. Моя задача получить более менее надежное пересечение - если будет 50/50 (что сейчас и происходит), то у меня там все равно есть свои фишки как ложные пробои отработать.
Ни в коем случае не хотел обидеть, просто дьявол в мелочах всегда кроется, чаще всего ошибка на поверхности, где даже не думал, с какого периода расхождения начинаются ? На периоде 1 не может ведь быть расхождений, это же просто цена закрытия будет.
На обиженных воду возят поговорка такая есть вроде бы - я про оскорбление же пошутил - все четко - правильный вопрос ты задал, что настройки индикатора типа проверь - да это так, все проверяю все делаю и если тупик то к тебе на сайт бегом - тупых или дурацких то вопросов вроде не задаю, сначала сам пытаюсь разобраться ну как ты и говорил и всем такой посыл - сначала сами, потом сюда к Дмитрию (а то есть чуваки разжуй им, тесты проведи и деньги еще им отдай - ну это то же +/- шутка).
"просто дьявол в мелочах всегда кроется" - смотришь в книгу видишь фигу - да так бывает - но это чисто если код пишешь и там есть ошибки - здесь в расчетах МА ошибок то нет - НО возможно что то где то не так надо искать и рыть буду смотреть делать
"чаще всего ошибка на поверхности, где даже не думал" - Дак да так и есть просто че то не вижу видимо
"с какого периода расхождения начинаются" - Я просто текущую свечу с показаниями бота (в таблице бота выведены) сравниваю
На периоде 1 не может ведь быть расхождений, это же просто цена закрытия будет - дак и я о том же - но происходит это - если вот интересен этот вопрос и время есть сам проверь увидишь
Еще как вариант может все таки я где то что не понял и накосячил - ну как вариант то же возможно - хотя функция вверху вот такая ей считаю
Попробую завтра посмотреть
Ну посмотри пожалуйста, просто интересно сравнить результаты и тему все таки эту отработать и добить.
Во первых я не знаю что такое функция RtS, а во вторых, я думаю, что все дело в том, что у тебя в коде идет разбег по времени. Если ты в коллбеке графика считаешь ма, то он, скорее всего сначала приходит в скрипт, а потом ма на графике пересчитывается, в тот момент когда ты посчитал свою ма, ма на графике еще не пересчиталась. Либо наоборот, ты берешь значение ма с графика, а потом считаешь свою, но в скрипте ты берешь последнее значение из DS, а оно может успеть поменяться в момент расчета и опять несовпадение, попробуй отключиться от сервера и тогда считай и сравнивай.
RtS - округляет до шага цены инструмента.
А так что то не понял совсем.
DS:SetEmptyCallback() - Эту строку убрать? Так ее и не было у меня первоначально - с ней и без нее все равно не так считает
Ты не понял что я имел в виду, SetEmptyCallback убирать не нужно, нужно при разорванном соединении с сервером тестировать, чтобы исключить изменяющуюся в моменте цену закрытия последней свечи.
Попробовал разорвать соединение сравнил - та же картина.
Щас только заметил при включенном графике все работает, если графика нет терминал виснет сразу и потом только перезагрузка. Удалил эту часть кода - график открыт - ну понятно все работает, графика нет - робот включается и 1-2 сек ждет потом начинает данные показывать.
Вот такой скрипт нормально работает (проверял):
Спасибо щас то же поставлю
Повфавуйфта 🙂
Ну короче рано радовались - запустил и твой скрипт в месседже смотрел смотрел - как назло все было одинаково (долго наблюдал), а сейчас смотрю (твой расчет вписал в своего бота для сравнения с моим расчетом - один в один все те же цифры ни разу не видел расхождений - наблюдаю долго), а с графиком щас вот опять пошло расхождение - я так заметил когда тихо спокойно, то все четко цифры одинаковые - как только дернулась цена, то все значения разные - вот так вот (ну наши расчеты одинаковые, а график другой)
Может у тебя скрипт как-то терминал подвешивает в моменты движений и он отрисовываться не успевает.
А при чем здесь мой скрипт (скрипты, боты мои в подвешивании терминала ни разу не были уличены - все четко работает) я смотрю в меседже за твоим скриптом и твоим расчетом/моим расчетом один в один все показывает. В меседже твой код то же расходится с графиком - я долго наблюдаю (сначала все с графиком сходилось щас пошли разночтения ну иногда так как в графике иногда нет)
Не знаю, короче, я что такое происходит у тебя там 🙂
Ну хочешь скину свой код тебе на почту - там уже вписан твой расчет и посмотришь - если да то да нет так нет
Скидывай
Расчеты выполняются правильно. Проблема в том, что в последней ("сырой") 1-минутке, при том, что ее индекс в течении одной минуты не изменяется, ее значение меняется из-за поступления новых данных. Пересчет скользящей выполняется с частотой 100 гц и поэтому она бывает разной.
я не нашёл, можете попустил? а где указывается количество Лотов для торговли? Робот будет торговать только одним лотом? или этот параметр можно изменить? Где?
я нашёл в тексте торгует 1 лотом. а в программе там где "дополнительные функции" с строки 214 до строки 224 есть данные 1 лот - количество. Значит если там изменить данные на другое количество, то этого достаточно , чтобы он торговал другим количеством лотов? или что-т еще требуется?
а вот на 371 строке еще надо заполнить количество лотов для сто лося и тэйк профит.
доброго времени суток
возникла такая проблема - из программы по сигналу отправляется команда в скрипт в виде строки и распарсивается на вменяемую команду, которую квик без проблем съедает, далее выставляется заявка на покупку/продажу по рынку И сразу же снимается
в чем может быть подвох или проблема?
цена, по которой выставляется заявка, берется из стакана в режиме онлайн
Здравствуйте! Чудес не бывает, подвох в заложенном в скрипт алгоритме, смотрите что делает каждая строка скрипта и найдете причину.
Вечер добрый, Дмитрий!
Помогите разобраться с кодом, сам не знаю что вышло:
при пересечении средних появляется только сообщение, например "Простой MA-робот: пересечение СНИЗУ ВВЕРХ"
Что-то не так наваял 🙂
Буду признателен за указание на ошибки.
п.с. знаки больше, меньше или равно не отражаются, но в коде присутствуют и работаю, так как сообщение о пересечении приходит своевременно
Здравствуйте! А что не работает-то? В приведенном Вами коде кроме вывода сообщений больше ничего и нет.
Есть в нем ошибка:
local totalnet == nil
чтобы присвоить значение переменной используется одинарный знак равно, а у Вас двойной, двойной используется в выражениях сравнения только. По идее, такой скрипт вообще не должен запускаться, а должно появляться сообщение о синтаксической ошибке в окне "Доступные скрипты" и в "Таблица сообщений", которую можно открыть нажав F7 и "Таблица сообщений"
А еще вот здесь getItem("FUTURES_CLIENT_HOLDING",i).SEC_CODE должно быть вот так getItem("FUTURES_CLIENT_HOLDING",i).sec_code
Спасибо, Дмитрий, за подсказку на строчные буквы в коде.
Я пытался изобразить логику: перебор таблицы "Позиции по клиентским счетам (фьючерсы)", при отсутствии чистых сделок задать направление и изменить состояние робота, но явно что-то не учел, что не дает коду работать дальше сообщения
Всегда пожалуйста! Ставьте message после каждой строки и увидите как код работает, или где перестает работать. Возможно у Вас в таблице позиций по счетам нет ни одной строки и цикл for не выполняется по этому, в общем, когда не понятно что происходит, нужно месседжами узнавать, т.е. отладку делать.
Отлично, методом месседжей самое то!
Спасибо за совет, иначе у меня знаний недостаточно узнать где косяк в коде 🙂
Но логика ведь есть в том, что я описал?
п.с. если нет строк в таблице=нет чистых позиций то подаем заявку, как то так задумывал ведь
Всегда пожалуйста, логика есть, если таблица пуста, то for ни разу не отработает и выполнение кода сразу уйдет ниже for. Ну, в общем, message'ы все покажут 🙂
Приветствую, Дмитрий.
Изменил Ваш код с отработкой на вход/выход только по условию пересечения средних. При тестировании на демо в Quik заметил, что иногда открывается в том же направлении еще одна позиция без видимого пересечения на графике Quik (видно разрабы заложили в алгоритм прорисовки линий некий фильтр), после чего при закрытии свечи пересечения на графике так и не происходит. Думаю причина в шумовых выбросах цены с последующим отловом Вашим кодом расчета момента пересечения по значениям МА.
Как можно исключить последовательное открытие в одном направлении более одной заявки?
Думаю, такая проверка (контроль кол-ва открытых позиций) должна быть ПОСЛЕ проверки условия на пересечение МА и ДО смены направления. Заранее благодарен
Здравствуйте! Заведите переменную и запоминаете в ней индекс свечи, на которой открываете позицию и, перед открытием новой позиции, проверяйте не равен ли индекс текущей свечи индексу, на котором была открыта предыдущая позиция. Если равен, то не открывайте больше, если не равен, то открывайте и сохраняйте текущий индекс в этой переменной.
спасибо, буду пробовать 🙂
Всегда пожалуйста:)
Здравстуйте! А как можно с помощью <> изменить размер стопа (если например 2 тейка и один сработал) или размер тейка (если например было усреднение и надо тейк изменить)?
Т.е. чтоб не делать лишних движений с удалениями старых и выставлениями новых...
часть строки не в шорткодах удалилась.
Здравствуйте! Только снимать старую стоп-заявку и выставлять новую.
Спасибо. Печально что так.
Пожалуйста, печально только в момент написания кода, потом робот будет это делать и Вас никак не будет это напрягать 🙂 В любом случае, любое изменение любой заявки происходит по факту с промежуточным снятием, даже если для этого используется всего одна транзакция.
Всем доброго времени суток! Объясните, пожалуйста, как снять все стоп заявки на FORTS?
Здравствуйте! А что так не работает?
TRANS_ID=2; CLASSCODE=SPBFUT; ACTION=KILL_ALL_STOP_ORDERS;
"Отправка транзакций данного типа из QPILE-скрипта не поддерживается"
А Вы не на QLua пишите? Я, кстати, не помню сейчас, помню только, что был какой-то нюанс с этим типом транзакций, вроде бы такая транзакция не поддерживается при отправке через библиотеку trans2quik.dll, но, мне кажется что через QLua должно работать. Если Вы на QPILE пишите, то я Вам ничего не подскажу, т.к. вообще не писал на нем никогда ничего, когда я познакомился с квиком, в нем уже была QLua и я ее сразу стал осваивать, тем более сейчас уже даже поддержку QPILE разработчики убрали, т.е. это "умирающая" технология и не рекомендуется ее использовать.
Пишу на LUA, загадка, что не так. А что-то наподобие KILL_ALL_FUTURES_ORDERS нет?
Уже который день написать не могу
Похоже QLua не поддерживает такую операцию, видимо выход один: перебирать таблицу стоп-заявок и снимать все активные, в принципе, довольно простая функция получится.
Вот какой ответ тех.поддержки нашел на форуме квика от 15.02.2016 10:46:21
Большое спасибо, теперь всё ясно. Буду убирать по одной
Всегда пожалуйста.
Теперь я решил снимать по одной заявке. Но мне выдаёт ошибку:"Не указан режим транзакции"
Вот код:
Вот такие поля только нужны: