// Indicator Manual
JavaScript Indicators
Соберите собственный индикатор в редакторе скриптов — готовые примеры, встроенная библиотека расчётов и как вывести индикатор на график.

Зачем это нужно
Каждый индикатор в QUANTIX кто-то написал. Редактор скриптов позволяет этим «кем-то» стать вам: опишите, что хотите видеть, — и оно нарисуется на графике рядом со встроенными инструментами.
Если вы работали в TradingView, это наш ответ Pine Script. Отличие — язык: здесь это JavaScript, поэтому любой пример из учебника, статьи или от ИИ-помощника работает как написан.
Писать с нуля не нужно
Редактор открывается с уже работающим индикатором. Поменяйте число, нажмите Save & Run и посмотрите на график. Это полноценный первый сеанс — всё, что ниже, понадобится, когда захочется большего.
Первый индикатор за пять шагов
- Откройте терминал и нажмите в панели инструментов кнопку
</>Script. - Впишите название в поле Name — под ним индикатор появится в вашем списке.
- В поле Params укажите число, с которым индикатор работает. В примере, который открылся,
20— это длина скользящей средней. - Выберите Placement: Main рисует поверх свечей, Sub открывает отдельную панель снизу. О выборе — чуть ниже.
- Нажмите Save & Run (или Ctrl / ⌘ + Enter). Индикатор появится на графике и с этого момента живёт в разделе Indicators → Custom вместе с остальными.
Это весь цикл. Всё остальное на этой странице — про то, что можно поставить в середину.
Main или Sub — решите до того, как писать
Именно этот выбор определяет, будет ли индикатор читаемым.
- Main — на самом графике, по ценовой шкале. Подходит всему, что измеряется в деньгах: скользящим средним, полосам, каналам, уровням.
- Sub — в собственной панели снизу, со своей шкалой. Подходит всему остальному: RSI со шкалой 0–100, дельте, соотношению, объёму.
Поставьте осциллятор на Main — и ценовая шкала растянется от 0 до 100, чтобы его вместить, а свечи превратятся в плоскую нитку. Если график вдруг выглядит пустым, причина почти всегда эта.
Три вещи, которые есть у вашего индикатора
Считайте редактор небольшой кухней: на столе лежат три вещи, а что из них приготовить — решаете вы.
Свечи — dataList
Все свечи на экране, от старых к новым. Из каждой можно взять:
| Что писать | Что получите |
|---|---|
d.close | Цену закрытия |
d.open | Цену открытия |
d.high / d.low | Максимум и минимум |
d.volume | Объём |
d.timestamp | Время свечи |
Обычная первая строка индикатора собирает одно из этих значений по всей истории:
const closes = dataList.map(d => d.close)Ваши числа — params
Всё, что вы вписали в поле Params через запятую, приходит как params[0], params[1] и так далее. Именно это делает индикатор настраиваемым, а не жёстко зашитым:
// Params: 20, 2
const period = params[0] ?? 20
const width = params[1] ?? 2Часть ?? 20 — значение, которое используется, если поле пустое. Всегда оставляйте его: оно позволяет индикатору работать, пока поле ещё не заполнено.
Набор инструментов — TA
Стандартные расчёты, уже написанные и проверенные. Передаёте список цен и длину — получаете результат:
const ema = TA.ema(closes, period)| Вызов | Что вернёт |
|---|---|
TA.sma(цены, длина) | Простую скользящую среднюю |
TA.ema(цены, длина) | Экспоненциальную скользящую среднюю |
TA.wma(цены, длина) | Взвешенную скользящую среднюю |
TA.hma(цены, длина) | Скользящую Халла |
TA.rma(цены, длина) | Сглаживание Уайлдера (то самое, что внутри RSI и ATR) |
TA.stdev(цены, длина) | Стандартное отклонение — насколько цена уходит от своей средней |
TA.rsi(цены, длина) | RSI, от 0 до 100 |
TA.macd(цены, быстрый, медленный, сигнальный) | MACD: dif, dea и macd сразу |
TA.bollinger(цены, длина, ширина) | Полосы Боллинджера: upper, mid, lower |
TA.tr(максимумы, минимумы, закрытия) | True Range |
TA.atr(максимумы, минимумы, закрытия, длина) | ATR — волатильность |
TA.vwap(максимумы, минимумы, закрытия, объёмы) | VWAP |
TA.cci(максимумы, минимумы, закрытия, длина) | CCI |
Что индикатор должен вернуть
По одному значению на свечу — для каждой линии, которую нужно нарисовать. Последняя строка скрипта говорит, какие линии есть и как они называются:
return closes.map((_, i) => ({
fast: fastEma[i],
slow: slowEma[i],
}))Два имени — две линии на графике, подписанные в легенде как fast и slow. Добавьте третье имя — появится третья линия, и так до 24.
Первые свечи обычно пустые
Средней с периодом 20 нечего показывать, пока не прошло 20 свечей, поэтому линия начинается чуть правее левого края. Это правильно, а не ошибка: индикатор отказывается рисовать число, которого у него нет.
Готовые примеры
Скопируйте любой в редактор, поменяйте числа, нажмите Save & Run.
Две скользящие средние (Placement: Main)
Классика. Params: 50, 200
const fastLength = params[0] ?? 50
const slowLength = params[1] ?? 200
const closes = dataList.map(d => d.close)
const fast = TA.ema(closes, fastLength)
const slow = TA.ema(closes, slowLength)
return closes.map((_, i) => ({
fast: fast[i],
slow: slow[i],
}))Полосы Боллинджера со средней (Placement: Main)
Это тот скрипт, с которого редактор начинается. Params: 20
const period = params[0] ?? 20
const closes = dataList.map(d => d.close)
const boll = TA.bollinger(closes, period, 2)
const ema = TA.ema(closes, period)
return closes.map((_, i) => ({
upper: boll.upper[i],
basis: boll.mid[i],
lower: boll.lower[i],
ema: ema[i],
}))RSI со своими уровнями (Placement: Sub)
Две последние строки — постоянные числа, поэтому они рисуются плоскими ориентирами на 70 и 30. Params: 14
const period = params[0] ?? 14
const closes = dataList.map(d => d.close)
const rsi = TA.rsi(closes, period)
return closes.map((_, i) => ({
rsi: rsi[i],
overbought: 70,
oversold: 30,
}))Волатильность, чтобы выбрать стоп (Placement: Sub)
ATR показывает, на сколько инструмент проходит за среднюю свечу, — это помогает выбрать расстояние до стопа не наугад. Params: 14
const period = params[0] ?? 14
const highs = dataList.map(d => d.high)
const lows = dataList.map(d => d.low)
const closes = dataList.map(d => d.close)
const atr = TA.atr(highs, lows, closes, period)
return closes.map((_, i) => ({
atr: atr[i],
}))Давление покупателей и продавцов (Placement: Sub)
Стандартным набором вы не ограничены. Этот пример задаёт вопрос, на который в библиотеке нет готового ответа: внутри каждой свечи цена держалась ближе к максимуму или к минимуму — и какой объём за этим стоял? Params: 21
const period = params[0] ?? 21
const pressure = dataList.map(d => {
const range = d.high - d.low
if (!range) return 0
const position = (d.close - d.low) / range // 1 = закрылась по максимуму, 0 = по минимуму
return (position - 0.5) * 2 * (d.volume ?? 0)
})
const smoothed = TA.ema(pressure, period)
return pressure.map((_, i) => ({
pressure: smoothed[i],
zero: 0,
}))Выше нуля — свечи закрываются у своих максимумов на реальном объёме. Ниже — у минимумов.
Управление своими индикаторами
- Saved слева в редакторе — список всего, что вы написали. Нажмите на строку, чтобы открыть.
- New очищает редактор под новую идею; сохранённые скрипты остаются на месте.
- Reset возвращает в редактор стартовый пример. Сохранённого он не трогает никогда.
- Indicators → Custom — там живут ваши готовые индикаторы: включить, выключить, скрыть, удалить, а карандаш открывает индикатор обратно в редакторе.
Скрипты хранятся в вашем браузере. Включите Cloud Sync — и они поедут вместе с аккаунтом на любое устройство, где вы войдёте.
Обмен и резервные копии
Export сохраняет текущий скрипт файлом, Import загружает его обратно. Этот файл и есть индикатор — отправьте его коллеге, держите как резервную копию или сложите всю коллекцию в папку.
Индикаторы, опубликованные командой QUANTIX, появляются в Indicators → Custom как шаблоны. Их можно использовать как есть; чтобы сделать шаблон своим, экспортируйте его, поменяйте что нужно и сохраните под новым именем.
Это безопасно?
Ваш индикатор только читает свечи и рисует. У него нет доступа ни в интернет, ни к аккаунту, ни к средствам, ни к чему-либо за пределами графика, а работает он отдельно от остального терминала — ошибка в скрипте не может сломать платформу. Скрипт, зациклившийся навсегда, останавливается через полторы секунды, и вам об этом сообщают.
Практические ограничения: до 24 линий на графике, последние 20 000 свечей истории и скрипт объёмом до 24 000 символов — это несколько страниц расчётов.
Если вы пришли из TradingView
| В Pine Script | Здесь |
|---|---|
indicator() / study() в начале | Переключатель Placement: Main или Sub |
input.int(20) | Поле Params, читается как params[0] |
plot(series) | Имя в возвращаемом списке |
ta.sma(close, 20) | TA.sma(closes, 20) |
na | null |
request.security() — другой инструмент или таймфрейм | Недоступно: индикатор видит тот график, на котором стоит |
strategy() и бэктест | Недоступно: здесь рисуют индикаторы, а не тестируют сделки |
Одну привычку придётся отпустить: Pine сам проходит по свечам, по одной за раз. Здесь вам сразу отдают всю историю, и вы говорите, что сделать со всей ней, — поэтому каждый пример заканчивается на map, инструкции со значением «для каждой свечи».
Если ничего не появилось
| Что видите | Что это значит |
|---|---|
| «Script must return an Array» | Последняя строка не начинается с return либо возвращает одно значение вместо значения на каждую свечу. |
| Свечи превратились в плоскую линию | Осциллятор попал на панель Main. Переключите Placement на Sub. |
| Линия начинается не у левого края | Так и должно быть: у индикатора нет значения, пока не набралось достаточно свечей. |
| «Timeout» | Расчёт не заканчивается. Обычно это цикл внутри цикла — вынесите тяжёлую часть наружу. |
| Ничего не нарисовано, ошибки нет | Значения получились пустыми. Верните на минуту фиксированное число, например { test: 1 }, убедитесь, что линия появляется, — и возвращайте настоящий расчёт по частям. |
Попросите помочь с написанием
Это обычный JavaScript, поэтому индикатор можно описать словами любому ИИ-помощнику, попросить его в виде функции на JavaScript и вставить результат сюда. Скажите ему две вещи: значения берутся из dataList (там есть close, open, high, low, volume), а скрипт должен вернуть по одному объекту на каждую свечу.