pub struct BilateralHawkes {
pub gamma: f64,
pub sigma: f64,
pub kappa: f64,
pub alpha: f64,
pub beta: f64,
pub mu: f64,
pub lambda_step: f64,
pub dq: f64,
pub q_min: f64,
pub q_max: f64,
pub terminal_condition: TerminalCondition,
pub terminal_liquidation_half_spread: Option<f64>,
}Expand description
Avellaneda-Stoikov model with a bilateral (2-D) Hawkes process.
§State Space [q, lambda_plus, lambda_minus]
| dim | symbol | description |
|---|---|---|
| 0 | q | Inventory level (integer, jump-controlled) |
| 1 | lambda+ | Buy market-order intensity (ODE drift, no noise) |
| 2 | lambda- | Sell market-order intensity (ODE drift, no noise) |
§Dynamics
d(lambda+) = beta*(mu - lambda+) dt + alpha dN+
d(lambda-) = beta*(mu - lambda-) dt + alpha dN-
N+ counts buy market orders (rate lambda+), N- counts sell market orders (rate lambda-).
Each side self-excites independently — there is no cross-excitation.
§Market-making mapping
| event | driven by | inventory effect |
|---|---|---|
| Sell MO hits bid | lambda- | q -> q + 1 |
| Buy MO hits ask | lambda+ | q -> q - 1 |
Effective fill rates:
Lambda_bid = lambda- * exp(-kappa * delta_bid)(sell MO hits MM bid)Lambda_ask = lambda+ * exp(-kappa * delta_ask)(buy MO hits MM ask)
§Hawkes approximation used in the FD solver
The lambda dimensions use the fluid (mean-field) approximation:
d(lambda+)/dt ~ beta*(mu - lambda+) + alpha * lambda+
d(lambda-)/dt ~ beta*(mu - lambda-) + alpha * lambda-
This is identical to the treatment in AvellanedaHawkes and ensures the
stationary mean of each intensity sits at mu / (1 - alpha/beta) in the
value-function PDE. Using discrete fill-triggered jumps instead requires
lambda_step << alpha for accuracy; at the grid resolution affordable for
4-D tables that condition is violated, causing the PDE to see a much lower
effective mean intensity than the actual simulation (mu vs mu/(1-rho)),
which corrupts the value function and the extracted spreads.
Fields§
§gamma: f64Risk-aversion parameter.
sigma: f64Price volatility.
kappa: f64Fill-rate decay (Avellaneda-Stoikov kappa).
alpha: f64Jump size added to the excited side’s intensity.
beta: f64Mean-reversion speed.
mu: f64Baseline intensity (mean-reversion target).
lambda_step: f64Grid step for both lambda+ and lambda- dimensions.
dq: f64Grid step for the inventory dimension.
q_min: f64Minimum inventory (lower hard boundary). Defaults to -infinity.
q_max: f64Maximum inventory (upper hard boundary). Defaults to +infinity.
terminal_condition: TerminalConditionTerminal condition for the value function at T. Defaults to Zero.
terminal_liquidation_half_spread: Option<f64>Optional terminal liquidation half-spread used when terminal_condition is LiquidationCost. If None, uses the AS base spread.
Implementations§
Source§impl BilateralHawkes
impl BilateralHawkes
pub fn new( gamma: f64, sigma: f64, kappa: f64, alpha: f64, beta: f64, mu: f64, ) -> Self
pub fn with_terminal_condition( self, terminal_condition: TerminalCondition, ) -> Self
pub fn with_terminal_liquidation_half_spread(self, half_spread: f64) -> Self
pub fn with_inventory_bounds(self, q_min: f64, q_max: f64) -> Self
pub fn with_lambda_step(self, lambda_step: f64) -> Self
pub fn with_dq(self, dq: f64) -> Self
Sourcepub fn get_spreads(&self, grads: &Gradients<3>) -> (f64, f64)
pub fn get_spreads(&self, grads: &Gradients<3>) -> (f64, f64)
Computes optimal bid/ask half-spreads from value-function gradients.
Bid spread: driven by the inventory gradient in the +q direction (sell MO fills). Ask spread: driven by the inventory gradient in the -q direction (buy MO fills).
Trait Implementations§
Source§impl Clone for BilateralHawkes
impl Clone for BilateralHawkes
Source§fn clone(&self) -> BilateralHawkes
fn clone(&self) -> BilateralHawkes
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for BilateralHawkes
impl Debug for BilateralHawkes
Source§impl Model<3> for BilateralHawkes
impl Model<3> for BilateralHawkes
Source§fn next_step(
&self,
current_state: &[f64; 3],
dt: f64,
_noise: &[f64; 3],
) -> [f64; 3]
fn next_step( &self, current_state: &[f64; 3], dt: f64, _noise: &[f64; 3], ) -> [f64; 3]
Forward step using the fluid (mean-field) drift, consistent with optimize().
The drift is beta*(mu - lambda) + alpha * lambda (same approximation used in
the PDE so that the forward simulation matches the value-function’s stationary
lambda regime at mu / (1 - alpha/beta)).
Source§fn next_step_controlled(
&self,
current_state: &[f64; 3],
control: &ControlOutput<3>,
dt: f64,
noise: &[f64; 3],
) -> [f64; 3]
fn next_step_controlled( &self, current_state: &[f64; 3], control: &ControlOutput<3>, dt: f64, noise: &[f64; 3], ) -> [f64; 3]
Coupled step: inventory jumps based on current fill probabilities.
Source§fn is_diffusion_dimension(&self, _dim: usize) -> bool
fn is_diffusion_dimension(&self, _dim: usize) -> bool
Both intensity dimensions follow deterministic ODE drift with no Brownian noise.
Source§fn fill_rate_base(&self, state: &[f64; 3]) -> f64
fn fill_rate_base(&self, state: &[f64; 3]) -> f64
The base arrival intensity is state-dependent: returns the average of the buy/sell intensity states for intensity-to-spread conversion.
Source§type Process = ()
type Process = ()
() for models without a corresponding market_model process.Source§fn optimize(&self, state: &[f64; 3], grads: &Gradients<3>) -> ControlOutput<3>
fn optimize(&self, state: &[f64; 3], grads: &Gradients<3>) -> ControlOutput<3>
Source§fn terminal(&self, state: &[f64; 3]) -> f64
fn terminal(&self, state: &[f64; 3]) -> f64
Source§fn constant_discount_rate(&self) -> Option<f64>
fn constant_discount_rate(&self) -> Option<f64>
Source§fn is_integer_dimension(&self, dim: usize) -> bool
fn is_integer_dimension(&self, dim: usize) -> bool
Source§fn gradient_step(&self, dim: usize) -> f64
fn gradient_step(&self, dim: usize) -> f64
Source§fn fill_rate_decay(&self) -> f64
fn fill_rate_decay(&self) -> f64
Source§fn discount_rate(&self, _state: &[f64; N]) -> f64
fn discount_rate(&self, _state: &[f64; N]) -> f64
Auto Trait Implementations§
impl Freeze for BilateralHawkes
impl RefUnwindSafe for BilateralHawkes
impl Send for BilateralHawkes
impl Sync for BilateralHawkes
impl Unpin for BilateralHawkes
impl UnsafeUnpin for BilateralHawkes
impl UnwindSafe for BilateralHawkes
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more