问题描述
比如EMA1返回了一个值,需要将EMA1返回的值继续在EMA2中继续使用,这个代码应该怎么写?
问了聚宽的客服,他们自己的这个代码:
EMA(security_list, check_date, timeperiod=30, unit = '1d', include_now = True, fq_ref_date = None)
不支持这种操作
解决方案
聚宽官方提供的 EMA 函数(属于 jqlib.technical_analysis)确实是高度封装的,它的输入必须是股票代码(security_list),因此无法直接将一个计算好的数值序列再次传入该函数。
要实现嵌套 EMA(即对 EMA 的结果再求 EMA),我们需要绕过官方的封装函数,直接获取历史价格数据,然后使用 Python 的数据处理库(如 pandas 或 talib)来进行计算。
以下提供两种最常用的实现方法:
方法一:使用 Pandas 的 ewm 方法(最推荐)
pandas 是 Python 数据分析的核心库,它的 ewm (Exponential Weighted functions) 方法非常适合计算 EMA,且支持对任意 Series 序列进行连续操作,完美契合嵌套计算的需求。
import pandas as pd
from jqdata import *
def get_nested_ema_pandas(security, check_date, period1=12, period2=26):
"""
使用 Pandas 计算嵌套 EMA
:param security: 股票代码
:param check_date: 截止日期
:param period1: 第一层 EMA 的周期
:param period2: 第二层 EMA 的周期
:return: 最新的 EMA1 和 嵌套 EMA2 的值
"""
# 1. 获取历史收盘价数据
# 注意:计算 EMA 需要足够的历史数据来消除初始值的影响,建议 count 设置为最大周期的 3-5 倍以上
df = get_price(security, end_date=check_date, count=150, fields=['close'])
close_prices = df['close']
# 2. 计算第一层 EMA
# adjust=False 保证计算公式与传统炒股软件的 EMA 公式一致
ema1_series = close_prices.ewm(span=period1, adjust=False).mean()
# 3. 计算第二层 EMA(嵌套计算)
# 直接对第一层的结果 ema1_series 再次调用 ewm
ema2_series = ema1_series.ewm(span=period2, adjust=False).mean()
# 4. 返回最新一天的值
return ema1_series.iloc[-1], ema2_series.iloc[-1]
# 测试调用
# ema1_val, ema2_val = get_nested_ema_pandas('000001.XSHE', '2023-10-10', 12, 26)
# print(f"EMA1: {ema1_val}, 嵌套EMA2: {ema2_val}")
方法二:使用 TA-Lib 库
talib 是量化领域最著名的技术指标库,聚宽环境已经内置了该库。它的 EMA 函数接受 numpy 数组作为输入,因此也可以轻松实现嵌套。
import talib
import numpy as np
from jqdata import *
def get_nested_ema_talib(security, check_date, period1=12, period2=26):
"""
使用 TA-Lib 计算嵌套 EMA
"""
# 1. 获取历史数据
df = get_price(security, end_date=check_date, count=150, fields=['close'])
# talib 需要 numpy array 格式的数据
close_prices = df['close'].values
# 2. 计算第一层 EMA
ema1_array = talib.EMA(close_prices, timeperiod=period1)
# 3. 计算第二层 EMA(嵌套计算)
# 注意:talib.EMA 计算结果的前 period1-1 个值会是 NaN
# talib 可以自动处理输入数组中的 NaN,直接传入即可
ema2_array = talib.EMA(ema1_array, timeperiod=period2)
# 4. 返回最新一天的值
return ema1_array[-1], ema2_array[-1]
核心注意事项
- 数据长度(
count参数):EMA(指数移动平均)是一个具有“无限长记忆性”的指标,今天的值受昨天值的影响,昨天受前天影响。因此,获取的历史数据长度(count)必须足够长。强烈建议count的值至少设置为period1 + period2的 3 到 5 倍(例如周期是 12 和 26,count 至少取 150),否则计算出的最新值会与同花顺/通达信等软件产生较大误差。 - Pandas 的
adjust=False:在使用 Pandas 计算时,务必加上adjust=False参数,这样其底层计算逻辑才会与传统金融软件的 EMA 逻辑(Y = [2*X + (N-1)*Y'] / (N+1))保持一致。 - 回测中的应用:在
handle_data中调用时,check_date可以直接传入context.current_dt。