pair manager to be constructed. update function result signatures updated THEY HAVE TO BE CONNECTED
This commit is contained in:
parent
71273ccc78
commit
f3cb051535
@ -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, ¤t_prices)?;
|
let closing_price = self.best_closing_price(&position, ¤t_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))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user