问题描述
如何在我的代码里使用 TA-Lib 库来计算移动平均线(MA)?
解决方案
在 QMT 平台中使用 TA-Lib 库计算移动平均线(MA)非常直接,因为 QMT 的内置 Python 环境通常已经预装了 talib 和 numpy 库。
要在代码中实现这一功能,主要步骤如下:
- 获取数据:使用
ContextInfo.get_market_data获取历史行情数据(通常是 pandas DataFrame 格式)。 - 数据转换:TA-Lib 的函数通常需要
numpy.ndarray类型的输入,因此需要将 pandas 数据转换为 numpy 数组。 - 调用函数:使用
talib.MA或具体的talib.SMA、talib.EMA等函数进行计算。
以下是一个完整的策略示例代码,展示了如何在 handlebar 函数中计算 5日简单移动平均线(SMA)和 10日指数移动平均线(EMA)。
# -*- coding: gbk -*-
import pandas as pd
import numpy as np
import talib
def init(ContextInfo):
# 设置股票池,这里以平安银行为例
ContextInfo.set_universe(['000001.SZ'])
# 设置基准
ContextInfo.benchmark = '000300.SH'
def handlebar(ContextInfo):
# 获取当前图表的股票代码
stock_code = ContextInfo.get_universe()[0]
# 1. 获取历史行情数据
# 我们需要获取足够的历史数据来计算 MA。例如计算 MA10,至少需要 10 根 K 线
# 这里获取过去 100 根日线数据的收盘价
# 注意:dividend_type='front' 表示使用前复权数据,这在计算指标时很重要
data = ContextInfo.get_market_data(
['close'],
stock_code=[stock_code],
count=100,
period='1d',
dividend_type='front'
)
# 检查数据是否获取成功
if data is None or data.empty:
return
# 2. 数据转换
# get_market_data 返回的是 pandas DataFrame
# 我们需要提取 'close' 列并转换为 numpy 数组,因为 TA-Lib 需要 numpy 数组作为输入
# 注意:TA-Lib 要求输入数据类型通常为 float
close_prices = data['close'].values.astype(float)
# 3. 使用 TA-Lib 计算移动平均线
# 计算 5日 简单移动平均线 (SMA)
# timeperiod: 周期
# matype: 移动平均类型 (0=SMA, 1=EMA, 2=WMA, 3=DEMA, 4=TEMA, etc.)
ma5 = talib.MA(close_prices, timeperiod=5, matype=0)
# 计算 10日 指数移动平均线 (EMA)
ma10 = talib.MA(close_prices, timeperiod=10, matype=1)
# 或者直接使用具体函数
# ma10_ema = talib.EMA(close_prices, timeperiod=10)
# 4. 获取最新的指标值
# 数组的最后一个元素 [-1] 是最新的计算结果
current_ma5 = ma5[-1]
current_ma10 = ma10[-1]
# 打印结果
# 注意:如果数据不足(例如刚上市的股票),计算结果可能是 nan
if not np.isnan(current_ma5) and not np.isnan(current_ma10):
print(f"代码: {stock_code}")
print(f"当前时间: {ContextInfo.get_bar_timetag(ContextInfo.barpos)}")
print(f"最新收盘价: {close_prices[-1]}")
print(f"MA5: {current_ma5:.2f}")
print(f"MA10 (EMA): {current_ma10:.2f}")
print("-" * 30)
# 简单的策略逻辑示例:金叉(MA5 上穿 MA10)
if len(ma5) >= 2 and len(ma10) >= 2:
prev_ma5 = ma5[-2]
prev_ma10 = ma10[-2]
# 排除 nan 值
if not np.isnan(prev_ma5) and not np.isnan(prev_ma10):
if prev_ma5 < prev_ma10 and current_ma5 > current_ma10:
print(f"信号触发: {stock_code} 形成金叉 (MA5 上穿 MA10)")
代码关键点说明:
# -*- coding: gbk -*-: 必须添加在文件首行,以确保中文字符和 QMT 环境兼容。import talib: 引入库。get_market_data: 获取数据时,count参数必须大于你要计算的 MA 周期。例如计算 MA60,count至少要设为 60,通常建议设得更大(如 100 或 200),以确保计算稳定。.values.astype(float): TA-Lib 对输入数据的类型比较敏感,确保传入的是float类型的numpy数组是最稳妥的做法。talib.MA参数:- 第一个参数是输入数组(收盘价)。
timeperiod: 计算周期(如 5, 10, 20)。matype: 移动平均线的类型。0代表 SMA (Simple),1代表 EMA (Exponential)。你也可以直接调用talib.SMA(...)或talib.EMA(...)。
- 处理
NaN: 移动平均线计算的前N-1个数据通常是NaN(无效值),在使用结果前最好进行非空判断。