第25章 迷你实战:从零搭建双均线策略Agent系统
本章顾问:龙马(技术落地)、沈飞(策略逻辑)
预估时长:4小时
本章前置检查:
- □ 已完成第24章的数据治理体系,能获取并清洗Tushare数据
- □ 熟悉OpenClaw和Hermes的基础配置(第1-12章)
- □ 理解双Agent协作的基本模式(第15章)
本章难点提示:
- 25.2节的回测函数虽然简单,但包含了未来函数检查、滑点模拟等关键细节,不要跳过。
- 25.3节的Agent配置是本章核心,建议按顺序逐个配置并测试,不要一次性全部部署。
- 25.4节的观察阶段至少运行一周模拟盘,不要急于实盘。
🎯 本章教学目标:从零搭建一个完整的双均线策略Agent系统,涵盖数据获取、信号生成、模拟交易、风控监控全流程,理解量化策略Agent化的核心模式,并为后续多因子策略扩展打下基础。
![图片[1]-从零跑通量化回测:双均线策略开发+绩效评估+调优全流程](http://www.ifisme.cn/wp-content/uploads/2026/05/教材2501.png)
25.1 策略简介:双均线金叉死叉
🎯 本节目标:理解双均线策略的逻辑、参数选择及其在量化交易中的地位。
预计时长:0.5小时
25.1.1 策略逻辑
双均线策略是最经典、最简单的趋势跟踪策略之一。它通过两条不同周期的移动平均线来判断趋势方向:
- 金叉(买入信号):短期均线从下方上穿长期均线,表示上升趋势开始
- 死叉(卖出信号):短期均线从上方下穿长期均线,表示下降趋势开始
核心代码逻辑:
python
def generate_signals(df, short_window=5, long_window=20):
df['short_ma'] = df['close'].rolling(window=short_window).mean()
df['long_ma'] = df['close'].rolling(window=long_window).mean()
df['signal'] = 0
df.loc[df['short_ma'] > df['long_ma'], 'signal'] = 1 # 持仓
df.loc[df['short_ma'] <= df['long_ma'], 'signal'] = 0 # 空仓
df['position'] = df['signal'].diff() # 仓位变化:+1买入,-1卖出
return df
沈飞注:双均线策略虽然简单,但它体现了趋势跟踪的核心思想——截断亏损,让利润奔跑。即使专业量化机构,也会用类似方法作为基础过滤器。不要因为它简单就轻视,实盘中它能避开震荡市的大部分亏损。
25.1.2 参数选择与敏感性
| 参数组合 | 适用场景 | 优缺点 |
|---|---|---|
| (5, 20) | 中短期交易 | 敏感,信号多,易震荡 |
| (10, 30) | 中期趋势 | 平衡 |
| (20, 60) | 中长期 | 滞后,信号少,但更稳定 |
龙马注:参数优化的陷阱在于“过度拟合”。本章先用固定参数(5,20),后续扩展中再讨论参数优化和过拟合防范。
🛠️ 实践任务(本节):在纸上画出金叉和死叉的示意图,标出买卖点。
💭 本节总结(不看书写3行):
1.
2.
3.
📊 用时记录:计划____min → 实际____min → 偏差原因:________
25.2 数据获取与回测准备
🎯 本节目标:使用Tushare获取历史数据,编写轻量级回测函数,验证策略有效性。
预计时长:1小时
25.2.1 数据获取(复用第24章清洗流程)
python
import tushare as ts
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
# 初始化Tushare
pro = ts.pro_api('你的token') # 请替换为实际token
# 获取贵州茅台历史日线数据(后复权)
df = pro.daily(ts_code='600519.SH', start_date='20200101', end_date='20231231')
df['trade_date'] = pd.to_datetime(df['trade_date'])
df = df.sort_values('trade_date')
# 计算后复权收盘价(复权因子已在Tushare返回中)
df['adj_close'] = df['close'] * df['adj_factor']
print(df.head())
25.2.2 轻量级回测函数(不使用复杂框架)
python
def backtest_dma(df, short=5, long=20, slippage=0.001, commission=0.0003):
"""
双均线策略回测
slippage: 滑点(单边0.1%)
commission: 手续费(双边0.03%)
"""
df = df.copy()
# 生成信号
df['short_ma'] = df['adj_close'].rolling(window=short).mean()
df['long_ma'] = df['adj_close'].rolling(window=long).mean()
df['signal'] = 0
df.loc[df['short_ma'] > df['long_ma'], 'signal'] = 1
df.loc[df['short_ma'] <= df['long_ma'], 'signal'] = 0
df['position'] = df['signal'].diff()
# 模拟交易
df['entry_price'] = df['adj_close']
df['trade_cost'] = 0.0
# 买入时支付滑点+佣金
buy_mask = df['position'] == 1
df.loc[buy_mask, 'trade_cost'] = df['entry_price'] * (slippage + commission)
# 卖出时支付滑点+佣金
sell_mask = df['position'] == -1
df.loc[sell_mask, 'trade_cost'] = df['entry_price'] * (slippage + commission)
# 计算每日收益
df['returns'] = df['adj_close'].pct_change() * df['signal'].shift(1)
df['net_returns'] = df['returns'] - df['trade_cost'] / df['entry_price']
df['cum_returns'] = (1 + df['net_returns']).cumprod()
# 绩效指标
total_return = df['cum_returns'].iloc[-1] - 1
annual_return = (1 + total_return) ** (252 / len(df)) - 1
sharpe = df['net_returns'].mean() / df['net_returns'].std() * np.sqrt(252)
max_drawdown = (df['cum_returns'] / df['cum_returns'].cummax() - 1).min()
print(f"总收益率: {total_return:.2%}")
print(f"年化收益率: {annual_return:.2%}")
print(f"夏普比率: {sharpe:.2f}")
print(f"最大回撤: {max_drawdown:.2%}")
return df
25.2.3 运行回测并可视化
python
result = backtest_dma(df, short=5, long=20)
# 绘制净值曲线
plt.figure(figsize=(12, 6))
plt.plot(result['trade_date'], result['cum_returns'], label='策略净值')
plt.plot(result['trade_date'], result['adj_close'] / result['adj_close'].iloc[0], label='买入持有')
plt.legend()
plt.title('双均线策略回测 (贵州茅台, 2020-2023)')
plt.show()
龙马注:回测函数中的滑点和手续费设置非常重要。很多新手忽略这些成本,导致回测看起来很美,实盘却亏损。本章设为单边0.1%滑点+双边0.03%佣金,是比较现实的估计。
🛠️ 实践任务(本节):
- 获取至少两只股票的历史数据(如茅台+五粮液),分别运行回测。
- 调整均线参数,观察绩效变化,记录最优参数。
💭 本节总结(不看书写3行):
1.
2.
3.
📊 用时记录:计划____min → 实际____min → 偏差原因:________
25.3 Agent配置:一个迷你团队
🎯 本节目标:将回测逻辑拆解为四个Agent,搭建可扩展的量化Agent团队。
预计时长:1.5小时
25.3.1 团队结构回顾
第23.5节我们定义了一人量化公司的核心Agent团队(6个Agent)。本章我们实现其中三个核心Agent的简化版:
| Agent | 类型 | 职责 | 本章实现内容 |
|---|---|---|---|
| 数据Agent | OpenClaw | 定时拉取最新行情 | Cron任务 + 数据清洗 |
| 策略Agent | Hermes | 计算均线信号,记录策略逻辑 | Skill + ACP委托 |
| 交易执行Agent | OpenClaw | 模拟下单 | 审批流程 + 模拟盘 |
| 风控Agent | Hermes(独立) | 监控回撤,触发暂停 | 独立ACP服务 + 共享记忆 |
25.3.2 数据Agent配置(OpenClaw Cron)
创建Cron任务,每天收盘后自动拉取最新数据:
bash
openclaw cron add --name "fetch_daily_data" \ --cron "30 15 * * 1-5" --tz Asia/Shanghai \ --message "从Tushare获取沪深300成分股最新日线数据,清洗后存入Parquet文件" \ --session isolated
对应的Skill或脚本(fetch_and_clean.py)应实现:调用Tushare API,执行第24章的清洗流程,保存到data/daily/目录。
25.3.3 策略Agent配置(Hermes Skill)
创建Hermes Skill用于生成交易信号。
目录:~/.hermes/skills/dma_strategy/
SKILL.md:
markdown
---
name: dma_strategy
description: 双均线策略信号生成器,根据最新数据计算金叉/死叉信号
---
## 触发器
- 用户请求“计算最新信号”
- 数据Agent更新后自动触发(通过ACP)
## 执行步骤
1. 读取最新清洗后的数据文件(Parquet)
2. 计算5日均线和20日均线
3. 判断是否金叉(短期上穿长期)或死叉(短期下穿长期)
4. 输出信号:买入/卖出/持有
5. 将信号和理由写入共享记忆(Redis)
## 输出格式
{
"signal": "BUY/SELL/HOLD",
"reason": "5日均线(价格)上穿20日均线(价格),形成金叉",
"timestamp": "2025-01-01"
}
手动测试Skill:
bash
hermes -c "使用dma_strategy技能,基于今天的日线数据生成信号"
25.3.4 交易执行Agent配置(OpenClaw + 审批)
模拟下单需要审批,避免实盘风险。
AGENTS.md(在OpenClaw中创建trade_executor Agent):
markdown
--- name: trade_executor role: 交易执行员 type: default --- ## 职责 - 接收策略Agent的信号 - 模拟下单(输出日志),实盘需审批 - 记录成交记录 ## 工作流 1. 从共享记忆读取最新信号 2. 如果是BUY/SELL,生成模拟订单 3. 调用审批工具,等待确认 4. 确认后记录到交易日志 5. 更新持仓状态 ## 约束 - 单笔交易金额不超过10%(模拟) - 每日总交易次数不超过3次
审批配置(openclaw.json):
json
{
"agents": {
"list": [{
"id": "trade_executor",
"tools": {
"requireApproval": ["execute_trade"]
}
}]
}
}
25.3.5 风控Agent配置(独立Hermes)
风控Agent必须独立运行,不与交易Agent共享记忆。它监控回撤,超限时触发暂停。
SKILL.md:
markdown
---
name: risk_monitor
description: 监控账户回撤,当超过阈值时发出告警并建议暂停
---
## 触发器
- 每5分钟运行一次(Cron)
- 交易后触发
## 执行步骤
1. 读取账户净值曲线(从共享记忆的只读区域)
2. 计算当前回撤(当前净值 / 历史最高净值 - 1)
3. 如果回撤 < -5%,发出告警
4. 如果回撤 < -8%,建议暂停所有交易
5. 将告警写入共享记忆的告警队列
## 输出
{
"drawdown": -0.06,
"alert_level": "warning",
"action": "reduce_position"
}
Cron任务:
bash
hermes cron add --name "risk_check" --every "5m" \ --message "执行风控检查,读取共享记忆中的净值,判断回撤是否超限"
25.3.6 协作流程总览(注:由于图表形式在本网页上显示错位,本节用纯文本和表格描述四个Agent之间的协作关系。)
协作流程步骤说明:
- 数据采集
数据Agent(OpenClaw Cron)在每日收盘后自动运行,从Tushare获取最新日线数据,执行清洗(复权、去极值、填充缺失),然后将处理后的数据写入共享记忆(Redis或共享文件)。写入的键名例如daily_data:600519。 - 信号生成
策略Agent(Hermes Skill)被Cron定时触发或由数据Agent通过ACP唤醒。它从共享记忆读取最新的日线数据,计算5日与20日均线,判断金叉或死叉。将生成的信号(BUY、SELL或HOLD)以及简要理由写入共享记忆,键名例如signal:latest。 - 交易执行
交易Agent(OpenClaw)监听共享记忆中signal:latest的变化。一旦发现有新信号且为BUY或SELL,它根据信号方向和最新价格生成模拟订单。随后交易Agent调用审批工具,通过飞书发送审批请求(例如:“是否执行买入茅台100股?”)。你审批通过后,交易Agent将订单记录写入共享记忆(orders键),并更新持仓和净值曲线(equity_curve键)。 - 风控监控
风控Agent(独立Hermes)每5分钟由Cron唤醒一次。它从共享记忆读取最近一段时间的净值曲线,计算当前回撤(最高净值到当前净值的跌幅)。如果回撤超过-5%,风控Agent写入一条警告信息到共享记忆的alerts键,并发送飞书告警。如果回撤超过-8%,则额外发送“暂停交易”指令给交易Agent(通过ACP或直接修改共享记忆中的pause_trading标志)。
数据流向与依赖关系表:
| 步骤 | 发起者 | 所需读取的共享数据 | 写入的共享数据 | 触发/通知对象 |
|---|---|---|---|---|
| 1 | 数据Agent | 无(直接从Tushare获取) | daily_data:<股票代码> | 策略Agent(间接,通过Cron或ACP) |
| 2 | 策略Agent | daily_data:<股票代码> | signal:latest,signal_history | 交易Agent(通过共享记忆监听) |
| 3 | 交易Agent | signal:latest,账户信息 | orders,equity_curve,positions | 风控Agent(通过净值更新间接触发) |
| 4 | 风控Agent | equity_curve,风控阈值 | alerts,pause_trading | 交易Agent(读取暂停标志) |
文字时序描述(模拟一次完整循环):
- 15:30 数据Agent运行 → 写入
daily_data:600519。 - 15:35 策略Agent运行 → 读取
daily_data:600519→ 计算得出BUY信号 → 写入signal:latest。 - 15:36 交易Agent监听到新信号 → 读取
signal:latest→ 生成模拟订单 → 飞书发送审批请求 → 你点击“批准” → 交易Agent写入orders和equity_curve。 - 15:40 风控Agent运行 → 读取
equity_curve→ 计算回撤为-3%(未超限)→ 无操作。 - (次日)如果市场下跌导致回撤达到-6%,风控Agent会写入
alerts并发送告警;若达到-9%,则写入pause_trading: true,交易Agent将拒绝后续信号直至你手动解除。
龙马注:这个迷你团队已经具备了量化系统的最小闭环。你可以先手动触发各个环节验证,然后再设置Cron自动化。建议先单独测试策略Agent是否正确生成信号,再集成交易Agent。
🛠️ 实践任务(本节):
- 按照上述配置,创建数据Agent的Cron任务并手动运行一次
- 创建策略Agent Skill并测试信号生成
- 配置交易Agent的审批流程,模拟一次买入信号
💭 本节总结(不看书写3行):
1.
2.
3.
📊 用时记录:计划____min → 实际____min → 偏差原因:________
25.4 运行与观察
🎯 本节目标:运行系统一周模拟盘,记录结果,分析Agent协作表现。
预计时长:0.5小时
25.4.1 启动系统
- 启动OpenClaw Gateway:
openclaw gateway start - 启动Hermes Gateway(可选,用于渠道推送):
hermes gateway start - 确保Cron任务已启用:
openclaw cron list
25.4.2 模拟盘运行一周
- 每天收盘后数据Agent自动拉取数据
- 策略Agent生成信号(可通过飞书/Telegram接收推送)
- 交易Agent根据信号模拟下单,需你审批
- 风控Agent每5分钟检查回撤
观察要点:
- 数据是否准时更新
- 信号是否合理(对比手动计算)
- 审批流程是否流畅
- 风控告警是否及时
25.4.3 记录日志与复盘
建议在飞书群中配置一个专用频道,接收所有Agent的日志推送。例如:
bash
openclaw cron add --name "daily_summary" --cron "0 16 * * 1-5" \ --message "汇总今日信号、交易、风控状态" \ --deliver feishu:oc_群ID
沈飞注:模拟盘至少运行一个月,经历至少一次完整的买卖周期。不要因为一周没信号就急躁。双均线策略在震荡市可能长期无信号,这正是它的风控价值。
🛠️ 实践任务(本节):
- 配置飞书群接收Agent日志
- 运行模拟盘至少一周,截图关键日志
- 记录遇到的任何异常(如数据丢失、信号延迟)及解决方案
💭 本节总结(不看书写3行):
1.
2.
3.
📊 用时记录:计划____min → 实际____min → 偏差原因:________
25.5 扩展讨论:如何将双均线升级为多因子模型
🎯 本节目标:理解从双均线到多因子策略的扩展路径,为第27章做铺垫。
预计时长:0.3小时
扩展方向
| 扩展维度 | 双均线 | 多因子模型 | 所需新增Agent |
|---|---|---|---|
| 信号来源 | 单一均线 | 多个因子(动量、价值、质量等) | 因子挖掘Agent |
| 信号合成 | 简单金叉死叉 | 加权打分、机器学习 | 因子合成Agent |
| 风险控制 | 简单回撤监控 | 因子暴露控制、行业中性 | 风险模型Agent |
| 资产配置 | 单一资产 | 多资产组合优化 | 资产配置Agent |
代码扩展示例
python
# 多因子打分框架(伪代码)
def multi_factor_score(df, factors):
"""
factors: 字典,键为因子名称,值为因子值Series
"""
scores = pd.DataFrame()
for name, factor in factors.items():
# 因子标准化(Z-score)
scores[name] = (factor - factor.mean()) / factor.std()
# 等权合成
total_score = scores.mean(axis=1)
# 选择得分最高的10%股票买入
return total_score
龙马注:双均线是单因子,多因子就是多个单因子的组合。你当前的数据Agent、策略Agent、交易Agent、风控Agent架构完全兼容多因子——只需将策略Agent改为调用多个因子Skill并合成信号即可。
🛠️ 实践任务(本节):在双均线策略代码基础上,尝试增加一个波动率因子(如ATR),当波动率过高时降低仓位。
💭 本节总结(不看书写3行):
1.
2.
3.
📊 用时记录:计划____min → 实际____min → 偏差原因:________
25.6 🚨 常见误解:双均线策略简单 = 没有价值
🎯 本节目标:纠正对简单策略的偏见,理解其在实盘中的价值。
预计时长:0.2小时
误解
“双均线是人尽皆知的简单策略,用它肯定赚不到钱。”
真相
- 趋势跟踪的有效性:双均线捕捉大趋势,在牛熊市中都能获利。
- 过滤器作用:即使不作为主策略,也可作为其他策略的“开关”(只在均线多头时开仓)。
- 稳健性:参数不敏感,不易过拟合。
- 实盘案例:许多CTA策略的核心就是双均线或其变种。
沈飞注:我在实盘中见过用双均线跑商品期货的团队,年化收益20%+,最大回撤10%以内。简单不等于无效,复杂不等于有效。关键是纪律执行——双均线在震荡市会连续亏损,但很少有人能坚持下来。
🛠️ 实践任务(本节):思考你所在的领域,有哪些“简单但有效”的规则值得Agent化?
💭 本节总结(不看书写3行):
1.
2.
3.
📊 用时记录:计划____min → 实际____min → 偏差原因:________
第25章 参考资料与扩展阅读
- Tushare Pro日线行情接口 https://tushare.pro/document/2?doc_id=27
- 双均线策略原理与实现(聚宽社区) https://www.joinquant.com/view/community/detail/xxxx
- 滑点与手续费对回测的影响 https://www.quantstart.com/articles/Slippage-and-Commission-in-Backtesting
- OpenClaw Cron任务配置 https://docs.openclaw.ai/zh-CN/automation/cron-jobs
- Hermes Skill开发最佳实践 https://hermes-agent.nousresearch.com/docs/skills/best-practices
第五篇综合任务(第25章完成后)
任务:完成以下所有检查项。
- 成功获取并清洗至少一只股票的历史日线数据
- 运行双均线回测,输出绩效指标,并保存净值曲线图
- 配置数据Agent的Cron任务,手动触发一次成功
- 创建策略Agent Skill,测试信号生成
- 配置交易Agent审批流程,模拟一次下单
- (可选)运行模拟盘一周,记录日志
完成后,保存回测脚本和Agent配置文件,命名为chapter25_dual_ma_agents.zip。
顾问审校意见
沈飞:
“第25章的双均线策略虽然简单,但麻雀虽小五脏俱全——它完整演示了量化系统的四个核心Agent:数据、策略、交易、风控。这对于初学者建立系统思维非常有帮助。
需要提醒的是:双均线在震荡市会连续亏损,这是策略本身的特点,不是Bug。实盘中很多人因为无法忍受连续的小亏损而放弃,这恰恰是最大的错误。因此,本章特别强调‘模拟盘至少运行一个月’——让读者亲身体验震荡期的煎熬,比任何说教都有效。”
龙马:
“本章的Agent配置已经可以跑通。我补充两个工程细节:
共享记忆推荐使用Redis,可以设置自动过期(如信号保留7天)。配置简单,适合个人量化。
策略Agent的SKILL.md中,读取数据时建议使用绝对路径,避免相对路径在不同上下文中出错。或者通过环境变量配置数据目录。
另外,建议读者在回测函数中加入 future_check,确保没有用到未来数据。虽然Tushare的数据本身是安全的,但自己写代码处理时容易出错。”下一章预告:第26章 量化投资公司的Agent化映射:从岗位到Agent —— 我们将系统化地将第23章的真实岗位映射为Agent角色,给出完整的映射表和协作设计,为第27章的Skill开发打下基础。























暂无评论内容