🚀 AI 一键生成 joinquant 策略代码

JoinQuant 期货策略实例:构建一个简单的螺纹钢双均线趋势跟踪策略

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

问题描述

请用 Python 给我写一个螺纹钢期货的趋势跟踪策略,使用均线系统来判断方向。

解决方案

这是一个基于聚宽(JoinQuant)平台的螺纹钢(RB)期货趋势跟踪策略。

策略思路

  1. 标的选择:选取螺纹钢期货的主力合约(get_dominant_future),并自动处理主力合约换月。
  2. 核心逻辑:双均线策略(Golden Cross/Death Cross)。
    • 做多信号:短期均线(如10日)上穿长期均线(如30日)。
    • 做空信号:短期均线下穿长期均线。
    • 平仓逻辑:趋势反转时,先平掉原有仓位,再反向开仓。
  3. 资金管理:每次开仓使用账户可用资金的一定比例(如 30%),防止爆仓。
  4. 移仓换月:每日检查持仓,如果持有的合约不再是主力合约,则强制平仓,并在新主力合约上按信号开仓。

策略代码

# -*- coding: utf-8 -*-
from jqdata import *

def initialize(context):
    """
    初始化函数,设定基准、手续费、全局变量等
    """
    # 设定基准为螺纹钢主力连续合约
    set_benchmark('RB9999.XSGE')
    
    # 开启动态复权模式(真实价格)
    set_option('use_real_price', True)
    
    # 过滤掉order系列API产生的比error级别低的log
    log.set_level('order', 'error')
    
    # 设定期货交易手续费(根据实际情况调整,这里设为万分之1)
    set_order_cost(OrderCost(open_commission=0.0001, 
                             close_commission=0.0001, 
                             close_today_commission=0.0001), type='futures')
    
    # 设定保证金比例(这里设为15%,具体视交易所标准而定)
    set_option('futures_margin_rate', 0.15)
    
    # 定义全局变量
    g.future_code = 'RB'       # 品种代码:螺纹钢
    g.short_window = 10        # 短期均线周期
    g.long_window = 30         # 长期均线周期
    g.position_ratio = 0.3     # 每次开仓资金比例
    
    # 每天开盘时运行
    run_daily(trade_func, time='open')

def trade_func(context):
    """
    交易主函数
    """
    # 1. 获取当前日期的主力合约代码
    dom_contract = get_dominant_future(g.future_code)
    
    # 2. 移仓换月处理:检查持仓,如果持有非主力合约,则平仓
    # 遍历多头持仓
    for security in list(context.portfolio.long_positions.keys()):
        # 如果持仓品种是螺纹钢,但不是当前主力合约
        if security.startswith(g.future_code) and security != dom_contract:
            order_target(security, 0, side='long')
            log.info("移仓换月:平掉旧合约多单 %s" % security)
            
    # 遍历空头持仓
    for security in list(context.portfolio.short_positions.keys()):
        if security.startswith(g.future_code) and security != dom_contract:
            order_target(security, 0, side='short')
            log.info("移仓换月:平掉旧合约空单 %s" % security)

    # 3. 获取行情数据
    # 获取过去 g.long_window + 2 天的收盘价,确保数据足够计算均线
    # 注意:这里直接获取主力合约的数据
    hist_data = attribute_history(dom_contract, g.long_window + 2, '1d', ['close'])
    close_prices = hist_data['close']
    
    # 如果数据长度不足,无法计算均线,则跳过
    if len(close_prices) < g.long_window:
        return

    # 4. 计算均线
    # 短期均线
    ma_short = close_prices[-g.short_window:].mean()
    # 长期均线
    ma_long = close_prices[-g.long_window:].mean()
    
    # 获取当前主力合约的持仓情况
    long_pos = context.portfolio.long_positions[dom_contract].total_amount
    short_pos = context.portfolio.short_positions[dom_contract].total_amount
    
    # 获取可用资金
    cash = context.portfolio.available_cash
    
    # 5. 交易逻辑
    # 情况A:短均线 > 长均线 (看多)
    if ma_short > ma_long:
        # 如果有空单,先平空
        if short_pos > 0:
            order_target(dom_contract, 0, side='short')
            log.info("趋势转多:平空单 %s" % dom_contract)
        
        # 如果没有多单,则开多
        if long_pos == 0:
            # 按资金比例开仓
            order_value(dom_contract, cash * g.position_ratio, side='long')
            log.info("趋势转多:开多单 %s" % dom_contract)

    # 情况B:短均线 < 长均线 (看空)
    elif ma_short < ma_long:
        # 如果有多单,先平多
        if long_pos > 0:
            order_target(dom_contract, 0, side='long')
            log.info("趋势转空:平多单 %s" % dom_contract)
            
        # 如果没有空单,则开空
        if short_pos == 0:
            # 按资金比例开仓
            order_value(dom_contract, cash * g.position_ratio, side='short')
            log.info("趋势转空:开空单 %s" % dom_contract)

代码关键点解析

  1. get_dominant_future('RB'):

    • 这是期货策略最关键的函数。它会自动返回当前日期的主力合约代码(例如 RB2405.XSGE)。
    • 策略中包含了一个循环检查,如果账户里持有旧的主力合约(例如上个月的主力),会自动将其平仓,实现“移仓换月”。
  2. attribute_history:

    • 用于获取历史收盘价。这里我们获取了比长期均线稍多几天的数据,以防计算边界问题。
  3. order_target vs order_value:

    • order_target(security, 0, side='...'): 用于将仓位调整为0,即平仓。
    • order_value(security, cash, side='...'): 用于按金额下单。这里使用 cash * g.position_ratio 来控制仓位,避免满仓操作导致风险过大。
  4. side='long' / side='short':

    • 期货交易必须指定方向。long 代表多头(买入开仓/卖出平仓),short 代表空头(卖出开仓/买入平仓)。

常见问题 (Q&A)

Q1: 为什么使用 RB9999 作为基准,但交易时用 get_dominant_future?
A: RB9999 是聚宽合成的指数或主力连续数据,适合用来观察大趋势或作为回测的业绩基准。但在实盘或模拟交易中,你必须对具体的合约(如 RB2410.XSGE)下单,交易所不支持直接对 RB9999 下单。

Q2: 策略中的 g.position_ratio = 0.3 是什么意思?
A: 这意味着每次开仓只使用账户可用资金的 30%。期货自带杠杆(通常 10倍左右),全仓交易(100%资金)风险极高,一旦方向判断错误极易爆仓。30% 是一个相对稳健的起始仓位。

Q3: 如何调整均线参数?
A: 修改 initialize 函数中的 g.short_window (短期) 和 g.long_window (长期) 即可。例如改为 5日和 20日均线。

Q4: 这个策略适合高频交易吗?
A: 不适合。这是一个日线级别的趋势策略,交易频率较低。如果需要更高频,需要将 run_daily 改为 run_daily(..., time='every_bar') 并修改数据获取频率为分钟级。