Placing orders#
Sides and results#
pub enum OrderSide { Buy, Sell }
OrderSide::from("short") and from("sell") give Sell; anything else gives Buy.
Order calls return OrderResult:
| Field | Type | Meaning |
|---|---|---|
success |
bool |
Whether the exchange accepted the order. |
order_id |
Option<String> |
Exchange order ID. result.order_id() returns "" if absent. |
symbol, side, order_type |
Echoed back. | |
quantity |
Option<f64> |
Executed quantity. |
entry_price |
Option<f64> |
Entry or average price. |
position_size, position_usdt |
Option<f64> |
Position after the order, in units and in USDT. |
error |
Option<String> |
Message when success is false. |
raw_response |
Option<HashMap<String, Value>> |
The exchange's raw response, if the adapter keeps it. |
Always check success. A rejected order is a normal Ok result with success == false. See Errors.
Market order#
let r = trader.place_market_order("BTCUSDT", OrderSide::Buy, 0.001).await?;
quantity is in base-asset units. To size by USDT, divide by the price yourself, or use fast entry or the test_market_order helper (Dry-run checks).
Quantity precision and minimum size are exchange rules. An order below the minimum, or with too many decimals, is rejected by the exchange. SymbolInfo in the models carries tick_size, step_size, min_quantity and min_notional for this, and tradersdk-trading has helpers for rounding. See Models and Utilities.
Limit order#
let r = trader
.place_limit_order("BTCUSDT", OrderSide::Sell, 0.001, 70_000.0, /* reduce_only */ false)
.await?;
With reduce_only = true the order can only reduce an existing position. Whether this is honored depends on the exchange and market type. Check the create_reduce_only_order capability.
Status#
let info = trader.get_order_status("BTCUSDT", &order_id).await?;
println!("{:?} filled {}/{} ({:.0}%)", info.status, info.filled_quantity, info.quantity, info.fill_percentage());
OrderInfo has order_id, client_order_id, symbol, status, side, order_type, price, quantity, filled_quantity, remaining_quantity, avg_price, timestamp, time_in_force and reduce_only.
OrderStatus is one of Pending, New, PartiallyFilled, Filled, Cancelled, Rejected, Expired. Two helpers: is_final() is true for Filled, Cancelled, Rejected, Expired; is_active() is true for Pending, New, PartiallyFilled.
Polling is fine for occasional checks. For fills as they happen, use Order updates.
Cancel#
let cancelled: bool = trader.cancel_order("BTCUSDT", &order_id).await?;
Close a position#
let r = trader.close_position("BTCUSDT").await?;
Meaningful on perpetual traders. It places the closing order and returns its OrderResult.
Order types and time in force#
The models define OrderType (Market, Limit, StopMarket, StopLimit, TakeProfitMarket, TakeProfitLimit, TrailingStop) and TimeInForce (GTC, IOC, FOK, PostOnly, GTX). They appear in results and events. The trait's placement methods today cover market and limit orders; stop and trailing orders are listed as capabilities but are not part of the trait.
Before you send money#
- Start on testnet where the exchange has one.
- Use
test_market_orderto check sizing. - Do not blindly retry a timed-out order. Query its status first.