Python + HDF5 因子计算与 DolphinDB 一体化因子计算方案对比

news2024/12/25 10:43:06

在量化交易中,基于金融市场的 L1/L2 的报价和交易高频数据来进行高频因子计算,是非常常见的投研需求。目前国内全市场十年的 L2 历史数据约为 20 ~ 50T,每日新增的数据量约为 10 ~ 20G。传统的关系数据库如 MS SQL Server 或 MySQL 已经很难支撑该量级的数据,即便分库分表,查询性能也远远无法达到要求。由此,一部分用户选择了分布式文件系统, 使用 HDF5 存储数据,并结合 Python 进行量化金融计算。

HDF5 的存储方案虽然可以支持海量的高频数据,但是也存在一些痛点,例如数据权限管理困难、不同数据关联不便、检索和查询不便、需要通过数据冗余来提高性能等。此外,通过 Python 来读取计算,也要耗费一些时间在数据传输上。

DolphinDB 是一款分析型的分布式时序数据库(time-series database)。目前,越来越多的券商和私募机构开始采用 DolphinDB 存储并进行高频数据的因子计算,也有不少还在使用 Python + HDF5 方案进行高频因子计算的客户对 DolphinDB 表现了浓厚的兴趣。因此,我们撰写了这篇对比 Python + HDF5 因子计算与 DolphinDB 一体化因子计算方案的文章,以供参考。

本文将分别介绍如何基于 Python + HDF5 和 DolphinDB 实现因子计算,并比较两者的计算性能。

1. 测试环境和测试数据

1.1 测试环境

本次测试对比了通过 Python +HDF5 和 DolphinDB 实现的因子计算。其中:

  • Python + HDF5 因子计算方案依赖 Numpy, Pandas, DolphinDB, Joblib 等库。
  • DolphinDB 一体化因子计算方案以 DolphinDB Server 作为计算平台,本次测试使用了单节点部署方式 。

测试所需硬件、软件环境信息如下:

  • 硬件环境
硬件名称配置信息
CPUIntel(R) Xeon(R) Silver 4210R CPU @ 2.40GHz
内存512 G
磁盘SSD 500 G
  • 软件环境
软件名称版本信息
操作系统CentOS Linux release 7.9.2009 (Core)
DolphinDBV2.00.8.7
PythonV3.6.8
NumpyV1.19.3
PandasV1.1.5

1.2 测试数据

本次测试选取了深市 2020.01.02 ~ 2020.01.06 期间共3个交易日的部分快照数据,该数据包含约 1992 支股票,平均一天数据量约为 760 万条,总数据量约为 2200 万条。初始数据存于 DolphinDB 中,HDF5 格式数据文件可从 DolphinDB 中导出生成。

快照表测试数据在 DolphinDB 中共55个字段,部分字段展示如下:

字段名数据类型字段名数据类型
1TradeDateDATE29OfferPX1INT
2OrigTimeTIMESTAMP30BidPX1DOUBLE
3dbtimeTIMESTAMP31OfferSize1DOUBLE
4SecurityIDSYMBOL32BidSize1INT
5…………33…………

部分数据示例如下:

| record | TradeDate  | OrigTime                | SendTime                | Recvtime                | dbtime                  | ChannelNo | SecurityID | SecurityIDSource | MDStreamID | OfferPX1 | BidPX1 | OfferSize1 | BidSize1 | OfferPX2 | BidPX2 | OfferSize2 | BidSize2 | OfferPX3 | BidPX3 | OfferSize3 | BidSize3 | OfferPX4 | BidPX4 | OfferSize4 | BidSize4 | OfferPX5 | BidPX5 | OfferSize5 | BidSize5 | OfferPX6 | BidPX6 | OfferSize6 | BidSize6 | OfferPX7 | BidPX7 | OfferSize7 | BidSize7 | OfferPX8 | BidPX8 | OfferSize8 | BidSize8 | OfferPX9 | BidPX9 | OfferSize9 | BidSize9 | OfferPX10 | BidPX10 | OfferSize10 | BidSize10 | NUMORDERS_B1 | NOORDERS_B1 | ORDERQTY_B1 | NUMORDERS_S1 | NOORDERS_S1 | ORDERQTY_S1 |
|--------|------------|-------------------------|-------------------------|-------------------------|-------------------------|-----------|------------|------------------|------------|----------|--------|------------|----------|----------|--------|------------|----------|----------|--------|------------|----------|----------|--------|------------|----------|----------|--------|------------|----------|----------|--------|------------|----------|----------|--------|------------|----------|----------|--------|------------|----------|----------|--------|------------|----------|-----------|---------|-------------|-----------|--------------|-------------|-------------|--------------|-------------|-------------|
| 0      | 2020.01.02 | 2020.01.02 09:00:09.000 | 2020.01.02 09:00:09.264 | 2020.01.02 09:00:09.901 | 202.01.02 09:00:09.902  | 1,014     | 14         | 102              | 10         | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0         | 0       | 0           | 0         | 0            | 0           |             | 0            | 0           |             |
| 1      | 2020.01.02 | 2020.01.02 09:01:09.000 | 2020.01.02 09:01:09.330 | 2020.01.02 09:01:09.900 | 2020.01.02 09:01:09.904 | 1,014     | 14         | 102              | 10         | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0         | 0       | 0           | 0         | 0            | 0           |             | 0            | 0           |             |
| 2      | 2020.01.02 | 2020.01.02 09:02:09.000 | 2020.01.02 09:02:09.324 | 2020.01.02 09:02:10.131 | 2020.01.02 09:02:10.139 | 1,014     | 14         | 102              | 10         | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0         | 0       | 0           | 0         | 0            | 0           |             | 0            | 0           |             |
| 3      | 2020.01.02 | 2020.01.02 09:03:09.000 | 2020.01.02 09:03:09.223 | 2020.01.02 09:03:10.183 | 2020.01.02 09:03:10.251 | 1,014     | 14         | 102              | 10         | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0         | 0       | 0           | 0         | 0            | 0           |             | 0            | 0           |             |
| 4      | 2020.01.02 | 2020.01.02 09:04:09.000 | 2020.01.02 09:04:09.227 | 2020.01.02 09:04:10.188 | 2020.01.02 09:04:10.215 | 1,014     | 14         | 102              | 10         | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0         | 0       | 0           | 0         | 0            | 0           |             | 0            | 0           |             |
| 5      | 2020.01.02 | 2020.01.02 09:05:09.000 | 2020.01.02 09:05:09.223 | 2020.01.02 09:05:09.930 | 2020.01.02 09:05:09.936 | 1,014     | 14         | 102              | 10         | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0         | 0       | 0           | 0         | 0            | 0           |             | 0            | 0           |             |
| 6      | 2020.01.02 | 2020.01.02 09:06:09.000 | 2020.01.02 09:06:09.218 | 2020.01.02 09:06:10.040 | 2020.01.02 09:06:10.044 | 1,014     | 14         | 102              | 10         | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0         | 0       | 0           | 0         | 0            | 0           |             | 0            | 0           |             |
| 7      | 2020.01.02 | 2020.01.02 09:07:09.000 | 2020.01.02 09:07:09.224 | 2020.01.02 09:07:09.922 | 2020.01.02 09:07:09.925 | 1,014     | 14         | 102              | 10         | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0         | 0       | 0           | 0         | 0            | 0           |             | 0            | 0           |             |
| 8      | 2020.01.02 | 2020.01.02 09:08:09.000 | 2020.01.02 09:08:09.220 | 2020.01.02 09:08:10.137 | 2020.01.02 09:08:10.154 | 1,014     | 14         | 102              | 10         | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0         | 0       | 0           | 0         | 0            | 0           |             | 0            | 0           |             |
| 9      | 2020.01.02 | 2020.01.02 09:09:09.000 | 2020.01.02 09:09:09.215 | 2020.01.02 09:09:10.175 | 2020.01.02 09:09:10.198 | 1,014     | 14         | 102              | 10         | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0        | 0      | 0          | 0        | 0         | 0       | 0           | 0         | 0            | 0           |             | 0            | 0           |             |

2. 高频因子与代码实现对比

本节将通过两个高频因子,流动状态因子(flow 因子)和权重偏度因子(mathWghtSkew 因子)进行计算比对。

2.1 高频因子

  • flow 因子
    • 因子介绍:流动状态因子的计算需要依赖历史数据,需要的参数分别为 buy_vol、sell_vol、askPrice1、bidPrice1 四个字段,运用 mavg 、iif 等函数计算。其计算结果可以反映买方资金流的情况。
    • 公式:

flow 因子计算公式

  • mathWghtSkew 因子
    • 因子介绍:接收多档报价数据(价格 BidPX1,BidPX2…BidPX10)并计算多档报价的权重偏度。
    • 公式:

mathWghtSkew 因子计算公式

2.2 DolphinDB 中的因子实现

本小节中,我们使用 DolphinDB 的编程语言来实现 flow 因子和 mathWghtSkew 因子。DolphinDB 提供了 mavg (滑动窗口系列 m 系列) 和 rowWavg (行计算系列row 系列)函数,并进行了针对性的性能优化。这两个系列的函数不但可用于快捷开发这两个因子,还提供了极佳的计算性能。如以下代码所示:

  • flow 因子的实现代码:
def flow(buy_vol, sell_vol, askPrice1, bidPrice1){
	buy_vol_ma = round(mavg(buy_vol, 60), 5)
	sell_vol_ma = round(mavg(sell_vol, 60), 5)
	buy_prop = iif(abs(buy_vol_ma+sell_vol_ma) < 0, 0.5 , buy_vol_ma/ (buy_vol_ma+sell_vol_ma))
	spd_tmp = askPrice1 - bidPrice1
	spd = iif(spd_tmp  < 0, 0, spd_tmp)
	spd_ma = round(mavg(spd, 60), 5)
	return iif(spd_ma == 0, 0, buy_prop / spd_ma)
}
  • mathWghtSkew 因子的实现代码:
def mathWghtCovar(x, y, w){
	v = (x - rowWavg(x, w)) * (y - rowWavg(y, w))
	return rowWavg(v, w)
}
def mathWghtSkew(x, w){
	x_var = mathWghtCovar(x, x, w)
	x_std = sqrt(x_var)
	x_1 = x - rowWavg(x, w)
	x_2 = x_1*x_1
	len = size(w)
	adj = sqrt((len - 1) * len) \ (len - 2)
	skew = rowWsum(x_2, x_1) \ (x_var * x_std) * adj \ len
	return iif(x_std==0, 0, skew)
}

2.3 Python 中的因子实现

本小节中,我们用 Python 实现 flow 因子和 mathWghtSkew 因子。

  • flow 因子的实现代码:
def flow(df):
    buy_vol_ma = np.round(df['BidSize1'].rolling(60).mean(), decimals=5)
    sell_vol_ma = np.round((df['OfferSize1']).rolling(60).mean(), decimals=5)
    buy_prop = np.where(abs(buy_vol_ma + sell_vol_ma) < 0, 0.5, buy_vol_ma / (buy_vol_ma + sell_vol_ma))
    spd = df['OfferPX1'].values - df['BidPX1'].values
    spd = np.where(spd < 0, 0, spd)
    spd = pd.DataFrame(spd)
    spd_ma = np.round((spd).rolling(60).mean(), decimals=5)
    return np.where(spd_ma == 0, 0, pd.DataFrame(buy_prop) / spd_ma)
  • mathWghtSkew 因子的实现代码:
def rowWavg(x, w):
    rows = x.shape[0]
    res = [[0]*rows]
    for row in range(rows):
        res[0][row] = np.average(x[row], weights=w)
    res = np.array(res)
    return res

def rowWsum(x, y):
    rows = x.shape[0]
    res = [[0]*rows]
    for row in range(rows):
        res[0][row] = np.dot(x[row],y[row])
    res = np.array(res)
    return res

def mathWghtCovar(x, y, w):
    v = (x - rowWavg(x, w).T)*(y - rowWavg(y, w).T)
    return rowWavg(v, w)

def mathWghtSkew(x, w):
    x_var = mathWghtCovar(x, x, w)
    x_std = np.sqrt(x_var)
    x_1 = x - rowWavg(x, w).T
    x_2 = x_1*x_1
    len = np.size(w)
    adj = np.sqrt((len - 1) * len) / (len - 2)
    skew = rowWsum(x_2, x_1) / (x_var*x_std)*adj / len
    return np.where(x_std == 0, 0, skew)

2.4 小结

从代码实现来看,使用 DolphinDB 和 Python 两种语言来开发这两个因子的难度差别不大,代码量上 DolphinDB 因为提供了 row 系列的行计算函数,开发上会容易一些。此外在移动窗口计算上 Python 中是通过 rolling 函数 + mean 等需要进行计算函数组合来进行计算。而在 DolphinDB 中,也可以类似的通过 moving 函数组合要进行计算的函数(例如 meanavg 等)来进行计算。但是这种组合的方式在进行数据移动时,因为不知道具体的计算业务而难以进行针对性的增量优化。为了提升性能,DolphinDB 专门提供了 m 系列滑动窗口函数。可以对不同的计算需求进行针对性的性能优化。这种针对性的移动计算函数在不同场景与组合方式计算方式相比最高可以提高 100 倍的性能。

3. 因子计算效率对比

本小节将进一步展示 flow 因子和 mathWghtSkew 因子的具体调用方法,以及如何实现并行调用。

3.1 DolphinDB 的因子调用计算

  • 因子调用计算

本次对比的因子中 , flow 因子要进行移动窗口计算,mathWghtSkew 因子要进行同行内多列计算。但计算涉及的数据都是对每只股票独立进行计算的。对于这种场景,DolphinDB 提供了 context by 函数,可以简化像移动窗口计算这样的时间序列数据操作。通过对股票 SecurityID 进行的 context by 操作,可以直接使用 DolphinDB 的 SQL 引擎进行批量股票的移动窗口计算。mathWghtSkew 因子的计算在同一行内的多列间进行,可以一起进行计算。计算代码如下:

m = 2020.01.02:2020.01.06
w = 10 9 8 7 6 5 4 3 2 1
res = select dbtime, SecurityID,flow(BidSize1,OfferSize1, OfferPX1, BidPX1) as Flow_val,mathWghtSkew(matrix(BidPX1,BidPX2,BidPX3,BidPX4,BidPX5,BidPX6,BidPX7,BidPX8,BidPX9,BidPX10),w) as Skew_val  from loadTable("dfs://LEVEL2_SZ","Snap") where TradeDate between  m context by SecurityID
  • 并行调用

DolphinDB 计算框架会将一个大的计算任务拆解成多个子任务进行并行计算。所以,在以上面的 Sql 进行计算时,会自动计算数据涉及的分区,并按照配置的参数 workerNum 和 localExecutors 所限制的最大工作线程数量,来自动进行多线程并行计算。但在本次对比中,我们需要在指定并发数下的进行一体化计算。我们可以通过修改 DolphinDB 配置文件中的 workerNum 和 localExecutors 参数来精确地限制系统资源的使用。在DolphinDB 的多线程机制中,任务分配线程也会参与计算,实际工作线程数量为 localExecutors 数量加 1 。参数调整与实际工作线程数量的关系如下:

workerNum 数量localExecutors 数量实际工作线程数量
101
212
201920

参数修改示例如下:

workerNum=20
localExecutors=19

通过参数调整,即可控制本次因子通过 DolphinDB Sql 引擎调用计算时的 CPU 资源使用并行度。

DolphinDB 当前任务的并行度可以通过 Web 版的管理器查看,下图展示了配置了4个并行度的并行计算作业。

3.2 Python + HDF5 的因子调度计算

  • HDF5 数据文件读取

区别于 DolphinDB 的库内一体化计算,在使用 Python 的计算库进行计算时,需要先从 HDF5 文件中读取快照数据。HDF5的 Python 读取包有若干种。不同的包在存储时会有不同的数据结构,相应的读取方式和性能也不同。

这里我们验证了两种常用的方式:

  • pandas 的 HDFStore()
  • pandas 的 read_hdf()

其中 read_hdf 方法支持只读取所需列的数据。但实际测试的结果显示,通过 pandas.read_hdf() 方法读取部分列数据的耗时与读取全部列数据的耗时差别非常小。而通过 pandas.to_hdf() 保存的 HDF5 文件数据比通过调用 pandas.HDFStore() 保存的 HDF5 文件数据在存储上要多 30% 左右。由于实际存储空间大,通过 pandas.read_hdf() 方法读取同样的 HDF5 存储数据的耗时也要多于使用 pandas.HDFStore() 方法。故本次测试选择使用 pandas 的 HDFStore() 方法存储和读取 HDF5 文件数据,并进行计算。本次测试对于 HDF5 文件数据以最通用的方式存储,存储前并未去冗或进行其他针对性的存储优化处理。原因在于,这些针对性的优化除了带来数据的冗余以外,也会增加数据使用、管理复杂度。尤其是在海量数据场景下数据管理的复杂度更会大幅上升。

采用 HDFStore 方法存、取 HDF5 的代码实现如下:

# 保存 HDF5 文件
def saveByHDFStore(path,df):
    store = pd.HDFStore(path)
    store["Table"] = df
    store.close()

# 读取单个 HDF5 文件
def loadData(path):
    store = pd.HDFStore(path, mode='r')
    data = store["Table"]
    store.close()
    return data
  • 因子调用计算

对于每只股票,循环读取每天的数据,拼接后转成 dataframe 并进行因子计算。代码如下:

def ParallelBySymbol(SecurityIDs,dirPath):
    for SecurityID in SecurityIDs:
        sec_data_list=[]
        for date in os.listdir(dirPath):
            filepath = os.path.join(dirPath,str(date),"data_"+str(date) + "_" + str(SecurityID) + ".h5")
            sec_data_list.append(loadData(filepath))
        df=pd.concat(sec_data_list)
        # 计算 flow 因子
        df_flow_res = flow(df)
        # 计算 mathWghtSkew 因子
        w = np.array([10, 9, 8, 7, 6, 5, 4, 3, 2, 1])
        pxs = np.array(df[["BidPX1","BidPX2","BidPX3","BidPX4","BidPX5","BidPX6","BidPX7","BidPX8","BidPX9","BidPX10"]])
        np.seterr(divide='ignore', invalid='ignore')
        df_skew_res = mathWghtSkew(pxs,w)
  • 并行调用

这里我们使用 Python 的 Joblib 库实现多进程的并行调度。我们将要计算的股票从文件中读出,然后按照并行度拆分成多组来用于并行计算。代码如下:

...
# 股票 HDF5 文件地址
pathDir=/data/stockdata
# 并行度
n = 1
# SecurityIDs 为要计算的全部股票列表
SecurityIDs_splits = np.array_split(SecurityIDs, n)
Parallel(n_jobs=n)(delayed(ParallelBySymbol)(SecurityIDs,pathDir) for SecurityIDs in SecurityIDs_splits)

3.3 计算性能对比

基于前述内容,本节我们进行不同并行度的 Python + HDF5 因子计算和 DolphinDB 库内一体化因子计算的性能比对。计算的数据量为 1992 只股票,3天总计 2200万行。我们调节不同的并行度,测试在使用不同 CPU 核数的情况下,两种方式计算因子的耗时。所有测试均在清除操作系统缓存后进行。测试结果如下表:

CPU核数Python+HDF5(秒)DolphinDB(秒)(Python+HDF5)/ DolphinDB
1200021.095
299311.586
45406.879
82555.844
161334.927
241144.326
401064.225

从比对结果可以看到。本次测试中,在单核的前提下,DolphinDB 库内计算比 Python + HDF5计算快接近100倍。随着可用 CPU 核数逐渐增加,DolphinDB 库内计算和 Python + HDF5 计算耗时比逐渐趋近 1:25 左右。考虑两种计算方式的特点,原因大概如下:

  • DolphinDB 自有的数据存储系统的读取效率远优于 Python 读取使用通用存储方式的 HDF5 文件存储。
  • DolphinDB 的针对性移动计算函数滑动窗口系列(m 系列)对于不同的移动窗口计算优化可提供更佳计算性能

尽管 HDF5 格式的数据文件读取可以从技术层面进行针对性的冗余存储或者其他针对性优化,但同时会带来额外的硬件资源成本、数据使用和管理成本等。相比之下,DolphinDB 的自有数据存储系统在使用上更为高效、方便和简单。 因此 DolphinDB 的库内一体化因子计算在完整的因子数据读取、计算全过程上的计算速度是远优于 Python + HDF5 的因子计算方式的。

从计算性能的对比中,不难发现以下现象:

  • 代码实现方面,DolphinDB 的库内 Sql 计算更易于实现因子计算调用及并行调用。
  • 并行计算方面,DolphinDB 可以自动使用当前可用的 CPU 资源,而Python 脚本需要通过并行调度代码实现,但更易于控制并发度。
  • 计算速度方面,DolphinDB 的库内计算比 Python + HDF5 的计算方式快 25 倍以上。

3.4 计算结果对比

上一节中,我们比对了两种计算的方式的计算性能。DolphinDB 的库内因子计算在计算速度上要远优于 Python + HDF5 的因子计算方式。但是计算快的前提是计算结果要正确一致。我们将 Python +HDF5 和 DolphinDB 的因子计算结果分别存入 DolphinDB 的分布式表中。部分计算结果比对展示如下图,显示的部分结果完全一致。全部的数据比对通过 DolphinDB 脚本进行,比对结果也是完全一致。

也可以通过如下代码进行全数据验证,输出 int[0] 则表示两张表内容一致。

resTb = select * from loadTable("dfs://tempResultDB","result_cyc_test")
resTb2 = select * from loadTable("dfs://tempResultDB","result_cyc_test2")
resTb.eq(resTb2).matrix().rowAnd().not().at()

验证结果显示,采用Python + HDF5 和 DolphinDB 两种方式进行计算,结果完全一致。

4. 总结

本篇文章的比较结果显示,在使用相同核数 CPU 的前提下:

  • DolphinDB 的库内一体化计算性能约为 Python + HDF5 因子计算方案的 25 倍左右,计算结果和 Python 方式完全一样。
  • 两种方案的因子开发效率相近
  • 在数据的管理和读取方面:
    • 每个 HDF5 文件的读取或写入基本是单线程处理的,难以对数据进行并行操作。 此外 HDF5 文件中数据读取效率较依赖于数据在 HDF5 的 group 和 dataset 组织结构。为了追求更好的读写效率,经常要考虑不同的数据读取需求来设计存储结构。需要通过一些数据冗余存储来满足不同场景的高效读写。这种数据操作方式在数据量逐渐上升到 T 级之后,数据管理和操作的复杂度更会大幅增加,实际使用中会增加大量的时间成本和存储空间成本。
    • 而 DolphinDB 的数据管理、查询、使用更为简单便捷。得益于 DolphinDB 的不同存储引擎及分区机制,用户可以以普通数据库的方式轻松管理、使用 PB 级及以上数量级别的数据。

综合而言,在生产环境中,使用 DolphinDB 进行因子计算和存储远比使用 Python + HDF5 计算方式更加高效。

附录

本教程中的对比测试使用了以下测试脚本:

createDBAndTable.dos

ddbFactorCal.dos

gentHdf5Files.py

pythonFactorCal.py

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/628294.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2023届【校招】安全面试题和岗位总结(字节、百度、腾讯、美团等大厂)

写在前面 个人强烈感觉面试因人而异&#xff0c;对于简历上有具体项目经历的同学&#xff0c;个人感觉面试官会着重让你介绍自己的项目&#xff0c;包括但不限于介绍一次真实攻防/渗透/挖洞/CTF/代码审计的经历 > 因此对于自己的项目&#xff0c;面试前建议做一次复盘&#…

Zigbee学习(四)入网流程及抓包分析

Zigbee学习系列文章 Zigbee学习&#xff08;一&#xff09;架构及入网 Zigbee学习&#xff08;二&#xff09;认识Profile和Cluster Zigbee学习&#xff08;三&#xff09;Z-Stack代码框架解析 文章目录 Zigbee学习系列文章前言一、概述二、入网报文解析1.Management Permit J…

双向交错CCM图腾柱无桥单相PFC学习仿真与实现(1)系统问题分解

目录 前言 系统硬件架构 系统软件架构 仿真实现 仿真效果 总结 前言 目前正在做双向交错CCM图腾柱无桥单相PFC的项目&#xff0c;硬件拓扑兼容三相和单相的PFC&#xff0c;三相PFC功能目前已经完成&#xff0c;准备把单相的PFC学习和开发过程记录一下&#xff0c;以及后面…

基于CH32F103的DAC播放WAV功能

一、理论 1.1 DAC理论 数字信号转化为电压信号&#xff0c;实现扬声器不同频率的发声。 12位DAC&#xff0c;表达范围0-4095 1.2音频wav理论 1.2.1 wav文件格式解析 wav 文件一般由3个区块组成&#xff1a;RIFF chunk、Format chunk 和 Data chunk。 RIFF chunk&#xff…

Vivado 下 IP核之单端口 RAM 读写

目录 Vivado 下 IP 核之单端口 RAM 读写 1、RAM 简介 2、实验任务 3、程序设计 3.1、RAM IP 核配置 3.2、时序图讲解 1、写优先模式的时序图如下所示&#xff1a; 2、读优先模式的时序图如下所示&#xff1a; 3、不变模式的时序图如下所示&#xff1a; 3.3、顶层模块…

mysql 数据库 不同数据类型字段设置长度大小、取值范围 及 存储空间

学习目标&#xff1a; 学习的目标 了解不同数据类型字段设置长度大小&#xff0c;从而 在使用 mysql 数据时为使用的字段设置适当的长度 。 学习内容&#xff1a; 学习的内容 整数型字符串型TEXT时间型 总结&#xff1a; 提示&#xff1a;总结 1、整数型 1、整数型的数值…

STM32队列

目录 什么是队列&#xff1f; 队列特点 1. 数据入队出队方式 2. 数据传递方式 3. 多任务访问 4. 出队、入队阻塞 队列相关 API 函数 1. 创建队列 参数&#xff1a; 2. 写队列 参数&#xff1a; 返回值&#xff1a; 3. 读队列 参数&#xff1a; 返回值&#xf…

找工作第一弹——三件套基础巩固

目录 前言HTML篇表格结构a的两种打开方式自定义列表单选&#xff0c;多选音视频标签 CSS篇伪元素清楚浮动固定定位fixedemCSS三角 JS细节篇原型链字符串拼接的方法递归 JS内置对象sort的升序和降序字符串大写和小写Objects对象的方法date的用法数字取整数组的最大值与最小值 We…

ROS中使用VLP16激光雷达获取点云数据

ROS中使用VLP16激光雷达获取点云数据 个人博客地址 本文测试环境为&#xff1a;Ubuntu20.04 ROS Noetic 需要将激光雷达与PC连接&#xff0c;然后在设置>网络>有线中将IPv4改为手动&#xff0c;并且地址为192.168.1.100&#xff0c;子网掩码为255.255.255.0&#xff0c…

leetcode61. 旋转链表(java)

旋转链表 leetcode61. 旋转链表题目描述 解题思路代码演示链表专题 leetcode61. 旋转链表 Leetcode链接&#xff1a; https://leetcode.cn/problems/rotate-list/ 题目描述 给你一个链表的头节点 head &#xff0c;旋转链表&#xff0c;将链表每个节点向右移动 k 个位置。 示例…

浅析 xml 数据格式文件

浅析 xml 数据格式文件 xml ( Extensible Markup Language ) 全称 -> 可拓展的标记语言&#xff1b; xml文件的主要用途&#xff1a;xml文件主要用于数据的 传输 和 存储&#xff0c;并不是展示&#xff1b; xml标签与html的区别&#xff1a;节点的标签使用方式和 html 十分…

【产品经理】企业的产品增长之路

英特尔前CEO安迪格鲁夫有本书叫做《Only the Paranoid Survive》&#xff0c;全文的中心思想是警示他人&#xff0c;要居安思危&#xff0c;唯有打破常规&#xff0c;不拘泥于现状才能生存。 一、为何企业都在关注增长&#xff1f; 1. 诺基亚的贱卖 13年市值曾位居全球上市公…

HNU-操作系统OS-作业1(4-9章)

这份文件是OS_homework_1 by计科2102 wolf 202108010XXX 文档设置了目录,可以通过目录快速跳转至答案部分。 第四章 4.1用以下标志运行程序:./process-run.py -l 5:100,5:100。CPU 利用率(CPU 使用时间的百分比)应该是多少?为什么你知道这一点?利用 -c 标记查看你…

Spring中如何获取Bean方法上的自定义注解

文章目录 背景描述场景复现问题追踪解决方案扩展思考 背景描述 项目中需要扫描出来所有 标注了自定义注解A的Service里面标注了自定义注解B的方法 来做后续处理。 基本的思路就是通过Spring提供的ApplicationContext#getBeansWithAnnotation反射 来实现。 但是&#xff0c;随…

【Spring】核心与设计思想

哈喽&#xff0c;哈喽&#xff0c;大家好~ 我是你们的老朋友&#xff1a;保护小周ღ 谈起Java 圈子里的框架&#xff0c;最年长最耀眼的莫过于 Spring 框架啦&#xff0c;如今已成为最流行、最广泛使用的Java开发框架之一。不知道大家有没有在使用 Spring 框架的时候思考过这…

11111111111

def cosine_similarity(vector_a, vector_b): “”" 计算两个向量之间的余弦相似度 :param vector_a: 向量 a :param vector_b: 向量 b :return: distance “”" vector_a np.mat(vector_a) vector_b np.mat(vector_b) num float(vector_a * vector_b.T) denom n…

华为OD机试真题 Java 实现【预定酒店】【2022Q4 100分】

一、题目描述 放暑假了,小明决定到某旅游景点游玩,他在网上搜索到了各种价位的酒店(长度为n的 数组A),他的心理价位是x元,请帮他筛选出k个最接近x元的酒店 (n>=k>0) ,并由低到高打印酒店的价格。 二、输入描述 第一行: n,k,x 第二行: A[o] A[1] A[2]…A[n-1] 三…

djiango orm简单实现增删改查

目录 一、配置数据库1.1 在settings.py文件中找到DATABASES &#xff0c;配置数据库连接&#xff0c;这里用的是mysql 二、切换操作数据库的模块三、 创建一个app并注册3.1创建一个app3.2 注册app 三、在app1定义模型类四、迁移数据库&#xff0c;使用以下命令&#xff0c;生成…

Android修改aar并重新打包

目录 一.修改 aar 需要用到的工具&#xff08;就一个工具&#xff0c;使用方式非常简单&#xff0c;别担心&#xff09; 二.修改 aar 代码层业务逻辑 三.修改 aar layout 布局文件 四.附上recyclerview aar修改工程源码 一.修改 aar 需要用到的工具&#xff08;就一个工具&…

MKS SERVO4257D 闭环步进电机_系列8 CAN通讯示例

第1部分 产品介绍 MKS SERVO 28D/35D/42D/57D 系列闭环步进电机是创客基地为满足市场需求而自主研发的一款产品。具备脉冲接口和RS485/CAN串行接口&#xff0c;支持MODBUS-RTU通讯协议&#xff0c;内置高效FOC矢量算法&#xff0c;采用高精度编码器&#xff0c;通过位置反馈&a…