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.
211 lines
8.4 KiB
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() |