moved amount out of OrderKind and into OrderForm. leverage detection for open positions

This commit is contained in:
Giulio De Pasquale 2021-02-13 15:29:00 +00:00
parent ce8eec71ff
commit 127ffaa1b9
4 changed files with 99 additions and 146 deletions

View File

@ -311,39 +311,46 @@ impl Connector for BitfinexConnector {
async fn submit_order(&self, order: &OrderForm) -> Result<ActiveOrder, BoxError> { async fn submit_order(&self, order: &OrderForm) -> Result<ActiveOrder, BoxError> {
let symbol_name = format!("t{}", BitfinexConnector::format_trading_pair(order.pair())); let symbol_name = format!("t{}", BitfinexConnector::format_trading_pair(order.pair()));
let amount = order.amount();
let order_form = match order.kind() { let order_form = {
OrderKind::Limit { price, amount } => { let pre_leverage = {
bitfinex::orders::OrderForm::new(symbol_name, price, amount, order.into()) match order.kind() {
.with_leverage(15) 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 = let response =
BitfinexConnector::retry_nonce(|| self.bfx.orders.submit_order(&order_form)).await?; 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())?, SymbolPair::from_str(response.symbol())?,
response.into(), response.into(),
response.into(), response.into(),
response.amount(),
), ),
creation_timestamp: 0, creation_timestamp: 0,
update_timestamp: 0, update_timestamp: 0,
@ -511,6 +519,7 @@ impl TryInto<Position> for bitfinex::positions::Position {
self.price_liq(), self.price_liq(),
self.position_id(), self.position_id(),
platform, platform,
self.leverage(),
) )
.with_creation_date(self.mts_create()) .with_creation_date(self.mts_create())
.with_creation_update(self.mts_update())) .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 => { bitfinex::orders::OrderKind::Limit | bitfinex::orders::OrderKind::ExchangeLimit => {
Self::Limit { Self::Limit {
price: response.price(), price: response.price(),
amount: response.amount(),
} }
} }
bitfinex::orders::OrderKind::Market | bitfinex::orders::OrderKind::ExchangeMarket => { bitfinex::orders::OrderKind::Market | bitfinex::orders::OrderKind::ExchangeMarket => {
Self::Market { Self::Market
amount: response.amount(),
}
} }
bitfinex::orders::OrderKind::Stop | bitfinex::orders::OrderKind::ExchangeStop => { bitfinex::orders::OrderKind::Stop | bitfinex::orders::OrderKind::ExchangeStop => {
Self::Stop { Self::Stop {
price: response.price(), price: response.price(),
amount: response.amount(),
} }
} }
bitfinex::orders::OrderKind::StopLimit bitfinex::orders::OrderKind::StopLimit
| bitfinex::orders::OrderKind::ExchangeStopLimit => Self::StopLimit { | bitfinex::orders::OrderKind::ExchangeStopLimit => Self::StopLimit {
price: response.price(), price: response.price(),
amount: response.amount(),
limit_price: response.price_aux_limit().expect("Limit price not found!"), limit_price: response.price_aux_limit().expect("Limit price not found!"),
}, },
bitfinex::orders::OrderKind::TrailingStop bitfinex::orders::OrderKind::TrailingStop
| bitfinex::orders::OrderKind::ExchangeTrailingStop => Self::TrailingStop { | bitfinex::orders::OrderKind::ExchangeTrailingStop => Self::TrailingStop {
distance: response.price_trailing().expect("Distance not found!"), distance: response.price_trailing().expect("Distance not found!"),
amount: response.amount(),
}, },
bitfinex::orders::OrderKind::Fok | bitfinex::orders::OrderKind::ExchangeFok => { bitfinex::orders::OrderKind::Fok | bitfinex::orders::OrderKind::ExchangeFok => {
Self::FillOrKill { Self::FillOrKill {
price: response.price(), price: response.price(),
amount: response.amount(),
} }
} }
bitfinex::orders::OrderKind::Ioc | bitfinex::orders::OrderKind::ExchangeIoc => { bitfinex::orders::OrderKind::Ioc | bitfinex::orders::OrderKind::ExchangeIoc => {
Self::ImmediateOrCancel { Self::ImmediateOrCancel {
price: response.price(), 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 => { bitfinex::orders::OrderKind::Limit | bitfinex::orders::OrderKind::ExchangeLimit => {
Self::Limit { Self::Limit {
price: response.price(), price: response.price(),
amount: response.amount(),
} }
} }
bitfinex::orders::OrderKind::Market | bitfinex::orders::OrderKind::ExchangeMarket => { bitfinex::orders::OrderKind::Market | bitfinex::orders::OrderKind::ExchangeMarket => {
Self::Market { Self::Market {}
amount: response.amount(),
}
} }
bitfinex::orders::OrderKind::Stop | bitfinex::orders::OrderKind::ExchangeStop => { bitfinex::orders::OrderKind::Stop | bitfinex::orders::OrderKind::ExchangeStop => {
Self::Stop { Self::Stop {
price: response.price(), price: response.price(),
amount: response.amount(),
} }
} }
bitfinex::orders::OrderKind::StopLimit bitfinex::orders::OrderKind::StopLimit
| bitfinex::orders::OrderKind::ExchangeStopLimit => Self::StopLimit { | bitfinex::orders::OrderKind::ExchangeStopLimit => Self::StopLimit {
price: response.price(), price: response.price(),
amount: response.amount(),
limit_price: response.price_aux_limit().expect("Limit price not found!"), limit_price: response.price_aux_limit().expect("Limit price not found!"),
}, },
bitfinex::orders::OrderKind::TrailingStop bitfinex::orders::OrderKind::TrailingStop
| bitfinex::orders::OrderKind::ExchangeTrailingStop => Self::TrailingStop { | bitfinex::orders::OrderKind::ExchangeTrailingStop => Self::TrailingStop {
distance: response.price_trailing().expect("Distance not found!"), distance: response.price_trailing().expect("Distance not found!"),
amount: response.amount(),
}, },
bitfinex::orders::OrderKind::Fok | bitfinex::orders::OrderKind::ExchangeFok => { bitfinex::orders::OrderKind::Fok | bitfinex::orders::OrderKind::ExchangeFok => {
Self::FillOrKill { Self::FillOrKill {
price: response.price(), price: response.price(),
amount: response.amount(),
} }
} }
bitfinex::orders::OrderKind::Ioc | bitfinex::orders::OrderKind::ExchangeIoc => { bitfinex::orders::OrderKind::Ioc | bitfinex::orders::OrderKind::ExchangeIoc => {
Self::ImmediateOrCancel { Self::ImmediateOrCancel {
price: response.price(), 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), group_id: order.group_id().map(|x| x as u64),
client_id: Some(order.client_id()), client_id: Some(order.client_id()),
symbol: pair.clone(), 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(), creation_timestamp: order.creation_timestamp(),
update_timestamp: order.update_timestamp(), update_timestamp: order.update_timestamp(),
} }

View File

@ -436,10 +436,11 @@ impl OrderManager {
self.pair.clone(), self.pair.clone(),
OrderKind::Limit { OrderKind::Limit {
price: closing_price, price: closing_price,
amount: position.amount().neg(),
}, },
TradingPlatform::Derivative, TradingPlatform::Derivative,
); position.amount().neg(),
)
.with_leverage(position.leverage());
info!("Submitting {} order", order_form.kind()); info!("Submitting {} order", order_form.kind());
if let Err(e) = self.client.submit_order(&order_form).await { if let Err(e) = self.client.submit_order(&order_form).await {

View File

@ -213,34 +213,13 @@ impl Display for TradingPlatform {
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
pub enum OrderKind { pub enum OrderKind {
Limit { Limit { price: f64 },
price: f64, Market,
amount: f64, Stop { price: f64 },
}, StopLimit { price: f64, limit_price: f64 },
Market { TrailingStop { distance: f64 },
amount: f64, FillOrKill { price: f64 },
}, ImmediateOrCancel { price: 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,
},
} }
impl OrderKind { impl OrderKind {
@ -260,67 +239,32 @@ impl OrderKind {
impl Display for OrderKind { impl Display for OrderKind {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self { 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!( write!(
f, f,
"[{} | Price: {:0.5}, Amount: {:0.5}]", "[{} | Price: {:0.5}, Limit Price: {:0.5}]",
self.as_str(), self.as_str(),
price, 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 limit_price
) )
} }
OrderKind::TrailingStop { distance, amount } => { OrderKind::TrailingStop { distance } => {
write!( write!(f, "[{} | Distance: {:0.5}]", self.as_str(), distance,)
f,
"[{} | Distance: {:0.5}, Amount: {:0.5}]",
self.as_str(),
distance,
amount
)
} }
OrderKind::FillOrKill { price, amount } => { OrderKind::FillOrKill { price } => {
write!( write!(f, "[{} | Price: {:0.5}]", self.as_str(), price,)
f,
"[{} | Price: {:0.5}, Amount: {:0.5}]",
self.as_str(),
price,
amount
)
} }
OrderKind::ImmediateOrCancel { price, amount } => { OrderKind::ImmediateOrCancel { price } => {
write!( write!(f, "[{} | Price: {:0.5}]", self.as_str(), price,)
f,
"[{} | Price: {:0.5}, Amount: {:0.5}]",
self.as_str(),
price,
amount
)
} }
} }
} }
@ -331,17 +275,31 @@ pub struct OrderForm {
pair: SymbolPair, pair: SymbolPair,
kind: OrderKind, kind: OrderKind,
platform: TradingPlatform, platform: TradingPlatform,
amount: f64,
leverage: Option<f64>,
} }
impl OrderForm { 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 { Self {
pair, pair,
kind: order_kind, kind: order_kind,
platform, platform,
amount,
leverage: None,
} }
} }
pub fn with_leverage(mut self, leverage: f64) -> Self {
self.leverage = Some(leverage);
self
}
pub fn pair(&self) -> &SymbolPair { pub fn pair(&self) -> &SymbolPair {
&self.pair &self.pair
} }
@ -355,15 +313,7 @@ impl OrderForm {
} }
pub fn amount(&self) -> f64 { pub fn amount(&self) -> f64 {
match self.kind { self.amount
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,
}
} }
pub fn price(&self) -> Option<f64> { pub fn price(&self) -> Option<f64> {
@ -377,6 +327,10 @@ impl OrderForm {
OrderKind::ImmediateOrCancel { price, .. } => Some(price), OrderKind::ImmediateOrCancel { price, .. } => Some(price),
} }
} }
pub fn leverage(&self) -> Option<f64> {
self.leverage
}
} }
/*************** /***************
@ -397,6 +351,7 @@ pub struct Position {
creation_date: Option<u64>, creation_date: Option<u64>,
creation_update: Option<u64>, creation_update: Option<u64>,
platform: TradingPlatform, platform: TradingPlatform,
leverage: f64,
} }
impl Position { impl Position {
@ -410,6 +365,7 @@ impl Position {
price_liq: f64, price_liq: f64,
position_id: u64, position_id: u64,
platform: TradingPlatform, platform: TradingPlatform,
leverage: f64,
) -> Self { ) -> Self {
Position { Position {
pair, pair,
@ -424,6 +380,7 @@ impl Position {
creation_update: None, creation_update: None,
profit_state: None, profit_state: None,
platform, platform,
leverage,
} }
} }
@ -511,6 +468,9 @@ impl Position {
pub fn platform(&self) -> TradingPlatform { pub fn platform(&self) -> TradingPlatform {
self.platform self.platform
} }
pub fn leverage(&self) -> f64 {
self.leverage
}
} }
impl Hash for Position { impl Hash for Position {

View File

@ -10,7 +10,7 @@ use crate::managers::OptionUpdate;
use crate::models::OrderBookEntry::Trading; use crate::models::OrderBookEntry::Trading;
use crate::models::{ use crate::models::{
ActiveOrder, OrderBook, OrderBookEntry, OrderForm, OrderKind, Position, PositionProfitState, ActiveOrder, OrderBook, OrderBookEntry, OrderForm, OrderKind, Position, PositionProfitState,
PositionState, TradingPlatform, PositionState, TradingFees, TradingPlatform,
}; };
use crate::BoxError; use crate::BoxError;
@ -309,10 +309,9 @@ impl OrderStrategy for FastOrderStrategy {
messages.push(Message::SubmitOrder { messages.push(Message::SubmitOrder {
order: OrderForm::new( order: OrderForm::new(
order.symbol.clone(), order.symbol.clone(),
OrderKind::Market { OrderKind::Market {},
amount: order.details.amount(),
},
order.details.platform().clone(), order.details.platform().clone(),
order.details.amount(),
), ),
}) })
} }