hyperliquid_backtest/
unified_data.rs

1use chrono::{DateTime, FixedOffset, Utc};
2use std::collections::HashMap;
3
4pub use crate::backtest::FundingPayment;
5
6/// Direction of an order.
7#[derive(Debug, Clone, Copy, PartialEq, Eq)]
8pub enum OrderSide {
9    Buy,
10    Sell,
11}
12
13/// Supported order execution types.
14#[derive(Debug, Clone, Copy, PartialEq, Eq)]
15pub enum OrderType {
16    Market,
17    Limit,
18}
19
20/// Time-in-force settings for orders.
21#[derive(Debug, Clone, Copy, PartialEq, Eq)]
22pub enum TimeInForce {
23    GoodTillCancel,
24    ImmediateOrCancel,
25    FillOrKill,
26    GoodTillDate,
27}
28
29/// Basic representation of a trading position.
30#[derive(Debug, Clone, PartialEq)]
31pub struct Position {
32    pub symbol: String,
33    pub size: f64,
34    pub entry_price: f64,
35    pub current_price: f64,
36    pub realized_pnl: f64,
37    pub funding_pnl: f64,
38    pub timestamp: DateTime<FixedOffset>,
39}
40
41impl Position {
42    pub fn new(
43        symbol: &str,
44        size: f64,
45        entry_price: f64,
46        current_price: f64,
47        timestamp: DateTime<FixedOffset>,
48    ) -> Self {
49        Self {
50            symbol: symbol.to_string(),
51            size,
52            entry_price,
53            current_price,
54            realized_pnl: 0.0,
55            funding_pnl: 0.0,
56            timestamp,
57        }
58    }
59
60    pub fn update_price(&mut self, price: f64) {
61        self.current_price = price;
62    }
63
64    pub fn apply_funding_payment(&mut self, payment: f64) {
65        self.funding_pnl += payment;
66    }
67
68    pub fn total_pnl(&self) -> f64 {
69        self.realized_pnl + self.unrealized_pnl() + self.funding_pnl
70    }
71
72    pub fn unrealized_pnl(&self) -> f64 {
73        self.size * (self.current_price - self.entry_price)
74    }
75}
76
77/// Request to place an order on the exchange.
78#[derive(Debug, Clone, PartialEq)]
79pub struct OrderRequest {
80    pub symbol: String,
81    pub side: OrderSide,
82    pub order_type: OrderType,
83    pub quantity: f64,
84    pub price: Option<f64>,
85    pub reduce_only: bool,
86    pub time_in_force: TimeInForce,
87    pub stop_price: Option<f64>,
88    pub client_order_id: Option<String>,
89    pub parameters: HashMap<String, String>,
90}
91
92impl OrderRequest {
93    pub fn market(symbol: &str, side: OrderSide, quantity: f64) -> Self {
94        Self {
95            symbol: symbol.to_string(),
96            side,
97            order_type: OrderType::Market,
98            quantity,
99            price: None,
100            reduce_only: false,
101            time_in_force: TimeInForce::GoodTillCancel,
102            stop_price: None,
103            client_order_id: None,
104            parameters: HashMap::new(),
105        }
106    }
107
108    pub fn limit(symbol: &str, side: OrderSide, quantity: f64, price: f64) -> Self {
109        Self {
110            symbol: symbol.to_string(),
111            side,
112            order_type: OrderType::Limit,
113            quantity,
114            price: Some(price),
115            reduce_only: false,
116            time_in_force: TimeInForce::GoodTillCancel,
117            stop_price: None,
118            client_order_id: None,
119            parameters: HashMap::new(),
120        }
121    }
122}
123
124/// Outcome of an order execution.
125#[derive(Debug, Clone, PartialEq)]
126pub struct OrderResult {
127    pub order_id: String,
128    pub symbol: String,
129    pub side: OrderSide,
130    pub quantity: f64,
131    pub price: f64,
132    pub timestamp: DateTime<FixedOffset>,
133}
134
135impl OrderResult {
136    pub fn new(order_id: &str, symbol: &str, side: OrderSide, quantity: f64, price: f64) -> Self {
137        Self {
138            order_id: order_id.to_string(),
139            symbol: symbol.to_string(),
140            side,
141            quantity,
142            price,
143            timestamp: Utc::now().with_timezone(&FixedOffset::east_opt(0).unwrap()),
144        }
145    }
146}