# HedgeArbiRiskManager

该项目专门用于对冲套利策略的交易风控，所有的风控逻辑来源于风控文档：https://vcn09ofngo3b.feishu.cn/wiki/PkXMwqZmliiKGwkO8AxctfFznNg

## 项目目录说明

```
HedgeArbiRiskManager/
├── risk_manager.py          # 风控管理器主模块，含风控逻辑和装饰器
├── example/                 # 示例代码目录
│   ├── main.py             # 示例主程序，展示如何使用风控模块
│   ├── strategy.py         # Mock 真实场景的示例策略类，实现策略相关接口
│   ├── datafeed.py         # 数据源模拟器，用于加载和流式输出测试数据
│   └── fake_data/          # 测试数据文件（JSON Lines 格式）
│       ├── bbo.jsonl       # 最佳买卖价（BBO）测试数据
│       ├── depth.jsonl      # 深度行情测试数据
│       ├── orders_slippage.jsonl  # 订单滑点测试数据
│       ├── orders_latency.jsonl   # 订单延迟测试数据
│       ├── receipts.jsonl         # 订单回执测试数据
│       ├── balances.jsonl         # 账户余额测试数据
│       └── fundings.jsonl         # 资金费率测试数据
├── usecase/                 # 风控用例实现目录
│   ├── tick_level/         # 逐笔（TICK）级别风控用例
│   │   ├── spread_check.py        # 价差检查用例
│   │   └── latency_check.py       # 延迟检查用例
│   ├── order_level/        # 订单（ORDER）级别风控用例
│   │   ├── exchange_order_check.py  # 交易所级别订单检查
│   │   └── symbol_order_check.py     # Symbol 级别订单检查
│   ├── global_level/       # 全局（GLOBAL）级别风控用例
│   │   ├── balance_check.py        # 余额检查用例
│   │   ├── commission_check.py     # 手续费检查用例
│   │   ├── exposure_check.py       # 敞口检查用例
│   │   ├── leverage_check.py       # 杠杆检查用例
│   │   └── position_check.py       # 持仓检查用例
│   ├── order_quality_scenarios.py  # 订单质量场景
│   └── order_receipt_scenarios.py # 订单回执场景
├── utils/                   # 工具模块目录
│   ├── position_manager.py  # Mock 真实场景的持仓管理相关工具模块
│   ├── statistics.py        # Mock 真实场景的统计工具模块
│   ├── trader.py            # Mock 真实场景的交易接口/封装
│   ├── signal_manager.py    # Mock 真实场景的信号管理相关工具
│   ├── risk_signal.py       # 风控信号数据结构定义
│   └── loader.py            # 数据加载工具
├── enums/                   # 枚举类型定义目录
│   └── risk_signal_types.py # 风控信号类型枚举（RiskScope, RiskAction）
├── config/                  # 配置文件目录
│   └── config.toml          # 风控配置文件
├── unittest/                # 单元测试目录
│   ├── risk_manager_test.py         # 风控管理器测试
│   ├── test_tick_level.py           # TICK 级别风控测试
│   ├── test_order_level_checks.py   # ORDER 级别风控测试
│   ├── test_order_quality_risk.py   # 订单质量风控测试
│   ├── test_order_receipt_risk.py   # 订单回执风控测试
│   └── test_global_level.py         # GLOBAL 级别风控测试
├── .gitignore               # Git 忽略文件配置
└── README.md                # 项目说明文档
```

### 目录说明

- **`risk_manager.py`**：对冲套利风控的主模块，实现风控装饰器与风控逻辑。包含 `RiskManager` 类和 `@risk_managed()` 装饰器。

- **`example/`**：示例代码目录，提供完整的使用示例和测试数据。
  - `main.py`：示例主程序，展示如何初始化和使用风控模块
  - `strategy.py`：Mock 策略类，展示如何在策略中集成风控功能
  - `datafeed.py`：数据源模拟器，用于加载和流式输出测试数据
  - `fake_data/`：包含各种测试场景的 JSON Lines 格式数据文件

- **`usecase/`**：风控用例实现目录，按风控层级组织。
  - `tick_level/`：逐笔级别风控，包括价差检查、延迟检查等
  - `order_level/`：订单级别风控，包括交易所级别和 Symbol 级别的订单检查
  - `global_level/`：全局级别风控，包括余额、敞口、杠杆、持仓等检查

- **`utils/`**：各类辅助工具模块，便于风控和策略逻辑解耦。
  - `risk_signal.py`：风控信号数据结构，用于封装和传递风控结果
  - 其他工具模块可根据需要添加功能来客制化

- **`enums/`**：枚举类型定义，包括风控作用域（RiskScope）和风控动作（RiskAction）。

- **`config/`**：配置文件目录，用于存放风控相关的配置参数。

- **`unittest/`**：单元测试目录，包含各种风控功能的测试用例。


## 代码逻辑设计

项目工程的设计使用了以下设计模式：

- 装饰器模式
- 面向切面编程 AOP
- 代理模式

通过以上的设计模式，最大化减少风控模块本身的逻辑对策略代码的注入，降低策略代码的复杂度，并且用最简单的方法帮助用户使用风控管理模块。  
在后续的更新与开发中，应该仍然秉持以上设计思想与需求，来对策略各个模块进行分层管理。

## 用法说明与示例

可以通过直接运行 `risk_mananger.py` 文件来理解 HedgeArbiRiskManager 的运行原理，并且查看运行效果。   

### 策略装饰
为了减少 HedgeArbiRiskManager 对于原有策略类的代码入侵，采用了装饰器的设计方法，如果策略需要进行对冲调用，则需要使用 HedgeArbiRiskManager 对 Strategy 类进行装饰。
```python
@risk_managed()                # 对策略类进行装饰，自动注入 RiskManager，并包装所有以 on_ 开头的方法，这种方法可以减少对策略类代码的注入
class Strategy:
    def __init__(self):
        # 模拟策略的成员变量
        self.bbo = [[100, 100, 101, 100], [99, 200, 102, 200]]
        self.symbols = [["BTC_USDT"], ["BTC_USDT"]]
        self.fundings = [
            {symbol: {"funding_rate": 0, "funding_interval": 8,
                        "next_funding_at": 0} for symbol in self.symbols[idx]}
            for idx in range(len(self.symbols))
        ]
        self.pm = HedgePositionManager()
        self.statistics = Statistics()
        self.signal_manager = SignalManager()
        self.name = "MockStrategy"

    def on_bbo(self):
        print("on_bbo: 业务逻辑执行")
        risk_signal = self.risk_manager.check_tick_risk()  # 实际使用风控管理器获取风控信号
        print(f"on_bbo 风控检查结果: {risk_signal}")

    def on_strategy(self):
        print("on_strategy: 业务逻辑执行")
        risk_signal = self.risk_manager.check_global_risk()  # 实际使用风控管理器获取风控信号
        print(f"on_strategy 风控检查结果: {risk_signal}")

    def not_triggered(self):
        print(f"{self.__class__.__name__} 由于该方法不以 on_ 开头，该方法不会触发风控")
```
通过装饰的方法，风控模块会自动监控 `on_` 开头的方法，并且在进入 `on_` 方法之前进行数据更新并且进行风控检查  
在原有策略需要访问风控信号并进行风控检查的部分，仅需要根据检查风控的函数地方，来调用不同的函数实现风控，例如：   
**当需要对 symbol 进行 tick 级别的风控：**
```python
risk_signal = self.risk_mananger.check_tick_risk()
```

**当需要对发单的回执进行风控时:**
```python
risk_signal = self.risk_manager.check_order_receipt_risk(0, 'BTC_USDT', {'Ok':{...}})
```

**当需要对交易所订单成交回执进行风控时:**
```python
risk_signal = self.risk_manager.check_order_risk()
```

**当需要对全局进行风控检查的时候：**
```python
risk_signal = self.risk_mananger.check_global_risk()
```

即可完成对风控的检查，之后可以根据 `risk_signal` 进行对应的风控信号处理。   

风控的信号 `risk_signal` 的数据结构如下：  
```json
{
  "signals": {
    "tick": [],
    "order": [
      {
        "id": "b033ae8dd9b348aebfe23eff53c5fcb5",
        "action": "STOP_ALL",
        "message": "订单发送失败，停止所有交易",
        "timestamp": "2025-11-11T15:05:21.765272Z",
        "target_id": "BTC_USDT",
        "context": {
          "err": "EXCHANGE_ERROR"
        }
      }
    ],
    "global": [
      {
        "id": "7ecc7d2e28a544919e465bf72829282c",
        "action": "STOP_ALL",
        "message": "账户杠杆过高，停止开仓",
        "timestamp": "2025-11-11T15:05:21.765275Z",
        "target_id": "ALL",
        "context": {
          "leverage": 8
        }
      }
    ]
  }
}
```
## 使用模板说明

进入目录 `example/main.py`， 执行该 `main.py` 文件，可以查看针对风控规则设计的假数据运行的风控检查结果。   

如果需要了解风控该如何嵌入策略中，请查看 `example/strategy.py` 文件。

## 风控依赖对象说明  

风控监控的数据来源包括以下两方面：   

1. open_quant 的基本数据类型与格式。包括行情的 `bbo`、`depth`、`balance`、`order`、`position` 等  

2. 本地维护策略状态的类。详情可见 `utils/` 路径下的 `position_mananger.py` 、 `statistics.py` 的基本实现，来辅助进行风控的监控。

## 版本管理方法

TODO: 还没想好后续这个风控的更新按照什么方式去更新和进行版本管理会好一些

## 风控用例说明

为了更好的对复杂情况进行风控，降低后续开发与更新难度，通过编写用例的方法来对风险行为特征进行识别并生成风控信号。目前已经创建了 17 个用例用来对 45 条风控规则进行尽可能的大范围覆盖。用例的说明与解释如下：

### 全局 GLOBAL 级风控

#### 余额风控

- 可用资金不足 20%  

    - 完成的风控需求清单：[13, 36, 44]

- 可用资金是否为 0 (监控是否爆仓/资金用尽/仓位有爆仓风险)

    - 完成的风控需求清单：[13, 30, ]

- 可用资金不平衡 (可用资金相差超过 20%，可能资金平衡系统出问题/链路堵死)

    - 完成的风控需求清单：[9, 13, 30, ]

- 资金回撤达到阈值 (5%，需要强停)

    - 完成的风控需求清单：[5, 13, 28]

- 日内亏损超过阈值 (-1000U)

    - 完成的风控需求清单：[6, 13]

#### 敞口风控

- 检测相同 symbol 是否出现 amount 的敞口 (amount 的数量差异超过 5%，可能发生了 ADL/对冲不充分/交易所平仓)

    - 完成的风控需求清单：[20, 29, 37]

- 检测单腿仓位 (防止单腿风控)

    - 完成的风控需求清单：[20, 29, 35]

#### 账户杠杆风控

- 同时检查账户杠杆和单个 symbol 的杠杆是否异常 (账户整体持仓杠杆不超过 8X，单个币种杠杆不超过 1X)

    - 完成的风控需求清单：[13, 31, ]

### 订单 ORDER 级风控

#### 交易所级别（相同交易所频繁发生问题，怀疑交易所有事故）

- 订单频繁发送失败用例检查 (10 秒内连续 5 次)  

    - 完成的风控需求清单：[7, 13, 27, 42]

- 订单频繁滑点 (10 秒内连续 5 次滑点超过 0.15%)  

    - 完成的风控需求清单：[3, 38, ]

- 订单频繁延迟巨大 (10 秒内连续 5 次延迟超过 800 ms)

    - 完成的风控需求清单：[38, ]

#### symbol 级别（相同 symbol 频繁发生问题，怀疑 symbol 不适合做交易）

- 订单频繁发送失败用例检查 (10 秒内连续 5 次)  

    - 完成的风控需求清单：[7, 27, 42]

- 订单频繁滑点 (10 秒内连续 5 次滑点超过 0.15%)  

    - 完成的风控需求清单：[3, 38, ]

- 订单频繁延迟巨大 (10 秒内连续 5 次延迟超过 800 ms)

    - 完成的风控需求清单：[38, ]

### 逐笔 TICK 级风控

- 行情延迟风控 (行情延迟超过 1 秒)

    - 完成的风控需求清单：[7, 8, 18, 33, 38]

- 相同 symbol 价差太大风控 (超过 20%)  

    - 完成的风控需求清单：[4, ]

- 交易所的 symbol 行情异常 (ask_1 价格小于等于 bid_1 价格；amount 小于等于 0)

    - 完成的风控需求清单：[2, 18, 33]

### 未实现覆盖的风控条款如下

#### 与人或策略本身逻辑相关，无法通过风控脚本实现风控

1. 因为修改了策略代码，未灰度测试直接上线，导致策略连续亏损 2023-4-26日 修改代码后无测试全部实盘直接上线，亏损2wu；2024-7 徐修改代码后无测试直接全部上线，亏损2wu  

10. 资金费率亏损是否会跳过开仓机会，价差比较大能否忽略亏损  

11. 资金费率4小时亏一次3%如何处理  

12. 价差较大能否自动加一点头寸  

22. 是否有风控人员值夜班，并且发现异常能否及时联系上你，你能否迅速有条件处理？  

21. 你用了市价单吗？部分小交易所2wu的市价单可以亏损2000u 2023年 Coinex使用市价单平仓 亏损5000u；2025-2月 Coinex 3m的仓位同时平仓亏损22wu  

34. 交易所设置某交易对杠杆10x设置失败，策略以为成功了，导致以最大可开10x去开仓，导致一直对冲失败导致亏损/或者降低资金利用率，这种问题很常见，经常出现在交易所拔网线的时候  

40. 如果本地计算仓位，是否会自动对比交易所的仓位，修正本地仓位，因为被ADL/人工平仓/订单漏报本地计算仓位不会更新  

41. 部分交易所查询仓位数量会有数量限制，比如200条，如果你的仓位数量大于200怎么办？  

42. 每个品种的Taker最大下单量和Maker最大下单量都不一样，如果你有10万敞口需要平仓，交易所只允许下5万u的订单，你会一直被拒绝订单，导致暴露敞口（需要获取下单最大值，并且每次下单拒绝减少一半下单量重试，直到成功）  

43. 小币种几小时上涨几倍后，市值和OI跟着上涨，策略原本根据市值和OI算出的最大持仓，随着上涨开更大的仓位，导致被暴击：改为最近7天内最低最大可开  

45. 预埋止盈止损单，防止10.11那种行情，交易所直接拔网线，不让你平仓

#### 与交易所/市场黑天鹅相关

16. 交易所被挤兑（FTX），如何提前识别  

25. Gas费异常  

26. 稳定币脱锚，比如USDT/USDC（之前发生了稳定币暴跌）  

32. 交易对规则和可交易状态变化和新币上下下架策略会及时更新吗？ 2025-4-7日 资金费率更新周期由8小时改为两小时Coinex对Bn套利亏损3000u                                      （策略重启最好，否则需要定时请求）


## [附录] 已实现风控条款  

### 与交易相关可直接实现
- [x] 交易所出现异常，价格推送错误或者交易对下架等其他原因，导致对冲连续亏损
- [x] 连续出现滑点，导致亏损
- [x] 整体账户余额回撤后禁止开仓，只可以平仓
- [x] 当日统计盈利达到阈值后禁止开仓，只可以平仓，比如当日累积盈利-100U，禁止再做开仓
- [x] 其中一个交易所拔网线，如何预防亏损
- [x] 跨交易所币种名字一致，价格不一样如何识别（价差超过20%跳过开仓） 2024-9 Gate出现名字一样，价格不一样的情况，亏损2wu
- [x] 持续15s资金不均衡是否能自动减仓，并且不平衡程度越严重，减仓条件越松，最高可以认亏3%出场 2023-4-19日亏损1wu后的风控条件
- [ ] 资金费率亏损是否会跳过开仓机会，价差比较大能否忽略亏损
- [ ] 资金费率4小时亏一次3%如何处理
- [x] 交易所拔网线如何防止被交易所爆仓
- [x] 交易所正常运行如何临近爆仓价格前自动减仓，如果价格达到仓位爆仓价格1%附近，需要强制认亏减仓，减仓到爆仓价格高于2%，无需全部减仓
- [x] 币种流动性真空无法平仓（Huobi出现过）
- [x] 手续费等级突然失去，原来赚钱的价差现在亏钱，如何及时发现
- [x] 币种下架，无法交易，但仓位还在（现货经常出现，合约较少出现）
- [x] 被爆仓清算了，单腿仓位能否在10s以内极速平仓（爆仓后价格会瞬间回弹，需要极速平仓） 2023-11-9日BitgetBsc链充值卡死，资金无法均衡，Bitget爆仓后平单腿15s平一次2000u，平了几十分钟，行情大反弹后亏损18万u
- [x] 保证金率/uniMMR 针对统一账户和普通账户下风险指标的监控和应急处理方法
- [x] 订单连续下单失败自动停机策略 2025-08-29 Coinex对Bn套利，Bn出现宕机，策略误以为价差一直存在一直下单，Coinex成交后，Bn一直无法成功对冲（无法下单），导致一直连续单腿亏损，共亏损1w+u
- [x] 出现风控后，是否会执行另一个风控模块，比如整体账户余额下调了触发了余额回撤风控，去执行减仓功能，但可能刚好是减仓功能的代码导致余额回撤。从而死循环直到归0
- [x] 出现风控后，是否会影响单腿仓位平衡模块运行，单腿仓位平衡模块一直在导致亏损如何及时处理
- [x] 爆仓后，交易所余额变成 0,，是否会影响策略运行：1. 交易所没有推送余额，导致本地变量找不到此交易所 2. 余额变成0，余额作为被除数，策略报错
- [x] 单币种杠杆是否过高，单币不允许高于1x杠杆，单币出现几分钟暴涨100%很常见。并且总体账户单边杠杆净值不得超过3倍，比如一共单边交易所持仓8倍，多仓持仓5.5倍的情况下，空仓得持仓2.5倍抵消，否则禁止开仓，避免519行情1分钟急速下跌10%
- [x] 两个交易所都建仓后，另一个交易所将该币种下架了，导致这个交易对不存在可对冲交易所，然后没有运行此币种的行情监控，风控也就没有运行，策略能否识别出此遗留仓位预警并平仓？
- [ ] 交易所设置某交易对杠杆10x设置失败，策略以为成功了，导致以最大可开10x去开仓，导致一直对冲失败导致亏损/或者降低资金利用率，这种问题很常见，经常出现在交易所拔网线的时候
- [x] 单腿仓位检查是否有时间检查？单腿持续15s再平（根据交易对单腿持续时间，而不是根据账户）。平完之后是否会把时间重置？防止平完单腿后，接着又继续平
- [x] 交易所设置杠杆10x，应该只允许仓位开到8x就暂停开仓，否则均衡无可用资金转出导致资金不均衡被强平，剩余2x可留给价差极大的机会增加年化；如果真的10x了，需要加上一条风控，可用资金低于1000u，选取一些开仓价差比较小、持仓时间久、浮盈过高的仓位亏一点平仓释放可用资金，把资金拿去做好的套利，增加年化； 2025-3-22日Coinex一直10x被强平亏损5000u
- [x] 如何防止被ADL？交易所ADL和爆仓平仓一样，很容易亏损几个点，特别是资费套利，被ADL是肯定会发生的 2025-4-14日Bitget OM交易对30分钟内暴跌90% 被ADL平了4wu，亏损2.6wu
- [x] 交易所拔网线，行情收到的是一小时以前的，导致一直巨额滑点亏损，下单延迟与行情延迟需要检测，行情如果发现异常自动重启机器人，下单延迟发现异常停止所有交易几分钟 2025-4-7日 Bitget对Bn套利亏损2000u
- [ ] 如果一个交易对一开始开了1x杠杆，这个交易对后面一天涨了10倍，因为价格上涨，价值变成了10x杠杆持仓，因为赚资金费率的原因，他不会减仓，此时价格只需要波动10%就会爆仓，策略是否能强制减仓？

### 不直接与交易相关的流程或市场风险
- [ ] 因为修改了策略代码，未灰度测试直接上线，导致策略连续亏损 2023-4-26日 修改代码后无测试全部实盘直接上线，亏损2wu；2024-7 徐修改代码后无测试直接全部上线，亏损2wu
- [ ] 开仓时价差正常，因为单机币或者操盘的原因，价差达到 -10%
- [ ] 价差较大能否自动加一点头寸
- [x] 交易所被挤兑（FTX），如何提前识别
- [ ] 交易所限频，IP被封禁一天
- [ ] 你用了市价单吗？部分小交易所2wu的市价单可以亏损2000u 2023年 Coinex使用市价单平仓 亏损5000u；2025-2月 Coinex 3m的仓位同时平仓亏损22wu
- [ ] 是否有风控人员值夜班，并且发现异常能否及时联系上你，你能否迅速有条件处理？
- [x] 出现519和312策略会如何应
- [ ] Gas费异常
- [x] 稳定币脱锚，比如USDT/USDC（之前发生了稳定币暴跌）
- [ ] 交易对规则和可交易状态变化和新币上下下架策略会及时更新吗？ 2025-4-7日 资金费率更新周期由8小时改为两小时Coinex对Bn套利亏损3000u
- [ ] 如果本地计算仓位，是否会自动对比交易所的仓位，修正本地仓位，因为被ADL/人工平仓/订单漏报本地计算仓位不会更新
- [ ] 部分交易所查询仓位数量会有数量限制，比如200条，如果你的仓位数量大于200怎么办？
- [ ] 每个品种的Taker最大下单量和Maker最大下单量都不一样，如果你有10万敞口需要平仓，交易所只允许下5万u的订单，你会一直被拒绝订单，导致暴露敞口（需要获取下单最大值，并且每次下单拒绝减少一半下单量重试，直到成功）
- [ ] 小币种几小时上涨几倍后，市值和OI跟着上涨，策略原本根据市值和OI算出的最大持仓，随着上涨开更大的仓位，导致被暴击：改为最近7天内最低最大可开
- [x] 可用资金不足和爆仓距离风控是线性的，让出的亏损价差太有限：应该改为指数级增加，强制平仓
- [ ] 预埋止盈止损单，防止10.11那种行情，交易所直接拔网线，不让你平仓
