MobChart
EN / DE / FR / RU / UA
What do we do?
Workspaces
Chart
Screeners
API for Custom Indicators

📘 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)

Регистрирует индикатор в системе.

ПараметрТипОписание
titlestringНазвание индикатора
descriptionstringКраткое описание
type'onchart' | 'offchart'Расположение индикатора (на графике или в отдельной панели)
isPublictrue | falseИндикатор доступен всем
isPublicCodetrue | 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)Прямая линия
ПараметрТип данныхОписание
titlestringНазвание элемента (уникальный идентификатор на графике)
date1number (timestamp, ms)Начальная временная метка
price1numberНачальная цена (координата по оси Y)
date2number (timestamp, ms)Конечная временная метка (для линий и прямоугольников)
price2numberКонечная цена (для линий и прямоугольников)
sizenumberРазмер фигуры (в пикселях)
radiusnumberРадиус круга (по умолчанию 10)
fillstring (hex, например "#FF0000")Цвет заливки фигуры
opacitynumber (0–1)Прозрачность заливки
strokestring (hex, например "#000000")Цвет обводки
strokeOpacitynumber (0–1)Прозрачность обводки
strokeWidthnumberТолщина линии обводки (в пикселях)
strokeDasharrayarray (например [5,5])Стиль пунктирной линии
fontSizenumberРазмер текста (в пикселях)
valuestringТекстовое значение (для метода 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 candles
const candles = source.ohlcv();
const colorUp = style.color("Color 1", "#2BB462"); // Greenish color for rising prices
const colorDown = style.color("Color 2", "#FB4C51"); // Reddish color for falling prices
const 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 candles
const cbCandles = source.ohlcv('coinbase', 'BTC-USD');
const binanceCandles = source.ohlcv('binance', 'BTCUSDT');
// Extract closes
const 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 index
plot.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
}
);