问题描述
解决方案
在聚宽(JoinQuant)平台中,处理持仓股票分红(现金分红或送转股)的最佳方式是开启“真实价格(动态复权)模式”。
开启该模式后,系统会自动处理分红派息,无需您手动编写复杂的计算逻辑。
以下是详细的处理机制和代码实现:
1. 核心设置:开启真实价格模式
在 initialize 函数中调用 set_option('use_real_price', True)。
- 未开启时(默认):使用的是前复权价格。历史价格会被调整以消除分红影响,分红发生时账户现金不会增加,持仓数量也不会变化(除非发生拆合),这不符合真实交易场景。
- 开启后(推荐):使用的是真实价格。
- 现金分红:在除权除息日,分红现金(扣税后)会自动打入您的账户(
available_cash增加),股价会自然回落。 - 送转股:持仓数量(
total_amount)会自动增加,股价会相应降低。
- 现金分红:在除权除息日,分红现金(扣税后)会自动打入您的账户(
2. 自动处理的细节
当您设置了 set_option('use_real_price', True) 后,系统行为如下:
- 除权除息:系统会在除权除息日自动调整您的持仓数量和可用资金。
- 税费扣除:
- 在回测和模拟交易中,由于难以精确追踪每一笔买入的持仓时长(先进先出原则),系统通常统一按照 20% 的税率扣除红利税。
- 分红现金 = 每股分红金额 × 持仓股数 × (1 - 20%)。
- 资金到账:现金会在除权除息日开盘前自动加到账户的
available_cash中,您可以在当天的交易中直接使用这笔资金。
3. 代码示例
以下是一个完整的策略示例,展示如何开启该模式,以及如何(可选地)使用 on_event 回调函数来监控分红事件。
# -*- coding: utf-8 -*-
from jqdata import *
def initialize(context):
# 1. 设定基准
set_benchmark('000300.XSHG')
# 2. 【关键步骤】开启动态复权模式(真实价格)
# 开启后,分红、送股将自动到账,股价使用真实历史价格
set_option('use_real_price', True)
# 设置手续费等其他配置
set_order_cost(OrderCost(close_tax=0.001, open_commission=0.0003, close_commission=0.0003, min_commission=5), type='stock')
# 举例:买入一只历史上分红较多的股票(如格力电器)
g.security = '000651.XSHE'
run_daily(market_open, time='09:30')
def market_open(context):
if g.security not in context.portfolio.positions:
order_value(g.security, 100000)
# 【可选】高级功能:使用事件回调监听分红
# 如果您需要在分红发生时执行特定逻辑(如收到分红立即再投资),可以使用此函数
def on_event(context, event):
# 检查是否是分红事件
if isinstance(event, DividendsEvent):
log.info("触发分红事件!")
log.info("标的: %s" % event.security)
# event.dividends 是一个列表,包含分红信息
# 结构示例: [{'date': datetime.date(2023, 6, 1), 'bonus_pre_tax': 0.5, 'scale_factor': 0}]
for div in event.dividends:
log.info("分红详情: %s" % str(div))
# 示例逻辑:如果收到现金分红,打印当前可用资金
log.info("当前可用资金(含分红): %s" % context.portfolio.available_cash)
4. 常见问题说明
- 为什么回测结果和不开启真实价格时不一样?
不开启真实价格时,使用的是前复权数据,历史股价被“压低”了。开启真实价格后,买入同样金额的股票,获得的股数可能不同(因为价格不同),且分红会以现金形式回流,这更接近真实实盘的收益曲线。 - 能否不扣税?
在回测环境中,税率计算是系统固定的(通常为20%),无法通过简单的API参数修改为不扣税或按持仓时长阶梯扣税。 - 数据更新时间:
分红数据通常在除权除息日当天生效。如果您在handle_data或run_daily中打印context.portfolio.available_cash,会发现资金已经包含了当天的分红。
总结
要在聚宽中自动处理分红,您只需要做一件事:在 initialize 中添加 set_option('use_real_price', True)。系统会自动处理除权、除息、派现和红股入账。
Q&A
Q: 如果我不开启 use_real_price,分红会怎么处理?
A: 如果不开启(即使用默认的前复权模式),系统会假设分红已经“再投资”到了股价中(通过降低历史股价来实现复权)。您的账户不会收到现金分红,持仓数量也不会因为送转而增加。这种模式适合技术指标分析,但不适合模拟真实的账户资金流。
Q: on_event 函数是必须写的吗?
A: 不是。on_event 是可选的。即使不写这个函数,只要开启了真实价格模式,分红资金和股票依然会自动到账。on_event 仅用于您需要在分红发生的瞬间执行特定代码(例如记录日志或立即将分红资金买入股票)时使用。
Q: 模拟交易中分红什么时候到账?
A: 在模拟交易中,分红通常在除权除息日的开盘前到账。系统会根据交易所的公告自动处理。