quant_primitives/
position_config.rs1use rust_decimal::Decimal;
8use serde::{Deserialize, Serialize};
9
10#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
17pub struct PositionConfig {
18 max_position_pct: Decimal,
19 volatility_scaling: bool,
20 risk_per_trade_pct: Option<Decimal>,
21}
22
23#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
25pub enum PositionConfigError {
26 #[error("max_position_pct {0} out of range [0, 1]")]
28 MaxPositionOutOfRange(Decimal),
29 #[error("risk_per_trade_pct {0} out of range [0, 1]")]
31 RiskPerTradeOutOfRange(Decimal),
32}
33
34impl PositionConfig {
35 pub fn new(
37 max_position_pct: Decimal,
38 volatility_scaling: bool,
39 risk_per_trade_pct: Option<Decimal>,
40 ) -> Result<Self, PositionConfigError> {
41 if max_position_pct < Decimal::ZERO || max_position_pct > Decimal::ONE {
42 return Err(PositionConfigError::MaxPositionOutOfRange(max_position_pct));
43 }
44 if let Some(risk) = risk_per_trade_pct {
45 if risk < Decimal::ZERO || risk > Decimal::ONE {
46 return Err(PositionConfigError::RiskPerTradeOutOfRange(risk));
47 }
48 }
49 Ok(Self {
50 max_position_pct,
51 volatility_scaling,
52 risk_per_trade_pct,
53 })
54 }
55
56 pub fn max_position_pct(&self) -> Decimal {
58 self.max_position_pct
59 }
60
61 pub fn volatility_scaling(&self) -> bool {
63 self.volatility_scaling
64 }
65
66 pub fn risk_per_trade_pct(&self) -> Option<Decimal> {
68 self.risk_per_trade_pct
69 }
70}
71
72impl Default for PositionConfig {
73 fn default() -> Self {
74 Self {
75 max_position_pct: Decimal::new(1, 1), volatility_scaling: false,
77 risk_per_trade_pct: None,
78 }
79 }
80}
81
82#[cfg(test)]
83#[path = "position_config_tests.rs"]
84mod tests;