Skip to content

Commit

Permalink
chore: introduce market order type
Browse files Browse the repository at this point in the history
  • Loading branch information
bonomat committed Mar 25, 2024
1 parent 35026ba commit b1b4072
Show file tree
Hide file tree
Showing 7 changed files with 85 additions and 17 deletions.
7 changes: 2 additions & 5 deletions coordinator/src/node/expired_positions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::position::models::PositionState;
use anyhow::Context;
use anyhow::Result;
use commons::average_execution_price;
use commons::LimitOrder;
use commons::MarketOrder;
use commons::Match;
use commons::MatchState;
use commons::NewOrder;
Expand Down Expand Up @@ -79,12 +79,9 @@ pub async fn close(node: Node, trading_sender: mpsc::Sender<NewOrderMessage>) ->

tracing::debug!(trader_pk=%position.trader, %position.expiry_timestamp, "Attempting to close expired position");

let new_order = LimitOrder {
let new_order = MarketOrder {
id: uuid::Uuid::new_v4(),
contract_symbol: position.contract_symbol,
// TODO(holzeis): we should not have to set the price for a market order. we propably
// need separate models for a limit and a market order.
price: Decimal::ZERO,
quantity: Decimal::try_from(position.quantity).expect("to fit into decimal"),
trader_id: position.trader,
direction: position.trader_direction.opposite(),
Expand Down
29 changes: 28 additions & 1 deletion coordinator/src/orderbook/db/orders.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use crate::schema::matches;
use crate::schema::orders;
use bitcoin::secp256k1::PublicKey;
use commons::LimitOrder;
use commons::MarketOrder;
use commons::Order as OrderbookOrder;
use commons::OrderReason as OrderBookOrderReason;
use commons::OrderState as OrderBookOrderState;
Expand Down Expand Up @@ -188,6 +189,32 @@ impl From<LimitOrder> for NewOrder {
}
}

impl From<MarketOrder> for NewOrder {
fn from(value: MarketOrder) -> Self {
NewOrder {
trader_order_id: value.id,
// TODO: it would be cool to get rid of this as well
price: 0.0,
trader_id: value.trader_id.to_string(),
direction: value.direction.into(),
quantity: value
.quantity
.round_dp(2)
.to_f32()
.expect("To be able to convert decimal to f32"),
order_type: value.order_type.into(),
expiry: value.expiry,
order_reason: OrderReason::Manual,
contract_symbol: value.contract_symbol.into(),
leverage: value
.leverage
.to_f32()
.expect("To be able to convert decimal to f32"),
stable: value.stable,
}
}
}

pub fn all_limit_orders(conn: &mut PgConnection) -> QueryResult<Vec<OrderbookOrder>> {
let orders = orders::table
.filter(orders::order_type.eq(OrderType::Limit))
Expand Down Expand Up @@ -262,7 +289,7 @@ pub fn insert_limit_order(
pub fn insert_market_order(
conn: &mut PgConnection,
// TODO: use market order here
order: LimitOrder,
order: MarketOrder,
order_reason: OrderBookOrderReason,
) -> QueryResult<OrderbookOrder> {
let new_order = NewOrder {
Expand Down
3 changes: 2 additions & 1 deletion coordinator/src/orderbook/trading.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use bitcoin::Network;
use commons::ChannelOpeningParams;
use commons::FilledWith;
use commons::LimitOrder;
use commons::MarketOrder;
use commons::Match;
use commons::Message;
use commons::Message::TradeError;
Expand Down Expand Up @@ -194,7 +195,7 @@ pub async fn process_new_limit_order(
pub async fn process_new_market_order(
node: Node,
notifier: mpsc::Sender<OrderbookMessage>,
new_order: LimitOrder,
new_order: MarketOrder,
order_reason: OrderReason,
network: Network,
oracle_pk: XOnlyPublicKey,
Expand Down
48 changes: 47 additions & 1 deletion crates/commons/src/order.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ impl NewOrderRequest {
#[derive(Serialize, Deserialize, Clone)]
pub enum NewOrder {
// TODO: introduce MarketOrder
Market(LimitOrder),
Market(MarketOrder),
Limit(LimitOrder),
}

Expand Down Expand Up @@ -83,6 +83,22 @@ impl NewOrder {
}
}

#[derive(Serialize, Deserialize, Clone)]
pub struct MarketOrder {
pub id: Uuid,
pub contract_symbol: ContractSymbol,
#[serde(with = "rust_decimal::serde::float")]
pub quantity: Decimal,
pub trader_id: PublicKey,
pub direction: Direction,
#[serde(with = "rust_decimal::serde::float")]
pub leverage: Decimal,
pub order_type: OrderType,
#[serde(with = "time::serde::timestamp")]
pub expiry: OffsetDateTime,
pub stable: bool,
}

#[derive(Serialize, Deserialize, Clone)]
pub struct LimitOrder {
pub id: Uuid,
Expand Down Expand Up @@ -134,6 +150,36 @@ impl LimitOrder {
}
}

impl MarketOrder {
pub fn message(&self) -> Message {
let mut vec: Vec<u8> = vec![];
let mut id = self.id.as_bytes().to_vec();
let unix_timestamp = self.expiry.unix_timestamp();
let mut seconds = unix_timestamp.to_le_bytes().to_vec();

let symbol = self.contract_symbol.label();
let symbol = symbol.as_bytes();
let order_type = self.order_type.label();
let order_type = order_type.as_bytes();
let direction = self.direction.to_string();
let direction = direction.as_bytes();
let quantity = format!("{:.2}", self.quantity);
let quantity = quantity.as_bytes();
let leverage = format!("{:.2}", self.leverage);
let leverage = leverage.as_bytes();

vec.append(&mut id);
vec.append(&mut seconds);
vec.append(&mut symbol.to_vec());
vec.append(&mut order_type.to_vec());
vec.append(&mut direction.to_vec());
vec.append(&mut quantity.to_vec());
vec.append(&mut leverage.to_vec());

Message::from_hashed_data::<sha256::Hash>(vec.as_slice())
}
}

#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq)]
pub enum OrderType {
#[allow(dead_code)]
Expand Down
2 changes: 1 addition & 1 deletion mobile/native/src/trade/order/handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ pub async fn submit_order(
let orderbook_client = OrderbookClient::new(url);

if let Err(err) = orderbook_client
.post_new_order(order.clone().into(), channel_opening_params)
.post_new_market_order(order.clone().into(), channel_opening_params)
.await
{
let order_id = order.id.clone().to_string();
Expand Down
7 changes: 2 additions & 5 deletions mobile/native/src/trade/order/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,16 +193,13 @@ impl Order {
}
}

impl From<Order> for commons::LimitOrder {
impl From<Order> for commons::MarketOrder {
fn from(order: Order) -> Self {
let quantity = Decimal::try_from(order.quantity).expect("to parse into decimal");
let trader_id = ln_dlc::get_node_pubkey();
commons::LimitOrder {
commons::MarketOrder {
id: order.id,
contract_symbol: order.contract_symbol,
// todo: this is left out intentionally as market orders do not set a price. this field
// should either be an option or differently modelled for a market order.
price: Decimal::ZERO,
quantity,
trader_id,
direction: order.direction,
Expand Down
6 changes: 3 additions & 3 deletions mobile/native/src/trade/order/orderbook_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::commons::reqwest_client;
use crate::ln_dlc::get_node_key;
use anyhow::Result;
use commons::ChannelOpeningParams;
use commons::LimitOrder;
use commons::MarketOrder;
use commons::NewOrder;
use commons::NewOrderRequest;
use reqwest::Url;
Expand All @@ -16,10 +16,10 @@ impl OrderbookClient {
Self { url }
}

pub(crate) async fn post_new_order(
pub(crate) async fn post_new_market_order(
&self,
// TODO: use market order
order: LimitOrder,
order: MarketOrder,
channel_opening_params: Option<ChannelOpeningParams>,
) -> Result<()> {
let secret_key = get_node_key();
Expand Down

0 comments on commit b1b4072

Please sign in to comment.