🚀 AI 一键生成 joinquant 策略代码
立即体验
👉 AI 生成代码 👈

JoinQuant量化平台:如何通过收盘价EMA判断市场趋势?

joinquant | 发布时间: 2026/6/24
以下内容由 EasyQuant 生成。

问题描述

【求助】在回测环境中,怎么通过收盘价EMA判断趋势?

我的思路:
通过收盘价EMA判断市场的趋势。
如果【当前K线的EMA>前1K线的EMA>前2K线的EMA】,
则认为市场处于上涨趋势;
如果【当前K线的EMA< 前1K线的EMA< 前2K线的EMA】,
则认为市场处于下跌趋势。

遇到的困难:
在回测环境中,怎么写代码计算【收盘价】的EMA趋势?
在这里卡住半个月了!
比如,想要写代码判断:
10分钟K线:当前EMA>前1EMA>前2EMA
该写什么代码?
聚宽的EMA函数如下:
EMA(security_list, check_date, timeperiod=30, unit = '1d', include_now = True, fq_ref_date = None)
check_date只能输入特定日期的EMA,要比较前后周期的EMA数值,要如何实现?
注:需要能在回测环境中使用的。
有知道的大佬,麻烦指点一下,不胜感激!!

解决方案

在 JoinQuant(聚宽)的回测环境中,如果你使用 jqlib.technical_analysis 库中的 EMA 函数,确实会遇到需要频繁传入 check_date 的问题,这在获取连续多个周期的 EMA 时非常不方便且运行效率低下。

最佳解决方案是:使用聚宽内置支持的第三方技术分析库 talib,结合 get_bars 函数获取历史 K 线数据,直接计算出一个 EMA 数组,然后通过数组切片轻松获取当前、前1、前2的 EMA 值。

以下是针对你“10分钟K线,判断当前EMA > 前1EMA > 前2EMA”需求的完整代码实现方案:

核心实现代码

# 导入聚宽函数库
import jqdata
# 导入 talib 库用于高效计算技术指标
import talib

def initialize(context):
    # 设定要操作的股票
    g.security = '000001.XSHE'
    # 设定 EMA 的计算周期,例如 30 周期
    g.ema_timeperiod = 30
    
    # 开启真实价格模式
    set_option('use_real_price', True)
    
    # 每天按分钟运行,这里我们可以在 handle_data 中控制频率,
    # 或者直接使用 run_daily 定时运行。为了演示10分钟K线,我们在 handle_data 中处理。

def handle_data(context, data):
    # 1. 获取历史 K 线数据
    # 获取 10分钟 (10m) 级别的收盘价数据
    # 注意:计算 EMA 需要一定的历史数据作为预热(通常是周期的 2-3 倍),所以 count 设大一点,比如 100
    bars = get_bars(g.security, count=100, unit='10m', fields=['close'], include_now=True)
    
    # 提取收盘价序列 (numpy.ndarray)
    close_prices = bars['close']
    
    # 2. 使用 talib 计算 EMA 序列
    # talib.EMA 会返回一个与 close_prices 长度相同的数组
    ema_array = talib.EMA(close_prices, timeperiod=g.ema_timeperiod)
    
    # 3. 提取最后 3 个周期的 EMA 值
    # 数组最后一位 [-1] 是当前 K 线的 EMA
    # [-2] 是前 1 K 线的 EMA
    # [-3] 是前 2 K 线的 EMA
    current_ema = ema_array[-1]
    prev_ema_1 = ema_array[-2]
    prev_ema_2 = ema_array[-3]
    
    # 过滤掉 NaN 值(在数据量不足时 talib 会返回 NaN)
    if np.isnan(current_ema) or np.isnan(prev_ema_1) or np.isnan(prev_ema_2):
        return
        
    # 4. 判断趋势逻辑
    if current_ema > prev_ema_1 and prev_ema_1 > prev_ema_2:
        # 上涨趋势
        log.info(f"【上涨趋势】当前EMA:{current_ema:.2f} > 前1:{prev_ema_1:.2f} > 前2:{prev_ema_2:.2f}")
        # 在这里编写买入逻辑
        if context.portfolio.positions[g.security].closeable_amount == 0:
            order_value(g.security, context.portfolio.available_cash)
            
    elif current_ema < prev_ema_1 and prev_ema_1 < prev_ema_2:
        # 下跌趋势
        log.info(f"【下跌趋势】当前EMA:{current_ema:.2f} < 前1:{prev_ema_1:.2f} < 前2:{prev_ema_2:.2f}")
        # 在这里编写卖出逻辑
        if context.portfolio.positions[g.security].closeable_amount > 0:
            order_target(g.security, 0)

代码原理解析

  1. get_bars 函数

    • unit='10m':直接获取 10 分钟级别的 K 线数据,完美契合你的需求。
    • count=100:EMA 是指数移动平均,它的计算依赖于历史所有的价格数据(越久远的数据权重越小)。为了保证当前 EMA 值的准确性,获取的数据长度(count)建议至少是 EMA 周期(timeperiod)的 3 倍以上。
    • include_now=True:包含当前正在生成的这根 10 分钟 K 线。
  2. talib.EMA 函数

    • 相比于聚宽自带的 jqlib.technical_analysis.EMAtalib 是 C 语言底层编写的,计算速度极快,且直接接收一个价格数组,返回一个完整的 EMA 数组。这是量化回测中最主流、最高效的指标计算方式。
  3. 数组切片 [-1], [-2], [-3]

    • Python 的列表/数组支持负数索引,-1 代表最后一个元素(即当前最新 K 线),-2 代表倒数第二个,以此类推。这样就能轻松拿到你需要的“当前”、“前1”、“前2”的数值进行比较。

通过这种方式,你不仅可以判断 10 分钟 K 线的趋势,只需修改 get_bars 中的 unit 参数(如 '1d', '5m', '60m'),就可以无缝切换到任何时间周期的趋势判断中。