1 · Three parallel groups
Rather than betting on one scenario, the same macro view is forked into three tilts:
- Base — risk-parity neutral with soft view overlay. Target vol ≤ 8%.
- Bull — overweights the 2–3 highest-conviction views on top of Base. Single-position cap 30%, vol ≤ 12%.
- Bear — not a short bet, but a defensive book for when Base is wrong. High cash + long duration + gold, vol ≤ 6%.
Running all three NAVs side-by-side puts "do my views actually have alpha?" on the table publicly: if Bull beats Base over time, views add value; if all three lag 60/40, the framework needs rebuilding.
2 · Asset universe
10 ETFs spanning 5 core asset classes:
- Equity: A-share large-cap (CSI 300) + mid-cap (CSI 500) + HK (Hang Seng) + US (SPY) + Nasdaq (QQQ)
- Rates: Onshore 10Y CGB + US 20Y+ Treasury (TLT)
- Credit: onshore LGFV bonds
- Commodities: gold
- Cash: MMF proxy
Reference variables (not traded, only used as view inputs and attribution factors): USD/CNY, DXY, UST 10Y/2Y yield, VIX.
3 · Monthly discipline (hard-coded, not flexible)
- Rebalance on the 1st trading day of each month, no intra-month moves (unless a hard stop triggers)
- At most 3 position changes per rebalance
- Single-position cap 30%, single-class cap 50%, cash floor 5%
- Every rebalance must be written down: trigger / expectation / falsification → timestamped via git commit
4 · Attribution (monthly)
Each month, excess return (vs Base / vs 60/40) is routed to:
- Asset-class allocation (Brinson allocation effect)
- Security selection (mostly broad ETFs — this should be small)
- Macro factors: rate direction / USD direction / risk appetite (VIX) / credit spread
5 · Baselines
Three groups are compared simultaneously against three baselines:
- 60/40 (60% equity / 40% bond)
- Equal weight (10 assets, 10% each)
- Pure risk-parity (no view, inverse historical vol)
No baseline, no alpha. Persistently losing to baselines = views have no value = the framework needs to be torn down.
6 · Data flow
- Prices: yfinance (offshore + A-share ETFs via .SS suffix) + akshare (onshore fill-in)
- GitHub Actions: weekdays 17:30 SGT auto-fetch + recompute NAV, commit back
- Daily NAV = last-rebalance unit counts × day’s close
- v1 keeps offshore assets in local currency (no USD/CNY adjustment); v2 will fold FX in
7 · Known simplifications (v1)
Honest disclosure of v1 limitations:
- No transaction cost / slippage (live would lose roughly 10–20 bps/year)
- Offshore assets priced in local currency — no USD/CNY adjustment yet (over- or under-states)
- No reinvestment modeling (dividends assumed auto-reinvested)
- ETFs as asset-class proxies (tracking error ignored)
See the GitHub roadmap for the v2 path.