Trading Write¶
futu_place_order¶
- Scope:
trade:real - Python SDK equivalent:
OpenTradeContext.place_order - Route: MCP JSON-RPC
tools/callwith name ="futu_place_order" - ⚠️ Trade write: launch
futu-mcpwith--enable-trading(real env also needs--allow-real-trading)
Description:
⚠️ REAL MONEY when env=real. Place an order on a live brokerage account. REQUIRES futu-mcp started with --enable-trading; real env additionally requires --allow-real-trading; gateway must have been unlocked via futu_unlock_trade first. Market-session fields: US pre/post-market orders must pass the same FTAPI fields as C++ OpenD (fill_outside_rth=true and/or session: 1=RTH, 2=ETH, 3=ALL, 4=OVERNIGHT; optional time_in_force: 0=DAY, 1=GTC, 2=IOC, 3=GTD). The daemon validates market, environment, security type, and broker-specific order-type support locally before any backend write. FTAPI protocol order types 16-19 remain unsupported by ordinary PlaceOrder. Guarded MOC: order type MOC=20 is a versioned v1.8 local extension for real US common stock only and requires an exact current US-equity static-data record; it accepts no price/stop_price, requires a non-empty idempotency_key, and the futu-opend daemon must start with --enable-moc-order (default OFF). An ACK is recorded as pending until an authoritative backend order query correlates the order; cache-only reads never count, and ambiguous outcomes are never resent automatically. This path is source-aligned and fixture-tested but remains UNVERIFIED on an authorized real-money account. Backend still validates symbol, session, and account eligibility. Risk-confirmation errors: when the broker requires the account owner to confirm a risk disclosure first, the error text carries a fixed four-line block (订单尚未提交,需要先完成风险确认。/ 风险确认链接:/ the complete HTTPS URL alone on its own line / 请由账户本人打开并完成确认。完成后重新提交订单。). Relay that block and the link to the user VERBATIM (not in a code fence, never summarised as just "risk confirmation needed"), pause the order flow, never accept the agreement or retry on the user's behalf, and re-check authorization, quotes and buying power before placing the order again after the user confirms.
Request arguments:
| Field | Type | Required | Alias | Description |
|---|---|---|---|---|
market |
string | ✅ | — | Trade market — accepts STRING (HK|US|CN|HKCC|FUTURES|SG|AU|JP|MY|CA) OR INT (1=HK, 2=US, 3=CN, 4=HKCC, 5=Futures, 6=SG, 8=AU, 15=JP, 111=MY, 112=CA per Trd_Common.TrdMarket). |
acc_id |
u64? | — | — | Trading account ID (u64). Either acc_id OR card_num is required. Call futu_list_accounts first to discover acc_id — gateway does NOT infer a default. Alternatively pass card_num (last 4 digits or full 16 digits shown in the app) and daemon resolves it via GetAccList. |
card_num |
string? | — | — | Card number shown by the app. Accepts 4-digit suffix (e.g. <card-suffix>, shown in the app as "Margin Composite Account (<card-suffix>)") OR 16-digit full (e.g. <full-card-num>). These are synthetic placeholders, not real account details. Daemon resolves via GetAccList → matched acc_id. Either acc_id OR card_num required; if both passed, daemon validates resolution matches acc_id (mismatch = 400 reject). |
env |
string | ✓ default default_env_simulate |
trd_env |
Trade environment: real|simulate. Defaults to simulate for safety. Alias: trd_env |
side |
string | ✅ | trd_side |
Order side: BUY|SELL|SELL_SHORT|BUY_BACK. Alias: trd_side |
order_type |
string | ✓ default default_order_type |
— | Order type — accepts STRING enum OR INT (Trd_Common.OrderType): NORMAL=1 (limit) | MARKET=2 | ABSOLUTE_LIMIT=5 | AUCTION=6 | AUCTION_LIMIT=7 | SPECIAL_LIMIT=8 | SPECIAL_LIMIT_ALL=9 | STOP=10 (stop market) | STOP_LIMIT=11 (stop limit) | MIT=12 (market if touched) | LIT=13 (limit if touched) | TRAILING_STOP=14 (trailing stop market) | TRAILING_STOP_LIMIT=15 (trailing stop limit) | TWAP_MARKET=16 | TWAP_LIMIT=17 | VWAP_MARKET=18 | VWAP_LIMIT=19 | MOC=20 (market on close). Algorithm values are rejected by ordinary PlaceOrder; use the typed futu_place_algo_order/futu_modify_algo_order tools (daemon --enable-algo-orders, default OFF). MOC is limited to real US common stock, accepts no price/stop_price, requires idempotency_key, and the daemon must start with --enable-moc-order. Conditional orders require the appropriate stop_price / trail_type / trail_value / trail_spread fields.alias: LIMIT → NORMAL. |
code |
string | ✅ | — | Security code WITHOUT market prefix, e.g. 00700 / AAPL / 600519 |
qty |
float | ✅ | — | Order quantity (shares / contracts) |
price |
float? | — | — | Limit price (required for NORMAL; optional for MARKET; forbidden for MOC) |
amount |
float? | — | — | Event Contract cash amount. Only valid for market=PREDICTION; the gateway derives effective quantity and rejects this field on non-Prediction markets. |
pred_side |
i32? | — | predSide |
Event Contract prediction side: 1=Yes, 2=No. Only valid for market=PREDICTION. Alias: predSide. |
time_in_force |
i32? | — | timeInForce |
Optional order time-in-force: 0=DAY, 1=GTC, 2=IOC, 3=GTD. Alias: timeInForce. |
fill_outside_rth |
boolean? | — | fillOutsideRTH |
US limit orders: allow pre-market / after-hours fills. Alias: fillOutsideRTH. |
session |
i32? | — | — | US order session: 0=NONE, 1=RTH, 2=ETH, 3=ALL, 4=OVERNIGHT. |
expire_time |
string? | — | expireTime |
GTD expire date in YYYY-MM-DD, only used when time_in_force=3. Alias: expireTime. |
jp_acc_type |
i32? | — | jpAccType |
JP sub-account type (Trd_Common.TrdSubAccType / TrdHeader.jpAccType). Required by JP account backend paths when no position_id/order_id path supplies the sub-account context. Alias: jpAccType. |
api_key |
string? | — | — | Optional per-call API key override (plaintext). When set, this key is used for authorization and usage limits instead of the process-wide FUTU_MCP_API_KEY. Useful for multi-tenant scenarios where different calls should be billed or scoped to different keys. |
idempotency_key |
string? | — | — | Optional for legacy order types, REQUIRED for MOC. Retries with the same key return the cached or durably reconciled result WITHOUT placing a duplicate order. Example: generate one UUID per logical order intent and reuse it for retries. |
stop_price |
float? | — | — | Stop / take-profit trigger price (aka aux_price). Required for STOP / STOP_LIMIT / MIT (market-if-touched) / LIT (limit-if-touched). For MIT/LIT it's the take-profit trigger. |
trail_type |
i32? | — | — | Trailing stop type: 1=Ratio (percentage) / 2=Amount (absolute value). Only for TRAILING_STOP / TRAILING_STOP_LIMIT order types. |
trail_value |
float? | — | — | Trailing stop value: trail percentage (if trail_type=1) or amount (if trail_type=2). |
trail_spread |
float? | — | — | Trailing stop limit price spread for TRAILING_STOP_LIMIT (limit offset from trigger). |
⚠️ Unknown fields:
deny_unknown_fieldsis enabled — any field not listed above returns anunknown fielderror (previously silently dropped).Runtime validation: this request type has a
validate()method that adds runtime required-field / enum-value validation on top of the JSON schema.
JSON-RPC call example:
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "futu_place_order",
"arguments": {
"market": "HK",
"acc_id": 123456,
"env": "simulate",
"side": "BUY",
"order_type": "NORMAL",
"code": "00700",
"qty": 100,
"api_key": "optional-per-call-api-key",
"idempotency_key": "uuid-v4-here"
}
}
}
Response: JSON text matching the corresponding REST endpoint / Python SDK. On failure MCP CallToolResult.is_error=true + content carries {"error": "...", "status": "error"}.
futu_modify_order¶
- Scope:
trade:real - Python SDK equivalent:
OpenTradeContext.modify_order - Route: MCP JSON-RPC
tools/callwith name ="futu_modify_order" - ⚠️ Trade write: launch
futu-mcpwith--enable-trading(real env also needs--allow-real-trading)
Description:
⚠️ REAL MONEY when env=real. Modify an existing live order (change qty/price, cancel, disable/enable/delete). REQUIRES --enable-trading; real env needs --allow-real-trading. For simple cancel, prefer futu_cancel_order. Market hours requirement: same as futu_place_order — off-hours hit server-side refusal regardless of op.
Request arguments:
| Field | Type | Required | Alias | Description |
|---|---|---|---|---|
market |
string | ✅ | — | Trade market — accepts STRING (HK|US|CN|HKCC|FUTURES|SG|AU|JP|MY|CA) OR INT (1=HK, 2=US, 3=CN, 4=HKCC, 5=Futures, 6=SG, 8=AU, 15=JP, 111=MY, 112=CA per Trd_Common.TrdMarket). |
acc_id |
u64? | — | — | Trading account ID (u64). Either acc_id OR card_num is required; alternatively pass card_num. |
card_num |
string? | — | — | Card number (4-digit suffix or 16-digit full). See PlaceOrderReq.card_num for semantics. |
env |
string | ✓ default default_env_simulate |
trd_env |
Trade environment: real|simulate (default simulate); alias: trd_env |
order_id |
string | ✅ | — | Order ID to modify. Accepts numeric orderID (integer or integer string) OR backend orderIDEx string such as FU.../FH...; string recommended for JS clients since u64 > 2^53 loses precision as JSON number. |
op |
string | ✓ default default_modify_op |
— | Modify op: NORMAL (change qty/price) | CANCEL | DISABLE | ENABLE | DELETE |
qty |
float? | — | — | New quantity (for NORMAL op) |
price |
float? | — | — | New price (for NORMAL op) |
jp_acc_type |
i32? | — | jpAccType |
JP sub-account type (Trd_Common.TrdSubAccType / TrdHeader.jpAccType). Alias: jpAccType. |
api_key |
string? | — | — | Optional per-call API key override. See PlaceOrderReq.api_key. |
idempotency_key |
string? | — | — | Optional idempotency key (90s TTL). See PlaceOrderReq.idempotency_key. |
⚠️ Unknown fields:
deny_unknown_fieldsis enabled — any field not listed above returns anunknown fielderror (previously silently dropped).Runtime validation: this request type has a
validate()method that adds runtime required-field / enum-value validation on top of the JSON schema.
JSON-RPC call example:
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "futu_modify_order",
"arguments": {
"market": "HK",
"acc_id": 123456,
"env": "simulate",
"order_id": "123456789",
"op": "NORMAL",
"api_key": "optional-per-call-api-key",
"idempotency_key": "uuid-v4-here"
}
}
}
Response: JSON text matching the corresponding REST endpoint / Python SDK. On failure MCP CallToolResult.is_error=true + content carries {"error": "...", "status": "error"}.
futu_unlock_trade¶
- Scope:
trade:unlock - Python SDK equivalent:
OpenTradeContext.unlock_trade - Route: MCP JSON-RPC
tools/callwith name ="futu_unlock_trade"
Description:
⚠️ Opens a trade window for subsequent futu_place_order / futu_modify_order / futu_cancel_order / futu_reconfirm_order calls. NEVER pass the password via tool args: configure FUTU_TRADE_PWD (trimmed) or, on Linux / Windows, an account-scoped OS credential-store entry selected by futu-mcp --trade-pwd-account <login-account>; packaged macOS builds do not support cross-binary Keychain writers. Compatibility credential-store reads have a 3-second safety boundary. Requires trade:unlock scope. Lifetime: once unlocked, all subsequent trade calls succeed without re-authenticating until gateway restart or an explicit unlock=false lock-back. Do NOT call this on every trade (server-side anti-abuse may throttle).
Request arguments:
| Field | Type | Required | Alias | Description |
|---|---|---|---|---|
unlock |
boolean | ✓ default default_true |
— | true to unlock trading (default); false to lock trading cipher back (defensive). Lock does not require a password. |
otp |
string? | — | token, one_time_password |
OTP / 2FA token (plaintext). Only required when a previous unlock call returned need_otp=true or err_code=-8 (TRADE_AUTH_NEED_AUTH_TOKEN). Leave empty for accounts without 2FA. Alias: token / one_time_password |
security_firm |
i32? | — | broker, security_firm_id |
Optional. Restrict unlock to a single security firm (broker). SecurityFirm enum (i32): 1=FutuHK, 2=FutuUS/MooMoo, 3=FutuSG, 4=FutuAU, 5=FutuCA, 6=FutuMY, 7=FutuJP. If omitted, unlocks all brokers in parallel (backward-compatible default). Alias: broker / security_firm_id |
acc_ids |
array of u64? | — | account_ids, accounts |
Optional. Array of positive non-zero u64 acc_ids to unlock (empty / omitted = no per-account filter, use security_firm rule or unlock all). Intersects with security_firm: account must satisfy BOTH. Use when you need to exclude a shadow sub-account that shares a broker with the main account — pass only the main acc_id here. Alias: account_ids / accounts |
⚠️ Unknown fields:
deny_unknown_fieldsis enabled — any field not listed above returns anunknown fielderror (previously silently dropped).
JSON-RPC call example:
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "futu_unlock_trade",
"arguments": {
"unlock": true,
"acc_ids": [
123456
]
}
}
}
Response: JSON text matching the corresponding REST endpoint / Python SDK. On failure MCP CallToolResult.is_error=true + content carries {"error": "...", "status": "error"}.
futu_reconfirm_order¶
- Scope:
trade:real - Python SDK equivalent:
OpenTradeContext.reconfirm_order - Route: MCP JSON-RPC
tools/callwith name ="futu_reconfirm_order" - ⚠️ Trade write: launch
futu-mcpwith--enable-trading(real env also needs--allow-real-trading)
Description:
⚠️ REAL MONEY when env=real. Reconfirm a pending high-risk or price-warning order by numeric order_id. REQUIRES --enable-trading; real env needs --allow-real-trading; gateway must have been unlocked via futu_unlock_trade first. Use only for orders that the backend explicitly asked to reconfirm.
Request arguments:
| Field | Type | Required | Alias | Description |
|---|---|---|---|---|
market |
string | ✅ | — | Trade market — accepts STRING (HK|US|CN|HKCC|FUTURES|SG|AU|JP|MY|CA) OR INT (1=HK, 2=US, 3=CN, 4=HKCC, 5=Futures, 6=SG, 8=AU, 15=JP, 111=MY, 112=CA per Trd_Common.TrdMarket). |
acc_id |
u64? | — | — | Trading account ID (u64). Either acc_id OR card_num is required. |
card_num |
string? | — | — | Card number (4-digit suffix or 16-digit full). Either acc_id OR card_num is required. |
env |
string | ✓ default default_env_simulate |
trd_env |
Trade environment: real|simulate (default simulate); alias: trd_env |
order_id |
string | ✅ | — | FTAPI numeric order_id to reconfirm. Accepts JSON number or integer string; orderIDEx strings are not supported by Trd_ReconfirmOrder. |
reason |
i32 | ✅ | — | Reconfirm reason int per Trd_Common.ReconfirmOrderReason. |
jp_acc_type |
i32? | — | jpAccType |
JP sub-account type (Trd_Common.TrdSubAccType / TrdHeader.jpAccType). Alias: jpAccType. |
api_key |
string? | — | — | Optional per-call API key override. See PlaceOrderReq.api_key. |
⚠️ Unknown fields:
deny_unknown_fieldsis enabled — any field not listed above returns anunknown fielderror (previously silently dropped).
JSON-RPC call example:
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "futu_reconfirm_order",
"arguments": {
"market": "HK",
"acc_id": 123456,
"env": "simulate",
"order_id": "123456789",
"reason": 0,
"api_key": "optional-per-call-api-key"
}
}
}
Response: JSON text matching the corresponding REST endpoint / Python SDK. On failure MCP CallToolResult.is_error=true + content carries {"error": "...", "status": "error"}.
futu_sub_acc_push¶
- Scope:
acc:read - Python SDK equivalent:
OpenTradeContext.subscribe_acc_push (internal to Futu daemon) - Route: MCP JSON-RPC
tools/callwith name ="futu_sub_acc_push"
Description:
Subscribe account order / deal push for given trading accounts. Legacy MCP clients receive LoggingMessage notifications with {kind, proto_id, body_base64}. MCP 2026-07-28 returns resource_uri: using a reusable HTTP Bearer or stdio startup key with acc:read, keep the same identity and call subscriptions/listen, receive notifications/resources/updated, then atomically drain events with resources/read; finish with futu_unsub_acc_push. Payload body is raw Futu protobuf; decode client-side. Python SDK: OpenTradeContext.sub_acc_push.
Request arguments:
| Field | Type | Required | Alias | Description |
|---|---|---|---|---|
acc_ids |
array of u64 | ✅ | account_ids, accounts |
Array of account IDs (u64) to receive order/deal push for. ⚠️ Call futu_list_accounts first to discover real acc_id values; do NOT hallucinate 18-digit numbers — invalid ids will silently fail to receive push. Alias: account_ids / accounts |
api_key |
string? | — | — | Optional per-call API key plaintext. HTTP scope mode still requires a valid Bearer on every /mcp request; this field overrides that identity for the tool handler. In stdio mode: tool argument > startup key. |
⚠️ Unknown fields:
deny_unknown_fieldsis enabled — any field not listed above returns anunknown fielderror (previously silently dropped).
JSON-RPC call example:
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "futu_sub_acc_push",
"arguments": {
"acc_ids": [
123456
],
"api_key": "optional-per-call-api-key"
}
}
}
Response: JSON text matching the corresponding REST endpoint / Python SDK. On failure MCP CallToolResult.is_error=true + content carries {"error": "...", "status": "error"}.
futu_unsub_acc_push¶
- Scope:
acc:read - Python SDK equivalent:
— (daemon-only session control) - Route: MCP JSON-RPC
tools/callwith name ="futu_unsub_acc_push"
Description:
Unsubscribe from account push notifications. Pass session_id from previous futu_sub_acc_push response (session_id field or unsub_hint). Returns {removed_count}. If session_id is not found, removed_count=0 (likely auto-purged or never registered).
Request arguments:
| Field | Type | Required | Alias | Description |
|---|---|---|---|---|
session_id |
string? | — | — | Required: session_id returned by futu_sub_acc_push response (session_id field or unsub_hint). If omitted, handler returns an error. If session_id not found (e.g. 4h auto-purged), removed_count=0 is returned. |
api_key |
string? | — | — | Optional per-call API key plaintext. HTTP scope mode still requires a valid Bearer on every /mcp request; this field overrides that identity for the tool handler. In stdio mode use the same tool/startup key that created the subscription. |
⚠️ Unknown fields:
deny_unknown_fieldsis enabled — any field not listed above returns anunknown fielderror (previously silently dropped).
JSON-RPC call example:
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "futu_unsub_acc_push",
"arguments": {
"session_id": "abc-session-xyz",
"api_key": "optional-per-call-api-key"
}
}
}
Response: JSON text matching the corresponding REST endpoint / Python SDK. On failure MCP CallToolResult.is_error=true + content carries {"error": "...", "status": "error"}.
futu_cancel_all_order¶
- Scope:
trade:real - Python SDK equivalent:
OpenTradeContext.cancel_all_order - Route: MCP JSON-RPC
tools/callwith name ="futu_cancel_all_order" - ⚠️ Trade write: launch
futu-mcpwith--enable-trading(real env also needs--allow-real-trading)
Description:
Cancel all pending orders for an account in a specific market. market is REQUIRED (HK / US / HKCC / A_SH / A_SZ / SG / JP / AU / CA). Python SDK: OpenTradeContext.cancel_all_order. REQUIRES --enable-trading. Real env requires --allow-real-trading. DANGER: unrecoverable — cancels every pending order in the specified market immediately.
Request arguments:
| Field | Type | Required | Alias | Description |
|---|---|---|---|---|
env |
string | ✓ default default_env_simulate |
trd_env |
Trading env: simulate (default) / real; alias: trd_env |
acc_id |
u64 | ✅ | — | Trading account ID (u64). ⚠️ Call futu_list_accounts first to discover — gateway does NOT infer a default. |
market |
string | ✓ default default |
— | Market (REQUIRED, NOT optional) — accepts STRING (HK|US|CN|HKCC|FUTURES|SG|AU|JP|MY|CA) OR INT (1=HK, 2=US, 3=CN, 4=HKCC, 5=Futures, 6=SG, 8=AU, 15=JP, 111=MY, 112=CA). Leaving empty returns a validation error — the backend needs a specific market to cancel orders in. |
api_key |
string? | — | — | Per-call API key override (optional) |
⚠️ Unknown fields:
deny_unknown_fieldsis enabled — any field not listed above returns anunknown fielderror (previously silently dropped).Runtime validation: this request type has a
validate()method that adds runtime required-field / enum-value validation on top of the JSON schema.Runtime validation: market must be non-empty. The schema description marks this field as required, but serde accepts an omitted string as the empty default; this check returns a clear validation error before the request reaches the backend.
JSON-RPC call example:
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "futu_cancel_all_order",
"arguments": {
"env": "simulate",
"acc_id": 123456,
"market": "HK",
"api_key": "optional-per-call-api-key"
}
}
}
Response: JSON text matching the corresponding REST endpoint / Python SDK. On failure MCP CallToolResult.is_error=true + content carries {"error": "...", "status": "error"}.
futu_cancel_order¶
- Scope:
trade:real - Python SDK equivalent:
OpenTradeContext.modify_order(op=ModifyOrderOp.CANCEL) - Route: MCP JSON-RPC
tools/callwith name ="futu_cancel_order" - ⚠️ Trade write: launch
futu-mcpwith--enable-trading(real env also needs--allow-real-trading)
Description:
⚠️ REAL MONEY when env=real. Cancel a live order by order_id. REQUIRES --enable-trading; real env needs --allow-real-trading. Convenience wrapper over futu_modify_order with op=CANCEL. Same market-hours requirement as futu_place_order.
Request arguments:
| Field | Type | Required | Alias | Description |
|---|---|---|---|---|
market |
string | ✅ | — | Trade market — accepts STRING (HK|US|CN|HKCC|FUTURES|SG|AU|JP|MY|CA) OR INT (1=HK, 2=US, 3=CN, 4=HKCC, 5=Futures, 6=SG, 8=AU, 15=JP, 111=MY, 112=CA per Trd_Common.TrdMarket). |
acc_id |
u64? | — | — | Trading account ID (u64). Either acc_id OR card_num is required; alternatively pass card_num. |
card_num |
string? | — | — | Card number (4-digit suffix or 16-digit full). See PlaceOrderReq.card_num for semantics. |
env |
string | ✓ default default_env_simulate |
trd_env |
Trade environment: real|simulate (default simulate); alias: trd_env |
order_id |
string | ✅ | — | Order ID to cancel. Accepts numeric orderID (integer or integer string) OR backend orderIDEx string such as FU.../FH...; string recommended for JS clients since u64 > 2^53 loses precision as JSON number. |
jp_acc_type |
i32? | — | jpAccType |
JP sub-account type (Trd_Common.TrdSubAccType / TrdHeader.jpAccType). Alias: jpAccType. |
api_key |
string? | — | — | Optional per-call API key override. See PlaceOrderReq.api_key. |
idempotency_key |
string? | — | — | Optional idempotency key (90s TTL). See PlaceOrderReq.idempotency_key. |
⚠️ Unknown fields:
deny_unknown_fieldsis enabled — any field not listed above returns anunknown fielderror (previously silently dropped).
JSON-RPC call example:
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "futu_cancel_order",
"arguments": {
"market": "HK",
"acc_id": 123456,
"env": "simulate",
"order_id": "123456789",
"api_key": "optional-per-call-api-key",
"idempotency_key": "uuid-v4-here"
}
}
}
Response: JSON text matching the corresponding REST endpoint / Python SDK. On failure MCP CallToolResult.is_error=true + content carries {"error": "...", "status": "error"}.
futu_place_combo_order¶
- Scope:
trade:real - Python SDK equivalent:
OpenSecTradeContext.place_combo_order - Route: MCP JSON-RPC
tools/callwith name ="futu_place_combo_order" - ⚠️ Trade write: launch
futu-mcpwith--enable-trading(real env also needs--allow-real-trading)
Description:
⚠️ REAL MONEY when header.trd_env=1. Place a combo-option order. REQUIRES --enable-trading; real env additionally requires --allow-real-trading. c2s_json must include header.acc_id, header.trd_env, header.trd_market, combo_legs, qty, and order_type.
Request arguments:
| Field | Type | Required | Alias | Description |
|---|---|---|---|---|
c2s_json |
string | ✅ | — | Official Trd_PlaceComboOrder.C2S JSON. Field names use generated proto serde snake_case. packet_id may be omitted; daemon fills it before forwarding. |
api_key |
string? | — | — | Optional per-call API key override. See PlaceOrderReq.api_key. |
idempotency_key |
string? | — | — | Optional idempotency key. When set, retries with the same key derive the same PacketId and hit daemon replay guard instead of placing a duplicate combo order. |
⚠️ Unknown fields:
deny_unknown_fieldsis enabled — any field not listed above returns anunknown fielderror (previously silently dropped).
JSON-RPC call example:
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "futu_place_combo_order",
"arguments": {
"c2s_json": "…",
"api_key": "optional-per-call-api-key",
"idempotency_key": "uuid-v4-here"
}
}
}
Response: JSON text matching the corresponding REST endpoint / Python SDK. On failure MCP CallToolResult.is_error=true + content carries {"error": "...", "status": "error"}.
futu_place_order_group¶
- Scope:
trade:real - Python SDK equivalent:
— - Route: MCP JSON-RPC
tools/callwith name ="futu_place_order_group" - ⚠️ Trade write: launch
futu-mcpwith--enable-trading(real env also needs--allow-real-trading)
Description:
Place one guarded server-atomic Bracket, OCO, or Basket group. Requires --enable-group-orders; default OFF; live backend unverified.
Request arguments:
| Field | Type | Required | Alias | Description |
|---|---|---|---|---|
c2s_json |
string | ✅ | — | Official generated C2S JSON. Field names use generated proto serde snake_case, e.g. multi_legs / combo_legs / order_type. |
api_key |
string? | — | — | Optional per-call API key plaintext. HTTP scope mode still requires a valid Bearer on every /mcp request; this field overrides that identity for the tool handler. In stdio mode: tool argument > startup key. |
⚠️ Unknown fields:
deny_unknown_fieldsis enabled — any field not listed above returns anunknown fielderror (previously silently dropped).
JSON-RPC call example:
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "futu_place_order_group",
"arguments": {
"c2s_json": "{\"header\":{\"trd_env\":1,\"acc_id\":900000001,\"trd_market\":2},\"initial\":{\"idempotency_key\":\"group-example-1\",\"group_type\":3,\"order_list\":[{\"acc_id\":900000001,\"client_order_id\":\"leg-1\",\"code\":\"AAPL\",\"sec_market\":2,\"trd_side\":1,\"order_type\":1,\"qty\":\"1\",\"price\":\"100\",\"lot_type\":2,\"children_relation\":0,\"brother_relation\":0}]},\"extension_version\":1}",
"api_key": "optional-per-call-api-key"
}
}
}
Response: JSON text matching the corresponding REST endpoint / Python SDK. On failure MCP CallToolResult.is_error=true + content carries {"error": "...", "status": "error"}.
futu_modify_order_group¶
- Scope:
trade:real - Python SDK equivalent:
— - Route: MCP JSON-RPC
tools/callwith name ="futu_modify_order_group" - ⚠️ Trade write: launch
futu-mcpwith--enable-trading(real env also needs--allow-real-trading)
Description:
Modify one authoritative current server order group. Requires --enable-group-orders; default OFF; live backend unverified.
Request arguments:
| Field | Type | Required | Alias | Description |
|---|---|---|---|---|
c2s_json |
string | ✅ | — | Official generated C2S JSON. Field names use generated proto serde snake_case, e.g. multi_legs / combo_legs / order_type. |
api_key |
string? | — | — | Optional per-call API key plaintext. HTTP scope mode still requires a valid Bearer on every /mcp request; this field overrides that identity for the tool handler. In stdio mode: tool argument > startup key. |
⚠️ Unknown fields:
deny_unknown_fieldsis enabled — any field not listed above returns anunknown fielderror (previously silently dropped).
JSON-RPC call example:
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "futu_modify_order_group",
"arguments": {
"c2s_json": "{\"header\":{\"trd_env\":1,\"acc_id\":900000001,\"trd_market\":2},\"initial\":{\"idempotency_key\":\"group-modify-1\",\"group_type\":3,\"order_list\":[{\"order_id\":\"server-order-id\",\"order_version\":1,\"new_price\":\"101\"}]},\"extension_version\":1}",
"api_key": "optional-per-call-api-key"
}
}
}
Response: JSON text matching the corresponding REST endpoint / Python SDK. On failure MCP CallToolResult.is_error=true + content carries {"error": "...", "status": "error"}.
futu_cancel_order_group¶
- Scope:
trade:real - Python SDK equivalent:
— - Route: MCP JSON-RPC
tools/callwith name ="futu_cancel_order_group" - ⚠️ Trade write: launch
futu-mcpwith--enable-trading(real env also needs--allow-real-trading)
Description:
Cancel one authoritative current server order group. Requires --enable-group-orders; default OFF; live backend unverified.
Request arguments:
| Field | Type | Required | Alias | Description |
|---|---|---|---|---|
c2s_json |
string | ✅ | — | Official generated C2S JSON. Field names use generated proto serde snake_case, e.g. multi_legs / combo_legs / order_type. |
api_key |
string? | — | — | Optional per-call API key plaintext. HTTP scope mode still requires a valid Bearer on every /mcp request; this field overrides that identity for the tool handler. In stdio mode: tool argument > startup key. |
⚠️ Unknown fields:
deny_unknown_fieldsis enabled — any field not listed above returns anunknown fielderror (previously silently dropped).
JSON-RPC call example:
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "futu_cancel_order_group",
"arguments": {
"c2s_json": "{\"header\":{\"trd_env\":1,\"acc_id\":900000001,\"trd_market\":2},\"initial\":{\"idempotency_key\":\"group-cancel-1\",\"group_type\":3,\"order_id_list\":[\"server-order-id\"]},\"extension_version\":1}",
"api_key": "optional-per-call-api-key"
}
}
}
Response: JSON text matching the corresponding REST endpoint / Python SDK. On failure MCP CallToolResult.is_error=true + content carries {"error": "...", "status": "error"}.
futu_delete_order_group¶
- Scope:
trade:real - Python SDK equivalent:
— - Route: MCP JSON-RPC
tools/callwith name ="futu_delete_order_group" - ⚠️ Trade write: launch
futu-mcpwith--enable-trading(real env also needs--allow-real-trading)
Description:
Delete one authoritative current server order group. Requires --enable-group-orders; default OFF; live backend unverified.
Request arguments:
| Field | Type | Required | Alias | Description |
|---|---|---|---|---|
c2s_json |
string | ✅ | — | Official generated C2S JSON. Field names use generated proto serde snake_case, e.g. multi_legs / combo_legs / order_type. |
api_key |
string? | — | — | Optional per-call API key plaintext. HTTP scope mode still requires a valid Bearer on every /mcp request; this field overrides that identity for the tool handler. In stdio mode: tool argument > startup key. |
⚠️ Unknown fields:
deny_unknown_fieldsis enabled — any field not listed above returns anunknown fielderror (previously silently dropped).
JSON-RPC call example:
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "futu_delete_order_group",
"arguments": {
"c2s_json": "{\"header\":{\"trd_env\":1,\"acc_id\":900000001,\"trd_market\":2},\"initial\":{\"idempotency_key\":\"group-delete-1\",\"group_type\":3,\"order_id_list\":[\"server-order-id\"]},\"extension_version\":1}",
"api_key": "optional-per-call-api-key"
}
}
}
Response: JSON text matching the corresponding REST endpoint / Python SDK. On failure MCP CallToolResult.is_error=true + content carries {"error": "...", "status": "error"}.
futu_place_algo_order¶
- Scope:
trade:real - Python SDK equivalent:
— - Route: MCP JSON-RPC
tools/callwith name ="futu_place_algo_order" - ⚠️ Trade write: launch
futu-mcpwith--enable-trading(real env also needs--allow-real-trading)
Description:
Place a guarded typed TWAP/VWAP/POV/Slicer/Peg/Iceberg order only when the pinned product/price-mode/side/round-lot table, live capability cell, customer-company fact, and required BCAN facts all agree. Requires --enable-algo-orders; default OFF; live backend unverified.
Request arguments:
| Field | Type | Required | Alias | Description |
|---|---|---|---|---|
c2s_json |
string | ✅ | — | Official generated C2S JSON. Field names use generated proto serde snake_case, e.g. multi_legs / combo_legs / order_type. |
api_key |
string? | — | — | Optional per-call API key plaintext. HTTP scope mode still requires a valid Bearer on every /mcp request; this field overrides that identity for the tool handler. In stdio mode: tool argument > startup key. |
⚠️ Unknown fields:
deny_unknown_fieldsis enabled — any field not listed above returns anunknown fielderror (previously silently dropped).
JSON-RPC call example:
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "futu_place_algo_order",
"arguments": {
"c2s_json": "{\"header\":{\"trd_env\":1,\"acc_id\":900000001,\"trd_market\":2},\"initial\":{\"idempotency_key\":\"algo-example-1\",\"client_order_id\":\"algo-client-1\",\"code\":\"AAPL\",\"sec_market\":2,\"trd_side\":1,\"qty\":\"100\",\"price_mode\":2,\"limit_price\":\"100\",\"lot_type\":2,\"order_trade_time_type\":1,\"position_open_type\":1,\"pdt_protection\":true,\"algo\":{\"algo_type\":2,\"start_time\":1788138000000000,\"end_time\":1788141600000000,\"vwap\":{\"participation_rate\":\"0.25\"}}},\"extension_version\":1}",
"api_key": "optional-per-call-api-key"
}
}
}
Response: JSON text matching the corresponding REST endpoint / Python SDK. On failure MCP CallToolResult.is_error=true + content carries {"error": "...", "status": "error"}.
futu_modify_algo_order¶
- Scope:
trade:real - Python SDK equivalent:
— - Route: MCP JSON-RPC
tools/callwith name ="futu_modify_algo_order" - ⚠️ Trade write: launch
futu-mcpwith--enable-trading(real env also needs--allow-real-trading)
Description:
Modify one nonterminal authoritative current algorithm order without changing its product, market, algorithm/price-mode, or server vendor. Requires fresh live/static/customer facts and --enable-algo-orders.
Request arguments:
| Field | Type | Required | Alias | Description |
|---|---|---|---|---|
c2s_json |
string | ✅ | — | Official generated C2S JSON. Field names use generated proto serde snake_case, e.g. multi_legs / combo_legs / order_type. |
api_key |
string? | — | — | Optional per-call API key plaintext. HTTP scope mode still requires a valid Bearer on every /mcp request; this field overrides that identity for the tool handler. In stdio mode: tool argument > startup key. |
⚠️ Unknown fields:
deny_unknown_fieldsis enabled — any field not listed above returns anunknown fielderror (previously silently dropped).
JSON-RPC call example:
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "futu_modify_algo_order",
"arguments": {
"c2s_json": "{\"header\":{\"trd_env\":1,\"acc_id\":900000001,\"trd_market\":2},\"initial\":{\"idempotency_key\":\"algo-modify-1\",\"order_id\":\"server-algo-order-id\",\"order_version\":1,\"new_qty\":\"200\",\"algo\":{\"algo_type\":2,\"start_time\":1788138000000000,\"end_time\":1788141600000000,\"vwap\":{\"participation_rate\":\"0.25\"}}},\"extension_version\":1}",
"api_key": "optional-per-call-api-key"
}
}
}
Response: JSON text matching the corresponding REST endpoint / Python SDK. On failure MCP CallToolResult.is_error=true + content carries {"error": "...", "status": "error"}.
futu_reverse_position¶
- Scope:
trade:real - Python SDK equivalent:
— - Route: MCP JSON-RPC
tools/callwith name ="futu_reverse_position" - ⚠️ Trade write: launch
futu-mcpwith--enable-trading(real env also needs--allow-real-trading)
Description:
Reverse one exact ordinary monthly futures position through server-atomic CMD4732. Both close/open legs are authorized atomically; success requires one fresh two-member legacy group plus exact 21056 side/qty/static proof. Requires --enable-position-actions; default OFF; live backend unverified.
Request arguments:
| Field | Type | Required | Alias | Description |
|---|---|---|---|---|
c2s_json |
string | ✅ | — | Official generated C2S JSON. Field names use generated proto serde snake_case, e.g. multi_legs / combo_legs / order_type. |
api_key |
string? | — | — | Optional per-call API key plaintext. HTTP scope mode still requires a valid Bearer on every /mcp request; this field overrides that identity for the tool handler. In stdio mode: tool argument > startup key. |
⚠️ Unknown fields:
deny_unknown_fieldsis enabled — any field not listed above returns anunknown fielderror (previously silently dropped).
JSON-RPC call example:
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "futu_reverse_position",
"arguments": {
"c2s_json": "{\"header\":{\"trd_env\":1,\"acc_id\":900000001,\"trd_market\":5},\"initial\":{\"idempotency_key\":\"reverse-example-1\",\"position_id\":9001,\"price_type\":1},\"extension_version\":1}",
"api_key": "optional-per-call-api-key"
}
}
}
Response: JSON text matching the corresponding REST endpoint / Python SDK. On failure MCP CallToolResult.is_error=true + content carries {"error": "...", "status": "error"}.
futu_roll_position¶
- Scope:
trade:real - Python SDK equivalent:
— - Route: MCP JSON-RPC
tools/callwith name ="futu_roll_position" - ⚠️ Trade write: launch
futu-mcpwith--enable-trading(real env also needs--allow-real-trading)
Description:
Roll one exact ordinary monthly futures position to a different contract with the same linkage identity through CMD4733. Source-close and target-open symbols/sides are authorized atomically; because CMD4733 has no target price, value-limited API keys fail closed. Success requires a fresh exact two-member group. Requires --enable-position-actions.
Request arguments:
| Field | Type | Required | Alias | Description |
|---|---|---|---|---|
c2s_json |
string | ✅ | — | Official generated C2S JSON. Field names use generated proto serde snake_case, e.g. multi_legs / combo_legs / order_type. |
api_key |
string? | — | — | Optional per-call API key plaintext. HTTP scope mode still requires a valid Bearer on every /mcp request; this field overrides that identity for the tool handler. In stdio mode: tool argument > startup key. |
⚠️ Unknown fields:
deny_unknown_fieldsis enabled — any field not listed above returns anunknown fielderror (previously silently dropped).
JSON-RPC call example:
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "futu_roll_position",
"arguments": {
"c2s_json": "{\"header\":{\"trd_env\":1,\"acc_id\":900000001,\"trd_market\":5},\"initial\":{\"idempotency_key\":\"roll-example-1\",\"position_id\":9001,\"target_code\":\"HSI2610\",\"target_sec_market\":1},\"extension_version\":1}",
"api_key": "optional-per-call-api-key"
}
}
}
Response: JSON text matching the corresponding REST endpoint / Python SDK. On failure MCP CallToolResult.is_error=true + content carries {"error": "...", "status": "error"}.
futu_clear_futures_positions¶
- Scope:
trade:real - Python SDK equivalent:
— - Route: MCP JSON-RPC
tools/callwith name ="futu_clear_futures_positions" - ⚠️ Trade write: launch
futu-mcpwith--enable-trading(real env also needs--allow-real-trading)
Description:
Clear explicit non-calendar-spread futures contracts, including supported futures options, through one CMD4734 and exact req_id operation-result reconciliation. Account-wide clear additionally requires all_positions=true and --allow-all-position-clear.
Request arguments:
| Field | Type | Required | Alias | Description |
|---|---|---|---|---|
c2s_json |
string | ✅ | — | Official generated C2S JSON. Field names use generated proto serde snake_case, e.g. multi_legs / combo_legs / order_type. |
api_key |
string? | — | — | Optional per-call API key plaintext. HTTP scope mode still requires a valid Bearer on every /mcp request; this field overrides that identity for the tool handler. In stdio mode: tool argument > startup key. |
⚠️ Unknown fields:
deny_unknown_fieldsis enabled — any field not listed above returns anunknown fielderror (previously silently dropped).
JSON-RPC call example:
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "futu_clear_futures_positions",
"arguments": {
"c2s_json": "{\"header\":{\"trd_env\":1,\"acc_id\":900000001,\"trd_market\":5},\"idempotency_key\":\"clear-example-1\",\"position_id_list\":[9001],\"price_type\":1,\"all_positions\":false,\"extension_version\":1}",
"api_key": "optional-per-call-api-key"
}
}
}
Response: JSON text matching the corresponding REST endpoint / Python SDK. On failure MCP CallToolResult.is_error=true + content carries {"error": "...", "status": "error"}.
futu_batch_close_positions¶
- Scope:
trade:real - Python SDK equivalent:
— - Route: MCP JSON-RPC
tools/callwith name ="futu_batch_close_positions" - ⚠️ Trade write: launch
futu-mcpwith--enable-trading(real env also needs--allow-real-trading)
Description:
Close an explicit deduplicated non-portfolio security-position list through one CMD4737 with Desktop-derived side/order/session fields and exact req_id result reconciliation. FUTU_JP and unsupported markets fail closed; KRX uses guarded local market contracts 18/121/111. Requires --enable-position-actions.
Request arguments:
| Field | Type | Required | Alias | Description |
|---|---|---|---|---|
c2s_json |
string | ✅ | — | Official generated C2S JSON. Field names use generated proto serde snake_case, e.g. multi_legs / combo_legs / order_type. |
api_key |
string? | — | — | Optional per-call API key plaintext. HTTP scope mode still requires a valid Bearer on every /mcp request; this field overrides that identity for the tool handler. In stdio mode: tool argument > startup key. |
⚠️ Unknown fields:
deny_unknown_fieldsis enabled — any field not listed above returns anunknown fielderror (previously silently dropped).
JSON-RPC call example:
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "futu_batch_close_positions",
"arguments": {
"c2s_json": "{\"header\":{\"trd_env\":1,\"acc_id\":900000001,\"trd_market\":2},\"idempotency_key\":\"batch-close-example-1\",\"mode\":1,\"target_list\":[{\"position_id\":9002,\"qty\":\"10\"}],\"extension_version\":1}",
"api_key": "optional-per-call-api-key"
}
}
}
Response: JSON text matching the corresponding REST endpoint / Python SDK. On failure MCP CallToolResult.is_error=true + content carries {"error": "...", "status": "error"}.