LLM与规则书量化交易对决:实验复现、局限分析与增强应用
2026/8/20 6:53:37 网站建设 项目流程

1. 先搞清楚这个实验到底在测什么:是AI交易员不行,还是规则书太强?

看到这个标题,很多人第一反应可能是“AI在交易上输给了死规则”,然后直接跳到结论。但先别急,这个实验的核心价值不在于谁赢谁输,而在于它提供了一个非常具体的、可复现的对比场景:用100K美元的资金,让多个大语言模型(LLMs)与一套“冻结”的规则手册进行交易对决

“冻结的规则书”是关键。这意味着规则是固定的、没有学习能力的、完全基于预设条件执行的。而LLMs则具备根据市场信息进行推理和决策的潜力。实验结果显示规则书领先,这引出了一个更值得技术人深究的问题:在特定、受限的交易模拟环境中,当前LLMs的“推理”能力,是否真的能稳定超越一套精心设计的、但“愚蠢”的规则系统?

这个主题适合三类人看:一是对AI在金融量化领域应用前景感兴趣的研究者和开发者;二是想了解如何设计实验来客观评估AI模型在决策任务中表现的技术人员;三是那些认为“上AI就能赚钱”的乐观主义者,需要一点现实检验。

最值得关注的不是结论本身,而是实验的可复现性框架评估维度。它不是一个黑箱演示,而是一个可以拆解、可以重现、可以在此基础上改进的测试方案。我们接下来就围绕如何理解、复现和扩展这个实验的思路来展开。

2. 实验环境与核心设定:如何搭建一个公平的“擂台”

要理解结果,必须先还原擂台。虽然原始材料没有给出完整代码,但我们可以根据标题和常见实践,推断出搭建这样一个对比实验所需的核心组件。这不是一个简单的脚本,而是一个包含数据、引擎、参与者和评估标准的系统。

2.1 数据层:历史数据与市场模拟

所有交易决策都基于数据。一个严谨的实验需要:

  • 数据源:通常是某一段历史时间内的股票、加密货币或外汇的Tick级或分钟级行情数据(开盘价、最高价、最低价、收盘价、成交量)。数据需要包含训练/验证期和测试期。
  • 数据预处理:统一数据格式(如pandas DataFrame),处理缺失值,计算常用的技术指标(如移动平均线、RSI、布林带等),这些指标将作为模型和规则书的输入特征。
  • 模拟环境:需要一个回测引擎。这个引擎负责:
    • 按时间步推进数据。
    • 接收来自“交易员”(LLM或规则书)的指令(如:买入、卖出、持有、数量)。
    • 根据当前价格和手续费模型更新虚拟账户的资产(现金+持仓市值)。
    • 强制执行交易规则(如:禁止做空、T+1限制、保证金要求等)。

2.2 参与者层:LLM智能体 vs. 规则书智能体

这是对决的双方。

  • 规则书智能体:其逻辑是“冻结”的、确定性的。例如:

    # 伪代码示例:一个简单的双均线规则 def rulebook_decision(current_data): short_ma = current_data['close'].rolling(window=10).mean().iloc[-1] long_ma = current_data['close'].rolling(window=30).mean().iloc[-1] if short_ma > long_ma and not holding_position: return {'action': 'BUY', 'amount': 0.1} # 使用10%资金 elif short_ma < long_ma and holding_position: return {'action': 'SELL', 'amount': 'ALL'} else: return {'action': 'HOLD'}

    它的优势是稳定、透明、无随机性。劣势是无法适应规则未涵盖的新模式。

  • LLM智能体:其核心是将市场状态(如过去N根K线的价格、指标、账户信息)组织成自然语言或结构化提示(Prompt),交给LLM生成交易决策。

    # 伪代码示例:构建给LLM的Prompt def build_trading_prompt(market_context, portfolio_status): prompt = f""" 你是一个交易员,管理一个10万美元的账户。 当前账户现金:{portfolio_status['cash']:.2f} USD,持有资产:{portfolio_status['holding']},当前价值:{portfolio_status['holding_value']:.2f} USD。 最近市场数据: {market_context.to_string()} 请根据以上信息,决定下一步操作。只输出以下JSON格式之一: {{"action": "BUY", "amount_proportion": 0.1}} # 使用10%现金买入 {{"action": "SELL", "amount_proportion": 0.5}} # 卖出50%持仓 {{"action": "HOLD"}} """ return prompt

    然后调用LLM API(如OpenAI GPT-4, Anthropic Claude,或本地部署的Llama、Qwen等)获取响应,并解析JSON。它的潜力在于能理解复杂、非线性的关系,但劣势是输出不稳定、成本高、可能产生无法解析的响应。

2.3 评估层:不仅仅是最终收益

实验以10万美元起步,但最终排名不能只看终点金额。一个全面的评估应包括:

  • 最终净资产(Net Asset Value, NAV):最直接的指标。
  • 夏普比率(Sharpe Ratio):衡量收益与风险的平衡,单位风险下的超额回报。规则书往往因为交易逻辑稳定,夏普比率可能更高。
  • 最大回撤(Max Drawdown):账户从峰值到谷底的最大跌幅,反映策略的抗风险能力。LLM如果做出几次极端错误决策,回撤可能巨大。
  • 胜率(Win Rate)盈亏比(Profit Factor):盈利交易次数占比,以及总盈利与总亏损的比值。
  • 交易次数与频率:避免过度交易(产生大量手续费)或极少交易(无法体现决策能力)。
  • 指令执行成功率:对于LLM,还需要统计其输出格式正确、可被解析的比例。如果经常输出无效指令,其实际决策机会就少了。

3. 实操:一步步构建并运行你的对比实验

理解了框架后,我们可以设计一个最小可行实验。这里我建议使用Python,因为它有丰富的量化回测库(如backtrader,zipline,但为了透明度和自定义,我们这里用基础方法演示)和LLM调用库。

3.1 环境准备与依赖安装

首先,确保你的环境已经就绪。你需要一个Python环境(3.8+),并安装以下基础包:

pip install pandas numpy matplotlib openai # 基础数据处理与绘图,以及一个LLM API客户端 # 如果你使用其他LLM,如Anthropic Claude或本地模型,安装对应的SDK,如`anthropic`或`transformers`, `vllm`等。

对于规则书,我们只需要pandasnumpy。对于LLM,你需要准备相应的API密钥或本地模型权重。

3.2 准备历史数据与回测引擎

我们以简单的CSV格式历史价格数据为例。

import pandas as pd import numpy as np class BacktestEngine: def __init__(self, data_df, initial_capital=100000): self.data = data_df # DataFrame,包含`close`, `high`, `low`, `open`, `volume`等列 self.initial_capital = initial_capital self.current_step = 0 self.cash = initial_capital self.holding = 0 # 持有资产的数量 self.positions = [] # 记录所有交易 self.equity_curve = [] # 记录每日净资产 def get_state(self, lookback=30): """获取当前时间点及之前lookback期的市场状态""" end_idx = self.current_step start_idx = max(0, end_idx - lookback) return self.data.iloc[start_idx:end_idx].copy() def execute_order(self, action, amount_proportion, current_price): """执行交易指令""" if action == 'BUY' and self.cash > 0: amount_cash = self.cash * amount_proportion buy_quantity = amount_cash / current_price self.holding += buy_quantity self.cash -= amount_cash self.positions.append(('BUY', self.current_step, current_price, buy_quantity)) elif action == 'SELL' and self.holding > 0: sell_quantity = self.holding * amount_proportion self.holding -= sell_quantity self.cash += sell_quantity * current_price self.positions.append(('SELL', self.current_step, current_price, sell_quantity)) # HOLD 什么都不做 def step(self, decision_maker): """向前推进一个时间步,并让决策者做出动作""" if self.current_step >= len(self.data): return False # 回测结束 current_price = self.data.iloc[self.current_step]['close'] market_state = self.get_state() # 从决策者(规则书或LLM)获取决策 action, amount_proportion = decision_maker.make_decision(market_state, self.cash, self.holding) # 执行决策 if action in ['BUY', 'SELL']: self.execute_order(action, amount_proportion, current_price) # 计算当前净资产 current_equity = self.cash + self.holding * current_price self.equity_curve.append(current_equity) self.current_step += 1 return True

3.3 实现规则书决策器

class RulebookTrader: def __init__(self): self.name = "Rulebook_MA_Crossover" def make_decision(self, market_state, cash, holding): # 计算双均线 closes = market_state['close'].values if len(closes) < 30: return 'HOLD', 0.0 short_ma = closes[-10:].mean() # 10期均线 long_ma = closes[-30:].mean() # 30期均线 if short_ma > long_ma and holding == 0: return 'BUY', 0.1 # 金叉且空仓,用10%现金买入 elif short_ma < long_ma and holding > 0: return 'SELL', 1.0 # 死叉且持仓,卖出全部 else: return 'HOLD', 0.0

3.4 实现LLM决策器(以OpenAI API为例)

import openai import json class LLMTrader: def __init__(self, model="gpt-3.5-turbo", api_key="your_key"): openai.api_key = api_key self.model = model self.name = f"LLM_{model}" def make_decision(self, market_state, cash, holding): # 1. 构建Prompt prompt = self._build_prompt(market_state, cash, holding) # 2. 调用LLM try: response = openai.ChatCompletion.create( model=self.model, messages=[{"role": "user", "content": prompt}], temperature=0.1, # 低温度,使输出更确定 max_tokens=100 ) content = response.choices[0].message.content.strip() # 3. 解析响应 decision = self._parse_response(content) return decision except Exception as e: print(f"LLM调用失败: {e}") return 'HOLD', 0.0 # 失败时默认持有 def _build_prompt(self, market_state, cash, holding): # 简化市场状态为文本描述 recent_prices = market_state['close'].tail(5).tolist() prompt = f""" 你是一个专业的量化交易员。请基于以下信息做出交易决策。 账户状态: - 可用现金:{cash:.2f} USD - 持有资产数量:{holding:.4f} - 当前资产价格:{market_state['close'].iloc[-1]:.2f} USD 近期价格序列(最新在最后):{recent_prices} 请只输出一个JSON对象,包含`action`和`amount_proportion`两个字段。 `action`必须是`BUY`、`SELL`或`HOLD`。 `amount_proportion`是一个0到1之间的浮点数,代表使用现金比例(买入时)或卖出持仓比例(卖出时)。 例如:{{"action": "BUY", "amount_proportion": 0.05}} 现在,输出你的决策JSON: """ return prompt def _parse_response(self, content): # 尝试从响应中提取JSON try: # 处理可能出现的代码块标记 if '```json' in content: content = content.split('```json')[1].split('```')[0] elif '```' in content: content = content.split('```')[1] decision = json.loads(content) action = decision.get('action', 'HOLD').upper() amount = decision.get('amount_proportion', 0.0) if action not in ['BUY', 'SELL', 'HOLD']: action = 'HOLD' amount = max(0.0, min(1.0, float(amount))) # 限制在0-1之间 return action, amount except json.JSONDecodeError: print(f"无法解析LLM响应: {content}") return 'HOLD', 0.0

3.5 运行对决与结果分析

def run_backtest(engine, trader): """运行单个交易者的回测""" while engine.step(trader): pass equity_curve = pd.Series(engine.equity_curve, index=engine.data.index[:len(engine.equity_curve)]) return equity_curve, engine.positions # 1. 加载数据 data = pd.read_csv('market_data.csv', parse_dates=['date'], index_col='date') # 2. 划分测试集(为了公平,规则书和LLM都使用同一段未见过的数据) test_data = data.iloc[-1000:] # 最后1000个数据点 # 3. 初始化引擎和交易员 engine_rule = BacktestEngine(test_data.copy()) engine_llm = BacktestEngine(test_data.copy()) rule_trader = RulebookTrader() llm_trader = LLMTrader(model="gpt-3.5-turbo") # 4. 运行回测 print("Running Rulebook...") equity_rule, trades_rule = run_backtest(engine_rule, rule_trader) print(f"Rulebook Final Equity: ${equity_rule.iloc[-1]:.2f}") print("Running LLM...") equity_llm, trades_llm = run_backtest(engine_llm, llm_trader) print(f"LLM Final Equity: ${equity_llm.iloc[-1]:.2f}") # 5. 绘制资金曲线对比 import matplotlib.pyplot as plt plt.figure(figsize=(12,6)) plt.plot(equity_rule.index, equity_rule.values, label=f'Rulebook ({rule_trader.name})') plt.plot(equity_llm.index, equity_llm.values, label=f'LLM ({llm_trader.name})') plt.axhline(y=100000, color='gray', linestyle='--', label='Initial Capital') plt.legend() plt.title('Equity Curve Comparison') plt.xlabel('Date') plt.ylabel('Portfolio Value (USD)') plt.grid(True) plt.show() # 6. 计算关键指标 def calculate_metrics(equity_curve): returns = equity_curve.pct_change().dropna() total_return = (equity_curve.iloc[-1] / equity_curve.iloc[0]) - 1 sharpe_ratio = np.sqrt(252) * returns.mean() / returns.std() if returns.std() > 0 else 0 max_drawdown = (equity_curve / equity_curve.expanding().max() - 1).min() return total_return, sharpe_ratio, max_drawdown metrics_rule = calculate_metrics(equity_rule) metrics_llm = calculate_metrics(equity_llm) print(f"\nRulebook - Total Return: {metrics_rule[0]:.2%}, Sharpe: {metrics_rule[1]:.2f}, MaxDD: {metrics_rule[2]:.2%}") print(f"LLM - Total Return: {metrics_llm[0]:.2%}, Sharpe: {metrics_llm[1]:.2f}, MaxDD: {metrics_llm[2]:.2%}")

运行这个流程,你就能在自己的环境下复现“LLM vs. Rulebook”的对决。我强烈建议先用模拟数据或一小段真实数据跑通整个流程,再扩展到更长时间和更多LLM模型上。

4. 为什么规则书常常领先?拆解LLM作为交易员的局限性

跑完实验,你很可能也会看到规则书领先。这不是偶然,而是由当前LLM在特定任务中的固有局限性决定的。理解这些,比单纯看输赢更重要。

4.1 决策的稳定性与一致性

规则书的优势在于绝对稳定。同样的市场条件输入,必然产生同样的输出。这使得它的回测结果具有高度可重复性,夏普比率等风险调整后收益指标往往更“好看”。

而LLM,即使将temperature参数设为0,其输出仍可能存在微妙的波动。更重要的是,LLM的决策严重依赖于提示词工程(Prompt Engineering)。提示词中描述任务的措辞、举例的顺序、输出格式的要求,都会极大影响最终决策。一个微小的提示词改动,可能导致从“激进”变为“保守”,从而产生完全不同的资金曲线。这种不稳定性在金融这种对错误零容忍的领域是致命的。

4.2 对数值与序列推理的固有弱点

LLM擅长处理语言和概念,但对精确的数值计算、时间序列的微观模式识别(如价格序列中的短期动量或反转),其能力远不如传统的统计模型或经过专门训练的时序预测网络(如LSTM、Transformer)。

当Prompt中给出“过去5天价格:[100, 102, 101, 103, 105]”时,LLM能理解“在上涨”,但它很难精确量化上涨的斜率、波动率,或者识别出这是一个“突破前高”的技术形态。它更多是基于文本模式进行联想式回答,而非进行严格的量化分析。规则书则直接通过代码(if short_ma > long_ma)执行精确的逻辑判断。

4.3 成本、延迟与实时性

在实盘交易中,速度就是生命。调用云端LLM API(如GPT-4)存在网络延迟,单次响应时间可能在几百毫秒到几秒,这对于高频或短线策略是不可接受的。即使使用本地部署的小模型,推理速度也比执行一行if-else规则慢几个数量级。此外,API调用成本高昂,频繁决策会导致费用激增。

4.4 幻觉与指令遵循风险

LLM存在“幻觉”,可能生成不符合事实或逻辑的回复。在交易场景中,这可能表现为:凭空捏造不存在的技术指标信号、对账户资金进行计算错误、或者输出无法被解析的指令格式。虽然可以通过后置解析和错误处理来缓解(如我们代码中的try-except),但每一次失败都意味着一次错过交易机会或默认持有,长期累积会影响绩效。

4.5 缺乏风险管理的“常识”

一套成熟的规则书通常会内置严格的风险管理模块,比如单笔交易最大亏损、每日最大亏损、仓位控制等。让LLM通过自然语言理解并执行这些复杂、多层次的约束非常困难。你需要在Prompt里用大量篇幅描述风控规则,而LLM仍可能在某些情况下“忘记”或“绕过”它们。规则书的风控是硬编码的,绝对执行。

5. LLM在量化交易中的正确打开方式:不是替代,而是增强

既然直接让LLM做交易员有这么多问题,那是不是就没用了?恰恰相反。这个实验的价值在于帮我们划清了边界:不要用LLM的短板去硬刚规则书的强项。LLM的真正潜力在于辅助和增强,而非替代。

5.1 应用场景一:策略研究与创意生成

这是LLM最擅长的领域。你可以让LLM扮演一个资深交易员或量化研究员,进行“头脑风暴”。

  • Prompt示例:“基于动量效应和均值回归理论,为一个加密货币日内交易策略列出5个具体的、可量化的入场规则想法。”
  • 作用:快速生成大量策略逻辑雏形,打破研究人员的思维定式。这些由LLM生成的“自然语言规则”,可以由人工翻译成具体的代码,再由规则书来回测验证。这极大地拓宽了策略研究的搜索空间。

5.2 应用场景二:新闻、舆情与事件分析

LLM在理解文本、总结情感、提取关键信息方面能力突出。

  • 工作流
    1. 爬取或订阅财经新闻、社交媒体舆情、公司公告。
    2. 使用LLM对每篇文章/帖子进行总结、情感分析(正面/负面/中性)、提取影响到的具体资产(如公司股票代码)和事件类型(如财报、并购、监管)。
    3. 将LLM的结构化输出(例如:{“asset”: “AAPL”, “sentiment”: “negative”, “intensity”: “high”, “event”: “earnings_miss”})作为一个因子,输入到传统的量化模型或多因子规则书中。
    4. 规则书根据这个“舆情因子”的强度,调整其原有的交易逻辑(例如,在负面情绪强烈时,降低仓位或增加止损幅度)。

这样,LLM负责处理非结构化的文本信息,规则书负责执行结构化的交易逻辑,两者优势互补。

5.3 应用场景三:策略代码的生成与解释

对于不精通编程的领域专家,可以用自然语言描述策略逻辑,让LLM(特别是代码能力强的模型)生成初步的Python回测代码框架。然后由开发者进行审查、调试和优化。反过来,也可以将复杂的策略代码丢给LLM,让它生成人类可读的解释文档,便于团队协作和策略传承。

5.4 应用场景四:自适应参数调整

一个规则书策略通常有若干参数(如均线的周期、RSI的超买超卖阈值)。我们可以让LLM来扮演“参数优化师”的角色。

  • 流程:在回测框架外,构建一个外层循环。将历史数据分为多个阶段。在每个阶段结束时,将策略表现、市场特征(波动率、趋势强度)总结成文本报告,交给LLM分析。Prompt可以是:“过去三个月,在波动率加大的市场环境下,双均线策略(短周期=10,长周期=30)出现了较大回撤。请分析可能的原因,并建议一组新的参数(短周期,长周期),以适应高波动环境。只输出两个数字。”
  • 注意:这需要非常谨慎,严防过拟合。LLM的建议必须在一个全新的、未参与交互的测试集上进行最终验证。

6. 实验扩展与深度思考:超越简单的对决

最初的实验设计是一个起点。如果你想获得更深刻的洞察,可以考虑从以下几个方向扩展:

6.1 引入更多元化的“规则书”

不要只用一个简单的双均线规则。可以引入一篮子经典策略进行对比:

  • 动量策略:买入过去N天涨幅最大的资产。
  • 反转策略:买入过去N天跌幅最大的资产。
  • 海龟交易法则:经典的趋势跟踪系统。
  • 静态资产配置:简单的60/40股债平衡。 这样,LLM的对手就从“一个简单的规则”变成了“一群经典的规则”,比较的基线更坚实。

6.2 为LLM提供更丰富、更结构化的上下文

原始的Prompt只给了价格序列。可以尝试为LLM提供更多信息:

  • 技术指标:将计算好的RSI、MACD、布林带宽度等数值直接以表格或JSON格式提供给LLM。
  • 市场状态标签:用规则预先判断当前市场是“趋势市”还是“震荡市”,并告诉LLM。
  • 宏观经济指标:利率、通胀数据等。
  • 账户风险状态:当前回撤、连续亏损次数等。 测试LLM在信息更充分的情况下,决策质量是否有提升。

6.3 测试不同的LLM与提示词工程

对比不同规模和家族的LLM:

  • 大型闭源模型:GPT-4, Claude 3。
  • 中小型开源模型:Llama 3, Qwen, DeepSeek。
  • 经过金融文本微调的模型:一些开源社区训练的FinGPT类模型。 同时,系统性地测试不同风格的Prompt:
  • 指令型:“你是一个保守的价值投资者...”
  • 示例型(Few-shot): 在Prompt中给出几个市场状态和正确决策的例子。
  • 思维链型(Chain-of-Thought): “请逐步推理:首先分析市场趋势,然后评估当前风险,最后做出决策...”

6.4 将评估周期拉长,观察适应性

“冻结的规则书”在一种市场环境下(如强趋势市)可能表现优异,但在另一种环境(如震荡市)可能持续亏损。一个有趣的问题是:LLM能否凭借其语言理解能力,识别出市场“范式”的转变,并相应地调整其决策风格?要测试这一点,需要足够长的回测周期,涵盖多种市场 regime(趋势、震荡、牛市、熊市)。观察LLM的资金曲线是否比规则书更平滑,适应性更强。

6.5 考虑集成学习:LLM作为“元决策者”

不直接让LLM输出买卖信号,而是让它来管理一篮子规则书策略

  • 思路:同时运行多个不同参数的规则书策略。在每个时间点,LLM的任务是分析当前市场状况和各个策略的近期表现,然后输出一个权重分配方案,将资金动态分配给不同的规则书策略。
  • Prompt示例:“现有三个策略:趋势跟踪策略A、均值回归策略B、波动率策略C。过去一周市场波动率上升,趋势不明显。请给出一个资金分配权重(三者之和为1),并简述理由。” 这种方式降低了LLM直接做微观价格预测的负担,转而利用其宏观分析能力进行资产配置,可能是一个更可行的落地路径。

这个实验的真正启示在于,它像一面镜子,清晰地照出了当前LLM在严肃金融决策中的长处和短板。对于开发者而言,最有价值的方向不是继续在“直接交易”这条窄路上硬闯,而是思考如何将LLM的“智能”与传统量化系统的“精准”和“稳定”深度融合,构建下一代更加强大、也更具适应性的量化工具。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询