6c2ce3d238
- Removed order_flow.rs (UnifiedTheoryParams, OrderFlowAnalyzer, MarketImpact) - Removed analyze_order_flow, unified_theory_params, market_impact Python bindings - Updated mod.rs documentation to be generic (no trading references) - Kept general-purpose: Hawkes, fBM, mfBM, Mittag-Leffler, Hurst estimation Finance-specific code moved to rust-hft-arbitrage-lab-internal
95 lines
2.7 KiB
Plaintext
95 lines
2.7 KiB
Plaintext
# Optimal Control
|
||
|
||
Hamilton–Jacobi–Bellman (HJB) solvers, regime-switching thresholds, OU parameter estimation, and Kalman filtering utilities backed by Rust.
|
||
|
||
## HJB switching boundaries (OU process)
|
||
|
||
```python
|
||
from optimizr import solve_hjb_py, solve_hjb_full_py
|
||
|
||
lower, upper, residual, iters = solve_hjb_py(
|
||
kappa=3.0,
|
||
theta=0.0,
|
||
sigma=0.2,
|
||
rho=0.04,
|
||
transaction_cost=0.001,
|
||
n_points=400,
|
||
max_iter=4000,
|
||
tolerance=1e-7,
|
||
n_std=5.0,
|
||
)
|
||
print(f"bounds=({lower:.3f}, {upper:.3f}), residual={residual:.2e}, iters={iters}")
|
||
```
|
||
|
||
- Model: $dX_t = \kappa(\theta - X_t)\,dt + \sigma\,dW_t$ with quadratic transaction costs.
|
||
- Output: optimal buy/sell thresholds; `solve_hjb_full_py` also returns $V, V_x, V_{xx}$ for diagnostics.
|
||
- Diagnostics: plot $V_x$ for smoothness near thresholds; monitor `residual` and increase `max_iter` if not converged.
|
||
|
||
## Backtesting optimal switching
|
||
|
||
```python
|
||
from optimizr import backtest_optimal_switching_py
|
||
|
||
metrics = backtest_optimal_switching_py(
|
||
spread=spread,
|
||
lower_bound=lower,
|
||
upper_bound=upper,
|
||
transaction_cost=0.001,
|
||
)
|
||
(
|
||
total_return,
|
||
sharpe,
|
||
max_dd,
|
||
n_trades,
|
||
win_rate,
|
||
pnl_path,
|
||
) = metrics
|
||
```
|
||
|
||
Inspect `win_rate` vs `max_dd` to tune aggressiveness; combine with HMM regimes for state-aware controls.
|
||
|
||
## OU parameter estimation
|
||
|
||
```python
|
||
import numpy as np
|
||
from optimizr import estimate_ou_params_py
|
||
|
||
spread = np.random.randn(10_000)
|
||
kappa, theta, sigma, half_life = estimate_ou_params_py(spread, dt=1/252)
|
||
```
|
||
|
||
Method-of-moments / MLE fit returns $(\kappa, \theta, \sigma, \text{half-life})$. Use a few thousand samples for stability; winsorize heavy tails if needed.
|
||
|
||
## Kalman filtering (linear, EKF, UKF)
|
||
|
||
```python
|
||
import numpy as np
|
||
from optimizr import LinearKalmanFilter
|
||
|
||
F = [[1.0, 1.0], [0.0, 1.0]]
|
||
H = [[1.0, 0.0]]
|
||
Q = [[1e-4, 0.0], [0.0, 1e-4]]
|
||
R = [[1e-2]]
|
||
|
||
kf = LinearKalmanFilter(
|
||
f_matrix=F,
|
||
h_matrix=H,
|
||
q_matrix=Q,
|
||
r_matrix=R,
|
||
initial_state=[0.0, 0.0],
|
||
initial_covariance=[[1.0, 0.0], [0.0, 1.0]],
|
||
)
|
||
|
||
kf.predict(control=[0.0, 0.0])
|
||
kf.update(observation=[1.2])
|
||
state = kf.get_state()
|
||
```
|
||
|
||
- Interfaces: `LinearKalmanFilter`, `UnscentedKalmanFilter`, and `KalmanState` for batch `filter` and smoothing.
|
||
- Concept: prediction (dynamics prior) + correction (measurement residual); RTS smoother refines past states.
|
||
|
||
## Practical notes
|
||
- Rust backend (`optimizr._core`) must be present for control utilities; install from source if wheels are unavailable.
|
||
- Grids: for HJB, `n_points≈400` is stable; widen `n_std` for volatile spreads.
|
||
- Combine with Mean Field Games: see `mean_field_games.md` for population dynamics; use Kalman estimates as control inputs if needed.
|