rust #10

Merged
peperunas merged 127 commits from rust into master 2021-02-18 09:42:16 +00:00
2 changed files with 47 additions and 26 deletions
Showing only changes of commit f3cb051535 - Show all commits

View File

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

View File

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