Ми стикаємося з ситуацією: трейдери пишуть прості стратегії на QLUA, але для ML-моделей (LSTM, градієнтний бустинг) потрібні Python-бібліотеки та GPU. QUIK — домінуючий термінал на російських ринках (ММВБ, СПБ Біржа), а QLUA — вбудований Lua-скриптовий двигун. Проблема: QLUA не тягне важкі обчислення, а Python не вміє безпосередньо виставляти ордери. Рішення — асинхронний TCP-міст між QLUA та Python AI-сервером. Помилка в QLUA-скрипті може коштувати мільйони, а latency в 50 мс — перетворити прибуткову стратегію на збиткову. Наша команда усуває ці ризики, маючи за плечима понад 50 інтеграцій та 5+ років досвіду. Середній обсяг даних на один тік — 100 байт, що при 10 тіках на секунду дає навантаження 1 Кб/с — некритично.
Як працює інтеграція AI-бота з QUIK?
Основний підхід — QLUA-скрипт виступає посередником: отримує дані від терміналу, відправляє їх до Python по TCP, отримує сигнал та відправляє ордер. Це дає мінімальну затримку (p99 <10 мс) та повний контроль над ML-логікою. Розглянемо типову реалізацію.
QLUA + Python TCP Bridge
-- QLUA скрипт: отримує дані, відправляє Python, отримує сигнал
local socket = require("socket")
local json = require("json")
local client = socket.tcp()
client:connect("127.0.0.1", 5555)
function OnBar(class_code, sec_code, interval, candle)
if class_code == "TQBR" and sec_code == "SBER" then
local features = {
open = candle.open,
high = candle.high,
low = candle.low,
close = candle.close,
volume = candle.volume,
symbol = sec_code
}
client:send(json.encode(features) .. "\n")
local signal_str = client:receive("*l")
local signal = json.decode(signal_str)
if signal.action == "buy" then
SendOrder(sec_code, signal.price, signal.quantity, true)
elseif signal.action == "sell" then
SendOrder(sec_code, signal.price, signal.quantity, false)
end
end
end
function SendOrder(sec_code, price, qty, is_buy)
local trans = {
CLASSCODE = "TQBR",
SECCODE = sec_code,
OPERATION = is_buy and "B" or "S",
PRICE = tostring(price),
QUANTITY = tostring(qty),
ACCOUNT = "L01-00000F00",
TYPE = "L",
TRANS_ID = tostring(os.time())
}
sendTransaction(trans)
end
# Python AI-сервер
import socket
import json
import numpy as np
from your_ml_model import predict
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(('127.0.0.1', 5555))
server.listen(1)
conn, addr = server.accept()
buffer = ""
while True:
data = conn.recv(4096).decode()
buffer += data
if '\n' in buffer:
line, buffer = buffer.split('\n', 1)
features = json.loads(line)
signal = predict(features)
conn.send((json.dumps(signal) + '\n').encode())
Порівняння підходів до інтеграції
| Підхід | Отримання даних | Відправка ордерів | Затримка (p99) | Складність |
|---|---|---|---|---|
| QLUA+TCP | Так | Так | <10 мс | Середня |
| Trans2Quik | Ні | Так | <2 мс | Низька |
| QuikSharp | Так | Так | <5 мс | Висока |
Вибір між ними залежить від пріоритетів: якщо потрібен повний цикл — QLUA+TCP, якщо тільки швидка відправка — Trans2Quik. Для .NET-проєктів зручний QuikSharp, але він вимагає встановлення відповідного середовища.
Як уникнути втрати з'єднання?
При розриві TCP-з'єднання QLUA-скрипт може зависнути. Рішення — watchdog у Python-сервері, який перезапускає скрипт при втраті зв'язку. Також у QLUA використовуємо тайм-аути та повторні підключення. У таблиці нижче — типові затримки при різних способах отримання даних.
| Джерело даних | Частота оновлення | Затримка (мс) |
|---|---|---|
| OnBar (1 хв) | Кожну хвилину | 100-200 |
| OnTrade | Реалтайм | 10-50 |
| Level II (стакан) | Кожна зміна | 5-20 |
Отримання біржових даних
Фінам Data Feed — для ML навчання: історичні дані через Фінам API або експорт з QUIK. QLUA Data Tables — для потокових даних.
-- Отримання всіх угод з таблиці
local trades_table = getTable("trades")
local num_rows = #trades_table
-- Підписка на стакан
Subscribe_Level_II_Quotes("TQBR", "SBER")
local order_book = getParamEx2("TQBR", "SBER", "BID")
Специфіка російського ринку
Режим T+2 на ММВБ: облік в AI-стратегіях. Short позиції вимагають РЕПО або наявності цінних паперів. Брокерські комісії: типові 0.035–0.1% від обороту. Для дейтрейдингу це значуще. Брокерський збір + біржовий збір + НКД для облігацій.
Ф'ючерси та опціони через FORTS: окремий клас SPBFUT. Кодування тікерів (SiM5, RIM5). Годинне гарантійне забезпечення.
Що робити, якщо модель дає хибні сигнали?
Хибні сигнали — часта проблема ML-стратегій. Ми впроваджуємо фільтрацію: додаткова статистична перевірка (z-score, Z-test) перед відправкою ордера. Також використовуємо стоп-лоси та обмеження на кількість угод за хвилину.
Процес роботи
- Аналітика: обговорюємо стратегію, обираємо стек (QLUA+Python або інший).
- Проєктування: архітектура TCP-моста, типи ордерів, частоти даних.
- Розробка: пишемо QLUA-скрипт, Python AI-сервер, інтегруємо модель.
- Тестування: paper trading у QUIK, симуляція ринкових умов з різними режимами T+2 та FORTS.
- Деплой: налаштування моніторингу, автостарт скриптів, документація.
Строки та вартість
Інтеграція під ключ займає від 2 до 4 тижнів залежно від складності ML-моделі та кількості інструментів. Вартість розраховується індивідуально. Для орієнтиру: базова інтеграція QLUA+Python — від 2 тижнів, з навчанням моделі — до 2 місяців.
Чек-лист для запуску AI-бота
- Налаштувати watchdog для TCP-з'єднання
- Увімкнути логування всіх транзакцій QLUA
- Перевірити latency в пікових навантаженнях (більше 100 угод на секунду)
- Протестувати роботу з різними класами інструментів (TQBR, SPBFUT)
- Встановити ліміти на частоту ордерів
Що входить в роботу
- QLUA-скрипт з обробкою помилок та перепідключенням
- Python AI-сервер з інтеграцією вашої моделі
- Моніторинг через логи та метрики (latency, throughput)
- Документація по запуску та обслуговуванню
- Навчання команди (2 години)
- Підтримка 1 місяць після деплою
Документація QLUA описує всі події та функції. Для старту достатньо socket-модуля Lua та socket-модуля Python.
Оцініть ваш проєкт — напишіть нам, ми допоможемо підібрати оптимальну архітектуру. Замовте консультацію, щоб ми проаналізували вашу стратегію. Зв'яжіться з нами для обговорення деталей.







