🚀 AI 一键生成 qmt 策略代码

基于线性回归斜率 (PLRC) 的趋势跟踪策略 Python 实现

qmt | 发布时间: 2025/12/30
以下内容由 EasyQuant 生成。

问题描述

怎么编写基于线性回归斜率的趋势策略?

解决方案

基于线性回归斜率的趋势策略是一种经典的动量策略。其核心逻辑是利用统计学中的线性回归方法,计算过去一段时间内价格走势的斜率(Slope)。

策略逻辑

  1. 计算斜率 ($k$):选取过去 $N$ 根 K 线的收盘价,利用最小二乘法拟合一条直线 $y = kx + b$。
    • $k > 0$:表示处于上升趋势。
    • $k < 0$:表示处于下降趋势。
  2. 交易信号
    • 买入信号:当斜率 $k$ 大于设定的正阈值(例如 0.05),认为上涨趋势确立,买入持仓。
    • 卖出信号:当斜率 $k$ 小于设定的负阈值(例如 -0.05)或跌破 0,认为趋势反转或结束,卖出平仓。

QMT 策略代码实现

以下是完整的 Python 策略代码。该代码使用了 numpy 库来进行线性拟合计算,并使用 get_market_data_ex 获取历史数据。

# -*- coding: gbk -*-
import numpy as np
import pandas as pd

def init(ContextInfo):
    """
    策略初始化函数
    """
    # 1. 设置策略参数
    ContextInfo.N = 20              # 线性回归计算周期(如过去20天)
    ContextInfo.slope_threshold = 0.1 # 斜率阈值,用于过滤震荡噪音
    ContextInfo.stock_list = ['600000.SH', '000001.SZ'] # 股票池示例
    
    # 2. 设置股票池
    ContextInfo.set_universe(ContextInfo.stock_list)
    
    # 3. 设置资金账号 (请替换为您的真实资金账号)
    ContextInfo.account_id = 'YOUR_ACCOUNT_ID' 
    ContextInfo.set_account(ContextInfo.account_id)
    
    # 4. 设置回测参数 (仅回测有效)
    ContextInfo.set_commission(0, [0.0001, 0.0001, 0.0003, 0.0003, 0, 5]) # 设置费率
    ContextInfo.capital = 1000000 # 初始资金

def handlebar(ContextInfo):
    """
    K线逐根运行函数
    """
    # 获取当前设置的股票池
    stock_list = ContextInfo.get_universe()
    
    # 获取当前周期 (例如 '1d')
    period = ContextInfo.period
    
    # 批量获取历史行情数据
    # 我们需要 N 个数据点来进行回归计算
    # count = ContextInfo.N 表示获取过去 N 根K线
    market_data = ContextInfo.get_market_data_ex(
        fields=['close'], 
        stock_code=stock_list, 
        period=period, 
        count=ContextInfo.N, 
        dividend_type='front' # 前复权
    )
    
    # 遍历每一只股票进行计算
    for stock in stock_list:
        # 获取该股票的 DataFrame 数据
        if stock not in market_data:
            continue
            
        df = market_data[stock]
        
        # 数据长度校验,如果数据不足 N 个,无法计算回归,跳过
        if len(df) < ContextInfo.N:
            continue
            
        # 提取收盘价序列
        close_prices = df['close'].values
        
        # --- 核心逻辑:计算线性回归斜率 ---
        # 创建 X 轴序列 [0, 1, 2, ..., N-1]
        x = np.arange(len(close_prices))
        # 创建 Y 轴序列 (收盘价)
        y = close_prices
        
        # 使用 numpy 的 polyfit 进行一次多项式拟合 (线性回归)
        # deg=1 表示一次方程 y = kx + b
        # 返回值 fit[0] 是斜率 k,fit[1] 是截距 b
        try:
            fit = np.polyfit(x, y, 1)
            slope = fit[0]
        except Exception as e:
            print(f"计算斜率出错 {stock}: {e}")
            continue
            
        # --- 交易逻辑 ---
        
        # 获取当前持仓信息
        position = get_position(stock, ContextInfo)
        
        # 1. 买入逻辑:斜率 > 阈值 且 当前无持仓
        if slope > ContextInfo.slope_threshold and position == 0:
            print(f"[{stock}] 触发买入信号,当前斜率: {slope:.4f} > 阈值: {ContextInfo.slope_threshold}")
            # 目标市值买入,例如调整仓位到 20% (假设资金足够分散)
            # 这里简单演示,全仓买入或固定比例买入
            order_target_percent(stock, 0.2, ContextInfo, ContextInfo.account_id)
            
        # 2. 卖出逻辑:斜率 < -阈值 (或跌破0) 且 当前有持仓
        # 这里设置为斜率转负即卖出,或者小于负阈值卖出,取决于激进程度
        elif slope < -ContextInfo.slope_threshold and position > 0:
            print(f"[{stock}] 触发卖出信号,当前斜率: {slope:.4f} < 阈值: -{ContextInfo.slope_threshold}")
            # 清仓
            order_target_percent(stock, 0, ContextInfo, ContextInfo.account_id)

def get_position(stock_code, ContextInfo):
    """
    辅助函数:获取某只股票的当前持仓数量
    """
    # 获取持仓对象列表
    positions = get_trade_detail_data(ContextInfo.account_id, 'stock', 'position')
    
    for pos in positions:
        if pos.m_strInstrumentID + '.' + pos.m_strExchangeID == stock_code:
            # 返回当前持仓量
            return pos.m_nVolume
    return 0

代码关键点解析

  1. 数据获取 (get_market_data_ex):

    • 使用 get_market_data_ex 是 QMT 推荐的方式,效率比旧接口高。
    • count=ContextInfo.N 确保我们获取了足够的数据点来进行回归分析。
    • dividend_type='front' 使用前复权数据,这对于计算历史趋势至关重要,避免因分红除权导致的价格跳空影响斜率计算。
  2. 线性回归计算 (np.polyfit):

    • 我们使用 numpy.polyfit(x, y, 1)。其中 x 是时间序列(0 到 N-1),y 是价格序列。
    • 参数 1 代表拟合一次函数(直线)。
    • 结果是一个数组,第一个元素即为斜率 $k$。
    • 斜率的含义:斜率代表了“平均每根 K 线价格变动的数值”。例如,斜率为 0.5 意味着在过去 N 天内,股价平均每天上涨 0.5 元。
  3. 阈值设定 (ContextInfo.slope_threshold):

    • 直接使用价格斜率有一个缺点:高价股(如贵州茅台)的斜率数值天然比低价股(如农业银行)大。
    • 优化建议:在实际应用中,建议对数据进行归一化处理。例如,对收盘价取对数,或者将斜率除以当前股价,将其转换为“涨跌幅斜率”,这样阈值就可以设置为百分比(如 0.01 代表平均每天涨 1%),从而适应不同价格的股票。
  4. 交易执行 (order_target_percent):

    • 使用 order_target_percent 可以方便地管理仓位。0.2 表示将该股票仓位调整至总资产的 20%。0 表示清仓。

常见问题 Q&A

Q: 为什么我的策略在回测时没有交易?
A: 请检查以下几点:

  1. ContextInfo.stock_list 是否包含了有效的股票代码。
  2. ContextInfo.slope_threshold 设置是否过大,导致很难触发信号。
  3. 数据是否下载完整(在“数据管理”中补充历史数据)。

Q: 如何让策略对高价股和低价股一视同仁?
A: 修改计算逻辑,对价格进行归一化。将 y = close_prices 改为 y = close_prices / close_prices[0](以区间第一天价格为基准)。这样计算出的斜率代表的是相对于起始价格的增长率。

Q: 这个策略适合什么周期?
A: 线性回归策略通常在趋势明显的周期表现较好,如日线(1d)或 60分钟线(60m)。在震荡市或极短周期(如 1分钟)中可能会产生大量假信号。