diff --git a/rustybot/src/models.rs b/rustybot/src/models.rs index e0423ed..c781f45 100644 --- a/rustybot/src/models.rs +++ b/rustybot/src/models.rs @@ -1,4 +1,6 @@ use crate::currency::SymbolPair; +use crate::BoxError; +use std::fmt::Display; /*************** * Prices @@ -62,6 +64,79 @@ pub enum OrderKind { ExchangeIoc, } +#[derive(Serialize, Clone)] +pub struct OrderForm { + /// Order Type: LIMIT, EXCHANGE LIMIT, MARKET, EXCHANGE MARKET, + /// STOP, EXCHANGE STOP, STOP LIMIT, EXCHANGE STOP LIMIT, + /// TRAILING STOP, EXCHANGE TRAILING STOP, FOK, + /// EXCHANGE FOK, IOC, EXCHANGE IOC + kind: OrderKind, + /// Symbol for desired pair + symbol: SymbolPair, + /// Price of order + price: String, + /// Amount of order (positive for buy, negative for sell) + amount: String, + /// Set the leverage for a derivative order, supported by derivative symbol orders only. + /// The value should be between 1 and 100 inclusive. + /// The field is optional, if omitted the default leverage value of 10 will be used. + leverage: Option, + /// The trailing price for a trailing stop order + price_trailing: Option, + /// Auxiliary Limit price (for STOP LIMIT) + price_aux_limit: Option, + /// Time-In-Force: datetime for automatic order cancellation (ie. 2020-01-01 10:45:23) ) + tif: Option, +} + +impl OrderForm { + pub fn new(symbol: &SymbolPair, price: f64, amount: f64, kind: OrderKind) -> Self { + OrderForm { + kind, + symbol: symbol.clone(), + price: price.to_string(), + amount: amount.to_string(), + leverage: None, + price_trailing: None, + price_aux_limit: None, + tif: None, + } + } + + pub fn with_leverage(mut self, leverage: u32) -> Self { + self.leverage = Some(leverage); + self + } + + pub fn with_price_trailing(mut self, trailing: f64) -> Result { + match self.kind { + OrderKind::TrailingStop => { + self.price_trailing = Some(trailing.to_string()); + Ok(self) + } + _ => Err("Invalid order type.".into()), + } + } + + pub fn price_aux_limit(mut self, limit: f64) -> Result { + match self.kind { + OrderKind::StopLimit | OrderKind::ExchangeStopLimit => { + self.price_aux_limit = Some(limit.to_string()); + Ok(self) + } + _ => Err("Invalid order type.".into()), + } + } + + pub fn with_tif(mut self, tif: DateTime) -> Self + where + T::Offset: Display, + { + self.tif = Some(tif.format("%Y-%m-%d %H:%M:%S").to_string()); + self + } +} + /*************** * Positions ***************/