本文是一个由多局部组成的系列文章的第二篇,该系列文章展现了FlinkSQL利用于市场数据的性能和可表白性。万一您错过了它,第一局部从计算流VWAP的简略状况开始。该系列的代码和数据可在github上取得。
速度在金融市场上至关重要。无论指标是最大化alpha还是最大水平地缩小危险,金融技术人员都会投入大量资金,以获取无关市场情况以及行情的最新见解。事件驱动和流式解决体系结构可在事件产生时对事件进行简单的解决,使其很天然地适宜金融市场利用。

Flink SQL是一种数据处理语言,可用于事件驱动和流应用程序的疾速原型设计和开发。Flink SQL将SQL的简略性和可拜访性与Apache Flink(一种风行的分布式流媒体平台)的性能和可伸缩性联合在一起。借助Flink SQL,业务剖析人员、开发人员和量化人员都能够疾速建设流传输管道,以实时执行简单的数据分析。

在本文中,咱们将应用Simudyne开发的基于代理的模型(ABM)生成的综合市场数据。ABM并不是自上而下的办法,而是在简单零碎中对自主参与者(或代理)进行建模,例如,金融市场中的各种买卖双方。能够捕捉这些交互,并能够针对许多应用程序剖析生成的综合数据集,例如用于检测紧急欺诈行为的培训模型,或摸索风险管理的“假如”场景。ABM生成的综合数据在历史数据有余或不可用的状况下很有用。

1 盘中VaR

危险价值(VaR)是风险管理中宽泛应用的指标。它有助于辨认危险敞口,为交易前的决策提供根据,并报告给监管机构进行压力测试。在给定的置信度和工夫范畴内,VaR将危险示意为货币金额,批示资产将来可能产生的最坏损失。例如,AAPL的1天10美元的99%VaR示意100的99倍,第二天AAPL的损失不会超过10美元。

计算股票的VaR的一种常见办法是获取历史日末收益(例如最近500个交易日的每日收盘价变动)并将其视为可能的将来收益的散布。VaR是第99个百分位数(或500天中第5个最差回报率)的最差每日收益乘以以后资产值。假如收益率遵从正态分布,则计算VaR的另一种办法是将标准偏差乘以与所需置信区间绝对应的z分数,在本例中,均值的99%置信区间为-2.58。将后果数字加到均匀收益上,而后乘以以后资产价值即可得出VaR。

图片起源:https://spot.pcc.edu/~evega/ConfidenceIntervals.html
在大多数市场危险利用中,VaR公式是基于日末定价并每天分批计算的。自从JP Morgan在1980年代创造VaR以来,这种做法在风险管理中很广泛。从那时起,钻研人员提出了用于计算日内VaR的办法[1],该办法受古代市场一直倒退的构造和动静驱动:

在过来的几年中,交易速度始终在一直进步。即日交易,当初是场内交易者的专属区域,当初所有投资者都能够应用。“高频金融对冲基金”曾经成为对冲基金的一个胜利的新类别。因而,风险管理当初必须与市场放弃同步。对于日间交易者,做市商或市场上其余沉闷的经纪人,应以短于每日的工夫距离评估危险,因为他们的投资期限通常少于一天。

本文中,咱们探讨了如何应用流式SQL从实时报价数据流中计算日内VaR(IVaR)。具体来说,咱们将依据前5分钟的定价数据,每秒计算出99%的IVaR。在本练习中,咱们将应用Simudyne生成的综合市场数据。他们为咱们提供了CSV格局的1级刻度数据,以实现虚构安全性(“ SIMUl ”):

time,sym,best_bid_prc,best_bid_vol,tot_bid_vol,num,sym,best_ask_prc,best_ask_vol,tot_ask_vol,num2020-10-22 08:00:00.000,SIMUl,149.34,2501,17180,1,SIMUl,150.26,2501,17026,12020-10-22 08:00:01.020,SIMUl,149.34,2901,17580,2,SIMUl,150.26,2501,17026,12020-10-22 08:00:02.980,SIMUl,149.36,3981,21561,1,SIMUl,150.26,2501,17026,12020-10-22 08:00:05.000,SIMUl,149.36,3981,21561,1,SIMUl,149.86,2300,19326,12020-10-22 08:00:05.460,SIMUl,149.36,3981,21561,1,SIMUl,149.86,6279,23305,22020-10-22 08:00:05.580,SIMUl,149.36,3981,21561,1,SIMUl,149.86,6279,23305,22020-10-22 08:00:06.680,SIMUl,149.36,3981,21561,1,SIMUl,149.86,6279,23305,22020-10-22 08:00:07.140,SIMUl,149.74,582,22143,1,SIMUl,149.86,6279,23305,22020-10-22 08:00:07.600,SIMUl,149.74,582,22143,1,SIMUl,149.86,2044,19070,12020-10-22 08:00:08.540,SIMUl,149.74,582,22143,1,SIMUl,149.86,2044,19070,1

级别1的报价数据在给定的即时工夫内传播了证券交易簿中的最佳买入价和最佳卖出价。咱们次要关注交易种类和工夫戳,以及市场中间价,咱们能够通过均匀最佳买入价和要价来获取中间价。为了使Flink SQL解决此数据,咱们首先通过以下语句申明一个流表:

    event_time     TIMESTAMP(3),    symbol         STRING,    best_bid_prc   DOUBLE,    best_bid_vol   INT,    tot_bid_vol    INT,    num            INT,    sym2           STRING,    best_ask_prc   DOUBLE,    best_ask_vol   INT,    tot_ask_vol    INT,    num2           INT,    WATERMARK FOR event_time AS event_time - INTERVAL '5' SECONDS) WITH (    'connector' = 'filesystem',    'path' = '/path/to/varstream/data/l1_raw',    'format' = 'csv') ;

2 Flink SQL中的工夫序列采样

为了计算IVaR,咱们须要在过来5分钟内调配每秒回报(两头价格与前一秒的变动百分比)。如果咱们将L1数据视为一个工夫序列,则须要每秒采样一次两头价格。实现此目标的一种办法是向前填充:每秒采样的两头价格是该秒之前或该秒之前的最初察看到的两头价格。

本能地,咱们能够尝试应用翻滚窗口来执行此操作,就像咱们在第一局部中计算VWAP所做的那样。然而,此办法将不起作用。思考上面的滚动窗口查问:

SELECT        symbol,        TUMBLE_START (event_time, INTERVAL '1' SECOND) AS start_time,        TUMBLE_ROWTIME (event_time, INTERVAL '1' SECOND) AS row_time,        LAST_VALUE (best_bid_prc) AS best_bid_prc,        LAST_VALUE (best_ask_prc) AS best_ask_prc    FROM        l1    GROUP BY        TUMBLE (event_time, INTERVAL '1' SECOND), symbol    LIMIT 20

滚动窗口可能会导致间隙,如下所示。

该查问在8 : 00: 03,8 : 00 :04和8:00:13没有产生任何记录。这是因为在源L1数据中,在第二个工夫距离内没有事件。潜在地,能够通过应用跳跃窗口来解决此问题,并具备足够的回溯期以确保在此期间察看到一个事件:

   SELECT       symbol,       HOP_START (event_time, INTERVAL '1' SECOND, INTERVAL '120' SECONDS) AS start_time,       HOP_ROWTIME (event_time, INTERVAL '1' SECOND, INTERVAL '120' SECONDS) AS row_time,       LAST_VALUE (best_bid_prc) AS best_bid_prc,       LAST_VALUE (best_ask_prc) AS best_ask_prc   FROM       l1   GROUP BY       HOP (event_time, INTERVAL '1' SECOND, INTERVAL '120' SECONDS), symbol   LIMIT 20

可怜的是,上述查问无奈运行,因为在编写本文时,LAST_VALUE函数不适用于跳跃窗口。Flink社区正在致力于修复(FLINK-20110)。同时,咱们提出了一种不依赖于跳变窗口或回溯期的解决办法。

首先,咱们得出每行的无效工夫范畴(开始和完结工夫):

CREATE VIEW l1_times AS    SELECT        symbol,        MIN (event_time) OVER w AS start_time,        CAST (event_time AS TIMESTAMP) AS end_time,        FIRST        FIRST_VALUE (best_ask_prc) OVER w AS ask_price    FROM l1    WINDOW w AS (        PARTITION BY symbol        ORDER BY event_time        ROWS BETWEEN 1 PRECEDING AND CURRENT ROW    );

*请留神应用MIN(event_time)而不是FIRST_VALUE(event_time)-以后,FIRST_VALUE函数不反对TIMESTAMP类型。

该视图在保留前一行的同时流式传输数据,并收回前一行的字段值以及以后行的event_time作为无效完结工夫。针对该视图的查问将产生以下内容,该结果显示每行(第一行除外)当初具备蕴含的开始工夫和排除的完结工夫。

为了每秒收回一行,咱们编写了一组用户定义的表函数(UDTF)。您能够在此处查看代码。该我的项目提供了无关如何构建二进制文件(.jar文件)以及如何将其与Flink SQL一起应用的简要阐明。您须要收回CREATE FUNCTION语句来注册每个UDTF,而后能力在查问中应用它们:

CREATE FUNCTION fill_sample_per_day    AS 'varstream.FillSample$PerDayFunction'    LANGUAGE JAVA ;CREATE FUNCTION fill_sample_per_hour   AS 'varstream.FillSample$PerHourFunction'   LANGUAGE JAVA ;CREATE FUNCTION fill_sample_per_minute AS 'varstream.FillSample$PerMinuteFunction' LANGUAGE JAVA ;CREATE FUNCTION fill_sample_per_second AS 'varstream.FillSample$PerSecondFunction' LANGUAGE JAVA ;

在查问中,UDTF具备以下语法:

      fill_sample_by_timeunit (start_time, end_time, frequency)

工夫单位能够是日、小时、分钟或秒。开始工夫和排他性完结工夫标记每行的无效工夫,频率批示给定的天、小时、分钟或秒采样次数。因而,频率为6的fill_sample_by_hour将每10分钟采样一次(:00,:10,:20,:30,:40和:50)。调用fill_sample_by_minute具备60的频率是性能上雷同fill_sample_by_second一个的频率。然而,因为UDTF实现的外部起因,by_second变体的性能会更好。

当初,咱们能够创立一个每秒对流进行采样的视图。留神应用的INNER JOIN LATERAL TABLE ,这确保了所发射的即将由UDTF输入进行管制:

CREATE VIEW l1_sample AS    SELECT        symbol,        start_time,        end_time,        sample_time,        bid_price,        ask_price,        (bid_price + ask_price) / 2 AS mid_price    FROM l1_times AS l1    INNER JOIN LATERAL TABLE (fill_sample_per_minute (l1.start_time, l1.end_time, 60))      AS T(sample_time) ON TRUE;SELECT symbol, start_time, end_time, sample_time, mid_price FROM l1_sample ;

查问此视图将产生以下后果。

3 计算流内盘中VaR

当初咱们有一个以秒为两头值采样的工夫序列,咱们能够开始计算流IVaR了。首先,咱们须要计算每秒的回报,这就是以后价格减去之前的价格。为了得出先前的价格,咱们再次应用OVER WINDOW语法:

CREATE VIEW l1_sample_prev AS    SELECT        symbol,        start_time,        sample_time,        mid_price,        FIRST_VALUE (mid_price) OVER w AS prev_price    FROM l1_sample    WINDOW w AS (        PARTITION BY symbol        ORDER BY start_time        ROWS BETWEEN 1 PRECEDING AND CURRENT ROW    );

为了取得第99个百分位数的回报,咱们计算了过来300行的回溯窗口中的回报(以百分比示意),这是因为咱们每秒采样的工夫为5分钟。咱们还计算了同一窗口的均匀收益率和标准差。

CREATE VIEW l1_stddev AS    SELECT        symbol,        start_time,        sample_time,        mid_price,        (mid_price - prev_price) / prev_price              AS pct_return,        AVG (mid_price)                                    OVER lookback AS avg_price,        AVG ((mid_price - prev_price) / prev_price)        OVER lookback AS avg_return,        STDDEV_POP ((mid_price - prev_price) / prev_price) OVER lookback AS stddev_return    FROM l1_sample_prev    WINDOW lookback AS (        PARTITION BY symbol        ORDER BY start_time        ROWS BETWEEN 300 PRECEDING AND CURRENT ROW     )   ;   

有了这些信息,咱们能够通过将标准偏差与-2.58的Z得分相乘并将该数字加到均匀收益中来得出第99个百分位数的最差收益。这在上面显示为var99_return。处于危险中的理论价值是以后两头价格乘以var99_return。在上面的查问中,咱们心愿显示该资产的99%可能的最差将来价格,因而咱们将以后价格(mid_price)乘以1 + var99_return。

CREATE VIEW l1_var99 AS    SELECT        *,        avg_return - 2.58 * stddev_return AS var99_return,        mid_price * (1 + (avg_return - 2.58 * stddev_return)) AS var99_price    FROM        l1_stddev;SELECT symbol, sample_time, mid_price, var99_price FROM l1_var99

4 论断

随着高频交易和小型交易解体变得越来越广泛[2],理解盘中市场危险可能会像了解一个人的盘中危险一样无益,尤其是在应用高频算法时。侥幸的是,借助像Flink这样的古代流媒体平台,以及像Flink SQL这样的易于应用的流编程语言,咱们能够疾速构建强壮的管道,以在市场数据实时达到时计算日内危险度量。
咱们心愿本系列文章能激励您尝试将Flink SQL用于流式市场数据应用程序。在下一部分中,咱们将向您展现如何应用行将公布的Cloudera SQL Stream Builder版本(Cloudera Streaming Analytics 1.4版的一部分)尝试这些示例。
感激Tim Spann,Felicity Liu,Jiyan Babaie-Harmon,Roger Teoh,Justin Lyon和Richard Harmon对这项工作的奉献。

5 引文

[1] Dionne,Georges和Duchesne,Pierre和Pacurar,Maria,应用逐笔交易数据并将其利用于多伦多证券交易所,其当日危险值(Ivar)(2005年12月13日)。在SSRN上可用:https ://ssrn.com/abstract=868594或http://dx.doi.org/10.2139/ssr...

[2] Bayraktar,Erhan和Munk,Alexander,Mini-Flash Crash,模型危险和最佳执行力(2017年5月27日)。在SSRN上可用:https ://ssrn.com/abstract=2975769或http://dx.doi.org/10.2139/ssr...

原文作者:Patrick Angeles& Krishnen Vytelingum

原文链接:https://blog.cloudera.com/streaming-market-data-with-flink-sql-part-ii-intraday-value-at-risk/

关注微信公共号理解更多信息:

本文由mdnice多平台公布