3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
在聚宽(JoinQuant)的期货策略中,判断保证金比例是否过低(即风险度过高)通常有两种方法:
当前持仓保证金 / 账户总资产 计算风险度。一般当该比例超过 80% 或 90% 时,就需要减仓。is_dangerous 函数判断可用资金是否低于设定比例。下面我将提供一个完整的策略示例,展示如何实时监控风险度,并在风险过高时自动按比例减仓以防止强平。
context.portfolio 获取总资产 (total_value) 和当前占用保证金 (margin)。risk_ratio = margin / total_value。risk_ratio 超过设定的阈值(例如 80%),则触发减仓逻辑。# -*- coding: utf-8 -*-
from jqdata import *
def initialize(context):
# 1. 设定期货账户
# 获取初始资金
init_cash = context.portfolio.starting_cash
# 设定账户类型为期货
set_subportfolios([SubPortfolioConfig(cash=init_cash, type='futures')])
# 2. 设定交易费率和滑点 (以螺纹钢为例,实际需按品种调整)
set_order_cost(OrderCost(open_commission=0.0001, close_commission=0.0001, close_today_commission=0.0001), type='futures')
set_slippage(FixedSlippage(0))
# 3. 设定基准
set_benchmark('RB9999.XSGE')
# 4. 定义全局变量
g.future_code = 'RB9999.XSGE' # 示例操作标的
# 5. 设定风控阈值
g.risk_limit = 0.8 # 风险度阈值 (保证金占比超过80%视为危险)
g.reduce_ratio = 0.5 # 触发风控时,减仓比例 (平掉50%持仓)
# 6. 运行频率
run_daily(market_open, time='every_bar')
# 单独注册一个风控检查函数,确保每分钟或定时检查
run_daily(check_risk_management, time='every_bar')
def market_open(context):
# 这里写你的开仓逻辑,仅作演示
# 示例:随机开仓以增加保证金占用
if context.portfolio.margin / context.portfolio.total_value < 0.5:
# 如果风险度低,尝试开多单
order(g.future_code, 1, side='long')
def check_risk_management(context):
"""
风控函数:检查保证金比例,过高则强平部分仓位
"""
# 获取当前账户对象 (如果是多账户,需指定 subportfolios[i])
portfolio = context.portfolio
# 1. 获取资金数据
total_value = portfolio.total_value # 总资产
margin_used = portfolio.margin # 已用保证金
# 防止除以0错误
if total_value == 0:
return
# 2. 计算当前风险度 (保证金占用比例)
current_risk = margin_used / total_value
# 打印当前风险日志
# log.info("当前风险度: {:.2%}".format(current_risk))
# 3. 判断是否超过阈值
if current_risk >= g.risk_limit:
log.warn("【风控触发】当前风险度 {:.2%} 超过阈值 {:.2%},开始执行减仓...".format(current_risk, g.risk_limit))
# 执行减仓操作
reduce_positions(context)
def reduce_positions(context):
"""
减仓逻辑:遍历所有持仓,按比例平仓
"""
portfolio = context.portfolio
# 1. 处理多单 (Long Positions)
for security, pos in portfolio.long_positions.items():
if pos.total_amount > 0:
# 计算需要卖出的数量
target_amount = int(pos.total_amount * (1 - g.reduce_ratio))
# 如果计算后数量为0但原持有量>0,强制至少平掉1手,或者直接全平
if target_amount == pos.total_amount and pos.total_amount > 0:
target_amount = 0
log.info("正在平多单: {}, 当前持仓: {}, 目标持仓: {}".format(security, pos.total_amount, target_amount))
# 平多单操作:side='long', amount设为目标持仓量
order_target(security, target_amount, side='long')
# 2. 处理空单 (Short Positions)
for security, pos in portfolio.short_positions.items():
if pos.total_amount > 0:
# 计算需要卖出的数量
target_amount = int(pos.total_amount * (1 - g.reduce_ratio))
log.info("正在平空单: {}, 当前持仓: {}, 目标持仓: {}".format(security, pos.total_amount, target_amount))
# 平空单操作:side='short', amount设为目标持仓量
order_target(security, target_amount, side='short')
context.portfolio.margin:
context.portfolio.total_value:
available_cash 来做分母,因为可用资金会随着开仓减少,而总权益才是衡量账户抗风险能力的基准。order_target(security, amount, side='...'):
side。side='long',amount 设置为比当前更小的值(或0)。side='short',amount 设置为比当前更小的值(或0)。is_dangerous聚宽提供了一个内置函数 is_dangerous,但它的逻辑是基于“可用资金”或“保证金比例”的判断,不如手动计算直观。如果你想用它,用法如下:
# 检查 subportfolios[0] 的保证金比例是否低于 20% (即风险度是否极高)
# 注意:这里的参数含义可能因语境不同而异,建议使用上面的手动计算法更稳妥
if context.subportfolios[0].is_dangerous(0.2):
log.warn("账户资金处于危险边缘")
# 执行平仓...
g.risk_limit 设置在 0.6 到 0.8 之间。期货波动大,留足 20%-40% 的可用资金作为缓冲是非常必要的。handle_data 或分钟级的 run_daily 中调用风控函数,确保盘中价格剧烈波动时能及时反应。Q1: 为什么计算风险度要用 margin / total_value 而不是 margin / available_cash?
A1: total_value 代表你的总权益(本金+盈亏)。风险度是指你用了多少总权益去抗单。available_cash 只是剩余没用的钱,它会随着开仓变成0,无法作为分母来衡量整体风险比例。
Q2: order_target 在平仓时,side 参数应该填什么?
A2: side 参数代表你操作的是哪个方向的持仓。
side 必须填 'long',并将数量设为 0 或更少。side 必须填 'short'。order_target 里是对 long 仓位进行目标调整。Q3: 模拟盘和实盘的保证金计算有区别吗?
A3: 有区别。模拟盘通常按交易所标准保证金计算,而实盘中期货公司通常会在交易所基础上加收几个点(例如交易所10%,期货公司可能收15%)。在编写策略时,建议将风控阈值设得比理论值更保守一些(更低一些),以覆盖这种差异。