问题描述
解决方案
在聚宽(JoinQuant)的回测或模拟交易中,模拟向账户增加或取出资金主要使用 inout_cash 函数。
核心函数说明
inout_cash(cash, pindex=0)
- 功能:用于账户的资金转入或转出。
- 参数:
cash(float): 资金金额。正数表示入金(增加资金),负数表示出金(取出资金)。pindex(int): 仓位索引(SubPortfolio index)。默认为 0,即默认账户。如果您使用了set_subportfolios设置了多个子账户,可以通过此参数指定操作哪个子账户。
- 影响:
- 当日的出入金从当日开始计入成本。
- 当日结束计算收益时,本金是包含当日出入金金额的。
- 直接改变
context.portfolio.available_cash(可用资金)和context.portfolio.total_value(总资产)。
代码示例
以下是一个完整的策略示例,展示了如何在特定日期向账户增加资金和取出资金,并打印资金变化情况。
# -*- coding: utf-8 -*-
def initialize(context):
# 设置基准
set_benchmark('000300.XSHG')
# 开启动态复权模式(真实价格)
set_option('use_real_price', True)
# 每天开盘时运行,检查是否需要出入金
run_daily(check_money_transfer, '09:30')
def check_money_transfer(context):
# 获取当前日期
current_date = str(context.current_dt.date())
# 示例1:模拟在 2020-06-01 入金 100,000 元
if current_date == '2020-06-01':
log.info("=== 执行入金操作前 ===")
log.info("当前可用资金: %.2f" % context.portfolio.available_cash)
log.info("当前总资产: %.2f" % context.portfolio.total_value)
# 执行入金:正数代表增加资金
inout_cash(100000, pindex=0)
log.info("=== 执行入金操作后 ===")
log.info("当前可用资金: %.2f" % context.portfolio.available_cash)
log.info("当前总资产: %.2f" % context.portfolio.total_value)
# 示例2:模拟在 2020-07-01 出金 50,000 元
if current_date == '2020-07-01':
log.info("=== 执行出金操作前 ===")
log.info("当前可用资金: %.2f" % context.portfolio.available_cash)
# 执行出金:负数代表取出资金
# 注意:出金金额不能超过当前可用资金,否则可能导致可用资金为负
if context.portfolio.available_cash >= 50000:
inout_cash(-50000, pindex=0)
log.info("已取出资金 50,000 元")
else:
log.warn("可用资金不足,无法出金")
log.info("=== 执行出金操作后 ===")
log.info("当前可用资金: %.2f" % context.portfolio.available_cash)
注意事项
- 收益率计算:使用
inout_cash后,回测系统的收益率计算分母(本金)会相应调整。入金会增加本金,出金会减少本金。 - 可用资金限制:在执行出金操作(负数)时,请确保账户内有足够的
available_cash(可用资金),否则虽然函数允许执行,但可能导致账户可用资金变为负数,从而影响后续的交易下单。 - 多账户支持:如果您的策略涉及股票、期货等多个子账户(通过
set_subportfolios设置),请务必正确指定pindex参数(例如pindex=1),否则默认操作的是股票账户(pindex=0)。
Q&A
Q: inout_cash 函数可以在 initialize 中调用吗?
A: 可以,但通常不建议。initialize 主要用于策略初始化配置。如果在回测开始前需要调整初始资金,建议直接在回测设置界面的“初始资金”选项中修改。如果在 initialize 中调用,它会在回测第一天开盘前生效。
Q: 出入金操作会产生手续费吗?
A: 不会。inout_cash 仅仅是资金的划转,不涉及买卖交易,因此不会产生佣金或印花税等交易费用。
Q: 如果我在盘中(例如 10:00)调用 inout_cash,这笔钱能立刻用于买股票吗?
A: 是的。inout_cash 是即时生效的。一旦代码执行完毕,context.portfolio.available_cash 会立即更新,您可以在随后的代码逻辑中使用这笔资金进行下单。
Q: 模拟交易(实盘模拟)中可以使用这个函数吗?
A: 可以。在模拟交易中调用此函数,同样会改变模拟账户的资金显示,常用于模拟实际账户的追加保证金或提取利润的操作。