第二十七章:波动率曲面API设计
说实话,API设计这事儿,看着简单,做起来全是坑。我在做波动率曲面系统的时候,前后重构了三次API接口,才找到比较顺手的方案。今天咱们就聊聊RESTful API怎么设计、WebSocket怎么推实时数据、以及安全认证那些绕不开的坎儿。
一、RESTful API设计:别把接口搞成四不像
很多人设计API,上来就是一堆动词。比如 /getVolSurface、/updateVolData。我个人习惯是:资源用名词,操作用HTTP方法。你想想看,RESTful的核心就是资源导向。
核心原则:
- 用名词表示资源:
/api/v1/volatility/surfaces - 用HTTP方法表示操作:GET(查)、POST(增)、PUT(改)、DELETE(删)
- 版本号放路径里:
/api/v1/,方便迭代
举个例子,查询某个期权链的波动率曲面:
# 请求
GET /api/v1/volatility/surfaces?underlying=SPX&expiry=2025-06-20
# 响应
{
"status": "success",
"data": {
"surface_id": "surf_20250620",
"underlying": "SPX",
"expiry": "2025-06-20",
"strikes": [4500, 4550, 4600, 4650, 4700],
"maturities": ["1W", "2W", "1M", "3M", "6M"],
"vol_matrix": [
[0.185, 0.182, 0.180, 0.183, 0.190],
[0.188, 0.185, 0.183, 0.186, 0.193],
...
],
"updated_at": "2025-04-01T10:30:00Z"
}
}
这里要注意,响应里我加了 status 字段。为什么?因为我在项目中遇到过,前端解析错误码时,HTTP状态码和业务错误码混在一起,调试起来特别痛苦。所以我习惯把业务状态单独拎出来。
我的小技巧:
分页查询曲面历史数据时,用 cursor 分页而不是 offset。曲面数据量大了以后,offset分页在数据库里会越来越慢。cursor分页虽然实现麻烦点,但性能稳定。
二、WebSocket实时推送:别让数据等太久
波动率曲面是实时变化的。尤其是期权做市商,每秒钟都在调整报价。RESTful轮询?那延迟能让你亏到哭。WebSocket才是正解。
我设计WebSocket接口时,分了三个频道:
| 频道名称 | 推送内容 | 推送频率 |
|---|---|---|
vol.surface.update |
曲面数据变化(新增/修改) | 实时(有变化即推) |
vol.surface.snapshot |
全量曲面快照 | 每5分钟一次 |
vol.surface.alert |
异常波动告警 | 触发时推送 |
连接方式很简单:
// 客户端连接
const ws = new WebSocket('wss://api.volsurface.com/v1/ws');
// 订阅曲面更新
ws.send(JSON.stringify({
"action": "subscribe",
"channel": "vol.surface.update",
"params": {
"underlying": "SPX",
"expiry": "2025-06-20"
}
}));
// 接收推送
ws.onmessage = function(event) {
const data = JSON.parse(event.data);
// 更新前端曲面图
updateSurfaceChart(data);
};
踩过的坑:
我曾经没做心跳检测,结果连接断了三天都没发现。后来加了每30秒一次的ping/pong机制,断线后自动重连。另外,推送数据别太大,曲面矩阵动辄几百个点,压缩一下能省不少带宽。
三、API安全与认证:别裸奔
波动率数据是核心资产。你想想看,要是被人爬走了曲面数据,那策略就白做了。安全这块,我分了三个层次。
3.1 认证:JWT + API Key
我习惯用双因子认证。API Key用于机器对机器的调用,JWT用于用户会话。
# 获取JWT Token
POST /api/v1/auth/login
{
"api_key": "sk_live_xxxxx",
"api_secret": "your_secret_key"
}
# 响应
{
"token": "eyJhbGciOiJIUzI1NiIs...",
"expires_in": 3600
}
# 后续请求带上Token
GET /api/v1/volatility/surfaces
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
3.2 授权:细粒度权限控制
不是所有人都能看全量曲面。比如实习生只能看历史数据,交易员能看实时数据,管理员才能修改参数。我一般用RBAC(基于角色的访问控制)。
| 角色 | 可访问接口 | 说明 |
|---|---|---|
| viewer | GET /surfaces, GET /history | 只读历史数据 |
| trader | GET /surfaces, WebSocket实时推送 | 可看实时数据 |
| admin | 全部接口(含PUT/POST/DELETE) | 可修改模型参数 |
3.3 防护:限流与加密
限流是必须的。我见过有人用脚本疯狂刷接口,直接把数据库打挂了。我的做法是:
- 每个API Key每分钟最多100次请求
- WebSocket每个连接最多订阅5个频道
- 所有传输走HTTPS,敏感字段(如曲面原始数据)用AES-256加密
避坑指南:
我曾经把API Key明文存在前端代码里,结果被用户抓包抓到了。后来改用后端代理转发,前端只存短期Token。另外,日志里别打印完整Token,只打后四位,方便排查又不泄露。
四、整体架构图
下面这张图是我做系统时的核心架构。你看一眼就明白数据怎么流转了。
你看这个架构,客户端只跟API网关打交道。网关负责认证、限流、路由。服务层做真正的计算和推送。数据层存历史数据和缓存。各层职责清晰,出了问题也好排查。
五、总结
API设计这事儿,说白了就是三个字:稳、快、安全。稳是指接口设计要规范,别今天改个字段名明天改个路径;快是指实时数据推送要低延迟;安全是指别让数据裸奔。我在项目中吃过不少亏,但每次重构都让系统更健壮。嗯,希望这些经验能帮你少走弯路。
公众号:蓝海资料掘金营,微信deep3321