trade -- Trading Action Tool
The unified trading action tool. Dispatches to one of 6 actions via the
action parameter. Always visible at root post-onboarding -- no hub
expansion needed.
All trade actions use a two-phase confirmation protocol: propose first, then confirm. Proposals expire after 60 seconds.
Actions
propose_entry
Create an entry proposal for an Iron Condor position.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
action |
string | Yes | -- | "propose_entry" |
ticker |
string | Yes | -- | Underlying symbol |
candidate |
dict | Yes | -- | Candidate from find_iron_condors (must include strikes and credit) |
qty |
int | Yes | -- | Number of contracts (>= 1) |
saved_strategy_id |
string | No | null | UUID from save_strategy for audit trail |
The candidate dict must include: expiry, short_put, long_put,
short_call, long_call, net_credit. Pass a complete candidate object
from find_iron_condors results.
When saved_strategy_id is provided, the proposal is linked to the optimizer
run that produced the strategy, creating a full audit trail from optimization
through execution.
Response: ProposalResponse with a proposal_id and 60-second TTL.
{
"id": "p1q2r3s4-...",
"type": "entry",
"ticker": "SPY",
"status": "pending",
"payload": {
"candidate": { "..." : "..." },
"qty": 2,
"saved_strategy_id": "e5f6g7h8-..."
},
"expires_at": "2026-05-12T14:31:00Z",
"created_at": "2026-05-12T14:30:00Z"
}
propose_roll
Create a roll proposal for an existing Iron Condor position.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
action |
string | Yes | -- | "propose_roll" |
position_id |
string | Yes | -- | UUID of the IC position to roll |
intent |
string | Yes | -- | "full_roll" (both spreads) or "spread_roll" (one side) |
candidate_id |
string | No | null | Specific roll candidate ID |
roll_side |
string | No | null | "put" or "call" (for spread_roll) |
new_short_strike |
float | No | null | Override short strike for the new spread |
new_long_strike |
float | No | null | Override long strike for the new spread |
new_expiry |
string | No | null | Override expiration date |
liquidation_order_type |
string | No | "market" | Order type for closing the old spread |
liquidation_net_debit |
float | No | null | Limit price for closing (if limit order) |
open_order_type |
string | No | "market" | Order type for opening the new spread |
open_net_credit |
float | No | null | Limit price for opening (if limit order) |
Response: ProposalResponse with a proposal_id and 60-second TTL.
propose_exit
Create an exit proposal to close an existing position.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
action |
string | Yes | -- | "propose_exit" |
position_id |
string | Yes | -- | UUID of the position to close |
reason |
string | No | "" | Why the exit is being requested |
Response: ProposalResponse with a proposal_id and 60-second TTL.
confirm
Submit a pending proposal to the broker for execution.
| Parameter | Type | Required | Description |
|---|---|---|---|
action |
string | Yes | "confirm" |
proposal_id |
string | Yes | UUID from a propose action |
Must be called within 60 seconds of the proposal creation. After confirmation, the order is submitted to the active broker account.
Response: PendingOrderSchema with order details.
Errors:
PROPOSAL_NOT_FOUND-- invalid or non-existent proposal IDPROPOSAL_EXPIRED-- TTL exceeded (create a new proposal)PROPOSAL_ALREADY_CONSUMED-- already confirmed
cancel
Cancel a pending proposal before it expires or is confirmed.
| Parameter | Type | Required | Description |
|---|---|---|---|
action |
string | Yes | "cancel" |
proposal_id |
string | Yes | UUID of the proposal to cancel |
Response:
{
"ok": true,
"proposal_id": "p1q2r3s4-...",
"status": "cancelled"
}
list
List proposals for the current user.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
action |
string | Yes | -- | "list" |
status |
string | No | null | Filter: "pending", "confirmed", "expired", "cancelled" |
limit |
int | No | 20 | Max results (1-50) |
Response: Array of proposal summaries, newest first.
[
{
"id": "p1q2r3s4-...",
"type": "entry",
"ticker": "SPY",
"status": "pending",
"qty": 2,
"net_credit": 1.42,
"expires_at": "2026-05-12T14:31:00Z",
"created_at": "2026-05-12T14:30:00Z"
}
]
Proposal Lifecycle
propose_entry / propose_roll / propose_exit
|
v
PENDING ---- 60 seconds ----> EXPIRED (automatic)
|
+---> confirm ----> CONFIRMED (order submitted to broker)
|
+---> cancel ----> CANCELLED (no order placed)
- Proposals are immutable once created. The 60-second TTL ensures prices do not drift too far between proposal and execution.
- A background worker (
proposal_expirer) marks uncollected proposals as expired. - Each proposal stores the full trade details (candidate, qty, strategy reference) so the agent can review what was proposed.
Audit Trail via saved_strategy_id
When propose_entry includes a saved_strategy_id, the full provenance
chain is recorded:
Optimizer run (run_id)
-> Saved strategy (saved_strategy_id, rank)
-> Chain scan (find_iron_condors with saved_strategy_id)
-> Entry proposal (proposal_id, saved_strategy_id)
-> Confirmed order (order_id)
-> Position (position_id)
This enables regulatory audit, performance attribution, and "what strategy produced this trade?" queries.
Cross-references
- find-iron-condors.md -- source of candidates for
propose_entry - positions.md -- querying positions after order execution
- create-strategy.md -- the
saved_strategy_idorigin - ../concepts/error-codes.md -- proposal and trading errors
- ../guides/full-trading-workflow.md -- complete workflow