initial-import: 2026-04-11 21:18:55
This commit is contained in:
@@ -0,0 +1,173 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
生成510300.SSE测试数据到vn.py数据库
|
||||
如果下载失败,手动生成测试数据用于回测测试
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
import sqlite3
|
||||
from datetime import datetime, timedelta
|
||||
import random
|
||||
|
||||
def generate_test_data():
|
||||
"""生成测试数据"""
|
||||
print("🚀 生成510300.SSE测试数据...")
|
||||
print("="*60)
|
||||
|
||||
# 配置
|
||||
symbol = "510300.SSE"
|
||||
db_path = "/Users/chufeng/.openclaw/workspace-zhaoyun/zhaoyun-data/data/database_test.db"
|
||||
|
||||
# 从2020年1月1日开始,生成1000个交易日数据
|
||||
start_date = datetime(2020, 1, 1)
|
||||
days = 1000 # 约4年数据
|
||||
|
||||
print(f"目标标的: {symbol}")
|
||||
print(f"生成数据: {days} 个交易日 (从 {start_date.strftime('%Y-%m-%d')} 开始)")
|
||||
print(f"数据库: {db_path}")
|
||||
|
||||
# 创建数据库
|
||||
if os.path.exists(db_path):
|
||||
os.remove(db_path)
|
||||
print(f"\n✅ 删除旧数据库")
|
||||
|
||||
os.makedirs(os.path.dirname(db_path), exist_ok=True)
|
||||
conn = sqlite3.connect(db_path)
|
||||
cursor = conn.cursor()
|
||||
|
||||
# 创建vn.py标准表结构
|
||||
cursor.execute("""
|
||||
CREATE TABLE dbbardata (
|
||||
symbol TEXT NOT NULL,
|
||||
exchange TEXT,
|
||||
interval TEXT NOT NULL,
|
||||
datetime INTEGER NOT NULL,
|
||||
open REAL NOT NULL,
|
||||
high REAL NOT NULL,
|
||||
low REAL NOT NULL,
|
||||
close REAL NOT NULL,
|
||||
volume INTEGER NOT NULL,
|
||||
open_interest REAL,
|
||||
turnover REAL,
|
||||
PRIMARY KEY (symbol, interval, datetime)
|
||||
);
|
||||
""")
|
||||
|
||||
# 创建索引
|
||||
cursor.execute("CREATE INDEX ix_dbbardata_symbol ON dbbardata(symbol);")
|
||||
cursor.execute("CREATE INDEX ix_dbbardata_symbol_interval ON dbbardata(symbol, interval);")
|
||||
|
||||
# 生成模拟数据(近似真实的走势)
|
||||
print(f"\n📊 生成数据...")
|
||||
|
||||
base_price = 3.0 # 510300沪深300ETF大致价格范围
|
||||
current_price = base_price
|
||||
imported = 0
|
||||
|
||||
current_date = start_date
|
||||
|
||||
# 随机游走模拟价格走势
|
||||
for i in range(days):
|
||||
# 跳过周末(周六周日)
|
||||
if current_date.weekday() >= 5:
|
||||
current_date += timedelta(days=1)
|
||||
continue
|
||||
|
||||
# 生成随机价格变动
|
||||
daily_change = random.uniform(-0.02, 0.02) # ±2%
|
||||
current_price = current_price * (1 + daily_change)
|
||||
|
||||
# 确保价格合理
|
||||
current_price = max(2.0, min(5.0, current_price))
|
||||
|
||||
# 生成OHLC
|
||||
open_price = current_price * (1 + random.uniform(-0.005, 0.005))
|
||||
high_price = max(open_price, current_price) * (1 + random.uniform(0, 0.01))
|
||||
low_price = min(open_price, current_price) * (1 - random.uniform(0, 0.01))
|
||||
close_price = current_price
|
||||
|
||||
# 成交量(百万级)
|
||||
volume = int(random.uniform(10000000, 500000000))
|
||||
turnover = volume * close_price # 成交额
|
||||
|
||||
# 转换为时间戳
|
||||
timestamp = int(current_date.timestamp())
|
||||
|
||||
# 插入
|
||||
cursor.execute("""
|
||||
INSERT INTO dbbardata (
|
||||
symbol, exchange, interval, datetime,
|
||||
open, high, low, close, volume, turnover
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
""", (
|
||||
symbol,
|
||||
'SSE',
|
||||
'1d',
|
||||
timestamp,
|
||||
round(open_price, 4),
|
||||
round(high_price, 4),
|
||||
round(low_price, 4),
|
||||
round(close_price, 4),
|
||||
volume,
|
||||
round(turnover, 2)
|
||||
))
|
||||
|
||||
imported += 1
|
||||
|
||||
# 下一个交易日
|
||||
current_date += timedelta(days=1)
|
||||
|
||||
# 进度
|
||||
if imported % 100 == 0:
|
||||
print(f" 已生成 {imported} 个交易日...")
|
||||
|
||||
# 提交
|
||||
conn.commit()
|
||||
|
||||
# 验证
|
||||
cursor.execute("SELECT COUNT(*) FROM dbbardata WHERE symbol = ?", (symbol,))
|
||||
count = cursor.fetchone()[0]
|
||||
|
||||
cursor.execute("SELECT MIN(datetime), MAX(datetime) FROM dbbardata WHERE symbol = ?", (symbol,))
|
||||
min_ts, max_ts = cursor.fetchone()
|
||||
|
||||
min_dt = datetime.fromtimestamp(min_ts).strftime('%Y-%m-%d') if min_ts else 'N/A'
|
||||
max_dt = datetime.fromtimestamp(max_ts).strftime('%Y-%m-%d') if max_ts else 'N/A'
|
||||
|
||||
cursor.execute("SELECT MIN(close), MAX(close) FROM dbbardata WHERE symbol = ?", (symbol,))
|
||||
min_close, max_close = cursor.fetchone()
|
||||
|
||||
conn.close()
|
||||
|
||||
# 总结
|
||||
print("\n" + "="*60)
|
||||
print("✅ 测试数据生成完成!")
|
||||
print(f"标的: {symbol}")
|
||||
print(f"数据库: {db_path}")
|
||||
print(f"总行数: {imported} (验证: {count})")
|
||||
print(f"时间范围: {min_dt} -> {max_dt}")
|
||||
print(f"价格范围: {min_close:.2f} ~ {max_close:.2f}")
|
||||
print("="*60)
|
||||
|
||||
print("\n💡 说明:")
|
||||
print("这是模拟测试数据,用于验证回测API功能")
|
||||
print("真实数据需要赵云将军通过AKShare下载")
|
||||
print("但测试数据足够验证API回测功能正常")
|
||||
|
||||
print("\n🎯 下一步:")
|
||||
print("1. 确认API数据路径配置正确")
|
||||
print(f" 数据库路径: {db_path}")
|
||||
print("2. 重启API服务")
|
||||
print("3. 关羽将军重新运行回测")
|
||||
print("="*60)
|
||||
|
||||
return True
|
||||
|
||||
def main():
|
||||
"""主函数"""
|
||||
success = generate_test_data()
|
||||
sys.exit(0 if success else 1)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user