AFML 为金融数据打标签

本文关于为金融数据打标签的方法逐一介绍

Python 代码实现

第三章 为金融数据打标签

3.1 动机

由于金融数据的高噪声和序列自相关性很强,很难预测股价的连续值,那么只能为数据打标签,从而预测离散值。

3.2 打标签

3.2.1 固定时间区间方法

几乎所有机器学习文献都使用了固定时间区间(Fixed-time Horizon, FH)方法对金融数据打标签。

这种方法简单直观,判断规则十分简单。在固定时间内对于某个股票,如果其收益

Image for post

用公式对上述规则进行表述。

Image

其中

Image

举个实际例子,从 2019 年 1 月 27 日开盘时点(,0)开始计算苹果股票10 个 bar 后(h = 10)的收益,得到 r = 0.5%,如果阈值是 0.1%(c = 0.1%),那么打上「涨」的标签。

该方法很常用,但也存在以下两个问题:

  1. 在〖从 Tick 到 Bar〗一帖可知等时抽样的 Time Bar 的统计特征不好

  2. 阈值 c 一直不变,但价格波动率却随时间变化,这就造成了

    • 在波动率很大时,价格很容易突破 [-c, c],因此很少样本会被标注为 0,大量 ±1
    • 而波动率很小时,价格不容易突破 [-c, c],因此很多样本会被标注为 0,少量 ±1

对于上面二个问题,也有两个解决方法:

  1. 将「等时抽样的 Time Bar」换成「等量抽样的 Volume Bar 」和「等额抽样的 Dollar Bar」,因为 Volume Bar 和 Dollar Bar 两个显示的波动率比较稳定。
  2. 指数加权移动平均(Exponential-Weighted Moving Average,EWMA)在收益的时间序列上计算出波动率,做为动态阈值(dynamic threshold)的基干(backbone)。

那么,再计算完波动率之后,可以设定上下阈值

其中, 是缩放因子

3.2.2 三隔栏方法

三隔栏方法(Triple-Barrier,TB)方法是一种路径依赖的标注方法,能够有效地解决上节所提到的止损止盈问题。

为什么要设定三隔栏?

TBFH 方法相似,我们需要三种情况来为数据打上 +1, -1, 0 三个标签,而打哪个标签看价格函数先碰到三隔栏的哪一个。

如何设定三隔栏?

设立两个价格上水平(horizontal)的隔栏和一个时间上垂直(vertical)的隔栏,其中

如何用三隔栏打标签?

如果

  1. 上水平隔栏先被触及,将样本标注为 1
  2. 下水平隔栏先被触及,将样本标注为 -1
  3. 如果垂直隔栏先被触及,将样本标注为 0,或者是该时段内收益的符号,

这显然是一个路径依赖的方法,因为我们需要确定在整个时间区间内三个隔栏是否在某一刻被触及。

我们定义

通常我们有 关系

此外,我们还可以用 来代表隔栏有效状态,其中

这三个状态只能去 0 和 1,0 代表此隔栏无效,1 代表此隔栏有效。三个状态那么可能会有 8 种情况,它们分别是:

Image

三种实际的情况(上图绿 √):

三种不太实际的情况(上图蓝 ?):

两种不合逻辑的*情况*(上图红 ×):

下面三图分别展示了 [1, 1, 1] 标配的三种退出方式。

一. 先碰到「下水平隔栏」而止损退出。

二. 先碰到「上水平隔栏」而止盈退出。

Image

三. 先碰到「竖直隔栏」而超过持有期限退出。

Image

 


Python 实现

数据下载:Stock Price

 DateSymbolOpenHighLowCloseAdj CloseVolume
02018-02-26AAPL176.350006179.389999176.210007178.970001176.28567538162200
12018-02-27AAPL179.100006180.479996178.160004178.389999175.71438638928100
22018-02-28AAPL179.259995180.619995178.050003178.119995175.44841037782100
32018-03-01AAPL178.539993179.779999172.660004175.000000172.37521448802000
42018-03-02AAPL172.800003176.300003172.449997176.210007173.56707838454000
2472019-02-20AAPL171.190002173.320007170.990005172.029999172.02999926114400
2482019-02-21AAPL171.800003172.369995170.300003171.059998171.05999817249700
2492019-02-22AAPL171.580002173.000000171.380005172.970001172.97000118913200
2502019-02-25AAPL174.160004175.869995173.949997174.229996174.22999621873400
2512019-02-26AAPL173.710007175.300003173.169998174.330002174.33000217006000

该函数为了计算上下水平隔栏对应的日期,用 result 来储存。

第 5 - 9 行计算上下水平隔栏的点位(level),用上述公式

其中 σ 是日波动率。而 width = [, ],它们都大于等于 0

当大于 0 时,乘上 σ 得到水平隔栏的点位,存储在 'UB' 和 'DB' 栏下。

当等于 0 时,表明不设定隔栏,那么隔栏的点位就设定为 NaN

第 12 - 13 行代码在每一个窗口都运行,即每一个起始日到它 15 天之后的竖直隔栏对应的日期,计算每天的收益率。

第 16 - 17 行检查每天的收益是否突破隔栏,突破了则记录第一次突破的时点,并储存起来,'' 代表第一次突破上隔栏日期,'' 代表第一次突破下隔栏日期。

 DateVButdtFirst
02018-02-262018-03-13NaTNaT2018-03-13
12018-02-272018-03-14NaTNaT2018-03-14
22018-02-282018-03-152018-03-092018-03-012018-03-01
32018-03-012018-03-162018-03-05NaT2018-03-05
42018-03-022018-03-172018-03-09NaT2018-03-09
2472019-02-202019-03-07NaTNaT2019-03-07
2482019-02-212019-03-08NaTNaT2019-03-08
2492019-02-222019-03-09NaTNaT2019-03-09
2502019-02-252019-03-12NaTNaT2019-03-12
2512019-02-262019-03-13NaTNaT2019-03-13
 DateReturnLabel
02018-02-260.0055871.0
12018-02-270.0002801.0
22018-02-28-0.017516-1.0
32018-03-010.0104001.0
42018-03-020.0213951.0
2362019-02-040.0024121.0
2372019-02-05-0.008108-1.0
2382019-02-06-0.014040-1.0
2392019-02-070.0162151.0
2412019-02-110.0283301.0

img