3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
这是一个基于QMT平台的布林带(Bollinger Bands)均值回归策略。
N 根K线的收盘价移动平均线(SMA)。K 倍的标准差。K 倍的标准差。# -*- 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}),执行卖出")
ContextInfo.account_id = 'YOUR_ACCOUNT_ID' 必须修改为您实际的资金账号(如果是回测,请在策略编辑器的“回测参数”中设置初始资金,代码中可以保留默认或设置虚拟账号)。handlebar 函数会在每一根K线结束或每一个Tick到来时触发。代码中使用了 order_target_percent,这个函数非常适合这种策略,因为它会自动计算需要买卖的数量来达到目标仓位(例如从0%变到100%会自动买入,从100%变到100%则不操作),避免了重复下单。"FIX" (指定价) 和 curr_close (当前价) 进行下单。在实盘中,为了保证成交,您可能希望将其改为 "LATEST" (最新价) 或 "MARKET" (市价)。pandas 计算均线和标准差,QMT内置环境已包含此库。dividend_type='front' (前复权),这对于技术指标策略非常重要,可以避免因分红配股导致的价格跳空触发错误信号。