Линейный индикатор Z-Score календарных спредов для QUIK

Скрипт Lua для QUIK: Линейный индикатор Z-Score календарных спредов

Автоматизация расчетов — это базовое условие для успешного арбитража внутри торговой сессии. Чтобы не высчитывать статистические отклонения вручную, трейдеры используют автоматические алгоритмы, интегрированные напрямую в торговый софт. В этом материале мы публикуем готовый высокоскоростной скрипт на языке Lua для торгового терминала QUIK от брокера Финам. Этот индикатор строит линейный график Z-Score для календарных спредов фьючерсов на Московской бирже (MOEX) и автоматически размечает критические зоны для входа в сделку.

Технические особенности кода и структура индикатора

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

Скрипт выводит в отдельное окно графика четыре независимые линии:

  • Z-Score Line (Основная линия): Сплошная синяя линия толщиной 2 пикселя, отражающая текущее количество стандартных отклонений спреда от математического ожидания.
  • Zero Line (Базовый уровень 0): Серый пунктир, обозначающий состояние идеального рыночного баланса сил.
  • Upper Level (+2): Красный точечный маркер. Сигнализирует об аномальном расширении спреда (зона шорта дорогой ноги).
  • Lower Level (-2): Зеленый точечный маркер. Сигнализирует об аномальном сужении спреда (зона лонга дешевой ноги).

Готовый Lua-код индикатора Z-Score для QUIK

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

-- Индикатор Z-Score для календарных спрэдов QUIK (Линейный вид)
Settings = {
    Name = "Z-Score Spread Line", 
    period = 20,             
    line = {
        {
            Name = "Z-Score Line",
            Type = TYPE_LINE,          -- Сплошная линия вместо гистограммы
            Color = RGB(0, 128, 255),  -- Основной синий цвет линии
            Width = 2,                 
            Style = LINE_SOLID
        },
        {
            Name = "Zero Line",
            Type = TYPE_LINE,
            Color = RGB(128, 128, 128), 
            Width = 1,
            Style = LINE_DASH
        },
        {
            Name = "Upper Level (+2)",
            Type = TYPE_LINE,
            Color = RGB(255, 50, 50),   -- Красный пунктир для верхней границы
            Width = 1,
            Style = LINE_DOT
        },
        {
            Name = "Lower Level (-2)",
            Type = TYPE_LINE,
            Color = RGB(0, 200, 0),     -- Зеленый пунктир для нижней границы
            Width = 1,
            Style = LINE_DOT
        }
    }
}

function Init()
    return 4 -- Теперь у нас строго 4 линии (1 индикатор и 3 уровня)
end

function OnCalculate(index)
    local p = Settings.period
    
    -- Значения по умолчанию для уровней (0, +2, -2)
    local zero, upper, lower = 0, 2, -2

    if index < p then
        return nil, zero, upper, lower
    end
    
    local sum = 0
    local prices = {}
    
    for i = 0, p - 1 do
        local cur_idx = index - i
        local val = C(cur_idx) 
        
        if val == nil then 
            return nil, zero, upper, lower 
        end
        
        sum = sum + val
        table.insert(prices, val)
    end
    
    local mean = sum / p
    
    local sum_sq = 0
    for i = 1, p do
        sum_sq = sum_sq + (prices[i] - mean)^2
    end
    
    local variance = sum_sq / p
    local std_dev = math.sqrt(variance)
    
    local current_close = C(index)
    if current_close == nil then
        return nil, zero, upper, lower
    end
    
    local z_score = 0
    if std_dev > 0.00001 then 
        z_score = (current_close - mean) / std_dev
    end
    
    -- Возвращаем значения строго по порядку линий in Settings
    return z_score, zero, upper, lower
end

Инструкция по установке скрипта в QUIK от Финама

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

  1. Создайте на своем компьютере текстовый файл и назовите его, например, zscore_line.lua. Обратите внимание, что расширение файла должно быть строго .lua, а не .txt. Вставьте скопированный код внутрь этого файла и сохраните его.
  2. В корневой папке вашего торгового терминала QUIK найдите или самостоятельно создайте папку с именем LuaIndicators. Переместите туда ваш сохраненный файл скрипта.
  3. Перезапустите QUIK. Откройте график интересующего вас календарного спреда (для этого предварительно создается график разницы цен двух фьючерсов через встроенный функционал математических графиков QUIK).
  4. Кликните правой кнопкой мыши по графику спреда, нажмите «Добавить индикатор» и найдите в открывшемся списке пользовательских инструментов название "Z-Score Spread Line". Нажмите «Добавить». Индикатор развернется в отдельном окне под основным графиком.

Практические правила торговли по индикатору

Параметр period = 20 в настройках скрипта является классическим и наиболее сбалансированным для пятиминутных (М5) и пятнадцатиминутных (М15) таймфреймов на срочном рынке FORTS. Логика отработки торговых сигналов опирается на строгий математический риск-менеджмент:

Когда синяя линия Z-Score пробивает верхний красный уровень +2, это сигнализирует о сильной перекупленности спреда фьючерсов. В этот момент арбитражер открывает короткую позицию по спреду. При падении синей линии под зеленый уровень -2 открывается длинная позиция. Закрытие сделок и фиксация прибыли происходят строго при возврате индикатора к серому пунктиру Zero Line (0), что подтверждает полное исчезновение рыночной неэффективности.

Чтобы изучить теоретические основы работы данного математического алгоритма, читайте статью в категории «Теории и обзоры», а запустить другие полезные расчетчики параметров ГО вы можете в разделе «Сервисы и ИИ для арбитража».