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