This commit is contained in:
2025-11-24 22:35:47 +08:00
parent 3508a1b496
commit f2a149d2cf
10 changed files with 269 additions and 217 deletions
+130 -217
View File
@@ -1,220 +1,133 @@
"""Alpha 因子表达式生成器 - 增强随机版本"""
import random
import itertools
from typing import List
class AlphaGenerator:
"""增强版因子表达式生成器,支持随机生成多样化因子"""
def __init__(self, seed=None):
if seed:
random.seed(seed)
# 基础操作符和函数库
OPERATORS = ['+', '-', '*', '/']
UNARY_OPERATORS = ['-', 'abs', 'rank', 'log', 'power', 'sqrt']
TIME_SERIES_FUNCTIONS = [
'delay', 'ts_mean', 'ts_std_dev', 'ts_rank', 'ts_decay_linear',
'ts_corr', 'ts_skewness', 'ts_kurtosis', 'ts_max', 'ts_min',
'ts_sum', 'ts_product', 'ts_delta', 'ts_returns'
]
GROUP_FUNCTIONS = [
'group_rank', 'group_mean', 'group_std', 'group_neutralize',
'group_zscore', 'group_percentile'
]
CONDITIONAL_FUNCTIONS = [
'if_else', 'trade_when', 'condition_filter', 'signal_when'
]
# 基础字段模板
BASE_FIELDS = ['open', 'close', 'high', 'low', 'volume', 'returns',
'vwap', 'turnover', 'volatility', 'cap', 'market_cap']
def generate_random_expression(self, datafields, depth=0, max_depth=3):
"""递归生成随机表达式"""
if depth >= max_depth or random.random() < 0.3:
# 叶子节点 - 选择基础字段或常数
if random.random() < 0.7 and datafields:
field = random.choice(datafields)
return field
else:
return f"{random.uniform(0.1, 10.0):.2f}"
# 选择操作类型
op_type = random.choice(['binary', 'unary', 'ts_function', 'group_function', 'conditional'])
if op_type == 'binary':
left = self.generate_random_expression(datafields, depth + 1, max_depth)
right = self.generate_random_expression(datafields, depth + 1, max_depth)
op = random.choice(self.OPERATORS)
return f"({left} {op} {right})"
elif op_type == 'unary':
arg = self.generate_random_expression(datafields, depth + 1, max_depth)
op = random.choice(self.UNARY_OPERATORS)
if op in ['-', 'abs']:
return f"{op}({arg})"
else:
return f"{op}({arg}, {random.randint(1, 30)})"
elif op_type == 'ts_function':
func = random.choice(self.TIME_SERIES_FUNCTIONS)
arg1 = self.generate_random_expression(datafields, depth + 1, max_depth)
lookback = random.choice([5, 10, 20, 30, 60, 90, 252])
if func in ['ts_corr', 'ts_covariance']:
arg2 = self.generate_random_expression(datafields, depth + 1, max_depth)
return f"{func}({arg1}, {arg2}, {lookback})"
else:
return f"{func}({arg1}, {lookback})"
elif op_type == 'group_function':
func = random.choice(self.GROUP_FUNCTIONS)
arg = self.generate_random_expression(datafields, depth + 1, max_depth)
group_by = random.choice(['subindustry', 'industry', 'sector', 'bucket(cap, range="0.1,1,0.1")'])
return f"{func}({arg}, {group_by})"
else: # conditional
func = random.choice(self.CONDITIONAL_FUNCTIONS)
condition = self.generate_random_expression(datafields, depth + 1, max_depth)
true_val = self.generate_random_expression(datafields, depth + 1, max_depth)
false_val = self.generate_random_expression(datafields, depth + 1, max_depth)
return f"{func}({condition} > 0, {true_val}, {false_val})"
def generate_basic_strategies(self, datafields, count=50):
"""生成基础单因子策略"""
strategies = []
for _ in range(count):
# 随机选择1-3个字段组合
num_fields = random.randint(1, 3)
selected_fields = random.sample(datafields, min(num_fields, len(datafields)))
# 生成随机表达式
expr = self.generate_random_expression(selected_fields)
# 添加分组操作
if random.random() < 0.7:
group_by = random.choice(['subindustry', 'industry'])
expr = f"group_rank({expr}, {group_by})"
strategies.append(expr)
return strategies
def generate_multi_factor_strategies(self, datafields, count=50):
"""生成多因子组合策略"""
strategies = []
for _ in range(count):
# 选择更多字段进行复杂组合
num_fields = random.randint(2, 5)
selected_fields = random.sample(datafields, min(num_fields, len(datafields)))
# 生成更复杂的表达式
expr = self.generate_random_expression(selected_fields, max_depth=4)
# 添加中性化或标准化
if random.random() < 0.6:
neutral_type = random.choice(['group_neutralize', 'regression_neut', 'vector_neut'])
if neutral_type == 'group_neutralize':
group_by = random.choice(['subindustry', 'industry', 'sector'])
expr = f"{neutral_type}({expr}, {group_by})"
else:
# 为回归中性化选择另一个因子
other_field = random.choice([f for f in datafields if f not in selected_fields] or selected_fields)
expr = f"{neutral_type}({expr}, {other_field})"
strategies.append(expr)
return strategies
def generate_advanced_strategies(self, datafields, count=30):
"""生成高级策略(均值回归、动量、波动率策略等)"""
strategies = []
# 均值回归策略
for _ in range(count // 3):
field = random.choice(datafields)
lookback = random.choice([5, 10, 20, 30])
expr = f"-ts_rank({field} - ts_mean({field}, {lookback}), 20)"
strategies.append(f"group_neutralize({expr}, subindustry)")
# 动量策略
for _ in range(count // 3):
field = random.choice(datafields)
short_lookback = random.choice([1, 2, 3, 5])
long_lookback = random.choice([10, 20, 30, 60])
expr = f"ts_mean({field}, {short_lookback}) - ts_mean({field}, {long_lookback})"
strategies.append(f"group_rank({expr}, subindustry)")
# 波动率策略
for _ in range(count // 3):
field = random.choice(datafields)
vol_lookback = random.choice([10, 20, 30])
expr = f"{field} / ts_std_dev({field}, {vol_lookback})"
strategies.append(f"group_rank({expr}, subindustry)")
return strategies
def generate_strategies(self, datafields, mode=1, count=100):
"""
生成因子表达式列表
参数:
datafields: 数据字段列表
mode: 生成模式 (1=基础策略, 2=多因子组合, 3=高级策略, 4=混合模式)
count: 生成数量
返回:
因子表达式列表
"""
all_fields = datafields + self.BASE_FIELDS
unique_fields = list(set(all_fields)) # 去重
if mode == 1:
return self.generate_basic_strategies(unique_fields, count)
elif mode == 2:
return self.generate_multi_factor_strategies(unique_fields, count)
elif mode == 3:
return self.generate_advanced_strategies(unique_fields, count)
elif mode == 4:
# 混合模式 - 从所有类型中随机选择
basic = self.generate_basic_strategies(unique_fields, count // 3)
multi = self.generate_multi_factor_strategies(unique_fields, count // 3)
advanced = self.generate_advanced_strategies(unique_fields, count // 3)
return basic + multi + advanced
else:
print("❌ 无效的生成模式,使用混合模式")
return self.generate_strategies(unique_fields, mode=4, count=count)
import os
import json
import openai
from datetime import datetime
def load_config(config_file="config.json"):
try:
with open(config_file, 'r', encoding='utf-8') as f:
return json.load(f)
except FileNotFoundError:
print(f"创建配置文件: {config_file}")
with open(config_file, 'w', encoding='utf-8') as f:
json.dump({}, f, indent=4)
print("请在config.json中配置siliconflow的api信息")
return None
def create_prompt_file():
if not os.path.exists("prompt.txt"):
with open("prompt.txt", 'w', encoding='utf-8') as f:
f.write("")
print("已创建prompt.txt,请填入提示词后重新运行")
return False
return True
def read_prompt():
with open("prompt.txt", 'r', encoding='utf-8') as f:
prompt = f.read().strip()
if not prompt:
print("prompt.txt是空的,请填入提示词")
return None
return prompt
def create_result_folder():
if not os.path.exists("ai_result"):
os.makedirs("ai_result")
return "ai_result"
def call_siliconflow(api_key, prompt, model, base_url):
try:
client = openai.OpenAI(
api_key=api_key,
base_url=base_url
)
response = client.chat.completions.create(
model=model,
messages=[{"role": "user", "content": prompt}]
)
return response.choices[0].message.content
except openai.AuthenticationError:
print("API密钥错误")
except openai.RateLimitError:
print("调用频率限制")
except openai.APIError as e:
print(f"API错误: {e}")
except Exception as e:
print(f"其他错误: {e}")
return None
def save_result(result, folder):
timestamp = datetime.now().strftime("%Y%m%d%H%M%S")
filename = f"{timestamp}.txt"
filepath = os.path.join(folder, filename)
with open(filepath, 'w', encoding='utf-8') as f:
f.write(result)
print(f"结果保存到: {filepath}")
def get_ai_config(config):
if not config:
return None
service_name = list(config.keys())[0]
service_config = config[service_name]
required_fields = ["api_keys", "model", "base_url"]
for field in required_fields:
if field not in service_config:
print(f"缺少配置字段: {field}")
return None
return service_name, service_config
def main():
config = load_config()
if not config:
return
if not create_prompt_file():
return
prompt = read_prompt()
if not prompt:
return
config_result = get_ai_config(config)
if not config_result:
return
service_name, service_config = config_result
print(f"使用服务: {service_name}")
print(f"使用模型: {service_config['model']}")
folder = create_result_folder()
print("正在调用AI...")
result = call_siliconflow(
service_config["api_keys"],
prompt,
service_config["model"],
service_config["base_url"]
)
if result:
print(f"AI回复: {result[:200]}...")
save_result(result, folder)
else:
print("AI调用失败")
# 使用示例
if __name__ == "__main__":
# 示例数据字段
sample_fields = ['volume', 'close', 'open', 'high', 'low', 'returns', 'turnover', 'pe_ratio', 'pb_ratio']
generator = AlphaGenerator(seed=42) # 设置随机种子以便复现
print("=== 基础策略因子 (20个示例) ===")
basic_strategies = generator.generate_strategies(sample_fields, mode=1, count=20)
for i, strategy in enumerate(basic_strategies[:10], 1): # 只显示前10个
print(f"{i}. {strategy}")
print(f"\n共生成 {len(basic_strategies)} 个基础因子")
print("\n=== 多因子组合策略 (20个示例) ===")
multi_strategies = generator.generate_strategies(sample_fields, mode=2, count=20)
for i, strategy in enumerate(multi_strategies[:10], 1):
print(f"{i}. {strategy}")
print(f"\n共生成 {len(multi_strategies)} 个多因子组合")
print("\n=== 随机测试 - 每次运行生成不同的因子 ===")
for run in range(3):
print(f"\n--- 第{run+1}次运行 ---")
random_strategies = generator.generate_strategies(sample_fields, mode=4, count=5)
for i, strategy in enumerate(random_strategies, 1):
print(f"{i}. {strategy}")
main()