You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
232 lines
9.1 KiB
232 lines
9.1 KiB
# -*- coding: utf-8 -*-
|
|
import time
|
|
import json
|
|
import os
|
|
from concurrent.futures import ThreadPoolExecutor, as_completed
|
|
from random import uniform
|
|
from typing import List, Dict, Any
|
|
|
|
from core.api_client import WorldQuantBrainSimulate
|
|
from core.models import SimulationResult
|
|
from utils.time_utils import format_time
|
|
from utils.file_utils import save_results_to_file, save_success_alpha
|
|
|
|
|
|
class AlphaSimulationManager:
|
|
def __init__(self, credentials_file='account.txt'):
|
|
self.credentials_file = credentials_file
|
|
self.results = []
|
|
|
|
"""模拟单个Alpha因子(线程安全)"""
|
|
def simulate_single_alpha(self, api: WorldQuantBrainSimulate, expression: str,
|
|
settings: Dict[str, Any] = None) -> SimulationResult:
|
|
alpha_start_time = time.time()
|
|
|
|
try:
|
|
# 模拟Alpha因子
|
|
simulation_result = api.simulate_alpha(expression, settings)
|
|
alpha_end_time = time.time()
|
|
time_consuming = alpha_end_time - alpha_start_time
|
|
|
|
# 根据模拟结果类型处理
|
|
if simulation_result["status"] == "success":
|
|
# 模拟成功的结果 - 直接使用原始metrics数据
|
|
metrics = simulation_result["metrics"]
|
|
result = SimulationResult(
|
|
expression=expression,
|
|
time_consuming=time_consuming,
|
|
formatted_time=format_time(time_consuming),
|
|
alpha_id=simulation_result["alpha_id"],
|
|
status="success",
|
|
description="/",
|
|
simulation_timestamp=time.strftime("%Y-%m-%d %H:%M:%S"),
|
|
metrics=metrics # 直接存储原始metrics数据
|
|
)
|
|
print(f"✓ 因子模拟成功: {expression}")
|
|
print(f" 耗时: {format_time(time_consuming)},Alpha ID: {simulation_result['alpha_id']}")
|
|
|
|
# 打印关键指标
|
|
self._print_success_metrics(metrics)
|
|
|
|
else:
|
|
# 模拟失败的结果(API返回的错误)
|
|
result = SimulationResult(
|
|
expression=expression,
|
|
time_consuming=time_consuming,
|
|
formatted_time=format_time(time_consuming),
|
|
alpha_id="/",
|
|
status="error",
|
|
description=simulation_result["message"],
|
|
simulation_timestamp=time.strftime("%Y-%m-%d %H:%M:%S"),
|
|
metrics=None
|
|
)
|
|
print(f"✗ 因子模拟失败: {expression}")
|
|
print(f" 耗时: {format_time(time_consuming)},错误: {simulation_result['message']}")
|
|
|
|
except Exception as e:
|
|
# 其他异常情况
|
|
alpha_end_time = time.time()
|
|
time_consuming = alpha_end_time - alpha_start_time
|
|
|
|
result = SimulationResult(
|
|
expression=expression,
|
|
time_consuming=time_consuming,
|
|
formatted_time=format_time(time_consuming),
|
|
alpha_id="/",
|
|
status="failed",
|
|
description=str(e),
|
|
simulation_timestamp=time.strftime("%Y-%m-%d %H:%M:%S"),
|
|
metrics=None
|
|
)
|
|
print(f"✗ 因子模拟异常: {expression}")
|
|
print(f" 耗时: {format_time(time_consuming)},异常: {str(e)}")
|
|
|
|
return result
|
|
|
|
"""打印成功因子的关键指标"""
|
|
def _print_success_metrics(self, metrics: Dict[str, Any]):
|
|
# 添加空值检查
|
|
if not metrics:
|
|
print(" 无指标数据")
|
|
return
|
|
|
|
print(" 关键指标 (训练集):")
|
|
# 从原始metrics数据中提取训练集指标
|
|
train_data = metrics.get('train', {}) or {}
|
|
key_metrics = [
|
|
('夏普比率', train_data.get('sharpe')),
|
|
('年化收益', train_data.get('returns')),
|
|
('最大回撤', train_data.get('drawdown')),
|
|
('换手率', train_data.get('turnover')),
|
|
('适应度', train_data.get('fitness')),
|
|
('PNL', train_data.get('pnl')),
|
|
]
|
|
|
|
for chinese_name, value in key_metrics:
|
|
if value is not None:
|
|
if isinstance(value, float):
|
|
value = f"{value:.4f}"
|
|
print(f" {chinese_name}: {value}") # 衡量风险调整后的收益
|
|
# 年化收益率
|
|
# 显示样本外测试的夏普比率(如果存在) # 最大亏损幅度
|
|
test_data = metrics.get('test', {}) or {} # 交易频率
|
|
if test_data.get('sharpe') is not None: # 策略适应度得分
|
|
print(f" 样本外夏普比率: {test_data.get('sharpe'):.4f}") # 净盈亏
|
|
|
|
"""模拟一批Alpha因子(3个一组)"""
|
|
def simulate_alpha_batch(self, alpha_batch: List[str], batch_number: int) -> List[SimulationResult]:
|
|
print(f"\n{'=' * 60}") # 只打印存在的指标
|
|
print(f"开始第 {batch_number} 批因子模拟 (共 {len(alpha_batch)} 个因子)") # 格式化浮点数显示
|
|
print(f"因子列表: {alpha_batch}")
|
|
print(f"{'=' * 60}")
|
|
|
|
batch_start_time = time.time()
|
|
batch_results = []
|
|
# 检查是否存在测试集夏普比率
|
|
# 创建API客户端实例(每个线程独立的客户端)
|
|
api = WorldQuantBrainSimulate(self.credentials_file)
|
|
|
|
try:
|
|
if api.login():
|
|
# 使用线程池执行3个因子的模拟
|
|
with ThreadPoolExecutor(max_workers=3) as executor:
|
|
# 提交所有任务
|
|
future_to_alpha = {
|
|
executor.submit(self.simulate_single_alpha, api, alpha): alpha
|
|
for alpha in alpha_batch
|
|
}
|
|
|
|
# 等待所有任务完成
|
|
for future in as_completed(future_to_alpha):
|
|
alpha = future_to_alpha[future]
|
|
try:
|
|
result = future.result()
|
|
batch_results.append(result)
|
|
except Exception as e:
|
|
print(f"因子 {alpha} 执行异常: {e}")
|
|
except Exception as e:
|
|
print(f"第 {batch_number} 批模拟过程中出错: {e}")
|
|
finally:
|
|
api.close()
|
|
|
|
batch_end_time = time.time()
|
|
batch_total_time = batch_end_time - batch_start_time
|
|
|
|
print(f"\n第 {batch_number} 批模拟完成!")
|
|
print(f"本批总耗时: {format_time(batch_total_time)}")
|
|
print(f"{'=' * 60}")
|
|
|
|
return batch_results
|
|
|
|
"""运行批量模拟"""
|
|
def run_simulation(self, alpha_list: List[str], batch_size: int = 3) -> List[SimulationResult]:
|
|
print("开始Alpha因子批量模拟...")
|
|
total_start_time = time.time()
|
|
|
|
# 将因子列表分成每批3个
|
|
batches = [alpha_list[i:i + batch_size] for i in range(0, len(alpha_list), batch_size)]
|
|
|
|
all_results = []
|
|
|
|
for i, batch in enumerate(batches, 1):
|
|
# 模拟当前批次
|
|
batch_results = self.simulate_alpha_batch(batch, i)
|
|
all_results.extend(batch_results)
|
|
|
|
# 如果不是最后一批,则等待3-5秒
|
|
if i < len(batches):
|
|
sleep_time = uniform(3, 5)
|
|
print(f"\n等待 {sleep_time:.2f} 秒后开始下一批...")
|
|
time.sleep(sleep_time)
|
|
|
|
total_end_time = time.time()
|
|
total_time = total_end_time - total_start_time
|
|
|
|
# 输出最终结果汇总
|
|
self.print_summary(all_results, total_time)
|
|
|
|
# 保存结果到文件
|
|
save_results_to_file(all_results)
|
|
|
|
return all_results
|
|
|
|
"""打印结果汇总"""
|
|
def print_summary(self, results: List[SimulationResult], total_time: float):
|
|
print(f"\n{'=' * 60}")
|
|
print("模拟结果汇总")
|
|
print(f"{'=' * 60}")
|
|
|
|
success_count = sum(1 for r in results if r.status == 'success')
|
|
error_count = sum(1 for r in results if r.status == 'error')
|
|
failed_count = sum(1 for r in results if r.status == 'failed')
|
|
|
|
print(f"总模拟因子数: {len(results)}")
|
|
print(f"成功: {success_count} 个")
|
|
print(f"模拟错误: {error_count} 个")
|
|
print(f"执行异常: {failed_count} 个")
|
|
print(f"总耗时: {format_time(total_time)}")
|
|
print(f"{'=' * 60}")
|
|
|
|
success_expression_list = []
|
|
|
|
for i, result in enumerate(results, 1):
|
|
status_icon = "✓" if result.status == 'success' else "✗"
|
|
|
|
if result.status == 'success':
|
|
success_expression_list.append(result.expression)
|
|
|
|
line_parts = [
|
|
f"{i}. {status_icon} {result.expression}",
|
|
f"状态: {result.status}",
|
|
f"耗时: {result.formatted_time}"
|
|
]
|
|
|
|
if result.alpha_id != '/':
|
|
line_parts.append(f"Alpha ID: {result.alpha_id}")
|
|
|
|
if result.status != 'success':
|
|
line_parts.append(f"原因: {result.description}")
|
|
|
|
print("\t".join(line_parts))
|
|
|
|
save_success_alpha(success_expression_list) |