🚀 AI 一键生成 qmt 策略代码

QMT 平台交易策略:如何利用布林带进行突破和反转交易?

qmt | 发布时间: 2025/11/24
以下内容由 EasyQuant 生成。

问题描述

请为我编写一个布林带策略,当价格跌破布林带下轨时买入,突破上轨时卖出。

解决方案

这是一个基于QMT平台的布林带(Bollinger Bands)均值回归策略。

策略逻辑

  1. 指标计算
    • 中轨 (MB):过去 N 根K线的收盘价移动平均线(SMA)。
    • 上轨 (UP):中轨 + K 倍的标准差。
    • 下轨 (DN):中轨 - K 倍的标准差。
  2. 交易信号
    • 买入:当当前收盘价 跌破 布林带下轨时,认为价格超卖,执行买入(满仓)。
    • 卖出:当当前收盘价 突破 布林带上轨时,认为价格超买,执行卖出(空仓)。

策略代码

# -*- coding: gbk -*-
import pandas as pd
import numpy as np

def init(ContextInfo):
    """
    初始化函数,设定策略参数和账号
    """
    # --- 策略参数设置 ---
    ContextInfo.M = 20       # 布林带周期 (默认20)
    ContextInfo.K = 2.0      # 标准差倍数 (默认2)
    
    # --- 账号设置 ---
    # 请务必将下方的 'YOUR_ACCOUNT_ID' 替换为您真实的资金账号
    ContextInfo.account_id = 'YOUR_ACCOUNT_ID' 
    ContextInfo.account_type = 'STOCK' # 账号类型:'STOCK'股票, 'FUTURE'期货
    
    # 绑定账号
    ContextInfo.set_account(ContextInfo.account_id)
    
    print("布林带策略初始化完成")

def handlebar(ContextInfo):
    """
    K线周期运行函数
    """
    # 获取当前主图的股票代码和市场
    # 格式如 '600000.SH'
    stock_code = ContextInfo.stockcode + '.' + ContextInfo.market
    
    # 获取当前周期 (如 '1d', '15m' 等)
    period = ContextInfo.period
    
    # 获取历史行情数据
    # 我们需要计算M周期的均线,所以至少取 M + 5 根K线以确保数据充足
    count = ContextInfo.M + 5
    
    # 获取收盘价数据
    # get_market_data 返回的是 pandas DataFrame 或 Series
    data = ContextInfo.get_market_data(
        ['close'], 
        stock_code=[stock_code], 
        count=count, 
        period=period, 
        dividend_type='front' # 使用前复权数据
    )
    
    # 检查数据是否获取成功
    if data is None or len(data) < ContextInfo.M:
        return

    # 提取收盘价序列 (Series)
    # 注意:get_market_data 返回的 DataFrame 索引是时间,列是字段
    # 如果是单只股票,直接取该股票的数据
    close_prices = data
    if isinstance(data, pd.DataFrame):
        # 如果返回的是DataFrame,通常结构是 index=time, columns=stock_list (当只取close时)
        # 或者 index=time, columns=['close'] (取决于调用方式,这里做个兼容处理)
        if stock_code in data.columns:
            close_prices = data[stock_code]
        elif 'close' in data.columns:
            close_prices = data['close']
    
    # --- 计算布林带 ---
    # 1. 计算中轨 (移动平均线)
    rolling_mean = close_prices.rolling(window=ContextInfo.M).mean()
    
    # 2. 计算标准差
    rolling_std = close_prices.rolling(window=ContextInfo.M).std()
    
    # 3. 计算上轨和下轨
    upper_band = rolling_mean + ContextInfo.K * rolling_std
    lower_band = rolling_mean - ContextInfo.K * rolling_std
    
    # 获取最新一根K线的数据值
    curr_close = close_prices.iloc[-1]
    curr_upper = upper_band.iloc[-1]
    curr_lower = lower_band.iloc[-1]
    
    # 打印调试信息 (可选)
    # print(f"代码:{stock_code} 收盘:{curr_close:.2f} 上轨:{curr_upper:.2f} 下轨:{curr_lower:.2f}")
    
    # --- 交易逻辑 ---
    
    # 信号1:价格跌破下轨 -> 买入
    if curr_close < curr_lower:
        # 使用 order_target_percent 调整仓位到 100% (全仓买入)
        # 这种方式会自动判断当前是否持有,如果未持有则买入,已持有则不动
        order_target_percent(stock_code, 1.0, "FIX", curr_close, ContextInfo, ContextInfo.account_id)
        
        # 如果是回测模式,打印日志
        if ContextInfo.do_back_test:
            print(f"【买入信号】{stock_code} 价格跌破下轨 ({curr_close} < {curr_lower}),执行买入")

    # 信号2:价格突破上轨 -> 卖出
    elif curr_close > curr_upper:
        # 使用 order_target_percent 调整仓位到 0% (清仓卖出)
        order_target_percent(stock_code, 0.0, "FIX", curr_close, ContextInfo, ContextInfo.account_id)
        
        if ContextInfo.do_back_test:
            print(f"【卖出信号】{stock_code} 价格突破上轨 ({curr_close} > {curr_upper}),执行卖出")

使用说明与注意事项

  1. 账号配置
    • 代码中的 ContextInfo.account_id = 'YOUR_ACCOUNT_ID' 必须修改为您实际的资金账号(如果是回测,请在策略编辑器的“回测参数”中设置初始资金,代码中可以保留默认或设置虚拟账号)。
  2. 运行模式
    • 回测:请确保您已下载了对应品种和周期的历史数据(通过“数据管理”下载)。
    • 实盘/模拟handlebar 函数会在每一根K线结束或每一个Tick到来时触发。代码中使用了 order_target_percent,这个函数非常适合这种策略,因为它会自动计算需要买卖的数量来达到目标仓位(例如从0%变到100%会自动买入,从100%变到100%则不操作),避免了重复下单。
  3. 下单价格
    • 示例中使用了 "FIX" (指定价) 和 curr_close (当前价) 进行下单。在实盘中,为了保证成交,您可能希望将其改为 "LATEST" (最新价) 或 "MARKET" (市价)。
  4. 数据依赖
    • 策略依赖 pandas 计算均线和标准差,QMT内置环境已包含此库。
  5. 复权方式
    • 代码中设置了 dividend_type='front' (前复权),这对于技术指标策略非常重要,可以避免因分红配股导致的价格跳空触发错误信号。