Py学习  »  Python

年化收益26.6%, 最大回撤5.06%, 年化夏普率1.36,aroon指标在期货里的应用案例,附python代码

七年实现财富自由 • 2 月前 • 140 次点击  
原创内容第970篇,专注AGI+,AI量化投资、个人成长与财富自由。
从量化指标的角度,有趋势指标和震荡指标,通过历史的价量数据去描述价格运动的状态。——部分有统计学的逻辑基础。
咱们在使用一个或多个指标时,一定要了解指标背后的计算公式,最好自己上手计算一下,这样就会理解这个指标的应用,适用场景及局限性。
今天咱们来说说aroon指标,并基于这个指标做一些回测。
aroon指标(又称阿隆指标)是由技术分析大师图莎尔·钱德(Tushar Chande)于1995年提出的趋势跟踪类指标。其名称源于梵文“Aroon”,意为“黎明之光”,寓意其能早期探测趋势的萌芽
相较于MACD、RSI等传统指标,Aroon因使用者较少且侧重“时间维度”而非价格波动,被认为在趋势识别上更具独特性和稳定性。
  1. Aroon Up(上升线)
    = [(N - 距离最近最高价的天数) / N] × 100
    衡量当前价格与近期最高价的“时间距离”,数值越高说明上升趋势越强18

  • 示例:若周期N=25天,今日创最高价,则Aroon Up = 100;若最高价出现在10天前,则Aroon Up = (25-10)/25×100 = 608

  • Aroon Down(下降线)
    = [(N - 距离最近最低价的天数) / N] × 100
    衡量当前价格与近期最低价的“时间距离”,数值越高说明下降趋势越强49

  • Aroon Oscillator(震荡线)
    = Aroon Up - Aroon Down
    用于量化多空力量差值,正值表示上升主导,负值表示下降主导。

  • 策略逻辑:

    开仓信号:

    该策略使用两种主要的开仓信号:

    • 交叉信号
      • 多头信号:Aroon Up从下方穿越Aroon Down
      • 空头信号:Aroon Down从下方穿越Aroon Up

    平仓信号:

    平仓信号基于Aroon指标的反向交叉:

    • 平多信号:Aroon Down从下方穿越Aroon Up
    • 平空信号:Aroon Up从下方穿越Aroon Down

    这些反向信号往往代表趋势可能发生转变,是获利了结的好时机。

    止损机制:

    该策略使用基于百分比的固定止损:

    • 止损百分比设定为1.2%(STOP_LOSS_PCT = 1.2)
    • 多头止损:当价格下跌超过入场价格的1.2%时触发
    • 空头止损:当价格上涨超过入场价格的1.2%时触发
    from tqsdk import TqApi, TqAuth, TqBacktest, TargetPosTask, BacktestFinishedimport pandas as pdfrom datetime import date
    from tqsdk import TqApi, TqAuth,TqBacktest,TargetPosTaskimport pandas as pdfrom datetime import dateimport osdef get_env_var(name, default=None):    value = os.environ.get(name)    if value is None and default is None:        raise EnvironmentError(f"环境变量 {name} 未设置")     return value or defaultusername = get_env_var('TQ_USERNAME')password = get_env_var('TQ_PASSWORD')
    # ===== 全局参数设置 =====SYMBOL = "SHFE.au2306"  # 黄金期货合约POSITION_SIZE = 30  # 持仓手数START_DATE = date(2023220)  # 回测开始日期END_DATE = date(202355)  # 回测结束日期
    # Aroon指标参数AROON_PERIOD = 10  # Aroon计算周期AROON_UPPER_THRESHOLD = 75  # Aroon上线阈值AROON_LOWER_THRESHOLD = 25  # Aroon下线阈值
    # 风控参数STOP_LOSS_PCT = 1.2  # 止损百分比
    # ===== 全局变量 =====position = 0  # 当前持仓entry_price = 0  # 入场价格trades = []  # 交易记录
    # ===== 主程序 =====print(f"开始回测 {SYMBOL} 的Aroon指标策略...")print(f"参数: Aroon周期={AROON_PERIOD}, 上阈值={AROON_UPPER_THRESHOLD}, 下阈值={AROON_LOWER_THRESHOLD}")print(f"回测期间: {START_DATE} 至 {END_DATE}")
    try:    # 创建API实例    api = TqApi(backtest=TqBacktest(start_dt=START_DATE, end_dt=END_DATE),                auth=TqAuth(username, password))
        # 订阅K线数据    klines = api.get_kline_serial(SYMBOL, 60 * 60 * 24)  # 日K线    target_pos = TargetPosTask(api, SYMBOL)
        # 主循环    while True:        api.wait_update()
            if api.is_changing(klines.iloc[-1], "datetime"):            # 确保有足够的数据            if len(klines) < AROON_PERIOD + 10:                continue
                # ===== 计算Aroon指标 =====            # 找出最近N周期内最高价和最低价的位置            klines['rolling_high'] = klines['high'].rolling(window=AROON_PERIOD).max()            klines['rolling_low'] = klines['low'].rolling(window=AROON_PERIOD).min()
                # 初始化Aroon Up和Aroon Down数组            aroon_up = []            aroon_down = []
                # 遍历计算每个时间点的Aroon值            for i in range(len(klines)):                if i < AROON_PERIOD - 1:                    aroon_up.append(0)                    aroon_down.append(0)                    continue
                    period_data = klines.iloc[i - AROON_PERIOD + 1:i + 1]                # 明确指定skipna=True来处理NaN值                high_idx = period_data['high'].fillna(float('-inf')).argmax()                low_idx = period_data['low'].fillna(float('inf')).argmin()
                    days_since_high = i - (i - AROON_PERIOD + 1 + high_idx)                days_since_low = i - (i - AROON_PERIOD + 1 + low_idx)
                    aroon_up.append(((AROON_PERIOD - days_since_high) / AROON_PERIOD) * 100)                aroon_down.append(((AROON_PERIOD - days_since_low) / AROON_PERIOD) * 100)
                # 将Aroon值添加到klines            klines['aroon_up'] = aroon_up            klines['aroon_down'] = aroon_down
                # 计算Aroon Oscillator (可选)            klines['aroon_osc'] = klines[ 'aroon_up'] - klines['aroon_down']
                # 获取当前和前一个周期的数据            current_price = float(klines.close.iloc[-1])            current_time = pd.to_datetime(klines.datetime.iloc[-1], unit='ns')            current_aroon_up = float(klines.aroon_up.iloc[-1])            current_aroon_down = float(klines.aroon_down.iloc[-1])
                prev_aroon_up = float(klines.aroon_up.iloc[-2])            prev_aroon_down = float(klines.aroon_down.iloc[-2])
                # 输出当前指标值,帮助调试            print(f"当前K线: {current_time.strftime('%Y-%m-%d')}, 价格: {current_price:.2f}")            print(f"Aroon Up: {current_aroon_up:.2f}, Aroon Down: {current_aroon_down:.2f}")
                # ===== 止损检查 =====            if position != 0 and entry_price != 0:                if position > 0:  # 多头止损                    profit_pct = (current_price / entry_price - 1) * 100                    if profit_pct < -STOP_LOSS_PCT:                        print(f"触发止损: 当前价格={current_price}, 入场价={entry_price}, 亏损={profit_pct:.2f}%")                        target_pos.set_target_volume(0)                        trades.append({                            'type''止损平多',                            'time': current_time,                            'price': current_price,                            'profit_pct': profit_pct                        })                        print(f"止损平多: {current_time}, 价格: {current_price:.2f}, 亏损: {profit_pct:.2f}%")                        position = 0                        entry_price = 0                        continue
                    elif position 0:  # 空头止损                    profit_pct = (entry_price / current_price - 1) * 100                    if profit_pct < -STOP_LOSS_PCT:                        print(f"触发止损: 当前价格={current_price}, 入场价={entry_price}, 亏损={profit_pct:.2f}%")                        target_pos.set_target_volume(0)                        trades.append({                            'type''止损平空',                            'time': current_time,                            'price': current_price,                            'profit_pct': profit_pct                        })                        print(f"止损平空: {current_time}, 价格: {current_price:.2f}, 亏损:  {profit_pct:.2f}%")                        position = 0                        entry_price = 0                        continue
                # ===== 交易信号判断 =====            # 1. Aroon交叉信号            aroon_cross_up = prev_aroon_up < prev_aroon_down and current_aroon_up > current_aroon_down            aroon_cross_down = prev_aroon_up > prev_aroon_down and current_aroon_up < current_aroon_down
                # 2. 强势信号            strong_up = current_aroon_up > AROON_UPPER_THRESHOLD and current_aroon_down < AROON_LOWER_THRESHOLD            strong_down = current_aroon_down > AROON_UPPER_THRESHOLD and current_aroon_up < AROON_LOWER_THRESHOLD
                # ===== 交易决策 =====            if position == 0:  # 空仓状态                # 多头信号                if aroon_cross_up or strong_up:                    position = POSITION_SIZE                    entry_price = current_price                    target_pos.set_target_volume(position)                    signal_type = "交叉" if aroon_cross_up else "强势"                    trades.append({                        'type''开多',                        'time': current_time,                        'price': current_price,                        'signal': signal_type                    })                    print(f"开多仓: {current_time}, 价格: {current_price:.2f}, 信号: Aroon {signal_type}")
                    # 空头信号                elif aroon_cross_down or strong_down:                    position = -POSITION_SIZE                    entry_price = current_price                    target_pos.set_target_volume(position)                    signal_type = "交叉" if aroon_cross_down else "强势"                    trades.append({                        'type''开空',                        'time': current_time,                        'price': current_price,                        'signal': signal_type                    })                    print(f"开空仓: {current_time}, 价格: {current_price:.2f}, 信号: Aroon {signal_type}")
                elif position > 0:  # 持有多头                # 平多信号                if aroon_cross_down:                    profit_pct = (current_price / entry_price - 1) * 100                    target_pos.set_target_volume(0)                    trades.append({                        'type''平多',                        'time': current_time,                        'price': current_price,                        'profit_pct': profit_pct                    })                    print(f"平多仓: {current_time}, 价格: {current_price:.2f}, 盈亏: {profit_pct:.2f}%")                    position = 0                    entry_price = 0
                elif position 0:  # 持有空头                # 平空信号                if aroon_cross_up:                    profit_pct = (entry_price / current_price - 1) * 100                    target_pos.set_target_volume(0)                     trades.append({                        'type''平空',                        'time': current_time,                        'price': current_price,                        'profit_pct': profit_pct                    })                    print(f"平空仓: {current_time}, 价格: {current_price:.2f}, 盈亏: {profit_pct:.2f}%")                    position = 0                    entry_price = 0
    except BacktestFinished as e:    print("回测结束")    api.close()
    今天代码所在的位置:
    代码已经提交:

    代码和数据下载:AI量化实验室——2025量化投资的星辰大海

    AI量化实验室 星球,已经运行三年多,1700+会员。

    aitrader代码,因子表达式引擎、遗传算法(Deap)因子挖掘引等,支持vnpy,qlib,backtrader和bt引擎,内置多个年化30%+的策略,每周五迭代一次,代码和数据在星球全部开源。

    点击 “查看原文”,直接访问策略集合

    扩展  •  历史文章   

    EarnMore(赚得更多)基于RL的投资组合管理框架:一致的股票表示,可定制股票池管理。(附论文+代码)

    机器学习驱动的策略开发通过流程 | 普通人阶层跃迁的可能路径?

    年化30.24%,最大回撤19%,综合动量多因子评分策略再升级(python代码+数据)

    三秒钟创建一个年化28%,夏普比1.25的策略(python系统已开放源代码下载)

    6年年化收益46%,最大回撤率为16%的策略(附python代码)

    Python社区是高质量的Python/Django开发社区
    本文地址:http://www.python88.com/topic/185589