orders are now per orderform and not per order manager. current order strategy is set only when executing limit order on profit by trailing stop
This commit is contained in:
		
							parent
							
								
									669bd70946
								
							
						
					
					
						commit
						634f86c6fa
					
				| @ -1,6 +1,8 @@ | ||||
| 
 | ||||
| use std::collections::HashMap; | ||||
| use std::ops::Neg; | ||||
| 
 | ||||
| 
 | ||||
| use futures_util::stream::FuturesUnordered; | ||||
| use futures_util::StreamExt; | ||||
| use log::{debug, error, info, trace}; | ||||
| @ -14,9 +16,7 @@ use crate::BoxError; | ||||
| use crate::connectors::{Client, ExchangeDetails}; | ||||
| use crate::currency::SymbolPair; | ||||
| use crate::events::{ActionMessage, ActorMessage, Event}; | ||||
| use crate::models::{ | ||||
|     ActiveOrder, OrderBook, OrderForm, OrderKind, Position, PriceTicker, | ||||
| }; | ||||
| use crate::models::{ActiveOrder, OrderBook, OrderForm, OrderKind, OrderMetadata, Position, PriceTicker}; | ||||
| use crate::strategy::{HiddenTrailingStop, MarketEnforce, OrderStrategy, PositionStrategy}; | ||||
| 
 | ||||
| pub type OptionUpdate = (Option<Vec<Event>>, Option<Vec<ActionMessage>>); | ||||
| @ -331,10 +331,10 @@ impl OrderManagerHandle { | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn new(pair: SymbolPair, client: Client, strategy: Box<dyn OrderStrategy>) -> Self { | ||||
|     pub fn new(pair: SymbolPair, client: Client) -> Self { | ||||
|         let (sender, receiver) = channel(1); | ||||
| 
 | ||||
|         let manager = OrderManager::new(receiver, pair, client, strategy); | ||||
|         let manager = OrderManager::new(receiver, pair, client); | ||||
| 
 | ||||
|         tokio::spawn(OrderManagerHandle::run_order_manager(manager)); | ||||
| 
 | ||||
| @ -390,7 +390,6 @@ pub struct OrderManager { | ||||
|     pair: SymbolPair, | ||||
|     open_orders: Vec<ActiveOrder>, | ||||
|     client: Client, | ||||
|     strategy: Box<dyn OrderStrategy>, | ||||
| } | ||||
| 
 | ||||
| impl OrderManager { | ||||
| @ -398,14 +397,12 @@ impl OrderManager { | ||||
|         receiver: Receiver<ActorMessage>, | ||||
|         pair: SymbolPair, | ||||
|         client: Client, | ||||
|         strategy: Box<dyn OrderStrategy>, | ||||
|     ) -> Self { | ||||
|         OrderManager { | ||||
|             receiver, | ||||
|             pair, | ||||
|             open_orders: Vec::new(), | ||||
|             client, | ||||
|             strategy, | ||||
|             tracked_positions: HashMap::new(), | ||||
|         } | ||||
|     } | ||||
| @ -452,9 +449,17 @@ impl OrderManager { | ||||
|     } | ||||
| 
 | ||||
|     pub async fn submit_order(&mut self, order_form: &OrderForm) -> Result<OptionUpdate, BoxError> { | ||||
|         info!("Submiting {}", order_form.kind()); | ||||
|         info!("Submitting order: {}", order_form.kind()); | ||||
| 
 | ||||
|         let active_order = self.client.submit_order(order_form).await?; | ||||
|         // adding strategy to order, if present in the metadata
 | ||||
|         let active_order = { | ||||
|             if let Some(metadata) = order_form.metadata() { | ||||
|                 // TODO: this seems extremely dirty. Double check!
 | ||||
|                 self.client.submit_order(order_form).await?.with_strategy(metadata.cloned_strategy()) | ||||
|             } else { | ||||
|                 self.client.submit_order(order_form).await? | ||||
|             } | ||||
|         }; | ||||
| 
 | ||||
|         debug!("Adding order to tracked orders."); | ||||
|         if let Some(metadata) = order_form.metadata() { | ||||
| @ -515,7 +520,10 @@ impl OrderManager { | ||||
|                         position.platform(), | ||||
|                         position.amount().neg(), | ||||
|                     ) | ||||
|                         .with_leverage(Some(position.leverage())); | ||||
|                         .with_leverage(Some(position.leverage())) | ||||
|                         .with_metadata(Some(OrderMetadata::new() | ||||
|                             .with_strategy(Some(Box::new(MarketEnforce::default())))) | ||||
|                         ); | ||||
| 
 | ||||
|                     info!("Submitting {} order", order_form.kind()); | ||||
|                     if let Err(e) = self.client.submit_order(&order_form).await { | ||||
| @ -585,13 +593,16 @@ impl OrderManager { | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         for active_order in open_orders { | ||||
|         // TODO: this syntax can be simplified
 | ||||
|         for active_order in open_orders.iter().filter(|x| x.strategy().is_some()) { | ||||
|             let strategy = active_order.strategy().as_ref().unwrap(); | ||||
| 
 | ||||
|             trace!( | ||||
|                 "Found open order, calling \"{}\" strategy.", | ||||
|                 self.strategy.name() | ||||
|                 "Found open order with \"{}\" strategy.", | ||||
|                 strategy.name() | ||||
|             ); | ||||
| 
 | ||||
|             let (_, strat_messages) = self.strategy.on_open_order(&active_order, &order_book)?; | ||||
|             let (_, strat_messages) = strategy.on_open_order(&active_order, &order_book)?; | ||||
| 
 | ||||
|             if let Some(messages) = strat_messages { | ||||
|                 for m in messages { | ||||
| @ -602,7 +613,7 @@ impl OrderManager { | ||||
|                             self.client.cancel_order(&active_order).await?; | ||||
| 
 | ||||
|                             info!("\tSubmitting {}...", order_form.kind()); | ||||
|                             self.client.submit_order(&order_form).await?; | ||||
|                             self.submit_order(&order_form).await?; | ||||
|                             info!("Done!"); | ||||
|                         } | ||||
|                         _ => { | ||||
| @ -659,7 +670,6 @@ impl PairManager { | ||||
|             order_manager: OrderManagerHandle::new( | ||||
|                 pair.clone(), | ||||
|                 client.clone(), | ||||
|                 Box::new(MarketEnforce::default()), | ||||
|             ), | ||||
|             position_manager: PositionManagerHandle::new( | ||||
|                 pair, | ||||
|  | ||||
| @ -2,8 +2,11 @@ use std::fmt; | ||||
| use std::fmt::{Display, Formatter}; | ||||
| use std::hash::{Hash, Hasher}; | ||||
| 
 | ||||
| use dyn_clone::clone_box; | ||||
| 
 | ||||
| use crate::connectors::Exchange; | ||||
| use crate::currency::{Symbol, SymbolPair}; | ||||
| use crate::strategy::OrderStrategy; | ||||
| 
 | ||||
| /*************** | ||||
| * Prices | ||||
| @ -148,7 +151,7 @@ impl OrderDetails { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Clone, Debug)] | ||||
| #[derive(Debug)] | ||||
| pub struct ActiveOrder { | ||||
|     exchange: Exchange, | ||||
|     id: u64, | ||||
| @ -158,6 +161,7 @@ pub struct ActiveOrder { | ||||
|     order_form: OrderForm, | ||||
|     creation_timestamp: u64, | ||||
|     update_timestamp: u64, | ||||
|     strategy: Option<Box<dyn OrderStrategy>>, | ||||
| } | ||||
| 
 | ||||
| impl ActiveOrder { | ||||
| @ -178,6 +182,7 @@ impl ActiveOrder { | ||||
|             order_form, | ||||
|             creation_timestamp, | ||||
|             update_timestamp, | ||||
|             strategy: None, | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| @ -191,6 +196,11 @@ impl ActiveOrder { | ||||
|         self | ||||
|     } | ||||
| 
 | ||||
|     pub fn with_strategy(mut self, strategy: Option<Box<dyn OrderStrategy>>) -> Self { | ||||
|         self.strategy = strategy; | ||||
|         self | ||||
|     } | ||||
| 
 | ||||
|     pub fn exchange(&self) -> Exchange { | ||||
|         self.exchange | ||||
|     } | ||||
| @ -215,6 +225,9 @@ impl ActiveOrder { | ||||
|     pub fn update_timestamp(&self) -> u64 { | ||||
|         self.update_timestamp | ||||
|     } | ||||
|     pub fn strategy(&self) -> &Option<Box<dyn OrderStrategy>> { | ||||
|         &self.strategy | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Hash for ActiveOrder { | ||||
| @ -285,13 +298,13 @@ impl Display for OrderKind { | ||||
|     fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { | ||||
|         match self { | ||||
|             OrderKind::Limit { price } => { | ||||
|                 write!(f, "[{} | Price: {:0.5}]", self.as_str(), 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,) | ||||
|                 write!(f, "[{} | Price: {:0.5}]", self.as_str(), price, ) | ||||
|             } | ||||
|             OrderKind::StopLimit { stop_price, limit_price } => { | ||||
|                 write!( | ||||
| @ -303,13 +316,13 @@ impl Display for OrderKind { | ||||
|                 ) | ||||
|             } | ||||
|             OrderKind::TrailingStop { distance } => { | ||||
|                 write!(f, "[{} | Distance: {:0.5}]", self.as_str(), distance,) | ||||
|                 write!(f, "[{} | Distance: {:0.5}]", self.as_str(), distance, ) | ||||
|             } | ||||
|             OrderKind::FillOrKill { price } => { | ||||
|                 write!(f, "[{} | Price: {:0.5}]", self.as_str(), price,) | ||||
|                 write!(f, "[{} | Price: {:0.5}]", self.as_str(), price, ) | ||||
|             } | ||||
|             OrderKind::ImmediateOrCancel { price } => { | ||||
|                 write!(f, "[{} | Price: {:0.5}]", self.as_str(), price,) | ||||
|                 write!(f, "[{} | Price: {:0.5}]", self.as_str(), price, ) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| @ -389,21 +402,50 @@ impl OrderForm { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug, Clone)] | ||||
| #[derive(Debug)] | ||||
| pub struct OrderMetadata { | ||||
|     position_id: Option<u64>, | ||||
|     strategy: Option<Box<dyn OrderStrategy>>, | ||||
| } | ||||
| 
 | ||||
| impl Clone for OrderMetadata { | ||||
|     fn clone(&self) -> Self { | ||||
|         Self { | ||||
|             position_id: self.position_id.clone(), | ||||
|             strategy: self.strategy.as_ref().map(|x| clone_box(&**x)), | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl OrderMetadata { | ||||
|     pub fn with_position_id(position_id: u64) -> Self { | ||||
|         OrderMetadata { | ||||
|             position_id: Some(position_id), | ||||
|     pub fn new() -> Self { | ||||
|         Self { | ||||
|             position_id: None, | ||||
|             strategy: None, | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn with_position_id(mut self, position_id: Option<u64>) -> Self { | ||||
|         self.position_id = position_id; | ||||
|         self | ||||
|     } | ||||
| 
 | ||||
|     pub fn with_strategy(mut self, strategy: Option<Box<dyn OrderStrategy>>) -> Self { | ||||
|         self.strategy = strategy; | ||||
|         self | ||||
|     } | ||||
| 
 | ||||
|     pub fn position_id(&self) -> Option<u64> { | ||||
|         self.position_id | ||||
|     } | ||||
|     pub fn cloned_strategy(&self) -> Option<Box<dyn OrderStrategy>> { | ||||
|         match &self.strategy { | ||||
|             None => { None } | ||||
|             Some(strategy) => { | ||||
|                 Some(clone_box(&**strategy)) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /*************** | ||||
|  | ||||
| @ -282,7 +282,7 @@ impl PositionStrategy for HiddenTrailingStop { | ||||
|                                   OrderKind::Stop { price: stop_loss_price }, | ||||
|                                   position.platform(), | ||||
|                                   position.amount().neg()) | ||||
|                 .with_metadata(Some(OrderMetadata::with_position_id(position.id()))) | ||||
|                 .with_metadata(Some(OrderMetadata::new().with_position_id(Some(position.id())))) | ||||
|         }; | ||||
|         let stop_loss_set = *self.stop_loss_flags.entry(position.id()).or_insert(false); | ||||
| 
 | ||||
| @ -590,7 +590,7 @@ pub struct MarketEnforce { | ||||
| impl Default for MarketEnforce { | ||||
|     fn default() -> Self { | ||||
|         Self { | ||||
|             threshold: 100.0, | ||||
|             threshold: 1.2 / 15.0, | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user