From 1cba37296d970095c1504d43e67d5dbdf98df5dd Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Sun, 2 Aug 2026 06:05:15 +0200 Subject: [PATCH] Working order --- pulse-sdk/src/general.rs | 2 +- pulse-sdk/src/lib.rs | 19 ++++++++++++++++++- src/engine/engine/execution.rs | 21 +++++++++++++-------- src/engine/engine/risk.rs | 9 ++++----- 4 files changed, 36 insertions(+), 15 deletions(-) diff --git a/pulse-sdk/src/general.rs b/pulse-sdk/src/general.rs index 0de0dfe..ec178ec 100644 --- a/pulse-sdk/src/general.rs +++ b/pulse-sdk/src/general.rs @@ -51,7 +51,7 @@ pub struct Signal { #[derive(Debug, Clone, Copy, serde::Serialize, serde::Deserialize)] pub struct EngineOrder { - pub risk_equity: Decimal, + pub risk: Decimal, pub size: Decimal, pub stop_loss: Decimal, diff --git a/pulse-sdk/src/lib.rs b/pulse-sdk/src/lib.rs index af0744e..340dfb9 100644 --- a/pulse-sdk/src/lib.rs +++ b/pulse-sdk/src/lib.rs @@ -3,6 +3,8 @@ pub mod strategy; pub mod terminal; pub use hypersdk; +use hypersdk::Decimal; +use rust_decimal::RoundingStrategy; use tokio::io::{AsyncReadExt, AsyncWriteExt}; use crate::{general::LogKind, strategy::StrategyEngineMessage}; @@ -10,9 +12,9 @@ use crate::{general::LogKind, strategy::StrategyEngineMessage}; pub mod prelude { pub use crate::Strategy; pub use crate::general::*; - pub use crate::server_path; pub use crate::strategy::*; pub use crate::terminal::*; + pub use crate::{round_price, server_path}; pub use hypersdk; pub use postcard; @@ -26,6 +28,21 @@ pub fn map_postcard_err(res: postcard::Result) -> tokio::io::Result { res.map_err(|e| tokio::io::Error::new(std::io::ErrorKind::Other, e)) } +pub fn round_price(price: Decimal) -> Decimal { + let digits = price.trunc().to_string().len() as u32; + let decimal_places = 5_i32 - digits as i32; + + if decimal_places < 0 { + let factor = Decimal::from(10_u64.pow((-decimal_places) as u32)); + (price / factor).round() * factor + } else { + price.round_dp_with_strategy( + decimal_places as u32, + RoundingStrategy::MidpointAwayFromZero, + ) + } +} + pub async fn send_raw(data: &[u8]) -> tokio::io::Result<()> { let mut stdout = tokio::io::stdout(); diff --git a/src/engine/engine/execution.rs b/src/engine/engine/execution.rs index 69e4569..96279ec 100644 --- a/src/engine/engine/execution.rs +++ b/src/engine/engine/execution.rs @@ -37,13 +37,16 @@ impl Engine { *size = Some(engine_order); + let limit_px = round_price(signal.entry_price); + let sz = round_price(engine_order.size / signal.entry_price); + let order = BatchOrder { orders: vec![ OrderRequest { asset: asset_id, is_buy: matches!(signal.side, Side::Bid), - limit_px: signal.entry_price, - sz: engine_order.size, + limit_px, + sz, reduce_only: false, order_type: OrderTypePlacement::Limit { tif: TimeInForce::Gtc, @@ -53,12 +56,12 @@ impl Engine { OrderRequest { asset: asset_id, is_buy: !matches!(signal.side, Side::Bid), - limit_px: signal.entry_price, - sz: engine_order.size, + limit_px, + sz, reduce_only: true, order_type: OrderTypePlacement::Trigger { is_market: true, - trigger_px: signal.take_profit, + trigger_px: round_price(signal.take_profit), tpsl: hypercore::TpSl::Tp, }, cloid: engine_order.take_profit, @@ -66,12 +69,12 @@ impl Engine { OrderRequest { asset: asset_id, is_buy: !matches!(signal.side, Side::Bid), - limit_px: signal.entry_price, - sz: engine_order.size, + limit_px, + sz, reduce_only: true, order_type: OrderTypePlacement::Trigger { is_market: true, - trigger_px: engine_order.stop_loss, + trigger_px: round_price(engine_order.stop_loss), tpsl: hypercore::TpSl::Sl, }, cloid: engine_order.stop_loss_id, @@ -81,6 +84,8 @@ impl Engine { builder: None, }; + println!("{order:?}"); + let nonce = NonceHandler::default(); match client diff --git a/src/engine/engine/risk.rs b/src/engine/engine/risk.rs index d217d16..07e4ff8 100644 --- a/src/engine/engine/risk.rs +++ b/src/engine/engine/risk.rs @@ -87,7 +87,7 @@ impl RiskEngine { for r in rm { let order = self.orders.lock().await.remove(r); - self.state.lock().await.pnl -= order.risk_equity; + self.state.lock().await.pnl -= order.risk; } } } @@ -157,15 +157,14 @@ impl RiskEngine { take_profit: Cloid::random(), stop_loss_id: Cloid::random(), - size: size.round_dp(3), - risk_equity: risk, + size, + risk, stop_loss: if matches!(signal.side, Side::Ask) { signal.entry_price + sl_distance } else { signal.entry_price - sl_distance - } - .round_dp(3), + }, }) }