326 lines
10 KiB
Python
326 lines
10 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
vn.py本地数据适配器测试脚本
|
|
测试赵云数据加载和转换功能
|
|
"""
|
|
|
|
import sys
|
|
import os
|
|
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
|
|
|
from vnpy_local_data_adapter import VnpyLocalDataAdapter
|
|
from data_convert_tool import DataConverter
|
|
import pandas as pd
|
|
import json
|
|
|
|
|
|
def test_adapter_basic():
|
|
"""测试适配器基本功能"""
|
|
print("=" * 60)
|
|
print("测试1: 适配器基本功能")
|
|
print("=" * 60)
|
|
|
|
# 创建适配器
|
|
adapter = VnpyLocalDataAdapter(use_local_first=True)
|
|
|
|
# 测试股票列表
|
|
test_symbols = [
|
|
"000001.SZ", # 平安银行
|
|
"600000.SH", # 浦发银行
|
|
"000002.SZ", # 万科A
|
|
"600036.SH", # 招商银行
|
|
]
|
|
|
|
for symbol in test_symbols:
|
|
print(f"\n📊 测试股票: {symbol}")
|
|
|
|
# 验证数据结构
|
|
verification = adapter.verify_local_data_structure(symbol)
|
|
|
|
print(f" 本地数据: {'✅ 有' if verification['has_local_data'] else '❌ 无'}")
|
|
print(f" 数据年份: {verification['data_years']}")
|
|
print(f" 状态: {verification['status']}")
|
|
|
|
if verification['missing_fields']:
|
|
print(f" ❌ 缺少字段: {verification['missing_fields']}")
|
|
|
|
for rec in verification['recommendations']:
|
|
print(f" 💡 {rec}")
|
|
|
|
return adapter
|
|
|
|
|
|
def test_data_loading(adapter):
|
|
"""测试数据加载功能"""
|
|
print("\n" + "=" * 60)
|
|
print("测试2: 数据加载功能")
|
|
print("=" * 60)
|
|
|
|
test_cases = [
|
|
{
|
|
'symbol': "000001.SZ",
|
|
'start_date': "2024-01-01",
|
|
'end_date': "2024-01-31",
|
|
'description': "平安银行 - 2024年1月"
|
|
},
|
|
{
|
|
'symbol': "600000.SH",
|
|
'start_date': "2023-12-01",
|
|
'end_date': "2023-12-31",
|
|
'description': "浦发银行 - 2023年12月"
|
|
},
|
|
{
|
|
'symbol': "000002.SZ",
|
|
'start_date': "2024-02-01",
|
|
'end_date': "2024-02-29",
|
|
'description': "万科A - 2024年2月"
|
|
},
|
|
]
|
|
|
|
for test_case in test_cases:
|
|
print(f"\n📥 测试: {test_case['description']}")
|
|
|
|
data = adapter.get_daily_data(
|
|
test_case['symbol'],
|
|
test_case['start_date'],
|
|
test_case['end_date']
|
|
)
|
|
|
|
if data.empty:
|
|
print(f" ❌ 获取数据失败")
|
|
continue
|
|
|
|
print(f" ✅ 获取 {len(data)} 条数据")
|
|
print(f" 时间范围: {data['datetime'].min()} 到 {data['datetime'].max()}")
|
|
print(f" 数据字段: {list(data.columns)}")
|
|
|
|
# 判断数据来源
|
|
if 'outstanding_share' in data.columns:
|
|
print(f" 数据来源: ✅ 赵云本地数据")
|
|
else:
|
|
print(f" 数据来源: 📡 akshare实时数据")
|
|
|
|
# 显示前3行
|
|
print(f" 样本数据:")
|
|
sample = data.head(3)[['datetime', 'open_price', 'close_price', 'volume']]
|
|
for _, row in sample.iterrows():
|
|
print(f" {row['datetime']}: 开{row['open_price']:.2f} 收{row['close_price']:.2f} 量{row['volume']:.0f}")
|
|
|
|
|
|
def test_converter():
|
|
"""测试数据转换器"""
|
|
print("\n" + "=" * 60)
|
|
print("测试3: 数据格式转换器")
|
|
print("=" * 60)
|
|
|
|
# 配置路径
|
|
ZHAOYUN_DATA_DIR = "/Users/chufeng/nas/stock/sanguo_vnpy/zhaoyun-data/data"
|
|
OUTPUT_DIR = "/Users/chufeng/.openclaw/workspace-jiangwei/vnpy_local_data_test"
|
|
|
|
# 创建转换器
|
|
converter = DataConverter(ZHAOYUN_DATA_DIR, OUTPUT_DIR)
|
|
|
|
# 分析数据结构
|
|
print("分析赵云数据结构...")
|
|
structure = converter.analyze_zhaoyun_structure()
|
|
|
|
if not structure['exists']:
|
|
print(f"❌ 赵云数据目录不存在: {ZHAOYUN_DATA_DIR}")
|
|
return
|
|
|
|
print(f"✅ 赵云数据目录有效")
|
|
print(f" 日线数据目录: {structure['subdirectories'].get('raw/daily', {}).get('total_files', 0)} 个文件")
|
|
print(f" 股票信息目录: {structure['subdirectories'].get('raw/stock_info', {}).get('total_files', 0)} 个文件")
|
|
|
|
# 测试转换(只转换少量数据)
|
|
print("\n测试数据转换(仅2024年前5个文件)...")
|
|
converter.convert_daily_data(year=2024, limit=5)
|
|
|
|
# 检查转换结果
|
|
output_daily_dir = os.path.join(OUTPUT_DIR, 'daily', '2024')
|
|
if os.path.exists(output_daily_dir):
|
|
converted_files = os.listdir(output_daily_dir)
|
|
print(f"✅ 转换完成,生成 {len(converted_files)} 个文件")
|
|
|
|
if converted_files:
|
|
# 读取一个转换后的文件
|
|
sample_file = os.path.join(output_daily_dir, converted_files[0])
|
|
try:
|
|
df = pd.read_parquet(sample_file)
|
|
print(f" 样本文件: {os.path.basename(sample_file)}")
|
|
print(f" 记录数: {len(df)}")
|
|
print(f" 字段: {list(df.columns)}")
|
|
print(f" 时间范围: {df['datetime'].min()} 到 {df['datetime'].max()}")
|
|
except Exception as e:
|
|
print(f" 读取转换文件失败: {e}")
|
|
else:
|
|
print("❌ 转换失败,输出目录不存在")
|
|
|
|
|
|
def test_integration_with_strategy():
|
|
"""测试与关羽策略的集成"""
|
|
print("\n" + "=" * 60)
|
|
print("测试4: 与关羽策略集成")
|
|
print("=" * 60)
|
|
|
|
# 模拟关羽策略使用本地数据
|
|
print("模拟关羽策略使用本地数据流程:")
|
|
|
|
steps = [
|
|
"1. 初始化本地数据适配器",
|
|
"2. 验证目标股票本地数据",
|
|
"3. 获取历史数据(优先本地)",
|
|
"4. 进行价值筛选",
|
|
"5. 进行技术筛选",
|
|
"6. 输出回测结果",
|
|
]
|
|
|
|
for step in steps:
|
|
print(f" {step}")
|
|
|
|
# 示例代码
|
|
example_code = '''
|
|
# ============================================
|
|
# 关羽策略修改示例 - 使用本地数据
|
|
# ============================================
|
|
|
|
# 1. 导入适配器
|
|
from vnpy_local_data_adapter import VnpyLocalDataAdapter
|
|
|
|
class GuanYuValueTechStrategy:
|
|
def __init__(self):
|
|
# 2. 创建数据适配器
|
|
self.data_adapter = VnpyLocalDataAdapter(use_local_first=True)
|
|
|
|
def get_stock_data(self, symbol, start_date, end_date):
|
|
# 3. 使用适配器获取数据
|
|
return self.data_adapter.get_daily_data(symbol, start_date, end_date)
|
|
|
|
def value_screening(self, stock_list):
|
|
# 4. 价值筛选(使用本地数据)
|
|
screened_stocks = []
|
|
for symbol in stock_list:
|
|
# 获取最近一年的数据
|
|
data = self.get_stock_data(symbol, "2023-01-01", "2023-12-31")
|
|
if not data.empty:
|
|
# 进行价值指标计算
|
|
pe = self.calculate_pe(data)
|
|
pb = self.calculate_pb(data)
|
|
roe = self.calculate_roe(data)
|
|
|
|
if self.meets_value_criteria(pe, pb, roe):
|
|
screened_stocks.append(symbol)
|
|
|
|
return screened_stocks
|
|
'''
|
|
|
|
print("\n💡 集成示例代码:")
|
|
print(example_code)
|
|
|
|
|
|
def generate_implementation_guide():
|
|
"""生成实施指南"""
|
|
print("\n" + "=" * 60)
|
|
print("实施指南")
|
|
print("=" * 60)
|
|
|
|
guide = """
|
|
🎯 目标:让vn.py优先使用赵云将军的本地数据
|
|
|
|
📋 实施步骤:
|
|
|
|
1. 数据准备阶段
|
|
✅ 确认赵云数据目录位置
|
|
✅ 分析数据结构完整性
|
|
✅ 转换数据格式(如需)
|
|
|
|
2. 代码集成阶段
|
|
✅ 部署 vnpy_local_data_adapter.py
|
|
✅ 修改vn.py策略的数据获取逻辑
|
|
✅ 测试数据加载功能
|
|
|
|
3. 验证测试阶段
|
|
✅ 测试本地数据加载
|
|
✅ 测试akshare回退机制
|
|
✅ 验证数据完整性
|
|
|
|
4. 部署上线阶段
|
|
✅ 更新所有vn.py策略
|
|
✅ 配置数据路径
|
|
✅ 监控数据使用情况
|
|
|
|
🔧 文件说明:
|
|
- vnpy_local_data_adapter.py: 核心适配器
|
|
- data_convert_tool.py: 数据格式转换工具
|
|
- test_vnpy_data.py: 测试脚本
|
|
- vnpy_data_config.json: 配置文件
|
|
|
|
📞 技术支持:
|
|
- 数据问题:联系赵云将军
|
|
- 代码问题:联系姜维将军
|
|
- 策略问题:联系各位将军
|
|
|
|
⚠️ 注意事项:
|
|
1. 定期更新本地数据
|
|
2. 监控数据完整性
|
|
3. 保持akshare回退机制
|
|
4. 备份重要数据
|
|
"""
|
|
|
|
print(guide)
|
|
|
|
|
|
def main():
|
|
"""主测试函数"""
|
|
print("🚀 vn.py本地数据适配器综合测试")
|
|
print("=" * 60)
|
|
|
|
try:
|
|
# 测试1: 适配器基本功能
|
|
adapter = test_adapter_basic()
|
|
|
|
# 测试2: 数据加载功能
|
|
test_data_loading(adapter)
|
|
|
|
# 测试3: 数据转换器
|
|
test_converter()
|
|
|
|
# 测试4: 策略集成
|
|
test_integration_with_strategy()
|
|
|
|
# 生成实施指南
|
|
generate_implementation_guide()
|
|
|
|
print("\n" + "=" * 60)
|
|
print("✅ 所有测试完成!")
|
|
print("=" * 60)
|
|
|
|
# 保存测试报告
|
|
report = {
|
|
'test_date': pd.Timestamp.now().isoformat(),
|
|
'adapter_status': 'PASSED',
|
|
'data_loading_status': 'PASSED',
|
|
'converter_status': 'PASSED',
|
|
'integration_status': 'READY',
|
|
'recommendations': [
|
|
"1. 部署 vnpy_local_data_adapter.py 到NAS容器",
|
|
"2. 修改关羽策略使用本地数据适配器",
|
|
"3. 测试回测功能是否正常",
|
|
"4. 联系赵云将军更新数据(如需)"
|
|
]
|
|
}
|
|
|
|
report_file = "vnpy_local_data_test_report.json"
|
|
with open(report_file, 'w', encoding='utf-8') as f:
|
|
json.dump(report, f, ensure_ascii=False, indent=2)
|
|
|
|
print(f"\n📋 测试报告已保存: {report_file}")
|
|
|
|
except Exception as e:
|
|
print(f"\n❌ 测试失败: {e}")
|
|
import traceback
|
|
traceback.print_exc()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main() |