精华帖子

近月合约与远月合约的价差因子加工

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

这一次我们选用螺纹钢的相关期货合约来加工一个近月与远月合约的价差因子。我们选用的标的为rb2503.SHF, rb2501.SHF。以下涉及到的流数据暂未开放,后期我们会为大家提供流数据获取服务。

因子代码

这里只需取出价格数据即可,所以我们直接对代码进行讲解。

import dai
import time
import plotly.graph_objects as go
from IPython.display import display
from plotly.subplots import make_subplots
 
dai.pull_data_to_table(datasource='cn_future_level1_snapshot', table_name='future_table', overwrite=True, lookback_time=8*24*60*60)
 
futher = 'rb2503.SHF'
closer = 'rb2501.SHF'

为近月合约和远月合约的价格数据创建两个流数据引擎:

sql = f"""
SELECT date_trunc('minute', to_timestamp(datetime * 1.0 / 1000 + 8 * 60 * 60)) as date, instrument AS closer_instrument, price AS closer_price FROM future_table
WHERE instrument = '{closer}'
"""
closer_engine = dai.stream_factor(sql, 'closer', True)
 
sql = f"""
SELECT date_trunc('minute', to_timestamp(datetime * 1.0 / 1000 + 8 * 60 * 60)) as date, instrument AS futher_instrument, price AS futher_price FROM future_table
WHERE instrument = '{futher}'
"""
futher_engine = dai.stream_factor(sql, 'futher', True)

接下来依旧是老生常谈的数据冷启动, 防止流数据引擎获取到空数据表:

for i in range(1000):
    closer_df = closer_engine.df()
    futher_df = futher_engine.df()
    if len(closer_df)!=0 and len(futher_df)!=0:
        break

最后我们需要为两种合约的价格数据以及差价数据创建三个流数据表:

# 往画布中添加数据
def fig_append(f, data1, data2, window_size:int=20):
    import pandas as pd
    data = pd.merge(data1, data2, on=['date'], how='inner')
    # 近月合约
    current_new_x = tuple(data['date'].to_list())
    current_new_y = tuple(data['closer_price'].to_list())
 
    # 远月合约
    future_new_x = tuple(data['date'].to_list())
    future_new_y = tuple(data['futher_price'].to_list())
 
    # 价差
    delta_new_x = tuple(data['date'].to_list())
    delta_new_y = tuple((data['closer_price'] - data['futher_price']).to_list())
 
    # 将上述放入两个列表
    new_x = [current_new_x, future_new_x, delta_new_x]
    new_y = [current_new_y, future_new_y, delta_new_y]
 
    for i in range(3):
        if len(f.data[i].x)==window_size and len(f.data[i].y)==window_size:
            x = f.data[i].x[1:] + (new_x[i][-1],)
            y = f.data[i].y[1:] + (new_y[i][-1],)
            f.data[i].x = x
            f.data[i].y = y
        else:
            f.data[i].x += (new_x[i][-1],)
            f.data[i].y += (new_y[i][-1],)
    return f.data[0].x, f.data[0].y
 
# 定义画布和曲线数据
fig = make_subplots(rows=3, cols=1)
fig.add_trace(go.Scatter(x=(), y=(), mode='lines+markers', name='近月'), row=1, col=1)
fig.add_trace(go.Scatter(x=(), y=(), mode='lines+markers', name='远月'), row=2, col=1)
fig.add_trace(go.Scatter(x=(), y=(), mode='lines+markers', name='差价'), row=3, col=1)
 
# 更新布局
fig.update_layout(title_text='动态数据点示例', height=600)
 
f = go.FigureWidget(fig)
display(f)
 
# 数据更新(由于是分钟数据, 所以这里不需要异步, 只要设置一个timesleep即可)
while True:
    closer_data = closer_df.groupby(['date', 'closer_instrument']).apply(lambda x: x['closer_price'].iloc[-1]).reset_index()
    closer_data.columns = ['date', 'closer_instrument', 'closer_price']
    futher_data = futher_df.groupby(['date', 'futher_instrument']).apply(lambda x: x['futher_price'].iloc[-1]).reset_index()
    futher_data.columns = ['date', 'futher_instrument', 'futher_price']
    x, y = fig_append(f, closer_data, futher_data)
    time.sleep(20)

结果展示

{link}