📘 API для пользовательских индикаторов
🤖 ИИ для генерации пользовательских индикаторов
Используйте следующий документ с ChatGPT, Claude, Gemini или другими ИИ-моделями для генерации пользовательских индикаторов для MobChart.
👉 AI.txt
Пример запроса:
Прочитай приложенный файл AI.txt:https://mobchart.com/docs/public/AI.txtИспользуй его как единственный источник информации об API скриптинга MobChart.Создай пользовательский индикатор, который отображает EMA с периодами 20 и 50 на графике. Окрась свечи в зелёный цвет, если EMA20 находится выше EMA50, и в красный — в противном случае.Используй только документированный API. Не придумывай функции. Верни полный код индикатора.
🔒 Принципы безопасности и текущие ограничения
- Среда исполнения скриптов основана на безопасной JavaScript-песочнице.
- На исполнение вашего скрипта выделяется
1500ms. - Длина массива возвращаемых данных не более 1500. Таким образом, индикатор не может распространяться глубже чем на 1500 свечей.
- Доступно 8 обращения к источнику данных в рамках одного индикатора.
⚒️ Разработка индикатора
Разработка индикатора ведется внутри отдельного виджета, который может располагаться рядом с графиком, внутри которого будет включен данный индикатор.

🧭 Создание индикатора
define(title, description, type, isPublic, isPublicCode)
Регистрирует индикатор в системе.
| Параметр | Тип | Описание |
|---|---|---|
title | string | Название индикатора |
description | string | Краткое описание |
type | 'onchart' | 'offchart' | Расположение индикатора (на графике или в отдельной панели) |
isPublic | true | false | Индикатор доступен всем |
isPublicCode | true | false | Исходный код индикатора доступен всем |
Пример:
define("My Indicator", "Shows EMA line", "onchart", true, false);
Расположение индикаторов при onchart и offchart:

⚙️ Ввод параметров
Классы input и style позволяют создавать настройки для пользователя (аналог input() в PineScript).
| Метод | Описание |
|---|---|
number(title, defaultValue, min, max, step) | Числовой ввод |
range(title, defaultValue, min, max, step) | Ввод из диапазона |
select(title, defaultValue, values) | Выпадающий список |
color(title, defaultValue) | Выбор цвета |
boolean(title, defaultValue) | Двоичная переменная |
Пример (input) для основных параметров:
const length = input.number("Period", 14, 1, 100, 1);const type = input.select("Type", 'sma', ['sma', 'ema']);const color = input.color("Line Color", "#FF0000");
Или (style) для визуальных параметров:
const length = style.number("Size", 14, 1, 100, 1);const color = style.select("Background Color", '#FF0000', ["#FF0000", "#AA0000", "#BB0000"]);const color = style.color("Background Color", "#FF0000");
Параметры из input и style отображаются в отдельных вкладках в настройках индикатора:

🧮 Источники данных
Класс source используется для получения рыночных данных с серверной стороны.
Мы не всегда гарантируем полное соответствие возвращенных данных к видимым свечам на графике.
Например, во время исполнения скрипта может быть возвращено 400 свечей от ohlcv() метода, но только 300 лимитных заявок(для тепловаой карты) от depths() метода.
Используйте дополнительные проверки по параметрам startTime в своем коде.
В данный момент длина массива возвращаемых данных не более 1500.
Таким образом, индикатор не может распространяться глубже чем на 1500 свечей.
В данный момент доступно 8 обращения к источнику данных в рамках одного индикатора.
Параметры exchange, ticker, timeframe по умолчанию привязаны к текущему графику, на котором был открыт индикатор.
Параметр lookback(выборка истории баров от текущей даты, но не более 1500) устанавливается по усмотрению.
| Метод "ohlcv" | Описание |
|---|---|
ohlcv(exchange, ticker, timeframe, lookback?) | Свечные данные |
[{"open": 115886.17,"high": 115911.96,"low": 115764.27,"close": 115815.16,"volume": 228.41528,"startTime": 1757699100000},{...},...]
| Метод "depths" | Описание |
|---|---|
depths(exchange, ticker, timeframe, lookback?) | Лимитные заявки |
[{"data": {"asks": {"109425": 5.467,"109495": 3.564,...},"bids": {"33000": 3.746,"35000": 16.49,...}},"startTime": 1757699100000},{...},...]
| Метод "clusters" | Описание |
|---|---|
clusters(exchange, ticker, timeframe, lookback?) | Кластерные данные |
[{"data": {"totalBuy": 16053385,"totalSell": 20490989,"0.8654": { "buy": 286845, "sell": 336689 },"0.8653": { "buy": 271848, "sell": 259167 },"0.8652": { "buy": 318814, "sell": 373497 },...},"startTime": 1757699100000},{...},...]
| Метод "liquidations" | Описание |
|---|---|
liquidations(exchange, ticker, timeframe, lookback?) | Ликвидации |
[{"data": {"totalBuy": 16053385,"totalSell": 20490989,"0.8654": { "buy": 286845, "sell": 336689 },"0.8653": { "buy": 271848, "sell": 259167 },"0.8652": { "buy": 318814, "sell": 373497 },...},"startTime": 1757699100000},{...},...]
| Метод "moreData" | Описание |
|---|---|
moreData(exchange, ticker, timeframe, lookback?) | Дополнительные данные |
[{"data": {"FR": 0.00003777, // Funding Rate"OI": { // Open Interest Candle"open": 85645.708,"close": 83496.225,"high": 85801.04,"low": 83397.918},"LS": { "l": 0.5426, "s": 0.4574 }, // Long/Short Ratio"taLS": { "l": 0.552, "s": 0.448 }, // Top Traders Account Ratio"tpLS": { "l": 0.5996, "s": 0.4004 } // Top Traders Position Ratio},"startTime": 1757699100000},{...},...]
Пример:
const candles = source.ohlcv(); //Параметры exchange, ticker, timeframe по умолчанию привязаны к текущему графику.const closes = candles.map(c => c.close);
🌐 Глобальные переменные
| Переменная | Описание | Пример |
|---|---|---|
currentExchange | Текущая биржа на графике | binance, binanceFutures, coinbase, ... |
currentTicker | Текущий тикер на графике(формат зависит от бижри) | BTCUSDT, ADA-USD, BTC/USDC, ... |
currentTimeframe | Текущий таймфрейм на графике | 1m, 5m, 15m, ... |
Пример:
const candles = source.ohlcv(currentExchange, currentTicker, currentTimeframe);const closes = candles.map(c => c.close);
🧾 Логирование
Класс logger используется для вывода информации и отладки.
| Метод | Описание |
|---|---|
log(...args) | Добавляет запись в лог (с ограничением длины и количества) |
Пример:
const candles = source.ohlcv();logger.log("First candle:", candles?.[0]);

📈 Визуализация
Класс plot отвечает за отрисовку графических элементов и серий данных.
🔹 Геометрические фигуры
| Метод | Описание |
|---|---|
box(title, date1, price1, date2, price2, fill, opacity, stroke, strokeOpacity, strokeWidth) | Прямоугольник |
square(title, date1, price1, size, fill, opacity, stroke, strokeOpacity, strokeWidth) | Квадрат |
diamond(title, date1, price1, size, fill, opacity, stroke, strokeOpacity, strokeWidth) | Ромб |
triangle(title, date1, price1, size, fill, opacity, stroke, strokeOpacity, strokeWidth) | Треугольник |
circle(title, date1, price1, radius = 10, fill, opacity, stroke, strokeOpacity, strokeWidth) | Круг |
text(title, value, date1, price1, fontSize, fill, opacity) | Текст на графике |
straightLine(title, date1, price1, date2, price2, stroke, strokeOpacity, strokeWidth, strokeDasharray) | Прямая линия |
| Параметр | Тип данных | Описание |
|---|---|---|
title | string | Название элемента (уникальный идентификатор на графике) |
date1 | number (timestamp, ms) | Начальная временная метка |
price1 | number | Начальная цена (координата по оси Y) |
date2 | number (timestamp, ms) | Конечная временная метка (для линий и прямоугольников) |
price2 | number | Конечная цена (для линий и прямоугольников) |
size | number | Размер фигуры (в пикселях) |
radius | number | Радиус круга (по умолчанию 10) |
fill | string (hex, например "#FF0000") | Цвет заливки фигуры |
opacity | number (0–1) | Прозрачность заливки |
stroke | string (hex, например "#000000") | Цвет обводки |
strokeOpacity | number (0–1) | Прозрачность обводки |
strokeWidth | number | Толщина линии обводки (в пикселях) |
strokeDasharray | array (например [5,5]) | Стиль пунктирной линии |
fontSize | number | Размер текста (в пикселях) |
value | string | Текстовое значение (для метода text) |
Пример:
plot.text("Text object", "Hello world!", 1757699100000, 115000, 10, "#00C8FF", 0.5);plot.straightLine(`${namePrefix} Open`, level.timeStart, level.open, level.timeEnd, level.open, color);plot.circle(`${namePrefix} High`, level.timeStart, level.high, 3, color);
Допустимо отобразить не более 3000 фигур на графике.
🔹 Серии данных
| Метод | Описание |
|---|---|
lineSeries(title, values, stroke, strokeOpacity, strokeWidth, strokeDasharray) | Линейный график |
barSeries(title, values, fill, opacity) | Гистограмма |
candleSeries(title, openValues, closeValues, highValues, lowValues, fill, opacity) | Свечи |
Пример:
plot.lineSeries("EMA", ta.ema(closes, 20), "#00C8FF");plot.barSeries("Premium %", premiumPercents, ((d) => d > 0 ? color1 : color2), 1);plot.candleSeries("Candles",opens, closes, highs, lows,(v, i) => {return opens?.[i] > closes?.[i] ? colorBuy : colorSell});
Допустимо отобразить не более 10 серий данных на графике.
📊 Технический анализ
Класс ta включает в себя набор функций, аналогичных PineScript.
🔹 Вспомогательные
| Метод | Описание |
|---|---|
highest(values, period) | Максимум за период |
lowest(values, period) | Минимум за период |
variance(values, period) | Дисперсия |
stdev(values, period) | Стандартное отклонение |
crossover(series1, series2) | Проверка пересечения вверх |
crossunder(series1, series2) | Проверка пересечения вниз |
cross(series1, series2) | Любое пересечение |
🔹 Скользящие средние
| Метод | Описание |
|---|---|
sma(values, period) | Простая скользящая средняя |
ema(values, period) | Экспоненциальная скользящая |
wma(values, period) | Взвешенная скользящая |
🔹 Индикаторы
| Метод | Описание |
|---|---|
rsi(values, period) | Индекс относительной силы |
macd(values, fast, slow, signalPeriod) | MACD |
bollinger(values, period, mult) | Полосы Боллинджера |
stoch(highs, lows, closes, period, smoothK, smoothD) | Стохастический осциллятор |
atr(highs, lows, closes, period) | Средний истинный диапазон |
adx(highs, lows, closes, period) | Индекс направленного движения |
cci(highs, lows, closes, period) | Товарный канал |
vwap(highs, lows, closes, volumes) | Объемно-взвешенная средняя цена |
Пример:
const candles = source.ohlcv();const closes = candles.map(c => c.close);const rsiValues = ta.rsi(closes, 14);plot.lineSeries("RSI", rsiValues, "#00C8FF");
🔔 Алерты
Пользователи могут создавать алерты для вашего индикатора во вкладке Алерты в настройках индикатора на графике. Алерты проверяются на стороне сервера каждые 30 секунд, уведомления отправляются в Telegram и/или на Webhook URL, указанный пользователем.
⚙️ Настройки алерта — alertInput
Класс alertInput объявляет настройки алертов. Он работает так же, как input, но поля отображаются во вкладке Алерты, и каждый пользователь задаёт свои значения для своего алерта.
Скрипты без объявлений alertInput не могут использоваться для алертов.
| Метод | Описание |
|---|---|
number(title, defaultValue, min, max, step) | Числовое поле |
range(title, defaultValue, min, max, step) | Ползунок |
select(title, defaultValue, values) | Выпадающий список |
color(title, defaultValue) | Выбор цвета |
boolean(title, defaultValue) | Логическое поле |
Пример:
const alertVolumeThreshold = alertInput.number("Порог объёма", 1000, 0, 10000000, 1);
🚨 Срабатывание алертов — alert.fire
| Метод | Описание |
|---|---|
fire(title, message, date) | Отправляет уведомление алерта |
- Все три параметра обязательны — вызов без
title,messageилиdateпропускается (в лог записывается предупреждение). - Используйте постоянный title, не генерируйте уникальные названия. Каждый title срабатывает только один раз за запуск (максимум 20 названий за запуск).
date— этоstartTimeсвечи, к которой относится сигнал: тот же title уведомит снова, только когда сработает для более новой свечи. Сигналы со свечей старше момента создания алерта пользователем игнорируются (защита от спама).
Пример:
if (candle.volume > alertVolumeThreshold) {alert.fire("Высокий объём", `объём ${candle.volume}`, candle.startTime);}
📐 Алерты фигур — plot.<фигура>(...).alert(...)
Все геометрические фигуры (box, square, diamond, triangle, circle, straightLine, text) возвращают объект с методом .alert().
Алерт срабатывает с date1 фигуры автоматически, поэтому защита от спама работает без дополнительного кода — это рекомендуемый способ для сигналов на конкретных свечах.
Две формы:
// простая: срабатывает каждый раз, когда фигура рисуется с новой датойplot.box(...).alert("Высокий объём", `объём ${candle.volume}`);plot.box(...).alert((shape) => {if (candle.volume > alertVolumeThreshold)alert.fire("High volume", `vol ${candle.volume}`, candle.startTime);});
Колбэк получает данные фигуры (date1, price1, date2, price2, ...).
📈 Алерты серий — plot.<серия>(...).alert(...)
Серии данных (lineSeries, barSeries, candleSeries) тоже возвращают объект с методом .alert().
Колбэк получает последнюю точку данных и дату последней свечи, алерт срабатывает с этой датой.
lineSeries/barSeries— колбэк получает последнее значение (число)candleSeries— колбэк получает последнюю свечу{open, close, high, low}
plot.lineSeries("RSI", rsiValues, color).alert((rsi, date) => {if (rsi > alertRsiThreshold) alert.fire("Высокий RSI", `RSI ${rsi.toFixed(1)}`, latestCandle.startTime);});
Условие, которое остаётся истинным, уведомляет один раз на каждую новую свечу. Для одноразовых сигналов используйте условия пересечения (ta.crossover).
🧩 Полный пример
const title = "Алерты объёма";const description = "Показывает боксы на свечах с высоким объёмом";define(title, description, "onchart", true, true);const color = style.color("Цвет", "#00C8FF");const volumeThreshold = input.number("Порог объёма", 1000, 0, 10000000, 1);const alertVolumeThreshold = alertInput.number("Порог объёма для алерта", 5000, 0, 10000000, 1);const alertCloseThreshold = alertInput.number("Порог закрытия для алерта", 100000, 0, 10000000, 1);const candles = source.ohlcv();const latestCandle = candles.at(-1);const closes = candles.map(c => c.close);// алерт серии: проверяет последнее закрытиеplot.lineSeries("Closes", closes, color).alert((close, date) => {if (close > alertCloseThreshold) alert.fire("Закрытие выше порога", `close ${close}`, latestCandle.startTime);});for (let i = 0; i < candles.length; i++) {const candle = candles[i];if (candle.volume > volumeThreshold) {const right = i < candles.length - 1 ? candles[i + 1].startTime : candle.startTime + 60000;// алерт фигуры: проверяется по порогу алерта пользователяplot.box(`Volume ${i}`, candle.startTime, candle.high, right, candle.low, "#00C8FF", 0.3).alert(() => {if (candle.volume > alertVolumeThreshold)alert.fire("Высокий объём", `объём ${candle.volume}`, latestCandle.startTime);});}}
🧠 Примеры индикаторов
const title = "Your first indicator";const description = "Shows closes lines on the chart";const indicatorType = "onchart";define(title, description, type, true, true);const color = input.color("Line Color", "#00C8FF");const candles = source.ohlcv();const closes = candles.map(c => c.close);plot.lineSeries("Closes", closes, color);
define("Example Indicator", "Demonstrates basic plotting", "onchart", true, true);const color = input.color("Line Color", "#00FF99");const candles = source.ohlcv();const closes = candles.map(c => c.close);const ema20 = ta.ema(closes, 20);plot.lineSeries("EMA 20", ema20, color);
const title = "Colored Volume Bars";const description = "Volumes colored based on candle direction.";const indicatorType = "onchart";const isPublic = true;const isPublicCode = true;define(title, description, indicatorType, isPublic, isPublicCode);// Get OHLC candlesconst candles = source.ohlcv();const colorUp = style.color("Color 1", "#2BB462"); // Greenish color for rising pricesconst colorDown = style.color("Color 2", "#FB4C51"); // Reddish color for falling pricesconst volumes = candles.map(candle => candle.volume);plot.barSeries("Volume", volumes, (value, index) => {const currentCandle = candles[index];return currentCandle.close >= currentCandle.open ? colorUp : colorDown;});
define('Coinbase Premium Index', 'Coinbase Premium Index', 'offchart', true, false);const color1 = style.color("Color 1", "#2BB462");const color2 = style.color("Color 2", "#FB4C51");// Get OHLC candlesconst cbCandles = source.ohlcv('coinbase', 'BTC-USD');const binanceCandles = source.ohlcv('binance', 'BTCUSDT');// Extract closesconst cbCloses = cbCandles.map(c => c.close);const binanceCloses = binanceCandles.map(c => c.close);// --- Coinbase Premium Index calculation ---const premiumPercent = cbCloses.map((cb, i) => {const b = binanceCloses[i];return ((cb - b) / b) * 100;});// Plot premium indexplot.barSeries("Premium %", premiumPercent, ((d) => d > 0 ? color1 : color2)) // Percentage difference
const title = "Candles";const description = "Simple candles draw";const indicatorType = "offchart";const isPublic = true;const isPublicCode = true;define(title, description, indicatorType, isPublic, isPublicCode);const colorBuy = style.color("Buy Color", "#2BB462");const colorSell = style.color("Sell Color", "#7a3d3f");const candles = source.ohlcv();const closes = candles.map(c => c.close);const opens = candles.map(c => c.open);const highs = candles.map(c => c.high);const lows = candles.map(c => c.low);plot.candleSeries("Candles",opens, closes, highs, lows,(v, i) => {return opens?.[i] > closes?.[i] ? colorBuy : colorSell});