# 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` 的基本实现，来辅助进行风控的监控。

## 版本管理方法

为了方便所有人的使用与维护。考虑到风控模块暂时没有那么多的限制，同时没有公司本地的 python 镜像库，秉持着开仓即用的方法，因此使用 python 官方的 PIPY 库用于存储代码并且进行更新与版本管理。  

**版本号规则：**

1. 在 `pyproject.toml` 和 `risk_manager.py` 中找到 `version` 字段。 `version`  是传统的三段式的字段，第一段表示重大版本更新，第二段表示有大功能的新增与说明，第三段表示小功能 bug fix。

2. 每次提交 `bug fix` 都需要对 `version` 进行对应的更新。  

**发布版本的命令**

当完成了 bug fix / feat dev 等需求之后，先将代码提交到 git，之后再在本地环境运行以下命令对代码进行发布：

```shell
cd hedgearbiriskmanager/
python -m build
twine upload dist/*
```

如果本地环境没有 twine，则通过以下命令进行安装

```shell
pip install build twine
```

当需要使用安装的时候，则在目标环境下使用命令：
```shell
python3.10 -m pip install oq-riskmanager 
```


## 风控用例说明

为了更好的对复杂情况进行风控，降低后续开发与更新难度，通过编写用例的方法来对风险行为特征进行识别并生成风控信号。目前已经创建了 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那种行情，交易所直接拔网线，不让你平仓
