Trading
The Rust SDK provides an async TradeClient built on Tokio. Every method returns a typed Result<T, TigerError> (e.g. Vec<Order>, Vec<Position>, Option<PlaceOrderResult>). v0.4.0 migrates 8 query methods to Request struct signatures (breaking) and adds 13 new methods.
Quick Start
use tigeropen::client::http_client::HttpClient;
use tigeropen::config::ClientConfig;
use tigeropen::model::order::limit_order;
use tigeropen::model::trade_requests::{OrdersRequest, PositionsRequest};
use tigeropen::trade::TradeClient;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let config = ClientConfig::builder().build()?;
let account = config.account.clone();
let http = HttpClient::new(config);
let tc = TradeClient::new(&http, &account);
// Query positions (v0.4.0: Request struct)
let positions = tc.get_positions(PositionsRequest::default()).await?;
println!("positions={}", positions.len());
// Build a limit order via helper
let mut order = limit_order(&account, "AAPL", "STK", "BUY", 100, 150.0);
order.market = Some("US".into());
order.currency = Some("USD".into());
// Preview before placing
if let Some(preview) = tc.preview_order(order.clone()).await? {
println!("commission={} initMargin={}", preview.commission, preview.init_margin);
}
// Place the order
if let Some(placed) = tc.place_order(order).await? {
println!("id={} orderId={}", placed.id, placed.order_id);
}
Ok(())
}OrderStatus (v0.4.0 aligned with Java)
v0.4.0 aligns OrderStatus with the Java SDK — 8 values. Numeric codes returned by the server are automatically deserialized to the corresponding string variant:
| Variant | String | Code |
|---|---|---|
OrderStatus::Invalid | "Invalid" | -2 |
OrderStatus::Initial | "Initial" | -1 |
OrderStatus::PendingCancel | "PendingCancel" | 3 |
OrderStatus::Cancelled | "Cancelled" | 4 |
OrderStatus::Submitted | "Submitted" | 5 |
OrderStatus::Filled | "Filled" | 6 |
OrderStatus::Inactive | "Inactive" | 7 |
OrderStatus::PendingSubmit | "PendingSubmit" | 8 |
Breaking: Python-derived
PendingNew/PartiallyFilledremoved (server never returns them).PendingSubmitadded.
use tigeropen::model::enums::OrderStatus;
println!("{}", OrderStatus::Filled.code()); // 6
println!("{}", OrderStatus::PendingSubmit.code()); // 8Order Model
v0.3.0 splits the order model into two types:
OrderRequest— request struct forplace_order/preview_order/modify_orderOrder— response struct returned byget_orders/get_active_orders/ etc.
Helper factories
| Helper | Order type | Extra args |
|---|---|---|
market_order | MKT | — |
limit_order | LMT | limit_price |
stop_order | STP | aux_price |
stop_limit_order | STP_LMT | limit_price, aux_price |
trail_order | TRAIL | trailing_percent |
auction_limit_order | AL | limit_price |
auction_market_order | AM | — |
Contract Query
get_contract
pub async fn get_contract(&self, symbol: &str, sec_type: &str) -> Result<Vec<Contract>, TigerError>let contracts = tc.get_contract("AAPL", "STK").await?;get_contracts
pub async fn get_contracts(&self, symbols: &[&str], sec_type: &str) -> Result<Vec<Contract>, TigerError>let contracts = tc.get_contracts(&["AAPL", "TSLA", "MSFT"], "STK").await?;get_quote_contract
pub async fn get_quote_contract(&self, symbol: &str, sec_type: &str, expiry: &str) -> Result<Vec<Contract>, TigerError>let contracts = tc.get_quote_contract("AAPL", "OPT", "20260619").await?;Order Management
place_order
pub async fn place_order(&self, order: OrderRequest) -> Result<Option<PlaceOrderResult>, TigerError>if let Some(placed) = tc.place_order(req).await? {
println!("id={} orderId={}", placed.id, placed.order_id);
}preview_order
pub async fn preview_order(&self, order: OrderRequest) -> Result<Option<PreviewResult>, TigerError>modify_order
pub async fn modify_order(&self, id: i64, order: OrderRequest) -> Result<Option<OrderIdResult>, TigerError>cancel_order
pub async fn cancel_order(&self, id: i64) -> Result<Option<OrderIdResult>, TigerError>Order Query
OrdersRequest (new in v0.4.0)
All four order-query methods share OrdersRequest. Every field is Option — account defaults to the client's configured account.
| Field | Type | Description |
|---|---|---|
| account | Option<String> | Account ID |
| sec_type | Option<String> | "STK" / "OPT" / "FUT" etc. |
| market | Option<String> | Market, e.g. "US" / "HK" |
| symbol | Option<String> | Symbol filter |
| start_date | Option<i64> | Start time (ms timestamp) |
| end_date | Option<i64> | End time (ms timestamp) |
| limit | Option<i32> | Max records |
| is_brief | Option<bool> | Return brief fields only |
| states | Option<Vec<String>> | State filter — see OrderStatus table |
| sort_by | Option<String> | "LATEST_CREATED" / "LATEST_STATUS_UPDATED" |
| page_token | Option<String> | Pagination token |
| parent_id | Option<i64> | Parent order ID (get_active_orders only) |
get_orders
async fn get_orders(&self, req: OrdersRequest) -> Result<Vec<Order>, TigerError>
v0.4.0 Breaking: changed from no-arg to
OrdersRequest.
use tigeropen::model::trade_requests::OrdersRequest;
// Simple call
let orders = tc.get_orders(OrdersRequest::default()).await?;
// Filtered: last 100 filled US stock orders
let filtered = tc.get_orders(OrdersRequest {
market: Some("US".to_string()),
sec_type: Some("STK".to_string()),
states: Some(vec!["Filled".to_string()]),
limit: Some(100),
..Default::default()
}).await?;get_order (new in v0.4.0)
async fn get_order(&self, req: GetOrderRequest) -> Result<Option<Order>, TigerError>
Query a single order by ID. Pass id (global) or order_id (account-level); at least one is required.
use tigeropen::model::trade_requests::GetOrderRequest;
let order = tc.get_order(GetOrderRequest {
id: Some(123456789),
..Default::default()
}).await?;get_active_orders
async fn get_active_orders(&self, req: OrdersRequest) -> Result<Vec<Order>, TigerError>
v0.4.0 Breaking: changed from no-arg to
OrdersRequest.
let active = tc.get_active_orders(OrdersRequest::default()).await?;get_inactive_orders
async fn get_inactive_orders(&self, req: OrdersRequest) -> Result<Vec<Order>, TigerError>
v0.4.0 Breaking: changed from no-arg to
OrdersRequest.
let inactive = tc.get_inactive_orders(OrdersRequest::default()).await?;get_filled_orders
async fn get_filled_orders(&self, req: OrdersRequest) -> Result<Vec<Order>, TigerError>
v0.4.0 Breaking: was
(start_ms: i64, end_ms: i64), nowOrdersRequestwithstart_date/end_datefields.
use std::time::{SystemTime, UNIX_EPOCH};
let now = SystemTime::now().duration_since(UNIX_EPOCH).map(|d| d.as_millis() as i64).unwrap_or(0);
let recent = tc.get_filled_orders(OrdersRequest {
start_date: Some(now - 30 * 24 * 3600 * 1000),
end_date: Some(now),
limit: Some(200),
..Default::default()
}).await?;get_order_transactions
async fn get_order_transactions(&self, req: OrderTransactionsRequest) -> Result<Vec<Transaction>, TigerError>
v0.4.0 Breaking: was
(order_id, symbol, sec_type), nowOrderTransactionsRequestwith all fields optional.
use tigeropen::model::trade_requests::OrderTransactionsRequest;
let txs = tc.get_order_transactions(OrderTransactionsRequest {
order_id: Some(12345),
symbol: Some("AAPL".to_string()),
sec_type: Some("STK".to_string()),
..Default::default()
}).await?;Positions and Assets
get_positions
async fn get_positions(&self, req: PositionsRequest) -> Result<Vec<Position>, TigerError>
v0.4.0 Breaking: changed from no-arg to
PositionsRequest.
use tigeropen::model::trade_requests::PositionsRequest;
let positions = tc.get_positions(PositionsRequest::default()).await?;
// Filter to US stocks only
let us = tc.get_positions(PositionsRequest {
market: Some("US".to_string()),
sec_type: Some("STK".to_string()),
..Default::default()
}).await?;get_assets
async fn get_assets(&self, req: AssetsRequest) -> Result<Vec<Asset>, TigerError>
v0.4.0 Breaking: changed from no-arg to
AssetsRequest.
use tigeropen::model::trade_requests::AssetsRequest;
let assets = tc.get_assets(AssetsRequest::default()).await?;get_prime_assets
async fn get_prime_assets(&self, req: AssetsRequest) -> Result<Option<PrimeAsset>, TigerError>
v0.4.0 Breaking: changed from no-arg to
AssetsRequest(shared withget_assets).
if let Some(pa) = tc.get_prime_assets(AssetsRequest::default()).await? {
println!("account={} segments={}", pa.account_id, pa.segments.len());
}Account Management (new in v0.4.0)
get_managed_accounts (new in v0.4.0)
async fn get_managed_accounts(&self, req: ManagedAccountsRequest) -> Result<Vec<ManagedAccount>, TigerError>
Query the list of managed sub-accounts under the current master account. Wire method: accounts.
use tigeropen::model::trade_requests::ManagedAccountsRequest;
let subs = tc.get_managed_accounts(ManagedAccountsRequest::default()).await?;
for s in &subs {
println!("{} type={:?} status={:?}", s.account, s.account_type, s.status);
}get_derivative_contracts (new in v0.4.0)
async fn get_derivative_contracts(&self, req: DerivativeContractsRequest) -> Result<Vec<Contract>, TigerError>
Batch query derivative contracts (options / warrants / IOPT). Wire method: quote_contract.
use tigeropen::model::trade_requests::DerivativeContractsRequest;
let cs = tc.get_derivative_contracts(DerivativeContractsRequest {
symbols: vec!["AAPL".to_string()],
sec_type: "OPT".to_string(),
expiry: Some("20260619".to_string()),
..Default::default()
}).await?;Asset Analytics (new in v0.4.0)
get_analytics_asset (new in v0.4.0)
async fn get_analytics_asset(&self, req: AnalyticsAssetRequest) -> Result<Vec<AnalyticsAsset>, TigerError>
Daily account asset analytics (holding value, cash balance, P&L, net value index). Wire method: analytics_asset.
use tigeropen::model::trade_requests::AnalyticsAssetRequest;
let rows = tc.get_analytics_asset(AnalyticsAssetRequest {
start_date: Some("2025-01-01".to_string()),
end_date: Some("2025-12-31".to_string()),
..Default::default()
}).await?;get_aggregate_assets (new in v0.4.0)
async fn get_aggregate_assets(&self, req: AggregateAssetsRequest) -> Result<Option<AggregateAssets>, TigerError>
Aggregate multi-currency assets in a single base currency view. Wire method: aggregate_assets.
use tigeropen::model::trade_requests::AggregateAssetsRequest;
if let Some(agg) = tc.get_aggregate_assets(AggregateAssetsRequest {
base_currency: Some("USD".to_string()),
..Default::default()
}).await? {
println!("netLiq={:?} currencies={}", agg.net_liquidation, agg.currency_assets.len());
}get_estimate_tradable_quantity (new in v0.4.0)
async fn get_estimate_tradable_quantity(&self, req: EstimateTradableQuantityRequest) -> Result<Option<EstimateTradableQuantity>, TigerError>
Estimate max tradable quantity based on available margin and current price. Wire method: estimate_tradable_quantity.
use tigeropen::model::trade_requests::EstimateTradableQuantityRequest;
if let Some(est) = tc.get_estimate_tradable_quantity(EstimateTradableQuantityRequest {
symbol: "AAPL".to_string(),
sec_type: "STK".to_string(),
action: "BUY".to_string(),
order_type: Some("LMT".to_string()),
limit_price: Some(150.0),
..Default::default()
}).await? {
println!("tradable={:?}", est.tradable_quantity);
}Fund Details and Transfers (new in v0.4.0)
get_fund_details (new in v0.4.0)
async fn get_fund_details(&self, req: FundDetailsRequest) -> Result<Vec<FundDetails>, TigerError>
Query fund flow records (deposits, withdrawals, fees, interest, dividends). Wire method: fund_details.
use tigeropen::model::trade_requests::FundDetailsRequest;
let rows = tc.get_fund_details(FundDetailsRequest {
currency: Some("USD".to_string()),
limit: Some(100),
..Default::default()
}).await?;get_funding_history (new in v0.4.0)
async fn get_funding_history(&self, req: FundingHistoryRequest) -> Result<Vec<FundingHistoryItem>, TigerError>
Query transfer fund history. Wire method: transfer_fund.
use tigeropen::model::trade_requests::FundingHistoryRequest;
let rows = tc.get_funding_history(FundingHistoryRequest::default()).await?;place_forex_order (new in v0.4.0)
async fn place_forex_order(&self, req: ForexOrderRequest) -> Result<Option<ForexOrderResult>, TigerError>
Submit a forex conversion order. Wire method: place_forex_order.
use tigeropen::model::trade_requests::ForexOrderRequest;
if let Some(res) = tc.place_forex_order(ForexOrderRequest {
source_currency: "USD".to_string(),
source_amount: Some(10000.0),
target_currency: "HKD".to_string(),
..Default::default()
}).await? {
println!("rate={:?} target={:?}", res.rate, res.target_amount);
}get_segment_fund_available (new in v0.4.0)
async fn get_segment_fund_available(&self, req: SegmentFundRequest) -> Result<Vec<SegmentFund>, TigerError>
Query available transfer amount between sub-account segments. Wire method: segment_fund_available.
get_segment_fund_history (new in v0.4.0)
async fn get_segment_fund_history(&self, req: SegmentFundRequest) -> Result<Vec<SegmentFundHistoryItem>, TigerError>
transfer_segment_fund (new in v0.4.0)
async fn transfer_segment_fund(&self, req: SegmentFundRequest) -> Result<Option<SegmentFund>, TigerError>
Transfer funds between sub-account segments. Wire method: transfer_segment_fund.
cancel_segment_fund (new in v0.4.0)
async fn cancel_segment_fund(&self, req: SegmentFundRequest) -> Result<Option<SegmentFund>, TigerError>
Cancel a pending segment fund transfer. Wire method: cancel_segment_fund.
Updated 14 days ago
