← К документации
LootX

Стратегии и тестер

Собрано: 2026-10-01 docs.lootx.trade
Основы

1Стратегии и тестер

Как написать стратегию на LootScript и проверить её на истории в тестере: объявление strategy(), заявки, модель исполнения, издержки, вкладки отчёта и ограничения бэктеста.

Стратегия — это скрипт, который кроме линий на графике подаёт заявки. Заявки исполняет не биржа, а симулятор внутри терминала: он прогоняет стратегию по истории графика с комиссиями, проскальзыванием и фандингом и показывает результат в окне Тестер стратегии.

Объявление strategy()

Стратегию отличает от индикатора первая строка: strategy(...) вместо indicator(...). Всё остальное — настройки, отрисовка, данные рынка — работает так же. Функции strategy.* в индикаторе не компилируются: «strategy.* доступно только в strategy(…)».

Параметр По умолчанию Что задаёт
initialCapital 10000 Стартовый капитал
defaultQtyType, defaultQtyValue strategy.qty.fixed, 1 Размер заявки, если в ней не указан qty
commissionType, commissionValue процент, не задана Комиссия: strategy.commission.percent — процент от оборота (0.05 = 0,05 %), strategy.commission.cash_per_contract — сумма за единицу количества, strategy.commission.cash_per_order — сумма за исполнение
slippageTicks 0 Проскальзывание в тиках
pyramiding 0 Сколько входов в одну сторону может быть открыто; 0 — один
positionModel strategy.model.netting Одна общая позиция или раздельные длинные и короткие (strategy.model.hedging)
processOrdersOnClose false Исполнять рыночные заявки по закрытию текущего бара
calcOnEveryTick false Разрешить заявки на формирующемся баре
marginLong, marginShort, leverage 0, 0, 1 Маржа в процентах или плечо; при 0 ликвидация не моделируется
applyFunding true Учитывать фандинг
fillModel strategy.fill.conservative Предположение о пути цены внутри бара

Значения параметров — только числа и константы прямо в тексте. Выражение или input.* в объявлении — ошибка компиляции. Параметр calcOnOrderFills принимается, но в этой версии не действует: на вкладке «Свойства» тестера он помечен «не действует в этой сборке».

Размер заявки при qty = na задаёт defaultQtyType:

Тип defaultQtyValue означает
strategy.qty.fixed Количество в монетах (базовой валюте)
strategy.qty.cash Сумму в валюте котировки
strategy.qty.percent_of_equity Процент текущего капитала
strategy.qty.risk_percent Процент капитала, которым рискуете до защитного стопа

Для strategy.qty.risk_percent нужен strategy.exit со стопом (loss или stop), иначе компилятор остановит: «требует стоп, от которого считать размер». Количество округляется вниз до шага количества инструмента. Если после округления остаётся ноль, заявка отклоняется и попадает в счётчик тестера «Отвергнуто заявок (размер)».

Заявки

Функция Что делает
strategy.entry(id, direction, qty, limit, stop, …) Открывает позицию или разворачивает её. Учитывает модель позиции и pyramiding
strategy.order(id, direction, qty, limit, stop, …) То же без учёта модели позиции и pyramiding
strategy.exit(id, from_entry, qty, qty_percent, profit, limit, loss, stop, trail_price, trail_points, trail_offset, …) Ставит выход — тейк, стоп или трейлинг — на открытый вход
strategy.close(id, comment, qty, qty_percent) Закрывает вход рыночной заявкой
strategy.close_all(comment) Закрывает всё
strategy.cancel(id), strategy.cancel_all() Снимает ещё не исполненные заявки

Направление — strategy.long или strategy.short. У всех функций есть необязательный when: when = false пропускает вызов. У входов, выходов и закрытий есть ещё comment — текстовая подпись к заявке.

  • Тип входа. Без limit и stop — рыночная заявка, с limit — лимитная, со stop — стоп-заявка, с обоими — стоп-лимит. Повторный strategy.entry с тем же id заменяет ещё не исполненную заявку.
  • Разворот. В модели netting вход в противоположную сторону закрывает текущую позицию и открывает новую одним действием.
  • Единицы выхода. profit и loss — в тиках от цены входа, limit и stop — абсолютные цены. Трейлинг задаётся парой: trail_offset плюс trail_price или trail_points.
  • Выход без уровней ничего не делает. Компилятор предупредит: «strategy.exit без единого уровня (profit/loss/stop/limit/trail) — пустая операция».
  • Перенос стопа. Повторный strategy.exit с тем же id заменяет выход — так двигают стоп.

Состояние стратегии читается рядами: strategy.position_size (со знаком, короткая позиция — отрицательная), strategy.position_avg_price, strategy.equity, strategy.netprofit, strategy.openprofit, strategy.opentrades, strategy.closedtrades, strategy.funding_paid и другими — полный список в справочнике.

Как тестер исполняет заявки

Заявка, поданная на баре, исполняется не раньше следующего бара. Решение принимается по закрытию бара, и исполнять его по той же цене значило бы заглянуть вперёд.

Заявка Исполнение
Рыночная По открытию следующего бара плюс проскальзывание. С processOrdersOnClose = true — по закрытию текущего
Лимитная Когда цена проходит лимит, по цене лимита. Если бар открылся за лимитом — по открытию
Стоп Когда цена проходит стоп, по цене стопа плюс проскальзывание. При гэпе — по открытию плюс проскальзывание

Путь цены внутри бара. Настоящего пути внутри бара тестер не знает и предполагает его. Модель strategy.fill.conservative (по умолчанию) считает, что цена сначала сходила к худшему экстремуму: на растущем баре — открытие → минимум → максимум → закрытие, на падающем — наоборот. Если в одном баре оказались и стоп, и тейк, срабатывает стоп. Модель strategy.fill.optimistic предполагает обратное — годится только для сравнения. Проигрывания по младшему таймфрейму в этой версии нет: в колонке «Путь» каждая сделка отмечена как предположенная моделью.

Издержки.

  • Комиссия. Если commissionValue не задан, тестер берёт тариф по умолчанию: 0,02 % за лимитные исполнения и 0,05 % за рыночные и стоп. Тариф вашего счёта и рибейты терминалу неизвестны. Заданное число действует на все исполнения.
  • Проскальзывание — slippageTicks против вас на рыночных и стоп-исполнениях. Лимитные не проскальзывают.
  • Фандинг списывается на каждом реальном расчёте биржи — по фактической ставке и цене закрытия бара расчёта. Для этого нужны данные фандинга: фьючерсы на биржах из таблицы покрытия.
  • Маржа. С marginLong/marginShort или плечом больше 1 тестер моделирует упрощённую изолированную маржу. Длинная позиция ликвидируется при цене вход × (1 − m/2), короткая — при вход × (1 + m/2), где m — доля начальной маржи. Ликвидированная сделка теряет всю начальную маржу.

Сделки, не закрытые к концу истории, закрываются по закрытию последнего бара с причиной «конец данных».

Тестер стратегии

Добавьте стратегию на график

В редакторе скриптов нажмите Добавить на график (Ctrl+Enter). Скрипт с ошибками на график не попадёт.

Откройте тестер

В панели инструментов редактора нажмите Тестер стратегии… — кнопка активна только для скрипта с strategy(...). Второй путь — настройки стратегии из легенды графика (шестерёнка), кнопка Тестер стратегии….

Дождитесь прогона

Тестер считает по свечам, загруженным на графике. Пока их нет, окно пишет «Стратегия ещё не считалась: дождитесь загрузки свечей». Когда приходят новые свечи, результат пересчитывается сам; кнопка Пересчитать запускает полный прогон вручную.

Если на графиках несколько стратегий, нужную можно выбрать прямо в окне тестера.

Вкладка Что на ней
Сводка Плитки «Чистая прибыль», «Профит-фактор», «Макс. просадка (по закрытиям)», «Доля прибыльных», «SQN»; полоса «Чего этот бэктест не знает»; кривые капитала, «купил-и-держи», капитала без фандинга и двух просадок
Показатели Результат, риск (просадка по закрытиям и внутри бара отдельно, Шарп, Сортино, Калмар), сделки (доля прибыльных, средние и крупнейшие, серии), издержки (комиссия и фандинг)
Сделки Таблица сделок: вход, выход, причина, объём, P&L, ран-ап, просадка, комиссия, фандинг. Клик по строке прокручивает график к бару входа, Ctrl+C копирует выделенные строки
Свойства Параметры объявления, диапазон баров, шаг цены, шаг количества, минимальный лот, комиссия, счётчики прогона: отклонённые заявки, пропущенные по pyramiding, ликвидации, расчёты фандинга

В заголовке окна — метки режима: conservative или optimistic по модели исполнения и close-fill при processOrdersOnClose = true. Метки optimistic и close-fill значат, что вживую результат, скорее всего, будет хуже.

Чего стратегия читать не может

Живой стакан и лента. Стратегия, которая читает book.* или tape.*, не компилируется: «Стратегия читает … у стакана и ленты нет истории, бэктест был бы вымыслом». Для истории стакана есть depth.*, для сделок — delta.* и cluster.*.

Скринер. screener.* тоже есть только на последнем баре, но компилятор такую стратегию пропускает. На истории значения скринера — na, поэтому условия на них там не выполняются, и сделок по ним в отчёте не будет.

Заглядывание вперёд. request.security(..., lookahead = true) в стратегии даёт в редакторе предупреждение «Стратегия заглядывает вперёд … отчёт помечен как недостижимый в реальном времени». Относитесь к такому отчёту как к завышенному: на истории стратегия видит значения, которых вживую ещё не было. Подробнее — в разделе Данные рынка.

Пример

Пробой канала с подтверждением дельтой. Вход — на закрытии за границей канала за последние len баров, если дельта бара в ту же сторону. Стоп — в ATR, тейк — вдвое дальше.

Loot
strategy("Пробой канала с дельтой", overlay = true,
         initialCapital = 10000,
         defaultQtyType = strategy.qty.percent_of_equity, defaultQtyValue = 20,
         commissionValue = 0.05, slippageTicks = 2)

len      = input.int(20, "Канал, баров", minval = 5, maxval = 200)
stopAtr  = input.float(1.5, "Стоп, ATR", minval = 0.5, maxval = 10, step = 0.1)
needFlow = input.bool(true, "Подтверждать дельтой")

upper = ta.highest(high, len)[1]
lower = ta.lowest(low, len)[1]
atr   = ta.atr(14)

flowLong  = not needFlow or (delta.available and delta.value > 0)
flowShort = not needFlow or (delta.available and delta.value < 0)

if close > upper and flowLong and strategy.position_size <= 0 {
    strategy.entry("L", strategy.long, comment = "пробой вверх")
}
if close < lower and flowShort and strategy.position_size >= 0 {
    strategy.entry("S", strategy.short, comment = "пробой вниз")
}

stopTicks = math.round(atr * stopAtr / sym.tick_size)
strategy.exit("L-x", from_entry = "L", loss = stopTicks, profit = stopTicks * 2)
strategy.exit("S-x", from_entry = "S", loss = stopTicks, profit = stopTicks * 2)

plot(upper, "Верх канала", color = color.teal)
plot(lower, "Низ канала", color = color.red)

На бирже без дельты (например, Binance Alpha) при включённой настройке «Подтверждать дельтой» стратегия не сделает ни одной сделки: delta.available там ложно. Это правило na в действии, а не ошибка.

Ограничения

  • Только симуляция: реальных заявок нет.
  • Лимитные заявки исполняются так, будто вы стояли первым в очереди. Для мейкерских стратегий это главный источник завышенного результата.
  • Ваши сделки не двигают цену, частичных исполнений нет: заявка исполняется целиком или никак.
  • Путь цены внутри бара предполагается моделью, а не берётся из младшего таймфрейма.
  • Ликвидация упрощена: движок ликвидаций биржи, ADL и страховой фонд не моделируются.
  • Комиссия — тариф по умолчанию, а не тариф вашего счёта.
  • Отсутствие данных — не отсутствие движения: бар без кластеров всё равно двигался.
  • Результат зависит от того, сколько истории загружено на графике.

Дальше

https://docs.lootx.trade/ru/loot/strategies