x-forecast · paper portfolio
Framework

Methodology

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%.
  • Bearnot 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.