From 127ffaa1b958fef2faecc12df74a564cb2fc6a5c Mon Sep 17 00:00:00 2001 From: Giulio De Pasquale Date: Sat, 13 Feb 2021 15:29:00 +0000 Subject: [PATCH] moved amount out of OrderKind and into OrderForm. leverage detection for open positions --- rustybot/src/connectors.rs | 93 ++++++++++++------------ rustybot/src/managers.rs | 5 +- rustybot/src/models.rs | 140 +++++++++++++------------------------ rustybot/src/strategy.rs | 7 +- 4 files changed, 99 insertions(+), 146 deletions(-) diff --git a/rustybot/src/connectors.rs b/rustybot/src/connectors.rs index 0a32b6c..f1da7ef 100644 --- a/rustybot/src/connectors.rs +++ b/rustybot/src/connectors.rs @@ -311,39 +311,46 @@ impl Connector for BitfinexConnector { async fn submit_order(&self, order: &OrderForm) -> Result { let symbol_name = format!("t{}", BitfinexConnector::format_trading_pair(order.pair())); + let amount = order.amount(); - let order_form = match order.kind() { - OrderKind::Limit { price, amount } => { - bitfinex::orders::OrderForm::new(symbol_name, price, amount, order.into()) - .with_leverage(15) + let order_form = { + let pre_leverage = { + match order.kind() { + OrderKind::Limit { price } => { + bitfinex::orders::OrderForm::new(symbol_name, price, amount, order.into()) + } + OrderKind::Market => { + bitfinex::orders::OrderForm::new(symbol_name, 0.0, amount, order.into()) + } + OrderKind::Stop { price } => { + bitfinex::orders::OrderForm::new(symbol_name, price, amount, order.into()) + } + OrderKind::StopLimit { price, limit_price } => { + bitfinex::orders::OrderForm::new(symbol_name, price, amount, order.into()) + .with_price_aux_limit(limit_price)? + } + OrderKind::TrailingStop { distance } => { + bitfinex::orders::OrderForm::new(symbol_name, 0.0, amount, order.into()) + .with_price_trailing(distance)? + } + OrderKind::FillOrKill { price } => { + bitfinex::orders::OrderForm::new(symbol_name, price, amount, order.into()) + } + OrderKind::ImmediateOrCancel { price } => { + bitfinex::orders::OrderForm::new(symbol_name, price, amount, order.into()) + } + } + .with_meta(OrderMeta::new( + BitfinexConnector::AFFILIATE_CODE.to_string(), + )) + }; + + // adding leverage, if any + match order.leverage() { + Some(leverage) => pre_leverage.with_leverage(leverage as u32), + None => pre_leverage, } - OrderKind::Market { amount, .. } => { - bitfinex::orders::OrderForm::new(symbol_name, 0.0, amount, order.into()) - .with_leverage(15) - } - OrderKind::Stop { price, amount } => { - bitfinex::orders::OrderForm::new(symbol_name, price, amount, order.into()) - } - OrderKind::StopLimit { - price, - amount, - limit_price, - } => bitfinex::orders::OrderForm::new(symbol_name, price, amount, order.into()) - .with_price_aux_limit(limit_price)?, - OrderKind::TrailingStop { distance, amount } => { - bitfinex::orders::OrderForm::new(symbol_name, 0.0, amount, order.into()) - .with_price_trailing(distance)? - } - OrderKind::FillOrKill { price, amount } => { - bitfinex::orders::OrderForm::new(symbol_name, price, amount, order.into()) - } - OrderKind::ImmediateOrCancel { price, amount } => { - bitfinex::orders::OrderForm::new(symbol_name, price, amount, order.into()) - } - } - .with_meta(OrderMeta::new( - BitfinexConnector::AFFILIATE_CODE.to_string(), - )); + }; let response = BitfinexConnector::retry_nonce(|| self.bfx.orders.submit_order(&order_form)).await?; @@ -474,6 +481,7 @@ impl TryFrom<&bitfinex::responses::OrderResponse> for ActiveOrder { SymbolPair::from_str(response.symbol())?, response.into(), response.into(), + response.amount(), ), creation_timestamp: 0, update_timestamp: 0, @@ -511,6 +519,7 @@ impl TryInto for bitfinex::positions::Position { self.price_liq(), self.position_id(), platform, + self.leverage(), ) .with_creation_date(self.mts_create()) .with_creation_update(self.mts_update())) @@ -579,41 +588,33 @@ impl From<&bitfinex::responses::OrderResponse> for OrderKind { bitfinex::orders::OrderKind::Limit | bitfinex::orders::OrderKind::ExchangeLimit => { Self::Limit { price: response.price(), - amount: response.amount(), } } bitfinex::orders::OrderKind::Market | bitfinex::orders::OrderKind::ExchangeMarket => { - Self::Market { - amount: response.amount(), - } + Self::Market } bitfinex::orders::OrderKind::Stop | bitfinex::orders::OrderKind::ExchangeStop => { Self::Stop { price: response.price(), - amount: response.amount(), } } bitfinex::orders::OrderKind::StopLimit | bitfinex::orders::OrderKind::ExchangeStopLimit => Self::StopLimit { price: response.price(), - amount: response.amount(), limit_price: response.price_aux_limit().expect("Limit price not found!"), }, bitfinex::orders::OrderKind::TrailingStop | bitfinex::orders::OrderKind::ExchangeTrailingStop => Self::TrailingStop { distance: response.price_trailing().expect("Distance not found!"), - amount: response.amount(), }, bitfinex::orders::OrderKind::Fok | bitfinex::orders::OrderKind::ExchangeFok => { Self::FillOrKill { price: response.price(), - amount: response.amount(), } } bitfinex::orders::OrderKind::Ioc | bitfinex::orders::OrderKind::ExchangeIoc => { Self::ImmediateOrCancel { price: response.price(), - amount: response.amount(), } } } @@ -626,41 +627,33 @@ impl From<&bitfinex::orders::ActiveOrder> for OrderKind { bitfinex::orders::OrderKind::Limit | bitfinex::orders::OrderKind::ExchangeLimit => { Self::Limit { price: response.price(), - amount: response.amount(), } } bitfinex::orders::OrderKind::Market | bitfinex::orders::OrderKind::ExchangeMarket => { - Self::Market { - amount: response.amount(), - } + Self::Market {} } bitfinex::orders::OrderKind::Stop | bitfinex::orders::OrderKind::ExchangeStop => { Self::Stop { price: response.price(), - amount: response.amount(), } } bitfinex::orders::OrderKind::StopLimit | bitfinex::orders::OrderKind::ExchangeStopLimit => Self::StopLimit { price: response.price(), - amount: response.amount(), limit_price: response.price_aux_limit().expect("Limit price not found!"), }, bitfinex::orders::OrderKind::TrailingStop | bitfinex::orders::OrderKind::ExchangeTrailingStop => Self::TrailingStop { distance: response.price_trailing().expect("Distance not found!"), - amount: response.amount(), }, bitfinex::orders::OrderKind::Fok | bitfinex::orders::OrderKind::ExchangeFok => { Self::FillOrKill { price: response.price(), - amount: response.amount(), } } bitfinex::orders::OrderKind::Ioc | bitfinex::orders::OrderKind::ExchangeIoc => { Self::ImmediateOrCancel { price: response.price(), - amount: response.amount(), } } } @@ -677,7 +670,7 @@ impl From<&bitfinex::orders::ActiveOrder> for ActiveOrder { group_id: order.group_id().map(|x| x as u64), client_id: Some(order.client_id()), symbol: pair.clone(), - details: OrderForm::new(pair, order.into(), order.into()), + details: OrderForm::new(pair, order.into(), order.into(), order.amount()), creation_timestamp: order.creation_timestamp(), update_timestamp: order.update_timestamp(), } diff --git a/rustybot/src/managers.rs b/rustybot/src/managers.rs index e62136b..6802f8d 100644 --- a/rustybot/src/managers.rs +++ b/rustybot/src/managers.rs @@ -436,10 +436,11 @@ impl OrderManager { self.pair.clone(), OrderKind::Limit { price: closing_price, - amount: position.amount().neg(), }, TradingPlatform::Derivative, - ); + position.amount().neg(), + ) + .with_leverage(position.leverage()); info!("Submitting {} order", order_form.kind()); if let Err(e) = self.client.submit_order(&order_form).await { diff --git a/rustybot/src/models.rs b/rustybot/src/models.rs index 305d52b..2b6d064 100644 --- a/rustybot/src/models.rs +++ b/rustybot/src/models.rs @@ -213,34 +213,13 @@ impl Display for TradingPlatform { #[derive(Copy, Clone, Debug)] pub enum OrderKind { - Limit { - price: f64, - amount: f64, - }, - Market { - amount: f64, - }, - Stop { - price: f64, - amount: f64, - }, - StopLimit { - price: f64, - amount: f64, - limit_price: f64, - }, - TrailingStop { - distance: f64, - amount: f64, - }, - FillOrKill { - price: f64, - amount: f64, - }, - ImmediateOrCancel { - price: f64, - amount: f64, - }, + Limit { price: f64 }, + Market, + Stop { price: f64 }, + StopLimit { price: f64, limit_price: f64 }, + TrailingStop { distance: f64 }, + FillOrKill { price: f64 }, + ImmediateOrCancel { price: f64 }, } impl OrderKind { @@ -260,67 +239,32 @@ impl OrderKind { impl Display for OrderKind { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { match self { - OrderKind::Limit { price, amount } => { + OrderKind::Limit { price } => { + write!(f, "[{} | Price: {:0.5}]", self.as_str(), price,) + } + OrderKind::Market => { + write!(f, "[{}]", self.as_str()) + } + OrderKind::Stop { price } => { + write!(f, "[{} | Price: {:0.5}", self.as_str(), price,) + } + OrderKind::StopLimit { price, limit_price } => { write!( f, - "[{} | Price: {:0.5}, Amount: {:0.5}]", + "[{} | Price: {:0.5}, Limit Price: {:0.5}]", self.as_str(), price, - amount - ) - } - OrderKind::Market { amount } => { - write!(f, "[{} | Amount: {:0.5}]", self.as_str(), amount) - } - OrderKind::Stop { price, amount } => { - write!( - f, - "[{} | Price: {:0.5}, Amount: {:0.5}]", - self.as_str(), - price, - amount - ) - } - OrderKind::StopLimit { - price, - amount, - limit_price, - } => { - write!( - f, - "[{} | Price: {:0.5}, Amount: {:0.5}, Limit Price: {:0.5}]", - self.as_str(), - price, - amount, limit_price ) } - OrderKind::TrailingStop { distance, amount } => { - write!( - f, - "[{} | Distance: {:0.5}, Amount: {:0.5}]", - self.as_str(), - distance, - amount - ) + OrderKind::TrailingStop { distance } => { + write!(f, "[{} | Distance: {:0.5}]", self.as_str(), distance,) } - OrderKind::FillOrKill { price, amount } => { - write!( - f, - "[{} | Price: {:0.5}, Amount: {:0.5}]", - self.as_str(), - price, - amount - ) + OrderKind::FillOrKill { price } => { + write!(f, "[{} | Price: {:0.5}]", self.as_str(), price,) } - OrderKind::ImmediateOrCancel { price, amount } => { - write!( - f, - "[{} | Price: {:0.5}, Amount: {:0.5}]", - self.as_str(), - price, - amount - ) + OrderKind::ImmediateOrCancel { price } => { + write!(f, "[{} | Price: {:0.5}]", self.as_str(), price,) } } } @@ -331,17 +275,31 @@ pub struct OrderForm { pair: SymbolPair, kind: OrderKind, platform: TradingPlatform, + amount: f64, + leverage: Option, } impl OrderForm { - pub fn new(pair: SymbolPair, order_kind: OrderKind, platform: TradingPlatform) -> Self { + pub fn new( + pair: SymbolPair, + order_kind: OrderKind, + platform: TradingPlatform, + amount: f64, + ) -> Self { Self { pair, kind: order_kind, platform, + amount, + leverage: None, } } + pub fn with_leverage(mut self, leverage: f64) -> Self { + self.leverage = Some(leverage); + self + } + pub fn pair(&self) -> &SymbolPair { &self.pair } @@ -355,15 +313,7 @@ impl OrderForm { } pub fn amount(&self) -> f64 { - match self.kind { - OrderKind::Limit { amount, .. } => amount, - OrderKind::Market { amount } => amount, - OrderKind::Stop { amount, .. } => amount, - OrderKind::StopLimit { amount, .. } => amount, - OrderKind::TrailingStop { amount, .. } => amount, - OrderKind::FillOrKill { amount, .. } => amount, - OrderKind::ImmediateOrCancel { amount, .. } => amount, - } + self.amount } pub fn price(&self) -> Option { @@ -377,6 +327,10 @@ impl OrderForm { OrderKind::ImmediateOrCancel { price, .. } => Some(price), } } + + pub fn leverage(&self) -> Option { + self.leverage + } } /*************** @@ -397,6 +351,7 @@ pub struct Position { creation_date: Option, creation_update: Option, platform: TradingPlatform, + leverage: f64, } impl Position { @@ -410,6 +365,7 @@ impl Position { price_liq: f64, position_id: u64, platform: TradingPlatform, + leverage: f64, ) -> Self { Position { pair, @@ -424,6 +380,7 @@ impl Position { creation_update: None, profit_state: None, platform, + leverage, } } @@ -511,6 +468,9 @@ impl Position { pub fn platform(&self) -> TradingPlatform { self.platform } + pub fn leverage(&self) -> f64 { + self.leverage + } } impl Hash for Position { diff --git a/rustybot/src/strategy.rs b/rustybot/src/strategy.rs index 90aabef..a7c2064 100644 --- a/rustybot/src/strategy.rs +++ b/rustybot/src/strategy.rs @@ -10,7 +10,7 @@ use crate::managers::OptionUpdate; use crate::models::OrderBookEntry::Trading; use crate::models::{ ActiveOrder, OrderBook, OrderBookEntry, OrderForm, OrderKind, Position, PositionProfitState, - PositionState, TradingPlatform, + PositionState, TradingFees, TradingPlatform, }; use crate::BoxError; @@ -309,10 +309,9 @@ impl OrderStrategy for FastOrderStrategy { messages.push(Message::SubmitOrder { order: OrderForm::new( order.symbol.clone(), - OrderKind::Market { - amount: order.details.amount(), - }, + OrderKind::Market {}, order.details.platform().clone(), + order.details.amount(), ), }) }