Skip to main content

fx_pricing/
engine.rs

1//! Pricing engine implementation
2
3use crate::ai_client::AiClient;
4use crate::risk_adjuster::RiskAdjuster;
5use crate::spread::{FixedSpreadModel, SpreadModel};
6use fx_md::Quote;
7use fx_risk::RiskEngine;
8use fx_utils::{Price, Result};
9use std::sync::Arc;
10
11/// Pricing engine that generates risk-adjusted prices
12pub struct PricingEngine {
13    spread_model: Box<dyn SpreadModel + Send + Sync>,
14    risk_adjuster: RiskAdjuster,
15    ai_client: Option<Arc<AiClient>>,
16}
17
18impl PricingEngine {
19    pub fn new() -> Self {
20        Self {
21            spread_model: Box::new(FixedSpreadModel::new(2)), // 2 bps default
22            risk_adjuster: RiskAdjuster::new(None),
23            ai_client: None,
24        }
25    }
26
27    pub fn with_risk_engine(mut self, risk_engine: Arc<RiskEngine>) -> Self {
28        self.risk_adjuster = RiskAdjuster::new(Some(risk_engine));
29        self
30    }
31
32    pub fn with_ai_client(mut self, ai_client: Arc<AiClient>) -> Self {
33        self.ai_client = Some(ai_client);
34        self
35    }
36
37    pub async fn calculate_prices(&self, base_quote: &Quote) -> Result<(Price, Price)> {
38        let mid = base_quote.mid_price();
39
40        // Get volatility from AI module if available
41        let volatility = if let Some(ai_client) = &self.ai_client {
42            ai_client
43                .predict_volatility(&base_quote.instrument)
44                .await
45                .unwrap_or(0.0) // Fallback to 0.0 if AI service fails
46        } else {
47            0.0
48        };
49
50        let spread = self.spread_model.calculate_spread(mid, volatility);
51
52        let bid = Price(mid.0.saturating_sub(spread.0 / 2));
53        let ask = Price(mid.0 + spread.0 / 2);
54
55        // Apply risk-based adjustments
56        let (adjusted_bid, adjusted_ask) =
57            self.risk_adjuster
58                .adjust_prices(&base_quote.instrument, bid, ask);
59
60        Ok((adjusted_bid, adjusted_ask))
61    }
62}
63
64impl Default for PricingEngine {
65    fn default() -> Self {
66        Self::new()
67    }
68}