Short Rate Models (Part 12: Local Momentum and Mean Reversion II)
2026-03-17
1 From Duan’s Full Model to Our Reduced Package Model
The theory notebook derived the paper’s formulas in full generality. The package implementation is intentionally narrower. The table below makes the mapping explicit.
Paper block
Package status
Comment
Local-momentum drift built from a recent-history summary
implemented exactly in spirit
The package keeps an explicit momentum state and a separate trend state.
Recursive local average / augmented Markov state
implemented exactly
The model state contains the recent-history summary rather than leaving it implicit.
Stochastic central tendency
approximated in reduced form
The package uses a single trend factor rather than the paper’s full specification.
Local variation factor in the full term-structure system
omitted
The current implementation focuses on the nonlinear momentum channel.
Full no-arbitrage pricing-kernel estimation
omitted
The notebook uses reduced deterministic yield construction instead.
Weekly public yield panel
implemented exactly
alphaforge builds the weekly dataset from public daily rates resampled to a fixed Friday grid.
Full likelihood estimation
approximated in reduced form
The package fit uses regression-based calibration rather than the full MLE problem.
The point of the notebook is therefore twofold. First, it demonstrates the public-data workflow. Second, it makes every approximation explicit rather than hiding it inside the code.
Code
import osimport sysfrom pathlib import Pathimport numpy as npimport pandas as pddef locate_workspace() -> Path: cwd = Path.cwd().resolve()for candidate in [cwd, *cwd.parents]:if (candidate /'alphaforge').exists() and (candidate /'short-rate-models').exists():return candidateraiseRuntimeError('Could not locate the steveya workspace from the current working directory.')WORKSPACE = locate_workspace()sys.path.insert(0, str(WORKSPACE /'alphaforge'))sys.path.insert(0, str(WORKSPACE /'short-rate-models'))from alphaforge import ( DataContext, DuckDBParquetStore, FREDDataSource, TradingCalendar, build_duan_weekly_dataset,)from short_rate_models import LocalMomentumTermStructureModel
The reduced fit treats the observed weekly short rate as the local level and constructs latent trend and momentum summaries directly from the history of that short-rate proxy. This is much simpler than the full term-structure estimation problem in the paper, but it isolates the local-momentum mechanism transparently.
Code
model, fit = LocalMomentumTermStructureModel.fit( short_rate=dataset.short_rate, yields=dataset.yields,)fit['state_proxy'].tail()
Code
comparison = fit.get('yield_comparison')if comparison isNone:raiseRuntimeError('The reduced fit did not produce a yield comparison block.')errors = comparison['errors'].abs().mean().rename('mean_absolute_error')errors
There are two questions to ask after the fit. First, does the estimated nonlinear momentum term matter numerically, or does the model collapse back to ordinary mean reversion? Second, when the nonlinear term does matter, does it improve the medium-horizon behavior of the fitted short rate and the fitted yield panel?
The reduced model earns its keep only if the answer to both questions is yes. If the nonlinear term is tiny, then the simpler affine Gaussian baseline is probably sufficient. If the term is large but unstable, then the paper’s mechanism may be real but the reduced implementation may still be too crude for reliable empirical work.
4 Limitations
This notebook is intentionally candid about what it does not do. It does not estimate the full pricing kernel, it does not recover every factor in the paper, and it does not claim exact no-arbitrage bond pricing. What it does do is fit the local nonlinear channel on a weekly public dataset, compare the resulting reduced-form yields to observed yields, and tie every implemented formula back to the derivation notebook.