🚀 AI 一键生成 joinquant 策略代码

JoinQuant 平台如何利用 run_monthly 实现月末自动调仓?

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

问题描述

如何让策略只在每个月的最后一个交易日运行?

解决方案

在 JoinQuant(聚宽)平台中,让策略只在每个月的最后一个交易日运行,最简单且推荐的方法是使用 run_monthly 定时运行函数,并将参数 monthday 设置为 -1

核心方法:使用 run_monthly

initialize 函数中调用 run_monthly,具体设置如下:

  • func: 你想要执行的交易函数名称。
  • monthday: 设置为 -1。在聚宽 API 中,负数表示倒数第几个交易日,-1 即代表该月的最后一个交易日。
  • time: 设置具体的运行时间(如 '09:30' 或 '14:50')。

完整代码示例

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

def initialize(context):
    # 设置基准
    set_benchmark('000300.XSHG')
    # 开开启真实价格
    set_option('use_real_price', True)
    
    # 设定定时运行:
    # monthday=-1 表示每月的最后一个交易日
    # time='09:30' 表示在开盘时运行(也可以设为 '14:50' 进行尾盘调仓)
    run_monthly(monthly_adjustment, monthday=-1, time='09:30')

def monthly_adjustment(context):
    """
    该函数只会在每个月的最后一个交易日被调用
    """
    log.info("当前时间: %s,是本月最后一个交易日,开始执行调仓逻辑" % context.current_dt)
    
    # --- 下面写你的策略逻辑 ---
    # 示例:获取当前持仓并简单的打印
    positions = context.portfolio.positions
    if len(positions) > 0:
        log.info("当前持仓: ", positions.keys())
    else:
        log.info("当前空仓")
        
    # 示例下单:买入平安银行 100 股
    # order('000001.XSHE', 100)

为什么推荐这种方式?

  1. 自动处理节假日:聚宽的 run_monthly 基于交易日历。如果某个月的31号是周日,30号是周六,那么“最后一个交易日”会自动识别为29号(周五)。你不需要自己写复杂的日期判断逻辑。
  2. 代码简洁:只需要一行代码即可实现,避免了在 handle_data 中进行繁琐的 if 判断。
  3. 回测效率高:定时运行函数比每日轮询检查日期的效率更高。

Q&A 常见问题解答

Q1: 如果我想在每个月倒数第二个交易日运行怎么办?
A:run_monthly 中的 monthday 参数设置为 -2 即可。

Q2: time 参数可以设置为收盘前吗?
A: 可以。如果你希望在月末收盘前进行调仓(以利用当天的收盘价作为结算参考),可以将 time 设置为 '14:50''14:55'

Q3: 如果我在 handle_data 中想判断今天是不是月末怎么办?
A: 虽然不推荐,但可以通过获取下一交易日来判断。逻辑是:如果“下一个交易日”的月份与“当前日期”的月份不同,则今天就是本月最后一个交易日。

# 仅作逻辑参考,推荐使用 run_monthly
def check_is_month_end(date):
    # 获取包含今天在内的未来2个交易日
    days = get_trade_days(start_date=date, count=2)
    if len(days) < 2:
        return True # 回测最后一天
    # 如果明天的月份不等于今天的月份,说明今天是月末
    return days[0].month != days[1].month

Q4: run_monthly 会在回测的第一天运行吗?
A: 这取决于回测的开始日期。如果回测开始日期恰好是该月的最后一个交易日,且开始时间早于你设定的 time,它就会运行。否则,它会等到下一个月的最后一个交易日才运行。