pub mod binance;
pub mod gdax;
pub mod hitbtc;
pub mod errors;
pub mod timestamp;
pub mod symbol;
pub mod order_book;
mod query_string;
mod wss;
use futures::prelude::*;
use std::collections::HashMap;
use serde_derive::{Serialize, Deserialize};
use bitflags::bitflags;
use crate::Side;
use crate::tick::{TickUnit, Tickable};
use crate::order_book::LimitUpdate;
use self::timestamp::Timestamped;
use self::symbol::{Symbol, WithSymbol};
pub use self::gdax as coinbase_pro;
#[derive(Clone, PartialEq, Eq, Hash, Debug, Serialize, Deserialize)]
pub struct Params {
pub streaming_endpoint: String,
pub rest_endpoint: String,
}
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Serialize, Deserialize)]
pub enum TimeInForce {
GoodTilCanceled,
ImmediateOrCancel,
FillOrKilll,
}
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Serialize, Deserialize)]
pub enum OrderType {
Limit,
LimitMaker,
}
#[derive(Clone, PartialEq, Eq, Hash, Debug, Serialize, Deserialize)]
pub struct Order {
price: Tickable,
size: Tickable,
side: Side,
#[serde(rename = "type")]
type_: OrderType,
time_in_force: TimeInForce,
time_window: u64,
order_id: Option<String>,
}
impl Order {
pub fn new<T, U>(price: T, size: U, side: Side) -> Self
where T: Into<Tickable>, U: Into<Tickable>
{
Order {
price: price.into(),
size: size.into(),
side,
type_: OrderType::Limit,
time_in_force: TimeInForce::GoodTilCanceled,
time_window: 5000,
order_id: None,
}
}
pub fn with_order_type(mut self, order_type: OrderType) -> Self {
self.type_ = order_type;
self
}
pub fn with_time_in_force(mut self, time_in_force: TimeInForce) -> Self {
self.time_in_force = time_in_force;
self
}
pub fn with_time_window(mut self, time_window: u64) -> Self {
self.time_window = time_window;
self
}
pub fn with_order_id<C: ApiClient>(mut self, hint: &str) -> Self {
self.order_id = Some(C::new_order_id(hint));
self
}
pub fn order_id(&self) -> Option<&str> {
self.order_id.as_ref().map(|s| s.as_ref())
}
pub fn price(&self) -> &Tickable {
&self.price
}
pub fn size(&self) -> &Tickable {
&self.size
}
pub fn order_type(&self) -> OrderType {
self.type_
}
pub fn time_in_force(&self) -> TimeInForce {
self.time_in_force
}
pub fn time_window(&self) -> u64 {
self.time_window
}
}
#[derive(Clone, PartialEq, Eq, Hash, Debug, Serialize, Deserialize)]
pub struct Cancel {
order_id: String,
time_window: u64,
}
impl Cancel {
pub fn new(order_id: String) -> Self {
Cancel {
order_id,
time_window: 5000,
}
}
pub fn with_time_window(mut self, time_window: u64) -> Self {
self.time_window = time_window;
self
}
pub fn order_id(&self) -> &str {
&self.order_id
}
pub fn time_window(&self) -> u64 {
self.time_window
}
}
#[derive(Clone, PartialEq, Eq, Hash, Debug, Serialize, Deserialize)]
pub struct OrderAck {
pub order_id: String,
}
#[derive(Clone, PartialEq, Eq, Hash, Debug, Serialize, Deserialize)]
pub struct CancelAck;
#[derive(Clone, PartialEq, Eq, Hash, Debug, Serialize, Deserialize)]
pub struct OrderUpdate {
pub order_id: String,
pub consumed_size: TickUnit,
pub remaining_size: TickUnit,
pub consumed_price: TickUnit,
pub commission: TickUnit,
}
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Serialize, Deserialize)]
pub struct Trade {
pub price: TickUnit,
pub size: TickUnit,
pub maker_side: Side,
}
#[derive(Clone, PartialEq, Eq, Hash, Debug, Serialize, Deserialize)]
pub struct OrderExpiration {
pub order_id: String,
}
#[derive(Clone, PartialEq, Eq, Hash, Debug, Serialize, Deserialize)]
pub struct OrderConfirmation {
pub order_id: String,
pub price: TickUnit,
pub size: TickUnit,
pub side: Side,
}
#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
pub enum Notification {
Trade(Timestamped<Trade>),
LimitUpdates(Vec<Timestamped<LimitUpdate>>),
OrderConfirmation(Timestamped<OrderConfirmation>),
OrderUpdate(Timestamped<OrderUpdate>),
OrderExpiration(Timestamped<OrderExpiration>),
}
bitflags! {
pub struct NotificationFlags: u8 {
const ORDER_BOOK = 0b0001;
const TRADES = 0b0010;
const ORDERS = 0b0100;
const ALL = Self::ORDER_BOOK.bits | Self::TRADES.bits | Self::ORDERS.bits;
}
}
pub trait GenerateOrderId {
fn new_order_id(hint: &str) -> String;
}
#[derive(Clone, PartialEq, Eq, Hash, Debug, Deserialize)]
pub struct Balance {
pub free: String,
pub locked: String,
}
pub type Balances = HashMap<String, Balance>;
pub trait ApiClient: GenerateOrderId {
type Stream: Stream<Item = Notification, Error = ()> + Send + 'static;
fn find_symbol(&self, symbol: &str) -> Option<Symbol>;
fn stream_with_flags(&self, symbol: Symbol, flags: NotificationFlags) -> Self::Stream;
fn stream(&self, symbol: Symbol) -> Self::Stream {
self.stream_with_flags(symbol, NotificationFlags::ALL)
}
fn order(&self, order: WithSymbol<&Order>)
-> Box<dyn Future<Item = Timestamped<OrderAck>, Error = errors::OrderError> + Send + 'static>;
fn cancel(&self, cancel: WithSymbol<&Cancel>)
-> Box<dyn Future<Item = Timestamped<CancelAck>, Error = errors::CancelError> + Send + 'static>;
fn ping(&self)
-> Box<dyn Future<Item = Timestamped<()>, Error = errors::Error> + Send + 'static>;
fn balances(&self)
-> Box<dyn Future<Item = Balances, Error = errors::Error> + Send + 'static>;
}