Стратегії та тестер
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, тейк-профіт — удвічі далі.
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/uk/loot/strategies