问题描述
帮我写一个双均线金叉买入,死叉卖出的策略。
解决方案
这是一个经典的趋势跟踪策略。策略逻辑如下:
- 核心逻辑:
- 金叉(买入信号):当短期均线(如5日均线)由下向上穿过长期均线(如20日均线)时,视为上涨趋势确立,全仓买入。
- 死叉(卖出信号):当短期均线由上向下穿过长期均线时,视为下跌趋势确立,清仓卖出。
- 标的:以平安银行(000001.XSHE)为例。
- 频率:按日回测。
以下是基于聚宽(JoinQuant)API 实现的完整策略代码:
# -*- coding: utf-8 -*-
# 导入聚宽函数库
import jqdata
def initialize(context):
"""
初始化函数,设定基准、股票池、参数等
"""
# 设定沪深300作为基准
set_benchmark('000300.XSHG')
# 开启动态复权模式(真实价格)
set_option('use_real_price', True)
# 过滤掉order系列API产生的比error级别低的log
log.set_level('order', 'error')
# 设定要操作的股票:平安银行
g.security = '000001.XSHE'
# 设定均线窗口
g.short_window = 5 # 短期均线窗口
g.long_window = 20 # 长期均线窗口
# 设定交易费率:买入万分之三,卖出万分之三加千分之一印花税,最低5元
set_order_cost(OrderCost(close_tax=0.001, open_commission=0.0003, close_commission=0.0003, min_commission=5), type='stock')
# 每天开盘时运行策略
run_daily(trade_func, time='9:30')
def trade_func(context):
"""
交易逻辑函数
"""
security = g.security
# 获取过去 g.long_window 天的收盘价数据
# 注意:为了计算长期均线,我们需要获取足够长的数据
# include_now=True 表示包含当前bar的数据(回测中如果是日频,开盘时取不到当日收盘价,通常取前一日数据计算信号)
# 这里我们使用 attribute_history 获取过去的数据(不包含今天,避免未来函数)
hist_data = attribute_history(security, g.long_window, '1d', ['close'])
# 如果数据长度不足(例如刚上市的股票),则跳过
if len(hist_data) < g.long_window:
return
# 计算短期均线 (MA5)
# 取最后 short_window 天的数据求平均
ma_short = hist_data['close'][-g.short_window:].mean()
# 计算长期均线 (MA20)
# 取所有 long_window 天的数据求平均
ma_long = hist_data['close'].mean()
# 获取当前持仓数量
current_position = context.portfolio.positions[security].total_amount
# 获取当前可用资金
available_cash = context.portfolio.available_cash
# 交易信号判断
# 1. 金叉买入:短期均线 > 长期均线 且 当前无持仓
if ma_short > ma_long and current_position == 0:
# 全仓买入
order_value(security, available_cash)
log.info("金叉出现 (MA5:%.2f > MA20:%.2f),买入 %s" % (ma_short, ma_long, security))
# 2. 死叉卖出:短期均线 < 长期均线 且 当前有持仓
elif ma_short < ma_long and current_position > 0:
# 清仓卖出
order_target(security, 0)
log.info("死叉出现 (MA5:%.2f < MA20:%.2f),卖出 %s" % (ma_short, ma_long, security))
# 记录均线值,方便在回测图表中查看
record(MA_Short=ma_short, MA_Long=ma_long)
代码要点解析:
-
initialize函数:- 设置了
use_real_price为True,这是聚宽回测的推荐设置,确保使用真实复权价格。 - 定义了全局变量
g.short_window和g.long_window,方便后续调整参数(例如改为 10日和60日)。 - 使用
run_daily指定每天 9:30 开盘时执行交易逻辑。
- 设置了
-
数据获取 (
attribute_history):- 使用
attribute_history获取过去g.long_window天的历史收盘价。 - 注意:在日级回测中,9:30 调用的
attribute_history获取的是截止到昨天收盘的数据。这意味着我们是利用昨天的均线形态来决定今天的开盘操作,这是一种常见的避免“未来函数”的做法。
- 使用
-
均线计算:
- 利用 Pandas 的切片功能
[-g.short_window:]截取最近的数据来计算短期均值。 - 利用
.mean()方法快速计算平均值。
- 利用 Pandas 的切片功能
-
交易执行:
order_value(security, cash):按金额下单,这里传入available_cash实现全仓买入。order_target(security, 0):调整持仓到目标数量,传入 0 即为清仓卖出。
-
record函数:- 将计算出的 MA 值记录下来,回测结束后,你可以在收益曲线图中看到这两条均线的走势,方便验证策略逻辑。