发布于VeighNa社区公众号【vnpy-community】
原文作者:用Python的交易员 | 发布时间:2025-11-10
上周发布了VeighNa的4.2.0版本,本次更新的主要内容是对RiskManager交易事前风控模块进行了重构升级,同时调整了框架的日志输出落地功能,完整适配期货程序化交易监管新规中对于程序化交易系统的功能要求。
对于已经安装了VeighNa Studio 4.0版本的用户,可以使用快速更新功能完成自动升级。对于没有安装的用户,请下载VeighNa Studio-4.2.0,体验一键安装的量化交易Python发行版,下载链接:
https://download.vnpy.com/veighna_studio-4.2.0.exe
RiskManager风控模块
标准化风控规则模板
新版 vnpy_riskmanager 模块设计的核心是标准化的风控规则模板 RuleTemplate。任何自定义风控规则都必须继承该基类,这保证了所有规则都具备统一的接口,使得风控引擎(RiskEngine)能够对其进行动态发现、加载和执行。
RuleTemplate 为风控规则定义了完整的生命周期和核心逻辑方法。创建一个新的风控规则,即是创建一个继承自 RuleTemplate 的子类,并根据实际需求实现其中的相关方法。
核心组件
一个标准的风控规则类主要包含以下几个部分:
name: str: 规则的唯一中文名称,用于图形界面上该规则相关的信息显示。parameters: dict[str, str]: 定义规则的可配置参数。该字典的键为参数的英文名,值为其在图形界面上显示的中文名,方便用户理解和修改。variables: dict[str, str]: 定义规则需要实时监控的状态变量,同样字典的键为变量的英文名,值为其在图形界面上显示的中文名。
核心方法
on_init(self) -> None: 规则的初始化方法。在被风控引擎加载时调用,主要用于设定参数的默认值以及初始化监控变量的初始状态。on_order(self, order: OrderData) -> None: 用于处理委托状态更新的回调方法。规则可在此方法内更新内部状态,例如跟踪活动委托的数量。on_trade(self, trade: TradeData) -> None: 用于处理成交回报的回调方法。规则可在此方法内统计累计成交信息等。on_tick(self, tick: TickData) -> None: 用于处理行情切片数据的回调方法。适用于需要基于实时行情进行判断的规则,但需注意其可能会因频繁调用而带来的性能开销。check_allowed(self, req: OrderRequest, gateway_name: str) -> bool: 风控检查的核心逻辑实现。每当交易系统产生新的委托请求(OrderRequest)时,风控引擎都会调用此方法进行检查。若订单允许通过,则方法返回True;若订单需要被拦截,则应先调用self.write_log()记录拦截的具体原因,随后返回False。
Python 规则示例
以下是一个完整的纯 Python 规则示例代码,实现了对单笔委托数量的上限限制。
from vnpy.trader.object import OrderRequest, OrderData
from ..template import RuleTemplate
class OrderVolumeRule(RuleTemplate):
"""单笔委托手数限制规则"""
# 规则的中文名称
name: str = "委托数量检查"
# 定义可配置的参数
parameters: dict[str, str] = {
"max_volume": "单笔最大委托量"
}
# 定义需监控的变量(可为空)
variables: dict[str, str] = {}
def on_init(self) -> None:
"""初始化"""
self.max_volume: int = 100 # 设置参数的默认值
def check_allowed(self, req: OrderRequest, gateway_name: str) -> bool:
"""核心风控逻辑"""
if req.volume > self.max_volume:
msg = f"委托数量{req.volume}超过参数限制{self.max_volume}:{req}"
self.write_log(msg)
returnFalse
returnTrue
模块的内置风控规则
vnpy_riskmanager 模块提供了一系列标准化的内置风控规则,覆盖了交易过程中的多个关键风险点。所有内置规则均提供纯 Python 和 Cython 两种实现,风控引擎在加载时会优先使用性能更优的 Cython 版本。
ActiveOrderRule(活动委托数量上限)此规则用于限制全局的活动(可撤)委托数量。当活动委托笔数超过设定的active_order_limit阈值时,新的委托请求将被拦截。它通过监听on_order事件来实时跟踪委托状态的变更,从而维护准确的活动委托计数。DailyLimitRule(每日流控上限)该规则用于对整个交易日内的委托、撤单、成交行为进行总次数和单个合约次数的双重流控。它包含六个可配置参数:total_order_limit(汇总委托上限),total_cancel_limit(汇总撤单上限),total_trade_limit(汇总成交上限),contract_order_limit(合约委托上限),contract_cancel_limit(合约撤单上限),contract_trade_limit(合约成交上限)。在发单时,会检查各项累计值是否超限;在收到委托、撤单和成交回报时,会更新相应的计数。DuplicateOrderRule(重复报单检查)用于防范因系统或人为失误导致的重复下单。该规则会统计历史上所有发出委托的缓存,当一个新的委托请求在合约、类型、方向、开平、价格、数量等字段上完全相同时,则会累加其重复次数。如果该次数超过duplicate_order_limit上限(默认为10次),委托就会被执行拦截。OrderSizeRule(单笔委托规模上限)这是一个基础但极为重要的风控规则,用于防止“乌龙指”。它包含两个维度的限制:order_volume_limit用于限制任何单笔委托请求的最大允许数量;order_value_limit用于限制该笔委托的总价值(数量 价格 合约乘数)。任何一个维度超限都会导致委托被拦截。OrderValidityRule(委托指令合法性监控)此规则在委托发送至交易接口前,对其指令的合法性进行预检查,提前拦截无效委托,减轻后端系统压力。检查内容包括:- 通过
main_engine.get_contract检查委托的合约是否存在。 - 检查委托价格是否为合约最小价格变动
pricetick的整数倍。 - 检查委托数量是否超过了合约规定的单笔最大下单量
contract.max_volume。 - 检查委托数量是否低于合约规定的单笔最小下单量
contract.min_volume。
- 通过
Cython 性能优化加速
风控引擎对所有规则的检查是串行执行的,在交易繁忙时,多条纯Python规则累加的检查延迟可能成为性能瓶颈。为了解决这个问题,vnpy_riskmanager模块支持使用Cython对代码进行性能优化。开发者可以将原有的纯Python风控规则,通过Cython语法重构为C语言级别的高性能版本,从而将检查延迟降低到微秒级。
Cython 规则的实现方式
编写 Cython 风控规则的关键是将核心逻辑(尤其是高频调用的check_allowed函数)放入一个 cdef class 中,同时保留一个标准的 Python class 作为外层包装器,以供风控引擎识别和加载。
以下是内置风控规则中 OrderSizeRule 的 Cython 版本实现代码作为示例:
# cython: language_level=3
from vnpy_riskmanager.template cimport RuleTemplate
cdef class OrderSizeRuleCy(RuleTemplate):
"""委托规模检查风控规则 (Cython 版本)"""
cdef public int order_volume_limit
cdef public float order_value_limit
cpdef void on_init(self):
"""初始化"""
self.order_volume_limit = 500
self.order_value_limit = 1_000_000
cpdef bint check_allowed(self, object req, str gateway_name):
"""检查是否允许委托"""
cdef object contract
cdef float order_value
if req.volume > self.order_volume_limit:
self.write_log(f"委托数量{req.volume}超过上限{self.order_volume_limit}:{req}")
return False
contract = self.get_contract(req.vt_symbol)
if contract and req.price: # 只考虑限价单
order_value = req.volume * req.price * contract.size
if order_value > self.order_value_limit:
self.write_log(f"委托价值{order_value}超过上限{self.order_value_limit}:{req}")
return False
return True
class OrderSizeRule(OrderSizeRuleCy):
"""委托规模检查规则的Python包装类"""
name: str = "委托规模检查"
parameters: dict[str, str] = {
"order_volume_limit": "委托数量上限",
"order_value_limit": "委托价值上限",
}
编译自定义 Cython 规则
对于自定义的 Cython 规则可以通过一个独立的编译脚本来编译生成pyd文件(注意编译过程中会需要用到 C++ 编译器,如 Windows 上的 Visual Studio):
创建
build_rule.py: 在项目根目录下创建此脚本。from setuptools import setup, Extension from Cython.Build import cythonize # 注意:需与 .pyx 文件名一致 rule_name = "order_size_rule_cy" extensions = [ Extension( name=f"vnpy_riskmanager.rules.{rule_name}", sources=[f"vnpy_riskmanager/rules/{rule_name}.pyx"], ) ] setup( ext_modules=cythonize( extensions, compiler_directives={"language_level": "3"} ) )执行编译: 在项目根目录下打开终端,运行编译命令。
python build_rule.py build_ext --inplace--inplace参数会使编译生成的二进制文件(.pyd或.so)直接输出到vnpy_riskmanager/rules目录下。编译完成后重启程序,RiskEngine会自动发现并优先加载这个高性能的 Cython 规则。
风控信息通知机制
当一个委托请求因为触发了某项风控规则而被拦截时,vnpy_riskmanager 模块会通过多种方式立即向用户发出警报,确保交易员能够第一时间注意到异常情况并进行处理。
声音报警提醒
一旦有委托被拦截,风控引擎会立刻调用操作系统内置的提示音发出警报,确保即使用户的注意力不在交易界面上,也能迅速察觉到风控事件的发生,从而避免错过关键的风险信息。
气泡弹窗通知
在声音报警的同时,一个可视化的气泡弹窗会从系统托盘区域(通常是屏幕右下角)弹出,该弹窗会明确展示具体的拦截原因,例如“委托数量100超过参数限制50”,气泡弹窗会持续显示一段时间(默认30秒)。
日志信息输出
为了确保风险事件的可追溯性,所有拦截信息在触发实时报警的同时,也会通过VeighNa框架的标准化日志系统进行输出,具体包括:主界面的日志监控组件、启动系统的命令行终端,以及本地日志文件。
核心框架日志输出落地
为了满足监管新规中的要求,确保程序化交易系统的关键操作都有据可查,VeighNa的4.2.0版本在日志记录方面进行了全面增强,主要更新包括:
- 日志默认启动与持久化:日志功能已默认激活并持久化,
INFO级别的系统常规操作信息将同步输出到终端和日志文件。 - 核心引擎操作日志:核心引擎
MainEngine会自动记录关键交易生命周期事件,覆盖连接登录、行情订阅、委托下单及委托撤单等操作。 - 策略模块日志自动注册:各大策略模块(如
CtaStrategy、PortfolioStrategy等)的日志将自动注册并转发至核心日志引擎,实现对策略层行为的全面监控。
CHANGELOG
新增
vnpy_riskmanager模块重构
a. 采用插件式设计,提供标准化风控规则开发模板
b. 支持中国期货程序化交易系统监管要求中的风控规则
c. 输出拦截日志后播放提示声音,目前仅支持Windows系统
d. 使用系统托盘栏图标,弹出交易风控拦截日志气泡框
e. 提供Cython版本的风控规则开发模板以及具体规则实现
f. 支持自动扫描加载用户自定义风控规则(放置于Trader目录下的rules文件夹中)vnpy_polygon数据服务接口,支持海外股票、期货、期权等资产品种的历史数据获取
调整
- vnpy_ctp更新底层API到6.7.11(生产和测试统一版本)
- vnpy_dolphindb升级适配4.0版本
- vnpy_tqsdk简化时间戳的格式化方法,提高效率
- vnpy_sqlite支持使用配置文件中声明的数据文件
- vnpy_taos优化get_bar_overview和get_tick_overview函数性能(直接访问超级表的tags)
- vnpy_spreadtrading / vnpy_portfoliostrategy / vnpy_scripttrader 注册模块日志输出到日志引擎
- vnpy_optionmaster优化定价模型中期权最小价值边界判断的逻辑
- 全局配置中的log.level改为INFO(10),默认启用详细日志记录输出
- MainEngine增加交易功能函数的调用日志输出
- vnpy.alpha中的Dataset增加process_data函数,便于测试不同数据处理器的效果
- vnpy_ib更新支持ibapi至10.40.1版本
修复
- vnpy_gm修复中金所和大商所合约代码转换的问题
- vnpy_rqdata修复RqdataGateway中的行情订阅函数错误问题
- vnpy_optionmaster修复关闭窗口时的异常报错
- vnpy_portfoliostrategy修复遗传算法参数优化中的调用传参问题
- 修复Linux系统上的sdist安装问题:vnpy_mini / vnpy_sopt / vnpy_rohon / vnpy_tap / vnpy_tts
- vnpy_xt修复XtGateway断线重连时的传参错误
- vnpy_optionmaster修复black-76模型中theta计算公式的问题
- vnpy_postgresql修复写入主键冲突时数据不会更新的问题
