1use chrono::{DateTime, FixedOffset, Utc};
2use std::collections::HashMap;
3
4pub use crate::backtest::FundingPayment;
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
8pub enum OrderSide {
9 Buy,
10 Sell,
11}
12
13#[derive(Debug, Clone, Copy, PartialEq, Eq)]
15pub enum OrderType {
16 Market,
17 Limit,
18}
19
20#[derive(Debug, Clone, Copy, PartialEq, Eq)]
22pub enum TimeInForce {
23 GoodTillCancel,
24 ImmediateOrCancel,
25 FillOrKill,
26 GoodTillDate,
27}
28
29#[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#[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#[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}