Սինտաքսիս և տիպերը
1Սինտաքսիս և տիպերը
Ինչպես կառուցված է LootScript-ը՝ հաշվարկը ըստ բարերի, script-ի հայտարարում, հնգակողմ ձևեր վերագրելու, տիպեր և որակագրիչներ, na, x[n]‑ի պատմությունը, օպերատորներ, պայմաններ, switch, ցիկլեր, ֆունկցիաներ և սեփական տիպեր։
Այս էջը — լեզվի կարճ նկարագիրը. ինչպես կամ չափով հաշվարկվում է script‑ը բարերով, ինչպես հայտարարել փոփոխականներ, ինչպիսի տիպեր կան, ինչ է na, ինչպես կարդալ անցյալ բարերը, ինչպես գրել պայմաններ, ցիկլեր և ֆունկցիաներ։ Բոլոր օրինակները ամբողջական աշխատանքային script‑ներ են․ դրանք կարելի է քպել խմբագրում և ավելացնել գրաֆիկին.
Как выполняется скрипт
Բ ملف‑ի վերին մակարդակում գտնվող ամեն ինչ կատարվում է մի անգամ յուրաքանչյուր բարի համար — ամենադրանից հնագույնից մինչեւ ներկա, տող առ տող։ Ուստի LootScript‑ում փոփոխականը չպահպանում է մեկ թիվ, այլ ունի արժեք յուրաքանչյուր բարի համար, և կարելի է փորձել անցյալ արժեքներին։
indicator("Тело свечи")
body = close - open // считается заново на каждом баре
plot(body, "Тело", style = plot.style_columns)Ներկա, դեռ չփակված բարի վրա script‑ը վերագնահատվում է յուրաքանչյուր նոր tick‑ի հետ, սկսելով նույն состояния‑ից, որը գոյություն ուներ նախորդ բարի փակման պահին։ Փակված բարերը այդ դեպքում չեն վերագնահատվում։
Объявление
Script‑ի առաջին հրամանը — ճիշտ մեկ հայտարարություն՝ indicator(...), strategy(...) կամ library(...)։ Նրա վերևում կարող են լինել միայն մեկնաբանություններ և միայնակ #version 1 տողի ընտրովի գրությունը։ Եթե հայտարարություն չկա, script‑ը չի կոմպիլացվի և կտպի սխալ՝ «Нет объявления скрипта — начните с indicator(“Название”)»։
#version 1
// Комментарии и строка версии могут стоять выше объявления.
indicator("Размах бара", shortTitle = "Размах", overlay = false)
plot(high - low, "Размах", style = plot.style_histogram)Ինդիկատորի գլխավոր պարամետրերը՝ title — անունը script‑ների ցանկում, shortTitle — կարճ անունը լեգենդայի համար, overlay — նկարել գնի վրայի՞ (true) թե առանձին վահանակում (false, ըստ էության)։ Ստրատեգիայի պարամետրերը նկարագրված են Стратегии и тестер էջում։
Переменные и присваивание
| Форма | Что делает |
|---|---|
x = выражение |
Հայտարարում է փոփոխական։ Յուրաքանչյուր բարում այն հաշվվում է նորից։ |
x := выражение |
Վերագրում է արդեն հայտարարված փոփոխականի նոր արժեքը։ Տիպը պետք է հապատառվի։ |
var x = выражение |
Հայտարարում է փոփոխականը մեկ անգամ՝ առաջին բարում։ Արժեքը փոխանցվում է հաջորդ բարերին։ |
varip x = выражение |
Ինչպես var, բայց արժեքը պահպանվում է նաև ներկա բարի ներսում tick‑երի միջով։ |
[a, b, c] = функция(...) |
Բազմաթիվ վերադարձների դեպքում տեղավորում է արդյունքները փոփոխականների մեջ։ |
Կարճ ձևեր արդեն հայտարարված փոփոխականի փոփոխման համար՝ +=, -=, *=, /=, %=. Տիպը կարելի է նշեl բացահայտ՝ float level = 0։ Վстроенные շարքերի և տարածությունների անունները (close, volume, ta և այլն) զբաղված են — տո Ձեր փոփոխականը այդ անունով կոչել нельзя։
Գլխավոր տարբերությունը սովորական լեզուներից՝ սովորական փոփոխականը չի կուտակում արժեքը բարերի միջև։ Ընդհանրական հաշիչների և գումարների համար պահանջվում է var:
indicator("Счётчик зелёных свечей")
var greens = 0 // объявляется один раз и переживает переход к следующему бару
if close > open {
greens += 1
}
today = 0 // а эта переменная равна 0 на каждом новом баре
today := today + 1 // поэтому здесь всегда 1
plot(greens, "Зелёных с начала истории")varip‑ը հազվադեպ է պետք — օրինակ՝ բարում tick‑երը հաշելու համար։ Tick‑երի պատմություն չկա, այնպես որ նման արժեքը անցյալ բարերում կարող է տարբեր լինել այն արժեքից, որը եղել է կենդան ժամանակında։ Եթե varip արժեքը գծապատկերին արտասերվի, խմբագիրը կհուշի հնարավոր վերագր绘։
Типы
| Тип | Что хранит | Пример |
|---|---|---|
int |
ամբողջ թիվ | 14, 1_000_000, 0xFF |
float |
հորիզոնական թիվ | 2.5, .5, 1e-9 |
bool |
ճշմարիտ կամ կեղծ | true, false |
string |
տեքստ | "BTC", 'BTC' |
color |
գույն թափանցիկությամբ | #FF9800, #FF980080, color.teal |
Կան նաև բաղադրյալ տիպեր՝ զանգվածներ array<float>, բառարաններ map<string, float>, մատրիցներ matrix<float>, ինչպես նաև ձեր սեփական տիպերը և enum‑ները (տես հետին՝), և գրաֆիկական օբյեկտներ line, box, label, table։
Հաճախ հայտնվող կանոնները՝
- Տիպը ֆիքսվում է հայտարարման պահին. Եթե
x = 1եք գրել, ապաx := 2.5գրել չեք կարող —xամբողջ է։ Գրեքx = 1.0կամfloat x = 1։ - Ամբողջը ինքնից չի դառնում բուծային, իսկ դառնալը՝ միայն ուղղակիորեն. Օգտագործեք
math.round,math.floor,math.ceil,math.trunc։ - Ամբողջների բաժանումը՝ ամբողջ է.
7 / 2=3. Սպասարկման համար մեկ թիվը դարձրեք բութ՝7.0 / 2։ - Թեքում
^միշտ տալիս է բութ թիվ.2 ^ 3=8.0։ - Տողը нельзя գումարել թվի հետ.
"Цена: " + closeչի կոմպիլացվի — օգտագործեք"Цена: " + str.tostring(close)։ - Պայմանը միայն
boolկարող է լինել.if volume { … }— սխալ, վերջացրեքif volume > 0 { … }։
Կвалификատորներ՝ որքան հաստատուն է արժեքը
Տիպից բացի յուրաքանչյուր արժեք ունի որակագրիչ՝ որքանով է այն փոփոխական թեր ժամանակի ընթացքում։ Սխալից դեպի ուժեղը՝
| Квалификатор | Когда известно значение | Пример |
|---|---|---|
const |
արդեն կոմպիլացիայի ընթացքում | 14, "EMA" |
input |
կարգավորումների ընթերցումից հետո, ավելի չի փոխվում | input.int(14, "Период") |
simple |
պրոցեսի մեկնարկի պահին, հետո չի փոխվում | գործիքի արժեքի քայլը |
series |
կարող է փոխվել յուրաքանչյուր բարի վրա | close, bar_index |
Նախնական կիրառման մեջ կարևոր է մեկ տեղ՝ ta.* ֆունկցիաների հաշվարկային տևողությունները պետք է լինեն հաստատուն — լիտերալ կամ input։ Ոչ այդպիսկ՝ ֆունկցիաները ստիպված կլինեին վերակառուցել իրենց վիճակը յուրաքանչյուր բարի վրա։
indicator("Период из настроек")
len = input.int(14, "Период", minval = 2)
plot(ta.rsi(close, len), "RSI")
// ta.rsi(close, bar_index) не скомпилируется:
// «length» в «ta.rsi» требует значение не слабее input, а передано seriesna — չկա արժեք
na նշանակում է «արժեք չկա»՝ ոչ բավական հին պատմություն հաշվարկի համար, բորսան չի վերադարձնում ցուցանիշը, տվյալներում բաց է։ na կարող է լինել ցանկացած տիպում։
- Арифметика с
naдаетna:na + 1→na. - Любое сравнение с
naложно, այնպես որif x > 0приx = naչի կատարվի։ - Միակապես բացակայությունը ստուգեք
na(x)-ով. Գրությունըx == naկոմպիլյատորը մերժում է սխալով՝ «Сравнение с na всегда ложно — используйте na(x)»։ nz(x)վերադարձնում է 0‑ըna‑ի փոխարեն,nz(x, v)վերաճում է v։ Հարմար կարճ ձևը՝x ?? v.- Ցանկացած
naգծապատկերին կդիմացնի գծի կտրուկ դադար, ոչ զրո։
indicator("Средняя без пустого начала", overlay = true)
avg = ta.sma(close, 50) // на первых 49 барах — na
line1 = na(avg) ? close : avg // проверка через na(x)
line2 = avg ?? close // то же короче
plot(line2, "Средняя или цена", color = color.orange)История: x[n]
x[n] — արժեքը x‑ի այն բարի վրա, որը եղել է n բարեր առաջ; x[0] — ներկա բարը։ Աշխատում է ցանկացած շարքի հետ, այդ թվում ձեր փոփոխականների։
indicator("Наклон средней")
ma = ta.ema(close, 20)
slope = ma - ma[1] // изменение за один бар
plot(slope, "Наклон", style = plot.style_histogram,
color = slope >= 0 ? color.teal : color.red)- Եթե
n‑ը մեծ է պատմության սկզբից մինչեւ ընթացիկ բարի քանակից, արդյունքըnaէ, ոչ սխալ։ nկարող է փոխվել բարից բար.close[len]при переменномlenթույլատված է։- Սխալ է օգտագործել բացասական ինդեքս՝ անցնել ապագա բարերը։
- Պատմության խորությունը կարգավորելու կարիք չկա․ script‑ին հասանելի է ամբողջ պատմությունը, որը լեցված է գրաֆիկում։
Операторы
Տարանջատման կարգը՝ բարձրից դեպի ցածր․
| Приоритет | Операторы |
|---|---|
| 1 | x[n], вызов f(…), доступ через точку a.b |
| 2 | ^ — степень, вычисляется справа налево |
| 3 | унарные -, +, not |
| 4 | *, /, % |
| 5 | +, - |
| 6 | <, >, <=, >= |
| 7 | ==, != |
| 8 | and |
| 9 | or |
| 10 | ?? — замена na |
| 11 | ? : — условное выражение |
- Сравнения не сцепляются: вместо
a < b < cգրեքa < b and b < c. andևorאינם հաշվարկում աջ կողմը, եթե լուծումը արդեն հայտնի է ձախից։- Դասավորություն՝ степень ավելի բարձր է унарного минуса से։
-2 ^ 2=-4. Եթե պետք է4՝ գրեք(-2) ^ 2։ - Բութ թվեր համեմատեք թույլատրելիությամբ՝
math.approx(a, b), որովհետև0.1 + 0.2 == 0.3կարող է կեղծ լինել։
Պայմաններ
Բլոկները միշտ ուղված են ծալքավոր բրակետներով {}։ if կարող է լինել և՛ հրահանգ, և՛ արտահայտություն; երկուսի դեպքում արագ ընտրությունն անում է ? :։
indicator("Направление бара")
dir = 0
if close > open {
dir := 1
} else if close < open {
dir := -1
}
// if как выражение: обе ветки обязательны
bodySize = if close >= open { close - open } else { open - close }
// условный оператор для простых случаев
barColor = dir > 0 ? color.teal : color.red
plot(bodySize, "Тело", style = plot.style_columns, color = barColor)switch
switch‑ը ընտրում է առաջին համընկնող շերտը։ Օբյեկտով ձևը համեմատում է այն շերտերի արժեքների հետ, առանց օբյեկտի ձևը հերթով ստուգում է պայմանները։ => առանց պայմանի — ստանդարտ (default) ճյուղն է։ Ցածրացման (fallthrough) механիզմ չկա. Եթե switch արժեք է վերադարձնում՝ default ճյուղը պարտադիր է։
indicator("Средняя на выбор", overlay = true)
kind = input.string("EMA", "Тип средней", options = ["EMA", "SMA", "WMA"])
ma = switch kind {
"EMA" => ta.ema(close, 20)
"SMA" => ta.sma(close, 20)
=> ta.wma(close, 20)
}
zone = switch {
close > ma * 1.02 => 1
close < ma * 0.98 => -1
=> 0
}
plot(ma, "Средняя", color = zone == 1 ? color.teal : zone == -1 ? color.red : color.gray)Циклы
for i in a .. b անցնում է թվերի միջոցով՝ սկսելով {a}‑ից ներառյալ մինչև {b} անընդմեջ չմասնակցելով։ Քայլը задаётся словом by, կարող է լինել բացասական։ Ցիկլի փոփոխականը գոյություն ունի միայն ցիկլի ներսում և չի փոփոխվում մարմնում։
indicator("Зелёные свечи за N баров")
n = input.int(10, "Сколько баров", minval = 1, maxval = 200)
greens = 0
for i in 0 .. n { // i = 0, 1, …, n − 1
if close[i] > open[i] {
greens += 1
}
}
plot(greens, "Зелёных", style = plot.style_columns)indicator("Виды циклов")
total = 0
for i in 0 .. 10 by 2 { // 0, 2, 4, 6, 8
total += i
}
for i in 10 .. 0 by -1 { // 10, 9, …, 1
if i % 3 == 0 {
continue // сразу к следующему шагу
}
total += i
}
var closes = array.new<float>(0)
closes.push(close)
if closes.size() > 20 {
closes.shift()
}
sum = 0.0
for v in closes { // по элементам массива; for [i, v] in … — с индексом
sum += v
}
k = 0
while k < 100 {
k += 7
if k > 50 {
break // выход из цикла
}
}
plot(sum / closes.size(), "Средняя из массива")Անվերջ ցիկլը սրա համար հանգեցուցիչ չի լինի, տերմինալը չի կախվի՝ script‑ին հատկացված է օպերացիաների բյուջե յուրաքանչյուր բարի համար և ժամանակի սահմանակ։ Դրանք հն تجاوزելու դեպքում script‑ը կանգ կտա և ցույց կտա հաղորդագրություն՝ «Скрипт исчерпал бюджет операций на бар — упростите цикл» կամ «Скрипт превысил лимит времени на проход»։
Функции
Ֆունկցիան հայտարարում են func‑ով։ Կարճ ձեւը՝ արտահայտություն =>‑ից հետո, երկար ձեւը՝ մարմինով {} և return‑ով։ Փարամետրերի տիպերը կարելի է չնշել — դրանք ինքնաբերաբար ենթադրվում են կանչերից; պարամետրերը կարող են ունենալ նախնական արժեքներ։ Պարգևները փոխանցվում են ըստ կարգի կամ ըստ անունի։
indicator("Z-оценка объёма")
func barRange(h, l) => h - l
func zscore(series float src, input int len) => float {
m = ta.sma(src, len)
s = ta.stdev(src, len)
return s == 0 ? na : (src - m) / s
}
func scaled(x, k = 2.0) => x * k
z = zscore(volume, 50)
plot(z, "Z объёма", style = plot.style_columns, color = z > 2 ? color.orange : color.gray)
plot(scaled(barRange(high, low), k = 0.5), "Полразмаха")- Ռեկուրսիա չկա. Ֆունկցիան չի կարող կանչել ինքն իրեն, ուղղակի կամ միջանկյալ միջոցով։ Վերադարձից կրկնությունը սրվում է ցիկլով։
- Վիճակը յուրաքանչյուր կանչի համար առանձին է. Եթե ֆունկցիայի մեջ կան
ta.*կամvar, երկու կանչերը նույն ֆունկցիայի տարբեր անկախ հաշվարկներ կիրականացնեն։
indicator("Два вызова одной функции", overlay = true)
func smooth(src, len) => ta.ema(src, len)
fast = smooth(close, 10) // своя средняя
slow = smooth(close, 30) // другая, независимая средняя
plot(fast, "Быстрая", color = color.teal)
plot(slow, "Медленная", color = color.orange)Նույն ֆունկցիաները, որոնց պետք է մի քանի script‑երում, կարելի է տեղափոխել գրադարան՝ հայտարարությամբ library("Имя", 1), ֆունկցիաների առաջ տեղադրել export, այլ script‑ում օգտագործել import Имя/1 as имя։ Գրադարանն առնվում է ձեր script‑ների فولդերից։
Несколько результатов
Որոշ ֆունկցիաներ վերադարձնում են միանգամից մի քանի շարքեր՝ ta.bb, ta.macd, ta.kc, ta.dmi, ta.supertrend և այլն։ Արդյունքը բաշխվում է փակագծերով ցուցադրված փոփոխականների մեջ; անունների թիվը պետք է համընկնի վերադարձվող արդյունքների թվի հետ։
indicator("Полосы Боллинджера", overlay = true)
[basis, upper, lower] = ta.bb(close, 20, 2.0)
plot(basis, "Середина", color = color.gray)
plot(upper, "Верх", color = color.teal)
plot(lower, "Низ", color = color.teal)Свои типы и перечисления
type‑ը հավաքում է մի քանի դաշտ մեկ կառուցվածքի մեջ։ Օբյեկտը ստեղծվում է Имя.new(...) միջոցով, դաշտերը ընթերցվում և վերագրվում են կետով։
indicator("Последний локальный максимум", overlay = true)
type Swing {
int barIndex
float price
}
var Swing last = Swing.new(barIndex = 0, price = high)
ph = ta.pivothigh(high, 5, 5)
if not na(ph) {
last.barIndex := bar_index - 5
last.price := ph
}
plot(last.price, "Максимум", style = plot.style_stepline, color = color.orange)enum — փակ տարբերակների ցուցակլեյբլներով։ Սխալներ տարբերակների անուններում ավելի լավ է դարձնել կոմպիլյացիոն սխալ, քան լռելյայն սխալով անցնել։ Միասինinput.enum`‑ի հետ enum‑ը կդառնա dropdown կարգավորումներում — տես Настройки и отрисовка։
indicator("Режим рынка")
enum Regime {
trend = "Тренд"
flat = "Флэт"
}
regime = math.abs(close - close[20]) > ta.atr(14) * 3 ? Regime.trend : Regime.flat
plot(regime == Regime.trend ? 1 : 0, "Тренд", style = plot.style_stepline)Функции ta.* внутри условий
Ֆունկցիաներ՝ ինչպիսիք են ta.ema, ta.rsi կամ ta.atr, հիշում են իրենց վիճակը նախորդ բարի մակարդակից։ Եթե այդպիսի կանչ կատարեր միայն որոշ բարերի վրա՝ օրինակ if‑ի ներսում կամ ? :-ի մի ճյուղում, հաշվարկը կսակավեցնի բարերը և կտա թերարժեքներ։
LootScript‑ը դա չէր թույլատրում՝ կոմպիլյատորը ինքն է դուրս բերում յուրաքանչյուր ta.* կանչը պայմաններից և կատարում այն յուրաքանչյուր բարի վրա, իսկ պայմանը միայն ընտրում է՝ օգտագործել արդյո՞ք արդյունքը։ Ուստի նման օրինակը ճիշտ կպատգամի RSI‑ը։
indicator("RSI только на зелёных барах")
r = close > open ? ta.rsi(close, 14) : na
plot(r, "RSI", style = plot.style_circles)Կհեռացվի միայն այն դեպքում, եթե նրա սննխահարկի (argument) ինքնը ծնվում է ճյուղի ներսում։ Այդ դեպքում կոմպիլյատորը չի կարող կանխատեսել և կտա սխալ՝ «Аргумент «len» нельзя вычислить вне ветки — вынесите вызов ta.* на верхний уровень». Իրականացումը՝ հաշվարկել արգումենտը նախ պայմանից դուրս։
indicator("Аргумент до условия")
// Так нельзя — len объявлена внутри ветки:
// if close > open {
// len = 10
// e = ta.ema(close, len)
// }
len = 10
e = ta.ema(close, len)
plot(close > open ? e : na, "EMA на зелёных барах", style = plot.style_circles)Комментарии и перенос строк
//— մեկնաբանություն մինչև տողի վերջը,/* … */— բլոկային մեկնաբանություն, բլոկները կարելի է ներարկել։- Հրամանն ավարտվում է տողի վերջում, կետակի պարզապես չի պահանջվում։
- Երկար արտահայտությունը շարունակվում է հաջորդ տողում, եթե տողը կտրվել է փակագծում, ավարտվում է օպերատորով կամ հաջորդ տողը սկսվում է օպերատորով,
?կամ:։
indicator("Перенос строк")
typical = high
+ low
+ close
signal = close > open
? typical / 3
: na
plot(signal, "Типичная цена на зелёных барах", style = plot.style_circles)Дальше
https://docs.lootx.trade/hy/loot/syntax