Appearance
Справочник торговых команд
Все команды отправляются одним endpoint:
http
POST /api/v1/signalsМеняются поля platform, instanceId, type, cmd и payload. Endpoint требует Public API key со scope signals:write. Формат envelope, идемпотентность и ответ 202 Accepted подробно описаны в разделе Сигналы и статус исполнения.
Два уровня валидации
Backend проверяет envelope (v, signalId, ts, ttlMs, platform, type, cmd, payload), но не проверяет terminal-specific содержимое payload. Поэтому синтаксически корректный запрос может получить 202 Accepted, а затем быть отклонён terminal plugin. Окончательный результат всегда проверяйте через GET /api/v1/signals/{requestId}.
Матрица поддержки
| Команда или возможность | NinjaTrader 8 | MetaTrader 5 |
|---|---|---|
system.pause | да | да |
system.resume | да | да |
system.info | да | да |
order.submit / market | да | да |
order.submit / limit | да | да |
order.submit / stop | да | да |
order.submit / stop_limit | да | нет, terminal вернёт unsupported_execution_type |
stopLoss, takeProfit как абсолютные цены | да | да |
stopLossTicks, takeProfitTicks | да | да |
position.close | да | да |
position.reduce | да | да |
position.protect | да | да |
position.close_all | да | да |
position.flatten_now | да | да |
risk.block_instrument | да | да |
risk.allow_instrument | да | да |
risk.flatten_now | да | да |
Для platform-specific команд не используйте platform=any: например, stop_limit будет направлен также в MT5 и завершится там отказом unsupported_execution_type.
atmStrategyName и другие неописанные дополнительные поля могут проходить через backend без HTTP-ошибки, но текущие tracked terminal plugins не обязаны их использовать. Они не входят в гарантированный Public API contract.
Общие вспомогательные функции
Следующие функции формируют актуальные ts, signalId и Idempotency-Key. Выполните подходящий helper один раз, затем используйте короткие вызовы из разделов ниже.
curl
Для helper нужны curl, jq и uuidgen. Переменная TMPRO_INSTANCE_ID может быть пустой: тогда поле instanceId не добавляется в signal body.
bash
export TMPRO_API_KEY='tmpro_api_REPLACE_ME'
export TMPRO_PLATFORM='ninjatrader'
export TMPRO_INSTANCE_ID='VPS-NT8-01'
send_signal() {
local type="$1"
local cmd="$2"
local payload="$3"
local ts
local signal_id
local idempotency_key
local body
ts=$(date +%s%3N)
signal_id="api-$(uuidgen)"
idempotency_key=$(uuidgen)
body=$(
jq -cn \
--arg signalId "$signal_id" \
--argjson ts "$ts" \
--arg platform "$TMPRO_PLATFORM" \
--arg instanceId "$TMPRO_INSTANCE_ID" \
--arg type "$type" \
--arg cmd "$cmd" \
--argjson payload "$payload" \
'{
v: 1,
signalId: $signalId,
ts: $ts,
ttlMs: 15000,
platform: $platform,
type: $type,
cmd: $cmd,
payload: $payload
} + (
if $instanceId == ""
then {}
else {instanceId: $instanceId}
end
)'
)
curl --request POST 'https://tradingmonitor.pro/api/v1/signals' \
--header "Authorization: Bearer $TMPRO_API_KEY" \
--header 'Content-Type: application/json' \
--header "Idempotency-Key: $idempotency_key" \
--data-binary "$body"
}C#
csharp
using System.Net.Http.Headers;
using System.Net.Http.Json;
static async Task<string> SendSignalAsync(
HttpClient http,
string type,
string cmd,
object payload,
string platform = "ninjatrader",
string? instanceId = "VPS-NT8-01",
CancellationToken cancellationToken = default)
{
var body = new Dictionary<string, object?>
{
["v"] = 1,
["signalId"] = $"api-{Guid.NewGuid():N}",
["ts"] = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
["ttlMs"] = 15_000,
["platform"] = platform,
["type"] = type,
["cmd"] = cmd,
["payload"] = payload
};
if (!string.IsNullOrWhiteSpace(instanceId))
{
body["instanceId"] = instanceId;
}
using var request = new HttpRequestMessage(HttpMethod.Post, "/api/v1/signals")
{
Content = JsonContent.Create(body)
};
request.Headers.Add("Idempotency-Key", Guid.NewGuid().ToString());
using var response = await http.SendAsync(request, cancellationToken);
var responseBody = await response.Content.ReadAsStringAsync(cancellationToken);
Console.WriteLine($"{(int)response.StatusCode} {responseBody}");
response.EnsureSuccessStatusCode();
return responseBody;
}
using var http = new HttpClient
{
BaseAddress = new Uri("https://tradingmonitor.pro")
};
http.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", "tmpro_api_REPLACE_ME");Python
python
import time
import uuid
import requests
API_KEY = "tmpro_api_REPLACE_ME"
def send_signal(
type_,
cmd,
payload,
platform="ninjatrader",
instance_id="VPS-NT8-01",
):
body = {
"v": 1,
"signalId": f"api-{uuid.uuid4().hex}",
"ts": int(time.time() * 1000),
"ttlMs": 15_000,
"platform": platform,
"type": type_,
"cmd": cmd,
"payload": payload,
}
if instance_id:
body["instanceId"] = instance_id
response = requests.post(
"https://tradingmonitor.pro/api/v1/signals",
headers={
"Authorization": f"Bearer {API_KEY}",
"Idempotency-Key": str(uuid.uuid4()),
},
json=body,
timeout=30,
)
print(response.status_code, response.text)
response.raise_for_status()
return response.json()system.pause
Временно переводит выбранный terminal instance в paused state. Новые входы и обычные live-команды блокируются локально. Уже выставленные broker orders автоматически не отменяются, а открытые позиции не закрываются.
Payload:
json
{}bash
send_signal system pause '{}'csharp
await SendSignalAsync(http, "system", "pause", new { });python
send_signal("system", "pause", {})system.resume
Снимает локальный paused state и разрешает дальнейшее исполнение команд.
bash
send_signal system resume '{}'csharp
await SendSignalAsync(http, "system", "resume", new { });python
send_signal("system", "resume", {})system.info
Показывает информационное сообщение в NinjaTrader 8 или MetaTrader 5. В NinjaTrader открывается окно TMPro; в MT5 сообщение выводится средствами plugin. Передавайте payload.info, блок рыночных данных или оба значения.
| Поле | Тип | Описание |
|---|---|---|
info | string | текст сообщения |
DOHLCV.D | string | дата или метка периода |
DOHLCV.O | number | open |
DOHLCV.H | number | high |
DOHLCV.L | number | low |
DOHLCV.C | number | close |
DOHLCV.V | number | volume |
NinjaTrader также принимает legacy-блок OHLC с полями O, H, L, C. Имена DOHLCV и OHLC передавайте именно в верхнем регистре.
bash
TMPRO_PLATFORM='ninjatrader' TMPRO_INSTANCE_ID='VPS-NT8-01' \
send_signal system info '{
"info": "Проверка сигнала перед публикацией NFP",
"DOHLCV": {
"D": "2026-07-16",
"O": 6300.25,
"H": 6312.00,
"L": 6294.50,
"C": 6308.75,
"V": 182450
}
}'csharp
await SendSignalAsync(
http,
"system",
"info",
new
{
info = "Проверка сигнала перед публикацией NFP",
DOHLCV = new
{
D = "2026-07-16",
O = 6300.25,
H = 6312.00,
L = 6294.50,
C = 6308.75,
V = 182450
}
},
platform: "ninjatrader",
instanceId: "VPS-NT8-01");python
send_signal(
"system",
"info",
{
"info": "Проверка сигнала перед публикацией NFP",
"DOHLCV": {
"D": "2026-07-16",
"O": 6300.25,
"H": 6312.00,
"L": 6294.50,
"C": 6308.75,
"V": 182450,
},
},
platform="ninjatrader",
instance_id="VPS-NT8-01",
)order.submit
Создаёт новый entry order. Только для этой команды backend формирует executions[].orderRef, который затем можно использовать для точной отмены.
Общие поля payload
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
instrument | string | да | точное имя инструмента в целевом terminal |
side | string | да | buy или sell |
executionType | string | да | market, limit, stop, stop_limit |
quantity | number | да | значение больше нуля до применения terminal multiplier |
limitPrice | number | зависит от типа | обязательно для limit и stop_limit |
stopPrice | number | зависит от типа | обязательно для stop и stop_limit |
stopLoss | number | нет | абсолютная цена stop loss |
takeProfit | number | нет | абсолютная цена take profit |
stopLossTicks | number | нет | расстояние stop loss в ticks/points terminal symbol |
takeProfitTicks | number | нет | расстояние take profit в ticks/points terminal symbol |
В NinjaTrader итоговый размер — quantity * QuantityMultiplier, нормализованный до количества contracts. В MT5 итоговый объём — quantity * Volume Multiplier, нормализованный по SYMBOL_VOLUME_MIN, SYMBOL_VOLUME_MAX и SYMBOL_VOLUME_STEP.
Если одновременно переданы абсолютная цена и tick-based значение одной защиты, оба terminal plugin используют абсолютную цену. В NinjaTrader расстояние рассчитывается от фактической Position.AveragePrice как ticks * TickSize, после чего цена округляется к tick size инструмента.
Market order
Market order не требует limitPrice или stopPrice.
bash
send_signal order submit '{
"instrument": "ES 09-26",
"side": "buy",
"executionType": "market",
"quantity": 1,
"stopLoss": 6280.25,
"takeProfit": 6310.25
}'csharp
await SendSignalAsync(http, "order", "submit", new
{
instrument = "ES 09-26",
side = "buy",
executionType = "market",
quantity = 1,
stopLoss = 6280.25,
takeProfit = 6310.25
});python
send_signal(
"order",
"submit",
{
"instrument": "ES 09-26",
"side": "buy",
"executionType": "market",
"quantity": 1,
"stopLoss": 6280.25,
"takeProfit": 6310.25,
},
)Для MT5 symbol обычно имеет broker-specific имя, например EURUSD, EURUSD.a или XAUUSDm.
Limit order
limitPrice обязателен и должен быть допустим для выбранного symbol, side и текущего рынка.
bash
send_signal order submit '{
"instrument": "NQ 09-26",
"side": "buy",
"executionType": "limit",
"quantity": 1,
"limitPrice": 23100.25
}'csharp
await SendSignalAsync(http, "order", "submit", new
{
instrument = "NQ 09-26",
side = "buy",
executionType = "limit",
quantity = 1,
limitPrice = 23100.25
});python
send_signal(
"order",
"submit",
{
"instrument": "NQ 09-26",
"side": "buy",
"executionType": "limit",
"quantity": 1,
"limitPrice": 23100.25,
},
)Stop order
stopPrice задаёт trigger price.
bash
send_signal order submit '{
"instrument": "NQ 09-26",
"side": "buy",
"executionType": "stop",
"quantity": 1,
"stopPrice": 23250.00
}'csharp
await SendSignalAsync(http, "order", "submit", new
{
instrument = "NQ 09-26",
side = "buy",
executionType = "stop",
quantity = 1,
stopPrice = 23250.00
});python
send_signal(
"order",
"submit",
{
"instrument": "NQ 09-26",
"side": "buy",
"executionType": "stop",
"quantity": 1,
"stopPrice": 23250.00,
},
)Stop-limit order — только NinjaTrader 8
Требуются одновременно stopPrice и limitPrice. MT5 connector принимает общий JSON, но текущий MT5 Expert Advisor отклоняет live execution со status rejected и reasonCode=unsupported_execution_type.
bash
TMPRO_PLATFORM='ninjatrader' send_signal order submit '{
"instrument": "NQ 09-26",
"side": "sell",
"executionType": "stop_limit",
"quantity": 1,
"stopPrice": 22990.00,
"limitPrice": 22988.00
}'csharp
await SendSignalAsync(
http,
"order",
"submit",
new
{
instrument = "NQ 09-26",
side = "sell",
executionType = "stop_limit",
quantity = 1,
stopPrice = 22990.00,
limitPrice = 22988.00
},
platform: "ninjatrader",
instanceId: "VPS-NT8-01");python
send_signal(
"order",
"submit",
{
"instrument": "NQ 09-26",
"side": "sell",
"executionType": "stop_limit",
"quantity": 1,
"stopPrice": 22990.00,
"limitPrice": 22988.00,
},
platform="ninjatrader",
instance_id="VPS-NT8-01",
)Protection в ticks
Для обоих terminal можно задать расстояния вместо абсолютных цен. В NinjaTrader защита применяется после появления позиции и рассчитывается от её фактической средней цены. В MT5 для pending order расстояние рассчитывается от entry price, а для market order — от фактической цены открытия.
bash
TMPRO_PLATFORM='mt5' TMPRO_INSTANCE_ID='MT5-DEMO-01' \
send_signal order submit '{
"instrument": "EURUSD",
"side": "buy",
"executionType": "market",
"quantity": 0.10,
"stopLossTicks": 200,
"takeProfitTicks": 300
}'csharp
await SendSignalAsync(
http,
"order",
"submit",
new
{
instrument = "EURUSD",
side = "buy",
executionType = "market",
quantity = 0.10,
stopLossTicks = 200,
takeProfitTicks = 300
},
platform: "mt5",
instanceId: "MT5-DEMO-01");python
send_signal(
"order",
"submit",
{
"instrument": "EURUSD",
"side": "buy",
"executionType": "market",
"quantity": 0.10,
"stopLossTicks": 200,
"takeProfitTicks": 300,
},
platform="mt5",
instance_id="MT5-DEMO-01",
)position.close
Закрывает открытую позицию указанного инструмента. Команда не отменяет независимые pending orders этого инструмента; для одновременной отмены orders и закрытия position используйте position.flatten_now.
В MT5 статус terminal_completed отправляется только после подтверждения, что целевая позиция фактически отсутствует.
bash
send_signal position close '{"instrument":"ES 09-26"}'csharp
await SendSignalAsync(
http,
"position",
"close",
new { instrument = "ES 09-26" });python
send_signal("position", "close", {"instrument": "ES 09-26"})position.reduce
Уменьшает текущую позицию на quantity до применения terminal multiplier. Если нормализованный объём не меньше текущего объёма позиции, terminal выполняет полное закрытие.
В MT5 операция завершается только после подтверждения уменьшенного фактического объёма.
bash
send_signal position reduce '{
"instrument": "ES 09-26",
"quantity": 1
}'csharp
await SendSignalAsync(http, "position", "reduce", new
{
instrument = "ES 09-26",
quantity = 1
});python
send_signal(
"position",
"reduce",
{"instrument": "ES 09-26", "quantity": 1},
)position.protect
Устанавливает или заменяет защиту открытой позиции. Требуется хотя бы одно поле stop loss или take profit.
| Поля | NinjaTrader 8 | MetaTrader 5 |
|---|---|---|
stopLoss, takeProfit | да | да |
stopLossTicks, takeProfitTicks | да | да |
NinjaTrader создаёт protective orders для текущего размера позиции; tick-based цены рассчитываются от Position.AveragePrice. MT5 изменяет фактические SL/TP позиции. Если одновременно указаны абсолютное и tick-based значения одной защиты, используется абсолютная цена.
bash
send_signal position protect '{
"instrument": "ES 09-26",
"stopLoss": 6280.25,
"takeProfit": 6310.25
}'csharp
await SendSignalAsync(http, "position", "protect", new
{
instrument = "ES 09-26",
stopLoss = 6280.25,
takeProfit = 6310.25
});python
send_signal(
"position",
"protect",
{
"instrument": "ES 09-26",
"stopLoss": 6280.25,
"takeProfit": 6310.25,
},
)Вариант в ticks:
bash
TMPRO_PLATFORM='mt5' TMPRO_INSTANCE_ID='MT5-DEMO-01' \
send_signal position protect '{
"instrument": "EURUSD",
"stopLossTicks": 150,
"takeProfitTicks": 250
}'csharp
await SendSignalAsync(
http,
"position",
"protect",
new
{
instrument = "EURUSD",
stopLossTicks = 150,
takeProfitTicks = 250
},
platform: "mt5",
instanceId: "MT5-DEMO-01");python
send_signal(
"position",
"protect",
{
"instrument": "EURUSD",
"stopLossTicks": 150,
"takeProfitTicks": 250,
},
platform="mt5",
instance_id="MT5-DEMO-01",
)position.close_all
Закрывает все открытые позиции account, обслуживаемого выбранным terminal instance. Команда не является cancel-all для pending orders.
Payload пустой. В MT5 успешный итог подтверждается только после отсутствия всех захваченных целевых positions.
bash
send_signal position close_all '{}'csharp
await SendSignalAsync(http, "position", "close_all", new { });python
send_signal("position", "close_all", {})position.flatten_now
Для одного instrument отменяет working/pending orders и закрывает открытую позицию. Используйте эту команду, когда нужно полностью убрать market exposure и ожидающие входы только по одному инструменту.
MT5 завершает operation после подтверждения отсутствия целевой позиции и целевых pending orders.
bash
send_signal position flatten_now '{"instrument":"ES 09-26"}'csharp
await SendSignalAsync(
http,
"position",
"flatten_now",
new { instrument = "ES 09-26" });python
send_signal(
"position",
"flatten_now",
{"instrument": "ES 09-26"},
)risk.block_instrument
Локально блокирует новые entry orders для указанного инструмента в выбранном terminal instance. Существующие orders и positions команда не изменяет.
Блокировка является локальным runtime state plugin и не должна рассматриваться как broker-side risk rule.
bash
send_signal risk block_instrument '{"instrument":"ES 09-26"}'csharp
await SendSignalAsync(
http,
"risk",
"block_instrument",
new { instrument = "ES 09-26" });python
send_signal(
"risk",
"block_instrument",
{"instrument": "ES 09-26"},
)risk.allow_instrument
Снимает локальную блокировку, созданную risk.block_instrument.
bash
send_signal risk allow_instrument '{"instrument":"ES 09-26"}'csharp
await SendSignalAsync(
http,
"risk",
"allow_instrument",
new { instrument = "ES 09-26" });python
send_signal(
"risk",
"allow_instrument",
{"instrument": "ES 09-26"},
)risk.flatten_now
Аварийная account-wide команда:
- переводит terminal plugin в paused state;
- отменяет working/pending orders account;
- отправляет закрытие всех открытых positions;
- требует последующего
system.resume, если нужно продолжить обработку новых entry commands.
В MT5 terminal_completed отправляется только после подтверждения, что positions закрыты и целевые pending orders удалены.
Account-wide действие
risk.flatten_now действует на весь account выбранного terminal instance. Не путайте его с position.flatten_now, который ограничен одним инструментом.
bash
send_signal risk flatten_now '{}'csharp
await SendSignalAsync(http, "risk", "flatten_now", new { });python
send_signal("risk", "flatten_now", {})Как интерпретировать результат
Для каждой команды сохраняйте requestId из 202 Accepted и читайте:
http
GET /api/v1/signals/{requestId}Типичные результаты:
| Status | Значение |
|---|---|
terminal_completed | non-order команда подтверждена terminal state |
broker_submitted | entry order принят broker/adapter |
partially_filled | order частично исполнен |
filled | order полностью исполнен |
rejected | terminal или broker отклонил команду; проверяйте reasonCode |
not_executed | команда не была выполнена |
not_confirmed | terminal confirmation не получено до timeout |
Для order.submit результат broker_submitted ещё не является исполнением. Для position/risk-команд не считайте HTTP 202 подтверждением изменения account: ждите terminal_completed, а при not_confirmed проверяйте terminal и broker вручную.
Частые значения reasonCode:
| Code | Значение |
|---|---|
paused | terminal instance находится в paused state |
risk_blocked | инструмент заблокирован risk.block_instrument |
invalid_volume | объём после multiplier/normalization недопустим |
invalid_instrument или instrument_not_found | symbol/instrument не найден или недоступен |
no_tick_data | MT5 не получил актуальные bid/ask для market operation |
broker_rejected | terminal trade request отклонён broker |
position_not_found | целевая открытая позиция отсутствует |
position_or_order_not_found | для instrument flatten нет позиции и pending orders |
unsupported_execution_type | execution type не поддерживается terminal, в частности MT5 stop_limit |
target_mismatch | tracked command адресован другому instance |
expired | команда истекла до обработки terminal |
terminal_timeout | backend не получил terminal confirmation до execution timeout |
Список не является закрытым: terminal plugins могут добавлять новые стабильные reason codes. Клиент должен сохранять неизвестное значение и показывать его оператору без аварийного завершения.