diff --git a/coordinator/src/node/liquidated_positions.rs b/coordinator/src/node/liquidated_positions.rs index e761f23b8..b2b0ac8ea 100644 --- a/coordinator/src/node/liquidated_positions.rs +++ b/coordinator/src/node/liquidated_positions.rs @@ -10,7 +10,6 @@ use commons::MatchState; use commons::NewMarketOrder; use commons::OrderReason; use commons::OrderState; -use commons::OrderType; use commons::Price; use rust_decimal::prelude::FromPrimitive; use rust_decimal::prelude::ToPrimitive; @@ -43,18 +42,8 @@ async fn check_if_positions_need_to_get_liquidated( ) -> Result<()> { let mut conn = node.pool.get()?; let open_positions = db::positions::Position::get_all_open_positions(&mut conn)?; - let open_orders = - orderbook::db::orders::get_all_orders(&mut conn, OrderType::Limit, OrderState::Open, true)?; - - if open_orders.is_empty() { - tracing::warn!("No open orders found."); - return Ok(()); - } - - let best_current_price = commons::best_current_price(&open_orders); - let best_current_price = best_current_price - .get(&ContractSymbol::BtcUsd) - .expect("btc usd prices"); + let best_current_price = + orderbook::db::orders::get_best_price(&mut conn, ContractSymbol::BtcUsd)?; for position in open_positions { let coordinator_liquidation_price = @@ -64,12 +53,12 @@ async fn check_if_positions_need_to_get_liquidated( let trader_liquidation = check_if_position_needs_to_get_liquidated( position.trader_direction, - best_current_price, + &best_current_price, trader_liquidation_price, ); let coordinator_liquidation = check_if_position_needs_to_get_liquidated( position.trader_direction.opposite(), - best_current_price, + &best_current_price, coordinator_liquidation_price, ); diff --git a/coordinator/src/orderbook/db/orders.rs b/coordinator/src/orderbook/db/orders.rs index 6e96cc617..ec94be0eb 100644 --- a/coordinator/src/orderbook/db/orders.rs +++ b/coordinator/src/orderbook/db/orders.rs @@ -13,6 +13,9 @@ use commons::Order as OrderbookOrder; use commons::OrderReason as OrderBookOrderReason; use commons::OrderState as OrderBookOrderState; use commons::OrderType as OrderBookOrderType; +use commons::Price; +use diesel::dsl::max; +use diesel::dsl::min; use diesel::prelude::*; use diesel::result::QueryResult; use diesel::PgConnection; @@ -250,6 +253,50 @@ pub fn all_by_direction_and_type( Ok(orders.into_iter().map(OrderbookOrder::from).collect()) } +pub fn get_best_price( + conn: &mut PgConnection, + contract_symbol: trade::ContractSymbol, +) -> QueryResult { + let best_price = Price { + bid: get_best_bid_price(conn, contract_symbol)?, + ask: get_best_ask_price(conn, contract_symbol)?, + }; + + Ok(best_price) +} + +pub fn get_best_bid_price( + conn: &mut PgConnection, + contract_symbol: trade::ContractSymbol, +) -> QueryResult> { + let price: Option = orders::table + .select(max(orders::price)) + .filter(orders::order_state.eq(OrderState::Open)) + .filter(orders::order_type.eq(OrderType::Limit)) + .filter(orders::direction.eq(Direction::Long)) + .filter(orders::contract_symbol.eq(ContractSymbol::from(contract_symbol))) + .filter(orders::expiry.gt(OffsetDateTime::now_utc())) + .first::>(conn)?; + + Ok(price.map(|bid| Decimal::try_from(bid).expect("to fit into decimal"))) +} + +pub fn get_best_ask_price( + conn: &mut PgConnection, + contract_symbol: trade::ContractSymbol, +) -> QueryResult> { + let price: Option = orders::table + .select(min(orders::price)) + .filter(orders::order_state.eq(OrderState::Open)) + .filter(orders::order_type.eq(OrderType::Limit)) + .filter(orders::direction.eq(Direction::Short)) + .filter(orders::contract_symbol.eq(ContractSymbol::from(contract_symbol))) + .filter(orders::expiry.gt(OffsetDateTime::now_utc())) + .first::>(conn)?; + + Ok(price.map(|ask| Decimal::try_from(ask).expect("to fit into decimal"))) +} + pub fn get_all_orders( conn: &mut PgConnection, order_type: OrderBookOrderType,