问题描述
解决方案
这是一个基于 Aroon(阿隆)指标的趋势跟踪策略。
策略原理
阿隆指标(Aroon Indicator) 由 Aroon Up(上线)和 Aroon Down(下线)两条曲线组成,用于判断趋势的方向和强度。
-
计算公式:
- Aroon Up = $[(N - \text{距离最高价的天数}) / N] \times 100$
- Aroon Down = $[(N - \text{距离最低价的天数}) / N] \times 100$
- $N$ 通常取 25 天。
-
交易逻辑:
- 买入信号:当 Aroon Up 大于 Aroon Down,且 Aroon Up 大于 50(表示上涨趋势强劲)时,全仓买入。
- 卖出信号:当 Aroon Down 大于 Aroon Up(表示下跌趋势占优)时,清仓卖出。
策略代码
# -*- coding: utf-8 -*-
import jqdata
import numpy as np
def initialize(context):
"""
初始化函数,设定基准、手续费、滑点、全局变量等
"""
# 设定沪深300作为基准
set_benchmark('000300.XSHG')
# 开启动态复权模式(真实价格)
set_option('use_real_price', True)
# 过滤掉order系列API产生的比error级别低的log
log.set_level('order', 'error')
# 设定股票类每笔交易时的手续费
set_order_cost(OrderCost(close_tax=0.001, open_commission=0.0003, close_commission=0.0003, min_commission=5), type='stock')
# 定义全局变量
# 设定要操作的标的,这里以平安银行为例
g.security = '000001.XSHE'
# 阿隆指标的计算周期 N
g.N = 25
# 每天开盘时运行
run_daily(market_open, time='open')
def market_open(context):
"""
每日交易逻辑
"""
security = g.security
# 获取过去 N 天的最高价和最低价数据
# 注意:我们需要包含今天的数据来判断当前的趋势,但在回测引擎中,
# 'open'时间点调用attribute_history获取的是昨天及之前的数据(避免未来函数)。
# 如果需要包含分钟级的实时数据,逻辑会更复杂。这里使用基于日线的收盘价逻辑(T-1数据决策,T日执行)。
h_data = attribute_history(security, g.N, '1d', ['high', 'low'])
# 如果数据长度不足(例如刚上市),则跳过
if len(h_data) < g.N:
return
# 提取最高价和最低价的数组
highs = h_data['high'].values
lows = h_data['low'].values
# 计算距离最高价和最低价的天数
# argmax() 返回最大值的索引,索引 0 代表 N 天前,索引 N-1 代表最近一天
# 距离天数 = (总天数 - 1) - 索引值
days_since_high = (g.N - 1) - highs.argmax()
days_since_low = (g.N - 1) - lows.argmin()
# 计算 Aroon Up 和 Aroon Down
aroon_up = ((g.N - days_since_high) / float(g.N)) * 100
aroon_down = ((g.N - days_since_low) / float(g.N)) * 100
# 获取当前持仓
curr_position = context.portfolio.positions[security].total_amount
available_cash = context.portfolio.available_cash
# --- 交易信号判断 ---
# 买入条件:Aroon Up > Aroon Down 且 Aroon Up > 50 (趋势向上且强度足够)
if aroon_up > aroon_down and aroon_up > 50:
if curr_position == 0:
# 全仓买入
order_value(security, available_cash)
log.info("买入信号触发: Aroon Up(%.2f) > Aroon Down(%.2f)" % (aroon_up, aroon_down))
# 卖出条件:Aroon Down > Aroon Up (趋势转跌)
elif aroon_down > aroon_up:
if curr_position > 0:
# 清仓卖出
order_target(security, 0)
log.info("卖出信号触发: Aroon Down(%.2f) > Aroon Up(%.2f)" % (aroon_down, aroon_up))
# 记录指标值,可以在回测图表中查看
record(Aroon_Up=aroon_up, Aroon_Down=aroon_down)
Q&A
Q1: 为什么代码中计算 days_since_high 使用了 (g.N - 1) - highs.argmax()?
A1: attribute_history 返回的数据是按时间顺序排列的数组。假设 g.N=25,数组索引范围是 0 到 24。索引 24 代表最近的一天(昨天)。如果最高价出现在索引 24,说明距离最高价的天数是 0 天。公式 (25 - 1) - 24 = 0 正好符合定义。
Q2: 这个策略适合什么类型的市场?
A2: Aroon 是一个典型的趋势指标。它在单边上涨或下跌的趋势行情中表现较好,但在震荡市(Aroon Up 和 Aroon Down 都在 50 以下纠缠时)容易产生频繁的买卖信号,导致磨损。
Q3: 如何修改策略以操作多只股票?
A3: 可以将 g.security 修改为一个列表(例如 get_index_stocks('000300.XSHG')),然后在 market_open 函数中使用 for 循环遍历这个列表,对每只股票分别计算指标和下单。同时需要注意资金分配(例如每只股票分配总资金的 1/10)。