From 87e3c2b9647afdc166134e471b657dbf9f6acc00 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Thu, 30 Jul 2026 04:44:21 +0200 Subject: [PATCH] Tidy up --- pulse-sdk/src/general.rs | 20 +++--- pulse-sdk/src/lib.rs | 4 +- pulse-sdk/src/terminal.rs | 46 ++------------ pulse-sdk/src/units.rs | 110 --------------------------------- src/engine/engine/execution.rs | 24 +++---- src/engine/engine/mod.rs | 11 ++-- src/engine/fetch.rs | 8 +-- src/terminal/formatting.rs | 108 ++++++++++++++++++-------------- 8 files changed, 95 insertions(+), 236 deletions(-) delete mode 100644 pulse-sdk/src/units.rs diff --git a/pulse-sdk/src/general.rs b/pulse-sdk/src/general.rs index f36fc66..1df15fd 100644 --- a/pulse-sdk/src/general.rs +++ b/pulse-sdk/src/general.rs @@ -1,7 +1,6 @@ +use hypersdk::hypercore::Side; use rust_decimal::Decimal; -use crate::units::{Direction, Symbol, USD}; - #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] pub enum MarketTrend { Bullish, @@ -20,12 +19,11 @@ pub enum LogKind { #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] pub struct Signal { pub symbol: String, - pub kind: Direction, + pub side: Side, pub confidence: f32, - pub size: Decimal, - pub price: USD, - pub take_profit: USD, - pub stop_loss: USD, + pub price: Decimal, + pub take_profit: Decimal, + pub stop_loss: Decimal, } #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] @@ -37,10 +35,10 @@ pub struct EventLog { #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] pub struct Position { - pub symbol: Symbol, - pub size: f64, - pub entry_price: USD, - pub profit: USD, + pub symbol: String, + pub size: Decimal, + pub entry_price: Decimal, + pub pnl: Decimal, } impl std::fmt::Display for MarketTrend { diff --git a/pulse-sdk/src/lib.rs b/pulse-sdk/src/lib.rs index 3ddcbb7..24b83cb 100644 --- a/pulse-sdk/src/lib.rs +++ b/pulse-sdk/src/lib.rs @@ -1,7 +1,6 @@ pub mod general; pub mod strategy; pub mod terminal; -pub mod units; pub use hypersdk; use tokio::io::{AsyncReadExt, AsyncWriteExt}; @@ -10,10 +9,9 @@ use crate::strategy::StrategyEngineMessage; pub mod prelude { pub use crate::general::*; - pub use crate::strategy::*; pub use crate::server_path; + pub use crate::strategy::*; pub use crate::terminal::*; - pub use crate::units::*; pub use hypersdk; pub use postcard; diff --git a/pulse-sdk/src/terminal.rs b/pulse-sdk/src/terminal.rs index efac397..67e5ac6 100644 --- a/pulse-sdk/src/terminal.rs +++ b/pulse-sdk/src/terminal.rs @@ -1,7 +1,6 @@ use crate::{ - general::{EventLog, MarketTrend, Position, Signal}, + general::{EventLog, Position, Signal}, strategy::StrategyManifest, - units::{Symbol, USD, Volatility}, }; use hypersdk::{Decimal, hypercore::CandleInterval}; @@ -39,37 +38,10 @@ pub enum TerminalClientMessage { #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] pub struct MarketItem { - pub symbol: Symbol, - pub price: USD, + pub symbol: String, + pub price: Decimal, pub trend: Decimal, - pub volume_24h: USD, -} - -#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] -pub struct MarketOverview { - pub trend: MarketTrend, - pub volatility: Volatility, - pub pressure: f64, - pub alerts: Vec, -} - -#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] -pub enum AlertLevel { - High, - Medium, - Low, -} -#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] -pub struct Alert { - pub level: AlertLevel, - pub message: String, -} - -#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] -pub struct Balance { - pub asset: String, - pub amount: f64, - pub value: f64, + pub volume_24h: Decimal, } #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] @@ -116,16 +88,6 @@ pub struct Strategy { pub cooldown: CandleInterval, } -impl std::fmt::Display for AlertLevel { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Self::High => write!(f, "H"), - Self::Medium => write!(f, "M"), - Self::Low => write!(f, "L"), - } - } -} - impl std::fmt::Display for Mode { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { diff --git a/pulse-sdk/src/units.rs b/pulse-sdk/src/units.rs deleted file mode 100644 index d598482..0000000 --- a/pulse-sdk/src/units.rs +++ /dev/null @@ -1,110 +0,0 @@ -use rust_decimal::Decimal; - -#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] -pub struct Symbol(pub String); - -#[derive(Debug, Clone, Copy, serde::Serialize, serde::Deserialize)] -pub struct USD(pub Decimal); - -#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] -pub enum Direction { - Buy, - Sell, -} - -#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] -pub enum Volatility { - Low, - Medium, - High, -} - -impl std::fmt::Display for Symbol { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "\x1b[35m{}\x1b[0m", self.0) - } -} - -impl std::fmt::Display for USD { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - if self.0.is_sign_positive() { - write!(f, "\x1b[32m${}\x1b[0m", format_f64(self.0.as_f64())) - } else { - write!(f, "\x1b[31m${}\x1b[0m", format_f64(self.0.as_f64())) - } - } -} - -pub fn format_f64(value: f64) -> String { - let abs = value.abs(); - - let (divisor, suffix) = if abs >= 1_000_000_000.0 { - (1_000_000_000.0, "B") - } else if abs >= 1_000_000.0 { - (1_000_000.0, "M") - } else if abs >= 1_000.0 { - (1_000.0, "K") - } else { - (1.0, "") - }; - - if divisor != 1.0 { - let formatted = value / divisor; - - // Remove unnecessary trailing zeros - let s = format!("{:.2}", formatted) - .trim_end_matches('0') - .trim_end_matches('.') - .to_string(); - - return format!("{}{}", s, suffix); - } - - let val = format!("{:.3}", value); - let parts: Vec<&str> = val.split('.').collect(); - - let int = parts[0].to_string(); - let negative = int.starts_with('-'); - - let start = if negative { 1 } else { 0 }; - let mut result = String::new(); - - for (i, c) in int[start..].chars().rev().enumerate() { - if i > 0 && i % 3 == 0 { - result.push(','); - } - result.push(c); - } - - let mut formatted: String = result.chars().rev().collect(); - - if negative { - formatted.insert(0, '-'); - } - - if parts.len() > 1 { - formatted.push('.'); - formatted.push_str(parts[1]); - } - - formatted -} - -impl std::fmt::Display for Direction { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Self::Buy => write!(f, "BUY"), - Self::Sell => write!(f, "SELL"), - } - } -} - -impl std::fmt::Display for Volatility { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Self::Low => write!(f, "Low"), - Self::Medium => write!(f, "Medium"), - Self::High => write!(f, "High"), - } - } -} diff --git a/src/engine/engine/execution.rs b/src/engine/engine/execution.rs index 9d56b4e..a5e1084 100644 --- a/src/engine/engine/execution.rs +++ b/src/engine/engine/execution.rs @@ -1,4 +1,4 @@ -use hypersdk::hypercore::{self, BatchOrder, OrderRequest, OrderTypePlacement, TimeInForce}; +use hypersdk::hypercore::{self, BatchOrder, OrderRequest, OrderTypePlacement, Side, TimeInForce}; use pulse_sdk::prelude::*; use crate::engine::Engine; @@ -34,9 +34,9 @@ impl Engine { orders: vec![ OrderRequest { asset: asset_id, - is_buy: matches!(signal.kind, Direction::Buy), - limit_px: signal.price.0, - sz: signal.size, + is_buy: matches!(signal.side, Side::Bid), + limit_px: signal.price, + sz: 0.into(), reduce_only: false, order_type: OrderTypePlacement::Limit { tif: TimeInForce::Gtc, @@ -45,26 +45,26 @@ impl Engine { }, OrderRequest { asset: asset_id, - is_buy: matches!(signal.kind, Direction::Buy), - limit_px: signal.price.0, - sz: signal.size, + is_buy: matches!(signal.side, Side::Bid), + limit_px: signal.price, + sz: 0.into(), reduce_only: true, order_type: OrderTypePlacement::Trigger { is_market: true, - trigger_px: signal.take_profit.0, + trigger_px: signal.take_profit, tpsl: hypercore::TpSl::Tp, }, cloid: Default::default(), }, OrderRequest { asset: asset_id, - is_buy: matches!(signal.kind, Direction::Buy), - limit_px: signal.price.0, - sz: signal.size, + is_buy: matches!(signal.side, Side::Bid), + limit_px: signal.price, + sz: 0.into(), reduce_only: true, order_type: OrderTypePlacement::Trigger { is_market: true, - trigger_px: signal.stop_loss.0, + trigger_px: signal.stop_loss, tpsl: hypercore::TpSl::Sl, }, cloid: Default::default(), diff --git a/src/engine/engine/mod.rs b/src/engine/engine/mod.rs index f6cb30b..f8011b9 100644 --- a/src/engine/engine/mod.rs +++ b/src/engine/engine/mod.rs @@ -104,13 +104,10 @@ impl Engine { .asset_positions .into_iter() .map(|position| Position { - symbol: Symbol(position.position.coin), - size: position.position.szi.as_f64(), - entry_price: USD(position - .position - .entry_px - .unwrap_or_default()), - profit: USD(position.position.unrealized_pnl), + symbol: position.position.coin, + size: position.position.szi, + entry_price: position.position.entry_px.unwrap_or_default(), + pnl: position.position.unrealized_pnl, }) .collect(), )) diff --git a/src/engine/fetch.rs b/src/engine/fetch.rs index bbd6038..18131ef 100644 --- a/src/engine/fetch.rs +++ b/src/engine/fetch.rs @@ -1,5 +1,5 @@ -use rust_decimal::Decimal; use pulse_sdk::prelude::*; +use rust_decimal::Decimal; use serde_json::Value; use std::collections::HashMap; @@ -80,9 +80,9 @@ pub async fn fetch_watch_list( } items.push(MarketItem { - symbol: Symbol(symbol.clone()), - price: USD(price), - volume_24h: USD(volume_24h), + symbol: symbol.clone(), + price: price, + volume_24h: volume_24h, trend: ((price / previous_day_price) - >::from(1)) * >::from(100), }); diff --git a/src/terminal/formatting.rs b/src/terminal/formatting.rs index dace9dd..ba695f4 100644 --- a/src/terminal/formatting.rs +++ b/src/terminal/formatting.rs @@ -1,3 +1,4 @@ +use hypersdk::hypercore::Side; use pulse_sdk::prelude::*; pub trait Formatted { @@ -22,23 +23,6 @@ impl Formatted for InspectTarget { } } -impl Formatted for Alert { - fn get_formatted(&self) -> Vec { - vec![ - format!( - "{}{}\x1b[0m", - match &self.level { - AlertLevel::Low => "\x1b[34m", - AlertLevel::Medium => "\x1b[33m", - AlertLevel::High => "\x1b[31m", - }, - self.level - ), - self.message.clone(), - ] - } -} - impl Formatted for EventLog { fn get_formatted(&self) -> Vec { vec![ @@ -64,7 +48,7 @@ impl Formatted for SignalStatus { Ok(signal) => { vec![ format!("\x1b[33mOK\x1b[0m"), - if matches!(signal.kind, Direction::Buy) { + if matches!(signal.side, Side::Ask) { format!("\x1b[32mBUY\x1b[0m") } else { format!("\x1b[31mSELL\x1b[0m") @@ -78,7 +62,7 @@ impl Formatted for SignalStatus { Err(signal) => { vec![ format!("\x1b[31mERR\x1b[0m"), - if matches!(signal.kind, Direction::Buy) { + if matches!(signal.side, Side::Ask) { format!("\x1b[32mBUY\x1b[0m") } else { format!("\x1b[31mSELL\x1b[0m") @@ -115,16 +99,16 @@ impl Formatted for Position { fn get_formatted(&self) -> Vec { vec![ self.symbol.to_string(), - format_f64(self.size), + format_f64(self.size.as_f64()), self.entry_price.to_string(), format!( "{}{}\x1b[0m", - if self.profit.0.is_sign_positive() { + if self.pnl.is_sign_positive() { "\x1b[32m" } else { "\x1b[31m" }, - self.profit, + self.pnl, ), ] } @@ -134,31 +118,6 @@ struct Pair<'a>(&'a str, &'a str); struct Triple<'a>(&'a str, &'a str, &'a str); -impl Formatted for MarketOverview { - fn get_formatted(&self) -> Vec { - let mut o = vec![ - Pair("TREND", &format!("{}", self.trend)), - Pair("VOLATILITY", &format!("{}", self.volatility)), - Pair( - "PRESSURE", - &if self.pressure.is_sign_positive() { - format!("\x1b[32m{:.3}\x1b[0m", self.pressure) - } else { - format!("\x1b[31m{:.3}\x1b[0m", self.pressure) - }, - ), - ] - .get_formatted(); - - o.push(format!( - "\n{}", - apply_padding(self.alerts.get_formatted()).join("\n") - )); - - o - } -} - impl Formatted for Status { fn get_formatted(&self) -> Vec { vec![ @@ -272,3 +231,58 @@ pub fn apply_padding(mut items: Vec) -> Vec { items } + +pub fn format_f64(value: f64) -> String { + let abs = value.abs(); + + let (divisor, suffix) = if abs >= 1_000_000_000.0 { + (1_000_000_000.0, "B") + } else if abs >= 1_000_000.0 { + (1_000_000.0, "M") + } else if abs >= 1_000.0 { + (1_000.0, "K") + } else { + (1.0, "") + }; + + if divisor != 1.0 { + let formatted = value / divisor; + + // Remove unnecessary trailing zeros + let s = format!("{:.2}", formatted) + .trim_end_matches('0') + .trim_end_matches('.') + .to_string(); + + return format!("{}{}", s, suffix); + } + + let val = format!("{:.3}", value); + let parts: Vec<&str> = val.split('.').collect(); + + let int = parts[0].to_string(); + let negative = int.starts_with('-'); + + let start = if negative { 1 } else { 0 }; + let mut result = String::new(); + + for (i, c) in int[start..].chars().rev().enumerate() { + if i > 0 && i % 3 == 0 { + result.push(','); + } + result.push(c); + } + + let mut formatted: String = result.chars().rev().collect(); + + if negative { + formatted.insert(0, '-'); + } + + if parts.len() > 1 { + formatted.push('.'); + formatted.push_str(parts[1]); + } + + formatted +}