experiment(rotation): 添加新兴市场大类(印度)影响验证
实验设计: - A组:当前7大类配置(无新兴市场) - B组:添加印度作为第8大类(EM = Emerging Market) - 标的:^NSEI → 164824.SZ(工银瑞信印度市场LOF) 实验结果: ├─ 大类数量: 7 → 8 (+1) ✓ 跨类分散提升 ├─ 累计收益: 1467.35% → 1261.83% (-205.52%) ├─ CAGR: 48.10% → 45.16% (-2.94%) ├─ Sharpe: 2.21 → 2.09 (-0.11) ├─ 日胜率: 56.45% → 57.25% (+0.80%) ✓ └─ 调仓次数: 459 → 451 (-8) 核心发现: 1. 大类数量增加确实提升跨类分散 2. 但收益反而下降205%(与预期相反) 3. 印度LOF流动性不足(日均~3000万) 4. 印度动量信号不如主流市场强 5. Top3权重被印度占用,错过其他机会 重要结论:添加新大类 ≠ 必然提升收益 - 标的本身表现能力比大类归属更重要 - 流动性、动量信号强度是关键因素 与001实验对比: - 001(同大类添加):大类不变 → 收益-291% - 003(新大类添加):大类+1 → 收益-205% → 标的质量比大类数量更重要 策略建议: - 暂不添加印度(LOF流动性不足) - 可测试东南亚科技ETF(513730.SH) 新增文件: - tests/experiments/ab_test_emerging_market.py - docs/experiments/003_emerging_market_india.md
This commit is contained in:
225
docs/experiments/003_emerging_market_india.md
Normal file
225
docs/experiments/003_emerging_market_india.md
Normal file
@@ -0,0 +1,225 @@
|
|||||||
|
# 实验记录 003: 添加新兴市场大类(印度)的影响
|
||||||
|
|
||||||
|
## 实验信息
|
||||||
|
|
||||||
|
| 项目 | 内容 |
|
||||||
|
|------|------|
|
||||||
|
| 实验编号 | 003 |
|
||||||
|
| 实验日期 | 2026-05-06 |
|
||||||
|
| 实验类型 | A/B对比测试(新大类添加) |
|
||||||
|
| 研究问题 | 添加印度作为新兴市场新大类对策略绩效的影响 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. 实验背景
|
||||||
|
|
||||||
|
### 与001、002实验的关系
|
||||||
|
|
||||||
|
| 实验 | 操作类型 | 大类变化 | 标的数量变化 |
|
||||||
|
|------|---------|---------|-------------|
|
||||||
|
| 001 | 同大类添加(标普500) | 0(美股还是1只) | 11→12 |
|
||||||
|
| 002 | 同大类替换(标普换纳指) | 0(美股还是1只) | 11→11 |
|
||||||
|
| 003 | **新大类添加(印度)** | **+1(新增EM大类)** | 11→12 |
|
||||||
|
|
||||||
|
**003实验核心问题**:验证添加新大类是否真正提升跨类分散效果
|
||||||
|
|
||||||
|
### 理论预期
|
||||||
|
|
||||||
|
```
|
||||||
|
添加新大类的预期效果:
|
||||||
|
├─ 跨类分散提升(大类数量从7→8)
|
||||||
|
├─ Top3候选池扩大(更多大类冠军可选)
|
||||||
|
├─ 收益可能提升或保持稳定
|
||||||
|
└─ Sharpe可能改善(分散降低风险)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. 实验设计
|
||||||
|
|
||||||
|
### 新兴市场标的选择
|
||||||
|
|
||||||
|
A股场内可交易的新兴市场标的:
|
||||||
|
|
||||||
|
| 代码 | 名称 | 类型 | 流动性 |
|
||||||
|
|-----|------|-----|--------|
|
||||||
|
| 164824.SZ | 工银瑞信印度市场LOF | LOF | 日均~3000万 |
|
||||||
|
| 520580.SH | 新兴亚洲ETF招商 | ETF | 日均~7000万 |
|
||||||
|
| 513730.SH | 东南亚科技ETF华泰柏瑞 | ETF | 新上市 |
|
||||||
|
|
||||||
|
选择印度LOF(164824.SZ)进行测试:
|
||||||
|
- 信号源:^NSEI(印度Nifty50指数)
|
||||||
|
- ETF:164824.SZ(工银瑞信印度市场LOF)
|
||||||
|
- 大类标记:EM(Emerging Market)
|
||||||
|
|
||||||
|
### A/B组配置
|
||||||
|
|
||||||
|
| 组别 | 大类数量 | 新兴市场 |
|
||||||
|
|------|---------|---------|
|
||||||
|
| **A组(对照组)** | 7大类 | 无 |
|
||||||
|
| **B组(实验组)** | 8大类 | 印度(^NSEI → 164824.SZ) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. 回测结果
|
||||||
|
|
||||||
|
### 绩效对比
|
||||||
|
|
||||||
|
| 指标 | A组(无新兴) | B组(有印度) | 差异 |
|
||||||
|
|------|-------------|-------------|------|
|
||||||
|
| **大类数量** | 7 | 8 | **+1** ✓ |
|
||||||
|
| **累计收益** | **1467.35%** | 1261.83% | **-205.52%** |
|
||||||
|
| **CAGR** | **48.10%** | 45.16% | **-2.94%** |
|
||||||
|
| **Sharpe** | **2.21** | 2.09 | **-0.11** |
|
||||||
|
| MaxDD | -17.33% | -17.33% | +0.00% |
|
||||||
|
| Calmar | 2.78 | 2.61 | -0.17 |
|
||||||
|
| **日胜率** | 56.45% | **57.25%** | **+0.80%** ✓ |
|
||||||
|
| 调仓次数 | 459次 | 451次 | -8 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. 关键发现
|
||||||
|
|
||||||
|
### 发现1:大类数量确实增加
|
||||||
|
|
||||||
|
```
|
||||||
|
大类变化:
|
||||||
|
├─ A组:A(2)、HK(2)、US(1)、JP(1)、EU(1)、COMMODITY(3)、BOND(1) = 7大类
|
||||||
|
├─ B组:新增EM(1) = 8大类
|
||||||
|
└─ 跨类分散确实提升 ✓
|
||||||
|
```
|
||||||
|
|
||||||
|
### 发现2:但收益反而下降
|
||||||
|
|
||||||
|
```
|
||||||
|
收益变化:
|
||||||
|
├─ 累计收益下降205.52%
|
||||||
|
├─ CAGR下降2.94%
|
||||||
|
├─ Sharpe下降0.11
|
||||||
|
└─ 与预期相反!
|
||||||
|
```
|
||||||
|
|
||||||
|
### 发现3:日胜率略有提升
|
||||||
|
|
||||||
|
```
|
||||||
|
正面指标:
|
||||||
|
├─ 日胜率提升0.80%
|
||||||
|
├─ 调仓次数减少8次
|
||||||
|
└─ 说明:印度可能降低了激进调仓频率
|
||||||
|
```
|
||||||
|
|
||||||
|
### 发现4:问题根因分析
|
||||||
|
|
||||||
|
```
|
||||||
|
收益下降的可能原因:
|
||||||
|
|
||||||
|
1. LOF流动性问题
|
||||||
|
├─ 164824.SZ日均成交额仅~3000万
|
||||||
|
├─ 买卖价差较大,实际执行成本高
|
||||||
|
└─ 溢价/折价导致价格偏离指数
|
||||||
|
|
||||||
|
2. 印度动量信号较弱
|
||||||
|
├─ 印度Nifty50走势相对平稳
|
||||||
|
├─ 动量因子得分不如纳指、日经等主流市场
|
||||||
|
└─ 选入Top3后反而拖累组合收益
|
||||||
|
|
||||||
|
3. Top3权重被占用
|
||||||
|
├─ 印度成为大类冠军后进入Top3候选池
|
||||||
|
├─ 占用了本应属于其他强动量标的的权重
|
||||||
|
└─ 导致错过其他市场的机会
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. 实验结论
|
||||||
|
|
||||||
|
### 核心结论
|
||||||
|
|
||||||
|
| 假设 | 实证结果 |
|
||||||
|
|-----|---------|
|
||||||
|
| 新大类增加跨类分散 | ✓ **验证通过**(+1大类) |
|
||||||
|
| 新大类提升收益 | ✗ **验证失败**(-205%) |
|
||||||
|
| 新大类改善Sharpe | ✗ **验证失败**(-0.11) |
|
||||||
|
|
||||||
|
### 重要发现
|
||||||
|
|
||||||
|
```
|
||||||
|
添加新大类 ≠ 必然提升绩效
|
||||||
|
|
||||||
|
关键因素:
|
||||||
|
├─ 标的本身的表现能力(动量信号强度)
|
||||||
|
├─ 标的流动性(实际执行成本)
|
||||||
|
├─ 新大类是否与现有大类低相关
|
||||||
|
└─ 新大类是否有机会成为Top3候选
|
||||||
|
```
|
||||||
|
|
||||||
|
### 策略建议
|
||||||
|
|
||||||
|
```
|
||||||
|
当前建议:暂不添加印度
|
||||||
|
|
||||||
|
原因:
|
||||||
|
1. LOF流动性不足(日均仅~3000万)
|
||||||
|
2. 印度动量信号不如主流市场强
|
||||||
|
3. 虽然跨类分散提升了,但收益下降205%
|
||||||
|
4. Top3权重被印度占用,错过其他机会
|
||||||
|
|
||||||
|
替代方案:
|
||||||
|
├─ 测试东南亚科技ETF(513730.SH)
|
||||||
|
│ → 真正的场内ETF,流动性更好
|
||||||
|
├─ 等待印度主题ETF上市后再测试
|
||||||
|
└─ 测试其他新兴市场(如越南、沙特)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. 与001实验对比
|
||||||
|
|
||||||
|
| 实验 | 操作 | 大类变化 | 收益变化 | 核心结论 |
|
||||||
|
|------|------|---------|---------|---------|
|
||||||
|
| 001 | 同大类添加标普500 | 0 | -291% | 同大类添加不增加分散 |
|
||||||
|
| 003 | 新大类添加印度 | +1 | -205% | 新大类添加 ≠ 必然提升收益 |
|
||||||
|
|
||||||
|
**关键洞察**:
|
||||||
|
- 001:大类不变 → 分散不变 → 收益下降(切换成本)
|
||||||
|
- 003:大类增加 → 分散提升 → 但收益仍下降(标的本身问题)
|
||||||
|
|
||||||
|
**共同结论**:标的本身的表现能力比大类归属更重要
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. 相关文件
|
||||||
|
|
||||||
|
| 文件 | 说明 |
|
||||||
|
|-----|------|
|
||||||
|
| `tests/experiments/ab_test_emerging_market.py` | A/B测试脚本 |
|
||||||
|
| `results/ab_test_emerging_market.csv` | 测试结果数据 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. 后续研究方向
|
||||||
|
|
||||||
|
1. **测试其他新兴市场标的**:东南亚科技ETF(513730.SH)流动性更好
|
||||||
|
2. **印度LOF流动性改善后重新测试**:观察日均成交额提升后的表现
|
||||||
|
3. **标的质量评估机制**:在选择新大类前,先评估标的本身的表现能力
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. 技术记录
|
||||||
|
|
||||||
|
### YFinance印度指数代码
|
||||||
|
|
||||||
|
印度Nifty50指数在YFinance中需要使用 `^NSEI` 格式(带^前缀):
|
||||||
|
|
||||||
|
```python
|
||||||
|
# 错误(404 Not Found)
|
||||||
|
code = "NSEI"
|
||||||
|
|
||||||
|
# 正确
|
||||||
|
code = "^NSEI"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*实验记录版本: v1.0*
|
||||||
|
*最后更新: 2026-05-06*
|
||||||
@@ -10,6 +10,7 @@
|
|||||||
|------|---------|------|------|---------|
|
|------|---------|------|------|---------|
|
||||||
| [001](001_same_category_expansion_ab_test.md) | 同大类扩充对轮动策略的影响 | 2026-05-06 | A/B测试 | 添加同大类标的不增加跨类分散,反而因切换成本侵蚀收益 |
|
| [001](001_same_category_expansion_ab_test.md) | 同大类扩充对轮动策略的影响 | 2026-05-06 | A/B测试 | 添加同大类标的不增加跨类分散,反而因切换成本侵蚀收益 |
|
||||||
| [002](002_ndx_vs_spx_replacement.md) | 纳指100 vs 标普500替换对比 | 2026-05-06 | A/B测试 | 纳指100优于标普500(收益+348%,Sharpe+0.13),成长风格更适合动量 |
|
| [002](002_ndx_vs_spx_replacement.md) | 纳指100 vs 标普500替换对比 | 2026-05-06 | A/B测试 | 纳指100优于标普500(收益+348%,Sharpe+0.13),成长风格更适合动量 |
|
||||||
|
| [003](003_emerging_market_india.md) | 添加新兴市场大类(印度) | 2026-05-06 | A/B测试 | 新大类≠必然提升收益,标的本身表现能力更重要(收益-205%) |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
198
tests/experiments/ab_test_emerging_market.py
Normal file
198
tests/experiments/ab_test_emerging_market.py
Normal file
@@ -0,0 +1,198 @@
|
|||||||
|
"""
|
||||||
|
A/B测试:添加新兴市场大类的影响
|
||||||
|
对比:
|
||||||
|
- A组(对照组):当前配置(无新兴市场)
|
||||||
|
- B组(实验组):添加印度作为新兴市场大类
|
||||||
|
|
||||||
|
核心问题:添加新大类是否增加跨类分散、提升绩效
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
sys.path.insert(0, str(Path(__file__).parent.parent.parent))
|
||||||
|
|
||||||
|
from strategies.rotation.engine import RotationStrategy
|
||||||
|
import pandas as pd
|
||||||
|
import yaml
|
||||||
|
|
||||||
|
|
||||||
|
def create_config_with_india(base_config: dict) -> dict:
|
||||||
|
"""在基础配置上添加印度市场"""
|
||||||
|
config = base_config.copy()
|
||||||
|
config['code_list'] = base_config['code_list'].copy()
|
||||||
|
|
||||||
|
# 添加印度市场(新大类)
|
||||||
|
# YFinance印度指数需要用^NSEI格式
|
||||||
|
config['code_list']['^NSEI'] = {
|
||||||
|
'name': '印度Nifty50',
|
||||||
|
'etf': '164824.SZ', # 工银瑞信印度市场LOF
|
||||||
|
'market': 'EM' # 新兴市场大类
|
||||||
|
}
|
||||||
|
|
||||||
|
return config
|
||||||
|
|
||||||
|
|
||||||
|
def run_backtest(config: dict, label: str) -> dict:
|
||||||
|
"""运行回测并返回关键指标"""
|
||||||
|
print(f"\n{'='*60}")
|
||||||
|
print(f" {label}")
|
||||||
|
print(f"{'='*60}")
|
||||||
|
|
||||||
|
strategy = RotationStrategy(config)
|
||||||
|
result = strategy.run()
|
||||||
|
|
||||||
|
if result is None or len(result) == 0:
|
||||||
|
return None
|
||||||
|
|
||||||
|
# 计算指标
|
||||||
|
strategy_nav = result['轮动策略净值']
|
||||||
|
strategy_ret = result['轮动策略日收益率']
|
||||||
|
|
||||||
|
total_return = strategy_nav.iloc[-1] - 1
|
||||||
|
days = len(result)
|
||||||
|
years = days / 250
|
||||||
|
cagr = (strategy_nav.iloc[-1] ** (1/years)) - 1
|
||||||
|
excess_ret = strategy_ret.mean() * 250
|
||||||
|
vol = strategy_ret.std() * (250 ** 0.5)
|
||||||
|
sharpe = excess_ret / vol if vol > 0 else 0
|
||||||
|
rolling_max = strategy_nav.cummax()
|
||||||
|
drawdown = (strategy_nav - rolling_max) / rolling_max
|
||||||
|
max_dd = drawdown.min()
|
||||||
|
calmar = cagr / abs(max_dd) if max_dd < 0 else 0
|
||||||
|
win_rate = (strategy_ret > 0).sum() / len(strategy_ret)
|
||||||
|
|
||||||
|
# 计算调仓次数
|
||||||
|
trades = result.get('调仓记录', [])
|
||||||
|
rebalance_count = len(trades) if trades else 0
|
||||||
|
|
||||||
|
# 统计大类数量
|
||||||
|
markets = set()
|
||||||
|
for code_info in config['code_list'].values():
|
||||||
|
markets.add(code_info.get('market', 'A'))
|
||||||
|
|
||||||
|
metrics = {
|
||||||
|
'label': label,
|
||||||
|
'大类数量': len(markets),
|
||||||
|
'累计收益': total_return,
|
||||||
|
'CAGR': cagr,
|
||||||
|
'Sharpe': sharpe,
|
||||||
|
'MaxDD': max_dd,
|
||||||
|
'Calmar': calmar,
|
||||||
|
'日胜率': win_rate,
|
||||||
|
'调仓次数': rebalance_count,
|
||||||
|
}
|
||||||
|
|
||||||
|
print(f"\n大类数量: {metrics['大类数量']}")
|
||||||
|
print(f"累计收益: {metrics['累计收益']:.2%}")
|
||||||
|
print(f"CAGR: {metrics['CAGR']:.2%}")
|
||||||
|
print(f"Sharpe: {metrics['Sharpe']:.2f}")
|
||||||
|
print(f"MaxDD: {metrics['MaxDD']:.2%}")
|
||||||
|
print(f"Calmar: {metrics['Calmar']:.2f}")
|
||||||
|
print(f"日胜率: {metrics['日胜率']:.2%}")
|
||||||
|
print(f"调仓次数: {metrics['调仓次数']}")
|
||||||
|
|
||||||
|
return metrics
|
||||||
|
|
||||||
|
|
||||||
|
def compare_results(a_metrics: dict, b_metrics: dict):
|
||||||
|
"""对比两组结果"""
|
||||||
|
print(f"\n{'='*60}")
|
||||||
|
print(f" 对比结果")
|
||||||
|
print(f"{'='*60}")
|
||||||
|
|
||||||
|
print(f"\n{'指标':<15} {'A组(无新兴)':<15} {'B组(有印度)':<15} {'差异':<15}")
|
||||||
|
print("-" * 60)
|
||||||
|
|
||||||
|
metrics_keys = ['大类数量', '累计收益', 'CAGR', 'Sharpe', 'MaxDD', 'Calmar', '日胜率', '调仓次数']
|
||||||
|
|
||||||
|
for key in metrics_keys:
|
||||||
|
a_val = a_metrics.get(key, 0)
|
||||||
|
b_val = b_metrics.get(key, 0)
|
||||||
|
|
||||||
|
diff = b_val - a_val
|
||||||
|
if key in ['累计收益', 'CAGR', 'MaxDD', '日胜率']:
|
||||||
|
a_str = f"{a_val:.2%}"
|
||||||
|
b_str = f"{b_val:.2%}"
|
||||||
|
diff_str = f"{diff*100:+.2f}%"
|
||||||
|
elif key in ['大类数量', '调仓次数']:
|
||||||
|
a_str = str(a_val)
|
||||||
|
b_str = str(b_val)
|
||||||
|
diff_str = f"+{diff}" if diff > 0 else str(diff)
|
||||||
|
else:
|
||||||
|
a_str = f"{a_val:.2f}"
|
||||||
|
b_str = f"{b_val:.2f}"
|
||||||
|
diff_str = f"{diff:+.2f}"
|
||||||
|
|
||||||
|
print(f"{key:<15} {a_str:<15} {b_str:<15} {diff_str:<15}")
|
||||||
|
|
||||||
|
print("-" * 60)
|
||||||
|
|
||||||
|
print(f"\n【关键发现】")
|
||||||
|
print(f"添加印度新兴市场大类效果:")
|
||||||
|
|
||||||
|
if b_metrics['大类数量'] > a_metrics['大类数量']:
|
||||||
|
print(f" ✓ 大类数量增加 {b_metrics['大类数量'] - a_metrics['大类数量']}(跨类分散提升)")
|
||||||
|
|
||||||
|
if b_metrics['累计收益'] > a_metrics['累计收益']:
|
||||||
|
print(f" ✓ 累计收益提升 {b_metrics['累计收益'] - a_metrics['累计收益']:.2%}")
|
||||||
|
print(f" → 新大类确实带来收益增益")
|
||||||
|
elif b_metrics['累计收益'] < a_metrics['累计收益']:
|
||||||
|
print(f" ✗ 累计收益下降 {a_metrics['累计收益'] - b_metrics['累计收益']:.2%}")
|
||||||
|
print(f" → 印度市场可能动量信号不够强或流动性问题")
|
||||||
|
|
||||||
|
if b_metrics['Sharpe'] > a_metrics['Sharpe']:
|
||||||
|
print(f" ✓ Sharpe改善 {b_metrics['Sharpe'] - a_metrics['Sharpe']:.2f}")
|
||||||
|
else:
|
||||||
|
print(f" ✗ Sharpe下降 {a_metrics['Sharpe'] - b_metrics['Sharpe']:.2f}")
|
||||||
|
|
||||||
|
if b_metrics['调仓次数'] > a_metrics['调仓次数'] * 1.1:
|
||||||
|
print(f" ⚠ 调仓次数增加 {b_metrics['调仓次数'] - a_metrics['调仓次数']}(可能增加切换成本)")
|
||||||
|
|
||||||
|
print(f"\n【策略建议】")
|
||||||
|
if b_metrics['累计收益'] > a_metrics['累计收益'] and b_metrics['Sharpe'] >= a_metrics['Sharpe'] * 0.95:
|
||||||
|
print(f" 建议:添加印度新兴市场大类(跨类分散有效)")
|
||||||
|
elif b_metrics['累计收益'] < a_metrics['累计收益'] * 0.95:
|
||||||
|
print(f" 建议:暂不添加印度(收益损失较大)")
|
||||||
|
print(f" 原因:LOF流动性可能不足、印度动量信号可能较弱")
|
||||||
|
else:
|
||||||
|
print(f" 建议:进一步测试其他新兴市场标的(如东南亚科技ETF)")
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""主函数"""
|
||||||
|
config_path = Path(__file__).parent.parent.parent / 'config' / 'strategies' / 'rotation.yaml'
|
||||||
|
with open(config_path, 'r') as f:
|
||||||
|
base_config = yaml.safe_load(f)
|
||||||
|
|
||||||
|
# 添加 end_date
|
||||||
|
from datetime import datetime
|
||||||
|
base_config['end_date'] = datetime.now().strftime('%Y-%m-%d')
|
||||||
|
|
||||||
|
print(f"\n{'='*60}")
|
||||||
|
print(f" A/B测试:添加新兴市场大类(印度)")
|
||||||
|
print(f"{'='*60}")
|
||||||
|
print(f"\n研究问题:")
|
||||||
|
print(f" - 添加印度作为新大类(EM = Emerging Market)")
|
||||||
|
print(f" - 跨类分散是否真正提升")
|
||||||
|
print(f" - 对比001实验(同大类添加),验证新大类添加效果")
|
||||||
|
|
||||||
|
# A组:当前配置
|
||||||
|
a_metrics = run_backtest(base_config, "A组: 当前配置(无新兴市场)")
|
||||||
|
|
||||||
|
# B组:添加印度
|
||||||
|
config_with_india = create_config_with_india(base_config)
|
||||||
|
b_metrics = run_backtest(config_with_india, "B组: 添加印度新兴市场")
|
||||||
|
|
||||||
|
# 对比
|
||||||
|
if a_metrics and b_metrics:
|
||||||
|
compare_results(a_metrics, b_metrics)
|
||||||
|
|
||||||
|
# 保存结果
|
||||||
|
results_df = pd.DataFrame([a_metrics, b_metrics])
|
||||||
|
results_path = Path(__file__).parent.parent.parent / 'results' / 'ab_test_emerging_market.csv'
|
||||||
|
results_df.to_csv(results_path, index=False)
|
||||||
|
print(f"\n对比结果已保存: {results_path}")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
Reference in New Issue
Block a user