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 {
 | 
			
		||||
@ -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