1use 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#[async_trait]
17pub trait BrokerClient: Send + Sync {
18 async fn get_account(&self) -> Result<Account>;
20
21 async fn get_positions(&self) -> Result<Vec<Position>>;
23
24 async fn place_order(&self, order: OrderRequest) -> Result<OrderResponse>;
26
27 async fn cancel_order(&self, order_id: &str) -> Result<()>;
29
30 async fn get_order(&self, order_id: &str) -> Result<OrderResponse>;
32
33 async fn list_orders(&self, filter: OrderFilter) -> Result<Vec<OrderResponse>>;
35
36 async fn health_check(&self) -> Result<HealthStatus>;
38}
39
40#[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#[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#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
78#[serde(rename_all = "lowercase")]
79pub enum PositionSide {
80 Long,
81 Short,
82}
83
84#[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#[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#[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
160pub type ExecutionError = BrokerError;
162
163pub type Result<T> = std::result::Result<T, BrokerError>;