【问题标题】:How to auto-discover a lagging of time-series data in scikit-learn and classify using time-series data如何在 scikit-learn 中自动发现滞后的时间序列数据并使用时间序列数据进行分类
【发布时间】:2017-06-29 10:48:59
【问题描述】:

我目前有一个巨大的时间序列数组,其中包含多个证券和经济统计的时间序列数据。

我已经编写了一个函数来对数据进行分类,使用 sci-kit learn,但该函数只使用非滞后时间序列数据。

有没有办法,在 Python 中,使用 sci-kit,自动 滞后所有这些时间序列来找到 时间序列(如果有的话)趋向滞后于其他数据?

我正在创建一个使用历史数据来预测未来表现的模型。

【问题讨论】:

  • 能否请您举例说明一下意图?自动声音作为量化建模的超级忍者和因果原理在这些领域处于危险之中(甚至谷歌不久前在使用 TensorFlow 进行预测方面也取得了巨大的“成功”,但是被发现只是犯了一个“窥视未来”的错误,并将他们的主张建立在“负滞后”在现实世界中行不通的不公平利益之上... ),所以这里确实必须注意。 >>> medium.com/@michalillich/…
  • 我试图弄清楚哪些统计数据(如果有的话)往往会引领现实世界的结果,以及它们在多大程度上领先于数据。我有一个预先存在的模型,我正在通过更改/添加额外的输入来改进。我正在尝试为我的模型寻找潜在的额外输入。我使用 sci-kit 构建了一个分类器函数来查找潜在的新输入,但它只对未滞后的数据进行分类。除非我编写一个巨大的嵌套循环来一次将每个数据滞后一个时间段(这将非常低效),否则我将无法看到滞后结果与统计数据的相关性。
  • 是的,避免任何“外部”for循环。请在附件中找到一个全 numpy 解决方案,该解决方案在 scikit-learn 中的特征工程工具的一些不同基础上工作,并具有纯 numpy 技巧的所有功能。本地主机 CPU 和 RAM 限制并不是一个隐藏的玻璃天花板,所以尽情享受吧。

标签: python scikit-learn time-series quantitative-finance


【解决方案1】:

TLDR 但为关心的人添加了一些 QF 宝石

序幕:

“没有免费的晚餐”,所以我们将不得不为想要的结果付出代价,但你知道这是非常值得的它,所以,获得先进的创造力,numpy 实用知识和scikit-learn 工具准备好,并将想象力的音量按钮调到最大。

接下来,不要指望流程会在几秒钟内交付结果。

根据示例 DataSETs 上的 AI/ML 超参数搜索工作计划的经验,跨越大约 X.shape ~ ( 400, 200000 ),最佳通用 ML 引擎超参数化交叉验证通常需要几天时间一个分布式多处理集群。

作为指导进一步 Quant 研究工作的奖励:

来自类似特征工程研究的样本,LDF()/GDF() 指标关于 各个特征的不同预测能力详细阐述为extendedDataSET
如下所述,人们可能会意识到
只是top 1. feature 本身占 43%
接下来的 27 个功能 占 +17%
“其余”360 多个功能剩下的 40% 用于决策作为重要性报告
(
个人特征和滞后前的细节$ 不会在此处公布,因为很明显$ rea$on$
并且可以单独讨论
)

|>>> aFeatureImportancesMAP_v4( loc_PREDICTOR, X_v412 )

 ID.|LDF( fI ) | GDF|HUMAN_READABLE_FEATURE_NAME[COL] min()     | MAX()    | var()
 ___|__________|____|___________________________[___]___________|__________|____________
    |          |    |                           [   ]           |          |
  0. 0.4360231 | 43%| __________xxxxxxxxxxxxxCE [216] min:  ... | MAX: ... | var():  ...
  1. 0.0464851 | 48%| __________xxxxxxxxxxxxx_0 [215] min:  ... | MAX: ... | var():  ...
  2. 0.0104704 | 49%| __________xxxxxxxxxxxxx_1 [251] min:  ... | MAX: ... | var():  ...
  3. 0.0061596 | 49%| __________xxxxxxxxxxxxx_3 [206] min:  ... | MAX: ... | var():  ...
  4. 0.0055069 | 50%| __________xxxxxxxxxxxxx_2 [203] min:  ... | MAX: ... | var():  ...
  5. 0.0053235 | 50%| __________xxxxxxxxxxxxx_3 [212] min:  ... | MAX: ... | var():  ...
  6. 0.0050404 | 51%| ________f_xxxxxxxxxxxxx_7 [261] min:  ... | MAX: ... | var():  ...
  7. 0.0049998 | 52%| ________f_xxxxxxxxxxxxx_7 [253] min:  ... | MAX: ... | var():  ...
  8. 0.0048721 | 52%| __________xxxxxxxxxxxxx_4 [113] min:  ... | MAX: ... | var():  ...
  9. 0.0047981 | 52%| __________xxxxxxxxxxxxx_4 [141] min:  ... | MAX: ... | var():  ...
 10. 0.0043784 | 53%| __________xxxxxxxxxxxxx_3 [142] min:  ... | MAX: ... | var():  ...
 11. 0.0043257 | 53%| __________xxxxxxxxxxxxx_4 [129] min:  ... | MAX: ... | var():  ...
 12. 0.0042124 | 54%| __________xxxxxxxxxxxxx_1 [144] min:  ... | MAX: ... | var():  ...
 13. 0.0041864 | 54%| ________f_xxxxxxxxxxxxx_8 [260] min:  ... | MAX: ... | var():  ...
 14. 0.0039645 | 55%| __________xxxxxxxxxxxxx_1 [140] min:  ... | MAX: ... | var():  ...
 15. 0.0037486 | 55%| ________f_xxxxxxxxxxxxx_8 [252] min:  ... | MAX: ... | var():  ...
 16. 0.0036820 | 55%| ________f_xxxxxxxxxxxxx_8 [268] min:  ... | MAX: ... | var():  ...
 17. 0.0036384 | 56%| __________xxxxxxxxxxxxx_1 [108] min:  ... | MAX: ... | var():  ...
 18. 0.0036112 | 56%| __________xxxxxxxxxxxxx_2 [207] min:  ... | MAX: ... | var():  ...
 19. 0.0035978 | 56%| __________xxxxxxxxxxxxx_1 [132] min:  ... | MAX: ... | var():  ...
 20. 0.0035812 | 57%| __________xxxxxxxxxxxxx_4 [248] min:  ... | MAX: ... | var():  ...
 21. 0.0035558 | 57%| __________xxxxxxxxxxxxx_3 [130] min:  ... | MAX: ... | var():  ...
 22. 0.0035105 | 57%| _______f_Kxxxxxxxxxxxxx_1 [283] min:  ... | MAX: ... | var():  ...
 23. 0.0034851 | 58%| __________xxxxxxxxxxxxx_4 [161] min:  ... | MAX: ... | var():  ...
 24. 0.0034352 | 58%| __________xxxxxxxxxxxxx_2 [250] min:  ... | MAX: ... | var():  ...
 25. 0.0034146 | 59%| __________xxxxxxxxxxxxx_2 [199] min:  ... | MAX: ... | var():  ...
 26. 0.0033744 | 59%| __________xxxxxxxxxxxxx_1 [ 86] min:  ... | MAX: ... | var():  ...
 27. 0.0033624 | 59%| __________xxxxxxxxxxxxx_3 [202] min:  ... | MAX: ... | var():  ...
 28. 0.0032876 | 60%| __________xxxxxxxxxxxxx_4 [169] min:  ... | MAX: ... | var():  ...
 ...
 62. 0.0027483 | 70%| __________xxxxxxxxxxxxx_8 [117] min:  ... | MAX: ... | var():  ...
 63. 0.0027368 | 70%| __________xxxxxxxxxxxxx_2 [ 85] min:  ... | MAX: ... | var():  ...
 64. 0.0027221 | 70%| __________xxxxxxxxxxxxx_1 [211] min:  ... | MAX: ... | var():  ...
 ...
104. 0.0019674 | 80%| ________f_xxxxxxxxxxxxx_3 [273] min:  ... | MAX: ... | var():  ...
105. 0.0019597 | 80%| __________xxxxxxxxxxxxx_6 [ 99] min:  ... | MAX: ... | var():  ...
106. 0.0019199 | 80%| __________xxxxxxxxxxxxx_1 [104] min:  ... | MAX: ... | var():  ...
 ...
169. 0.0012095 | 90%| __________xxxxxxxxxxxxx_4 [181] min:  ... | MAX: ... | var():  ...
170. 0.0012017 | 90%| __________xxxxxxxxxxxxx_3 [  9] min:  ... | MAX: ... | var():  ...
171. 0.0011984 | 90%| __________xxxxxxxxxxxxx_4 [185] min:  ... | MAX: ... | var():  ...
172. 0.0011926 | 90%| __________xxxxxxxxxxxxx_1 [ 19] min:  ... | MAX: ... | var():  ...
 ...
272. 0.0005956 | 99%| __________xxxxxxxxxxxxx_2 [ 33] min:  ... | MAX: ... | var():  ...
273. 0.0005844 | 99%| __________xxxxxxxxxxxxx_2 [127] min:  ... | MAX: ... | var():  ...
274. 0.0005802 | 99%| __________xxxxxxxxxxxxx_3 [ 54] min:  ... | MAX: ... | var():  ...
275. 0.0005663 | 99%| __________xxxxxxxxxxxxx_3 [ 32] min:  ... | MAX: ... | var():  ...
276. 0.0005534 | 99%| __________xxxxxxxxxxxxx_1 [ 83] min:  ... | MAX: ... | var():  ...
 ...
391. 0.0004347 |100%| __________xxxxxxxxxxxxx_2 [ 82] min:  ... | MAX: ... | var():  ...

因此,与其计划和保留更多的 vCPU 内核容量
而不是期望它仅在即将到来的午餐时间在笔记本电脑上运行此类搜索...


让我们制定一个工作计划

预期的auto-find服务,由于多种原因,不是scikit-learn的一部分,但是,目标是可以实现的。

我们将使用以下适应步骤,这将使我们能够使其工作:

  1. 我们将依靠 scikit-learn 的能力来搜索 [learner + hyperparameters] 的最佳串联,以获得定义明确的 AI/ML问题

  2. 我们将依靠 numpy 权力来支持scikit-learn 阶段

  3. 我们将依赖相当合适的scikit-learn AI/ML 引擎处理和过程控制(pipelineGridSearchCV 等),它们在低级性能上得到了更好的优化对于如此大规模的攻击,而不是尝试依赖“外部”协调的 for-循环(这会丢失所有有价值的缓存/数据局部性进步)并且已知显着的性能劣势。

  4. 我们将用快速、一步、先验的DataSET 适应替换希望的自动发现

  5. 我们会让scikit-learn决定(定量表示)哪些预先滞后的特征,人工合成到[4]中阐述的复合DataSET最终具有最好的预测能力


[4]DataSET智能适配numpy辅助:

您的 DataSET 包含未指定计数的 TimeSeries 数据。对于每个此类,您假设某些预滞后可能具有您希望找到的更好的预测能力(在数量上支持选择此类,用于最终的 ML 预测器)。

所以让我们首先在DataSET 的源部分中为每个TimeSerie DataSET[i,:] 构造DataSET 的扩展部分,其中包含此TimeSerie 的相应预滞后版本:

>>> def generate_TimeSERIE_preLAGs( aTimeSERIE, pre_lag_window_depth ):
...     #
...     # COURTESY & THANKS TO:
...     #                     Nicolas P. Rougier, INRIA
...     #             Author: Joe Kington / Erik Rigtorp
...     #
...     shape   = ( aTimeSERIE.size - pre_lag_window_depth + 1,
...                 pre_lag_window_depth
...                 )
...     strides = ( aTimeSERIE.itemsize,
...                 aTimeSERIE.itemsize
...                 )
...     return np.lib.stride_tricks.as_strided( aTimeSERIE,
...                                             shape,
...                                             strides = strides
...                                             )
...
>>> xVECTOR = np.arange( 10 )
>>>
>>> pre_laggz_on_xVECTOR = generate_TimeSERIE_preLAGs( xVECTOR, 4 )
>>>
>>> pre_laggz_on_xVECTOR
array([[0, 1, 2, 3],
       [1, 2, 3, 4],
       [2, 3, 4, 5],
       [3, 4, 5, 6],
       [4, 5, 6, 7],
       [5, 6, 7, 8],
       [6, 7, 8, 9]])
>>>

有了这样的扩展(更广泛,你知道很多)但静态extendedDataSET,现在包含原始TimeSERIE 向量和所有希望测试的预滞后版本至此,您的 ML 搜索就开始了。

阶段[1.A]
最初使用 scikit-learn 工具进行支持您的假设的最佳特征选择
+
阶段 [1.B]
下一步开始超参数优化以获得最佳交叉验证结果,支持最大学习者的泛化能力。

阶段[1.B],自然应该在extendedDataSET 的子集上运行(为了在特征选择阶段[1.A] 中进行scikit-learn 评估而有意扩展)。


结语:
Memento mori: Quants 不喜欢这样……但是

为了您对时间序列分析和定量建模的进一步兴趣,you might be interested in the best answer on this >>>

相关性并不意味着因果关系,因此在做出要执行的决策时需要更加小心(纸总是比市场可以处理更多的事情:o))。

【讨论】:

  • OP 已经拒绝了一个涉及不免费享用晚餐的答案。 (但我喜欢你的文章。)
  • 很抱歉我的措辞选择...我想在 16 小时以上的工作日之后,我表达自己想法的能力往往会付诸东流。 “自动”可能不是最好的选择....然而,我觉得这种骗局是没有根据的....
  • 没有必要为选词感到难过。您已决定设计一个功能非常强大的工具,而复杂性在您进一步的发现路径中很常见。祝你好运和坚持,希望你喜欢上面的几分钱和故事。
【解决方案2】:

没有。在 Python 中,没有办法使用 sci-kit自动 滞后所有这些时间序列,以找出哪些时间序列(如果有)往往滞后于其他数据。 您必须编写一些代码

【讨论】:

  • 是的,完全正确。即使是 量子计算新时代的承诺也不会免费提供任何这样的晚餐,正如在下面 [结语] 部分中发布的更长的故事中所报道的那样 >>> stackoverflow.com/a/37214127/3666197
【解决方案3】:

试试这个

import pandas as pd
import numpy as np
from sklearn.base import BaseEstimator, TransformerMixin

class InsertLags(BaseEstimator, TransformerMixin):
    """
    Automatically Insert Lags
    """
    def __init__(self, lags):
        self.lags = lags

    def fit(self, X, y=None):
        return self

    def transform(self, X, y=None):
        original_cols=list(range(len(X[0,:])))
        for lag in self.lags:
            X_lagged=pd.DataFrame(X[:,original_cols]).shift(lag).as_matrix()
            X=np.concatenate((X,X_lagged), axis=1)
        return X

然后测试一下

add_lags=InsertLags([1,2,3])

test=np.array([[1,3,5,7,9],
      [2,4,6,8,10]]).T

test

add_lags.fit_transform(test)

这应该会创建一个自动创建滞后的 sklearn 转换器。如果需要,可以将 original_cols 作为类的初始化函数的一部分,以便选择性地滞后变量。

【讨论】:

    【解决方案4】:

    您可以简单地使用numpy.roll()。不要忘记擦除缠绕的元素,例如你不想要[6,7,1,2,3,4,5],而是[NA,NA,1,2,3,4,5]

    【讨论】:

    • 这将涉及必须遍历每个证券并为每个给定的滞后量运行回归/分类......我正在寻找一个可以更有效地执行此操作的预先存在的库。
    猜你喜欢
    • 2021-07-06
    • 2019-04-04
    • 2015-08-01
    • 2015-06-27
    • 2016-10-01
    • 2017-05-09
    • 2019-12-13
    • 2015-08-16
    • 1970-01-01
    相关资源
    最近更新 更多