A reproducible Julia research laboratory for transparent weekly market-regime analysis. The project separates data ingestion, deterministic risk calculations, regime classification and expanding-window validation.
Regime labels are easy to invent after looking at a chart. This project makes the
decision rule explicit and evaluates it chronologically. A week is classified as
risk_on only when trailing S&P 500 momentum is positive and VIX is no higher
than its trailing median. No future observation enters the label or forecast.
The committed fixture contains real weekly observations downloaded from the Federal Reserve Economic Data service:
| Column | FRED series | Interpretation |
|---|---|---|
sp500 |
SP500 |
S&P 500 index |
vix |
VIXCLS |
CBOE volatility index |
usd |
DTWEXBGS |
broad trade-weighted U.S. dollar index |
btc |
CBBTCUSD |
Coinbase Bitcoin/U.S. dollar |
real10y |
DFII10 |
10-year inflation-indexed Treasury yield |
Daily observations are aligned, forward-filled only across missing market dates, and sampled on Fridays. The frozen CSV makes tests reproducible and auditable.
For weekly log returns r_t, the library computes annualized geometric return,
volatility, historical VaR, expected shortfall, maximum drawdown and quarter-Kelly
allocation capped at 25% in absolute value.
The empirical first-order transition estimator is:
P(i, j) = count(S_t = i, S_t+1 = j) / count(S_t = i)
Walk-forward validation re-estimates P on an expanding window and predicts only
the next state. Accuracy is reported beside a naive persistence forecast.
On the committed 2017-2026 weekly panel, the transition model records a 75.73% one-step hit rate versus 75.96% for naive regime persistence. The current model therefore does not demonstrate incremental forecasting edge. That negative result is preserved deliberately: future changes must beat the same chronological benchmark rather than improve an in-sample story.
julia --project=. -e 'using Pkg; Pkg.instantiate()'
julia --project=. scripts/run_analysis.jl
julia --project=. -e 'using Pkg; Pkg.test()'Refresh the public-data fixture:
julia --project=. scripts/fetch_data.jlOpen the reactive Pluto notebook:
julia --project=. -e 'using Pluto; Pluto.run()'Then open notebooks/regime_explorer.jl.
src/ data pipeline, risk metrics and regime model
data/ frozen real-world weekly observations
test/ deterministic and integration tests
notebooks/ reactive Pluto exploration
reports/ executable Quarto methodology report
scripts/ data refresh and command-line analysis
- no synthetic market data in integration tests;
- no look-ahead in regime labels or walk-forward estimation;
- no API keys or proprietary feeds;
- calculations are deterministic and tested;
- methodology and limitations are explicit.
This repository is for research and education. It is not investment advice.