From 1fca536c950cfe14ed9f16d452231eaf06f0f80a Mon Sep 17 00:00:00 2001 From: aszerW Date: Mon, 11 May 2026 23:34:23 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E5=BD=92=E6=A1=A3=E6=97=A7?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=EF=BC=8C=E4=BF=9D=E7=95=99=E6=96=B0=E6=A1=86?= =?UTF-8?q?=E6=9E=B6=E7=BB=93=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 归档内容: - core/ (数据源、因子计算、通用工具) → archive/legacy_core/ - strategies/rotation/engine.py, portfolio.py, report.py → archive/legacy_core/ - scripts/ (run_rotation, daily_scheduler) → archive/legacy_scripts/ - examples/ → archive/legacy_examples/ - tests/ (实验、对比测试) → archive/legacy_tests/ - 单独文件 (fetch_*.py, 动量.py, 全球市场.py等) → archive/single_files/ 保留新结构: - framework/ (抽象接口) - strategies/shared/ (定制组件) - strategies/rotation/strategy.py (新策略) - 外层配置: .env, .dockerignore, build-and-push.sh, hk_ecs.pem, README.md, requirements.txt - Docker相关: Dockerfile, Dockerfile_base, docker-compose.yml 更新README反映新框架架构 --- README.md | 311 +++++++++--------- archive/README.md | 69 ++++ .../legacy_core/core}/__init__.py | 0 .../legacy_core/core}/common/__init__.py | 0 .../legacy_core/core}/common/db.py | 0 .../legacy_core/core}/common/notify.py | 0 .../legacy_core/core}/common/oss_utils.py | 0 .../legacy_core/core}/common/utils.py | 0 .../legacy_core/core}/datasource/__init__.py | 0 .../core}/datasource/akshare_source.py | 0 .../legacy_core/core}/datasource/base.py | 0 .../legacy_core/core}/datasource/cache.py | 0 .../core}/datasource/flask_server.py | 0 .../core}/datasource/hybrid_source.py | 0 .../core}/datasource/socks2http.py | 0 .../core}/datasource/universal_fetcher.py | 0 .../core}/datasource/yfinance_source.py | 0 .../legacy_core/core}/factors/__init__.py | 0 .../legacy_core/core}/factors/momentum.py | 0 .../legacy_core/core}/factors/technical.py | 0 .../legacy_core}/engine.py | 0 .../legacy_core}/portfolio.py | 0 .../legacy_core}/report.py | 0 .../examples}/flask_api_client.py | 0 .../examples}/universal_fetcher_examples.py | 0 .../scripts}/daily_scheduler.py | 0 .../scripts}/run_cci_screener.py | 0 .../legacy_scripts/scripts}/run_rotation.py | 0 .../legacy_tests/tests}/__init__.py | 0 .../tests}/experiments/__init__.py | 0 .../experiments/ab_test_emerging_market.py | 0 .../tests}/experiments/ab_test_france.py | 0 .../experiments/ab_test_france_in_eu.py | 0 .../tests}/experiments/ab_test_iterations.py | 0 .../tests}/experiments/ab_test_ndx_vs_spx.py | 0 .../tests}/experiments/ab_test_sea_etf.py | 0 .../tests}/experiments/ab_test_spx.py | 0 .../experiments/analyze_negative_scores.py | 0 .../experiments/full_pool_top3_backtest.py | 0 .../tests}/experiments/momentum_experiment.py | 0 .../tests}/experiments/test_select_num.py | 0 .../legacy_tests/tests}/fetch_3033.py | 0 .../legacy_tests/tests}/fetch_au9999.py | 0 .../legacy_tests/tests}/fetch_btc_okx.py | 0 .../tests}/framework_comparison_test.py | 0 .../tests}/full_backtest_comparison.py | 0 .../legacy_tests/tests}/test_flask_api.py | 0 .../legacy_tests/tests}/test_ssh_tunnel.py | 0 .../tests}/test_universal_fetcher.py | 0 .../legacy_tests/tests}/utils/__init__.py | 0 .../tests}/utils/build_etf_universe.py | 0 .../tests}/utils/etf_data_cache.py | 0 .../tests}/utils/export_rotation_data.py | 0 .../single_files/Dockerfile.flask | 0 .../single_files/fetch_159516_nav.py | 0 .../single_files/fetch_159930.py | 0 .../single_files/index_basic.csv | 0 .../single_files/index_fund_info.csv | 0 .../single_files/start_flask_server.sh | 0 .../single_files/全球市场.py | 0 动量.py => archive/single_files/动量.py | 0 61 files changed, 221 insertions(+), 159 deletions(-) create mode 100644 archive/README.md rename {core => archive/legacy_core/core}/__init__.py (100%) rename {core => archive/legacy_core/core}/common/__init__.py (100%) rename {core => archive/legacy_core/core}/common/db.py (100%) rename {core => archive/legacy_core/core}/common/notify.py (100%) rename {core => archive/legacy_core/core}/common/oss_utils.py (100%) rename {core => archive/legacy_core/core}/common/utils.py (100%) rename {core => archive/legacy_core/core}/datasource/__init__.py (100%) rename {core => archive/legacy_core/core}/datasource/akshare_source.py (100%) rename {core => archive/legacy_core/core}/datasource/base.py (100%) rename {core => archive/legacy_core/core}/datasource/cache.py (100%) rename {core => archive/legacy_core/core}/datasource/flask_server.py (100%) rename {core => archive/legacy_core/core}/datasource/hybrid_source.py (100%) rename {core => archive/legacy_core/core}/datasource/socks2http.py (100%) rename {core => archive/legacy_core/core}/datasource/universal_fetcher.py (100%) rename {core => archive/legacy_core/core}/datasource/yfinance_source.py (100%) rename {core => archive/legacy_core/core}/factors/__init__.py (100%) rename {core => archive/legacy_core/core}/factors/momentum.py (100%) rename {core => archive/legacy_core/core}/factors/technical.py (100%) rename {strategies/rotation => archive/legacy_core}/engine.py (100%) rename {strategies/rotation => archive/legacy_core}/portfolio.py (100%) rename {strategies/rotation => archive/legacy_core}/report.py (100%) rename {examples => archive/legacy_examples/examples}/flask_api_client.py (100%) rename {examples => archive/legacy_examples/examples}/universal_fetcher_examples.py (100%) rename {scripts => archive/legacy_scripts/scripts}/daily_scheduler.py (100%) rename {scripts => archive/legacy_scripts/scripts}/run_cci_screener.py (100%) rename {scripts => archive/legacy_scripts/scripts}/run_rotation.py (100%) rename {tests => archive/legacy_tests/tests}/__init__.py (100%) rename {tests => archive/legacy_tests/tests}/experiments/__init__.py (100%) rename {tests => archive/legacy_tests/tests}/experiments/ab_test_emerging_market.py (100%) rename {tests => archive/legacy_tests/tests}/experiments/ab_test_france.py (100%) rename {tests => archive/legacy_tests/tests}/experiments/ab_test_france_in_eu.py (100%) rename {tests => archive/legacy_tests/tests}/experiments/ab_test_iterations.py (100%) rename {tests => archive/legacy_tests/tests}/experiments/ab_test_ndx_vs_spx.py (100%) rename {tests => archive/legacy_tests/tests}/experiments/ab_test_sea_etf.py (100%) rename {tests => archive/legacy_tests/tests}/experiments/ab_test_spx.py (100%) rename {tests => archive/legacy_tests/tests}/experiments/analyze_negative_scores.py (100%) rename {tests => archive/legacy_tests/tests}/experiments/full_pool_top3_backtest.py (100%) rename {tests => archive/legacy_tests/tests}/experiments/momentum_experiment.py (100%) rename {tests => archive/legacy_tests/tests}/experiments/test_select_num.py (100%) rename {tests => archive/legacy_tests/tests}/fetch_3033.py (100%) rename {tests => archive/legacy_tests/tests}/fetch_au9999.py (100%) rename {tests => archive/legacy_tests/tests}/fetch_btc_okx.py (100%) rename {tests => archive/legacy_tests/tests}/framework_comparison_test.py (100%) rename {tests => archive/legacy_tests/tests}/full_backtest_comparison.py (100%) rename {tests => archive/legacy_tests/tests}/test_flask_api.py (100%) rename {tests => archive/legacy_tests/tests}/test_ssh_tunnel.py (100%) rename {tests => archive/legacy_tests/tests}/test_universal_fetcher.py (100%) rename {tests => archive/legacy_tests/tests}/utils/__init__.py (100%) rename {tests => archive/legacy_tests/tests}/utils/build_etf_universe.py (100%) rename {tests => archive/legacy_tests/tests}/utils/etf_data_cache.py (100%) rename {tests => archive/legacy_tests/tests}/utils/export_rotation_data.py (100%) rename Dockerfile.flask => archive/single_files/Dockerfile.flask (100%) rename fetch_159516_nav.py => archive/single_files/fetch_159516_nav.py (100%) rename fetch_159930.py => archive/single_files/fetch_159930.py (100%) rename index_basic.csv => archive/single_files/index_basic.csv (100%) rename index_fund_info.csv => archive/single_files/index_fund_info.csv (100%) rename start_flask_server.sh => archive/single_files/start_flask_server.sh (100%) rename 全球市场.py => archive/single_files/全球市场.py (100%) rename 动量.py => archive/single_files/动量.py (100%) diff --git a/README.md b/README.md index 2b5f47c..c308aa5 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -# ETF轮动策略系统 +# ETF轮动策略框架 -基于多因子动量的ETF轮动量化交易系统,支持多市场数据(A股/港股/美股/加密货币),提供回测分析、定时调度和自动通知功能。 +基于抽象接口的量化交易框架,支持因子计算、信号生成、风控管理和回测执行。 ## 架构设计 @@ -9,194 +9,187 @@ │ 应用层 (Applications) │ ├─────────────────────────────────────────────────────────────────────────────┤ │ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ -│ │ run_rotation │ │ daily_scheduler │ │ test_chart │ │ -│ │ (回测入口) │ │ (定时调度) │ │ (图表测试) │ │ -│ └────────┬────────┘ └────────┬────────┘ └─────────────────┘ │ -└───────────┼────────────────────┼──────────────────────────────────────────────┘ - │ │ - ▼ ▼ +│ │ Rotation │ │ Screener │ │ 自定义策略 │ │ +│ │ Strategy │ │ Strategy │ │ (继承框架) │ │ +│ └────────┬────────┘ └────────┬────────┘ └────────┬────────┘ │ +└───────────┼────────────────────┼────────────────────┼─────────────────────────┘ + │ │ │ + ▼ ▼ ▼ ┌─────────────────────────────────────────────────────────────────────────────┐ -│ 策略层 (Strategies) │ +│ 定制组件层 (strategies/shared) │ ├─────────────────────────────────────────────────────────────────────────────┤ -│ ┌─────────────────────────────────────────────────────────────────────┐ │ -│ │ ETF Rotation Strategy │ │ -│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌───────────┐ │ │ -│ │ │ Engine │ │ Report │ │ Portfolio │ │ Signal │ │ │ -│ │ │ (回测引擎) │ │ (报告生成) │ │ (持仓跟踪) │ │ (信号生成) │ │ │ -│ │ └─────────────┘ └─────────────┘ └─────────────┘ └───────────┘ │ │ -│ └─────────────────────────────────────────────────────────────────────┘ │ +│ ┌──────────────────────────────────────────────────────────────────────┐ │ +│ │ factors/ │ signals/ │ risk/ │ data/│ │ +│ │ ├─ MomentumFactor │ ├─ TopNSelector │ ├─ StopLossControl │ ... │ │ +│ │ ├─ TrendFactor │ ├─ TrendFollower │ ├─ PremiumControl │ │ │ +│ │ ├─ ReversalFactor │ ├─ ReversalTrader │ ├─ Callbacks │ │ │ +│ │ └─ VolatilityFactor│ │ │ │ │ +│ └──────────────────────────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────────────────┐ -│ 核心层 (Core) │ +│ 框架抽象层 (framework) │ ├─────────────────────────────────────────────────────────────────────────────┤ -│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ -│ │ Data Sources │ │ Factors │ │ Utils │ │ -│ │ ┌───────────┐ │ │ ┌───────────┐ │ │ ┌───────────┐ │ │ -│ │ │ Tushare │ │ │ │ Momentum │ │ │ │ Metrics │ │ │ -│ │ │ (A股指数) │ │ │ │ (动量因子) │ │ │ │ (绩效计算) │ │ │ -│ │ ├───────────┤ │ │ └───────────┘ │ │ └───────────┘ │ │ -│ │ │ YFinance │ │ │ │ │ │ │ -│ │ │ (港美加密) │ │ │ ┌───────────┐ │ │ ┌───────────┐ │ │ -│ │ ├───────────┤ │ │ │ CCI │ │ │ │ Chart │ │ │ -│ │ │SSH Tunnel │ │ │ │ (CCI因子) │ │ │ │ (图表绘制) │ │ │ -│ │ │(代理支持) │ │ │ └───────────┘ │ │ └───────────┘ │ │ -│ │ └───────────┘ │ │ │ │ │ │ -│ └─────────────────┘ └─────────────────┘ └─────────────────┘ │ -└─────────────────────────────────────────────────────────────────────────────┘ - │ - ▼ -┌─────────────────────────────────────────────────────────────────────────────┐ -│ 基础设施层 (Infrastructure) │ -├─────────────────────────────────────────────────────────────────────────────┤ -│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ -│ │ Notification │ │ OSS Storage │ │ Database │ │ -│ │ ┌───────────┐ │ │ ┌───────────┐ │ │ ┌───────────┐ │ │ -│ │ │ DingTalk │ │ │ │ Aliyun │ │ │ │ PostgreSQL│ │ │ -│ │ │ (钉钉) │ │ │ │ OSS │ │ │ │ │ │ │ -│ │ └───────────┘ │ │ └───────────┘ │ │ └───────────┘ │ │ -│ └─────────────────┘ └─────────────────┘ └─────────────────┘ │ +│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ +│ │ factors/ │ │ signals/ │ │ risk/ │ │ execution/ │ │ +│ │ FactorBase │ │SignalGen │ │ RiskControl │ │ Executor │ │ +│ │ Registry │ │ │ │ CallbackHook│ │ Portfolio │ │ +│ │ Combiner │ │ │ │ Position │ │ │ │ +│ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ │ +│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ +│ │ strategy/ │ │ data/ │ │ config/ │ │ +│ │ StrategyBase│ │ DataSource │ │ ConfigLoader│ │ +│ │ │ │ DataCache │ │ │ │ +│ └─────────────┘ └─────────────┘ └─────────────┘ │ └─────────────────────────────────────────────────────────────────────────────┘ ``` ## 核心特性 -### 1. 多市场数据支持 -- **A股指数**: 通过 Tushare 获取沪深300、中证500等17只指数 -- **港股/美股/加密货币**: 通过 YFinance 获取恒生科技、纳斯达克、BTC、ETH等 -- **交易日历对齐**: 以A股交易日为基准,非A股市场数据前向填充 +### 1. 框架抽象接口(framework) + +只提供抽象基类,不含具体实现: + +- **FactorBase**:因子抽象基类 + FactorRegistry注册器 + FactorCombiner组合器 +- **SignalGenerator**:信号生成抽象基类 +- **RiskControl**:风控抽象基类 + CallbackHook回调机制 +- **StrategyBase**:策略抽象基类(含回调自动注册) +- **Executor/Portfolio**:执行器抽象 + 持仓管理 + +### 2. 定制组件(strategies/shared) + +具体实现,可跨策略复用: + +- **MomentumFactor**:加权线性回归动量 + 崩盘过滤 +- **TrendFactor**:MA交叉/MACD趋势因子 +- **ReversalFactor**:RSI反转信号 +- **TopNSelector**:分散化选股 + 调仓周期控制 +- **StopLossControl**:固定止损/跟踪止损 +- **PremiumControl**:溢价过滤回调 + +### 3. 完整回测执行 -### 2. 混合数据源架构 ```python -# config/strategies/rotation.yaml -ssh_tunnel: - enabled: true - host: "x.x.x.x" # 阿里云香港ECS - key_path: "hk_ecs.pem" # SSH私钥(相对路径) +from framework.execution import BacktestExecutor -data_source: - china_indices: "tushare" - global_indices: "yfinance" +executor = BacktestExecutor( + initial_capital=100000, + trade_cost=0.001, + select_num=3 +) + +portfolio = executor.execute(signals, data) +# 支持日收益率计算、交易成本扣除、净值归一化、基准对比 ``` -### 3. 定时调度系统 -```bash -# 本地运行 -python scripts/daily_scheduler.py - -# Docker运行 -docker run -d --name etf-scheduler \ - -v $(pwd)/hk_ecs.pem:/app/hk_ecs.pem:ro \ - 192.168.0.115:5000/etf-scheduler:latest -``` - -### 4. 自动报告通知 -- 策略绩效对比表格(转置布局) -- 最新调仓信号(支持调入/调出/维持标记) -- 净值曲线、回撤分析、持仓分布 -- 钉钉图文推送(OSS图床) - ## 项目结构 ``` . -├── config/ +├── framework/ # 框架抽象接口 +│ ├── factors/ # FactorBase/Registry/Combiner +│ ├── signals/ # SignalGenerator抽象 +│ ├── risk/ # RiskControl/Position/CallbackHook +│ ├── strategy/ # StrategyBase抽象 +│ ├── execution/ # Executor/Portfolio/BacktestExecutor +│ ├── data/ # DataSource/DataCache抽象 +│ ├── config/ # ConfigLoader配置加载 +│ └── tests/ # 单元测试 +│ +├── strategies/ # 策略实现 +│ ├── shared/ # 定制组件(跨策略复用) +│ │ ├── factors/ # MomentumFactor/TrendFactor等 +│ │ ├── signals/ # TopNSelector/TrendFollower等 +│ │ ├── risk/ # StopLossControl/PremiumControl等 +│ │ └── data/ # HybridDataSourceAdapter等 +│ ├── rotation/ # 轮动策略 +│ │ └── strategy.py # RotationStrategy实现 +│ └── screener/ # CCI选股策略 +│ +├── config/ # 配置文件 │ └── strategies/ -│ └── rotation.yaml # 策略配置(code_list/benchmark/SSH等) -├── core/ -│ ├── common/ -│ │ ├── notify.py # 钉钉通知 -│ │ ├── oss_utils.py # 阿里云OSS -│ │ └── utils.py # 通用工具 -│ ├── data/ -│ │ ├── hybrid_source.py # 混合数据源(Tushare+YFinance) -│ │ └── yfinance_source.py # YFinance数据源 -│ └── factors/ -│ ├── momentum.py # 动量因子计算 -│ └── cci.py # CCI因子计算 -├── strategies/ -│ └── rotation/ -│ ├── engine.py # 回测引擎 -│ ├── report.py # 报告生成 -│ ├── portfolio.py # 持仓跟踪 -│ └── signal.py # 信号生成 -├── scripts/ -│ ├── run_rotation.py # 回测入口 -│ └── daily_scheduler.py # 定时调度 -├── Dockerfile # 应用镜像 -├── Dockerfile_base # 基础镜像 -├── build-and-push.sh # 构建脚本 -└── docker-compose.yml # 部署配置 +│ └── rotation.yaml # 轮动策略配置 +│ +├── visualization/ # 可视化 +│ └── report_generator/ # 报告生成 +│ +├── data/ # 数据目录 +├── docs/ # 文档目录 +├── archive/ # 归档旧代码 +│ +├── .env # 环境变量 +├── .dockerignore # Docker忽略 +├── build-and-push.sh # 构建脚本 +├── docker-compose.yml # Docker部署 +├── Dockerfile # 应用镜像 +├── Dockerfile_base # 基础镜像 +├── hk_ecs.pem # SSH密钥 +├── README.md # 本文件 +└── requirements.txt # 依赖 ``` ## 快速开始 -### 1. 环境配置 +### 1. 使用新框架 + +```python +from framework import FactorBase, FactorRegistry, SignalGenerator, StrategyBase +from strategies.shared.factors.momentum import MomentumFactor +from strategies.shared.signals.selectors import TopNSelector + +# 注册因子 +FactorRegistry.register(MomentumFactor) + +# 创建因子组合器 +factor = FactorRegistry.get('momentum', n_days=25, crash_filter=True) +combiner = FactorCombiner([factor]) + +# 创建信号生成器(支持分散化选股) +selector = TopNSelector( + select_num=3, + group_mapping={'399006.SZ': 'A', 'NDX': 'US'}, # 按大类分组 + min_score=0.0, # 过滤负分 + rebalance_days=1, # 调仓周期 + rebalance_threshold=0.05 # 调仓阈值 +) + +# 生成信号 +signals = selector.generate(factor_data) +``` + +### 2. 运行测试 + ```bash -# 创建 .env 文件 -cp .env.example .env +# 框架单元测试 +python -m pytest framework/tests/ -v -# 编辑配置 -vim .env +# 对比测试(验证新旧实现一致性) +python tests/full_backtest_comparison.py ``` -### 2. 本地运行 -```bash -# 安装依赖 -pip install -r requirements.txt +## 设计原则 -# 运行回测 -python scripts/run_rotation.py - -# 定时调度 -python scripts/daily_scheduler.py --run-now -``` - -### 3. Docker部署 -```bash -# 构建并推送 -./build-and-push.sh etf-scheduler - -# 运行容器 -docker-compose up -d -``` - -## 配置说明 - -### rotation.yaml -```yaml -# 标的配置(字典格式) -code_list: - "000300.SH": "沪深300" - "HSTECH": "恒生科技" - "BTC": "比特币" - -# 基准配置 -benchmark: - code: "000300.SH" - name: "沪深300指数" - -# SSH隧道(用于YFinance) -ssh_tunnel: - enabled: true - host: "your-ecs-ip" - key_path: "hk_ecs.pem" - -# 回测参数 -start_date: "2020-01-01" -factor_type: "slope_r2" -select_num: 5 -rebalance_days: 1 -``` +| 模块 | 职责 | 位置 | +|------|------|------| +| **抽象接口** | 所有策略共用的基础设施 | framework | +| **定制组件** | 具体实现,可跨策略复用 | strategies/shared | +| **策略实现** | 业务逻辑,使用框架+组件 | strategies/{name} | ## 技术栈 -- **Python 3.12**: 核心语言 -- **Pandas/NumPy**: 数据处理 -- **Matplotlib**: 图表绘制 -- **Tushare/YFinance**: 金融数据 -- **Schedule**: 定时任务 -- **Docker**: 容器化部署 -- **OSS**: 图片存储 -- **DingTalk**: 消息通知 +- **Python 3.12**:核心语言 +- **Pandas/NumPy**:数据处理 +- **PyYAML**:配置加载 +- **scikit-learn**:因子计算(加权回归) +- **pytest**:单元测试 + +## 归档说明 + +旧代码已移动到 `archive/` 目录,包括: +- 原 `core/` 目录(数据源、因子计算) +- 原 `strategies/rotation/engine.py`(旧引擎) +- 原 `scripts/`(旧脚本入口) +- 原 `tests/`(旧测试文件) + +详见 [archive/README.md](archive/README.md) \ No newline at end of file diff --git a/archive/README.md b/archive/README.md new file mode 100644 index 0000000..bd70b87 --- /dev/null +++ b/archive/README.md @@ -0,0 +1,69 @@ +# 归档代码说明 + +本目录存放已重构迁移的旧代码,保留用于参考和过渡期兼容。 + +## 目录结构 + +``` +archive/ +├── legacy_core/ # 旧核心模块 +│ ├── core/ # 原core目录 +│ │ ├── common/ # 通用工具(notify, oss_utils, utils等) +│ │ ├── datasource/ # 数据源(hybrid_source, yfinance_source等) +│ │ └── factors/ # 因子计算(momentum, technical) +│ ├── engine.py # 原轮动策略引擎 +│ ├── portfolio.py # 原持仓跟踪 +│ └── report.py # 原报告生成 +│ +├── legacy_scripts/ # 旧脚本入口 +│ ├── scripts/ +│ │ ├── daily_scheduler.py # 原定时调度 +│ │ ├── run_rotation.py # 原回测入口 +│ │ └── run_cci_screener.py # CCI选股入口 +│ +├── legacy_examples/ # 旧示例文件 +│ ├── examples/ +│ │ ├── flask_api_client.py +│ │ └ universal_fetcher_examples.py +│ +├── legacy_tests/ # 旧测试文件 +│ ├── tests/ +│ │ ├── experiments/ # A/B测试等实验 +│ │ ├── utils/ # 工具测试 +│ │ ├── framework_comparison_test.py +│ │ ├── full_backtest_comparison.py +│ │ └ ... +│ +└── single_files/ # 单独文件 + ├── fetch_159516_nav.py + ├── fetch_159930.py + ├── 动量.py + ├── 全球市场.py + ├── index_basic.csv + ├── index_fund_info.csv + ├── Dockerfile.flask + └── start_flask_server.sh +``` + +## 新框架位置 + +重构后的新代码位于: +- `framework/` - 抽象接口层 +- `strategies/shared/` - 定制组件层 +- `strategies/rotation/strategy.py` - 新策略实现 + +## 过渡说明 + +1. **数据源**:原`core/datasource/hybrid_source.py`功能待迁移到`strategies/shared/data/sources.py` +2. **回测引擎**:原`strategies/rotation/engine.py`功能已迁移到`framework/execution/__init__.py` +3. **因子计算**:原`core/factors/momentum.py`功能已迁移到`strategies/shared/factors/momentum.py` +4. **报告生成**:原`strategies/rotation/report.py`功能保留在`visualization/report_generator/` + +## 归档时间 + +- 日期:2025-05-11 +- 原因:框架抽象化重构,分离通用能力与定制代码 + +--- + +*本目录内容仅供参考,新功能请使用framework和strategies/shared目录* \ No newline at end of file diff --git a/core/__init__.py b/archive/legacy_core/core/__init__.py similarity index 100% rename from core/__init__.py rename to archive/legacy_core/core/__init__.py diff --git a/core/common/__init__.py b/archive/legacy_core/core/common/__init__.py similarity index 100% rename from core/common/__init__.py rename to archive/legacy_core/core/common/__init__.py diff --git a/core/common/db.py b/archive/legacy_core/core/common/db.py similarity index 100% rename from core/common/db.py rename to archive/legacy_core/core/common/db.py diff --git a/core/common/notify.py b/archive/legacy_core/core/common/notify.py similarity index 100% rename from core/common/notify.py rename to archive/legacy_core/core/common/notify.py diff --git a/core/common/oss_utils.py b/archive/legacy_core/core/common/oss_utils.py similarity index 100% rename from core/common/oss_utils.py rename to archive/legacy_core/core/common/oss_utils.py diff --git a/core/common/utils.py b/archive/legacy_core/core/common/utils.py similarity index 100% rename from core/common/utils.py rename to archive/legacy_core/core/common/utils.py diff --git a/core/datasource/__init__.py b/archive/legacy_core/core/datasource/__init__.py similarity index 100% rename from core/datasource/__init__.py rename to archive/legacy_core/core/datasource/__init__.py diff --git a/core/datasource/akshare_source.py b/archive/legacy_core/core/datasource/akshare_source.py similarity index 100% rename from core/datasource/akshare_source.py rename to archive/legacy_core/core/datasource/akshare_source.py diff --git a/core/datasource/base.py b/archive/legacy_core/core/datasource/base.py similarity index 100% rename from core/datasource/base.py rename to archive/legacy_core/core/datasource/base.py diff --git a/core/datasource/cache.py b/archive/legacy_core/core/datasource/cache.py similarity index 100% rename from core/datasource/cache.py rename to archive/legacy_core/core/datasource/cache.py diff --git a/core/datasource/flask_server.py b/archive/legacy_core/core/datasource/flask_server.py similarity index 100% rename from core/datasource/flask_server.py rename to archive/legacy_core/core/datasource/flask_server.py diff --git a/core/datasource/hybrid_source.py b/archive/legacy_core/core/datasource/hybrid_source.py similarity index 100% rename from core/datasource/hybrid_source.py rename to archive/legacy_core/core/datasource/hybrid_source.py diff --git a/core/datasource/socks2http.py b/archive/legacy_core/core/datasource/socks2http.py similarity index 100% rename from core/datasource/socks2http.py rename to archive/legacy_core/core/datasource/socks2http.py diff --git a/core/datasource/universal_fetcher.py b/archive/legacy_core/core/datasource/universal_fetcher.py similarity index 100% rename from core/datasource/universal_fetcher.py rename to archive/legacy_core/core/datasource/universal_fetcher.py diff --git a/core/datasource/yfinance_source.py b/archive/legacy_core/core/datasource/yfinance_source.py similarity index 100% rename from core/datasource/yfinance_source.py rename to archive/legacy_core/core/datasource/yfinance_source.py diff --git a/core/factors/__init__.py b/archive/legacy_core/core/factors/__init__.py similarity index 100% rename from core/factors/__init__.py rename to archive/legacy_core/core/factors/__init__.py diff --git a/core/factors/momentum.py b/archive/legacy_core/core/factors/momentum.py similarity index 100% rename from core/factors/momentum.py rename to archive/legacy_core/core/factors/momentum.py diff --git a/core/factors/technical.py b/archive/legacy_core/core/factors/technical.py similarity index 100% rename from core/factors/technical.py rename to archive/legacy_core/core/factors/technical.py diff --git a/strategies/rotation/engine.py b/archive/legacy_core/engine.py similarity index 100% rename from strategies/rotation/engine.py rename to archive/legacy_core/engine.py diff --git a/strategies/rotation/portfolio.py b/archive/legacy_core/portfolio.py similarity index 100% rename from strategies/rotation/portfolio.py rename to archive/legacy_core/portfolio.py diff --git a/strategies/rotation/report.py b/archive/legacy_core/report.py similarity index 100% rename from strategies/rotation/report.py rename to archive/legacy_core/report.py diff --git a/examples/flask_api_client.py b/archive/legacy_examples/examples/flask_api_client.py similarity index 100% rename from examples/flask_api_client.py rename to archive/legacy_examples/examples/flask_api_client.py diff --git a/examples/universal_fetcher_examples.py b/archive/legacy_examples/examples/universal_fetcher_examples.py similarity index 100% rename from examples/universal_fetcher_examples.py rename to archive/legacy_examples/examples/universal_fetcher_examples.py diff --git a/scripts/daily_scheduler.py b/archive/legacy_scripts/scripts/daily_scheduler.py similarity index 100% rename from scripts/daily_scheduler.py rename to archive/legacy_scripts/scripts/daily_scheduler.py diff --git a/scripts/run_cci_screener.py b/archive/legacy_scripts/scripts/run_cci_screener.py similarity index 100% rename from scripts/run_cci_screener.py rename to archive/legacy_scripts/scripts/run_cci_screener.py diff --git a/scripts/run_rotation.py b/archive/legacy_scripts/scripts/run_rotation.py similarity index 100% rename from scripts/run_rotation.py rename to archive/legacy_scripts/scripts/run_rotation.py diff --git a/tests/__init__.py b/archive/legacy_tests/tests/__init__.py similarity index 100% rename from tests/__init__.py rename to archive/legacy_tests/tests/__init__.py diff --git a/tests/experiments/__init__.py b/archive/legacy_tests/tests/experiments/__init__.py similarity index 100% rename from tests/experiments/__init__.py rename to archive/legacy_tests/tests/experiments/__init__.py diff --git a/tests/experiments/ab_test_emerging_market.py b/archive/legacy_tests/tests/experiments/ab_test_emerging_market.py similarity index 100% rename from tests/experiments/ab_test_emerging_market.py rename to archive/legacy_tests/tests/experiments/ab_test_emerging_market.py diff --git a/tests/experiments/ab_test_france.py b/archive/legacy_tests/tests/experiments/ab_test_france.py similarity index 100% rename from tests/experiments/ab_test_france.py rename to archive/legacy_tests/tests/experiments/ab_test_france.py diff --git a/tests/experiments/ab_test_france_in_eu.py b/archive/legacy_tests/tests/experiments/ab_test_france_in_eu.py similarity index 100% rename from tests/experiments/ab_test_france_in_eu.py rename to archive/legacy_tests/tests/experiments/ab_test_france_in_eu.py diff --git a/tests/experiments/ab_test_iterations.py b/archive/legacy_tests/tests/experiments/ab_test_iterations.py similarity index 100% rename from tests/experiments/ab_test_iterations.py rename to archive/legacy_tests/tests/experiments/ab_test_iterations.py diff --git a/tests/experiments/ab_test_ndx_vs_spx.py b/archive/legacy_tests/tests/experiments/ab_test_ndx_vs_spx.py similarity index 100% rename from tests/experiments/ab_test_ndx_vs_spx.py rename to archive/legacy_tests/tests/experiments/ab_test_ndx_vs_spx.py diff --git a/tests/experiments/ab_test_sea_etf.py b/archive/legacy_tests/tests/experiments/ab_test_sea_etf.py similarity index 100% rename from tests/experiments/ab_test_sea_etf.py rename to archive/legacy_tests/tests/experiments/ab_test_sea_etf.py diff --git a/tests/experiments/ab_test_spx.py b/archive/legacy_tests/tests/experiments/ab_test_spx.py similarity index 100% rename from tests/experiments/ab_test_spx.py rename to archive/legacy_tests/tests/experiments/ab_test_spx.py diff --git a/tests/experiments/analyze_negative_scores.py b/archive/legacy_tests/tests/experiments/analyze_negative_scores.py similarity index 100% rename from tests/experiments/analyze_negative_scores.py rename to archive/legacy_tests/tests/experiments/analyze_negative_scores.py diff --git a/tests/experiments/full_pool_top3_backtest.py b/archive/legacy_tests/tests/experiments/full_pool_top3_backtest.py similarity index 100% rename from tests/experiments/full_pool_top3_backtest.py rename to archive/legacy_tests/tests/experiments/full_pool_top3_backtest.py diff --git a/tests/experiments/momentum_experiment.py b/archive/legacy_tests/tests/experiments/momentum_experiment.py similarity index 100% rename from tests/experiments/momentum_experiment.py rename to archive/legacy_tests/tests/experiments/momentum_experiment.py diff --git a/tests/experiments/test_select_num.py b/archive/legacy_tests/tests/experiments/test_select_num.py similarity index 100% rename from tests/experiments/test_select_num.py rename to archive/legacy_tests/tests/experiments/test_select_num.py diff --git a/tests/fetch_3033.py b/archive/legacy_tests/tests/fetch_3033.py similarity index 100% rename from tests/fetch_3033.py rename to archive/legacy_tests/tests/fetch_3033.py diff --git a/tests/fetch_au9999.py b/archive/legacy_tests/tests/fetch_au9999.py similarity index 100% rename from tests/fetch_au9999.py rename to archive/legacy_tests/tests/fetch_au9999.py diff --git a/tests/fetch_btc_okx.py b/archive/legacy_tests/tests/fetch_btc_okx.py similarity index 100% rename from tests/fetch_btc_okx.py rename to archive/legacy_tests/tests/fetch_btc_okx.py diff --git a/tests/framework_comparison_test.py b/archive/legacy_tests/tests/framework_comparison_test.py similarity index 100% rename from tests/framework_comparison_test.py rename to archive/legacy_tests/tests/framework_comparison_test.py diff --git a/tests/full_backtest_comparison.py b/archive/legacy_tests/tests/full_backtest_comparison.py similarity index 100% rename from tests/full_backtest_comparison.py rename to archive/legacy_tests/tests/full_backtest_comparison.py diff --git a/tests/test_flask_api.py b/archive/legacy_tests/tests/test_flask_api.py similarity index 100% rename from tests/test_flask_api.py rename to archive/legacy_tests/tests/test_flask_api.py diff --git a/tests/test_ssh_tunnel.py b/archive/legacy_tests/tests/test_ssh_tunnel.py similarity index 100% rename from tests/test_ssh_tunnel.py rename to archive/legacy_tests/tests/test_ssh_tunnel.py diff --git a/tests/test_universal_fetcher.py b/archive/legacy_tests/tests/test_universal_fetcher.py similarity index 100% rename from tests/test_universal_fetcher.py rename to archive/legacy_tests/tests/test_universal_fetcher.py diff --git a/tests/utils/__init__.py b/archive/legacy_tests/tests/utils/__init__.py similarity index 100% rename from tests/utils/__init__.py rename to archive/legacy_tests/tests/utils/__init__.py diff --git a/tests/utils/build_etf_universe.py b/archive/legacy_tests/tests/utils/build_etf_universe.py similarity index 100% rename from tests/utils/build_etf_universe.py rename to archive/legacy_tests/tests/utils/build_etf_universe.py diff --git a/tests/utils/etf_data_cache.py b/archive/legacy_tests/tests/utils/etf_data_cache.py similarity index 100% rename from tests/utils/etf_data_cache.py rename to archive/legacy_tests/tests/utils/etf_data_cache.py diff --git a/tests/utils/export_rotation_data.py b/archive/legacy_tests/tests/utils/export_rotation_data.py similarity index 100% rename from tests/utils/export_rotation_data.py rename to archive/legacy_tests/tests/utils/export_rotation_data.py diff --git a/Dockerfile.flask b/archive/single_files/Dockerfile.flask similarity index 100% rename from Dockerfile.flask rename to archive/single_files/Dockerfile.flask diff --git a/fetch_159516_nav.py b/archive/single_files/fetch_159516_nav.py similarity index 100% rename from fetch_159516_nav.py rename to archive/single_files/fetch_159516_nav.py diff --git a/fetch_159930.py b/archive/single_files/fetch_159930.py similarity index 100% rename from fetch_159930.py rename to archive/single_files/fetch_159930.py diff --git a/index_basic.csv b/archive/single_files/index_basic.csv similarity index 100% rename from index_basic.csv rename to archive/single_files/index_basic.csv diff --git a/index_fund_info.csv b/archive/single_files/index_fund_info.csv similarity index 100% rename from index_fund_info.csv rename to archive/single_files/index_fund_info.csv diff --git a/start_flask_server.sh b/archive/single_files/start_flask_server.sh similarity index 100% rename from start_flask_server.sh rename to archive/single_files/start_flask_server.sh diff --git a/全球市场.py b/archive/single_files/全球市场.py similarity index 100% rename from 全球市场.py rename to archive/single_files/全球市场.py diff --git a/动量.py b/archive/single_files/动量.py similarity index 100% rename from 动量.py rename to archive/single_files/动量.py