基于无监督学习的期权定价异常检测(代码+数据)

论坛 期权论坛 期权     
量化投资与机器学习   2019-8-24 18:59   5493   0
标星★公众号,第一时间获取最新研究
本期作者:Boris B
作者介绍:1+1=6


近期原创文章:
[h1] 啥是佩琪?恕我直言,搞量化这样配齐![/h1][h1] 深入研读:利用Twitter情绪去预测股市[/h1][h1] Two Sigma用新闻来预测股价走势,带你吊打Kaggle[/h1][h1] 利用深度学习最新前沿预测股价走势
[/h1][h1] 一位数据科学PhD眼中的算法交易[/h1][h1] 基于RNN和LSTM的股市预测方法[/h1][h1] 人工智能『AI』应用算法交易,7个必踩的坑!
[/h1][h1] 神经网络在算法交易上的应用系列(一)[/h1][h1] 预测股市 | 如何避免p-Hacking,为什么你要看涨?[/h1][h1] 如何鉴别那些用深度学习预测股价的花哨模型?[/h1][h1] 优化强化学习Q-learning算法进行股市交易[/h1]



明  天  就  上  班  啦  ~




前言

本文是一部分预测股价内容。结果(识别出的异常)是LSTM模型(在GAN体系结构中)中的一个特征(输入)具体请看这篇文章:


[h1]【2万字干货】利用深度学习最新前沿预测股价走势[/h1][h1]
[/h1]动机

期权估值是一项非常困难的工作。首先,它需要使用大量的数据点,其中一些是非常主观的(如隐含波动率——见下文),很难精确计算。作为一个例子让我们调用的θ,θ的计算:







其中,N(d1)和N(d2)为标准正态分布的累积分布函数,分别为:






期权定价难易的另一个例子是Black-Scholes公式,它用于计算期权价格本身。以t为期限,以S0为当期价格的欧式看涨期权价格计算公式为:






其次,Black-Scholes模型,也被称为二叉树,需要满足很多假设才能使模型准确。然而,这些规则在现实生活中往往无法实现。其中包括:


1、该模型假设基础波动率(σ)在期权的整个期间内保持不变,不受基础股票价格水平变化的影响。很多时候,波动性随着执行价格的变化而变化——执行价格与基础价格之间的差异越大,波动性就越大。这种现象被称为波动微笑(见下图)。


2、假设一个恒定的无风险回报率(随着全球经济每天的变化,这很难预测)。


3、该模型不考虑流动性风险和额外费用。


4、假设股票收益服从对数正态分布(即模型忽略了价格大幅偏离、暴涨或下跌的可能性,而这些在实际交易中很容易观察到)。


5、假设没有派息。股利支付改变了股票的当前估值,这反过来又会改变期权价格。


5、该模型仅适用于欧式期权。

获取全部代码,见文末

  1. """
  2. ===== IMPORTANT:
  3. Execute the following code cells (below) first in order to instantiate the 'options_df' dataframe
  4. """
  5. curr_price_ = options_df.iloc[0,0]
  6. plt.figure(figsize=(10, 6))
  7. plt.scatter(options_df.Strike, options_df.IVAsk, label='IV to Strike', \
  8.             c='royalblue')
  9. plt.vlines(curr_price_, options_df.IVAsk.min(), \
  10.            options_df.IVAsk.max(), \
  11.            label='Current GS price - ${}'.format(curr_price_), \
  12.            linestyles='--', colors='gray')
  13. plt.xlabel('Strike price - $')
  14. plt.ylabel('IV')
  15. plt.title('Options Volatility smile')
  16. plt.legend(fontsize='large')
  17. plt.savefig('imgs/Options/volatilitysmile.jpg', dpi=100)
  18. plt.show()
复制代码



不是一个完美的波动微笑,只使用了一天的数据


上述假设在现实生活中很少得到满足,这正是可以观察到异常现象的原因。这反过来又创造了许多我们可以利用机器学习/深度学习来探索和利用的机会,比如套利交易


希腊值(Greeks值)的选择很重要,以便我们充分了解异常检测是否正确,简要介绍一下:


隐含波动率-σ:隐含波动率是一个衡量的估计价格可能会改变多少。更高的数字意味着交易员相信期权可能会带来巨大的变化。基本上就是波动指数。


Delta-δ:Delta衡量期权价格相对于标的股票价格变化的变化程度。 Delta为0.5意味着股票移动每1美元期权将变为50美分(δ是价格的一阶导数)。


Gamma-γ:γ测量当股票价格变化时δ的变化速度。数值很大意味着这是一个非常“活跃”的选项 ,并且可以快速获得或损失价值(γ是价格的二阶导数)。


Theta-θ:θ衡量由于时间衰减,期权每天损失的速度。随着到期日的临近,theta增加。


Vega:vega衡量期权价格对隐含波动率变化的敏感程度。非现金期权或到期前较长的期权对隐含波动率的变化更为敏感,


Rho:rho是衍生品价格相对于无风险利率变化的变化率。


数据
  1. # Filtered options data for Goldman Sachs
  2. options_df = pd.read_csv('option_GS_df.csv', parse_dates=["Expiration", ' DataDate'])
  3. options_df['date_diff'] = (options_df['Expiration'] - options_df[' DataDate']).dt.days
  4. options_df['Spread'] = options_df['Ask'] - options_df['Bid']
复制代码

使用的数据是2016年1月5日高盛期权的每日报价。它包含了不同到期日的定价(加上波动性和greeks)以及在那一天产生的行权价格。当日的现价(GS)为174.09美元。有22个特征和858行。

获取全部代码,见文末

[/quote]options_df.shape
output >>> (858, 22)
  1. print(', '.join(x for x in options_df.columns))
  2. output >> UnderlyingPrice, OptionSymbol, Type, Expiration,
  3. DataDate, Strike, Last, Bid, Ask, Volume, OpenInterest,
  4. T1OpenInterest, IVMean, IVBid, IVAsk, Delta, Gamma,
  5. Theta, Vega, AKA, date_diff, Spread
复制代码

基本上我们需要的所有功能都是可用的。让我们把数据可视化成一个配对图,其中:


  • 绘制的特征是Strike、Bid、Delta、Gamma、Vega和Spread。
  • 色调是选项的类型(看涨或看跌)。
  • 对角线是每个特征的分布。

  1. sns_options_colors = ["#9b59b6", "#3498db"]
  2. sns_options_vars = ['Strike', 'Bid', 'Delta', \
  3.                     'Gamma', 'Vega', 'Spread']
  4. sns.set_palette(sns.color_palette(sns_options_colors))
  5. sns.set_context("paper", rc={"axes.labelsize": 22})
  6. options_g = sns.pairplot(options_df, \
  7.                          vars=sns_options_vars, \
  8.                          diag_kind='kde', \
  9.                          hue='Type', \
  10.                          markers=["o", "x"], \
  11.                          plot_kws=dict(edgecolor='white', \
  12.                                        linewidth=.85, alpha=.85), \
  13.                          diag_kws=dict(shade=True),\
  14.                          height=5)
  15. for i, j in zip(*np.triu_indices_from(options_g.axes, 1)):
  16.     options_g.axes[i, j].set_visible(False)
  17. xlabels, ylabels = [], []
  18. for ax in options_g.axes[-1,:]:
  19.     xlabel = ax.xaxis.get_label_text()
  20.     xlabels.append(xlabel)
  21. for ax in options_g.axes[:,0]:
  22.     ylabel = ax.yaxis.get_label_text()
  23.     ylabels.append(ylabel)
  24. i,j=0,0
  25. for i in range(len(xlabels)):
  26.     for j in range(len(ylabels)):
  27.         options_g.axes[j,i].xaxis.set_label_text(col_names_pairplot[xlabels[i]])
  28.         options_g.axes[j,i].yaxis.set_label_text(col_names_pairplot[ylabels[j]])
  29. plt.savefig('imgs/Options/options_pairplot.jpg')
  30. plt.show()
复制代码




无监督学习查找异常值

什么是异常?在通常情况下,异常是选项逻辑中的任何不匹配。例如,两个执行价格相同但在执行日相差1-2天的看涨期权的买入价(或卖出价)应该几乎相同(除非有不寻常的情况,这种情况可能在greeks以某种方式得到了解释)。因此,这两种期权的买入价格之间的差异将不是“正常的”。或者,例如,高Theta或小Vega的(OTM)选项有很长的到期时间。等等。



[quote]我们将再次跳过期权定价背后的技术和数学方面(如随机过程、布朗运动和扩散方程)。相反,我们试图看看是否可以利用机器学习来使用数据近似所有这些数学公式(数据驱动方法而不是模型驱动方法)。结果可能不像原来的公式那样精确,但计算量较小。或者,另一方面,机器学习可以“学习”如何执行金融模型(如期权定价),甚至比金融数学更好,因为我们可以在模型中加入许多新的方法和数据,允许模型揭示人类隐藏的模式和相关性。

为了检测异常,我们将使用孤立森林(Isolation Forest)。




GS期权数据(x轴是当前价格和行使价格之间的差异,y轴是买入价和卖出价的平均值 - 基本上是期权的价格),其中圆圈表示看涨期权,星星表示看跌期权。 聚类颜色基于Vega。


让我们将一个交易日(2016/01/05)的期权数据可视化,看看我们能否直观地识别异常。有几件事看起来可疑——这些可能或不是异常现象:




GS选项数据(遵循图1中的逻辑),但聚类颜色基于Delta。


在图2中 - 考虑到合约具有相同的特征,买入/卖出的平均值,当前价格与执行价格之间的差异,非常非常接近的到期日期,如果订购合约的价格小于其它合约,则很奇怪。是底部的选项,蓝色包围着灰色的颜色(它有点隐藏)。在另一边,有一个相同异常的调用:紫色圆圈被灰色圆圈包围。




GS期权数据(x轴是Delta,y轴是当前价格和行使价之间的差异)。 聚类颜色基于Delta,聚类形状(圆形,方形,加号和x)基于Theta。


在图3中(右侧)有几个看涨期权(我们知道它们是看涨期权,因为看涨期权有一个正的delta,介于0和1之间),Theta的范围明显更低 - 圆圈的θ小于-4.5,考虑到具有相同特征的其他选项(附近)具有高于-1.5。





GS期权数据(x轴是Delta,y轴是Spread),其中聚类颜色范围来自Bid和Ask的平均价格。


我们感兴趣的主要特征是买入/卖出价格(或我们创建的特征:平均值)和点差(=卖出价)。 从理论上讲,相同类型、接近执行价格和到期日的期权价格和价差不应存在显著差异。


好的,让我们进入异常检测。我们来打赌:通过数据分布,算法将学习这些optoins规则,并设法找出不遵循“平均”分布的数据点。

获取全部代码,见文末

  1. it_X_train = options_df[['Strike', 'Delta', 'Gamma', 'date_diff']]
  2. it_X_train['s_k'] = options_df['UnderlyingPrice'] - options_df['Strike']
  3. it_X_train['b_a_mean'] = (options_df['Bid'] + options_df['Ask']) / 2
  4. it_X_train['b_a_mean'] = it_X_train['b_a_mean'].apply(lambda x: int(round(x, 0)))
  5. it_X_train['s_k'] = it_X_train['s_k'].apply(lambda x: int(round(x, 0)))
复制代码

我们不会使用所有的特征来检测异常。我们使用的特征是:

  1. print(', '.join(col_names[x] for x in it_X_train.columns))
  2. output >>> Strike, Delta, Gamma, Difference between Date of valuation and Exercise date, Difference between Current and Strike prices, Average of Bid and Ask.
复制代码

我们为什么要使用这些特征?我们希望使用的特征应该遵循上面描述的选项逻辑。


孤立森林的逻辑非常简单:

  1. clf = IsolationForest(max_samples='auto', contamination=.025,\
  2.                       n_estimators=10, \
  3.                       random_state=19117, max_features=it_X_train.shape[1])
  4. clf.fit(it_X_train)
  5. y_pred_train = clf.predict(it_X_train)
复制代码

结果

让我们把模型的结果可视化。x轴是当前和执行价格之间的差值,y轴是买入价和卖出价的平均值。蓝色的x和紫色的圆分别是看跌和看涨期权,在特征分布中没有异常。其他的则是异常现象。


获取全部代码,见文末


[quote][/quote]
  1. it_outlier = -1
  2. sns_options_colors = ["#9b59b6", "#3498db"]
  3. sns.set_palette(sns.color_palette(sns_options_colors))
  4. sns.set_context("paper", rc={"axes.labelsize": 10})
  5. plt.figure(figsize=(14, 8))
  6. it_x_ = 's_k'
  7. it_y_ = 'b_a_mean'
  8. plt.scatter(it_X_train[(it_X_train['y']==1) & (it_X_train['Type']=='put')][it_x_], \
  9.             it_X_train[(it_X_train['y']==1) & (it_X_train['Type']=='put')][it_y_], \
  10.             label='Normal put', c=sns_options_colors[1], s=10*4, alpha=.55, marker='x')
  11. plt.scatter(it_X_train[(it_X_train['y']==1) & (it_X_train['Type']=='call')][it_x_], \
  12.             it_X_train[(it_X_train['y']==1) & (it_X_train['Type']=='call')][it_y_], \
  13.             label='Normal call', c=sns_options_colors[0], s=10*4, alpha=.55, marker='o')
  14. plt.scatter(it_X_train[(it_X_train['y']==-1) & (it_X_train['Type']=='call')][it_x_], \
  15.             it_X_train[(it_X_train['y']==-1) & (it_X_train['Type']=='call')][it_y_], \
  16.             label='Anomaly call', c='red', s=60*4, edgecolor='black', marker='o', alpha=.7)
  17. plt.scatter(it_X_train[(it_X_train['y']==-1) & (it_X_train['Type']=='put')][it_x_], \
  18.             it_X_train[(it_X_train['y']==-1) & (it_X_train['Type']=='put')][it_y_], \
  19.             label='Anomaly put', c='orange', s=60*4, edgecolor='black', marker='x')
  20. plt.xlabel(col_names[it_x_])
  21. plt.ylabel(col_names[it_y_])
  22. plt.legend(fontsize='medium')
  23. plt.savefig('imgs/Options/it_result_options.jpg', dpi=200)
  24. plt.show()
复制代码





这些是孤立森林识别出的异常。尽管从上一张图表中看不到,因为我们似乎无法修复python和Tableau之间的y轴刻度,所识别的异常(红色和橙色)是我们在上面的4个图(交叉引用了每个合约的索引)。

  1. sns_options_colors = ["#f9a602", "#3498db"]
  2. sns_options_vars = ['b_a_mean', 'Delta', 'Gamma', 's_k', 'date_diff']
  3. sns.set_palette(sns.color_palette(sns_options_colors))
  4. sns.set_context("paper", rc={"axes.labelsize": 14})
  5. options_g = sns.pairplot(it_X_train, \
  6.                          vars=sns_options_vars, \
  7.                          diag_kind='kde', \
  8.                          hue='y', \
  9.                          markers=["o", "x"], \
  10.                          plot_kws=dict(edgecolor='white', \
  11.                                        linewidth=.85, alpha=.85), \
  12.                          diag_kws=dict(shade=True),\
  13.                          height=3)
  14. for i, j in zip(*np.triu_indices_from(options_g.axes, 1)):
  15.     options_g.axes[i, j].set_visible(False)
  16. xlabels, ylabels = [], []
  17. for ax in options_g.axes[-1,:]:
  18.     xlabel = ax.xaxis.get_label_text()
  19.     xlabels.append(xlabel)
  20. for ax in options_g.axes[:,0]:
  21.     ylabel = ax.yaxis.get_label_text()
  22.     ylabels.append(ylabel)
  23. for i in range(len(xlabels)):
  24.     for j in range(len(ylabels)):
  25.         options_g.axes[j,i].xaxis.set_label_text(col_names_pairplot[xlabels[i]])
  26.         options_g.axes[j,i].yaxis.set_label_text(col_names_pairplot[ylabels[j]])
  27. plt.savefig('imgs/Options/it_result_pairplot.jpg', dpi=100)
  28. plt.show()
复制代码


橙色点代表异常,蓝色点代表正常


从这对图中可以观察到期权定价异常的几个例子:


  • 平均价格(买价和卖价的平均值)高于其他期权。


  • 平均分布在不同的到期日(尽管原始数据主要分布在较近的到期日)。


  • 目前减去执行价格不是正态分布的原始数据。


  • 如上所述,我们对股票期权定价进行异常检测,以便将其作为预测高盛股价走势的一项功能。


期权定价异常对于预测股价走势有何重要性?请看:


[h1]【2万字干货】利用深度学习最新前沿预测股价走势[/h1]
那么我们将从选项数据和异常检测中使用什么?选项数据非常大。 我们每个交易日都有:


  • 不同到期日的期权价格(期权合约的时间范围,例如90天合约,180天等)。
  • 不同执行价格的期权价格。
  • 看涨期权和看跌期权的期权价格。
  • greeks。
  • 在IV,IVBid,IVAsk,IVMean中。

  1. print('So for every day of the training data we have {} data points.'.\
  2.       format(options_df.shape[0]*options_df.shape[1]))
  3. So for every day of the training data we have 18876 data points.
复制代码

显然,我们不能每天都包含18887个特征。因此,我们将只包含60和90天的看涨期权,并将执行价与当前价格(买入价和卖出价的平均值)相等,加上和减去5%,10%和20%。还有delta,gamma和差价。共有12个特征。


在异常检测部分,我们将创建一个布尔特征,显示在执行价格或到期日期的当天是否检测到异常。当然,用一个数字来表示偏差的严重程度会好得多。我们将把它留到后面的阶段。这意味着我们的总数据集中增加了13个新特征(共有125个特征)。


这里只是展示了如何尝试在一天内进行异常检测。对于LSTM,我们将所有数据(所有日期)放在一起。日期本身对于异常检测并不重要,因为我们使用的是估值日期和到期日期之间的差异。对于每个异常,我们将1(表示异常)分配给训练数据中的相应日期。


使用自动编码器对异常检测也很有意义。



原文:
https://towardsdatascience.com/unsupervised-learning-for-anomaly-detection-in-stock-options-pricing-e599728958c7


推荐阅读

01、经过多年交易之后你应该学到的东西(深度分享)

02、监督学习标签在股市中的应用(代码+书籍)
03、全球投行顶尖机器学习团队全面分析

04、使用Tensorflow预测股票市场变动
05、使用LSTM预测股票市场基于Tensorflow
06、美丽的回测——教你定量计算过拟合概率
07、利用动态深度学习预测金融时间序列基于Python
08、Facebook开源神器Prophet预测时间序列基于Python
09、Facebook开源神器Prophet预测股市行情基于Python
10、2018第三季度最受欢迎的券商金工研报前50(附下载)

11、实战交易策略的精髓(公众号深度呈现)
12、Markowitz有效边界和投资组合优化基于Python
13、使用LSTM模型预测股价基于Keras
14、量化金融导论1:资产收益的程式化介绍基于Python
15、预测股市崩盘基于统计机器学习与神经网络(Python+文档)
16、实现最优投资组合有效前沿基于Python(附代码)
17、精心为大家整理了一些超级棒的机器学习资料(附链接)
18、海量Wind数据,与全网用户零距离邂逅!
19、机器学习、深度学习、量化金融、Python等最新书籍汇总下载
20、各大卖方2019年A股策略报告,都是有故事的人!


如何获取代码

后台输入
20190210
后台获取方式介绍




扫码关注我们

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:55
帖子:13
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP