You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在DolphinDB中妥善处理股票逐笔行情数据的连续NULL值?

处理DolphinDB中股票逐笔报价数据的连续NULL值问题

在DolphinDB处理股票逐笔报价数据时,因买卖盘不平衡产生大量NULL值,尝试过多种填充方法但无法处理连续NULL值的情况。

示例数据

// Generate sample data
n = 20
tradetime = 2024.01.08T09:30:00.000 + (1..n) * 500  
symbol = take(`000001, n)

base_price = 10.25
bid_price1 = base_price + rand(0.05, n) - 0.02  
ask_price1 = bid_price1 + rand(0.03, n) + 0.01  

bid_null_mask = rand(1.0, n) < 0.3
ask_null_mask = rand(1.0, n) < 0.3
bid_price1[bid_null_mask] = NULL
ask_price1[ask_null_mask] = NULL

bid_vol1 = rand(2000, n) + 500  
ask_vol1 = rand(2000, n) + 500
bid_vol1[bid_null_mask] = NULL 
ask_vol1[ask_null_mask] = NULL

last_price = (bid_price1 + ask_price1) \ 2 
last_price = nullFill(last_price, base_price) 

tick_quotes = table(tradetime, symbol, bid_price1, bid_vol1, ask_price1, ask_vol1, last_price)

select * from tick_quotes

已尝试方法

1. 直接计算产生大量NULL值

// Calculate bid-ask spread
result1 = select tradetime, bid_price1, ask_price1, 
    (ask_price1 - bid_price1) as spread 
from tick_quotes

// Check NULL count
select count(*) as total, sum(isNull(spread)) as null_count from result1

spread列存在大量NULL值,导致后续统计分析无法进行。

2. 使用prev()函数无法处理连续NULL值

t4 = select tradetime,
    iif(isNull(bid_price1), prev(bid_price1), bid_price1) as bid
from tick_quotes
context by symbol

select * from t4 where isNull(bid)

该方法仅能填充单个NULL值,当多个时间点存在连续NULL值时,后续记录仍为NULL。

解决方案

方法1:使用ffill函数进行前向填充

DolphinDB内置的ffill函数可以沿序列(按股票分组后)将连续NULL值替换为最近的前一个非NULL值,完美解决连续NULL的问题。

// 按symbol分组,对买卖盘价格和成交量进行前向填充
filled_data = select tradetime, symbol,
    ffill(bid_price1) as filled_bid_price1,
    ffill(bid_vol1) as filled_bid_vol1,
    ffill(ask_price1) as filled_ask_price1,
    ffill(ask_vol1) as filled_ask_vol1,
    last_price
from tick_quotes
context by symbol

// 计算spread,此时NULL值大幅减少
result = select tradetime, filled_bid_price1, filled_ask_price1,
    (filled_ask_price1 - filled_bid_price1) as spread
from filled_data

// 验证NULL数量
select count(*) as total, sum(isNull(spread)) as null_count from result

如果序列开头就存在NULL值,可以结合nullFill指定默认值(比如基准价):

filled_bid_price1 = nullFill(ffill(bid_price1), base_price)

方法2:结合last_price的业务逻辑填充

考虑到last_price字段已填充了有效值,可以将其作为买卖盘缺失时的参考,再结合前向填充处理连续NULL:

enhanced_filled = select tradetime, symbol,
    // 用last_price填充单个NULL,再前向填充连续NULL
    ffill(iif(isNull(bid_price1), last_price, bid_price1)) as filled_bid_price1,
    ffill(iif(isNull(bid_vol1), prev(bid_vol1), bid_vol1)) as filled_bid_vol1,
    ffill(iif(isNull(ask_price1), last_price, ask_price1)) as filled_ask_price1,
    ffill(iif(isNull(ask_vol1), prev(ask_vol1), ask_vol1)) as filled_ask_vol1,
    last_price
from tick_quotes
context by symbol

这种方式更贴合股票交易的实际逻辑,成交价(last_price)可以作为买卖盘价格缺失时的合理替代。

内容的提问来源于stack exchange,提问作者Jane

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.11 18:05:08