🚀 AI 一键生成 qmt 策略代码
立即体验

QMT 平台如何基于条件在险价值 (CVaR) 实现动态仓位风控管理?(附 Python 代码)

qmt | 发布时间: 2026/8/1
以下内容由 EasyQuant 生成。

问题描述

请根据以下 SEO 主题生成完整页面内容:

Title: QMT 组合风控:基于条件在险价值 (CVaR) 的动态仓位优化

Question: 请帮我实现在 QMT 中基于 CVaR 尾部风险评估的动态调仓逻辑

解决方案

QMT 组合风控:基于条件在险价值 (CVaR) 的动态仓位优化

在极端市场行情下,传统的波动率或 VaR(在险价值)往往无法有效度量尾部巨亏风险。CVaR(Conditional Value at Risk,条件在险价值),又称超额损失均值,能够有效捕捉极端损失的期望值,具备次可加性,是构建稳健量化组合风控系统的理想指标。

本文将演示如何在 QMT(迅投 Python API) 中利用历史行情数据计算股票池的 CVaR,并根据尾部风险动态调整整体仓位。


1. 核心风控逻辑设计

  1. 数据获取:利用 ContextInfo.get_market_data_ex() 调取股票池内标的历史日线收益率。
  2. CVaR 计算:设置置信水平(如 95%),计算超过 VaR 阈值的损失均值。
  3. 动态调仓机制
    • 设置 CVaR 风险上限风控阈值(例如 3%)。
    • 当组合 CVaR 低于阈值时,维持高仓位;
    • 当组合 CVaR 超过阈值时,按比例线性缩减总持仓市值,实现动态避险。

2. QMT 策略实现源码

以下策略代码基于 QMT Python API 规范编写:

#encoding:gbk
import numpy as np
import pandas as pd

def init(ContextInfo):
    # 1. 设置股票池与交易账号
    ContextInfo.stock_list = ['600000.SH', '000001.SZ', '600519.SH', '000858.SZ']
    ContextInfo.set_universe(ContextInfo.stock_list)
    ContextInfo.account = '6000000001'
    ContextInfo.set_account(ContextInfo.account)
    
    # 2. 设置风控参数
    ContextInfo.confidence_level = 0.95  # CVaR 置信度
    ContextInfo.max_cvar_limit = 0.03    # CVaR 容忍上限 (3%)
    ContextInfo.lookback_days = 120     # 回溯历史数据天数
    
    print("CVaR 动态风控策略初始化完成")

def calculate_cvar(returns, confidence_level=0.95):
    """计算单资产或均权组合的 CVaR"""
    portfolio_returns = returns.mean(axis=1) # 简化假设:按等权重组合计算收益
    var = np.percentile(portfolio_returns, (1 - confidence_level) * 100)
    cvar = -portfolio_returns[portfolio_returns <= var].mean()
    return cvar if not np.isnan(cvar) else 0.0

def handlebar(ContextInfo):
    # 仅在最新 K 线(或盘中 tick)且到达执行点时计算风险并调仓
    if not ContextInfo.is_last_bar():
        return
    
    # 获取历史收盘价计算收益率
    data = ContextInfo.get_market_data_ex(
        ['close'], 
        ContextInfo.stock_list, 
        period='1d', 
        count=ContextInfo.lookback_days + 1
    )
    
    # 数据整理与收益率计算
    df_close = pd.DataFrame()
    for code in ContextInfo.stock_list:
        if code in data:
            df_close[code] = data[code]['close']
            
    returns = df_close.pct_change().dropna()
    
    # 计算当前组合 CVaR
    current_cvar = calculate_cvar(returns, ContextInfo.confidence_level)
    print(f"当前组合 95% 置信度下的 CVaR: {current_cvar:.4f}")
    
    # 确定目标仓位系数
    if current_cvar > ContextInfo.max_cvar_limit:
        # 超出风险上限,按比例缩减仓位
        target_pos_ratio = ContextInfo.max_cvar_limit / current_cvar
        print(f"触发风险控制,CVaR 超过容忍上限 {ContextInfo.max_cvar_limit:.4f},仓位降至: {target_pos_ratio:.2%}")
    else:
        target_pos_ratio = 1.0
        print("风险指标正常,维持全仓运行")
        
    # 执行调仓下单(以目标比例下单操作为例)
    for code in ContextInfo.stock_list:
        target_weight = (1.0 / len(ContextInfo.stock_list)) * target_pos_ratio
        # 使用 QMT 目标比例下单接口 order_target_percent
        order_target_percent(code, target_weight, 'LATEST', 0, ContextInfo, ContextInfo.account)

3. 策略实施建议

  1. 协方差与权重优化:上述代码基于等权重组合评估 CVaR,实盘中可结合 SciPy.optimize 求解在指定 CVaR 约束下的最优资产配置比例。
  2. 计算频率:尾部风险计算不需要在每一个 Tick 驱动,建议通过 ContextInfo.run_time() 设为每日收盘前或按固定时间间隔调用,以降低计算开销。
  3. 异常处理:在市场停牌或新股上市等导致数据缺失的情况下,请确保使用 skip_paused=True 或填充缺失值,避免对 CVaR 估计造成偏差。