3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
编写 DMI(Directional Movement Index,动向指标)策略通常涉及计算 +DI(上升方向线)、-DI(下降方向线)和 ADX(平均趋向指标)。
DMI 策略的核心逻辑通常是:
以下是一个完整的 QMT Python DMI 策略示例代码。
# -*- coding: gbk -*-
import pandas as pd
import numpy as np
import talib
def init(ContextInfo):
"""
策略初始化函数
"""
# 设置要交易的股票列表
ContextInfo.stock_list = ['600000.SH', '000001.SZ']
# 设置交易账号(请替换为您自己的资金账号)
ContextInfo.account_id = '您的资金账号'
ContextInfo.account_type = 'STOCK' # 股票账号
# 设置策略参数
ContextInfo.N = 14 # DMI计算周期
ContextInfo.M = 6 # ADX平滑周期
ContextInfo.ADX_THRESHOLD = 20 # ADX 阈值,用于确认趋势强度
# 设置周期
ContextInfo.period = '1d'
# 设置基准和费率(回测用)
ContextInfo.set_universe(ContextInfo.stock_list)
ContextInfo.set_account(ContextInfo.account_id)
def handlebar(ContextInfo):
"""
K线周期运行函数
"""
# 获取当前K线位置
index = ContextInfo.barpos
# 获取当前时间
realtime = ContextInfo.get_bar_timetag(index)
# 遍历股票池
for stock in ContextInfo.stock_list:
# 获取历史行情数据 (多取一些数据以保证指标计算准确)
# 注意:talib计算通常需要一定长度的前置数据才能稳定
count = 100
data = ContextInfo.get_market_data_ex(
['high', 'low', 'close'],
[stock],
period=ContextInfo.period,
count=count,
dividend_type='front' # 前复权
)
if stock not in data or data[stock].empty:
continue
df = data[stock]
# 确保数据量足够计算指标
if len(df) < ContextInfo.N + ContextInfo.M + 5:
continue
# 提取 numpy 数组供 talib 使用
high_prices = df['high'].values
low_prices = df['low'].values
close_prices = df['close'].values
# ----------------------------------------------------------------
# 计算 DMI 指标
# ----------------------------------------------------------------
# 计算 +DI (PDI)
pdi = talib.PLUS_DI(high_prices, low_prices, close_prices, timeperiod=ContextInfo.N)
# 计算 -DI (MDI)
mdi = talib.MINUS_DI(high_prices, low_prices, close_prices, timeperiod=ContextInfo.N)
# 计算 ADX
adx = talib.ADX(high_prices, low_prices, close_prices, timeperiod=ContextInfo.N)
# 获取最新和上一个周期的指标值
# -1 代表当前K线,-2 代表上一根K线
current_pdi = pdi[-1]
current_mdi = mdi[-1]
current_adx = adx[-1]
last_pdi = pdi[-2]
last_mdi = mdi[-2]
# ----------------------------------------------------------------
# 交易逻辑
# ----------------------------------------------------------------
# 获取当前持仓
positions = ContextInfo.get_position(stock)
current_holding = 0
if positions:
# 注意:get_position 返回的是对象列表,通常取第一个
# 实盘中建议使用 get_trade_detail_data 获取更准确持仓
pass
# 这里为了简化回测逻辑,我们使用 order_target_percent 来控制仓位
# 买入条件:
# 1. +DI 上穿 -DI (金叉)
# 2. ADX 大于阈值 (趋势确认)
buy_condition = (last_pdi <= last_mdi) and (current_pdi > current_mdi) and (current_adx > ContextInfo.ADX_THRESHOLD)
# 卖出条件:
# 1. +DI 下穿 -DI (死叉)
sell_condition = (last_pdi >= last_mdi) and (current_pdi < current_mdi)
# 执行交易
if buy_condition:
# 满仓买入 (目标仓位调整为 100%)
# 注意:实盘请做好资金管理,不要轻易满仓
print(f"{stock} 触发买入信号: PDI={current_pdi:.2f}, MDI={current_mdi:.2f}, ADX={current_adx:.2f}")
order_target_percent(stock, 1.0, ContextInfo, ContextInfo.account_id)
elif sell_condition:
# 清仓卖出 (目标仓位调整为 0%)
print(f"{stock} 触发卖出信号: PDI={current_pdi:.2f}, MDI={current_mdi:.2f}")
order_target_percent(stock, 0.0, ContextInfo, ContextInfo.account_id)
初始化 (init):
stock_list 和交易账号。N=14 是标准周期,ADX_THRESHOLD=20 用于过滤震荡行情。ContextInfo.set_universe 设定股票池。数据获取 (handlebar):
ContextInfo.get_market_data_ex 获取历史的高、低、收盘价。count 必须大于指标计算所需的周期(例如 100),否则 talib 计算出的结果可能是 NaN。指标计算:
talib 库进行高效计算。talib.PLUS_DI: 计算 +DI。talib.MINUS_DI: 计算 -DI。talib.ADX: 计算 ADX。交易逻辑:
last_pdi <= last_mdi 且 current_pdi > current_mdi。这意味着上一根 K 线 -DI 在上方或相等,当前 K 线 +DI 跑到了上方。current_adx > ContextInfo.ADX_THRESHOLD 条件,避免在无趋势的震荡市中频繁开仓。last_pdi >= last_mdi 且 current_pdi < current_mdi。下单执行:
order_target_percent 函数。这是一个非常方便的函数,它会自动计算需要买卖的数量,将该股票的持仓调整到总资产的指定比例(例如 1.0 代表满仓,0.0 代表清仓)。talib 库。如果您的环境报错找不到模块,可能需要联系管理员或手动安装。count 设置为 N 的 3-5 倍以上。ContextInfo.account_id 必须修改为您实际登录的资金账号,否则无法下单。1d) 级别运行。如果需要在分钟级别运行,请修改 ContextInfo.period 并确保下载了对应的分钟数据。Q: 如何调整 DMI 的灵敏度?
A: 修改 init 函数中的 ContextInfo.N。减小 N 值(如改为 7)会使指标更灵敏,但假信号增多;增大 N 值(如改为 20)会使指标更平滑,但信号会有滞后。
Q: 为什么要用 ADX 过滤?
A: DMI 是一个趋势指标。在盘整(横盘)行情中,+DI 和 -DI 会频繁交叉,导致频繁止损。ADX 代表趋势的强度,只有当 ADX 大于一定数值(如 20 或 25)时,才认为当前有足够的趋势去进行交易。
Q: order_target_percent 在回测和实盘都能用吗?
A: 是的,这个函数在回测和实盘模式下都支持。在实盘中,它会根据账户的总资产计算目标市值,然后下单调整持仓。