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

64 lines
2.0 KiB
Markdown

# 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`