nt_execution/
broker.rs

1// Broker adapter trait and error types
2//
3// This module defines the abstract broker interface that all
4// broker implementations must implement.
5
6use crate::{OrderRequest, OrderResponse, OrderStatus, OrderUpdate};
7use async_trait::async_trait;
8use chrono::{DateTime, Utc};
9use nt_core::types::Symbol;
10use rust_decimal::Decimal;
11use serde::{Deserialize, Serialize};
12use std::collections::HashMap;
13use thiserror::Error;
14
15/// Broker client trait
16#[async_trait]
17pub trait BrokerClient: Send + Sync {
18    /// Get account information
19    async fn get_account(&self) -> Result<Account>;
20
21    /// Get current positions
22    async fn get_positions(&self) -> Result<Vec<Position>>;
23
24    /// Place an order
25    async fn place_order(&self, order: OrderRequest) -> Result<OrderResponse>;
26
27    /// Cancel an order
28    async fn cancel_order(&self, order_id: &str) -> Result<()>;
29
30    /// Get order status
31    async fn get_order(&self, order_id: &str) -> Result<OrderResponse>;
32
33    /// List all orders with optional filter
34    async fn list_orders(&self, filter: OrderFilter) -> Result<Vec<OrderResponse>>;
35
36    /// Health check
37    async fn health_check(&self) -> Result<HealthStatus>;
38}
39
40/// Account information
41#[derive(Debug, Clone, Serialize, Deserialize)]
42pub struct Account {
43    pub account_id: String,
44    pub cash: Decimal,
45    pub portfolio_value: Decimal,
46    pub buying_power: Decimal,
47    pub equity: Decimal,
48    pub last_equity: Decimal,
49    pub multiplier: String,
50    pub currency: String,
51    pub shorting_enabled: bool,
52    pub long_market_value: Decimal,
53    pub short_market_value: Decimal,
54    pub initial_margin: Decimal,
55    pub maintenance_margin: Decimal,
56    pub day_trading_buying_power: Decimal,
57    pub daytrade_count: i32,
58}
59
60/// Position information
61#[derive(Debug, Clone, Serialize, Deserialize)]
62pub struct Position {
63    pub symbol: Symbol,
64    pub qty: i64,
65    pub side: PositionSide,
66    pub avg_entry_price: Decimal,
67    pub market_value: Decimal,
68    pub cost_basis: Decimal,
69    pub unrealized_pl: Decimal,
70    pub unrealized_plpc: Decimal,
71    pub current_price: Decimal,
72    pub lastday_price: Decimal,
73    pub change_today: Decimal,
74}
75
76/// Position side
77#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
78#[serde(rename_all = "lowercase")]
79pub enum PositionSide {
80    Long,
81    Short,
82}
83
84/// Order filter for querying orders
85#[derive(Debug, Clone, Default)]
86pub struct OrderFilter {
87    pub status: Option<OrderStatus>,
88    pub limit: Option<usize>,
89    pub after: Option<DateTime<Utc>>,
90    pub until: Option<DateTime<Utc>>,
91    pub direction: Option<String>,
92    pub nested: Option<bool>,
93    pub symbols: Option<Vec<String>>,
94}
95
96/// Health status
97#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
98#[serde(rename_all = "lowercase")]
99pub enum HealthStatus {
100    Healthy,
101    Degraded,
102    Unhealthy,
103}
104
105/// Broker error types
106#[derive(Debug, Error)]
107pub enum BrokerError {
108    #[error("Insufficient funds")]
109    InsufficientFunds,
110
111    #[error("Invalid order: {0}")]
112    InvalidOrder(String),
113
114    #[error("Order not found: {0}")]
115    OrderNotFound(String),
116
117    #[error("Market closed")]
118    MarketClosed,
119
120    #[error("Rate limit exceeded")]
121    RateLimit,
122
123    #[error("Authentication failed: {0}")]
124    Auth(String),
125
126    #[error("Network error: {0}")]
127    Network(String),
128
129    #[error("Parse error: {0}")]
130    Parse(String),
131
132    #[error("Broker unavailable: {0}")]
133    Unavailable(String),
134
135    #[error("Order error: {0}")]
136    Order(String),
137
138    #[error("Operation timeout")]
139    Timeout,
140
141    #[error("Circuit breaker open")]
142    CircuitBreakerOpen,
143
144    #[error(transparent)]
145    Other(#[from] anyhow::Error),
146}
147
148impl From<reqwest::Error> for BrokerError {
149    fn from(err: reqwest::Error) -> Self {
150        BrokerError::Network(err.to_string())
151    }
152}
153
154impl From<serde_json::Error> for BrokerError {
155    fn from(err: serde_json::Error) -> Self {
156        BrokerError::Parse(err.to_string())
157    }
158}
159
160/// Execution error type (alias to BrokerError for compatibility)
161pub type ExecutionError = BrokerError;
162
163/// Result type for execution operations
164pub type Result<T> = std::result::Result<T, BrokerError>;