retrieving updated information on open orders before calling strategy
This commit is contained in:
parent
5b84c99703
commit
9b92d38318
@ -155,8 +155,10 @@ impl Connector for BitfinexConnector {
|
|||||||
Ok(ticker)
|
Ok(ticker)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn active_orders(&self, pair: &SymbolPair) -> Result<Vec<ActiveOrder>, BoxError> {
|
async fn active_orders(&self, _: &SymbolPair) -> Result<Vec<ActiveOrder>, BoxError> {
|
||||||
unimplemented!()
|
let response = self.bfx.orders.active_orders().await?;
|
||||||
|
|
||||||
|
Ok(response.iter().map(Into::into).collect())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn submit_order(&self, order: &OrderForm) -> Result<ActiveOrder, BoxError> {
|
async fn submit_order(&self, order: &OrderForm) -> Result<ActiveOrder, BoxError> {
|
||||||
@ -321,6 +323,21 @@ impl From<&bitfinex::orders::OrderResponse> for TradingPlatform {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<&bitfinex::orders::ActiveOrder> for TradingPlatform {
|
||||||
|
fn from(response: &bitfinex::orders::ActiveOrder) -> Self {
|
||||||
|
match response.order_type() {
|
||||||
|
bitfinex::orders::OrderKind::Limit
|
||||||
|
| bitfinex::orders::OrderKind::Market
|
||||||
|
| bitfinex::orders::OrderKind::StopLimit
|
||||||
|
| bitfinex::orders::OrderKind::Stop
|
||||||
|
| bitfinex::orders::OrderKind::TrailingStop
|
||||||
|
| bitfinex::orders::OrderKind::Fok
|
||||||
|
| bitfinex::orders::OrderKind::Ioc => Self::Margin,
|
||||||
|
_ => Self::Exchange,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<&bitfinex::orders::OrderResponse> for OrderKind {
|
impl From<&bitfinex::orders::OrderResponse> for OrderKind {
|
||||||
fn from(response: &OrderResponse) -> Self {
|
fn from(response: &OrderResponse) -> Self {
|
||||||
match response.order_type() {
|
match response.order_type() {
|
||||||
@ -345,11 +362,11 @@ impl From<&bitfinex::orders::OrderResponse> for OrderKind {
|
|||||||
| bitfinex::orders::OrderKind::ExchangeStopLimit => Self::StopLimit {
|
| bitfinex::orders::OrderKind::ExchangeStopLimit => Self::StopLimit {
|
||||||
price: response.price(),
|
price: response.price(),
|
||||||
amount: response.amount(),
|
amount: response.amount(),
|
||||||
limit_price: response.price_aux_limit(),
|
limit_price: response.price_aux_limit().expect("Limit price not found!"),
|
||||||
},
|
},
|
||||||
bitfinex::orders::OrderKind::TrailingStop
|
bitfinex::orders::OrderKind::TrailingStop
|
||||||
| bitfinex::orders::OrderKind::ExchangeTrailingStop => Self::TrailingStop {
|
| bitfinex::orders::OrderKind::ExchangeTrailingStop => Self::TrailingStop {
|
||||||
distance: response.price_trailing(),
|
distance: response.price_trailing().expect("Distance not found!"),
|
||||||
amount: response.amount(),
|
amount: response.amount(),
|
||||||
},
|
},
|
||||||
bitfinex::orders::OrderKind::Fok | bitfinex::orders::OrderKind::ExchangeFok => {
|
bitfinex::orders::OrderKind::Fok | bitfinex::orders::OrderKind::ExchangeFok => {
|
||||||
@ -368,6 +385,70 @@ impl From<&bitfinex::orders::OrderResponse> for OrderKind {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<&bitfinex::orders::ActiveOrder> for OrderKind {
|
||||||
|
fn from(response: &bitfinex::orders::ActiveOrder) -> Self {
|
||||||
|
match response.order_type() {
|
||||||
|
bitfinex::orders::OrderKind::Limit | bitfinex::orders::OrderKind::ExchangeLimit => {
|
||||||
|
Self::Limit {
|
||||||
|
price: response.price(),
|
||||||
|
amount: response.amount(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bitfinex::orders::OrderKind::Market | bitfinex::orders::OrderKind::ExchangeMarket => {
|
||||||
|
Self::Market {
|
||||||
|
amount: response.amount(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bitfinex::orders::OrderKind::Stop | bitfinex::orders::OrderKind::ExchangeStop => {
|
||||||
|
Self::Stop {
|
||||||
|
price: response.price(),
|
||||||
|
amount: response.amount(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bitfinex::orders::OrderKind::StopLimit
|
||||||
|
| bitfinex::orders::OrderKind::ExchangeStopLimit => Self::StopLimit {
|
||||||
|
price: response.price(),
|
||||||
|
amount: response.amount(),
|
||||||
|
limit_price: response.price_aux_limit().expect("Limit price not found!"),
|
||||||
|
},
|
||||||
|
bitfinex::orders::OrderKind::TrailingStop
|
||||||
|
| bitfinex::orders::OrderKind::ExchangeTrailingStop => Self::TrailingStop {
|
||||||
|
distance: response.price_trailing().expect("Distance not found!"),
|
||||||
|
amount: response.amount(),
|
||||||
|
},
|
||||||
|
bitfinex::orders::OrderKind::Fok | bitfinex::orders::OrderKind::ExchangeFok => {
|
||||||
|
Self::FillOrKill {
|
||||||
|
price: response.price(),
|
||||||
|
amount: response.amount(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bitfinex::orders::OrderKind::Ioc | bitfinex::orders::OrderKind::ExchangeIoc => {
|
||||||
|
Self::ImmediateOrCancel {
|
||||||
|
price: response.price(),
|
||||||
|
amount: response.amount(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&bitfinex::orders::ActiveOrder> for ActiveOrder {
|
||||||
|
fn from(order: &bitfinex::orders::ActiveOrder) -> Self {
|
||||||
|
let pair = SymbolPair::from_str(&order.symbol()).expect("Invalid symbol!");
|
||||||
|
|
||||||
|
Self {
|
||||||
|
exchange: Exchange::Bitfinex,
|
||||||
|
id: order.id(),
|
||||||
|
group_id: order.group_id().map(|x| x as u64),
|
||||||
|
client_id: Some(order.client_id()),
|
||||||
|
symbol: pair.clone(),
|
||||||
|
current_form: OrderForm::new(pair, order.into(), order.into()),
|
||||||
|
creation_timestamp: order.creation_timestamp(),
|
||||||
|
update_timestamp: order.update_timestamp(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<TradingPairTicker> for PriceTicker {
|
impl From<TradingPairTicker> for PriceTicker {
|
||||||
fn from(t: TradingPairTicker) -> Self {
|
fn from(t: TradingPairTicker) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
@ -319,7 +319,8 @@ impl PositionManager {
|
|||||||
* ORDERS
|
* ORDERS
|
||||||
******************/
|
******************/
|
||||||
|
|
||||||
pub type TrackedPositionsMap = HashMap<u64, ActiveOrder>;
|
// Position ID: Order ID
|
||||||
|
pub type TrackedPositionsMap = HashMap<u64, u64>;
|
||||||
|
|
||||||
pub struct OrderManagerHandle {
|
pub struct OrderManagerHandle {
|
||||||
sender: Sender<ActorMessage>,
|
sender: Sender<ActorMessage>,
|
||||||
@ -405,7 +406,7 @@ impl OrderManager {
|
|||||||
pub async fn handle_message(&mut self, msg: ActorMessage) -> Result<(), BoxError> {
|
pub async fn handle_message(&mut self, msg: ActorMessage) -> Result<(), BoxError> {
|
||||||
match msg.message {
|
match msg.message {
|
||||||
Message::Update { .. } => {
|
Message::Update { .. } => {
|
||||||
self.update();
|
self.update().await?;
|
||||||
}
|
}
|
||||||
Message::ClosePosition {
|
Message::ClosePosition {
|
||||||
position,
|
position,
|
||||||
@ -424,39 +425,23 @@ impl OrderManager {
|
|||||||
position: &Position,
|
position: &Position,
|
||||||
order_form: &OrderForm,
|
order_form: &OrderForm,
|
||||||
) -> Result<(), BoxError> {
|
) -> Result<(), BoxError> {
|
||||||
let open_order = self.tracked_positions.get(&position.id());
|
info!("Closing position #{}", position.id());
|
||||||
|
|
||||||
|
debug!("Retrieving open orders...");
|
||||||
|
let open_orders = self.client.active_orders(&self.pair).await?;
|
||||||
|
|
||||||
|
let opt_position_order = open_orders
|
||||||
|
.iter()
|
||||||
|
.find(|x| x.current_form.amount().neg() == position.amount());
|
||||||
|
|
||||||
debug!("Closing position #{}", position.id());
|
|
||||||
debug!("Getting current prices...");
|
debug!("Getting current prices...");
|
||||||
let order_book = self.client.order_book(&self.pair).await?;
|
let order_book = self.client.order_book(&self.pair).await?;
|
||||||
|
|
||||||
// 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 opt_position_order {
|
||||||
Some(open_order) => {
|
// No open order, undercutting best price with limit order
|
||||||
debug!("There is an open order. Calling strategy.");
|
|
||||||
let (_, messages) =
|
|
||||||
self.strategy
|
|
||||||
.on_position_close(open_order, position, &order_book)?;
|
|
||||||
|
|
||||||
if let Some(messages) = messages {
|
|
||||||
for m in messages {
|
|
||||||
match m {
|
|
||||||
Message::ClosePosition { order_form, .. } => {
|
|
||||||
info!("Closing open order with a {} order", order_form.kind());
|
|
||||||
if let Ok(_) = self.client.submit_order(&order_form).await {
|
|
||||||
info!("Cancelling open order #{}", open_order.id);
|
|
||||||
self.client.cancel_order(open_order).await?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
debug!("Received unsupported message from order strategy. Unimplemented.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None => {
|
None => {
|
||||||
let closing_price = self.best_closing_price(&position, &order_book);
|
let closing_price = self.best_closing_price(&position, &order_book);
|
||||||
|
|
||||||
@ -471,16 +456,50 @@ impl OrderManager {
|
|||||||
);
|
);
|
||||||
|
|
||||||
info!("Submitting {} order", order_form.kind());
|
info!("Submitting {} order", order_form.kind());
|
||||||
let active_order = self.client.submit_order(&order_form).await?;
|
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()
|
||||||
|
);
|
||||||
|
|
||||||
self.tracked_positions.insert(position.id(), active_order);
|
let (_, strat_messages) =
|
||||||
|
self.strategy
|
||||||
|
.on_position_close(active_order, position, &order_book)?;
|
||||||
|
|
||||||
|
if let Some(messages) = strat_messages {
|
||||||
|
for m in messages {
|
||||||
|
match m {
|
||||||
|
Message::ClosePosition { order_form, .. } => {
|
||||||
|
info!("Closing open order with a {} order", order_form.kind());
|
||||||
|
|
||||||
|
if let Ok(_) = self.client.submit_order(&order_form).await {
|
||||||
|
info!("Cancelling open order #{}", active_order.id);
|
||||||
|
self.client.cancel_order(active_order).await?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
debug!("Received unsupported message from order strategy. Unimplemented.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update(&self) -> Result<OptionUpdate, BoxError> {
|
pub async fn update(&self) -> Result<OptionUpdate, BoxError> {
|
||||||
// TODO: implement me
|
// TODO: implement me
|
||||||
Ok((None, None))
|
Ok((None, None))
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user