pair manager to be constructed. update function result signatures updated THEY HAVE TO BE CONNECTED

This commit is contained in:
Giulio De Pasquale 2021-01-17 21:06:18 +00:00
parent 71273ccc78
commit f3cb051535
2 changed files with 47 additions and 26 deletions

View File

@ -4,7 +4,7 @@ use std::ops::Neg;
use bitfinex::ticker::TradingPairTicker; use bitfinex::ticker::TradingPairTicker;
use futures_util::stream::FuturesUnordered; use futures_util::stream::FuturesUnordered;
use futures_util::StreamExt; use futures_util::StreamExt;
use log::{debug, error}; use log::{debug, error, info};
use tokio::signal::unix::Signal; use tokio::signal::unix::Signal;
use tokio::sync::mpsc::channel; use tokio::sync::mpsc::channel;
use tokio::sync::mpsc::{Receiver, Sender}; use tokio::sync::mpsc::{Receiver, Sender};
@ -16,6 +16,8 @@ use crate::models::{ExecutedOrder, OrderForm, OrderKind, Position, PriceTicker};
use crate::strategy::{FastOrderStrategy, OrderStrategy, PositionStrategy, TrailingStop}; use crate::strategy::{FastOrderStrategy, OrderStrategy, PositionStrategy, TrailingStop};
use crate::BoxError; use crate::BoxError;
type OptionUpdate = (Option<Vec<Event>>, Option<Vec<SignalKind>>);
pub struct EventManager { pub struct EventManager {
events: Vec<Event>, events: Vec<Event>,
} }
@ -226,10 +228,8 @@ impl PositionManager {
Ok(()) Ok(())
} }
pub async fn update(
&mut self, pub async fn update(&mut self, tick: u64) -> Result<OptionUpdate, BoxError> {
tick: u64,
) -> Result<(Option<Vec<Event>>, Option<OrderForm>), BoxError> {
let opt_active_positions = self.client.active_positions(&self.pair).await?; let opt_active_positions = self.client.active_positions(&self.pair).await?;
let mut events = vec![]; let mut events = vec![];
@ -265,7 +265,7 @@ impl PositionManager {
} }
}; };
Ok(((events.is_empty().then_some(events)), None)) Ok((None, None))
} }
pub fn position_previous_tick(&self, id: u64, tick: Option<u64>) -> Option<&Position> { pub fn position_previous_tick(&self, id: u64, tick: Option<u64>) -> Option<&Position> {
@ -369,19 +369,26 @@ impl OrderManager {
pub async fn close_position(&mut self, position: &Position) -> Result<(), BoxError> { pub async fn close_position(&mut self, position: &Position) -> Result<(), BoxError> {
let open_order = self.tracked_positions.get(&position.id()); let open_order = self.tracked_positions.get(&position.id());
info!("Closing position {}", position.id());
// checking if the position has an open order. // checking if the position has an open order.
// If so, the strategy method is called, otherwise we open // If so, the strategy method is called, otherwise we open
// an undercut limit order at the best current price. // an undercut limit order at the best current price.
match open_order { match open_order {
Some(open_order) => { Some(open_order) => {
info!("There is an open order. Calling strategy.");
self.tracked_positions = self self.tracked_positions = self
.strategy .strategy
.on_position_close(open_order, &self.tracked_positions); .on_position_close(open_order, &self.tracked_positions);
} }
None => { None => {
info!("Getting current prices...");
let current_prices = self.client.current_prices(&self.pair).await?; let current_prices = self.client.current_prices(&self.pair).await?;
info!("Calculating best closing price...");
let closing_price = self.best_closing_price(&position, &current_prices)?; let closing_price = self.best_closing_price(&position, &current_prices)?;
info!("Submitting order...");
// submitting order // submitting order
let order_form = OrderForm::new( let order_form = OrderForm::new(
&self.pair, &self.pair,
@ -394,6 +401,7 @@ impl OrderManager {
Err(e) => error!("Could not submit order: {}", e), Err(e) => error!("Could not submit order: {}", e),
Ok(o) => { Ok(o) => {
self.tracked_positions.insert(position.id(), o); self.tracked_positions.insert(position.id(), o);
info!("Done!");
} }
}; };
} }
@ -402,7 +410,7 @@ impl OrderManager {
Ok(()) Ok(())
} }
pub fn update(&self) -> Option<Vec<Event>> { pub fn update(&self) -> Result<OptionUpdate, BoxError> {
unimplemented!() unimplemented!()
} }
@ -464,17 +472,16 @@ impl ExchangeManager {
} }
} }
pub async fn update_managers(&mut self, tick: u64) -> Result<(), BoxError> { pub async fn update_managers(&mut self, tick: u64) -> Result<OptionUpdate, BoxError> {
self.update_price_managers(tick).await?; let (price_opt_events, price_opt_signals) = self.update_price_managers(tick).await?;
self.update_position_managers(tick).await?; let (pos_opt_events, pos_opt_signals) = self.update_position_managers(tick).await?;
Ok(()) debug!("{:?}", pos_opt_signals);
Ok((pos_opt_events, price_opt_signals))
} }
async fn update_position_managers( async fn update_position_managers(&mut self, tick: u64) -> Result<OptionUpdate, BoxError> {
&mut self,
tick: u64,
) -> Result<Option<Vec<Event>>, BoxError> {
let mut futures: FuturesUnordered<_> = self let mut futures: FuturesUnordered<_> = self
.position_managers .position_managers
.iter_mut() .iter_mut()
@ -483,10 +490,10 @@ impl ExchangeManager {
while let Some(x) = futures.next().await {} while let Some(x) = futures.next().await {}
Ok(None) Ok((None, None))
} }
async fn update_price_managers(&mut self, tick: u64) -> Result<Option<Vec<Event>>, BoxError> { async fn update_price_managers(&mut self, tick: u64) -> Result<OptionUpdate, BoxError> {
let mut futures: FuturesUnordered<_> = self let mut futures: FuturesUnordered<_> = self
.price_managers .price_managers
.iter_mut() .iter_mut()
@ -495,6 +502,6 @@ impl ExchangeManager {
while let Some(x) = futures.next().await {} while let Some(x) = futures.next().await {}
Ok(None) Ok((None, None))
} }
} }

View File

@ -17,7 +17,7 @@ pub trait PositionStrategy: DynClone + Send {
&self, &self,
position: Position, position: Position,
manager: &PositionManager, manager: &PositionManager,
) -> (Position, Vec<Event>, Option<OrderForm>); ) -> (Position, Option<Vec<Event>>, Option<Vec<SignalKind>>);
} }
impl Debug for dyn PositionStrategy { impl Debug for dyn PositionStrategy {
@ -60,7 +60,7 @@ impl TrailingStop {
const BREAK_EVEN_PERC: f64 = 0.2; const BREAK_EVEN_PERC: f64 = 0.2;
const MIN_PROFIT_PERC: f64 = TrailingStop::BREAK_EVEN_PERC + 0.3; const MIN_PROFIT_PERC: f64 = TrailingStop::BREAK_EVEN_PERC + 0.3;
const GOOD_PROFIT_PERC: f64 = TrailingStop::MIN_PROFIT_PERC * 2.5; const GOOD_PROFIT_PERC: f64 = TrailingStop::MIN_PROFIT_PERC * 2.5;
const MAX_LOSS_PERC: f64 = -1.7; const MAX_LOSS_PERC: f64 = -0.01;
const TAKER_FEE: f64 = 0.2; const TAKER_FEE: f64 = 0.2;
@ -84,11 +84,11 @@ impl PositionStrategy for TrailingStop {
&self, &self,
position: Position, position: Position,
manager: &PositionManager, manager: &PositionManager,
) -> (Position, Vec<Event>, Option<OrderForm>) { ) -> (Position, Option<Vec<Event>>, Option<Vec<SignalKind>>) {
let mut signals = vec![]; let mut signals = vec![];
let pl_perc = TrailingStop::net_pl_percentage(position.pl_perc(), TrailingStop::TAKER_FEE);
let events = vec![]; let events = vec![];
let mut order = None;
let pl_perc = TrailingStop::net_pl_percentage(position.pl_perc(), TrailingStop::TAKER_FEE);
let state = { let state = {
if pl_perc > TrailingStop::GOOD_PROFIT_PERC { if pl_perc > TrailingStop::GOOD_PROFIT_PERC {
@ -114,10 +114,20 @@ impl PositionStrategy for TrailingStop {
match opt_pre_pw { match opt_pre_pw {
Some(prev) => { Some(prev) => {
if prev.profit_state() == Some(state) { if prev.profit_state() == Some(state) {
return (new_position, events, order); return (
new_position,
(!events.is_empty()).then_some(events),
(!signals.is_empty()).then_some(signals),
);
} }
} }
None => return (new_position, events, order), None => {
return (
new_position,
(!events.is_empty()).then_some(events),
(!signals.is_empty()).then_some(signals),
)
}
}; };
let events = { let events = {
@ -158,7 +168,11 @@ impl PositionStrategy for TrailingStop {
events events
}; };
return (new_position, events, order); return (
new_position,
(!events.is_empty()).then_some(events),
(!signals.is_empty()).then_some(signals),
);
} }
} }