Практика трейдинга и автоматизации под Московскую биржу

Трейдинг на MOEX: QUIK + LUA для исполнения, Python для аналитики

На этой странице — краткий “скелет” проекта: как обычно строят связку терминал QUIKскрипт на LUAPython-сервис для стратегий, риск-менеджмента, бэктестов и мониторинга.

Фьючерсы/акции/облигации
Поток котировок
Заявки и стоп-ордера
Логи, алерты, метрики
Тестирование стратегий
⚠️ Важно: торговля несёт риск. Автоматизацию запускают только после тестов, лимитов и защит (kill switch).

Московская биржа: что обычно автоматизируют

Технически чаще всего автоматизация сводится к получению данных, расчёту сигналов и управлению заявками.

Данные

Стакан, сделки, свечи, позиции, состояние портфеля, торговые сессии и статусы инструментов.

Сигналы

Спреды, тренд/контртренд, арбитраж, маркет-мейкинг, фильтры по волатильности и ликвидности.

Исполнение

Лимитные/рыночные заявки, стоп-ордера, сопровождение позиций, частичное исполнение, отмены.

Торговля в терминале QUIK

QUIK часто используют как “шлюз”: он получает данные от брокера и позволяет отправлять заявки через LUA.

1
Подключение

Настройка брокера/счёта, проверка доступов и торговых ограничений.

2
Подписки на данные

Таблицы/стакан/лента — выбираем минимум нужного, чтобы не перегружать терминал.

3
LUA-скрипт

Обрабатывает события, пишет логи, ставит/снимает заявки, общается с внешним сервисом.

4
Контроль

Ручная панель: пауза, аварийная остановка, состояние позиций, отчёты по сделкам.

LUA в QUIK: автоматизация исполнения

Скрипт в QUIK обычно делает самое “критичное”: реагирует на рынок и управляет заявками.

События

Обработка изменений стакана/сделок/свечей и статусов заявок.

Заявки

Создание/снятие/модификация заявок, стопов, контроль частичного исполнения.

Связь с Python

Отправка данных в локальный сервис (HTTP/сокеты/файлы) и получение команд/сигналов.

Python: исследования, стратегии и мониторинг

Python удобен для бэктестов, оптимизации параметров, интеграций (БД/Telegram/Prometheus) и UI.

Бэктест

Симуляция сделок по историческим данным, учёт комиссий/проскальзывания, проверка устойчивости.

Риск-менеджмент

Лимиты на позицию, дневной убыток, максимальный объём, фильтры волатильности.

Мониторинг

Журналы, алерты, метрики: latency, отказоустойчивость, состояние соединений и очередей.

Типовая архитектура

Один из простых вариантов — держать исполнение внутри QUIK, а “мозг” вынести в Python.

📈 QUIK получает котировки → LUA подписывается на события и нормализует данные
🔁 LUA отправляет события в Python gateway (локально) и получает команды
🧠 Python рассчитывает сигнал/лимиты → отдаёт команду “поставить/снять/изменить” заявку
🛡️ LUA применяет “последний рубеж” защиты: ограничение частоты, проверка цены/объёма, kill switch
Подсказка: если связь с Python пропала — LUA может автоматически перевести систему в безопасный режим (снять заявки / запретить новые).

Мини-примеры: LUA ↔ Python (шаблоны)

Ниже — безопасные “рыбки” кода без привязки к конкретным функциям брокера. Подставьте свои поля/методы.

LUA: отправка события в локальный HTTP endpoint
-- Псевдокод: отправка котировки/сигнала в локальный Python-сервис
-- В QUIK используются доступные вам способы связи (в т.ч. сокеты/файлы/HTTP через dll).
-- Здесь логика показана схематично.

local function to_json(tbl)
  -- замените на вашу JSON-сериализацию
  return string.format('{"ticker":"%s","price":%s,"ts":%s}', tbl.ticker, tbl.price, tbl.ts)
end

local function send_event(event)
  local payload = to_json(event)
  -- send_http("http://127.0.0.1:8000/event", payload) -- пример
  -- или write_to_file("events.log", payload .. "\n")
end

function onQuote(ticker, price)
  send_event({
    ticker = ticker,
    price = price,
    ts = os.time()
  })
end
Идея: LUA — “тонкий клиент” событий и исполнения, Python — расчёт и управление.
Python: приём события и выдача команды
# Псевдокод: простой HTTP сервер (Flask) и логика "сигнал -> команда"
# pip install flask

from flask import Flask, request, jsonify
import time

app = Flask(__name__)

STATE = {
    "last_price": {},
    "cooldown_until": 0
}

def decide(ticker: str, price: float):
    # Пример: очень условный "сигнал"
    # Замените на вашу стратегию + риск-лимиты
    prev = STATE["last_price"].get(ticker)
    STATE["last_price"][ticker] = price

    if prev is None:
        return None

    if price > prev * 1.002:
        return {"action": "BUY_LIMIT", "ticker": ticker, "qty": 1, "price": round(price * 0.999, 2)}
    if price < prev * 0.998:
        return {"action": "SELL_LIMIT", "ticker": ticker, "qty": 1, "price": round(price * 1.001, 2)}
    return None

@app.post("/event")
def event():
    data = request.get_json(force=True)
    ticker = data.get("ticker", "UNKNOWN")
    price = float(data.get("price", 0))

    # Пример простого "тормоза", чтобы не флудить командами
    now = time.time()
    if now < STATE["cooldown_until"]:
        return jsonify({"command": None, "reason": "cooldown"})

    cmd = decide(ticker, price)
    if cmd:
        STATE["cooldown_until"] = now + 0.2  # 200мс пауза
    return jsonify({"command": cmd})

if __name__ == "__main__":
    app.run(host="127.0.0.1", port=8000)
На практике добавляют очередь, ретраи, подпись сообщений и журналирование.

FAQ

Короткие ответы на типичные вопросы при старте автоматизации.

Можно ли всё делать только в LUA, без Python?

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

Как безопасно “прикрутить” автоматизацию к реальным деньгам?

Начинают с симуляции/песочницы, затем минимальные объёмы. Обязательно: лимиты, аварийная остановка, логи, мониторинг, контроль рассинхронизаций.

Что критично для надёжности?

Идемпотентность команд (повтор не ломает), подтверждения статусов заявок, восстановление после падений, журнал событий, и “безопасный режим” при ошибках связи.

Скопировано ✅