精华帖子

中间价系列因子

由bq7zuymm创建,最终由bq7zuymm 被浏览 18 用户

这一章节介绍和中间价相关的一系列分钟频因子的加工,需要用到快照数据cn_stock_level2_snapshot, 需要开通数据的请咨询小Q

时间加权成交价比中间价

数据定义

我们来看看需要加工该因子的字段:

时间 委卖一价 委买一价 成交量 成交额
t1 a1 b1 v1 amount1
t2 a2 b2 v2 amount2
tn an bn vn amountn

我么来看几个因子的定义。首先是快照成交均价:

他表示的是成交额和成交量的增量相除, t表示的是当前快照, t-1表示的是上一时刻快照。进一步我们可以使用卖一和买一价计算均值得到中间价, 所以我们可以通过以下公式计算出快照因子:

分母是当前快照中间价与上一快照中间价的加和,分母部分为两个价格,而分子只有一种价格,为统一量纲,所以乘以2。

因子加工代码

我们以平安银行这只股票为例。

import dai

instruments = "('000001.SZ')"
dai.pull_data_to_table(datasource='cn_stock_level2_snapshot', table_name='stock_table', overwrite=True, lookback_time=72*60*60)

计算中间价、上一快照的成交额成交量等数据。值得注意的是dai.stream_factor注重因子提取,使用引擎来计算因子可能不是特别方便。

sql = f"""
SELECT date_trunc('minute', to_timestamp(datetime * 1.0 / 1000 + 8 * 60 * 60)) as date, instrument, datetime, 
(ask_price1 + bid_price1) / 2 AS mid_price, 
amount, volume, 
LAG(amount, 1) OVER (PARTITION BY instrument ORDER BY datetime) AS lag_amount, 
LAG(volume, 1) OVER (PARTITION BY instrument ORDER BY datetime) AS lag_volume
FROM stock_table
WHERE instrument in {instruments}
"""

engine = dai.stream_factor(sql, 'test2', True)

接下来就是冷启动引擎:

while True:
    df = engine.df()
    if len(df) != 0:
        break

计算快照因子:

# 计算快照成交均价以及两期快照中间价求和
df['down'] = (df['mid_price'] + df['mid_price'].shift(1))
df['up'] = (df['amount'] - df['lag_amount']) / (df['volume'] - df['lag_volume'])
df['tavg_trdmidprice_ratio'] = (df['up'] / df['down']) * 2 - 1

进一步在分钟内取平均即可得到分钟频率的时间加权成交价比中间价因子了:

data = df.groupby(['date', 'instrument']).apply(lambda x: x['tavg_trdmidprice_ratio'].mean()).reset_index()
data.columns = ['date', 'instrument', 'tavg_trdmidprice_ratio']
data

如果需要对数据进行实时更新的话,我们不妨将冷启动和计算因子的步骤拼接到一块:

import time

while True:
    df = engine.df()
    time.sleep(60)
    if len(df) == 0:
        continue
    df['down'] = (df['mid_price'] + df['mid_price'].shift(1))
    df['up'] = (df['amount'] - df['lag_amount']) / (df['volume'] - df['lag_volume'])
    df['tavg_trdmidprice_ratio'] = (df['up'] / df['down']) * 2 - 1
    data = df.groupby(['date', 'instrument']).apply(lambda x: x['tavg_trdmidprice_ratio'].mean()).reset_index()

結果展示

stream_factor在收盘后也是会产生数据流的,但是数据都会使用收盘那一刻的数据进行填充, 所以收盘之后的量价维持在收盘时的水平,故因子时序差始终为0,所以会导致在计算成交均价时为NaN,故因子值为NaN。

成交量加权成交价比中间价

数据定义

我们参考一下成交量加权净委买比例这篇帖子可知,构造该因子时,其权重为成交量增量(所有数学符号沿用“时间加权成交价比中间价”因子加工时的数学符号):

那么被加权项就是截面成交价比中间价,所以我们将公式进行整合:

我们依旧采用先截面后时序的方式来逐步加工该因子。

因子加工代码

代码与时序加权成交价比中间价这个因子是类似的:

import dai
import pandas as pd

instruments = "('000001.SZ')"
dai.pull_data_to_table(datasource='cn_stock_level2_snapshot', table_name='stock_table', overwrite=True, lookback_time=100000*60*60)

sql = f"""
SELECT date_trunc('minute', to_timestamp(datetime * 1.0 / 1000 + 8 * 60 * 60)) as date, instrument, datetime, 
(ask_price1 + bid_price1) / 2 AS mid_price, 
amount, volume, 
LAG(amount, 1) OVER (PARTITION BY instrument ORDER BY datetime) AS lag_amount, 
LAG(volume, 1) OVER (PARTITION BY instrument ORDER BY datetime) AS lag_volume
FROM stock_table
WHERE instrument in {instruments}
"""

engine = dai.stream_factor(sql, 'test2', True)

数据冷启动:

while True:
    df = engine.df()
    if len(df) != 0:
        break

接下来我们分别计算分子分母求和符号当中的算式:

df['up'] = (((df['amount'] - df['lag_amount']) / (df['volume'] - df['lag_volume'])) * 2 / (df['mid_price']+df['mid_price'].shift(1)) - 1) * (df['volume'] - df['volume'].shift(1))
df['down'] = (df['volume'] - df['volume'].shift(1))

进一步的我们使用dai.query函数来加工分钟频的成交量加权成交价比中间价因子:

sql = """
SELECT date, instrument, AVG(up) / AVG(down) AS vavg_trdmidprice_ratio
FROM df
GROUP BY date, instrument
"""
df=dai.query(sql).df()

进一步的我们将冷启动以下的所有步骤整合到一起:

import time

while True:
    df = engine.df()
    time.sleep(60)
    if len(df) == 0:
        continue
    df['up'] = (((df['amount'] - df['lag_amount']) / (df['volume'] - df['lag_volume'])) * 2 / (df['mid_price']+df['mid_price'].shift(1)) - 1) * (df['volume'] - df['volume'].shift(1))
    df['down'] = (df['volume'] - df['volume'].shift(1))
    sql = """
    SELECT date, instrument, AVG(up) / AVG(down) AS vavg_trdmidprice_ratio
    FROM df
    GROUP BY date, instrument
    """
    df=dai.query(sql).df()           # 至此实时因子加工完毕

结果展示

由于是在双休日写的该文档,故加工出来的因子为NaN,具体原因可参考==时间加权成交价比中间价==因子结果展示中的解释。

成交价加权成交价比中间价

数据定义

这个因子的权重如下:

该权重的表达式与我之前加工的成交价加权净委买比例的权重是一致的。我们的加权对象依旧是截面成交价比中间价,这个系列都是针对这个比值来进行加权的,所以后续不在赘述。为了让读者对该因子有更清晰的认识,我们还是将因子算式列出来了:

因子加工代码

这个因子的加工思路与成交量加权成交价比中间价的思路是一致的。

import dai
import pandas as pd

instruments = "('000001.SZ')"
dai.pull_data_to_table(datasource='cn_stock_level2_snapshot', table_name='stock_table', overwrite=True, lookback_time=100000*60*60)

sql = f"""
SELECT date_trunc('minute', to_timestamp(datetime * 1.0 / 1000 + 8 * 60 * 60)) as date, instrument, datetime, 
(ask_price1 + bid_price1) / 2 AS mid_price, 
amount, volume, 
LAG(amount, 1) OVER (PARTITION BY instrument ORDER BY datetime) AS lag_amount, 
LAG(volume, 1) OVER (PARTITION BY instrument ORDER BY datetime) AS lag_volume
FROM stock_table
WHERE instrument in {instruments}
"""

engine = dai.stream_factor(sql, 'test3', True)

将冷启动和因子加工写到同一个循环中:

while True:
    df = engine.df()
    if len(df)!=0:
        continue
    df['down'] = (df['amount']-df['lag_amount']) / (df['volume']-df['lag_volume'])
    df['up'] = 2 * df['down'] / (df['mid_price'] + df['mid_price'].shift(1)) - 1
    sql = """
    SELECT date, instrument, AVG(up) / AVG(down) AS pavg_trdmidprice_ratio FROM df
    GROUP BY date, instrument
    """
    factor_data = dai.query(sql).df()
    

结果展示

{link}