6. 机器学习检测法:DBSCAN聚类算法在曲面异常检测中的应用
波动率曲面这东西,做期权交易的朋友都不陌生。表面看着平滑,其实暗藏玄机。我见过太多人盯着曲面上的异常点,却拿不准该不该信。今天咱们聊聊DBSCAN——一个特别适合干这活的聚类算法。
6.1 为什么是DBSCAN?
先说说我的个人习惯。做异常检测,我首选DBSCAN。为什么?
K-means你得指定聚成几类,可波动率曲面上的异常点,鬼知道有几个。DBSCAN不用。它自己根据数据密度来聚类。密度高的地方是一类,密度低的地方——嗯,那就是异常点。
说白了,DBSCAN就干两件事:
- 找稠密区域,把它们归为一类
- 剩下的孤立点,标记为异常
我在项目中遇到过好几次,用K-means死活调不出好结果,换成DBSCAN一次搞定。你想想看,波动率曲面上的异常点往往就是那些「格格不入」的数据点,DBSCAN天生就是干这个的。
6.2 DBSCAN的核心参数
DBSCAN有两个关键参数,搞懂了它们,你就能用好这个算法。
| 参数 | 含义 | 对结果的影响 |
|---|---|---|
| eps | 邻域半径 | 太小则很多点被误判为异常,太大则异常点被吞并 |
| min_samples | 核心点的最小邻居数 | 越大则聚类越粗糙,越小则聚类越细碎 |
eps怎么选?我一般先画个k距离图。把每个点到第k近邻的距离排个序,找那个「拐点」。拐点处的距离,就是eps的好选择。
6.3 实战:用DBSCAN检测曲面异常
好,理论说完了,上代码。这是我实际项目中用过的流程,你直接拿去改改就能用。
import numpy as np
import pandas as pd
from sklearn.cluster import DBSCAN
from sklearn.preprocessing import StandardScaler
import matplotlib.pyplot as plt
# 假设我们有一个波动率曲面数据
# 列:行权价、到期时间、隐含波动率
data = pd.read_csv('vol_surface.csv')
X = data[['strike', 'maturity', 'implied_vol']].values
# 标准化——这一步很重要
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# DBSCAN聚类
# eps和min_samples需要根据数据调
db = DBSCAN(eps=0.3, min_samples=5)
labels = db.fit_predict(X_scaled)
# 标记异常点
data['cluster'] = labels
data['is_anomaly'] = (labels == -1)
# 看看结果
print(f"正常点数量: {len(data[data['is_anomaly'] == False])}")
print(f"异常点数量: {len(data[data['is_anomaly'] == True])}")
代码跑完,你会看到标签为-1的那些点,就是DBSCAN认为的异常点。
6.4 参数调优的实战经验
参数调优,说白了就是试。但有个套路可以少走弯路。
我一般这么做:
- 先固定min_samples=5
- 从0.1开始,每次加0.05,试eps
- 观察异常点数量的变化曲线
- 找到曲线「陡降」的那个点——那就是好参数
为什么会这样?因为eps太小的时候,很多正常点也被判为异常。随着eps增大,异常点数量会快速下降。当eps大到一定程度,下降就变缓了。那个拐点,就是密度分界线。
嗯,这里要注意:不同市场的波动率曲面,参数差异很大。股指期权的曲面比较平滑,eps可以设小一点。商品期权的曲面波动大,eps得大一些。我做过一个原油期权的项目,eps设到0.8才出效果。
6.5 知识体系总览
下面这张图,把DBSCAN做异常检测的整个流程串起来了。你照着这个思路走,不会乱。
6.6 避坑指南
做DBSCAN异常检测,有几个坑我踩过,你注意一下:
- 数据量太小别用——DBSCAN需要足够的数据点才能形成密度。少于100个点,效果很差。
- 高维数据要降维——超过5维,距离计算就失效了。曲面数据一般3维,刚好。
- 参数敏感——eps差0.1,结果可能天差地别。多试几次,别偷懒。
好了,DBSCAN这块就聊到这儿。你回去拿自己的数据跑一遍,感受一下参数变化对结果的影响。实践出真知,这话一点不假。