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…
Reference in New Issue
Block a user