Files
quant-factor-research/docs/ETF_TREND_SYSTEM.md

2.0 KiB

ETF Trend System (K<=4, no leverage) - v2

This is a daily-signal / daily-rebalance trend-following system on a configurable ETF universe.

It is designed for:

  • K<=4 holdings
  • no leverage (net exposure <= 100%)
  • portfolio vol cap (de-risk only), remainder parked in a rates ETF
  • practical execution hygiene (cooldown / new listing protection / turnover band)

Signals

  • Trend filter (entry universe): MA(fast) > MA(slow)

    • default: MA5 > MA20
  • Ranking score (higher is better):

    score = (0.5*R20 + 0.3*R60 + 0.2*R120) / max(vol20, floor) + 0.5*trend_strength

    where trend_strength = ma_fast/ma_slow - 1.

Entry

On each rebalance day (daily):

  • Candidate must satisfy:
    • trend_ok == True (MA cross)
    • score >= min_score
    • min_history_days protection (skip too-new series)
    • cooldown_days protection (after exit, avoid immediate re-entry)

Position Sizing

  • Risk parity on vol20 across selected holdings.

  • Per-asset cap: max_weight_per_asset (default 0.50)

  • Portfolio vol cap (no leverage):

    scale = min(1, target_ann_vol / port_vol(port_vol_window))

    Remaining weight (1 - sum(weights)) is parked in rates_fallback.

Exits (checked daily)

A position exits if any triggers:

  • Trend break: MA(fast) < MA(slow)
  • Chandelier stop: close < highest_close - atr_mult*ATR
  • Stop loss from entry: close < entry_price - stop_loss_atr*ATR
  • Take profit from entry: close > entry_price + take_profit_atr*ATR

Trading Hygiene

  • rebalance_band: ignore small weight changes to reduce churn.
  • min_hold_days: do not rebalance-sell a very fresh position (risk exits still apply).
  • new_asset_days/new_asset_max_w: cap weight of a newly-eligible asset for its first N tradable days after it passes the history gate.

Outputs

Backtest runner writes 3 artifacts:

  • equity curve parquet: data/etf_trend_equity_*.parquet
  • weights parquet: data/etf_trend_equity_*_weights.parquet
  • trades parquet: data/etf_trend_equity_*_trades.parquet