Пользовательские шаблоны оповещений позволяют точно контролировать, какая информация отображается в ваших сообщениях Telegram, вебхук-запросах или email-уведомлениях при срабатывании сигнала арбитража. Шаблоны используют простой синтаксис с заполнителями, циклами и условной логикой — опыт программирования не требуется.
Как Работают Шаблоны
Когда сигнал соответствует фильтрам оповещения, система берёт сохранённый текст шаблона и заменяет каждый заполнитель фактическим значением сигнала перед отправкой уведомления.
- {variable} — заменяется одним значением
- {% for %} — повторяет блок для каждого шага торговли
- {% if %} — показывает разный текст в зависимости от условия
Переменные уровня сигнала
| Заполнитель | Описание | Пример |
|---|---|---|
{signalId} | Уникальный числовой ID сигнала | 4821 |
{signalType} | Ex1 = все шаги на одной бирже · Ex2 = кросс-биржевой | Ex2 |
{coinType} | Торговый цикл: A-B-A (2 пары) или A-B-C-A (3 пары) | A-B-C-A |
{profitPercent} | Валовая прибыль в процентах | 1.85 |
{feePercent} | Расчётная суммарная комиссия в процентах | 0.30 |
{netProfit} | Чистая прибыль после комиссий (profit − fee) | 1.55 |
{volume} | Объём первого (основного) шага | 0.5 |
{lifetime} | Возраст сигнала в секундах с момента создания | 312 |
{createdAt} | Временная метка первого обнаружения сигнала | 2025-03-11 14:02:10 |
{updatedAt} | Временная метка последнего обновления сигнала | 2025-03-11 14:07:22 |
{freeSignal} | 1 если это бесплатный (публичный) сигнал, иначе 0 | 0 |
| Заполнитель | Описание | Пример |
|---|---|---|
{coin_path} | Полный путь монеты от котировки к котировке | USDT → BTC → ETH → USDT |
{symbol_steps} | Список всех торговых пар через запятую | BTCUSDT, ETHBTC, ETHUSDT |
{exchanges_list} | Уникальные задействованные биржи (через запятую) | Binance, KuCoin |
{signal_cards} | Предварительно отформатированный сводный блок сигнала | (multi-line) |
| Заполнитель | Описание | Пример |
|---|---|---|
{exchanges[i]} | Название биржи для шага i | Binance |
{symbols[i]} | Полный символ торговой пары для шага i | BTCUSDT |
{baseSymbols[i]} | Базовый актив пары | BTC |
{quoteSymbols[i]} | Котируемый актив пары | USDT |
{directions[i]} | Направление: 1 = Покупка, -1 = Продажа | 1 |
{prices[i]} | Цена исполнения для шага i | 42318.57 |
{volumes[i]} | Объём торговли для шага i | 0.01182 |
{i+1} | Номер шага начиная с 1 (читаемый человеком) | 1, 2, 3 |
| Заполнитель | Описание |
|---|---|
{symbolStats[exchanges[i]+'_'+symbols[i]].minBid} | Минимальная цена bid в стакане |
{symbolStats[exchanges[i]+'_'+symbols[i]].maxBid} | Максимальная цена bid в стакане |
{symbolStats[exchanges[i]+'_'+symbols[i]].minAsk} | Минимальная цена ask в стакане |
{symbolStats[exchanges[i]+'_'+symbols[i]].maxAsk} | Максимальная цена ask в стакане |
{symbolStats[exchanges[i]+'_'+symbols[i]].bidQty} | Общее количество доступное на стороне bid |
{symbolStats[exchanges[i]+'_'+symbols[i]].askQty} | Общее количество доступное на стороне ask |
Синтаксис Шаблонов
Сигналы имеют 2 шага (A-B-A) или 3 шага (A-B-C-A). Цикл выполняется автоматически один раз для каждого шага.
{% for i in 0..symbols.length-1 %}
Step {i+1}: {symbols[i]} on {exchanges[i]}
{% endfor %}
Вывод для 3-шагового сигнала:
Step 1: BTCUSDT on Binance
Step 2: ETHBTC on Binance
Step 3: ETHUSDT on KuCoin
Используйте {% if %}...{% else %}...{% endif %} для отображения разного текста в зависимости от значения. Работает как внутри, так и вне циклов.
Направление покупки/продажи:
{% if directions[i] == 1 %}BUY{% else %}SELL{% endif %}
Тип биржи:
{% if signalType == 'Ex2' %}Cross-Exchange{% else %}Same-Exchange{% endif %}
Тип цикла монет:
{% if coinType == 'A-B-C-A' %}Triangular{% else %}Simple{% endif %}
Бейдж бесплатного сигнала:
{% if freeSignal == 1 %}🆓 Free Signal{% endif %}
| Заполнитель | Описание | Пример |
|---|---|---|
== | Равно | directions[i] == 1 |
!= | Не равно | signalType != 'Ex1' |
> | Больше чем | profitPercent > 2 |
< | Меньше чем | feePercent < 0.5 |
Готовые Шаблоны
Это те же шаблоны, что доступны в выпадающем меню в окне оповещений. Используйте их как есть или как отправную точку для своего шаблона.
🚀 Arbitrage Alert [{signalType}] - {coinType}
📊 Profit: +{profitPercent}% | Fee: {feePercent}% | Net: +{netProfit}%
🔀 Path: {coin_path}
🏦 {exchanges_list}
⏱ Lifetime: {lifetime}
🚀 *Arbitrage Signal* [{signalType} | {coinType}]
━━━━━━━━━━━━━━━━━━━━
💰 *Profit:* +{profitPercent}%
💸 *Fee:* {feePercent}%
📈 *Net:* +{netProfit}%
📦 *Volume:* {volume}
🔀 *Path:* {coin_path}
🏦 *Exchanges:* {exchanges_list}
📋 *Steps:*
{% for i in 0..symbols.length-1 %}
[{i+1}] {exchanges[i]} | {symbols[i]}
↳ {% if directions[i] == 1 %}🟢 Buy{% else %}🔴 Sell{% endif %} @ {prices[i]}
↳ Vol: {volumes[i]}
{% endfor %}
⏱ *Lifetime:* {lifetime}
🕐 *Updated:* {updatedAt}
🚀 *Arbitrage Signal* #️⃣{signalId}
━━━━━━━━━━━━━━━━━━━━
📌 *Type:* {signalType} ({coinType})
{% if signalType == 'Ex2' %}🔁 *Cross-Exchange*{% else %}🔄 *Same-Exchange*{% endif %}
💰 *Profit:* +{profitPercent}%
💸 *Fee:* -{feePercent}%
📈 *Net Profit:* +{netProfit}%
📦 *Volume:* {volume}
🔀 *Coin Path:* {coin_path}
📍 *Symbols:* {symbol_steps}
🏦 *Exchanges:* {exchanges_list}
━━━━━━━━━━━━━━━━━━━━
📋 *STEP DETAILS*
━━━━━━━━━━━━━━━━━━━━
{% for i in 0..symbols.length-1 %}
[STEP {i+1}]
Exchange: {exchanges[i]}
Pair: {symbols[i]} ({baseSymbols[i]}/{quoteSymbols[i]})
Action: {% if directions[i] == 1 %}🟢 BUY{% else %}🔴 SELL{% endif %}
Price: {prices[i]}
Volume: {volumes[i]}
Order Book:
Bid → min: {symbolStats[exchanges[i]+'_'+symbols[i]].minBid} max: {symbolStats[exchanges[i]+'_'+symbols[i]].maxBid} qty: {symbolStats[exchanges[i]+'_'+symbols[i]].bidQty}
Ask → min: {symbolStats[exchanges[i]+'_'+symbols[i]].minAsk} max: {symbolStats[exchanges[i]+'_'+symbols[i]].maxAsk} qty: {symbolStats[exchanges[i]+'_'+symbols[i]].askQty}
{% endfor %}
━━━━━━━━━━━━━━━━━━━━
⏱ Lifetime: {lifetime}
🕐 Created: {createdAt}
🔄 Updated: {updatedAt}
{% if freeSignal == 1 %}🆓 Free Signal{% endif %}
Расширенные Примеры
Отправляйте структурированные данные на свой эндпоинт или C# приложение.
{
"id": {signalId},
"type": "{signalType}",
"coinType": "{coinType}",
"profit": {profitPercent},
"fee": {feePercent},
"netProfit": {netProfit},
"volume": {volume},
"path": "{coin_path}",
"exchanges": "{exchanges_list}",
"lifetime": {lifetime},
"createdAt": "{createdAt}",
"steps": [
{% for i in 0..symbols.length-1 %}
{
"step": {i+1},
"exchange": "{exchanges[i]}",
"symbol": "{symbols[i]}",
"base": "{baseSymbols[i]}",
"quote": "{quoteSymbols[i]}",
"direction": {% if directions[i] == 1 %}"buy"{% else %}"sell"{% endif %},
"price": {prices[i]},
"volume": {volumes[i]},
"orderBook": {
"minBid": {symbolStats[exchanges[i]+'_'+symbols[i]].minBid},
"maxBid": {symbolStats[exchanges[i]+'_'+symbols[i]].maxBid},
"minAsk": {symbolStats[exchanges[i]+'_'+symbols[i]].minAsk},
"maxAsk": {symbolStats[exchanges[i]+'_'+symbols[i]].maxAsk},
"bidQty": {symbolStats[exchanges[i]+'_'+symbols[i]].bidQty},
"askQty": {symbolStats[exchanges[i]+'_'+symbols[i]].askQty}
}
}{% endfor %}
]
}
Добавьте визуальный маркер, когда чистая прибыль превышает порог.
{% if netProfit > 1.5 %}🔥 HIGH PROFIT{% else %}🚀 Signal{% endif %} [{signalType}] {coinType}
Net: +{netProfit}% | Path: {coin_path}
{% if signalType == 'Ex2' %}⚡ Cross-exchange — check transfer fees!{% endif %}
Signal #{signalId} — {coinType} — Net +{netProfit}%
{% for i in 0..symbols.length-1 %}
▸ Step {i+1} · {exchanges[i]} · {symbols[i]}
{% if directions[i] == 1 %}BUY{% else %}SELL{% endif %} @ {prices[i]} (vol: {volumes[i]})
Bid {symbolStats[exchanges[i]+'_'+symbols[i]].minBid} – {symbolStats[exchanges[i]+'_'+symbols[i]].maxBid} qty {symbolStats[exchanges[i]+'_'+symbols[i]].bidQty}
Ask {symbolStats[exchanges[i]+'_'+symbols[i]].minAsk} – {symbolStats[exchanges[i]+'_'+symbols[i]].maxAsk} qty {symbolStats[exchanges[i]+'_'+symbols[i]].askQty}
{% endfor %}
Советы и Распространённые Ошибки
- Всегда закрывайте циклы и условия. Каждый
{% for %}нуждается в соответствующем{% endfor %}, а каждый{% if %}— в{% endif %}. - Переменные стакана работают только внутри цикла. Ключ
exchanges[i]+'_'+symbols[i]требует, чтобыiбыл определён блоком{% for %}. - Строковые сравнения требуют кавычек. Используйте
signalType == 'Ex2'(с одинарными кавычками), а неsignalType == Ex2. - Числовые сравнения не требуют кавычек. Используйте
directions[i] == 1илиnetProfit > 1.5. - Lifetime указан в секундах. Значение
312означает 5 минут и 12 секунд. При необходимости отформатируйте в сообщении. - Жирный шрифт Markdown в Telegram. Оберните текст
*звёздочками*для жирного шрифта в Telegram (режим разбора MarkdownV1). - Не используйте голые фигурные скобки
{}ни для чего кроме заполнителей — они будут интерпретированы как теги шаблона и могут нарушить рендеринг.
| Переменная | Тип | Примечания |
|---|---|---|
{signalId} | Integer | Безопасно использовать в JSON без кавычек |
{profitPercent}, {feePercent}, {netProfit} | Decimal | До 4 знаков после запятой |
{prices[i]}, {volumes[i]} | Decimal | До 8 знаков после запятой |
{directions[i]} | Integer | 1 или -1 |
{freeSignal} | Integer | 0 или 1 |
{lifetime} | Integer | Секунды (напр. 312) |
{createdAt}, {updatedAt} | String | Формат: ГГГГ-ММ-ДД ЧЧ:ММ:СС |
| Переменные пути и сводки | String | Заключайте в кавычки в JSON-запросах |