tesser_broker/
lib.rs

1//! Exchange-agnostic traits used by the rest of the framework.
2
3use std::any::Any;
4
5use async_trait::async_trait;
6use serde::{de::DeserializeOwned, Deserialize, Serialize};
7use tesser_core::{
8    AccountBalance, Candle, Instrument, Order, OrderBook, OrderId, OrderRequest,
9    OrderUpdateRequest, Position, Signal, Symbol, Tick,
10};
11use thiserror::Error;
12
13pub mod limiter;
14
15pub use governor::Quota;
16pub use limiter::{RateLimiter, RateLimiterError};
17
18/// Convenience alias for broker results.
19pub type BrokerResult<T> = Result<T, BrokerError>;
20
21/// Common error type returned by broker implementations.
22#[derive(Debug, Error)]
23pub enum BrokerError {
24    /// Represents transport-level failures (network, timeouts, etc.).
25    #[error("transport error: {0}")]
26    Transport(String),
27    /// Returned when authentication fails or credentials are missing.
28    #[error("authentication failed: {0}")]
29    Authentication(String),
30    /// Returned when the request parameters are invalid for the target exchange.
31    #[error("invalid request: {0}")]
32    InvalidRequest(String),
33    /// Wraps serialization or parsing errors.
34    #[error("serialization error: {0}")]
35    Serialization(String),
36    /// Exchange responded with a business error (e.g., insufficient margin).
37    #[error("exchange error: {0}")]
38    Exchange(String),
39    /// A catch-all branch for other issues.
40    #[error("unexpected error: {0}")]
41    Other(String),
42}
43
44impl BrokerError {
45    /// Helper used by connectors when mapping any error type into a broker error.
46    pub fn from_display(err: impl std::fmt::Display, kind: BrokerErrorKind) -> Self {
47        match kind {
48            BrokerErrorKind::Transport => Self::Transport(err.to_string()),
49            BrokerErrorKind::Authentication => Self::Authentication(err.to_string()),
50            BrokerErrorKind::InvalidRequest => Self::InvalidRequest(err.to_string()),
51            BrokerErrorKind::Serialization => Self::Serialization(err.to_string()),
52            BrokerErrorKind::Exchange => Self::Exchange(err.to_string()),
53            BrokerErrorKind::Other => Self::Other(err.to_string()),
54        }
55    }
56}
57
58/// Enumerates the broad families of broker errors.
59#[derive(Debug, Clone, Copy)]
60pub enum BrokerErrorKind {
61    Transport,
62    Authentication,
63    InvalidRequest,
64    Serialization,
65    Exchange,
66    Other,
67}
68
69/// Represents metadata describing the capabilities of a connector.
70#[derive(Clone, Debug, Serialize, Deserialize)]
71pub struct BrokerInfo {
72    pub name: String,
73    pub markets: Vec<String>,
74    pub supports_testnet: bool,
75}
76
77/// Trait describing data subscriptions (live WebSocket or replayed feeds).
78#[async_trait]
79pub trait MarketStream: Send + Sync {
80    /// Exchange specific subscription descriptor.
81    type Subscription: Send + Sync + Serialize;
82
83    /// Human-friendly name of the connector used for logging purposes.
84    fn name(&self) -> &str;
85
86    /// Returns optional metadata describing the connector.
87    fn info(&self) -> Option<&BrokerInfo> {
88        None
89    }
90
91    /// Subscribe to a new stream (e.g., order book or trades).
92    async fn subscribe(&mut self, subscription: Self::Subscription) -> BrokerResult<()>;
93
94    /// Fetch the next tick in FIFO order.
95    async fn next_tick(&mut self) -> BrokerResult<Option<Tick>>;
96
97    /// Fetch the next candle when available.
98    async fn next_candle(&mut self) -> BrokerResult<Option<Candle>>;
99
100    /// Fetch the next order book snapshot.
101    async fn next_order_book(&mut self) -> BrokerResult<Option<OrderBook>>;
102}
103
104/// Trait describing the execution interface (REST or WebSocket).
105#[async_trait]
106pub trait ExecutionClient: Send + Sync {
107    /// Return metadata about the connector for telemetry.
108    fn info(&self) -> BrokerInfo;
109
110    /// Place a new order on the exchange.
111    async fn place_order(&self, request: OrderRequest) -> BrokerResult<Order>;
112
113    /// Cancel an existing order by identifier.
114    async fn cancel_order(&self, order_id: OrderId, symbol: Symbol) -> BrokerResult<()>;
115
116    /// Amend an existing order in-place when the exchange supports it.
117    async fn amend_order(&self, request: OrderUpdateRequest) -> BrokerResult<Order>;
118
119    /// Get all open orders for a symbol.
120    async fn list_open_orders(&self, symbol: Symbol) -> BrokerResult<Vec<Order>>;
121
122    /// Retrieve the latest known account balances.
123    async fn account_balances(&self) -> BrokerResult<Vec<AccountBalance>>;
124
125    /// Retrieve the current open positions.
126    async fn positions(&self) -> BrokerResult<Vec<Position>>;
127
128    /// Retrieve instrument metadata for the provided market category.
129    async fn list_instruments(&self, category: &str) -> BrokerResult<Vec<Instrument>>;
130
131    /// Helper for downcasting to a concrete type.
132    fn as_any(&self) -> &dyn Any;
133}
134
135/// Strategy and execution share this event channel API during live trading and backtests.
136#[async_trait]
137pub trait EventPublisher: Send + Sync {
138    /// Publish an event of arbitrary payload to downstream consumers (e.g., CLI UI).
139    async fn publish<T>(&self, topic: &str, payload: &T) -> BrokerResult<()>
140    where
141        T: Serialize + Send + Sync;
142}
143
144/// Provides access to historical market data snapshots.
145#[async_trait]
146pub trait HistoricalData {
147    /// Fetch a chunk of historical candles.
148    async fn candles(
149        &self,
150        symbol: &str,
151        interval: tesser_core::Interval,
152        limit: usize,
153    ) -> BrokerResult<Vec<Candle>>;
154
155    /// Fetch raw ticks, when supported by the exchange.
156    async fn ticks(&self, symbol: &str, limit: usize) -> BrokerResult<Vec<Tick>>;
157}
158
159/// Allows connectors to emit framework-native signals (e.g., risk alerts).
160#[async_trait]
161pub trait SignalBus: Send + Sync {
162    /// Send a signal downstream.
163    async fn dispatch(&self, signal: Signal) -> BrokerResult<()>;
164}
165
166/// Helper trait used by connectors to (de)serialize exchange payloads.
167pub trait PayloadExt: Sized {
168    /// Deserialize JSON bytes into a strongly typed payload.
169    fn from_json_bytes(bytes: &[u8]) -> BrokerResult<Self>
170    where
171        Self: DeserializeOwned,
172    {
173        serde_json::from_slice(bytes).map_err(|err| {
174            BrokerError::Serialization(format!("failed to deserialize payload: {err}"))
175        })
176    }
177}
178
179impl<T> PayloadExt for T where T: DeserializeOwned {}
180
181mod connector;
182pub use connector::{
183    get_connector_factory, register_connector_factory, registered_connectors, ConnectorFactory,
184    ConnectorStream, ConnectorStreamConfig,
185};
186pub mod router;
187pub use router::RouterExecutionClient;