问题描述
解决方案
乖离率 (BIAS) 的计算与交易策略实现
乖离率(BIAS)是测量股价偏离移动平均线大小程度的指标。它基于“均值回归”的原理:当股价偏离移动平均线太远时,无论是在均线上方还是下方,都有可能向均线回归。
1. 乖离率计算公式
$$
BIAS(N) = \frac{\text{收盘价} - \text{N日移动平均价}}{\text{N日移动平均价}} \times 100%
$$
- N:时间周期,常用的有6日、12日、24日等。
- 正乖离:股价在均线之上,数值越大表示获利盘越多,回调风险越大(超买)。
- 负乖离:股价在均线之下,数值越小表示亏损盘越多,反弹可能性越大(超卖)。
2. 交易策略逻辑
本策略将基于以下简单的均值回归逻辑进行交易:
- 买入信号:当 BIAS 低于设定的负阈值(例如 -6%),认为股价超卖,进行买入。
- 卖出信号:当 BIAS 高于设定的正阈值(例如 +6%),认为股价超买,进行卖出。
3. PTrade 策略代码实现
以下是完整的策略代码,您可以直接在 PTrade 回测或交易环境中运行。
def initialize(context):
"""
初始化函数,设置股票池和全局参数
"""
# 设置要操作的股票,这里以恒生电子为例
g.security = '600570.SS'
set_universe(g.security)
# 策略参数设置
g.N = 12 # 计算BIAS的周期,如12日
g.bias_lower = -6 # 买入阈值:乖离率低于 -6%
g.bias_upper = 6 # 卖出阈值:乖离率高于 +6%
# 设置手续费(可选,回测常用)
set_commission(commission_ratio=0.0003, min_commission=5.0)
def handle_data(context, data):
"""
盘中运行函数,每个单位时间(如每天)运行一次
"""
security = g.security
# 1. 获取历史数据
# 获取过去 g.N 天的收盘价数据,include=True 表示包含当前周期的最新数据
# 注意:为了计算准确,如果是在盘中运行,include=True会包含当前的最新价
hist = get_history(g.N, '1d', 'close', security, fq='pre', include=True)
# 检查数据长度是否足够,不足则不计算
if len(hist) < g.N:
return
# 提取收盘价序列
closes = hist['close']
# 2. 计算指标
# 计算 N 日移动平均线 (MA)
ma_n = closes.mean()
# 获取当前最新价格
current_price = closes[-1]
# 计算乖离率 (BIAS)
# 公式:(当前价格 - 均线价格) / 均线价格 * 100
bias = (current_price - ma_n) / ma_n * 100
# 打印日志方便调试
log.info("日期: %s, 价格: %.2f, MA%d: %.2f, BIAS: %.2f%%" % (
context.blotter.current_dt, current_price, g.N, ma_n, bias
))
# 3. 交易逻辑
# 获取当前持仓数量
position = get_position(security).amount
# 获取当前可用现金
cash = context.portfolio.cash
# 信号判断:超卖(BIAS 过低),买入
if bias < g.bias_lower:
# 如果有现金,则全仓买入
if cash > 0:
log.info("BIAS (%.2f%%) 低于阈值 (%.2f%%),触发买入信号" % (bias, g.bias_lower))
order_value(security, cash)
# 信号判断:超买(BIAS 过高),卖出
elif bias > g.bias_upper:
# 如果有持仓,则清仓卖出
if position > 0:
log.info("BIAS (%.2f%%) 高于阈值 (%.2f%%),触发卖出信号" % (bias, g.bias_upper))
order_target(security, 0)
def before_trading_start(context, data):
"""
盘前处理(可选)
"""
pass
def after_trading_end(context, data):
"""
盘后处理(可选)
"""
pass
4. 代码关键点解析
-
数据获取 (
get_history):- 使用了
get_history(g.N, '1d', 'close', ...)获取过去 N 天的收盘价。 - 参数
include=True非常重要,它确保计算时包含当天的最新价格,从而计算出实时的 BIAS 值。 - 参数
fq='pre'使用前复权数据,这在涉及历史价格比较时是标准做法,避免分红派息导致的价格跳空影响计算。
- 使用了
-
计算逻辑:
- 利用
pandas的.mean()方法快速计算均线。 - 严格按照 BIAS 公式编写代码。
- 利用
-
交易执行:
order_value(security, cash):用于按金额买入,这里示例为全仓买入。order_target(security, 0):用于调整持仓到目标数量,这里设为 0 即代表清仓。
-
Python 版本兼容性:
- 代码中使用了
%格式化字符串(如"BIAS: %.2f%%" % bias),这是为了确保兼容 Python 3.5 及更早版本,避免使用 f-string。
- 代码中使用了
Q&A
Q: 乖离率的阈值(如6%)应该如何设置?
A: 阈值取决于股票的波动性(Beta值)和所选的均线周期。
- 周期越短(如6日),股价波动越频繁,阈值应设置得相对较小。
- 周期越长(如24日),均线越平滑,偏离均线较难,阈值应设置得相对较大。
- 个股特性:大盘股波动小,阈值可设低(如3%-5%);小盘股或妖股波动大,阈值需设高(如8%-10%)。建议通过回测来寻找最优参数。
Q: 这个策略有什么风险?
A: 乖离率是反趋势指标(均值回归)。在强劲的单边趋势行情中(例如连续暴跌或暴涨),股价可能长时间维持在高乖离状态而不回归,导致策略过早抄底被套或过早卖出踏空。通常建议结合趋势指标(如MACD或均线排列)一起使用。
Q: 如何在多只股票上运行此策略?
A: 可以在 initialize 中使用 get_index_stocks 获取一个指数的成分股列表赋值给 g.security(列表),然后在 handle_data 中使用 for 循环遍历这只列表,对每一只股票分别计算 BIAS 并执行交易逻辑。