时间加权净委买比例
由bq7zuymm创建,最终由bq7zuymm 被浏览 20 用户
数据定义
以下涉及到的流数据暂未开放,后期我们会为大家提供流数据获取服务。
构造这个因子需要用到的数据的表格形式如下:
日期 | 买一量 | 卖一量 |
---|---|---|
t1 | b1 | a1 |
t2 | b2 | a2 |
… | … | … |
tn | bn | an |
首先我们求出截面净委买比例:
最后将分钟内的截面净委买比例求平均即可得到时间加权的净委买比例,所以这个因子依旧是一个分钟因子, 具体构造分钟因子的技巧请参考**分钟盘口平均委买量**这篇文。
值得注意的是,若分母为0,该快照求出来的截面净委买比例将无意义,直接表现为:当天收盘或者股票退市,又或是节假日导致没有委托单,还有可能股票没有流动性。但是dai.stream_factor
计算时会使用零值填补。
因子加工代码
首先导入第三方库以及获取推送数据:
import dai
import pandas as pd
dai.pull_data_to_table(datasource='cn_stock_level2_snapshot', lookback_time=8*24*60*60, table_name='stock_data', overwrite=True)
之后获取我们需要加工该因子的数据:
instrument = '000001.SZ'
sql = f"""
-- 取出需要的因子
WITH t1 AS (
SELECT date_trunc('minute', to_timestamp(datetime * 1.0 / 1000 + 8 * 60 * 60)) as date,
instrument,
datetime,
LAG(bid_volume1) OVER (PARTITION BY instrument ORDER BY datetime) AS lag_bid_volume1,
LAG(ask_volume1) OVER (PARTITION BY instrument ORDER BY datetime) AS lag_ask_volume1,
ask_volume1,
bid_volume1
FROM stock_data
WHERE instrument = '{instrument}'
ORDER BY datetime
),
-- 计算时序差分
t2 AS (
SELECT date,
instrument,
(bid_volume1 - lag_bid_volume1) AS delta_bid,
(ask_volume1 - lag_ask_volume1) AS delta_ask
FROM t1
)
-- 计算截面净委买比率的分子和分母
SELECT date, instrument, (delta_bid - delta_ask) AS up,
(abs(delta_bid) + abs(delta_ask)) AS down
FROM t2
"""
stock_data = dai.stream_factor(sql, 'test', True, "date ASC")
进一步计算截面净委买比率,最后我们对日期和股票代码进行分组平均聚合即可得到时间加权净委买比例因子:
for _ in range(1000):
# 初始化引擎获取sql表达式中的数据, 引擎冷启动, 防止取到空数据
df = stock_data.df()
if len(df) == 0:
continue
else:
break
df['rate'] = df['up'] / df['down'] # 计算截面净委买比率
data = df.groupby(['date', 'instrument']).apply(lambda x: x['rate'].mean()).reset_index() # 平均值聚合
data.columns = ['date', 'instrument', 'tavg_net_buy_quote_volume_ratio']
data['date'] = pd.to_datetime(data['date'])
data.sort_values('date').dropna()
最后我们可以得到数据:
接下来我们对因子进行实时可视化操作:
import time
import plotly.graph_objects as go
from IPython.display import display
from plotly.subplots import make_subplots
def update_data(fig, new_data, window_size:int=20):
"""
往表格添加新的因子数据
:params fig: 画布
:params new_data: 新的数据点
"""
# 将因子计算方法封装进来
new_data['rate'] = new_data['up'] / new_data['down']
data = new_data.groupby(['date', 'instrument']).apply(lambda x: x['rate'].mean()).reset_index()
data.columns = ['date', 'instrument', 'tavg_net_buy_quote_volume_ratio']
data['date'] = pd.to_datetime(data['date'])
new_data = data.sort_values('date').dropna()
factor = new_data['tavg_net_buy_quote_volume_ratio'].iloc[-1]
date = new_data['date'].iloc[-1]
# 只留20个数据点
if len(fig.data[0].x)==window_size and len(fig.data[0].y)==window_size:
x = fig.data[0].x[1:] + (date, )
y = fig.data[0].y[1:] + (factor, )
fig.data[0].x = x
fig.data[0].y = y
else:
f.data[0].x += (date, )
f.data[0].y += (factor, )
# 定义画布
fig = make_subplots(rows=1, cols=1)
fig.add_trace(go.Scatter(x=(), y=(), mode='lines+markers', name='时序加权净委买比率'), row=1, col=1)
# 更新布局
fig.update_layout(title_text='时序加权净委买比率', height=600)
f = go.FigureWidget(fig)
display(f)
while True:
update_data(f, stock_data.df()) # 第一次运行df.df()会较慢, 请耐心等候
time.sleep(2)