@@ -37,7 +37,7 @@ in Python, execution runs in Rust.
3737
3838| Crate | Description |
3939| -------| -------------|
40- | ` nanobook ` | LOB matching engine, portfolio simulator, backtest bridge |
40+ | ` nanobook ` | LOB matching engine, portfolio simulator, backtest bridge, GARCH, optimizers |
4141| ` nanobook-broker ` | Broker trait with IBKR and Binance adapters |
4242| ` nanobook-risk ` | Pre-trade risk engine (position limits, leverage, short exposure) |
4343| ` nanobook-python ` | PyO3 bindings for all layers |
@@ -68,6 +68,9 @@ cargo test
6868
6969# Python bindings
7070cd python && maturin develop --release
71+
72+ # Binance adapter (feature-gated, not in PyPI wheels)
73+ cd python && maturin develop --release --features binance
7174```
7275
7376## The Bridge: Python Strategy → Rust Execution
@@ -78,7 +81,7 @@ Rust simulates the portfolio and returns metrics:
7881``` python
7982import nanobook
8083
81- result = nanobook.py_backtest_weights (
84+ result = nanobook.backtest_weights (
8285 weight_schedule = [
8386 [(" AAPL" , 0.5 ), (" MSFT" , 0.5 )],
8487 [(" AAPL" , 0.3 ), (" NVDA" , 0.7 )],
@@ -98,51 +101,25 @@ print(result["holdings"][-1]) # per-period symbol weights
98101print (result[" stop_events" ]) # stop trigger metadata
99102```
100103
101- Your optimizer produces weights. ` py_backtest_weights ()` handles rebalancing,
104+ Your optimizer produces weights. ` backtest_weights ()` handles rebalancing,
102105cost modeling, position tracking, and return computation at compiled speed
103106with the GIL released.
104107
105- Clean aliases are also available for new callers:
106- ` backtest_weights ` , ` capabilities ` , ` garch_forecast ` , ` optimize_* ` .
107-
108- ### qtrade v0.4 Capability Gating
108+ ** v0.9 additions:** GARCH(1,1) forecasting, portfolio optimizers
109+ (min-variance, max-Sharpe, risk-parity, CVaR, CDaR), and trailing/fixed
110+ stop-loss simulation — all accessible from Python.
109111
110- Use ` py_capabilities() ` and keep fallback logic in ` calc.bridge ` :
112+ ### Optimizer Example
111113
112114``` python
113115import nanobook
116+ import numpy as np
117+
118+ # Daily returns matrix (T × N)
119+ returns = np.random.randn(252 , 5 ) * 0.01
114120
115- def has_nanobook () -> bool :
116- try :
117- import nanobook as _nb # noqa: F401
118- return True
119- except Exception :
120- return False
121-
122- def nanobook_version () -> str | None :
123- return getattr (nanobook, " __version__" , None ) if has_nanobook() else None
124-
125- def has_nanobook_feature (name : str ) -> bool :
126- if not has_nanobook():
127- return False
128-
129- caps = set (nanobook.py_capabilities()) if hasattr (nanobook, " py_capabilities" ) else set ()
130- if name in caps:
131- return True
132-
133- # Symbol fallback for older builds
134- symbol_map = {
135- " backtest_stops" : " py_backtest_weights" ,
136- " garch_forecast" : " py_garch_forecast" ,
137- " optimize_min_variance" : " py_optimize_min_variance" ,
138- " optimize_max_sharpe" : " py_optimize_max_sharpe" ,
139- " optimize_risk_parity" : " py_optimize_risk_parity" ,
140- " optimize_cvar" : " py_optimize_cvar" ,
141- " optimize_cdar" : " py_optimize_cdar" ,
142- " backtest_holdings" : " py_backtest_weights" ,
143- }
144- sym = symbol_map.get(name)
145- return bool (sym and hasattr (nanobook, sym))
121+ weights = nanobook.optimize_max_sharpe(returns, risk_free_rate = 0.0 )
122+ print (dict (zip ([" A" ," B" ," C" ," D" ," E" ], weights)))
146123```
147124
148125## Layer Examples
0 commit comments