Приклади скриптів
Вісім готових скриптів на LootScript: ковзні, RSI, VWAP зі смугами відхилень, кумулятивна дельта з розбіжностями, відкритий інтерес, ставка фінансування, дисбаланси кластерів і стратегія для тестера.
Вісім готових скриптів на LootScript: від ковзних і RSI до кумулятивної дельти, відкритого інтересу, ставки фінансування і кластерів. Кожен — робочий індикатор, який можна відразу додати на графік і підлаштувати під себе. Усі приклади збираються компілятором поточної версії без помилок і попереджень.
Як запустити приклад
- Натисніть ƒ на панелі графіка, у вікні Індикатори — Редактор….
- У редакторі натисніть Новий (Ctrl+N), замініть шаблон кодом прикладу і натисніть Зберегти.
- Натисніть Додати на графік (Ctrl+Enter). Налаштування з
input.*з’являться у вікні налаштувань індикатора.
1. Три ковзні з вибором типу
Швидка, середня і повільна середні одного типу на вибір. Фон підсвічується, коли всі три вибудувалися за трендом.
indicator("Три скользящие", shortTitle = "MA×3", overlay = true)
maType = input.string("EMA", "Тип средней", options = ["EMA", "SMA", "WMA", "HMA"])
src = input.source(close, "Источник")
len1 = input.int(20, "Быстрая", minval = 1)
len2 = input.int(50, "Средняя", minval = 1)
len3 = input.int(200, "Медленная", minval = 1)
func ma(s, len) => switch maType {
"SMA" => ta.sma(s, len)
"WMA" => ta.wma(s, len)
"HMA" => ta.hma(s, len)
=> ta.ema(s, len)
}
m1 = ma(src, len1)
m2 = ma(src, len2)
m3 = ma(src, len3)
plot(m1, "Быстрая", color = m1 >= m1[1] ? color.teal : color.red, linewidth = 2)
plot(m2, "Средняя", color = color.orange)
plot(m3, "Медленная", color = color.gray, linewidth = 2)
bgcolor(m1 > m2 and m2 > m3 ? color.new(color.teal, 20) : m1 < m2 and m2 < m3 ? color.new(color.red, 20) : na)Як влаштовано
input.stringзoptionsперетворюється на випадаючий список у налаштуваннях.- Функція
maвибирає середню черезswitch. Станta.*живе в кожному місці виклику, тому три викликиma— три незалежні середні. - Колір швидкої лінії — вираз: зростає порівняно з попередньою свічкою (
m1[1]) — бірюзова, падає — червона. - Панель малює до трьох ліній
plotна скрипт — тому середніх три.
2. RSI з зонами і сповіщеннями
RSI із зафарбованою смугою між рівнями. Лінія й фон фарбуються, коли RSI у зоні перекупленості або перепроданості.
indicator("RSI с зонами", shortTitle = "RSI", overlay = false)
len = input.int(14, "Период", minval = 2)
src = input.source(close, "Источник")
ob = input.float(70, "Перекупленность", minval = 50, maxval = 100)
os = input.float(30, "Перепроданность", minval = 0, maxval = 50)
r = ta.rsi(src, len)
hOb = hline(ob, "Перекупленность", color = color.red)
hOs = hline(os, "Перепроданность", color = color.teal)
fill(hOb, hOs, color = color.new(color.purple, 20))
plot(r, "RSI", color = r > ob ? color.red : r < os ? color.teal : color.purple, linewidth = 2)
bgcolor(r > ob ? color.new(color.red, 35) : r < os ? color.new(color.teal, 35) : na)
alertcondition(ta.crossunder(r, ob), "RSI вышел из перекупленности", "RSI опустился ниже верхнего уровня")
alertcondition(ta.crossover(r, os), "RSI вышел из перепроданности", "RSI поднялся выше нижнего уровня")Як влаштовано
hlineповертає ручку рівня, аfillзафарбовує смугу між двома ручками.- Рівні — налаштування
input.float, тому лінії й заливка рухаються разом із ними. alertconditionоголошує два сповіщення. Самі по собі вони не дзвонять — як їх ввімкнути, описано на сторінці Алерти зі скриптів.- Альфа в
color.new— від 0 (прозоро) до 255 (непрозоро).
3. VWAP дня зі смугами відхилення
Зважена по обсягу ціна з початку доби за UTC і смуга ±σ навколо неї.
indicator("VWAP дня с полосами", shortTitle = "VWAP", overlay = true)
src = input.source(hlc3, "Цена")
mult = input.float(1.0, "Ширина полосы, σ", minval = 0.1, step = 0.1)
anchor = session.isfirstbar
vw = ta.vwap(src, anchor)
// Сумма объёма и сумма объёма на квадрат цены с начала дня — для разброса вокруг VWAP.
var float sumV = 0.0
var float sumV2 = 0.0
if anchor {
sumV := 0.0
sumV2 := 0.0
}
if not na(volume) and not na(src) {
sumV := sumV + volume
sumV2 := sumV2 + volume * src * src
}
sigma = sumV > 0 and not na(vw) ? math.sqrt(math.max(sumV2 / sumV - vw * vw, 0)) : na
pUp = plot(vw + mult * sigma, "Верх", color = color.new(color.blue, 150))
plot(vw, "VWAP", color = color.blue, linewidth = 2)
pDn = plot(vw - mult * sigma, "Низ", color = color.new(color.blue, 150))
fill(pUp, pDn, color = color.new(color.blue, 25))Як влаштовано
ta.vwapпочинає рахунок заново на барі, де якір істинний. Для криптовалютsession.isfirstbar— перший бар після 00:00 UTC.- Змінні
varпереживають перехід між барами. Їх обнуляє той самий якір, тому смуга рахується за той самий період, що й VWAP. - Розкид — корінь із середньозваженого квадрата ціни мінус квадрат VWAP.
math.max(…, 0)захищає від крихітного мінуса через округлення. - Має сенс на внутріденних таймфреймах. Хочете VWAP від останньої виплати ставки фінансування — поставте
anchor = funding.settled.
4. Добова кумулятивна дельта з розбіжностями
Кумулятивна дельта, яка обнуляється щодня, і позначки на барах, де ціна оновила екстремум, а дельта — ні.
indicator("Дневная кумдельта с расхождениями", shortTitle = "CVD", overlay = false)
len = input.int(20, "Окно поиска максимумов", minval = 3)
var float cvd = 0.0
if session.isfirstbar {
cvd := 0.0
}
if delta.available {
cvd := cvd + delta.value
}
cvdLine = delta.available ? cvd : na
// Цена обновила максимум окна, а кумдельта — нет: покупатели не подтверждают рост.
bearish = high >= ta.highest(high, len) and cvdLine < ta.highest(cvdLine, len)
bullish = low <= ta.lowest(low, len) and cvdLine > ta.lowest(cvdLine, len)
plot(cvdLine, "Кумдельта", color = cvdLine >= 0 ? color.teal : color.red, linewidth = 2)
hline(0, "Ноль", color = color.gray)
plotshape(bearish, "Медвежье расхождение", style = shape.triangledown, location = location.top, color = color.red, size = size.tiny)
plotshape(bullish, "Бычье расхождение", style = shape.triangleup, location = location.bottom, color = color.teal, size = size.tiny)Як влаштовано
delta.value— агресивні покупки мінус агресивні продажі за бар. Там, де покриття немає,delta.availableхибне, і лінія переривається, а не малює нуль.- Накопичувач
varобнуляється на початку доби. Потрібна кумдельта по всій завантаженій історії без скидання — візьміть готовий рядdelta.cum. - Розбіжність: ціна на максимумі вікна, а кумдельта нижча свого максимуму за те саме вікно. Для мінімумів — дзеркально.
location.topіlocation.bottomставлять позначки на краях підвікна, а не біля ціни.
5. Сплески відкритого інтересу
Зміна відкритого інтересу від бару до бару у відсотках і помітки там, де вона вибивається з звичайного розкиду.
indicator("Изменение открытого интереса", shortTitle = "ΔOI %", overlay = false)
len = input.int(50, "Окно для всплесков", minval = 5)
k = input.float(3.0, "Порог всплеска, σ", minval = 0.5, step = 0.5)
pct = oi.available and oi.close[1] > 0 ? 100 * (oi.close - oi.close[1]) / oi.close[1] : na
sd = ta.stdev(pct, len)
spike = not na(sd) and math.abs(pct) > k * sd
plot(pct, "ΔOI, %", style = plot.style_columns, color = pct >= 0 ? color.teal : color.red)
hline(0, "Ноль", color = color.gray)
plotshape(spike, "Всплеск", style = shape.circle, location = location.top, color = color.orange, size = size.tiny)Як влаштовано
oi.close— відкритий інтерес на закритті бара,oi.close[1]— на попередньому барі. Перевіркаoi.availableне дає порахувати зміну з пустоти.- Сплеск — бар, де зміна по модулю більша за
kстандартних відхилень за вікноlen. - Відкритий інтерес приходить поминутно. На таймфреймах менше хвилини сусідні бари повторюють одне значення, і зміна там нульова — це дані, а не помилка.
6. Ставка фінансування
Ставка фінансування безстрокового ф’ючерса у відсотках за період або перерахована на рік, з позначками виплат і підсвіткою високої ставки.
indicator("Ставка финансирования", shortTitle = "Funding", overlay = false)
mode = input.string("За период", "Показывать", options = ["За период", "Годовых"])
thr = input.float(0.05, "Порог, %", minval = 0.0, step = 0.01)
perPeriod = funding.rate * 100
periodsPerYear = funding.interval_hours > 0 ? 24.0 / funding.interval_hours * 365 : na
value = mode == "Годовых" ? perPeriod * periodsPerYear : perPeriod
level = mode == "Годовых" ? thr * periodsPerYear : thr
plot(value, "Ставка, %", style = plot.style_columns, color = value >= 0 ? color.teal : color.red)
hline(0, "Ноль", color = color.gray)
plotshape(funding.settled, "Выплата", style = shape.circle, location = location.bottom, color = color.gray, size = size.tiny)
bgcolor(math.abs(value) > level ? color.new(color.orange, 30) : na)Як влаштовано
funding.rate— доля, а не відсотки: 0.0001 — це 0,01 %. Тому ставку множать на 100.- Для річних значень ставка множиться на число виплат у році.
24.0записано дробом навмисно: ділення двох цілих у LootScript відкидає залишок. funding.settledістинно на барі, де пройшла виплата — там унизу ставиться точка.- Поріг задається за період і для річних перераховується тим самим множником.
7. Дисбаланси в кластерах
Позначки на графіку ціни там, де в кластерах бара стоїть «драбинка» дисбалансів або їх просто багато, плюс рівень максимального обсягу (POC) кожного бара.
indicator("Дисбалансы кластеров", shortTitle = "Imbalance", overlay = true)
minSteps = input.int(3, "Уровней подряд", minval = 2)
minCount = input.int(5, "Дисбалансов в баре", minval = 1)
levels = cluster.available ? cluster.levels : 0
buys = 0
sells = 0
for i in 0 .. levels {
side = cluster.imbalance(i)
if side == 1 {
buys := buys + 1
} else if side == -1 {
sells := sells + 1
}
}
plot(cluster.poc, "POC", style = plot.style_circles, color = color.orange)
plotshape(cluster.stacked_buy_steps >= minSteps, "Лесенка покупок", style = shape.triangleup, location = location.belowbar, color = color.teal, size = size.small)
plotshape(cluster.stacked_sell_steps >= minSteps, "Лесенка продаж", style = shape.triangledown, location = location.abovebar, color = color.red, size = size.small)
plotshape(buys >= minCount, "Много дисбалансов покупок", style = shape.circle, location = location.belowbar, color = color.new(color.teal, 120), size = size.tiny)
plotshape(sells >= minCount, "Много дисбалансов продаж", style = shape.circle, location = location.abovebar, color = color.new(color.red, 120), size = size.tiny)Як влаштовано
cluster.imbalance(i)повертає +1, −1 або 0 для цінового рівняi. Поріг дисбалансу береться з налаштувань кластерного графіка, тому скрипт бачить те саме, що й ви.cluster.stacked_buy_steps— скільки рівнів підряд іде дисбаланс покупок. Циклfor i in 0 .. levelsрахує всі дисбаланси бара, не тільки підрядні.- Скрипт сам підписується на кластери і працює на звичайному свічковому графіку. На біржі без покриття і на таймфреймах менше 30 секунд або більше доби кластерів немає — тоді
levelsдорівнює 0 і позначок не буде.
8. Стратегія: перетин EMA зі стопом за ATR
Вхід у лонг на перетині середніх, стоп і ціль — у частках ATR, вихід — по зворотному перетину.
strategy("EMA-кросс со стопом по ATR", overlay = true, initialCapital = 10000,
defaultQtyType = strategy.qty.percent_of_equity, defaultQtyValue = 10,
slippageTicks = 2)
fastLen = input.int(12, "Быстрая EMA", minval = 1)
slowLen = input.int(26, "Медленная EMA", minval = 2)
atrLen = input.int(14, "Период ATR", minval = 1)
stopK = input.float(1.5, "Стоп, в ATR", minval = 0.1, step = 0.1)
takeK = input.float(3.0, "Цель, в ATR", minval = 0.1, step = 0.1)
fast = ta.ema(close, fastLen)
slow = ta.ema(close, slowLen)
atr = ta.atr(atrLen)
// ATR запоминается в момент сигнала, чтобы стоп и цель не ползли вслед за волатильностью.
var float riskAtr = na
if ta.crossover(fast, slow) and strategy.position_size == 0 {
riskAtr := atr
strategy.entry("Long", strategy.long)
}
if ta.crossunder(fast, slow) {
strategy.close("Long", comment = "Обратный кросс")
}
if strategy.position_size > 0 {
entry = strategy.position_avg_price
strategy.exit("Стоп/цель", from_entry = "Long", stop = entry - stopK * riskAtr, limit = entry + takeK * riskAtr)
}
plot(fast, "Быстрая", color = color.teal)
plot(slow, "Медленная", color = color.orange)Як влаштовано
- Параметри
strategy(…)— літерали: капітал 10 000, розмір позиції 10 % капіталу, прослизання 2 тики. Комісія не вказана, тому тестер бере тариф за замовчуванням: 0,02 % за лімітне виконання і 0,05 % за ринкове і стоп. Свій тариф у процентах задаєcommissionValue. - Ринковий вхід виконується по відкриттю наступного бара, а не по закриттю сигнального: так тестер не заглядає в майбутнє.
strategy.exitставить стоп і ціль від середньої ціни входу. Якщо за один бар зачепилися обидва, тестер за замовчуванням вважає, що спрацював стоп.- Результати — угоди, крива капіталу, просідання — у вікні Тестер стратегії… редактора. Детальніше — на сторінці Стратегії і тестер.