Create Signal Bot (MCP Tool)
Description
Based on: /docs/rest-api/post-signal-bot-create
Create a Signal Bot using the same settings and validation as the cabinet form. Check the REST API reference for conditional settings and field rules. The response includes the saved bot code. This tool runs on WunderTrading.
Required permission: signal_bot:write.
Prompt example
Create a Signal Bot with DCA mode Order Averaging and cost averaging by quote. Ask me for any other required settings.
For this request, use applyDcaForFirstSafetyOrder: true and extraOrderCostAveraging: "quote". The UI's Bot start condition is signalSource; its Form/JSON settings switch controls alertSettingsType.
Input Schema
{
"type": "object",
"description": "Complete Signal Bot settings, as required by the REST API. On edit, provide the full settings payload, not only changed fields. Match cabinet labels to the API fields described below; do not send UI-only names. The DCA switch controls whether extraOrder* fields are sent.",
"properties": {
"name": {
"type": "string",
"example": "My Signal Bot",
"description": "Bot name in the UI."
},
"about": {
"type": [
"string",
"null"
],
"description": "Optional description shown with the bot."
},
"time": {
"type": "string",
"example": "5M",
"description": "Timeframe in the UI, joined as value and period, for example 5M."
},
"exchanges": {
"type": "object",
"description": "Exchange accounts and pairs selected in the UI. Key by exchange code; each value has profiles [{code, multiplier}], pairsCodes, leverage and leverageBy. For leverageBy, cost multiplies the order amount by leverage; value leaves that multiplier at 1. Read responses show null leverage and leverageBy for paper profiles and spot exchanges.",
"additionalProperties": {
"type": "object",
"required": [
"profiles",
"pairsCodes"
],
"properties": {
"profiles": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"required": [
"code"
],
"properties": {
"code": {
"type": "string",
"description": "API profile code."
},
"multiplier": {
"type": "number",
"minimum": 0.1,
"maximum": 125,
"default": 1,
"description": "Multiplier for this profile's order amount."
}
},
"description": "One API profile and its order multiplier."
},
"description": "API profiles that receive this bot's signals."
},
"pairsCodes": {
"type": "array",
"minItems": 1,
"items": {
"type": "string",
"description": "One trading pair code."
},
"description": "Pairs traded on this exchange."
},
"leverage": {
"type": "number",
"default": 1,
"description": "Leverage for this exchange's orders."
},
"leverageBy": {
"type": "string",
"enum": [
"value",
"cost"
],
"default": "value",
"description": "cost multiplies order amount by leverage; value keeps the amount multiplier at 1 while setting position leverage."
}
},
"description": "Settings for one exchange."
}
},
"multipleEntries": {
"type": "boolean",
"description": "Multiple entries: allow repeated same-side entries for a pair. When false, an existing same-side position blocks another entry."
},
"dynamicPair": {
"type": "boolean",
"description": "Dynamic pair: use the pair named in each alert if configured on this single-exchange bot. The brand must enable this feature; otherwise true is rejected."
},
"swingTrade": {
"type": "boolean",
"description": "Swing trade: an opposite Enter Long/Enter Short alert can close or reverse the position; ordinary Exit Long/Exit Short alerts are disabled."
},
"maxOpenPositions": {
"type": [
"number",
"null"
],
"description": "Max open positions in the UI."
},
"alertSettingsType": {
"type": "string",
"enum": [
"message",
"base_json",
"advanced_json"
],
"description": "Alert body: message = plain-text action code and bot-saved amount; message requires amountPerTrade, amountPerTradeType, reduceOnly, keepPositionOpen and placeConditionalOrdersOnExchange. base_json requires the three boolean position settings and sends the entry amount in each JSON alert. advanced_json sends trading settings in each alert. After creating the bot, call get_signal_bot_alerts for the exact webhook URL and bodies."
},
"signalSource": {
"type": "string",
"example": "trading_view",
"description": "Webhook source. Default brand: trading_view, trading_view_strategy, take_profit_com, runbot, custom, other; 3Commas: trading_view, trading_view_strategy, custom, other. get_signal_bot_alerts returns the external /bot/{signalSource} URL and action codes. trading_view_strategy needs advanced_json strategy data; custom needs an approved source IP."
},
"simulateSignal": {
"type": "string",
"enum": [
"long",
"short",
"wait"
],
"default": "wait",
"deprecated": true,
"description": "Default side used by the cabinet's signal simulation control."
},
"maxCapitalUsdCents": {
"type": [
"integer",
"null"
],
"minimum": 1,
"description": "Max capital: UI amount is in USD; multiply by 100 for API cents."
},
"amountPerTrade": {
"type": "number",
"minimum": 0,
"description": "Saved trade amount for message alerts only. base_json and advanced_json read entry amounts from the signal, so editing this field does not change those bots. For percents, send a fraction (10% = 0.1)."
},
"amountPerTradeType": {
"type": "string",
"enum": [
"base",
"quote",
"contracts",
"$",
"percents"
],
"description": "Message-alert amount unit. One spot pair: base (BTC in BTC/USDT), quote (USDT), or percents. One derivative pair: quote, contracts, or percents. Multiple pairs: $ or percents. The cabinet UI uses different internal values."
},
"orderType": {
"type": "string",
"enum": [
"market",
"limit",
"stop_limit",
"best_bid_ask_limit"
],
"description": "Entry order type. UI Conditional limit = best_bid_ask_limit; Market = market."
},
"orderTypeSettings": {
"type": [
"object",
"null"
],
"description": "Conditional limit settings. UI max chase distance is a percent; send a fraction (5% = 0.05).",
"properties": {
"postOnly": {
"type": "boolean",
"description": "Place the limit order without taking existing liquidity."
},
"maxAttempts": {
"type": "integer",
"minimum": 1,
"maximum": 5,
"description": "Maximum attempts to place a conditional limit order."
},
"afterMaxAttemptsReached": {
"type": "string",
"enum": [
"cancel",
"market"
],
"description": "Cancel or use a market order after the last attempt."
},
"maxChaseDistance": {
"type": [
"number",
"null"
],
"minimum": 0.0001,
"maximum": 0.05,
"description": "Maximum price drift to chase for a limit order, as a fraction (5% = 0.05)."
}
}
},
"limitOrderPriceType": {
"type": [
"string",
"null"
],
"enum": [
"bid",
"ask",
"last",
null
],
"description": "Limit order price reference: bid, ask or last."
},
"limitOrderPriceDeviation": {
"type": [
"number",
"null"
],
"exclusiveMinimum": 0,
"description": "Limit order price deviation. When the UI unit is %, send a fraction (1% = 0.01)."
},
"limitOrderPriceDeviationType": {
"type": [
"string",
"null"
],
"enum": [
"quote",
"percents",
null
],
"description": "Price deviation unit for a limit order: percents or quote."
},
"timeToLive": {
"type": [
"integer",
"null"
],
"minimum": 5,
"maximum": 20160,
"description": "Limit order lifetime in minutes."
},
"takeProfits": {
"type": "array",
"description": "Take profit targets. The UI shows portfolio and price deviation in percent; send fractions (25% = 0.25). Minimum price deviation is 0.01% (0.0001).",
"items": {
"type": "object",
"required": [
"portfolio"
],
"properties": {
"price": {
"type": [
"number",
"null"
],
"description": "Fixed target price when a price is used."
},
"priceDeviation": {
"type": [
"number",
"null"
],
"minimum": 0.0001,
"description": "Target price change from the reference price, as a fraction. Minimum 0.01% (send 0.0001)."
},
"portfolio": {
"type": "number",
"exclusiveMinimum": 0,
"description": "Share of the position to close at this target, as a fraction."
}
},
"description": "One take-profit target."
}
},
"takeProfitBaseOn": {
"type": "string",
"enum": [
"entry_order",
"average_price"
],
"default": "average_price",
"description": "Take profit type: Based on entry order = entry_order; Based on average price = average_price."
},
"takeProfitOrderType": {
"type": "string",
"enum": [
"market",
"best_bid_ask_limit"
],
"description": "Order type used to take profit."
},
"takeProfitOrderTypeSettings": {
"type": [
"object",
"null"
],
"description": "Settings for best_bid_ask_limit take-profit orders.",
"properties": {
"postOnly": {
"type": "boolean",
"description": "Place the take-profit limit order without taking existing liquidity."
}
}
},
"stopLoss": {
"type": [
"number",
"null"
],
"minimum": 0.0001,
"description": "Stop loss target. For Signal and DCA Bots, UI percent is sent as a fraction (2% = 0.02); minimum is 0.01% (0.0001)."
},
"stopLossBaseOn": {
"type": "string",
"enum": [
"entry_order",
"average_price"
],
"default": "entry_order",
"description": "Stop loss type: Based on entry order = entry_order; Based on average price = average_price."
},
"stopLossOrderType": {
"type": "string",
"enum": [
"market",
"best_bid_ask_limit"
],
"description": "Order type used to execute stop loss."
},
"stopLossOrderTypeSettings": {
"type": [
"object",
"null"
],
"description": "Settings for best_bid_ask_limit stop-loss orders.",
"properties": {
"postOnly": {
"type": "boolean",
"description": "Place the stop-loss limit order without taking existing liquidity."
}
}
},
"stopLossMove": {
"type": [
"number",
"null"
],
"exclusiveMinimum": 0,
"description": "Favorable move from entry that triggers a one-time stop-loss update when monitored: Long rises, Short falls. Send a fraction (2% = 0.02)."
},
"stopLossMoveExecute": {
"type": [
"number",
"null"
],
"description": "New stop-loss level relative to entry: Long adds this fraction, Short subtracts it. If omitted, move to current average entry price; if set, it must be below stopLossMove."
},
"trailingStopActivation": {
"type": [
"number",
"null"
],
"exclusiveMinimum": 0,
"description": "Trailing stop activation, as a fraction of the UI percentage."
},
"trailingStopExecute": {
"type": [
"number",
"null"
],
"exclusiveMinimum": 0,
"description": "Trailing-stop distance after activation, as a fraction of the UI percentage."
},
"reduceOnly": {
"type": "boolean",
"description": "Use reduce-only derivative exit orders; has no effect on spot strategies."
},
"keepPositionOpen": {
"type": "boolean",
"description": "Keep monitoring a spot position after TP and SL are disabled so later exit alerts can act."
},
"placeConditionalOrdersOnExchange": {
"type": "boolean",
"description": "Place supported TP/SL orders on the exchange rather than relying only on monitor triggers. DCA disables this; exchange support and order limits apply."
},
"extraOrderCount": {
"type": [
"integer",
"null"
],
"minimum": 1,
"maximum": 30,
"description": "Max DCA orders: includes the initial entry; 5 permits the entry and four extra orders."
},
"extraOrderDeviation": {
"type": [
"number",
"null"
],
"minimum": 0.001,
"maximum": 0.2,
"description": "Price deviation before each extra order, as a fraction: UI 0.8% = 0.008. Long orders follow falling prices; Short orders follow rising prices."
},
"extraOrderVolumeMultiplier": {
"type": [
"number",
"null"
],
"minimum": 0.1,
"maximum": 10,
"description": "Order size multiplier; Order Averaging applies it to the first extra order, Position Averaging starts with the initial size."
},
"extraOrderDeviationMultiplier": {
"type": [
"number",
"null"
],
"minimum": 0.1,
"maximum": 10,
"description": "Price deviation multiplier; Order Averaging applies it to the first extra order, Position Averaging starts with unmultiplied spacing."
},
"extraOrderCostAveraging": {
"type": [
"string",
"null"
],
"enum": [
"base",
"quote",
null
],
"description": "Cost averaging by: By base = base, holding the conventional base-asset quantity (BTC in BTC/USDT); By quote = quote, holding its quote-asset cost (USDT). Final orders are rounded to exchange rules."
},
"extraOrderType": {
"type": [
"string",
"null"
],
"enum": [
"market",
"limit",
null
],
"description": "market waits until price crosses the calculated level, then submits at the current price; limit places a resting order at that level, including the first extra order immediately after entry."
},
"applyDcaForFirstSafetyOrder": {
"type": "boolean",
"default": false,
"description": "UI DCA mode: Order Averaging = true, applying size and spacing multipliers to the first extra order; Position Averaging = false, starting with the initial size and unmultiplied spacing. Do not send a separate UI mode field."
}
},
"required": [
"name",
"time",
"exchanges",
"multipleEntries",
"dynamicPair",
"swingTrade",
"alertSettingsType",
"signalSource"
],
"additionalProperties": true,
"allOf": [
{
"if": {
"properties": {
"alertSettingsType": {
"const": "message"
}
},
"required": [
"alertSettingsType"
]
},
"then": {
"required": [
"amountPerTrade",
"amountPerTradeType"
]
}
},
{
"if": {
"properties": {
"alertSettingsType": {
"enum": [
"message",
"base_json"
]
}
},
"required": [
"alertSettingsType"
]
},
"then": {
"required": [
"reduceOnly",
"keepPositionOpen",
"placeConditionalOrdersOnExchange"
]
}
}
]
}