枢轴点反转策略

一、交易策略解释

核心思想

枢轴点反转策略基于价格围绕关键支撑位和阻力位波动的市场特性。该策略认为,当价格达到计算出的支撑位或阻力位后,有较大概率发生反转。 具体而言,当价格下跌至支撑位附近并开始回升时,可能是做多信号;当价格上涨至阻力位附近并开始下跌时,可能是做空信号。这种策略特别适合震荡市场,能够捕捉价格在一定区间内的波动。

该策略通过前一交易日的高点、低点和收盘价计算枢轴点,并衍生出多个支撑位和阻力位,这些价格水平共同构成了一个完整的交易系统,能够捕捉市场中的价格反转信号。

理论基础

枢轴点策略的理论基础主要来自于市场微观结构和价格行为理论:

  • 供需平衡点理论:枢轴点代表了市场参与者认为的价格公允水平,价格围绕这一水平波动。

  • 价格记忆效应:市场对历史价格水平有"记忆",昨日的高低点对今日交易有重要影响。

  • 市场惯性与反转:市场在短期内往往遵循惯性运动原则,但达到极限点后会发生反转。

多项学术研究表明,支撑位和阻力位在短期内对价格走势具有显著影响。Lo和MacKinlay(1999)的研究表明,市场在短期内存在可预测性,这为反转策略提供了理论支持。同时,专业交易者长期经验也证实,在震荡市场中,价格往往在关键水平附近发生反转。

策略适用场景

  • 市场类型:震荡市或区间震荡市场,价格在一定范围内波动。

  • 波动特征:日内波动较大,但总体趋势不明显的市场。

  • 流动性:流动性充足的市场,如主力合约期货。

  • 交易时间框架:短线交易,特别是日内交易。

  • 品种选择:波动较大的商品期货,如螺纹钢、铜、原油等。

二、天勤介绍

天勤平台概述

天勤(TqSdk)是一个由信易科技开发的开源量化交易系统,为期货、期权等衍生品交易提供专业的量化交易解决方案。平台具有以下特 点:

  • 丰富的行情数据 提供所有可交易合约的全部Tick和K线数据,基于内存数据库实现零延迟访问。
  • 一站式的解决方案 从历史数据分析到实盘交易的完整工具链,打通开发、回测、模拟到实盘的全流程。
  • 专业的技术支持 近百个技术指标源码,深度集成pandas和numpy,采用单线程异步模型保证性能。

策略开发流程

  • 环境准备
    • 安装Python环境(推荐Python 3.6或以上版本)
    • 安装tqsdk包:pip install tqsdk
    • 注册天勤账户获取访问密钥
  • 数据准备
    • 订阅近月与远月合约行情
    • 获取历史K线或者Tick数据(用于分析与行情推进)
  • 策略编写
    • 设计信号生成逻辑(基于价差、均值和标准差)
    • 编写交易执行模块(开仓、平仓逻辑)
    • 实现风险控制措施(止损、资金管理)
  • 回测验证
    • 设置回测时间区间和初始资金
    • 运行策略获取回测结果
    • 分析绩效指标(胜率、收益率、夏普率等)
  • 策略优化
    • 调整参数(标准差倍数、窗口大小等)
    • 添加过滤条件(成交量、波动率等)
    • 完善风险控制机制

三、天勤实现策略

策略原理

枢轴点反转策略基于前一交易日的高点、低点和收盘价计算出关键价格水平:

枢轴点(Pivot) = (High + Low + Close) / 3
第一支撑位(S1) = (2 × P) - High
第一阻力位(R1) = (2 × P) - Low
第二支撑位(S2) = P - (High - Low)
第二阻力位(R2) = P + (High - Low)

在实际应用中,我们还可以增加更多支撑位和阻力位:

第三支撑位(S3) = S1 - (High - Low)
第三阻力位(R3) = R1 + (High - Low)

这些价格水平构成了交易信号的基础:

  1. 反转情景:当价格接近支撑位或阻力位并出现反转迹象时入场

  2. 反弹交易:从支撑位附近做多,目标价格为枢轴点或阻力位

  3. 回落交易:从阻力位附近做空,目标价格为枢轴点或支撑位

交易逻辑

做多信号:

  • 当价格下跌到第一支撑位(S1)附近并开始反弹时,开仓做多。

  • 当价格下跌到第二支撑位(S2)附近并开始反弹时,开仓做多。

做空信号:

  • 当价格上涨到第一阻力位(R1)附近并开始回落时,开仓做空。

  • 当价格上涨到第二阻力位(R2)附近并开始回落时,开仓做空。

入场确认:

  • 可结合K线形态(如上升锤形线、吞没形态等)确认反转信号。

  • 可使用RSI等指标确认超买超卖状态,增强信号可靠性。

平仓规则:

  • 反向位置平仓:做多单在接近阻力位时平仓,做空单在接近支撑位时平仓。

  • 日内交易在收盘前15分钟平仓。

  • 或者当价格达到预设止损水平时平仓。

止损设置:

  • 做多止损设置在支撑位下方10-20个点。

  • 做空止损设置在阻力位上方10-20个点。

回测

回测初始设置

  • 测试周期: 2023 年 2 月 10 日 - 2023 年 3 月 15 日
  • 交易品种: SHFE.cu2309
  • 初始资金: 1000万元

回测结果

上述回测累计收益走势图

完整代码示例

#!/usr/bin/env python
# -*- coding: utf-8 -*-
__author__ = "Chaos"

from datetime import date
from tqsdk import TqApi, TqAuth, TqBacktest, TargetPosTask, BacktestFinished
from tqsdk.tafunc import time_to_str

# ===== 全局参数设置 =====
SYMBOL = "SHFE.cu2309"
POSITION_SIZE = 100  
START_DATE = date(2023, 2, 10)  # 回测开始日期
END_DATE = date(2023, 3, 15)  # 回测结束日期

# 策略参数
REVERSAL_CONFIRM = 50  # 反转确认点数
STOP_LOSS_POINTS = 100  # 止损点数

# ===== 全局变量 =====
current_direction = 0  # 当前持仓方向:1=多头,-1=空头,0=空仓
entry_price = 0  # 开仓价格
stop_loss_price = 0  # 止损价格
prev_high = 0  # 前一日最高价
prev_low = 0  # 前一日最低价
prev_close = 0  # 前一日收盘价

# ===== 策略开始 =====
print("开始运行枢轴点反转策略...")

# 创建API实例
api = TqApi(backtest=TqBacktest(start_dt=START_DATE, end_dt=END_DATE),
            auth=TqAuth("快期账号", "快期密码"))

# 订阅合约的K线数据
klines = api.get_kline_serial(SYMBOL, 60 * 60 * 24)  # 日线数据

# 创建目标持仓任务
target_pos = TargetPosTask(api, SYMBOL)

def calculate_pivot_points(high, low, close):
    """计算枢轴点及支撑阻力位"""
    pivot = (high + low + close) / 3
    r1 = (2 * pivot) - low
    s1 = (2 * pivot) - high
    r2 = pivot + (high - low)
    s2 = pivot - (high - low)
    r3 = r1 + (high - low)
    s3 = s1 - (high - low)
    return pivot, r1, r2, r3, s1, s2, s3

try:
    while True:
        # 等待更新
        api.wait_update()

        # 如果K线有更新
        if api.is_changing(klines.iloc[-1], "datetime"):
            # 确保有足够的数据
            if len(klines) < 2:
                continue

            # 获取当前价格和前一日数据
            current_price = klines.close.iloc[-1].item()
            current_high = klines.high.iloc[-1].item()
            current_low = klines.low.iloc[-1].item()
            prev_close = klines.close.iloc[-2].item()

            # 如果是新的一天,更新前一日数据
            if klines.datetime.iloc[-1] != klines.datetime.iloc[-2]:
                prev_high = klines.high.iloc[-2].item()
                prev_low = klines.low.iloc[-2].item()
                prev_close = klines.close.iloc[-2].item()
                print(f"\n新的一天开始:")
                print(f"前一日数据 - 最高价: {prev_high:.2f}, 最低价: {prev_low:.2f}, 收盘价: {prev_close:.2f}")

            # 计算枢轴点及支撑阻力位
            pivot, r1, r2, r3, s1, s2, s3 = calculate_pivot_points(prev_high, prev_low, prev_close)

            # 获取最新数据
            current_timestamp = klines.datetime.iloc[-1]
            current_datetime = time_to_str(current_timestamp)

            # 打印当前状态
            print(f"\n日期: {current_datetime}")
            print(f"当前价格: {current_price:.2f}")
            print(f"枢轴点: {pivot:.2f}")
            print(f"支撑位: S1={s1:.2f}, S2={s2:.2f}, S3={s3:.2f}")
            print(f"阻力位: R1={r1:.2f}, R2={r2:.2f}, R3={r3:.2f}")

            # 打印信号条件
            print("\n多头信号条件:")
            print(f"1. 价格在S1附近: {current_price <= s1 + REVERSAL_CONFIRM and current_price > s1 - REVERSAL_CONFIRM}")
            print(f"2. 价格高于当日最低价: {current_price > klines.low.iloc[-1].item()}")
            print(f"3. 价格高于前一日收盘价: {current_price > prev_close}")

            print("\n空头信号条件:")
            print(f"1. 价格在R1附近: {current_price >= r1 - REVERSAL_CONFIRM and current_price < r1 + REVERSAL_CONFIRM}")
            print(f"2. 价格低于当日最高价: {current_price < klines.high.iloc[-1].item()}")
            print(f"3. 价格低于前一日收盘价: {current_price < prev_close}")

            # ===== 交易逻辑 =====

            # 空仓状态 - 寻找开仓机会
            if current_direction == 0:
                # 多头开仓条件:价格低于S1
                if current_price < s1:
                    current_direction = 1
                    target_pos.set_target_volume(POSITION_SIZE)
                    entry_price = current_price
                    stop_loss_price = entry_price - STOP_LOSS_POINTS
                    print(f"\n多头开仓信号! 开仓价: {entry_price:.2f}, 止损价: {stop_loss_price:.2f}")

                # 空头开仓条件:价格高于R1
                elif current_price > r1:
                    current_direction = -1
                    target_pos.set_target_volume(-POSITION_SIZE)
                    entry_price = current_price
                    stop_loss_price = entry_price + STOP_LOSS_POINTS
                    print(f"\n空头开仓信号! 开仓价: {entry_price:.2f}, 止损价: {stop_loss_price:.2f}")

            # 多头持仓 - 检查平仓条件
            elif current_direction == 1:
                # 止盈条件:价格回到枢轴点或更高
                if current_price >= pivot:
                    profit = (current_price - entry_price) * POSITION_SIZE
                    target_pos.set_target_volume(0)
                    current_direction = 0
                    print(f"多头止盈平仓: 价格={current_price:.2f}, 盈利={profit:.2f}")
                # 止损条件
                elif current_price <= stop_loss_price:
                    loss = (entry_price - current_price) * POSITION_SIZE
                    target_pos.set_target_volume(0)
                    current_direction = 0
                    print(f"多头止损平仓: 价格={current_price:.2f}, 亏损={loss:.2f}")

            # 空头持仓 - 检查平仓条件
            elif current_direction == -1:
                # 止盈条件:价格回到枢轴点或更低
                if current_price <= pivot:
                    profit = (entry_price - current_price) * POSITION_SIZE
                    target_pos.set_target_volume(0)
                    current_direction = 0
                    print(f"空头止盈平仓: 价格={current_price:.2f}, 盈利={profit:.2f}")
                # 止损条件
                elif current_price >= stop_loss_price:
                    loss = (current_price - entry_price) * POSITION_SIZE
                    target_pos.set_target_volume(0)
                    current_direction = 0
                    print(f"空头止损平仓: 价格={current_price:.2f}, 亏损={loss:.2f}")

except BacktestFinished as e:
    print("回测结束")
    api.close()