removed extra function for orderstrategy (for now). order manager update is now working
This commit is contained in:
		
							parent
							
								
									ef618ad754
								
							
						
					
					
						commit
						ac1fd3669f
					
				@ -404,104 +404,52 @@ impl OrderManager {
 | 
			
		||||
        info!("Closing position #{}", position_id);
 | 
			
		||||
 | 
			
		||||
        debug!("Retrieving open orders, positions and current prices...");
 | 
			
		||||
        let (open_orders, order_book, open_positions) = tokio::join!(
 | 
			
		||||
        let (res_open_orders, res_order_book, res_open_positions) = tokio::join!(
 | 
			
		||||
            self.client.active_orders(&self.pair),
 | 
			
		||||
            self.client.order_book(&self.pair),
 | 
			
		||||
            self.client.active_positions(&self.pair)
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        let open_orders = match open_orders {
 | 
			
		||||
            Ok(open_orders) => open_orders,
 | 
			
		||||
            Err(e) => {
 | 
			
		||||
                error!("Could not retrieve open orders: {}", e);
 | 
			
		||||
                return Err(e);
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
        let (open_orders, order_book, open_positions) =
 | 
			
		||||
            (res_open_orders?, res_order_book?, res_open_positions?);
 | 
			
		||||
 | 
			
		||||
        let order_book = match order_book {
 | 
			
		||||
            Ok(order_book) => order_book,
 | 
			
		||||
            Err(e) => {
 | 
			
		||||
                error!("Could not retrieve order book: {}", e);
 | 
			
		||||
                return Err(e);
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        let position = match open_positions {
 | 
			
		||||
            Ok(opt_positions) => {
 | 
			
		||||
                let positions = opt_positions.ok_or::<BoxError>("No open positions".into())?;
 | 
			
		||||
 | 
			
		||||
                positions
 | 
			
		||||
                    .into_iter()
 | 
			
		||||
                    .find(|x| x.id() == position_id)
 | 
			
		||||
                    .ok_or::<BoxError>("Position #{} not found in open positions".into())?
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            Err(e) => {
 | 
			
		||||
                error!("Could not retrieve open positions: {}", e);
 | 
			
		||||
                return Err(e);
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
        let position = open_positions
 | 
			
		||||
            .ok_or("No open positions!")?
 | 
			
		||||
            .into_iter()
 | 
			
		||||
            .find(|x| x.id() == position_id)
 | 
			
		||||
            .ok_or("Position #{} not found in open positions.")?;
 | 
			
		||||
 | 
			
		||||
        let opt_position_order = open_orders
 | 
			
		||||
            .iter()
 | 
			
		||||
            .find(|x| x.current_form.amount().neg() == position.amount());
 | 
			
		||||
 | 
			
		||||
        // 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 opt_position_order {
 | 
			
		||||
        // If so, don't do anything since the order is taken care of
 | 
			
		||||
        // in the update phase.
 | 
			
		||||
        // If no order is open, send an undercut limit order at the best current price.
 | 
			
		||||
        if let None = opt_position_order {
 | 
			
		||||
            // No open order, undercutting best price with limit order
 | 
			
		||||
            None => {
 | 
			
		||||
                let closing_price = self.best_closing_price(&position, &order_book);
 | 
			
		||||
            let closing_price = self.best_closing_price(&position, &order_book);
 | 
			
		||||
 | 
			
		||||
                // TODO: hardocoded platform to Margin!
 | 
			
		||||
                let order_form = OrderForm::new(
 | 
			
		||||
                    self.pair.clone(),
 | 
			
		||||
                    OrderKind::Limit {
 | 
			
		||||
                        price: closing_price,
 | 
			
		||||
                        amount: position.amount().neg(),
 | 
			
		||||
                    },
 | 
			
		||||
                    TradingPlatform::Margin,
 | 
			
		||||
            // TODO: hardcoded platform to Margin!
 | 
			
		||||
            let order_form = OrderForm::new(
 | 
			
		||||
                self.pair.clone(),
 | 
			
		||||
                OrderKind::Limit {
 | 
			
		||||
                    price: closing_price,
 | 
			
		||||
                    amount: position.amount().neg(),
 | 
			
		||||
                },
 | 
			
		||||
                TradingPlatform::Margin,
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            info!("Submitting {} order", order_form.kind());
 | 
			
		||||
            if let Err(e) = self.client.submit_order(&order_form).await {
 | 
			
		||||
                error!(
 | 
			
		||||
                    "Could not submit {} to close position #{}: {}",
 | 
			
		||||
                    order_form.kind(),
 | 
			
		||||
                    position.id(),
 | 
			
		||||
                    e
 | 
			
		||||
                );
 | 
			
		||||
 | 
			
		||||
                info!("Submitting {} order", order_form.kind());
 | 
			
		||||
                if let Err(e) = self.client.submit_order(&order_form).await {
 | 
			
		||||
                    error!(
 | 
			
		||||
                        "Could not submit {} to close position #{}: {}",
 | 
			
		||||
                        order_form.kind(),
 | 
			
		||||
                        position.id(),
 | 
			
		||||
                        e
 | 
			
		||||
                    );
 | 
			
		||||
                    return Err(e);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            Some(active_order) => {
 | 
			
		||||
                debug!(
 | 
			
		||||
                    "Found open order, calling \"{}\" strategy.",
 | 
			
		||||
                    self.strategy.name()
 | 
			
		||||
                );
 | 
			
		||||
 | 
			
		||||
                let (_, strat_messages) =
 | 
			
		||||
                    self.strategy
 | 
			
		||||
                        .on_position_order(active_order, &position, &order_book)?;
 | 
			
		||||
 | 
			
		||||
                if let Some(messages) = strat_messages {
 | 
			
		||||
                    for m in messages {
 | 
			
		||||
                        match m {
 | 
			
		||||
                            Message::SubmitOrder { order } => {
 | 
			
		||||
                                info!("Closing open order.");
 | 
			
		||||
                                info!("Cancelling open order #{}", active_order.id);
 | 
			
		||||
                                self.client.cancel_order(active_order).await?;
 | 
			
		||||
 | 
			
		||||
                                info!("Submitting {}...", order.kind());
 | 
			
		||||
                                self.client.submit_order(&order).await?;
 | 
			
		||||
                            }
 | 
			
		||||
                            _ => {
 | 
			
		||||
                                debug!("Received unsupported message from order strategy. Unimplemented.")
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                return Err(e);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -512,11 +460,42 @@ impl OrderManager {
 | 
			
		||||
    pub async fn update(&self) -> Result<OptionUpdate, BoxError> {
 | 
			
		||||
        trace!("\t[OrderManager] Updating {}", self.pair);
 | 
			
		||||
 | 
			
		||||
        let (open_orders, opt_open_positions) = tokio::join!(
 | 
			
		||||
        let (res_open_orders, res_order_book) = tokio::join!(
 | 
			
		||||
            self.client.active_orders(&self.pair),
 | 
			
		||||
            self.client.active_positions(&self.pair)
 | 
			
		||||
            self.client.order_book(&self.pair)
 | 
			
		||||
        );
 | 
			
		||||
        let (_open_orders, _opt_open_positions) = (open_orders?, opt_open_positions?);
 | 
			
		||||
 | 
			
		||||
        let (open_orders, order_book) = (res_open_orders?, res_order_book?);
 | 
			
		||||
 | 
			
		||||
        for active_order in open_orders {
 | 
			
		||||
            debug!(
 | 
			
		||||
                "Found open order, calling \"{}\" strategy.",
 | 
			
		||||
                self.strategy.name()
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            let (_, strat_messages) = self.strategy.on_open_order(&active_order, &order_book)?;
 | 
			
		||||
 | 
			
		||||
            if let Some(messages) = strat_messages {
 | 
			
		||||
                for m in messages {
 | 
			
		||||
                    match m {
 | 
			
		||||
                        Message::SubmitOrder { order: order_form } => {
 | 
			
		||||
                            info!("Closing open order...");
 | 
			
		||||
                            info!("\tCancelling open order #{}", &active_order.id);
 | 
			
		||||
                            self.client.cancel_order(&active_order).await?;
 | 
			
		||||
 | 
			
		||||
                            info!("\tSubmitting {}...", order_form.kind());
 | 
			
		||||
                            self.client.submit_order(&order_form).await?;
 | 
			
		||||
                            info!("Done!");
 | 
			
		||||
                        }
 | 
			
		||||
                        _ => {
 | 
			
		||||
                            debug!(
 | 
			
		||||
                                "Received unsupported message from order strategy. Unimplemented."
 | 
			
		||||
                            )
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        Ok((None, None))
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -5,6 +5,7 @@ use dyn_clone::DynClone;
 | 
			
		||||
use log::info;
 | 
			
		||||
 | 
			
		||||
use crate::events::{Event, EventKind, EventMetadata, Message};
 | 
			
		||||
use crate::managers::OptionUpdate;
 | 
			
		||||
use crate::models::{
 | 
			
		||||
    ActiveOrder, OrderBook, OrderBookEntry, OrderForm, OrderKind, Position, PositionProfitState,
 | 
			
		||||
    PositionState, TradingPlatform,
 | 
			
		||||
@ -42,15 +43,19 @@ pub trait OrderStrategy: DynClone + Send + Sync {
 | 
			
		||||
    fn name(&self) -> String;
 | 
			
		||||
    /// This method is called when the OrderManager checks the open orders on a new tick.
 | 
			
		||||
    /// It should manage if some orders have to be closed or keep open.
 | 
			
		||||
    fn on_open_order(&self);
 | 
			
		||||
    /// This method is called when the OrderManager is requested to close
 | 
			
		||||
    /// a position that has an open order associated to it.
 | 
			
		||||
    fn on_position_order(
 | 
			
		||||
    fn on_open_order(
 | 
			
		||||
        &self,
 | 
			
		||||
        order: &ActiveOrder,
 | 
			
		||||
        open_position: &Position,
 | 
			
		||||
        order_book: &OrderBook,
 | 
			
		||||
    ) -> Result<(Option<Vec<Event>>, Option<Vec<Message>>), BoxError>;
 | 
			
		||||
    ) -> Result<OptionUpdate, BoxError>;
 | 
			
		||||
    // /// This method is called when the OrderManager is requested to close
 | 
			
		||||
    // /// a position that has an open order associated to it.
 | 
			
		||||
    // fn on_position_order(
 | 
			
		||||
    //     &self,
 | 
			
		||||
    //     order: &ActiveOrder,
 | 
			
		||||
    //     open_position: &Position,
 | 
			
		||||
    //     order_book: &OrderBook,
 | 
			
		||||
    // ) -> Result<OptionUpdate, BoxError>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Debug for dyn OrderStrategy {
 | 
			
		||||
@ -81,12 +86,6 @@ impl TrailingStop {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn update_stop_percentage(&mut self, position: &Position) {
 | 
			
		||||
        info!(
 | 
			
		||||
            "\tState: {:?} | PL%: {:0.2}",
 | 
			
		||||
            position.profit_state().unwrap(),
 | 
			
		||||
            position.pl_perc()
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        if let Some(profit_state) = position.profit_state() {
 | 
			
		||||
            let profit_state_delta = match profit_state {
 | 
			
		||||
                PositionProfitState::MinimumProfit => Some(0.2),
 | 
			
		||||
@ -95,12 +94,6 @@ impl TrailingStop {
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            if let Some(profit_state_delta) = profit_state_delta {
 | 
			
		||||
                println!(
 | 
			
		||||
                    "PL%: {:0.2} | Delta: {}",
 | 
			
		||||
                    position.pl_perc(),
 | 
			
		||||
                    profit_state_delta
 | 
			
		||||
                );
 | 
			
		||||
 | 
			
		||||
                let current_stop_percentage = position.pl_perc() - profit_state_delta;
 | 
			
		||||
 | 
			
		||||
                match profit_state {
 | 
			
		||||
@ -121,6 +114,12 @@ impl TrailingStop {
 | 
			
		||||
                    _ => {}
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            info!(
 | 
			
		||||
                "\tState: {:?} | PL%: {:0.2} | Stop: {:0.2}",
 | 
			
		||||
                position.profit_state().unwrap(),
 | 
			
		||||
                position.pl_perc(),
 | 
			
		||||
                self.stop_percentages.get(&position.id()).unwrap_or(&0.0)
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -223,6 +222,7 @@ impl PositionStrategy for TrailingStop {
 | 
			
		||||
        if let Some(profit_state) = position.profit_state() {
 | 
			
		||||
            match profit_state {
 | 
			
		||||
                PositionProfitState::Critical => {
 | 
			
		||||
                    info!("Maximum loss reached. Closing position.");
 | 
			
		||||
                    return (position, None, Some(vec![close_message]));
 | 
			
		||||
                }
 | 
			
		||||
                _ => {}
 | 
			
		||||
@ -267,16 +267,11 @@ impl OrderStrategy for FastOrderStrategy {
 | 
			
		||||
        "Fast order strategy".into()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn on_open_order(&self) {
 | 
			
		||||
        unimplemented!()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn on_position_order(
 | 
			
		||||
    fn on_open_order(
 | 
			
		||||
        &self,
 | 
			
		||||
        order: &ActiveOrder,
 | 
			
		||||
        _: &Position,
 | 
			
		||||
        order_book: &OrderBook,
 | 
			
		||||
    ) -> Result<(Option<Vec<Event>>, Option<Vec<Message>>), BoxError> {
 | 
			
		||||
    ) -> Result<OptionUpdate, BoxError> {
 | 
			
		||||
        let mut messages = vec![];
 | 
			
		||||
 | 
			
		||||
        // long
 | 
			
		||||
@ -310,4 +305,44 @@ impl OrderStrategy for FastOrderStrategy {
 | 
			
		||||
 | 
			
		||||
        Ok((None, (!messages.is_empty()).then_some(messages)))
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // fn on_position_order(
 | 
			
		||||
    //     &self,
 | 
			
		||||
    //     order: &ActiveOrder,
 | 
			
		||||
    //     _: &Position,
 | 
			
		||||
    //     order_book: &OrderBook,
 | 
			
		||||
    // ) -> Result<OptionUpdate, BoxError> {
 | 
			
		||||
    //     let mut messages = vec![];
 | 
			
		||||
    //
 | 
			
		||||
    //     // long
 | 
			
		||||
    //     let offer_comparison = {
 | 
			
		||||
    //         if order.current_form.amount() > 0.0 {
 | 
			
		||||
    //             order_book.highest_bid()
 | 
			
		||||
    //         } else {
 | 
			
		||||
    //             order_book.lowest_ask()
 | 
			
		||||
    //         }
 | 
			
		||||
    //     };
 | 
			
		||||
    //
 | 
			
		||||
    //     // if the best offer is higher than our threshold,
 | 
			
		||||
    //     // ask the manager to close the position with a market order
 | 
			
		||||
    //     let order_price = order
 | 
			
		||||
    //         .current_form
 | 
			
		||||
    //         .price()
 | 
			
		||||
    //         .ok_or("The active order does not have a price!")?;
 | 
			
		||||
    //     let delta = (1.0 - (offer_comparison / order_price)).abs() * 100.0;
 | 
			
		||||
    //
 | 
			
		||||
    //     if delta > self.threshold {
 | 
			
		||||
    //         messages.push(Message::SubmitOrder {
 | 
			
		||||
    //             order: OrderForm::new(
 | 
			
		||||
    //                 order.symbol.clone(),
 | 
			
		||||
    //                 OrderKind::Market {
 | 
			
		||||
    //                     amount: order.current_form.amount(),
 | 
			
		||||
    //                 },
 | 
			
		||||
    //                 order.current_form.platform().clone(),
 | 
			
		||||
    //             ),
 | 
			
		||||
    //         })
 | 
			
		||||
    //     }
 | 
			
		||||
    //
 | 
			
		||||
    //     Ok((None, (!messages.is_empty()).then_some(messages)))
 | 
			
		||||
    // }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user