initial import: etf strategy project
This commit is contained in:
63
docs/ETF_TREND_SYSTEM.md
Normal file
63
docs/ETF_TREND_SYSTEM.md
Normal file
@@ -0,0 +1,63 @@
|
||||
# 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`
|
||||
18
docs/FACTOR_PIPELINE.md
Normal file
18
docs/FACTOR_PIPELINE.md
Normal file
@@ -0,0 +1,18 @@
|
||||
# Factor Pipeline (Draft)
|
||||
|
||||
1) Load universe + prices + fundamentals
|
||||
2) Compute raw factor values
|
||||
3) Clean:
|
||||
- missing handling
|
||||
- winsorize (per-date cross section)
|
||||
- z-score (per-date cross section)
|
||||
4) Neutralize (optional):
|
||||
- industry
|
||||
- size
|
||||
5) Evaluate:
|
||||
- IC / Rank IC
|
||||
- decay
|
||||
- turnover
|
||||
6) Backtest:
|
||||
- long-short / top-k
|
||||
- transaction costs
|
||||
28
docs/TUSHARE.md
Normal file
28
docs/TUSHARE.md
Normal file
@@ -0,0 +1,28 @@
|
||||
# Tushare Integration
|
||||
|
||||
## Setup
|
||||
|
||||
1) Add token
|
||||
|
||||
- Create `/home/openclaw/projects/quant-factor-research/.env`:
|
||||
|
||||
- `TUSHARE_TOKEN=...`
|
||||
- `TUSHARE_TIMEOUT=30`
|
||||
|
||||
Template: `configs/tushare.env.example`
|
||||
|
||||
2) Install dependency into conda env
|
||||
|
||||
- `conda activate qfr`
|
||||
- Prefer conda-forge where possible; but `tushare` is usually pip:
|
||||
- `pip install tushare`
|
||||
|
||||
## Download daily bars
|
||||
|
||||
Example:
|
||||
|
||||
- `python scripts/tushare_download_daily.py --ts-code 000001.SZ --start 20250101 --end 20250131 --out data/raw/000001SZ_202501.parquet`
|
||||
|
||||
Notes:
|
||||
|
||||
- Tushare API has rate limits based on your account积分. Cache results locally.
|
||||
69
docs/dev-flow-checklist.md
Normal file
69
docs/dev-flow-checklist.md
Normal file
@@ -0,0 +1,69 @@
|
||||
# QFR 策略开发最小闭环(Checklist)
|
||||
|
||||
目标:让每次改动都能被复现、复算、对比、落库,避免只看日志导致的错觉与过拟合。
|
||||
|
||||
## 0) 约定
|
||||
|
||||
- 唯一入口:所有优化结果必须可用 scripts/run_etf_trend_backtest.py 复算。
|
||||
- 固定数据窗:同一次实验必须固定 start/end 与 configs 下的 universe json。
|
||||
- 落库优先:优化与复算都要写入 data/experiments.sqlite(或输出可追溯 artifacts)。
|
||||
|
||||
## 1) 提出假设(写清楚再改)
|
||||
|
||||
- 本次改动想提升什么?(ann_return / max_drawdown / ann_vol / sharpe / trades_per_year)
|
||||
- 风险约束是什么?(例如:max_trades_per_year <= 80,回撤不恶化超过阈值)
|
||||
- 预期影响:趋势/均值回归/风险控制/换仓逻辑/过滤条件 哪一块在起作用?
|
||||
|
||||
## 2) 实现改动 + 基线自检
|
||||
|
||||
- 运行一次基线回测(固定 config + 时间窗):
|
||||
- python scripts/run_etf_trend_backtest.py --config <CONF> --start <START> --end <END>
|
||||
- 确认输出 artifacts:
|
||||
- data/etf_trend_equity.parquet
|
||||
- data/etf_trend_equity_weights.parquet
|
||||
- data/etf_trend_equity_trades.parquet(如有)
|
||||
|
||||
## 3) 搜索/优化(iterate_optimize)
|
||||
|
||||
- 固定参数:seed、start/end、config、rawdir
|
||||
- 记录 run_id(建议用时间戳)
|
||||
- 让优化写库:data/experiments.sqlite
|
||||
|
||||
## 4) Top-N 复算(必须做)
|
||||
|
||||
目的:避免优化器算出来的 top config 因入口不同/代码变更/数据差异而不可复现。
|
||||
|
||||
- 复算命令:
|
||||
- python scripts/verify_topn.py --db data/experiments.sqlite --topn 10 --config <CONF> --rawdir data/raw
|
||||
|
||||
输出:
|
||||
- 每个 trial 的原始指标 vs 复算指标差异
|
||||
- 标记不一致(超过容忍阈值)的 trial
|
||||
|
||||
## 5) 更新 best 与汇报规则
|
||||
|
||||
- 只有在满足:
|
||||
- ann_return 相比 last_reported_ann_return 提升 >= 5pp
|
||||
- 且 Top-N 复算一致
|
||||
- 且风险约束不恶化
|
||||
|
||||
才更新 data/opt_state.json 的 last_reported_ann_return 并对外汇报。
|
||||
|
||||
## 6) 借鉴四大流派(落成 模块 + 指标)
|
||||
|
||||
- 趋势:多周期一致性、风险调整动量
|
||||
- 均值回归:偏离/回归信号(用于降低回撤/提高夏普)
|
||||
- 风险/宏观:PCA/absorption ratio/相关性升高时降风险
|
||||
- 相对价值/结构:强弱腿替换、组内中性、主题子宇宙
|
||||
|
||||
要求:每个模块都要
|
||||
- 可开关(参数化)
|
||||
- 可记录原因(trades/日志中写入 reason 字段)
|
||||
- 可对比(A/B vs baseline)
|
||||
|
||||
## 7) 迭代准则(用户确认)
|
||||
|
||||
- 当已有一个还可以的策略(例如年化 25%+)后:
|
||||
- 必须以该基础策略为主框架逐步叠加技巧与改进
|
||||
- 不要换一套完全不同的思路/框架
|
||||
- 每次微调的因子不超过 4 个(单次改动可归因、可回滚、可复现)
|
||||
Reference in New Issue
Block a user