问题描述
即向前引用的指标,引用X在N个周期前的值
解决方案
在传统的股票分析软件(如通达信、同花顺)中,REF(X, N) 是一个非常常用的函数,用于引用变量 X 在 N 个周期前的值。在 JoinQuant(聚宽)量化平台中,我们使用的是 Python 语言,可以通过平台提供的历史数据 API(如 attribute_history 或 history)来轻松实现这一功能。
实现原理
在 JoinQuant 的回测引擎中,attribute_history(security, count, unit, fields) 函数用于获取指定标的过去 count 个周期的历史数据。需要注意的是,该函数返回的数据不包含当前周期(例如当天)的数据。
因此,如果当前是 T 日,调用 attribute_history(security, N, '1d', ['close']) 将返回 T-N 日到 T-1 日共 N 天的数据。这个返回的 DataFrame 中,第一行(索引为 0)的数据正是 T-N 日的数据,也就是我们想要的 REF(X, N)。
封装 REF 函数
为了方便在策略中重复使用,我们可以将其封装成一个 Python 函数:
def REF(security, field, n, unit='1d'):
"""
模拟传统指标中的 REF(X, N) 函数
:param security: 标的代码,如 '000001.XSHE'
:param field: 引用的字段,如 'close', 'open', 'high', 'low', 'volume'
:param n: 向前引用的周期数
:param unit: 周期单位,默认为 '1d'(天),也可设为 '1m' 等
:return: N个周期前的值
"""
if n <= 0:
return None
# 获取过去 N 个周期的数据
hist = attribute_history(security, n, unit, [field])
# 确保获取到的数据长度足够
if len(hist) == n:
return hist[field][0] # 索引 0 即为 N 个周期前的数据
else:
return None # 数据不足(如新股上市不足 N 天)
在策略中的具体应用示例
以下是一个完整的策略示例,展示了如何在 handle_data 中调用上述逻辑来获取 REF(CLOSE, 1) 和 REF(CLOSE, 5):
import jqdata
def initialize(context):
# 设定要操作的股票
g.security = '000001.XSHE'
# 开启动态复权模式(真实价格)
set_option('use_real_price', True)
def handle_data(context, data):
security = g.security
# 1. 直接使用 API 获取 REF(CLOSE, 5) 即 5天前的收盘价
# 获取过去5天的收盘价数据
close_data = attribute_history(security, 5, '1d', ['close'])
if len(close_data) == 5:
ref_5_close = close_data['close'][0] # 索引0是5天前,索引-1是昨天
log.info("5天前的收盘价 REF(CLOSE, 5) 为: %s" % ref_5_close)
# 2. 获取昨天的收盘价 REF(CLOSE, 1)
ref_1_close = attribute_history(security, 1, '1d', ['close'])['close'][0]
log.info("昨天的收盘价 REF(CLOSE, 1) 为: %s" % ref_1_close)
# 3. 结合当前价格进行逻辑判断
current_price = data[security].close
if current_price > ref_5_close:
log.info("当前价格大于5天前的收盘价,产生买入信号")
# order(security, 100)
总结与注意事项
- 数据对齐:
attribute_history默认返回的是前复权数据,这与传统软件的默认行为一致,适合用于计算技术指标。 - 性能优化:如果你需要同时获取多个指标或多个周期的
REF值,建议一次性获取足够长的数据(例如attribute_history(security, 10, '1d', ['close', 'open'])),然后在本地 DataFrame 中通过索引取值(如df['close'][-N]),这样可以减少 API 调用次数,提高回测速度。 - 多标的查询:如果需要同时查询多只股票的
REF值,请使用history函数替代attribute_history。