压力测试概述:定义、目的与重要性
做市策略这东西,平时看着挺稳的。但市场一抽风,什么都有可能发生。我见过太多策略在正常行情下跑得漂亮,一到极端行情就崩盘。所以,压力测试不是可选项,是必选项。
什么是压力测试?
说白了,压力测试就是故意给策略制造麻烦。你想想看,一个做市策略平时赚点买卖价差,日子过得挺滋润。但突然来个大单砸盘,或者流动性瞬间枯竭,你的策略扛得住吗?
压力测试就是模拟这些极端场景。它不关心你平时赚多少,只关心你在最坏的情况下会亏多少。我个人习惯把压力测试分成两类:
- 历史场景回放:用过去真实发生过的黑天鹅事件来测试。比如2015年A股股灾、2020年原油暴跌。
- 假设情景模拟:自己构造极端条件。比如价格瞬间跌20%、成交量萎缩90%、延迟突然增加500ms。
嗯,这里要注意:历史场景不一定能覆盖未来的风险。所以我建议两种都要做。
压力测试的目的
目的其实就三个字:找底线。你要知道你的策略在什么情况下会死,怎么死的,死之前有没有预警信号。
我在项目中遇到过一件事。有个做市策略在回测里年化收益30%,最大回撤才2%。团队都觉得稳了。结果上线第三天,遇到一次小范围的流动性枯竭,策略直接亏了半个月的利润。后来一查,问题出在库存管理上——策略在流动性差的时候还在拼命报价,结果被对手方吃掉了所有深度。
所以压力测试要回答这几个问题:
- 最大亏损是多少? 不是平均亏损,是极端情况下的亏损。
- 亏损速度有多快? 是慢慢亏还是瞬间爆仓?
- 恢复需要多久? 亏完之后还能不能赚回来?
- 哪些参数最脆弱? 是价差设置太窄,还是订单撤单太慢?
核心观点:压力测试不是为了证明策略有多强,而是为了暴露策略有多弱。你越早发现弱点,损失越小。
在量化交易中的重要性
做市策略和其他策略不一样。趋势策略可以止损离场,套利策略可以等待回归。但做市策略必须一直在场,你撤单就等于放弃利润。这种「不得不交易」的特性,让做市策略对极端行情特别敏感。
我曾经见过一个团队,他们的做市策略在正常行情下表现完美。结果遇到一次交易所系统升级,网络延迟从1ms飙到200ms。策略完全没反应过来,还在按原来的速度报价,结果被高频交易者反复收割。一天亏了三个月的收益。
为什么会这样?因为压力测试没做网络延迟的极端场景。他们只测试了价格波动,没测试基础设施的波动。
所以压力测试的重要性体现在这几个方面:
| 维度 | 正常行情 | 极端行情 | 压力测试的作用 |
|---|---|---|---|
| 流动性 | 买卖盘充足 | 深度骤降、价差扩大 | 测试策略在低流动性下的报价能力 |
| 波动率 | 平稳波动 | 剧烈跳动、跳空 | 测试库存风险敞口和止损逻辑 |
| 延迟 | 稳定低延迟 | 网络拥堵、系统卡顿 | 测试策略对延迟变化的鲁棒性 |
| 资金 | 正常占用 | 保证金飙升、强平风险 | 测试资金管理是否足够保守 |
我的经验:做压力测试时,别只盯着价格。流动性、延迟、手续费变化、交易所故障,这些因素往往比价格波动更致命。我曾经因为没测试交易所维护期间的策略行为,吃了大亏。
压力测试的核心逻辑
为了让你更直观地理解压力测试在整个做市策略中的位置,我画了一张图。这张图展示了从策略设计到压力测试再到优化的完整链路。
从这张图你可以看到,压力测试不是孤立的步骤。它连接着策略设计和结果分析,形成一个闭环。你测试出问题,就要回去改策略,改完再测,直到满意为止。
警告:别以为压力测试通过就万事大吉。市场永远会给你惊喜。我见过最惨的一次,是策略通过了所有压力测试,结果败给了一个谁都没预料到的因素——交易所的撮合引擎在极端行情下改了撮合规则。所以,压力测试要定期重做,参数要动态调整。
一个简单的压力测试代码示例
下面是一个极简的压力测试框架。它模拟了价格瞬间暴跌的场景,看看你的做市策略会亏多少。
import numpy as np
def stress_test_price_crash(strategy, initial_price, crash_pct=0.2):
"""
模拟价格瞬间暴跌的压力测试
参数:
strategy: 做市策略对象
initial_price: 初始价格
crash_pct: 暴跌幅度,默认20%
"""
# 记录暴跌前的库存和现金
inventory_before = strategy.inventory
cash_before = strategy.cash
# 模拟价格瞬间下跌
crash_price = initial_price * (1 - crash_pct)
# 策略在暴跌后的反应
# 这里简化处理:假设策略来不及撤单,所有挂单都被成交
filled_buys = strategy.pending_buy_orders # 未成交的买单
filled_sells = strategy.pending_sell_orders # 未成交的卖单
# 计算亏损
buy_loss = sum([(crash_price - order.price) * order.qty
for order in filled_buys])
sell_loss = sum([(order.price - crash_price) * order.qty
for order in filled_sells])
total_loss = buy_loss + sell_loss
# 计算新的库存和现金
inventory_after = inventory_before + sum([order.qty for order in filled_buys]) \
- sum([order.qty for order in filled_sells])
cash_after = cash_before - sum([order.price * order.qty for order in filled_buys]) \
+ sum([order.price * order.qty for order in filled_sells])
return {
'crash_price': crash_price,
'total_loss': total_loss,
'inventory_before': inventory_before,
'inventory_after': inventory_after,
'cash_before': cash_before,
'cash_after': cash_after,
'survived': abs(total_loss) < strategy.max_loss_limit
}
# 使用示例
result = stress_test_price_crash(my_strategy, initial_price=100, crash_pct=0.2)
print(f"暴跌后价格: {result['crash_price']:.2f}")
print(f"总亏损: {result['total_loss']:.2f}")
print(f"是否存活: {result['survived']}")
这段代码虽然简单,但抓住了压力测试的核心——模拟极端事件,量化损失。实际项目中,你需要考虑更多因素:撤单延迟、对手方行为、交易所熔断机制等等。但原理是一样的。
我的建议:刚开始做压力测试时,别追求完美。先跑通最简单的场景,比如价格暴跌10%、20%、30%。看看你的策略在哪个阈值开始崩溃。找到那个临界点,然后针对性地优化。我曾经用这个方法,把一个策略的最大承受能力从5%提升到了25%。
好了,压力测试的基本概念就这些。记住一句话:压力测试不是用来证明策略有多好,而是用来发现策略有多差。你越早发现弱点,损失越小。下一节我们会深入具体的压力测试方法,包括历史回放和情景模拟的实操细节。
公众号:蓝海资料掘金营,微信deep3321