问题描述
解决方案
这是一个基于 PTrade 量化交易平台的 斐波那契回撤(Fibonacci Retracement) 策略实现。
策略原理
斐波那契回撤是一种基于技术分析的策略,用于判断资产价格在趋势中的支撑位和阻力位。
- 趋势识别:首先确定一个时间窗口内的最高价(Swing High)和最低价(Swing Low)。
- 回撤计算:如果当前是上升趋势(最低价出现在最高价之前),我们寻找价格从高点回落的时机。
- 买入信号:当价格回撤到关键的斐波那契水平(通常是 61.8% 或 50%)附近时,视为潜在的支撑位,执行买入。
- 卖出/止损:当价格跌破前期最低价(趋势破坏)止损,或者价格突破前期最高价(趋势延续)止盈。
PTrade 策略代码
import numpy as np
def initialize(context):
"""
策略初始化函数
"""
# 1. 设置要操作的股票,这里以贵州茅台为例
g.security = '600519.SS'
set_universe(g.security)
# 2. 设置策略参数
g.lookback_days = 60 # 回溯窗口,用于寻找波段高低点
g.fib_ratio = 0.618 # 斐波那契回撤比例 (黄金分割)
g.threshold = 0.02 # 价格触及回撤位的容忍偏差范围 (2%)
# 3. 设置滑点和手续费 (回测常用设置)
set_commission(commission_ratio=0.0003, min_commission=5.0, type='STOCK')
set_slippage(slippage=0.002)
def handle_data(context, data):
"""
盘中运行函数,每日或每分钟调用
"""
security = g.security
# 1. 获取历史数据
# 获取过去 N 天的最高、最低、收盘价
# 注意:count要取够,确保能覆盖 lookback_days
hist = get_history(g.lookback_days, '1d', ['high', 'low', 'close'], security, fq='pre', include=False)
if len(hist) < g.lookback_days:
# 数据不足时不操作
return
# 2. 计算波段高低点
highs = hist['high'].values
lows = hist['low'].values
max_price = np.max(highs) # 窗口内最高价
min_price = np.min(lows) # 窗口内最低价
# 获取最高价和最低价出现的索引位置
max_idx = np.argmax(highs)
min_idx = np.argmin(lows)
# 获取当前最新价格
current_price = data[security]['close']
# 获取当前持仓
position = get_position(security)
# 3. 策略逻辑:判断趋势方向
# 如果 最低价索引 < 最高价索引,说明是上升趋势(先低后高),我们寻找回调买点
if min_idx < max_idx:
# 计算波段幅度
diff = max_price - min_price
# 计算斐波那契回撤支撑位 (从高点向下回撤 61.8%)
# 公式:支撑位 = 最高价 - (波段幅度 * 0.618)
fib_support_level = max_price - (diff * g.fib_ratio)
# 计算触发买入的价格区间
buy_upper = fib_support_level * (1 + g.threshold)
buy_lower = fib_support_level * (1 - g.threshold)
# 4. 交易信号
# 信号1:买入
# 如果当前空仓,且价格落入斐波那契支撑区间
if position.amount == 0:
if buy_lower <= current_price <= buy_upper:
# 全仓买入
order_value(security, context.portfolio.cash)
log.info("上升趋势回调:价格触及0.618回撤位 %.2f,执行买入" % fib_support_level)
# 信号2:止损/止盈
elif position.amount > 0:
# 止损:如果价格跌破了波段最低价,说明趋势反转/失效
if current_price < min_price:
order_target(security, 0)
log.info("止损卖出:价格跌破波段前低 %.2f" % min_price)
# 止盈:如果价格突破了波段最高价,说明趋势延续,可以选择止盈或继续持有
# 这里演示为止盈
elif current_price > max_price:
order_target(security, 0)
log.info("止盈卖出:价格突破波段前高 %.2f" % max_price)
# 如果是下降趋势(先高后低),本策略暂不做空(A股通常只能做多),可选择空仓观望
else:
if position.amount > 0:
# 如果持有仓位但趋势判定为下降(最高点在最低点之前),考虑清仓
# 这里是一个简单的风控逻辑
pass
def before_trading_start(context, data):
"""
盘前处理
"""
pass
def after_trading_end(context, data):
"""
盘后处理
"""
pass
代码核心逻辑解析
-
get_history获取数据:
我们获取了过去g.lookback_days(例如60天)的行情数据。这是确定“波段”的基础。 -
np.argmax与np.argmin:
这两个函数用于确定最高价和最低价在时间轴上的相对位置。- 如果
min_idx < max_idx:意味着最低点出现在最高点之前,这是一个上升波段,我们才有理由去接回调(Buy the dip)。 - 如果
min_idx > max_idx:意味着最高点出现在最低点之前,这是一个下降波段,此时买入风险较大,策略选择观望。
- 如果
-
回撤位计算:
在上升趋势中,回撤位的计算公式为:
$$ \text{Support} = \text{High} - (\text{High} - \text{Low}) \times 0.618 $$
这意味着价格从高点回吐了上涨幅度的 61.8%。 -
容错区间 (
g.threshold):
价格很少会精确地打在计算出的价位上。因此我们设置了一个threshold(如 2%),只要价格进入支撑位 ± 2%的区间,就触发交易。 -
风控:
- 止损:如果价格跌破了波段的起始最低点(
min_price),说明斐波那契支撑失效,趋势可能反转,必须止损。 - 止盈:如果价格反弹并突破了前高(
max_price),说明这一波调整结束,趋势继续向上,策略选择获利了结(也可以修改代码为继续持有直到趋势破坏)。
- 止损:如果价格跌破了波段的起始最低点(
注意事项
- Python 版本:代码兼容 Python 3.5+,未使用 f-string 等新特性,符合 PTrade 现有环境要求。
- 参数调整:
g.lookback_days决定了你是做短线(如10-20天)还是中长线(60-120天)。g.fib_ratio可以修改为 0.5 或 0.382 以适应不同的市场强度。 - API 调用:所有数据获取和下单均使用 PTrade 标准 API(如
order_value,get_position)。
Q&A: 斐波那契策略常见问题
Q1: 为什么选择 0.618 作为回撤比例?
A1: 0.618 是数学上的“黄金分割率”。在金融市场心理学中,许多交易者认为价格在回撤 61.8% 时会有较强的支撑。当然,0.5 (50%) 和 0.382 (38.2%) 也是常用的回撤位,你可以通过修改 g.fib_ratio 来测试不同的效果。
Q2: 这个策略适合什么频率?
A2: 上述代码使用的是 1d (日线) 数据,适合日线级别的波段交易。如果你想做日内高频,需要将 get_history 的频率改为 1m 或 5m,并相应调整 g.lookback_days 的数值(例如改为 60 分钟)。
Q3: 如何避免“假突破”或“假支撑”?
A3: 单一的斐波那契指标容易出现误判。建议结合其他指标进行过滤,例如:
- 成交量:价格跌至回撤位时,成交量是否萎缩(惜售)?
- MACD/KDJ:指标是否在低位形成金叉?
- 均线:回撤位是否刚好在 60 日均线附近(双重支撑)?
Q4: 代码中的 set_universe 是必须的吗?
A4: 是的。在 PTrade 中,必须先设置股票池,后续的 handle_data 中的 data 对象才会包含该股票的实时行情数据。