diff --git a/.gitignore b/.gitignore index cf7c11e..9fe049b 100644 --- a/.gitignore +++ b/.gitignore @@ -63,3 +63,8 @@ target/ other/split_clash_config/split_config ai_news/save_data daily/*.txt + +result/ +./alpha.txt +./account.txt + diff --git a/ai_result/20251124170421.txt b/ai_result/20251124170421.txt new file mode 100644 index 0000000..7a1fcd0 --- /dev/null +++ b/ai_result/20251124170421.txt @@ -0,0 +1,5 @@ +你好!😊 很高兴见到你! + +看起来你在问候后面加了一些空格,不管怎样,我都很开心能和你聊天!我是DeepSeek,一个热心的AI助手,随时准备为你提供帮助。 + +无论你想聊什么话题,需要解答问题,还是想要一些建议,我都会尽我所能地帮助你。今天有什么特别想了解或讨论的吗?✨ \ No newline at end of file diff --git a/ai_result/20251124172559.txt b/ai_result/20251124172559.txt new file mode 100644 index 0000000..1b7955e --- /dev/null +++ b/ai_result/20251124172559.txt @@ -0,0 +1,5 @@ +rank(((ts_rank(close,10)-ts_rank(close,50)))*rank(ts_rank(volume,5))) +rank(ts_corr(ts_rank(close,20),ts_rank(volume,5),10)) +-1*rank((close-ts_mean(close,10))/ts_std_dev(close,10)*ts_mean(volume,30)) +rank(ts_delta(close,15)*rank(ts_corr((high+low)/2,volume,15))) +-1*rank(ts_rank(close,5)-ts_rank(close,60))*rank(ts_std_dev(close,20)*ts_mean(volume,40)) \ No newline at end of file diff --git a/ai_result/20251124174559.txt b/ai_result/20251124174559.txt new file mode 100644 index 0000000..56b845c --- /dev/null +++ b/ai_result/20251124174559.txt @@ -0,0 +1,5 @@ +ts_mean(group_rank(ts_mean(return_60(close), 20)), 5) / ts_std_dev(return_60(close), 20) +group_rank(ts_rank(ts_mean(close/vwap, 60), 20)) - group_rank(ts_rank(close/vwap, 5)) +ts_delay(group_rank(ts_corr(ts_mean(close, 5), ts_mean(volume, 5), 10)), 5) * ts_mean(return_20(close), 5) +group_rank(ts_mean(return_20(close), 10)) / group_rank(ts_std_dev(return_5(close), 20)) +group_rank(ts_mean(return_10(close), 5)) - group_mean(ts_mean(return_10(close), 5)) \ No newline at end of file diff --git a/ai_result/20251124175745.txt b/ai_result/20251124175745.txt new file mode 100644 index 0000000..2f0d1b2 --- /dev/null +++ b/ai_result/20251124175745.txt @@ -0,0 +1,20 @@ + + +Here are the five industry factors using WebSim functions: + +```python +group_mean(ts_return(close, 252), industry) # Industry Momentum Factor +group_mean((close / ts_mean(close, 252) - 1), industry) # Valuation Repair Factor +group_mean(ts_sum((close - ts_lag(close, 1)) * volume, 21), industry) # Capital Flow Factor +group_mean(ts_std(ts_return(close, 1), 21), industry) # Volatility Adjustment Factor +group_mean(ts_rank(close, 252), industry) # Relative Strength Factor +``` + +These factors: +1. Measure industry momentum using 12-month returns +2. Evaluate valuation through 200-day mean reversion +3. Track capital flow with 1-month price-volume accumulation +4. Assess volatility risk with 21-day standard deviation +5. Gauge cross-sectional strength via 12-month price ranking + +Each is calculated by averaging stock-level metrics within industry groups using `group_mean()` for industry-specific signals. \ No newline at end of file diff --git a/ai_result/20251124180630.txt b/ai_result/20251124180630.txt new file mode 100644 index 0000000..f697544 --- /dev/null +++ b/ai_result/20251124180630.txt @@ -0,0 +1,18 @@ + + +```python +# 行业动量因子(相对强度) +group_rank(ts_mean(close / close[3], 3), 'industry') + +# 行业估值修复因子(均值回归) +group_rank(ts_mean(close, 3) / close, 'industry') + +# 行业资金流向因子(量价结合) +group_rank(ts_sum(volume * (close - close[1]), 3), 'industry') + +# 行业波动率特征因子(风险调整) +group_rank(1 / (ts_std(close / close[1], 3) + 1e-8), 'industry') + +# 行业间相对强度因子(横截面) +group_rank(close / ts_max(close, 3), 'industry') +``` \ No newline at end of file diff --git a/config.json b/config.json new file mode 100644 index 0000000..ba31892 --- /dev/null +++ b/config.json @@ -0,0 +1,7 @@ +{ + "siliconflow": { + "base_url": "https://api.siliconflow.cn/v1", + "api_keys": "sk-pvdiisdowmuwkrpnxsrlhxaovicqibmlljwrwwvbbdjaitdl", + "model": "Qwen/Qwen3-VL-235B-A22B-Instruct" + } +} \ No newline at end of file diff --git a/main.py b/main.py index 25767e4..5049549 100644 --- a/main.py +++ b/main.py @@ -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}") \ No newline at end of file + main() \ No newline at end of file diff --git a/prompt.txt b/prompt.txt new file mode 100644 index 0000000..11e72c8 --- /dev/null +++ b/prompt.txt @@ -0,0 +1,37 @@ +【重要平台约束】 +平台:WorldQuant WebSim +可用函数:ts_*(时间序列), group_*(横截面), 基础数学运算 +可用字段:open, high, low, close, volume, vwap, sector, industry, country, market_cap +禁用函数:pandas, numpy, 自定义Python函数,机器学习库 +输出格式:严格一行WebSim表达式,使用WQ平台函数 +表达式要求:必须能直接在WebSim中运行 + +我正在WorldQuant研究行业轮动策略,请设计行业选择因子: + +**策略背景**: +- 目标:在不同经济周期中选择强势行业 +- 数据:使用sector, industry分类字段 +- 频率:月度调仓 +- 风险:控制行业集中度 + +**需要5个行业因子**: +1. 行业动量因子(相对强度) +2. 行业估值修复因子(均值回归) +3. 行业资金流向因子(量价结合) +4. 行业波动率特征因子(风险调整) +5. 行业间相对强度因子(横截面) + +**具体要求**: +- 必须使用group函数处理行业分组 +- 每个因子包含清晰的行业轮动逻辑 +- 考虑行业特性的持久性 +- 提供经济周期适应的解释 + +**输出格式**(一行一个, 不要输出多余的东西): +[表达式] +[表达式] +[表达式] +... + +请提供具体的WQ表达式。 +重申:请确保所有表达式都使用WorldQuant WebSim平台函数,不要使用pandas、numpy或其他Python库函数。输出必须是一行有效的WQ表达式。 \ No newline at end of file diff --git a/siliconflow_detail.py b/siliconflow_detail.py new file mode 100644 index 0000000..49766ba --- /dev/null +++ b/siliconflow_detail.py @@ -0,0 +1,37 @@ +# -*- coding: utf-8 -*- +import json +import httpx + +with open('config.json', 'r') as f: + config = json.load(f) + siliconflow = config['siliconflow'] + token = siliconflow['api_keys'] + +headers = {"Authorization": f"Bearer {token}"} + +def get_user_info(): + # 获取用户信息 + url = "https://api.siliconflow.cn/v1/user/info" + + response = httpx.get(url, headers=headers) + + for key, value in response.json().items(): + if key != "data": + print(f"{key}: {value}") + else: + for sub_key, sub_value in value.items(): + print(f"{sub_key}: {sub_value}") + + +def get_models_info(): + url = "https://api.siliconflow.cn/v1/models" + + response = httpx.get(url, headers=headers) + + data = response.json()['data'] + + for d in data: + print(d) + +# get_models_info() +# get_user_info() \ No newline at end of file