main
jack 4 weeks ago
parent 168298ace4
commit 83bac3cf78
  1. 4
      .gitignore
  2. 6
      alpha.txt
  3. 130
      core/api_client.py
  4. 7
      core/models.py
  5. 496
      main_bak.py
  6. 83
      managers/simulation_manager.py
  7. 139
      result/simulation_results-1763048082.json
  8. 289
      result/simulation_results-1763109446.json
  9. 524
      result/simulation_results-1763110929.json
  10. 82
      result/simulation_results-1763112962.json
  11. 12
      result/simulation_results-1763113286.json
  12. 4
      success.txt
  13. 45
      utils/file_utils.py

4
.gitignore vendored

@ -64,4 +64,6 @@ other/split_clash_config/split_config
ai_news/save_data ai_news/save_data
daily/*.txt daily/*.txt
./result ./result
./alpha.txt
./account.txt

@ -1,5 +1 @@
ts_rank(ts_returns(close, 15), 30) ts_delta(ts_mean(close, 5), 10) / ts_std(close, 20) * (ts_mean(close, 20) / ts_mean(close, 100) > 1.02)
-ts_corr(ts_rank(close, 30), ts_rank(volume, 30), 10)
(close - ts_min(close, 20)) / (ts_max(close, 20) - ts_min(close, 20))
ts_rank(ts_delta(close, 3) / ts_delay(close, 3), 15)
-ts_std(ts_returns(close, 1), 30)

@ -5,8 +5,6 @@ import time
from httpx import BasicAuth from httpx import BasicAuth
from typing import Dict, Any, Optional, Tuple from typing import Dict, Any, Optional, Tuple
from .models import AlphaMetrics, TrainMetrics, TestMetrics, AlphaInfo
class WorldQuantBrainSimulate: class WorldQuantBrainSimulate:
def __init__(self, credentials_file='account.txt'): def __init__(self, credentials_file='account.txt'):
@ -37,6 +35,7 @@ class WorldQuantBrainSimulate:
if response.status_code == 201: if response.status_code == 201:
print("登录成功!") print("登录成功!")
print(f"账户信息: {response.json()}")
return True return True
else: else:
print(f"登录失败: {response.json()}") print(f"登录失败: {response.json()}")
@ -83,7 +82,12 @@ class WorldQuantBrainSimulate:
if retry_after_sec == 0: if retry_after_sec == 0:
break break
print(sim_progress_resp.json()) if sim_progress_resp.json():
result = sim_progress_resp.json()
progress = result['progress']
if progress:
print(f"模拟进度: {float(progress)*100}%")
print(f"等待 {retry_after_sec} 秒...") print(f"等待 {retry_after_sec} 秒...")
time.sleep(retry_after_sec) time.sleep(retry_after_sec)
@ -103,7 +107,7 @@ class WorldQuantBrainSimulate:
return {"status": "success", "alpha_id": alpha_id, "metrics": metrics} return {"status": "success", "alpha_id": alpha_id, "metrics": metrics}
"""获取Alpha因子的详细指标""" """获取Alpha因子的详细指标"""
def get_alpha_metrics(self, alpha_id: str) -> AlphaMetrics: def get_alpha_metrics(self, alpha_id: str) -> Dict[str, Any]:
if self.client is None: if self.client is None:
raise Exception("请先登录") raise Exception("请先登录")
@ -114,99 +118,39 @@ class WorldQuantBrainSimulate:
if alpha_resp.status_code in [200, 201]: if alpha_resp.status_code in [200, 201]:
alpha_data = alpha_resp.json() alpha_data = alpha_resp.json()
return self._parse_alpha_metrics(alpha_data)
# 以后可能需要获取其他参数
if alpha_data.get('metrics'):
alpha_data = alpha_data.get('metrics')
return alpha_data or {}
else: else:
return AlphaMetrics( print(f"获取Alpha指标失败: {alpha_resp.status_code}")
train_metrics=TrainMetrics(), # 返回一个空的字典结构
is_metrics=TestMetrics(), return {
test_metrics=TestMetrics(), "train": {},
alpha_info=AlphaInfo() "is": {},
) "test": {},
"grade": None,
"stage": None,
"status": None,
"dateCreated": None,
"id": alpha_id
}
except Exception as e: except Exception as e:
print(f"获取指标时出错: {str(e)}") print(f"获取指标时出错: {str(e)}")
return AlphaMetrics( # 返回一个空的字典结构
train_metrics=TrainMetrics(), return {
is_metrics=TestMetrics(), "train": {},
test_metrics=TestMetrics(), "is": {},
alpha_info=AlphaInfo() "test": {},
) "grade": None,
"stage": None,
"""解析Alpha数据,提取关键指标""" "status": None,
def _parse_alpha_metrics(self, alpha_data: Dict[str, Any]) -> AlphaMetrics: "dateCreated": None,
# 解析训练集数据 "id": alpha_id
train_metrics = TrainMetrics() }
if 'train' in alpha_data and alpha_data['train']:
train_data = alpha_data['train']
train_metrics = TrainMetrics(
sharpe_ratio=train_data.get('sharpe'),
annual_return=train_data.get('returns'),
max_drawdown=train_data.get('drawdown'),
turnover=train_data.get('turnover'),
fitness=train_data.get('fitness'),
pnl=train_data.get('pnl'),
book_size=train_data.get('bookSize'),
long_count=train_data.get('longCount'),
short_count=train_data.get('shortCount'),
margin=train_data.get('margin'),
)
# 解析样本内测试数据
is_metrics = TestMetrics()
if 'is' in alpha_data and alpha_data['is']:
is_data = alpha_data['is']
is_metrics = TestMetrics(
sharpe_ratio=is_data.get('sharpe'),
annual_return=is_data.get('returns'),
max_drawdown=is_data.get('drawdown'),
turnover=is_data.get('turnover'),
fitness=is_data.get('fitness'),
pnl=is_data.get('pnl'),
)
# 解析样本外测试数据
test_metrics = TestMetrics()
if 'test' in alpha_data and alpha_data['test']:
test_data = alpha_data['test']
test_metrics = TestMetrics(
sharpe_ratio=test_data.get('sharpe'),
annual_return=test_data.get('returns'),
max_drawdown=test_data.get('drawdown'),
turnover=test_data.get('turnover'),
fitness=test_data.get('fitness'),
pnl=test_data.get('pnl'),
)
# 解析Alpha基本信息
alpha_info = AlphaInfo(
grade=alpha_data.get('grade'),
stage=alpha_data.get('stage'),
status=alpha_data.get('status'),
date_created=alpha_data.get('dateCreated'),
)
# 解析检查结果
if 'is' in alpha_data and 'checks' in alpha_data['is']:
checks = alpha_data['is']['checks']
check_results = {}
for check in checks:
check_name = check.get('name', '')
result = check.get('result', '')
value = check.get('value', None)
check_results[check_name.lower()] = {
'result': result,
'value': value,
'limit': check.get('limit', None)
}
alpha_info.checks = check_results
return AlphaMetrics(
train_metrics=train_metrics,
is_metrics=is_metrics,
test_metrics=test_metrics,
alpha_info=alpha_info,
alpha_id=alpha_data.get('id')
)
def close(self): def close(self):
"""关闭连接""" """关闭连接"""

@ -56,10 +56,7 @@ class SimulationResult:
time_consuming: float time_consuming: float
formatted_time: str formatted_time: str
alpha_id: str alpha_id: str
status: str # success, error, failed status: str
description: str description: str
simulation_timestamp: str simulation_timestamp: str
train_metrics: Optional[TrainMetrics] = None metrics: Optional[Dict[str, Any]] = None
is_metrics: Optional[TestMetrics] = None
test_metrics: Optional[TestMetrics] = None
alpha_info: Optional[AlphaInfo] = None

@ -1,496 +0,0 @@
import os.path
import httpx
import json
from httpx import BasicAuth
import time
from random import uniform
import threading
from concurrent.futures import ThreadPoolExecutor, as_completed
class WorldQuantBrainSimulate:
def __init__(self, credentials_file='account.txt'):
self.credentials_file = credentials_file
self.client = None
self.brain_api_url = 'https://api.worldquantbrain.com'
"""读取本地账号密码"""
def load_credentials(self):
if not os.path.exists(self.credentials_file):
print("未找到 account.txt 文件")
with open(self.credentials_file, 'w') as f: f.write("")
print("account.txt 文件已创建,请填写账号密码, 格式: ['username', 'password]")
exit(1)
with open(self.credentials_file) as f:
credentials = eval(f.read())
return credentials[0], credentials[1]
"""登录认证"""
def login(self):
username, password = self.load_credentials()
self.client = httpx.Client(auth=BasicAuth(username, password))
response = self.client.post(f'{self.brain_api_url}/authentication')
print(f"登录状态: {response.status_code}")
if response.status_code == 201:
print("登录成功!")
return True
else:
print(f"登录失败: {response.json()}")
return False
"""模拟Alpha因子"""
def simulate_alpha(self, expression, settings=None):
if self.client is None:
raise Exception("请先登录")
default_settings = {
'instrumentType': 'EQUITY',
'region': 'USA',
'universe': 'TOP3000',
'delay': 1,
'decay': 0,
'neutralization': 'INDUSTRY',
'truncation': 0.08,
'pasteurization': 'ON',
'unitHandling': 'VERIFY',
'nanHandling': 'OFF',
'language': 'FASTEXPR',
'visualization': False,
}
if settings:
default_settings.update(settings)
simulation_data = {
'type': 'REGULAR',
'settings': default_settings,
'regular': expression
}
sim_resp = self.client.post(f'{self.brain_api_url}/simulations', json=simulation_data)
print(f"模拟提交状态: {sim_resp.status_code}")
sim_progress_url = sim_resp.headers['location']
print(f"进度URL: {sim_progress_url}")
while True:
sim_progress_resp = self.client.get(sim_progress_url)
retry_after_sec = float(sim_progress_resp.headers.get("Retry-After", 0))
if retry_after_sec == 0:
break
print(sim_progress_resp.json())
print(f"等待 {retry_after_sec} 秒...")
time.sleep(retry_after_sec)
# 如果因子模拟不通过, 获取一下失败信息
if sim_progress_resp.json()["status"] == "ERROR":
result = sim_progress_resp.json()["message"]
print(f"因子模拟失败: {result}")
# 返回一个特殊标识,表示模拟失败
return {"status": "error", "message": result}
alpha_id = sim_progress_resp.json()["alpha"]
print(f"生成的Alpha ID: {alpha_id}")
# 获取详细的性能指标
metrics = self.get_alpha_metrics(alpha_id)
return {"status": "success", "alpha_id": alpha_id, "metrics": metrics}
"""获取Alpha因子的详细指标"""
def get_alpha_metrics(self, alpha_id):
if self.client is None:
raise Exception("请先登录")
try:
# 获取Alpha的基本信息和指标
alpha_url = f'{self.brain_api_url}/alphas/{alpha_id}'
alpha_resp = self.client.get(alpha_url)
if alpha_resp.status_code in [200, 201]:
alpha_data = alpha_resp.json()
return self._parse_alpha_metrics(alpha_data)
else:
return {"error": f"无法获取Alpha信息: {alpha_resp.status_code}"}
except Exception as e:
return {"error": f"获取指标时出错: {str(e)}"}
"""解析Alpha数据,提取关键指标"""
def _parse_alpha_metrics(self, alpha_data):
metrics = {}
try:
# 从train字段获取指标数据
if 'train' in alpha_data and alpha_data['train']:
train_data = alpha_data['train']
metrics.update({
'sharpe_ratio': train_data.get('sharpe', None),
'annual_return': train_data.get('returns', None),
'max_drawdown': train_data.get('drawdown', None),
'turnover': train_data.get('turnover', None),
'fitness': train_data.get('fitness', None),
'pnl': train_data.get('pnl', None),
'book_size': train_data.get('bookSize', None),
'long_count': train_data.get('longCount', None),
'short_count': train_data.get('shortCount', None),
'margin': train_data.get('margin', None),
'start_date': train_data.get('startDate', None),
})
# 从is字段获取样本内测试数据
if 'is' in alpha_data and alpha_data['is']:
is_data = alpha_data['is']
metrics.update({
'is_sharpe': is_data.get('sharpe', None),
'is_returns': is_data.get('returns', None),
'is_drawdown': is_data.get('drawdown', None),
'is_turnover': is_data.get('turnover', None),
'is_fitness': is_data.get('fitness', None),
'is_pnl': is_data.get('pnl', None),
})
# 从test字段获取样本外测试数据
if 'test' in alpha_data and alpha_data['test']:
test_data = alpha_data['test']
metrics.update({
'test_sharpe': test_data.get('sharpe', None),
'test_returns': test_data.get('returns', None),
'test_drawdown': test_data.get('drawdown', None),
'test_turnover': test_data.get('turnover', None),
'test_fitness': test_data.get('fitness', None),
'test_pnl': test_data.get('pnl', None),
})
# 其他重要信息
metrics.update({
'alpha_id': alpha_data.get('id', None),
'grade': alpha_data.get('grade', None),
'stage': alpha_data.get('stage', None),
'status': alpha_data.get('status', None),
'date_created': alpha_data.get('dateCreated', None),
})
# 解析检查结果
if 'is' in alpha_data and 'checks' in alpha_data['is']:
checks = alpha_data['is']['checks']
check_results = {}
for check in checks:
check_name = check.get('name', '')
result = check.get('result', '')
value = check.get('value', None)
check_results[check_name.lower()] = {
'result': result,
'value': value,
'limit': check.get('limit', None)
}
metrics['checks'] = check_results
except Exception as e:
metrics['error'] = f"解析指标时出错: {str(e)}"
return metrics
def close(self):
"""关闭连接"""
if self.client:
self.client.close()
class AlphaSimulationManager:
def __init__(self, credentials_file='account.txt'):
self.credentials_file = credentials_file
self.results = []
"""将秒数格式化为 xx分xx秒 格式"""
def format_time(self, seconds):
if seconds < 60:
return f"{seconds:.2f}"
else:
minutes = int(seconds // 60)
remaining_seconds = seconds % 60
return f"{minutes}{remaining_seconds:.2f}"
"""模拟单个Alpha因子(线程安全)"""
def simulate_single_alpha(self, api, expression, settings=None):
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":
# 模拟成功的结果
result = {
"expression": expression,
"time_consuming": time_consuming,
"formatted_time": self.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": {
"sharpe_ratio": simulation_result["metrics"].get('sharpe_ratio'),
"annual_return": simulation_result["metrics"].get('annual_return'),
"max_drawdown": simulation_result["metrics"].get('max_drawdown'),
"turnover": simulation_result["metrics"].get('turnover'),
"fitness": simulation_result["metrics"].get('fitness'),
"pnl": simulation_result["metrics"].get('pnl'),
"book_size": simulation_result["metrics"].get('book_size'),
"long_count": simulation_result["metrics"].get('long_count'),
"short_count": simulation_result["metrics"].get('short_count'),
"margin": simulation_result["metrics"].get('margin'),
},
# 样本内测试指标
"is_metrics": {
"sharpe_ratio": simulation_result["metrics"].get('is_sharpe'),
"annual_return": simulation_result["metrics"].get('is_returns'),
"max_drawdown": simulation_result["metrics"].get('is_drawdown'),
"turnover": simulation_result["metrics"].get('is_turnover'),
"fitness": simulation_result["metrics"].get('is_fitness'),
"pnl": simulation_result["metrics"].get('is_pnl'),
},
# 样本外测试指标
"test_metrics": {
"sharpe_ratio": simulation_result["metrics"].get('test_sharpe'),
"annual_return": simulation_result["metrics"].get('test_returns'),
"max_drawdown": simulation_result["metrics"].get('test_drawdown'),
"turnover": simulation_result["metrics"].get('test_turnover'),
"fitness": simulation_result["metrics"].get('test_fitness'),
"pnl": simulation_result["metrics"].get('test_pnl'),
},
# 其他信息
"alpha_info": {
"grade": simulation_result["metrics"].get('grade'),
"stage": simulation_result["metrics"].get('stage'),
"status": simulation_result["metrics"].get('status'),
"date_created": simulation_result["metrics"].get('date_created'),
"checks": simulation_result["metrics"].get('checks', {})
}
}
print(f"✓ 因子模拟成功: {expression}")
print(f" 耗时: {self.format_time(time_consuming)},Alpha ID: {simulation_result['alpha_id']}")
# 打印关键指标
self._print_success_metrics(simulation_result["metrics"])
else:
# 模拟失败的结果(API返回的错误)
result = {
"expression": expression,
"time_consuming": time_consuming,
"formatted_time": self.format_time(time_consuming),
"alpha_id": "/",
"status": "error",
"description": simulation_result["message"],
"simulation_timestamp": time.strftime("%Y-%m-%d %H:%M:%S"),
"performance_metrics": {},
"risk_metrics": {},
"quantile_metrics": {},
"other_metrics": {}
}
print(f"✗ 因子模拟失败: {expression}")
print(f" 耗时: {self.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 = {
"expression": expression,
"time_consuming": time_consuming,
"formatted_time": self.format_time(time_consuming),
"alpha_id": "/",
"status": "failed",
"description": str(e),
"simulation_timestamp": time.strftime("%Y-%m-%d %H:%M:%S"),
"performance_metrics": {},
"risk_metrics": {},
"quantile_metrics": {},
"other_metrics": {}
}
print(f"✗ 因子模拟异常: {expression}")
print(f" 耗时: {self.format_time(time_consuming)},异常: {str(e)}")
return result
"""打印成功因子的关键指标"""
def _print_success_metrics(self, metrics):
if 'error' in metrics:
print(f" 指标获取错误: {metrics['error']}")
return
print(" 关键指标 (训练集):")
key_metrics = [
('夏普比率', 'sharpe_ratio'),
('年化收益', 'annual_return'),
('最大回撤', 'max_drawdown'),
('换手率', 'turnover'),
('适应度', 'fitness'),
('PNL', 'pnl'),
]
for chinese_name, metric_key in key_metrics:
value = metrics.get(metric_key)
if value is not None:
if isinstance(value, float):
value = f"{value:.4f}"
print(f" {chinese_name}: {value}")
# 显示样本外测试的夏普比率(如果存在)
test_sharpe = metrics.get('test_sharpe')
if test_sharpe is not None:
print(f" 样本外夏普比率: {test_sharpe:.4f}")
"""模拟一批Alpha因子(3个一组)"""
def simulate_alpha_batch(self, alpha_batch, batch_number):
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"本批总耗时: {self.format_time(batch_total_time)}")
print(f"{'=' * 60}")
return batch_results
"""运行批量模拟"""
def run_simulation(self, alpha_list, batch_size=3):
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)
# 保存结果到文件
self.save_results(all_results)
return all_results
"""打印结果汇总"""
def print_summary(self, results, total_time):
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"总耗时: {self.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()
"""保存结果到文件"""
def save_results(self, results):
# 转换为可序列化的格式
serializable_results = []
for result in results:
serializable_result = result.copy()
serializable_result['time_consuming'] = round(serializable_result['time_consuming'], 2)
# 处理metrics中的浮点数,保留6位小数
for metric_category in ['performance_metrics', 'risk_metrics', 'quantile_metrics', 'other_metrics']:
if metric_category in serializable_result:
for key, value in serializable_result[metric_category].items():
if isinstance(value, float):
serializable_result[metric_category][key] = round(value, 6)
serializable_results.append(serializable_result)
# 将日志文件, 保存到当前目录下, result 文件夹中
if not os.path.exists('./result'):
os.makedirs('./result')
result_name = f"result/simulation_results-{str(int(time.time()))}.json"
with open(result_name, 'w', encoding='utf-8') as f:
json.dump(serializable_results, f, ensure_ascii=False, indent=2)
print(f"结果已保存到 {result_name}")
if __name__ == "__main__":
# 待模拟因子列表
with open('alpha.txt', 'r', encoding='utf-8') as file:
alpha_list = [line.strip() for line in file]
if not alpha_list:
print("alpha.txt 文件不存在")
with open('alpha.txt', 'w', encoding='utf-8') as file: file.write("")
print("已创建 alpha.txt 文件, 请添加因子后重新运行, 一行一个因子")
exit(1)
# 创建模拟管理器并运行
manager = AlphaSimulationManager()
results = manager.run_simulation(alpha_list, batch_size=3)

@ -7,9 +7,9 @@ from random import uniform
from typing import List, Dict, Any from typing import List, Dict, Any
from core.api_client import WorldQuantBrainSimulate from core.api_client import WorldQuantBrainSimulate
from core.models import SimulationResult, TrainMetrics, TestMetrics, AlphaInfo from core.models import SimulationResult
from utils.time_utils import format_time from utils.time_utils import format_time
from utils.file_utils import save_results_to_file from utils.file_utils import save_results_to_file, save_success_alpha
class AlphaSimulationManager: class AlphaSimulationManager:
@ -19,7 +19,7 @@ class AlphaSimulationManager:
"""模拟单个Alpha因子(线程安全)""" """模拟单个Alpha因子(线程安全)"""
def simulate_single_alpha(self, api: WorldQuantBrainSimulate, expression: str, def simulate_single_alpha(self, api: WorldQuantBrainSimulate, expression: str,
settings: Dict[str, Any] = None) -> SimulationResult: settings: Dict[str, Any] = None) -> SimulationResult:
alpha_start_time = time.time() alpha_start_time = time.time()
try: try:
@ -30,7 +30,7 @@ class AlphaSimulationManager:
# 根据模拟结果类型处理 # 根据模拟结果类型处理
if simulation_result["status"] == "success": if simulation_result["status"] == "success":
# 模拟成功的结果 # 模拟成功的结果 - 直接使用原始metrics数据
metrics = simulation_result["metrics"] metrics = simulation_result["metrics"]
result = SimulationResult( result = SimulationResult(
expression=expression, expression=expression,
@ -40,10 +40,7 @@ class AlphaSimulationManager:
status="success", status="success",
description="/", description="/",
simulation_timestamp=time.strftime("%Y-%m-%d %H:%M:%S"), simulation_timestamp=time.strftime("%Y-%m-%d %H:%M:%S"),
train_metrics=metrics.train_metrics, metrics=metrics # 直接存储原始metrics数据
is_metrics=metrics.is_metrics,
test_metrics=metrics.test_metrics,
alpha_info=metrics.alpha_info
) )
print(f"✓ 因子模拟成功: {expression}") print(f"✓ 因子模拟成功: {expression}")
print(f" 耗时: {format_time(time_consuming)},Alpha ID: {simulation_result['alpha_id']}") print(f" 耗时: {format_time(time_consuming)},Alpha ID: {simulation_result['alpha_id']}")
@ -60,7 +57,8 @@ class AlphaSimulationManager:
alpha_id="/", alpha_id="/",
status="error", status="error",
description=simulation_result["message"], description=simulation_result["message"],
simulation_timestamp=time.strftime("%Y-%m-%d %H:%M:%S") simulation_timestamp=time.strftime("%Y-%m-%d %H:%M:%S"),
metrics=None
) )
print(f"✗ 因子模拟失败: {expression}") print(f"✗ 因子模拟失败: {expression}")
print(f" 耗时: {format_time(time_consuming)},错误: {simulation_result['message']}") print(f" 耗时: {format_time(time_consuming)},错误: {simulation_result['message']}")
@ -77,7 +75,8 @@ class AlphaSimulationManager:
alpha_id="/", alpha_id="/",
status="failed", status="failed",
description=str(e), description=str(e),
simulation_timestamp=time.strftime("%Y-%m-%d %H:%M:%S") simulation_timestamp=time.strftime("%Y-%m-%d %H:%M:%S"),
metrics=None
) )
print(f"✗ 因子模拟异常: {expression}") print(f"✗ 因子模拟异常: {expression}")
print(f" 耗时: {format_time(time_consuming)},异常: {str(e)}") print(f" 耗时: {format_time(time_consuming)},异常: {str(e)}")
@ -85,37 +84,45 @@ class AlphaSimulationManager:
return result return result
"""打印成功因子的关键指标""" """打印成功因子的关键指标"""
def _print_success_metrics(self, metrics): def _print_success_metrics(self, metrics: Dict[str, Any]):
# 添加空值检查
if not metrics:
print(" 无指标数据")
return
print(" 关键指标 (训练集):") print(" 关键指标 (训练集):")
# 从原始metrics数据中提取训练集指标
train_data = metrics.get('train', {}) or {}
key_metrics = [ key_metrics = [
('夏普比率', metrics.train_metrics.sharpe_ratio), ('夏普比率', train_data.get('sharpe')),
('年化收益', metrics.train_metrics.annual_return), ('年化收益', train_data.get('returns')),
('最大回撤', metrics.train_metrics.max_drawdown), ('最大回撤', train_data.get('drawdown')),
('换手率', metrics.train_metrics.turnover), ('换手率', train_data.get('turnover')),
('适应度', metrics.train_metrics.fitness), ('适应度', train_data.get('fitness')),
('PNL', metrics.train_metrics.pnl), ('PNL', train_data.get('pnl')),
] ]
for chinese_name, value in key_metrics: for chinese_name, value in key_metrics:
if value is not None: if value is not None:
if isinstance(value, float): if isinstance(value, float):
value = f"{value:.4f}" value = f"{value:.4f}"
print(f" {chinese_name}: {value}") print(f" {chinese_name}: {value}") # 衡量风险调整后的收益
# 年化收益率
# 显示样本外测试的夏普比率(如果存在) # 显示样本外测试的夏普比率(如果存在) # 最大亏损幅度
if metrics.test_metrics.sharpe_ratio is not None: test_data = metrics.get('test', {}) or {} # 交易频率
print(f" 样本外夏普比率: {metrics.test_metrics.sharpe_ratio:.4f}") if test_data.get('sharpe') is not None: # 策略适应度得分
print(f" 样本外夏普比率: {test_data.get('sharpe'):.4f}") # 净盈亏
"""模拟一批Alpha因子(3个一组)""" """模拟一批Alpha因子(3个一组)"""
def simulate_alpha_batch(self, alpha_batch: List[str], batch_number: int) -> List[SimulationResult]: def simulate_alpha_batch(self, alpha_batch: List[str], batch_number: int) -> List[SimulationResult]:
print(f"\n{'=' * 60}") print(f"\n{'=' * 60}") # 只打印存在的指标
print(f"开始第 {batch_number} 批因子模拟 (共 {len(alpha_batch)} 个因子)") print(f"开始第 {batch_number} 批因子模拟 (共 {len(alpha_batch)} 个因子)") # 格式化浮点数显示
print(f"因子列表: {alpha_batch}") print(f"因子列表: {alpha_batch}")
print(f"{'=' * 60}") print(f"{'=' * 60}")
batch_start_time = time.time() batch_start_time = time.time()
batch_results = [] batch_results = []
# 检查是否存在测试集夏普比率
# 创建API客户端实例(每个线程独立的客户端) # 创建API客户端实例(每个线程独立的客户端)
api = WorldQuantBrainSimulate(self.credentials_file) api = WorldQuantBrainSimulate(self.credentials_file)
@ -200,12 +207,26 @@ class AlphaSimulationManager:
print(f"总耗时: {format_time(total_time)}") print(f"总耗时: {format_time(total_time)}")
print(f"{'=' * 60}") print(f"{'=' * 60}")
success_expression_list = []
for i, result in enumerate(results, 1): for i, result in enumerate(results, 1):
status_icon = "" if result.status == 'success' else "" status_icon = "" if result.status == 'success' else ""
print(f"{i}. {status_icon} {result.expression}")
print(f" 状态: {result.status}") if result.status == 'success':
print(f" 耗时: {result.formatted_time}") success_expression_list.append(result.expression)
print(f" Alpha ID: {result.alpha_id}")
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': if result.status != 'success':
print(f" 原因: {result.description}") line_parts.append(f"原因: {result.description}")
print()
print("\t".join(line_parts))
save_success_alpha(success_expression_list)

@ -1,139 +0,0 @@
[
{
"expression": "ts_rank(ts_returns(close, 15), 30)",
"time_consuming": 5.89,
"formatted_time": "5.89秒",
"alpha_id": "/",
"status": "error",
"description": "Attempted to use inaccessible or unknown operator \"ts_returns\"",
"simulation_timestamp": "2025-11-13 23:30:43",
"train_metrics": null,
"is_metrics": null,
"test_metrics": null,
"alpha_info": null
},
{
"expression": "(close - ts_min(close, 20)) / (ts_max(close, 20) - ts_min(close, 20))",
"time_consuming": 7.89,
"formatted_time": "7.89秒",
"alpha_id": "/",
"status": "error",
"description": "Attempted to use inaccessible or unknown operator \"ts_min\"",
"simulation_timestamp": "2025-11-13 23:30:45",
"train_metrics": null,
"is_metrics": null,
"test_metrics": null,
"alpha_info": null
},
{
"expression": "-ts_corr(ts_rank(close, 30), ts_rank(volume, 30), 10)",
"time_consuming": 88.99,
"formatted_time": "1分28.99秒",
"alpha_id": "JjEVlkNx",
"status": "success",
"description": "/",
"simulation_timestamp": "2025-11-13 23:32:06",
"train_metrics": {
"sharpe_ratio": null,
"annual_return": null,
"max_drawdown": null,
"turnover": null,
"fitness": null,
"pnl": null,
"book_size": null,
"long_count": null,
"short_count": null,
"margin": null
},
"is_metrics": {
"sharpe_ratio": 1.15,
"annual_return": 0.0604,
"max_drawdown": 0.1311,
"turnover": 0.4517,
"fitness": 0.42,
"pnl": 2988907
},
"test_metrics": {
"sharpe_ratio": null,
"annual_return": null,
"max_drawdown": null,
"turnover": null,
"fitness": null,
"pnl": null
},
"alpha_info": {
"grade": "INFERIOR",
"stage": "IS",
"status": "UNSUBMITTED",
"date_created": "2025-11-13T10:32:05-05:00",
"checks": {
"low_sharpe": {
"result": "FAIL",
"value": 1.15,
"limit": 1.25
},
"low_fitness": {
"result": "FAIL",
"value": 0.42,
"limit": 1.0
},
"low_turnover": {
"result": "PASS",
"value": 0.4517,
"limit": 0.01
},
"high_turnover": {
"result": "PASS",
"value": 0.4517,
"limit": 0.7
},
"concentrated_weight": {
"result": "PASS",
"value": null,
"limit": null
},
"low_sub_universe_sharpe": {
"result": "PASS",
"value": 0.76,
"limit": 0.5
},
"self_correlation": {
"result": "PENDING",
"value": null,
"limit": null
},
"matches_competition": {
"result": "PASS",
"value": null,
"limit": null
}
}
}
},
{
"expression": "-ts_std(ts_returns(close, 1), 30)",
"time_consuming": 1.42,
"formatted_time": "1.42秒",
"alpha_id": "/",
"status": "error",
"description": "Attempted to use inaccessible or unknown operator \"ts_std\"",
"simulation_timestamp": "2025-11-13 23:32:15",
"train_metrics": null,
"is_metrics": null,
"test_metrics": null,
"alpha_info": null
},
{
"expression": "ts_rank(ts_delta(close, 3) / ts_delay(close, 3), 15)",
"time_consuming": 148.04,
"formatted_time": "2分28.04秒",
"alpha_id": "/",
"status": "failed",
"description": "_ssl.c:980: The handshake operation timed out",
"simulation_timestamp": "2025-11-13 23:34:42",
"train_metrics": null,
"is_metrics": null,
"test_metrics": null,
"alpha_info": null
}
]

@ -0,0 +1,289 @@
[
{
"expression": "-ts_correlation(open, close, 20)",
"time_consuming": 21.09,
"formatted_time": "21.09秒",
"alpha_id": "/",
"status": "error",
"description": "Attempted to use inaccessible or unknown operator \"ts_correlation\"",
"simulation_timestamp": "2025-11-14 16:35:40",
"metrics": null
},
{
"expression": "ts_mean(volume / ts_mean(volume, 20), 30)",
"time_consuming": 90.94,
"formatted_time": "1分30.94秒",
"alpha_id": "akZ63dm1",
"status": "success",
"description": "/",
"simulation_timestamp": "2025-11-14 16:36:50",
"metrics": {
"id": "akZ63dm1",
"type": "REGULAR",
"author": "YC93384",
"settings": {
"instrumentType": "EQUITY",
"region": "USA",
"universe": "TOP3000",
"delay": 1,
"decay": 0,
"neutralization": "INDUSTRY",
"truncation": 0.08,
"pasteurization": "ON",
"unitHandling": "VERIFY",
"nanHandling": "OFF",
"maxTrade": "OFF",
"language": "FASTEXPR",
"visualization": false,
"startDate": "2018-01-20",
"endDate": "2023-01-20"
},
"regular": {
"code": "ts_mean(volume / ts_mean(volume, 20), 30)",
"description": null,
"operatorCount": 3
},
"dateCreated": "2025-11-14T03:36:48-05:00",
"dateSubmitted": null,
"dateModified": "2025-11-14T03:36:48-05:00",
"name": null,
"favorite": false,
"hidden": false,
"color": null,
"category": null,
"tags": [],
"classifications": [
{
"id": "DATA_USAGE:SINGLE_DATA_SET",
"name": "Single Data Set Alpha"
}
],
"grade": "INFERIOR",
"stage": "IS",
"status": "UNSUBMITTED",
"is": {
"pnl": 752501,
"bookSize": 20000000,
"longCount": 1462,
"shortCount": 1666,
"turnover": 0.1707,
"returns": 0.0152,
"drawdown": 0.1146,
"margin": 0.000178,
"sharpe": 0.25,
"fitness": 0.07,
"startDate": "2018-01-20",
"checks": [
{
"name": "LOW_SHARPE",
"result": "FAIL",
"limit": 1.25,
"value": 0.25
},
{
"name": "LOW_FITNESS",
"result": "FAIL",
"limit": 1.0,
"value": 0.07
},
{
"name": "LOW_TURNOVER",
"result": "PASS",
"limit": 0.01,
"value": 0.1707
},
{
"name": "HIGH_TURNOVER",
"result": "PASS",
"limit": 0.7,
"value": 0.1707
},
{
"name": "CONCENTRATED_WEIGHT",
"result": "PASS"
},
{
"name": "LOW_SUB_UNIVERSE_SHARPE",
"result": "PASS",
"limit": 0.11,
"value": 0.83
},
{
"name": "SELF_CORRELATION",
"result": "PENDING"
},
{
"name": "MATCHES_COMPETITION",
"result": "PASS",
"competitions": [
{
"id": "challenge",
"name": "Challenge"
}
]
}
]
},
"os": null,
"train": null,
"test": null,
"prod": null,
"competitions": null,
"themes": null,
"pyramids": null,
"pyramidThemes": null,
"team": null
}
},
{
"expression": "ts_rank((high - low) / (close - open + 0.001), 15)",
"time_consuming": 116.93,
"formatted_time": "1分56.93秒",
"alpha_id": "VkjVoGGb",
"status": "success",
"description": "/",
"simulation_timestamp": "2025-11-14 16:37:16",
"metrics": {
"id": "VkjVoGGb",
"type": "REGULAR",
"author": "YC93384",
"settings": {
"instrumentType": "EQUITY",
"region": "USA",
"universe": "TOP3000",
"delay": 1,
"decay": 0,
"neutralization": "INDUSTRY",
"truncation": 0.08,
"pasteurization": "ON",
"unitHandling": "VERIFY",
"nanHandling": "OFF",
"maxTrade": "OFF",
"language": "FASTEXPR",
"visualization": false,
"startDate": "2018-01-20",
"endDate": "2023-01-20"
},
"regular": {
"code": "ts_rank((high - low) / (close - open + 0.001), 15)",
"description": null,
"operatorCount": 5
},
"dateCreated": "2025-11-14T03:37:13-05:00",
"dateSubmitted": null,
"dateModified": "2025-11-14T03:37:14-05:00",
"name": null,
"favorite": false,
"hidden": false,
"color": null,
"category": null,
"tags": [],
"classifications": [
{
"id": "DATA_USAGE:SINGLE_DATA_SET",
"name": "Single Data Set Alpha"
}
],
"grade": "INFERIOR",
"stage": "IS",
"status": "UNSUBMITTED",
"is": {
"pnl": -1933631,
"bookSize": 20000000,
"longCount": 1562,
"shortCount": 1565,
"turnover": 1.3813,
"returns": -0.0391,
"drawdown": 0.2222,
"margin": -5.7e-05,
"sharpe": -1.15,
"fitness": -0.19,
"startDate": "2018-01-20",
"checks": [
{
"name": "LOW_SHARPE",
"result": "FAIL",
"limit": 1.25,
"value": -1.15
},
{
"name": "LOW_FITNESS",
"result": "FAIL",
"limit": 1.0,
"value": -0.19
},
{
"name": "LOW_TURNOVER",
"result": "PASS",
"limit": 0.01,
"value": 1.3813
},
{
"name": "HIGH_TURNOVER",
"result": "FAIL",
"limit": 0.7,
"value": 1.3813
},
{
"name": "CONCENTRATED_WEIGHT",
"result": "PASS"
},
{
"name": "LOW_SUB_UNIVERSE_SHARPE",
"result": "FAIL",
"limit": -0.5,
"value": -0.73
},
{
"name": "UNITS",
"result": "WARNING",
"message": "Incompatible unit for input of \"add\" at index 1, expected \"Unit[CSPrice:1]\", found \"Unit[]\""
},
{
"name": "SELF_CORRELATION",
"result": "PENDING"
},
{
"name": "MATCHES_COMPETITION",
"result": "PASS",
"competitions": [
{
"id": "challenge",
"name": "Challenge"
}
]
}
]
},
"os": null,
"train": null,
"test": null,
"prod": null,
"competitions": null,
"themes": null,
"pyramids": null,
"pyramidThemes": null,
"team": null
}
},
{
"expression": "-ts_rank(ts_skewness(returns(close), 10), 25)",
"time_consuming": 1.44,
"formatted_time": "1.44秒",
"alpha_id": "/",
"status": "error",
"description": "Attempted to use inaccessible or unknown operator \"ts_skewness\"",
"simulation_timestamp": "2025-11-14 16:37:22",
"metrics": null
},
{
"expression": "(close - ts_min(low, 50)) / (ts_max(high, 50) - ts_min(low, 50) + 0.001)",
"time_consuming": 5.76,
"formatted_time": "5.76秒",
"alpha_id": "/",
"status": "error",
"description": "Attempted to use inaccessible or unknown operator \"ts_min\"",
"simulation_timestamp": "2025-11-14 16:37:26",
"metrics": null
}
]

@ -0,0 +1,524 @@
[
{
"expression": "ts_rank(close - vwap, 12)",
"time_consuming": 15.79,
"formatted_time": "15.79秒",
"alpha_id": "/",
"status": "failed",
"description": "The read operation timed out",
"simulation_timestamp": "2025-11-14 16:58:48",
"metrics": null
},
{
"expression": "ts_mean((close - open) / (high - low + 0.001), 20)",
"time_consuming": 109.71,
"formatted_time": "1分49.71秒",
"alpha_id": "VkjVwxrG",
"status": "success",
"description": "/",
"simulation_timestamp": "2025-11-14 17:00:22",
"metrics": {
"id": "VkjVwxrG",
"type": "REGULAR",
"author": "YC93384",
"settings": {
"instrumentType": "EQUITY",
"region": "USA",
"universe": "TOP3000",
"delay": 1,
"decay": 0,
"neutralization": "INDUSTRY",
"truncation": 0.08,
"pasteurization": "ON",
"unitHandling": "VERIFY",
"nanHandling": "OFF",
"maxTrade": "OFF",
"language": "FASTEXPR",
"visualization": false,
"startDate": "2018-01-20",
"endDate": "2023-01-20"
},
"regular": {
"code": "ts_mean((close - open) / (high - low + 0.001), 20)",
"description": null,
"operatorCount": 5
},
"dateCreated": "2025-11-14T04:00:17-05:00",
"dateSubmitted": null,
"dateModified": "2025-11-14T04:00:18-05:00",
"name": null,
"favorite": false,
"hidden": false,
"color": null,
"category": null,
"tags": [],
"classifications": [
{
"id": "DATA_USAGE:SINGLE_DATA_SET",
"name": "Single Data Set Alpha"
}
],
"grade": "INFERIOR",
"stage": "IS",
"status": "UNSUBMITTED",
"is": {
"pnl": -4252305,
"bookSize": 20000000,
"longCount": 1570,
"shortCount": 1558,
"turnover": 0.3075,
"returns": -0.0859,
"drawdown": 0.5096,
"margin": -0.000559,
"sharpe": -0.83,
"fitness": -0.44,
"startDate": "2018-01-20",
"checks": [
{
"name": "LOW_SHARPE",
"result": "FAIL",
"limit": 1.25,
"value": -0.83
},
{
"name": "LOW_FITNESS",
"result": "FAIL",
"limit": 1.0,
"value": -0.44
},
{
"name": "LOW_TURNOVER",
"result": "PASS",
"limit": 0.01,
"value": 0.3075
},
{
"name": "HIGH_TURNOVER",
"result": "PASS",
"limit": 0.7,
"value": 0.3075
},
{
"name": "CONCENTRATED_WEIGHT",
"result": "PASS"
},
{
"name": "LOW_SUB_UNIVERSE_SHARPE",
"result": "FAIL",
"limit": -0.36,
"value": -0.7
},
{
"name": "UNITS",
"result": "WARNING",
"message": "Incompatible unit for input of \"add\" at index 1, expected \"Unit[CSPrice:1]\", found \"Unit[]\""
},
{
"name": "SELF_CORRELATION",
"result": "PENDING"
},
{
"name": "MATCHES_COMPETITION",
"result": "PASS",
"competitions": [
{
"id": "challenge",
"name": "Challenge"
}
]
}
]
},
"os": null,
"train": null,
"test": null,
"prod": null,
"competitions": null,
"themes": null,
"pyramids": null,
"pyramidThemes": null,
"team": null
}
},
{
"expression": "-ts_rank(ts_decay_linear(volume, 10), 30)",
"time_consuming": 124.43,
"formatted_time": "2分4.43秒",
"alpha_id": "E5W10mem",
"status": "success",
"description": "/",
"simulation_timestamp": "2025-11-14 17:00:37",
"metrics": {
"id": "E5W10mem",
"type": "REGULAR",
"author": "YC93384",
"settings": {
"instrumentType": "EQUITY",
"region": "USA",
"universe": "TOP3000",
"delay": 1,
"decay": 0,
"neutralization": "INDUSTRY",
"truncation": 0.08,
"pasteurization": "ON",
"unitHandling": "VERIFY",
"nanHandling": "OFF",
"maxTrade": "OFF",
"language": "FASTEXPR",
"visualization": false,
"startDate": "2018-01-20",
"endDate": "2023-01-20"
},
"regular": {
"code": "-ts_rank(ts_decay_linear(volume, 10), 30)",
"description": null,
"operatorCount": 3
},
"dateCreated": "2025-11-14T04:00:33-05:00",
"dateSubmitted": null,
"dateModified": "2025-11-14T04:00:34-05:00",
"name": null,
"favorite": false,
"hidden": false,
"color": null,
"category": null,
"tags": [],
"classifications": [
{
"id": "DATA_USAGE:SINGLE_DATA_SET",
"name": "Single Data Set Alpha"
}
],
"grade": "INFERIOR",
"stage": "IS",
"status": "UNSUBMITTED",
"is": {
"pnl": -1352690,
"bookSize": 20000000,
"longCount": 1610,
"shortCount": 1517,
"turnover": 0.3383,
"returns": -0.0273,
"drawdown": 0.2176,
"margin": -0.000162,
"sharpe": -0.58,
"fitness": -0.16,
"startDate": "2018-01-20",
"checks": [
{
"name": "LOW_SHARPE",
"result": "FAIL",
"limit": 1.25,
"value": -0.58
},
{
"name": "LOW_FITNESS",
"result": "FAIL",
"limit": 1.0,
"value": -0.16
},
{
"name": "LOW_TURNOVER",
"result": "PASS",
"limit": 0.01,
"value": 0.3383
},
{
"name": "HIGH_TURNOVER",
"result": "PASS",
"limit": 0.7,
"value": 0.3383
},
{
"name": "CONCENTRATED_WEIGHT",
"result": "PASS"
},
{
"name": "LOW_SUB_UNIVERSE_SHARPE",
"result": "FAIL",
"limit": -0.25,
"value": -0.66
},
{
"name": "SELF_CORRELATION",
"result": "PENDING"
},
{
"name": "MATCHES_COMPETITION",
"result": "PASS",
"competitions": [
{
"id": "challenge",
"name": "Challenge"
}
]
}
]
},
"os": null,
"train": null,
"test": null,
"prod": null,
"competitions": null,
"themes": null,
"pyramids": null,
"pyramidThemes": null,
"team": null
}
},
{
"expression": "ts_rank(adv20 - volume, 15) + ts_rank(volume, 15)",
"time_consuming": 85.26,
"formatted_time": "1分25.26秒",
"alpha_id": "0m3qkZN1",
"status": "success",
"description": "/",
"simulation_timestamp": "2025-11-14 17:02:08",
"metrics": {
"id": "0m3qkZN1",
"type": "REGULAR",
"author": "YC93384",
"settings": {
"instrumentType": "EQUITY",
"region": "USA",
"universe": "TOP3000",
"delay": 1,
"decay": 0,
"neutralization": "INDUSTRY",
"truncation": 0.08,
"pasteurization": "ON",
"unitHandling": "VERIFY",
"nanHandling": "OFF",
"maxTrade": "OFF",
"language": "FASTEXPR",
"visualization": false,
"startDate": "2018-01-20",
"endDate": "2023-01-20"
},
"regular": {
"code": "ts_rank(adv20 - volume, 15) + ts_rank(volume, 15)",
"description": null,
"operatorCount": 4
},
"dateCreated": "2025-11-14T04:02:06-05:00",
"dateSubmitted": null,
"dateModified": "2025-11-14T04:02:07-05:00",
"name": null,
"favorite": false,
"hidden": false,
"color": null,
"category": null,
"tags": [],
"classifications": [
{
"id": "DATA_USAGE:SINGLE_DATA_SET",
"name": "Single Data Set Alpha"
}
],
"grade": "INFERIOR",
"stage": "IS",
"status": "UNSUBMITTED",
"is": {
"pnl": 1607957,
"bookSize": 20000000,
"longCount": 1749,
"shortCount": 1375,
"turnover": 0.8699,
"returns": 0.0325,
"drawdown": 0.0811,
"margin": 7.5e-05,
"sharpe": 0.71,
"fitness": 0.14,
"startDate": "2018-01-20",
"checks": [
{
"name": "LOW_SHARPE",
"result": "FAIL",
"limit": 1.25,
"value": 0.71
},
{
"name": "LOW_FITNESS",
"result": "FAIL",
"limit": 1.0,
"value": 0.14
},
{
"name": "LOW_TURNOVER",
"result": "PASS",
"limit": 0.01,
"value": 0.8699
},
{
"name": "HIGH_TURNOVER",
"result": "FAIL",
"limit": 0.7,
"value": 0.8699
},
{
"name": "CONCENTRATED_WEIGHT",
"result": "PASS"
},
{
"name": "LOW_SUB_UNIVERSE_SHARPE",
"result": "PASS",
"limit": 0.31,
"value": 0.84
},
{
"name": "SELF_CORRELATION",
"result": "PENDING"
},
{
"name": "MATCHES_COMPETITION",
"result": "PASS",
"competitions": [
{
"id": "challenge",
"name": "Challenge"
}
]
}
]
},
"os": null,
"train": null,
"test": null,
"prod": null,
"competitions": null,
"themes": null,
"pyramids": null,
"pyramidThemes": null,
"team": null
}
},
{
"expression": "ts_mean(high - ts_delay(high, 1), 60) - ts_mean(low - ts_delay(low, 1), 60)",
"time_consuming": 86.01,
"formatted_time": "1分26.01秒",
"alpha_id": "wpxqw73d",
"status": "success",
"description": "/",
"simulation_timestamp": "2025-11-14 17:02:09",
"metrics": {
"id": "wpxqw73d",
"type": "REGULAR",
"author": "YC93384",
"settings": {
"instrumentType": "EQUITY",
"region": "USA",
"universe": "TOP3000",
"delay": 1,
"decay": 0,
"neutralization": "INDUSTRY",
"truncation": 0.08,
"pasteurization": "ON",
"unitHandling": "VERIFY",
"nanHandling": "OFF",
"maxTrade": "OFF",
"language": "FASTEXPR",
"visualization": false,
"startDate": "2018-01-20",
"endDate": "2023-01-20"
},
"regular": {
"code": "ts_mean(high - ts_delay(high, 1), 60) - ts_mean(low - ts_delay(low, 1), 60)",
"description": null,
"operatorCount": 7
},
"dateCreated": "2025-11-14T04:02:06-05:00",
"dateSubmitted": null,
"dateModified": "2025-11-14T04:02:06-05:00",
"name": null,
"favorite": false,
"hidden": false,
"color": null,
"category": null,
"tags": [],
"classifications": [
{
"id": "DATA_USAGE:SINGLE_DATA_SET",
"name": "Single Data Set Alpha"
}
],
"grade": "INFERIOR",
"stage": "IS",
"status": "UNSUBMITTED",
"is": {
"pnl": -1454336,
"bookSize": 20000000,
"longCount": 1602,
"shortCount": 1526,
"turnover": 1.0897,
"returns": -0.0294,
"drawdown": 0.5598,
"margin": -5.4e-05,
"sharpe": -0.19,
"fitness": -0.03,
"startDate": "2018-01-20",
"checks": [
{
"name": "LOW_SHARPE",
"result": "FAIL",
"limit": 1.25,
"value": -0.19
},
{
"name": "LOW_FITNESS",
"result": "FAIL",
"limit": 1.0,
"value": -0.03
},
{
"name": "LOW_TURNOVER",
"result": "PASS",
"limit": 0.01,
"value": 1.0897
},
{
"name": "HIGH_TURNOVER",
"result": "FAIL",
"limit": 0.7,
"value": 1.0897
},
{
"name": "CONCENTRATED_WEIGHT",
"result": "FAIL",
"date": "2022-10-27",
"limit": 0.1,
"value": 0.298634
},
{
"name": "LOW_SUB_UNIVERSE_SHARPE",
"result": "FAIL",
"limit": -0.08,
"value": -0.37
},
{
"name": "SELF_CORRELATION",
"result": "PENDING"
},
{
"name": "MATCHES_COMPETITION",
"result": "PASS",
"competitions": [
{
"id": "challenge",
"name": "Challenge"
}
]
}
]
},
"os": null,
"train": null,
"test": null,
"prod": null,
"competitions": null,
"themes": null,
"pyramids": null,
"pyramidThemes": null,
"team": null
}
}
]

@ -0,0 +1,82 @@
[
{
"expression": "ts_mean(close, 20) / ts_mean(close, 100) > 1.05 and ts_std(close / ts_mean(close, 10), 20) / ts_mean(close, 20) < 0.15",
"time_consuming": 5.94,
"formatted_time": "5.94秒",
"alpha_id": "/",
"status": "error",
"description": "Unexpected character 'a' near \"0) > 1.05 and ts_std\"",
"simulation_timestamp": "2025-11-14 17:35:28",
"metrics": null
},
{
"expression": "ts_min(low, 20) / ts_max(high, 60) > 0.8 and market_cap > ts_mean(market_cap, all)",
"time_consuming": 6.53,
"formatted_time": "6.53秒",
"alpha_id": "/",
"status": "error",
"description": "Unexpected character 'a' near \"60) > 0.8 and market\"",
"simulation_timestamp": "2025-11-14 17:35:29",
"metrics": null
},
{
"expression": "close > ts_mean(close, 50) and ts_delta(ts_rank(volume, 10), 5) > 0",
"time_consuming": 7.6,
"formatted_time": "7.60秒",
"alpha_id": "/",
"status": "error",
"description": "Unexpected character 'a' near \"lose, 50) and ts_del\"",
"simulation_timestamp": "2025-11-14 17:35:30",
"metrics": null
},
{
"expression": "ts_corr(close, vwap, 30) < 0.3 and ts_mean(volume, 5) / ts_mean(volume, 60) < 0.8",
"time_consuming": 5.8,
"formatted_time": "5.80秒",
"alpha_id": "/",
"status": "error",
"description": "Unexpected character 'a' near \"30) < 0.3 and ts_mea\"",
"simulation_timestamp": "2025-11-14 17:35:40",
"metrics": null
},
{
"expression": "abs(close - vwap) / vwap < 0.02 and volume < ts_mean(volume, 20)",
"time_consuming": 6.62,
"formatted_time": "6.62秒",
"alpha_id": "/",
"status": "error",
"description": "Unexpected character 'a' near \"ap < 0.02 and volume\"",
"simulation_timestamp": "2025-11-14 17:35:41",
"metrics": null
},
{
"expression": "(close - ts_mean(close, 30)) / ts_std(close, 30) > 1.5 and ts_delta(close, 5) < 0",
"time_consuming": 15.51,
"formatted_time": "15.51秒",
"alpha_id": "/",
"status": "error",
"description": "Unexpected character 'a' near \"30) > 1.5 and ts_del\"",
"simulation_timestamp": "2025-11-14 17:35:50",
"metrics": null
},
{
"expression": "ts_std(log(close / close[1]), 20) > ts_mean(ts_std(log(close / close[1]), 20), 60)",
"time_consuming": 1.2,
"formatted_time": "1.20秒",
"alpha_id": "/",
"status": "error",
"description": "Unexpected character '[' near \"se / close[1]), 20)\"",
"simulation_timestamp": "2025-11-14 17:35:56",
"metrics": null
},
{
"expression": "ts_range(high - low, 5) / ts_mean(high - low, 60) > 1.5 and ts_delta(ts_std(close, 10), 5) > 0",
"time_consuming": 7.38,
"formatted_time": "7.38秒",
"alpha_id": "/",
"status": "error",
"description": "Unexpected character 'a' near \"60) > 1.5 and ts_del\"",
"simulation_timestamp": "2025-11-14 17:36:02",
"metrics": null
}
]

@ -0,0 +1,12 @@
[
{
"expression": "ts_delta(ts_mean(close, 5), 10) / ts_std(close, 20) * (ts_mean(close, 20) / ts_mean(close, 100) > 1.02)",
"time_consuming": 6.62,
"formatted_time": "6.62秒",
"alpha_id": "/",
"status": "error",
"description": "Attempted to use inaccessible or unknown operator \"ts_std\"",
"simulation_timestamp": "2025-11-14 17:41:26",
"metrics": null
}
]

@ -0,0 +1,4 @@
ts_mean((close - open) / (high - low + 0.001), 20)
-ts_rank(ts_decay_linear(volume, 10), 30)
ts_rank(adv20 - volume, 15) + ts_rank(volume, 15)
ts_mean(high - ts_delay(high, 1), 60) - ts_mean(low - ts_delay(low, 1), 60)

@ -26,7 +26,7 @@ def save_results_to_file(results: List[Any], result_dir: str = 'result') -> str:
serializable_results = [] serializable_results = []
for result in results: for result in results:
if hasattr(result, '__dict__'): if hasattr(result, '__dict__'):
# 如果是dataclass对象 # 如果是dataclass对象,转换为字典
result_dict = result.__dict__.copy() result_dict = result.__dict__.copy()
else: else:
# 如果是字典 # 如果是字典
@ -36,14 +36,19 @@ def save_results_to_file(results: List[Any], result_dir: str = 'result') -> str:
if 'time_consuming' in result_dict: if 'time_consuming' in result_dict:
result_dict['time_consuming'] = round(result_dict['time_consuming'], 2) result_dict['time_consuming'] = round(result_dict['time_consuming'], 2)
# 处理metrics对象 # 只需要确保所有浮点数精度一致
for key in list(result_dict.keys()): def round_floats(obj):
if hasattr(result_dict[key], '__dict__'): if isinstance(obj, float):
result_dict[key] = result_dict[key].__dict__ return round(obj, 6)
# 处理浮点数精度 elif isinstance(obj, dict):
for metric_key, value in result_dict[key].items(): return {k: round_floats(v) for k, v in obj.items()}
if isinstance(value, float): elif isinstance(obj, list):
result_dict[key][metric_key] = round(value, 6) return [round_floats(item) for item in obj]
else:
return obj
# 对结果中的所有浮点数进行精度处理
result_dict = round_floats(result_dict)
serializable_results.append(result_dict) serializable_results.append(result_dict)
@ -56,4 +61,24 @@ def save_results_to_file(results: List[Any], result_dir: str = 'result') -> str:
json.dump(serializable_results, f, ensure_ascii=False, indent=2) json.dump(serializable_results, f, ensure_ascii=False, indent=2)
print(f"结果已保存到 {result_name}") print(f"结果已保存到 {result_name}")
return result_name return result_name
def save_success_alpha(success_expression_list):
"""
将成功的表达式列表保存到 success.txt 文件中
如果文件不存在则创建如果存在则追加写入
"""
if not success_expression_list:
print("没有成功的表达式需要保存")
return
try:
with open('success.txt', 'a', encoding='utf-8') as f:
for expression in success_expression_list:
f.write(expression + '\n')
print(f"成功保存 {len(success_expression_list)} 个表达式到 success.txt")
except Exception as e:
print(f"保存文件时出错: {e}")

Loading…
Cancel
Save