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.
 
 
FactorSimulator/managers/simulation_manager.py

211 lines
8.4 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, TrainMetrics, TestMetrics, AlphaInfo
from utils.time_utils import format_time
from utils.file_utils import save_results_to_file
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 = 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"),
train_metrics=metrics.train_metrics,
is_metrics=metrics.is_metrics,
test_metrics=metrics.test_metrics,
alpha_info=metrics.alpha_info
)
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")
)
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")
)
print(f"✗ 因子模拟异常: {expression}")
print(f" 耗时: {format_time(time_consuming)},异常: {str(e)}")
return result
"""打印成功因子的关键指标"""
def _print_success_metrics(self, metrics):
print(" 关键指标 (训练集):")
key_metrics = [
('夏普比率', metrics.train_metrics.sharpe_ratio),
('年化收益', metrics.train_metrics.annual_return),
('最大回撤', metrics.train_metrics.max_drawdown),
('换手率', metrics.train_metrics.turnover),
('适应度', metrics.train_metrics.fitness),
('PNL', metrics.train_metrics.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}")
# 显示样本外测试的夏普比率(如果存在)
if metrics.test_metrics.sharpe_ratio is not None:
print(f" 样本外夏普比率: {metrics.test_metrics.sharpe_ratio:.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}")
for i, result in enumerate(results, 1):
status_icon = "" if result.status == 'success' else ""
print(f"{i}. {status_icon} {result.expression}")
print(f" 状态: {result.status}")
print(f" 耗时: {result.formatted_time}")
print(f" Alpha ID: {result.alpha_id}")
if result.status != 'success':
print(f" 原因: {result.description}")
print()