#![warn(
missing_debug_implementations,
missing_copy_implementations,
rust_2018_idioms,
// missing_docs
)]
#![allow(clippy::type_complexity)]
use crate::{
error::ExecutionError,
model::{
balance::SymbolBalance,
order::{Cancelled, Open, Order, OrderId, RequestCancel, RequestOpen},
AccountEvent,
},
};
use async_trait::async_trait;
use barter_integration::model::Exchange;
use serde::{Deserialize, Serialize};
use std::fmt::{Display, Formatter};
use tokio::sync::mpsc;
pub mod error;
pub mod model;
pub mod execution;
pub mod simulated;
#[async_trait]
pub trait ExecutionClient {
const CLIENT: ExecutionId;
type Config;
async fn init(config: Self::Config, event_tx: mpsc::UnboundedSender<AccountEvent>) -> Self;
async fn fetch_orders_open(&self) -> Result<Vec<Order<Open>>, ExecutionError>;
async fn fetch_balances(&self) -> Result<Vec<SymbolBalance>, ExecutionError>;
async fn open_orders(
&self,
open_requests: Vec<Order<RequestOpen>>,
) -> Vec<Result<Order<Open>, ExecutionError>>;
async fn cancel_orders(
&self,
cancel_requests: Vec<Order<RequestCancel>>,
) -> Vec<Result<Order<Cancelled>, ExecutionError>>;
async fn cancel_orders_all(&self) -> Result<Vec<Order<Cancelled>>, ExecutionError>;
}
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Deserialize, Serialize)]
#[serde(rename = "execution", rename_all = "snake_case")]
pub enum ExecutionId {
Simulated,
Ftx,
}
impl From<ExecutionId> for Exchange {
fn from(execution_id: ExecutionId) -> Self {
Exchange::from(execution_id.as_str())
}
}
impl Display for ExecutionId {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.as_str())
}
}
impl ExecutionId {
pub fn as_str(&self) -> &'static str {
match self {
ExecutionId::Simulated => "simulated",
ExecutionId::Ftx => "ftx",
}
}
}
pub mod test_util {
use crate::{
model::{
trade::{SymbolFees, Trade, TradeId},
ClientOrderId,
},
simulated::exchange::account::order::Orders,
Open, Order, OrderId,
};
use barter_data::model::PublicTrade;
use barter_integration::model::{Exchange, Instrument, InstrumentKind, Side};
pub fn client_orders(
trade_number: u64,
bids: Vec<Order<Open>>,
asks: Vec<Order<Open>>,
) -> Orders {
Orders {
trade_counter: trade_number,
bids,
asks,
}
}
pub fn order_open(
cid: ClientOrderId,
side: Side,
price: f64,
quantity: f64,
filled: f64,
) -> Order<Open> {
Order {
exchange: Exchange::from("exchange"),
instrument: Instrument::from(("base", "quote", InstrumentKind::FuturePerpetual)),
cid,
side,
state: Open {
id: OrderId::from("order_id"),
price,
quantity,
filled_quantity: filled,
},
}
}
pub fn public_trade(side: Side, price: f64, quantity: f64) -> PublicTrade {
PublicTrade {
id: "trade_id".to_string(),
price,
quantity,
side,
}
}
pub fn trade(id: TradeId, side: Side, price: f64, quantity: f64, fees: SymbolFees) -> Trade {
Trade {
id,
order_id: OrderId::from("order_id"),
instrument: Instrument::from(("base", "quote", InstrumentKind::FuturePerpetual)),
side,
price,
quantity,
fees,
}
}
}