solver/models/
avellaneda_impact.rs1use super::traits::{ControlOutput, Gradients, Model};
2
3#[derive(Clone)]
12pub struct AvellanedaImpact {
13 pub gamma: f64,
14 pub sigma: f64,
15 pub kappa: f64,
16 pub a: f64,
17 pub xi: f64,
20}
21
22impl AvellanedaImpact {
23 pub fn get_spreads(&self, grads: &Gradients<2>, q: f64) -> (f64, f64) {
25 let base_spread = (1.0 / self.gamma) * (1.0 + self.gamma / self.kappa).ln();
26
27 let dv_dq_buy = grads.fwd[0];
28 let dv_dq_sell = grads.bwd[0];
29
30 let mut delta_bid = base_spread - dv_dq_buy + (q + 1.0) * self.xi;
31 let mut delta_ask = base_spread + dv_dq_sell - (q - 1.0) * self.xi;
32
33 let min_spread = -5.0;
34 delta_bid = delta_bid.max(min_spread);
35 delta_ask = delta_ask.max(min_spread);
36
37 (delta_bid, delta_ask)
38 }
39}
40
41impl Model<2> for AvellanedaImpact {
42 type Process = ();
43
44 fn process(&self) {}
45
46 fn optimize(&self, state: &[f64; 2], grads: &Gradients<2>) -> ControlOutput<2> {
47 let q = state[0];
48
49 let (d_bid, d_ask) = self.get_spreads(grads, q);
50
51 let lambda_bid = self.a * (-self.kappa * d_bid).exp();
52 let lambda_ask = self.a * (-self.kappa * d_ask).exp();
53
54 let hamiltonian_val = (lambda_bid + lambda_ask) / (self.gamma + self.kappa);
57
58 let drift_correction = lambda_bid * grads.fwd[0] - lambda_ask * grads.bwd[0];
63
64 let risk_penalty = -0.5 * self.gamma * self.sigma.powi(2) * q.powi(2);
65
66 ControlOutput {
67 lambda_plus: [lambda_bid, 0.0],
68 lambda_minus: [lambda_ask, 0.0],
69 flow: hamiltonian_val + risk_penalty - drift_correction,
70 }
71 }
72
73 fn terminal(&self, state: &[f64; 2]) -> f64 {
74 let q = state[0];
82 -0.5 * self.xi * q.powi(2)
83 }
84
85 fn constant_discount_rate(&self) -> Option<f64> {
86 Some(0.0)
87 }
88
89 fn next_step(&self, current_state: &[f64; 2], dt: f64, noise: &[f64; 2]) -> [f64; 2] {
90 let mut next = *current_state;
91 let sqrt_dt = dt.sqrt();
92 next[1] += self.sigma * sqrt_dt * noise[1];
95 next
96 }
97
98 fn fill_rate_base(&self, _state: &[f64; 2]) -> f64 {
99 self.a
100 }
101
102 fn fill_rate_decay(&self) -> f64 {
103 self.kappa
104 }
105}