3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
这是一个基于 PTrade 平台的量化交易策略,实现了 ATR(平均真实波幅)动态追踪止损 的逻辑。
talib 库计算 14 日 ATR 指标。Highest_High)。止损价 = 历史最高价 - (系数 * ATR)。Highest_High 会更新,止损线也会随之上移,从而锁定利润;当股价下跌时,止损线保持不变,直到价格触及止损线离场。import talib
import numpy as np
def initialize(context):
"""
初始化函数,设置参数和股票池
"""
# 设置要操作的股票,这里以贵州茅台为例
g.security = ['600519.SS']
set_universe(g.security)
# 策略参数设置
g.atr_period = 14 # ATR计算周期
g.atr_multiplier = 2.0 # ATR倍数,用于计算止损距离
g.ma_short = 5 # 短期均线周期
g.ma_long = 20 # 长期均线周期
# 用于记录持仓股票的持仓期间最高价,格式:{stock_code: highest_price}
g.highest_prices = {}
def before_trading_start(context, data):
"""
盘前处理
"""
pass
def handle_data(context, data):
"""
盘中每分钟或每天运行的逻辑
"""
# 获取当前回测/交易的股票列表
security_list = g.security
# 获取历史数据,取足够长的数据以确保指标计算准确
# count=100 保证有足够的数据计算 MA20 和 ATR14
hist_data = get_history(100, frequency='1d', field=['high', 'low', 'close'], security_list=security_list, fq='pre')
for stock in security_list:
# 检查该股票是否停牌,如果停牌则跳过
if stock in data and data[stock].is_open == 0:
continue
# 获取该股票的 K 线数据
# 注意:get_history 返回的数据结构在单只和多只股票时可能不同
# 这里使用 query 确保获取到的是 DataFrame
if len(security_list) == 1:
df = hist_data
else:
df = hist_data.query('code == "%s"' % stock)
# 提取 numpy 数组用于 talib 计算
high_prices = df['high'].values
low_prices = df['low'].values
close_prices = df['close'].values
# 确保数据长度足够
if len(close_prices) < 30:
continue
# --- 1. 计算技术指标 ---
# 计算 ATR
atr = talib.ATR(high_prices, low_prices, close_prices, timeperiod=g.atr_period)
current_atr = atr[-1] # 获取最新的 ATR 值
# 计算均线 (用于入场)
ma_short = talib.MA(close_prices, timeperiod=g.ma_short)
ma_long = talib.MA(close_prices, timeperiod=g.ma_long)
# 获取当前价格
current_price = data[stock]['close']
# 获取当前持仓
position = get_position(stock)
# --- 2. 交易逻辑 ---
# A. 如果当前持有仓位 -> 执行 ATR 追踪止损逻辑
if position.amount > 0:
# 初始化或更新持仓期间的最高价
# 如果该股票不在记录中,说明是刚买入,初始化为买入成本或当前价
if stock not in g.highest_prices:
g.highest_prices[stock] = current_price
else:
# 如果当前价格创新高,则更新最高价
if current_price > g.highest_prices[stock]:
g.highest_prices[stock] = current_price
# 计算动态止损价
# 止损价 = 持仓期最高价 - (ATR系数 * 当前ATR)
stop_loss_price = g.highest_prices[stock] - (g.atr_multiplier * current_atr)
# 打印调试日志 (可选)
# log.info("%s 持仓中, 最高价: %.2f, ATR: %.2f, 止损价: %.2f, 当前价: %.2f" % (stock, g.highest_prices[stock], current_atr, stop_loss_price, current_price))
# 判断是否触发止损
if current_price < stop_loss_price:
log.info("触发ATR追踪止损: %s, 卖出价格: %.2f" % (stock, current_price))
order_target(stock, 0) # 清仓
# 卖出后,清除最高价记录
if stock in g.highest_prices:
del g.highest_prices[stock]
# B. 如果当前空仓 -> 执行均线入场逻辑
else:
# 简单的金叉判断:短期均线上穿长期均线
# 前一天短均线 < 长均线,且 今天短均线 > 长均线
if ma_short[-2] < ma_long[-2] and ma_short[-1] > ma_long[-1]:
log.info("均线金叉买入: %s, 价格: %.2f" % (stock, current_price))
# 全仓买入 (这里简单使用可用资金买入)
order_value(stock, context.portfolio.cash)
# 买入后,立即初始化最高价记录,防止下一分钟/下一天逻辑出错
g.highest_prices[stock] = current_price
def after_trading_end(context, data):
"""
盘后处理
"""
pass
import talib: PTrade 环境内置了 TA-Lib 库,这是计算 ATR 最标准、最高效的方法。g.highest_prices 字典:
current_price > g.highest_prices[stock],我们就更新这个最高价。del 删除这个记录,以免影响下一次交易。stop_loss_price = g.highest_prices[stock] - (g.atr_multiplier * current_atr)g.highest_prices 变大,stop_loss_price 也跟着变大(上移),从而保护浮盈。g.atr_multiplier (ATR倍数) 通常设置为 2.0 到 3.0 之间。倍数越小,止损越紧,容易被震荡洗出;倍数越大,止损越松,回撤可能较大。get_history(100, ...)。虽然 ATR 只需要 14 天数据,但为了计算结果的稳定性(ATR 和 MA 都需要一定的历史数据来平滑),取 100 条数据是比较稳妥的做法。Q1: 为什么使用 ATR 而不是固定百分比止损?
A: 固定百分比(如跌 5% 止损)忽略了市场的波动率。ATR 代表了资产的平均真实波幅。在市场波动剧烈时,ATR 变大,止损间距自动变宽,防止被正常波动震出;在市场平稳时,ATR 变小,止损间距变窄,能更敏锐地锁定利润。
Q2: 如何调整策略的灵敏度?
A: 修改 initialize 中的 g.atr_multiplier。
Q3: 这个策略可以直接用于实盘吗?
A: 该代码是一个基础框架。在实盘前,建议您:
order_value(stock, context.portfolio.cash) 是全仓买入,实盘建议根据资金量分仓操作。