交易所 Level-2 历史行情数据自动化导入攻略
用户部署完 DolphinDB 后,需要将历史股票数据批量导入数据库,再进行数据查询、计算和分析等操作。DolphinDB 开发了 ExchData 模块,主要用于沪深交易所 Level-2 行情原始数据的自动化导入,目前已支持的数据源包括:
- 沪深 Level-2 快照行情
- 沪深逐笔委托
- 沪深逐笔成交
- 上交所逐笔合并
注意:本教程代码基于 DolphinDB 2.00.11.3 开发,建议用户使用 2.00.11.3 及以上版本 。
1. 模块介绍
ExchData 模块主要包含预加载数据表结构、创建数据库及分区表、导入数据三部分。
1.1 数据表结构
schema 文件夹下的模块是根据本文第二章节中的合并规则整理的数据结构。该文件夹按照数据源格式,包含以下几个模块文件:
- tradeSchema 用于指定逐笔成交数据存入数据库的数据格式以及 DolphinDB 读取 CSV 文件时的数据格式。
- orderSchema 用于指定逐笔委托数据存入数据库的数据格式以及 DolphinDB 读取 CSV 文件时的数据格式。
- snapshotSchema 用于指定 Level-2 快照行情数据存入数据库的数据格式以及 DolphinDB 读取 CSV 文件时的数据格式。
- tradeOrderSchema 用于 DolphinDB 读取上交所逐笔合并数据的 CSV 文件时的数据格式。
1.2 创建数据库和分区表
数据库和分区表创建可参考 createTB.dos,其用于创建存储交易所数据的分布式库表。根据业务需求,这里对沪深股票 Level-2 高频行情数据采用一库三表的建库建表方案,分区方案如下:
表 1-1 分区方案
表名 | 分区方案 | 分区列 | 排序列 |
---|---|---|---|
trade | 时间维度按天分区+交易所 VALUE 分区 + 证券代码维度 HASH 25分区 | TradeDate、Market、SecurityID | SecurityID 和 TradeTime |
order | 时间维度按天分区 +交易所 VALUE 分区+ 证券代码维度 HASH 25分区 | TradeDate、Market、SecurityID | SecurityID 和 OrderTime |
snapshot | 时间维度按天分区+交易所 VALUE 分区+ 证券代码维度 HASH 25分区 | TradeDate、Market、 SecurityID | SecurityID 和 OrigTime |
1.3 数据导入
数据导入部分涉及 ExchData 文件夹和 ExchData.dos,作用如下:
- ExchData 包含了 Order.dos 、Snapshot.dos、Trade.dos、TradeOrder.dos 三个模块文件,分别用于导入沪深交易所的逐笔委托、行情快照和逐笔成交 Level-2 高频行情数据。
- ExchData.dos 用于导入指定目录下的所有交易所数据,是对前面所有模块的整合。
下面列出模块中的主要函数 ExchData
的语法和参数介绍。
语法
ExchData(dbName, tbNames, filePath, startDate, endDate, dataTypes, market="ALL", tmpPath=NULL, rowCount=1000000, deleteDuplicate=true, initialTB=false, initialDB=false)
详情
将 fileDir 路径下从 startDate 到 endDate 日期的 dataSource 数据导入 dbName
数据库中的 tableName
表里。
参数
- dbName 字符串,数据库名称。
- tbNames 字符串型的向量,分布式表名称。若需要导入逐笔合并数据,需要传入如 [“Order”, “Trade”] 的逐笔成交和逐笔委托表名;若需要导入其他行情数据,只需要传入导入的单一表名即可。
- filePath 字符串,指定的存放数据的路径,需要确保和第一章的文件结构一致。
- startDate 字符串,导入数据的起始日期,比如 2022.01.01(包括这一天)。默认值为 NULL,此时从上一个交易日开始导入。
- endDate 字符串,导入数据的结束日期,比如 2022.12.31(包括这一天)。默认值为 NULL,此时从上一个交易日开始导入。
- dataTypes 字符串型的向量,导入行情的数据源类型, “Snapshot”, “Order”, “Trade” 三选一或者 [“Order”, “Trade”]。
- market 字符串,交易所,目前只能 “ALL”, “SZ”, “SH” 三选一。当 market=“ALL” 时,会将沪深的数据全部导入一张名为 tableName 的分布式表;否则,会只导入一个交易所的数据。
- tmpPath 字符串,指定的临时文件存放路径,用于存放解压后的深交所的中间文件,解压后会将解压的临时文件删除。默认为 NULL,此时不会去解压缩,并基于指定的文件夹去识别数据文件导入数据。
- rowCount 整数,分段写入的最高数据量。指定后会对 CSV 数据分段写入分布式库表。默认值为 0,此时全量导入数据。
- deleteDuplicate 布尔值,表示是否需要删除数据库已导入的数据。默认值为 true,此时导入数据前不会删除库表中已存在的数据。
- initialDB 布尔值,是否需要初始化数据库。如果已经存在名为 dbName 的数据库,当 initialDB=true 时,会删除原来的数据库并重新创建;否则会保留原来的数据库并输出 "[dbName] 数据库已经存在" 的提示。
- initialTB 布尔值,是否需要初始化分布式表。如果在 dbName 数据库下已经存在名为 tbName 的表,当 initialTB=true 时,会删除原来的表并重新创建;否则会保留原来的表并输出 "数据库 [dbName] 已经存在表 [tbName]" 的提示。
2. 历史股票数据文件结构
在使用本功能模块时,需要准备解压缩后的历史股票数据文件(未解压缩的文件结构见附件),并确保在主目录下创建了对应的文件目录,不同时间段下(见第二章不同数据源的文件说明)的文件结构如下,假设最上层文件夹为 Data 文件夹,Data 文件夹下存放对应上交所(SH)、深交所(SZ)的交易所股票行情原始数据。
Data
└──SH
| ├── 2015
| │ └── 20150105
| │ ├── Entrust.csv
| │ ├── Snapshot.csv
| │ └── Tick.csv
| | ……
| ├── 2020
| │ └── 20200104
| │ ├── Entrust.csv
| │ ├── Snapshot.csv
| │ └── Tick.csv
| | ……
| └── 2023
| └── 20231205
| ├── Snapshot.csv
| └── StockTick.csv
| ……
└──SZ├── 2016│ └── 0506│ │ ├── SZL2_ORDER_20160506.TXT│ │ ├── SZL2_SNAPSHOT_20160506.TXT│ │ ├── SZL2_SNAPSHOTDW_20160506.TXT│ │ └── SZL2_TRADE_20160506.TXT│ └── 0509│ ├── am_hq_order_spot.txt│ ├── am_hq_snap_spot.txt│ ├── am_hq_trade_spot.txt │ ├── am_snap_level_spot.txt│ ├── pm_hq_order_spot.txt│ └── pm_hq_trade_spot.txt| ……
3. 行情数据存储模型设计
ExchData 模块将两个交易所的数据合并为一张表,其中表中的字段是两个交易所数据字段的并集,并新增字段 Market 为分区列用于标识数据来自哪个交易所。
上交所和深交所两个交易所数据的结构不同,且不同时期同一个交易所的数据结构也不同。根据《深圳证券信息有限公司高频增强行情数据服务》和《上海证券交易所历史股票数据接口说明书》,我们整理了两个交易所提供的各个时期的数据结构,最终确定以下述的表结构将数据存入数据库。
3.1 逐笔成交数据
- 沪深交易所导入逐笔成交数据的源文件
- 沪深交易所逐笔成交库表结构
字段含义 | 入库字段名 | 入库数据类型 | 上交所字段 | 上交所字段说明 | 深交所字段 | 深交所字段说明 |
---|---|---|---|---|---|---|
成交日期 | TradeDate | DATE | - | TradeDate | ||
数据生成时间 | OrigTime | TIMESTAMP | - | OrigTime | 2016 年 5 月 9 日新增 | |
发送时间 | SendTime | TIMESTAMP | SendingTime | 业务时间20150803093008,精确到百分之一秒自 2021年 4 月 26 日启 | SendTime | |
接收时间 | Recvtime | TIMESTAMP | - | Recvtime | 2016 年 5 月9 日新增 | |
入库时间 | Dbtime | TIMESTAMP | - | Dbtime | 2016 年 5 月 9 日新增 | |
证券代码 | SecurityID | SYMBOL | SecurityID | SecurityID | ||
成交时间 | TradeTime | TIMESTAMP | TradeTime | 业务时间 2015112309163002 ,精确到百分之一秒 | TradeTime | |
成交价格 | TradePrice | DOUBLE | TradePrice | Price | ||
成交量 | TradeQty | INT | TradeQty | TradeQty | ||
成交金额 | TradeAmount | DOUBLE | TradeAmount | - | ||
买方订单号 | BuyNo | LONG | BuyNo | BidApplSeqNum | ||
卖方订单号 | SellNo | LONG | SellNo | OfferApplSeqNum | ||
成交序号 | TradeIndex | INT | TradeIndex | |||
频道代码 | ChannelNo | INT | ChannelNo | ChannelNo | ||
内外盘标志 | TradeBSFlag | SYMBOL | TradeBSFlag | 内外盘标志: B – 外盘,主动买 S – 内盘,主动卖 N – 未知 | ||
业务序列号 | ApplSeqNum | LONG | BizIndex | 业务序列号 与竞价逐笔委托消息合并后 的连续编号,从 1 开始,按Channel 连续 | ApplSeqNum | |
成交类别 | ExecType | SYMBOL | - | ExecType | 4=撤消F=成交 | |
行情类别 | MDStreamID | SYMBOL | - | MDStreamID | MDStreamID=0112016 年 5 月 9 日新增 | |
证券代码源 | SecurityIDSource | SYMBOL | - | SecurityIDSource | 102 = 深圳证券交易所2016 年 5 月 9 日新增 | |
交易所名称 | Market | SYMBOL | - | 取值为SH | - | 取值为SZ |
3.2 逐笔委托数据
- 沪深交易所导入逐笔委托数据的源文件列表
- 沪深交易所逐笔委托库表结构
字段含义 | 入库字段名 | 入库数据类型 | 上交所字段 | 上交所字段说明 | 深交所字段 | 深交所字段说明 |
---|---|---|---|---|---|---|
成交日期 | TradeDate | DATE | TradeDate | |||
数据生成时间 | OrigTime | TIMESTAMP | OrigTime | 交易所数据生成时间2016年5月9日新增 | ||
发送时间 | SendTime | TIMESTAMP | SendTime | |||
接收时间 | Recvtime | TIMESTAMP | Recvtime | 2016年5月9日新增 | ||
入库时间 | Dbtime | TIMESTAMP | Dbtime | 2016年5月9日新增 | ||
证券代码 | SecurityID | SYMBOL | SecurityID | SecurityID | ||
委托时间 | OrderTime | TIMESTAMP | TransactTime | 如 20150803093008000 精确到毫秒 | TransactTime | |
委托订单号 | OrderNo | INT | OrderNo | |||
委托价格(元) | OrderPrice | DOUBLE | Price | Price | ||
委托数量 | OrderQty | INT | Balance | 剩余的委托数量 | OrderQty | 相对于上交所,该字段为总委托数量 |
已成交的委托数量 | TradeMoney | INT | TradeQty | 逐笔合并新增字段,用以区分Balance,表明成交的委托数量 | ||
买卖标志 | Side | SYMBOL | OrderBSFlag | 对于委托订单: B – 买单 S – 卖单 | Side | 1=买,2=卖G=借入,F=借出 |
订单类别 | OrderType | SYMBOL | OrdType | 订单类型A – 新增委托订单D – 删除委托订单,即撤单 | OrderType | 1=市价,2=限价,U=本方最优 |
委托序号 | OrderIndex | INT | OrderIndex | 从 1 开始,按 Channel 连 | ||
频道代码 | ChannelNo | INT | ChannelNo | 通道 | ChannelNo | 证券集代号 |
业务序列号 | ApplSeqNum | LONG | BizIndex | 业务序列号 与竞价逐笔成交消息合并后的连续编号,从 1 开始,按Channel 连续 | ApplSeqNum | 消息ID |
行情类别 | MDStreamID | SYMBOL | MDStreamID | 2016年5月9日新增 | ||
证券代码源 | SecurityIDSource | SYMBOL | SecurityIDSource | 102 = 深圳证券交易所2016年5月9日新增 | ||
定价行情约定号 | ConfirmID | INT | ConfirmID | 2016年5月9日新增 | ||
联系人 | Contactor | STRING | Contactor | 2016年5月9日新增 | ||
联系方式 | ContactInfo | STRING | ContactInfo | 2016年5月9日新增 | ||
期限 | ExpirationDays | INT | ExpirationDays | 2016年5月9日新增 | ||
期限类型 | ExpirationType | INT | ExpirationType | 2016年5月9日新增 | ||
交易所 | Market | SYMBOL | - | SH | - | SZ |
3.3 Level-2 快照数据
- 沪深交易所导入 Level-2 快照数据的源文件列表
- 沪深交易所 Level-2 快照行情表结构
字段含义 | 入库字段名 | 入库数据类型 | 上交所字段 | 上交所字段说明 | 深交所字段 | 深交所字段说明 |
---|---|---|---|---|---|---|
成交日期 | TradeDate | DATE | TradeDate | |||
数据生成时间 | OrigTime | TIMESTAMP | DateTime | 业务时间 格式如20151123091630 | OrigTime | |
发送时间 | SendTime | TIMESTAMP | SendingTime | 自 2021 年 12 月 1 日启用 | SendTime | |
接收时间 | Recvtime | TIMESTAMP | Recvtime | |||
入库时间 | Dbtime | TIMESTAMP | Dbtime | |||
行情类别 | MDStreamID | SYMBOL | MDStreamID | |||
证券代码 | SecurityID | SYMBOL | SecurityID | SecurityID | ||
交易状态 | TradeStatus | SYMBOL | InstrumentStatus | INIT 启动时段 PCALL 集中撮合时段 POSMT 连续交易时段 ENDPT 闭市时段 POSSP 停牌 | ||
快照类型 | NumImageStatus | INT | NumImageStatus | 1: 全量 2: 增量 自 2021 年12 月 1 日启用 | ||
频道代码 | ChannelNo | INT | ChannelNo | |||
证券代码源 | SecurityIDSource | SYMBOL | SecurityIDSource | 102 = 深圳证券交易所 | ||
昨收价 | PreClosePx | DOUBLE | PreClosePx | PreClosePx | ||
开盘价 | OpenPx | DOUBLE | OpenPx | OpenPx | ||
最高价 | HighPx | DOUBLE | HighPx | HighPx | ||
最低价 | LowPx | DOUBLE | LowPx | LowPx | ||
最新价 | LastPx | DOUBLE | LastPx | LastPx | ||
均价 | AvgPx | DOUBLE | AvgPx | 自 2021 年 12 月 1 日启用 | ||
收盘价 | ClosePx | DOUBLE | ClosePx | 自 2021 年 12 月 1 日启用 | ||
升跌1 | PxChange1 | DOUBLE | PxChange1 | |||
升跌2 | PxChange2 | DOUBLE | PxChange2 | |||
成交总量 | TotalVolumeTrade | INT | TotalVolumeTrade | 股票:股 基金:份 债券:千元面额 指数:手 | TotalVolumeTrade | |
成交总金额 | TotalValueTrade | DOUBLE | TotalValueTrade | 元 | TotalValueTrade | |
市盈率1 | PE1 | DOUBLE | PERatio1 | |||
市盈率2 | PE2 | DOUBLE | PERatio2 | |||
申买十价 | BidPrice | DOUBLE[10] | BidPrice | BidPX1/…/BidPX10 | ||
申买十量 | BidOrderQty | INT[10] | BidOrderQty | BidSize1/…/BidSize10 | ||
申买十实际总委托笔数 | BidNumOrders | INT[10] | BidNumOrders | NUMORDERS_B1 | ||
买一揭示委托笔数 | BidNoOrders1 | INT | NOORDERS_B1 | |||
申买一前50笔订单 | BidOrders | INT[50] | BidOrders | ORDERQTY_B1 | ||
申卖十价 | OfferPrice | DOUBLE[10] | OfferPrice | OfferPX1/…/OfferPX10 | ||
申卖十量 | OfferOrderQty | INT[10] | OfferOrderQty | OfferSize1/…/OfferSize10 | ||
申卖十实际总委托笔数 | OfferNumOrders | INT[10] | OfferNumOrders | NUMORDERS_S1 | ||
申卖一前50笔订单 | OfferOrders | INT[50] | OfferOrders | ORDERQTY_S1 | ||
卖一揭示委托笔数 | OfferNoOrders1 | INT | NOORDERS_S1 | |||
成交笔数 | NumTrades | INT | NumTrades | NumTrades | ||
基金T-1净值 | PreNAV | DOUBLE | PreNAV | 基金 | ||
基金实时参考净值IOPV | RealTimeNAV | DOUBLE | RealTimeNAV | 基金 | ||
ETF 净值估值 | IOPV | DOUBLE | IOPV | 从 20221104 日开始 | ||
权证溢价率 | WarrantPremiumRate | DOUBLE | WarrantPremiumRate | 权证 | ||
买入总量 | TotalBidQty | INT | TotalBidQty | 股票:股 基金:份 债券:千元面额 | totalbidqty | 协议 量和价是合一个条目中 |
卖出总量 | TotalOfferQty | INT | TotalOfferQty | 股票:股 基金:份 债券:千元面额 | totalofferqty | |
买入加权平均价 | WeightedAvgBidPx | DOUBLE | WeightedAvgBidPx | weightedavgbidpx | 协议 量和价是合一个条目中 | |
卖出加权平均价 | WeightedAvgOfferPx | DOUBLE | WeightedAvgOfferPx | weightedavgofferpx | ||
买入总比数 | TotalBidNumber | INT | TotalBidNumber | |||
卖出总比数 | TotalOfferNumber | INT | TotalOfferNumber | |||
总持仓量 | TotalLongPosition | INT | TotalLongPosition | |||
涨停价 | UpLimitPx | DOUBLE | UpLimitPx | |||
跌停价 | DownLimitPx | DOUBLE | DownLimitPx | |||
买入成交最大等待时间 | BidTradeMaxDuration | LONG | BidTradeMaxDuration | |||
卖出成交最大等待时间 | OfferTradeMaxDuration | LONG | OfferTradeMaxDuration | |||
买方委托价位数 | NumBidOrders | LONG | NumBidOrders | |||
卖方委托价位数 | NumOfferOrders | LONG | NumOfferOrders | |||
买入撤单笔数 | WithdrawBuyNumber | LONG | WithdrawBuyNumber | |||
买入撤单数量 | WithdrawBuyAmount | LONG | WithdrawBuyAmount | |||
买入撤单金额 | WithdrawBuyMoney | DOUBLE | WithdrawBuyMoney | |||
卖出撤单笔数 | WithdrawSellNumber | INT | WithdrawSellNumber | |||
卖出撤单数量 | WithdrawSellAmount | INT | WithdrawSellAmount | |||
卖出撤单金额 | WithdrawSellMoney | DOUBLE | WithdrawSellMoney | |||
ETF 申购笔 | ETFBuyNumber | INT | ETFBuyNumber | xwnum | 自 2024 年 01 月 04 日新增 | |
ETF 申购数量 | ETFBuyAmount | INT | ETFBuyAmount | xwsize | 自 2024 年 01 月 04 日新增 | |
ETF 申购金额 | ETFBuyMoney | DOUBLE | ETFBuyMoney | |||
ETF 赎回笔数 | ETFSellNumber | INT | ETFSellNumber | xxnum | 自 2024 年 01 月 04 日新增 | |
ETF 赎回数量 | ETFSellAmount | INT | ETFSellAmount | xxsize | 自 2024 年01 月 04 日新增 | |
ETF 赎回金额 | ETFSellMoney | DOUBLE | ETFSellMoney | |||
消息序号 | MsgSeqNum | INT | MsgSeqNum | 自 2021 年 12 月 1 日启用 | ||
债券质押式回购品种加权平均价 | WarLowerPx | DOUBLE | WarLowerPx | 自 2021 年 12 月 1 日启 | ||
产品实时阶段 | TradingPhaseCode | SYMBOL | TradingPhaseCode | 自 2021 年 12 月 1日启用 | TradingPhaseCode | 产品所处的交易阶段代码第 0 位:S=启动(开市前)O=开盘集合竞价T=连续竞价B=休市C=收盘集合竞价E=已闭市H=临时停牌A=盘后交易V=波动性中断第 1 位:0=正常状态1=全天停牌 |
加权平均价涨跌 | xj | DOUBLE | xj | 自 2017 年 5月 12 日新增 | ||
昨收盘加权平均价 | xk | DOUBLE | xk | 自 2017 年 5月 12 日新增 | ||
加权平均价 | Vwap | DOUBLE | Vwap | 自 2017 年 5月 12 日新增 |
4. 使用示例
- 第一步:用户按照第 2 章文件结构中准备好数据。假设数据放在 /home/wwluo/data/stockData 目录下,文件结构如下图:
图 4-1 文件结构示例
- 第二步: 将模块同步至 DolphinDB的 getHomeDir()+/modules 的目录下
图 4-2 更新模块示例
- 第三步:载入模块和导入数据方法如下,其中为了数据完整性以及避免执行
shell
函数引入安全问题,推荐基于本模块(见附录中的 ExchData.zip 文件)直接导入全量数据,若需要解压缩、分段导入,则分别需要指定tmpPath
、rowCount
等参数。
use ExchData::ExchData
go;// 导入逐笔成交数据 day=2021.04.26
startDate,endDate = 2021.04.26,2021.04.26
dbName = "dfs://TSDB_level2"
tbName = "trade"
dataType = "trade"
filePath = "/home/wwluo/data/stockData/"
tmpPath = "/home/wwluo/tmp/ALL/"
// 沪深交易所一起导入
market="ALL"
// 手动解压后导入数据;如需要自动解压缩需要指定tmpPath路径
tmpPath = NULL
// 全量导入数据;如需要指定分段导入,指定大于0的rowCount即可
rowCount = 0
jobId1 = submitJob("loadTradeData","loadTradeData",ExchData{dbName,tbName,filePath,startDate,endDate,dataType,market,tmpPath,rowCount,false,false})
getJobStatus(jobId1)
print getJobMessage(jobId1)// 导入逐笔委托数据
dbName = "dfs://TSDB_level2"
tbName = "order"
dataType = "order"
startDate,endDate = 2021.04.26,2021.04.26
filePath = "/home/wwluo/data/stockData/"
tmpPath = "/home/wwluo/tmp/ALL/"
// 沪深交易所一起导入
market="ALL"
// 手动解压后导入数据;如需要自动解压缩需要指定tmpPath路径
tmpPath = NULL
// 全量导入数据;如需要指定分段导入,指定大于0的rowCount即可
rowCount = 0
jobId2 = submitJob("loadOrderData","loadOrderData",ExchData{dbName,tbName,filePath,startDate,endDate,dataType,market,tmpPath,rowCount,false,false})
print getJobMessage(jobId2)// 导入快照数据
dbName = "dfs://TSDB_level2"
tbName = "snapshot"
dataType = "snapshot"
startDate,endDate = 2021.04.26,2021.04.26
filePath = "/home/wwluo/data/stockData/"
// 沪深交易所一起导入
market="ALL"
// 手动解压后导入数据;如需要自动解压缩需要指定tmpPath路径
tmpPath = NULL
// 全量导入数据;如需要指定分段导入,指定大于0的rowCount即可
rowCount = 0
jobId3 = submitJob("loadSnapshotData","loadSnapshotData",ExchData{dbName,tbName,filePath,startDate,endDate,dataType,market,tmpPath,rowCount,false,false})
print getJobMessage(jobId3)// 导入逐笔合并数据
startDate,endDate = 2024.01.22,2024.01.22
dbName = "dfs://TSDB_level2"
tbNames = ["trade","order"]
dataTypes = ["trade","order"]
filePath = "/home/wwluo/data/stockData/"
tmpPath = "/home/wwluo/tmp/ALL/"
// 只导入上交所数据
market="ALL"
// 手动解压后导入数据;如需要自动解压缩需要指定tmpPath路径
tmpPath = NULL
// 全量导入数据;如需要指定分段导入,指定大于0的rowCount即可
rowCount = 0
jobId4 = submitJob("loadSHTradeOrderData","loadSHTradeOrderData",ExchData{dbName,tbNames,filePath,startDate,endDate,dataTypes,market,tmpPath,rowCount,false,false})
print getJobMessage(jobId4)
- 第四步:查询任务状态
(1)使用 getJobStatus(jobId)
可以查询任务状态,当 endTime 有值的时候表示任务结束。例如:
图 4-3 getJobStatus 示例
(2)使用 getJobMessage(jobId)
可以查询任务中间信息,例如:
图 4-4 getJobMessage 示例
(3)可以通过查询日志内容,查看任务执行结果。例如:
cat dolphindb.log | grep message
图 4-5 log 示例
- 第五步:查询数据
(1)快照数据
select * from loadTable("dfs://TL_Level-2", "snapshot") limit 10
图 4-6 快照数据预览
(2)逐笔委托
select * from loadTable("dfs://TL_Level-2", "snapshot") limit 10
图 4-7 逐笔委托预览
(3)逐笔成交
select * from loadTable("dfs://TL_Level-2", "snapshot") limit 10
图 4-8 逐笔成交预览
5. 数据校验
在处理和分析交易所的 Level-2 历史行情数据时,针对原始数据的数据校验是一个至关重要的步骤。基于本模块的数据校验功能,可以监测交易所的 Level-2 历史行情数据是否存在数据遗漏、数据异常。
5.1 校验规则
ExchData 模块的 checkStockData.dos 支持对沪深交易所的逐笔成交和逐笔委托数据做数据校验,校验逻辑包括:
- 检查导入的逐笔成交和逐笔委托数据量是否小于 1500 万,否则提示数据异常。
- 针对2023年以后的数据,检查逐笔数据的 ChannelNo 的取值范围,检查上交所的 ChannelNo 所有取值是否包含 1~6 、深交所的 ChannelNo 所有取值是否包含2011~2014。
- 检查逐笔数据每一支 ChannelNo 下的所有 ApplSeqNum 是否连续;若不连续检查是否存在重复数据,以及是否存在数据缺失的异常情况。
5.2 校验接口
语法
checkStockData(startDate, endDate, market)
详情
校验 startDate 和 endDate 期间的逐笔数据,若校验未通过将返回统计信息表。
参数
startDate
开始日期。endDate
结束日期。market
交易所类型,支持”SH”、”SZ”、”ALL”。
使用示例
如下校验 2021.04.26 的逐笔数据是否存在异常,结果如下:
use ExchData::checkStockData
go;
checkAllData(2021.04.26,2021.04.26,"ALL")
图 5-1 数据校验示例
6. 异常处理
导入交易所的 Level-2 历史行情数据过程可拆分为如下步骤,其中每一步均可能存在异常,如下表所示。
- 创建库表:第一次运行时创建数据库表;若已存在本地库表,会与模块中库表的表结构做对比
- 解压缩:若导入深交所行情文件,若文件未解压缩,需要先将文件解压缩
- 加载 CSV:检查行情文件是否存在;若存在,检查文件的表结构与模块中预先指定的表结构的列数是否一致
- 数据导入:基于预先指定的表结构导入对应行情文件
- 数据校验:导入完成以后,进行数据校验
阶段 | 异常情况 | 输出信息 |
---|---|---|
创建库表 | 创建数据库时,名为 dbName 的数据库已经存在且 initialDB=false | {"code": "warning","message": "[dbName] 数据库已经存在"} |
创建库表 | 创建分布式表时,名为 tableName 的表已经存在且 initialDB=false | {"code": "warning","message": "数据库 [dbName] 已经存在表 [tableName]"} |
解压缩 | 导入深交所文件时解压失败 | {"code": "error","message": "解压文件失败: [fileName],请检查日志"} |
加载 CSV | 日期文件夹下,没有对应的 CSV 文件 | {"code": "error","message": "深交所 [day] 日期的 [CSVNames] 的 CSV 文件不全或者不存在"}{"code": "error","message": "上交所 [day] 日期的 [CSVNames] 的 CSV 文件不全或者不存在"} |
加载 CSV | 实际 CSV 文件的数据列数和 CsvSchema.dos 模块里面预设的表结构的列数不一致 | {"code": "error","message": "[CSVPath] 的数据格式有误,列数不匹配"} |
数据导入 | 写入分布式库表的数据量和 CSV 的数据量不一致 | {"code": "error","message": "深交所 [day] 日期的 [CSVNames] 的 CSV数据和写入dfs数据不一致,t1 size:[n1],t2 size:[n2]"}{"code": "error","message": "上交所 [day] 日期的 [CSVNames] 的 CSV数据和写入dfs数据不一致,t1 size:[n1],t2 size:[n2]"} |
数据导入 | 导入上交所逐笔合并数据时,CSV 文件的格式与模块中的 schema 不一致 | {"code": "error","message": "CSV 文件[StockTick.csv] 与分布式表待入库数据[“dfs:\\TSDB_Level-2“,”trade”]不一致"}{"code": "error","message": "CSV 文件[StockTick.csv] 与分布式表待入库数据[“dfs:\\TSDB_Level-2“,”order”]不一致"} |
数据导入 | 导入深交所快照行情数据时,快照行情和挡位表行数不一致 | {"code": "error","message": "深交所 [" + string(day) + "] 日期 [CSVName1] 和 [CSVName2]!"} |
数据校验 | 数据校验发现逐笔数据缺失channelNo | {"code": "error","message": "上交所 [" + string(day) + "] 日期 [" +"channelNo 数据缺失,共计 [" + string(channelSh.size()) + "] 个, 预计6个,请检查!"}{"code": "error","message": "深交所 [" + string(day) + "] 日期 [" +"channelNo 数据缺失,共计 [" + string(channelSh.size()) + "] 个, 预计4个,请检查!"} |
数据校验 | 数据校验发现逐笔数据小于 1500万 | {"code": "error","message": " [day] trade 数据异常! order 数据异常! "} |
数据校验 | 数据校验发现逐笔数据的某一支 channelNo 存在重复数据 | {"code": "error","message": "[深交所] 交易所 [day] 日期 [channelNo] channelNo 存在 [n] 条重复数据, 请检查!"}{"code": "error","message": "[上交所] 交易所 [day] 日期 [channelNo] channelNo 存在 [n] 条重复数据, 请检查!"} |
数据校验 | 数据校验发现逐笔数据的某一支 channelNo 存在 ApplSeqNum 数据缺失 | {"code": "error","message": "[深交所] 交易所 [day] 日期 [channelNo] channelNo [ApplSeqNum] ApplSeqNum缺失, 请检查!"}{"code": "error","message": "[上交所] 交易所 [day] 日期 [channelNo] channelNo [ApplSeqNum] ApplSeqNum缺失, 请检查!"} |
数据导入/数据校验 | 其他错误【通过 try{}catch(ex){} 捕获异常】 | {"code": "error","message": 输出报错信息 ex} |
7. 注意事项
- 导入数据时,请确保数据源文件路径正确,否则会导致导入失败。极端情况下,可能存在数据源文件未完全同步完,导致数据导入异常。
- 由于分段导入非强事务操作,因此内存充足情况下,不建议使用本模块分块导入数据;若部署的 DolphinDB 服务内存不足,一次性写入的沪深交易所数据量超过了 maxMemSize 大小,建议导入数据时设置较小的 rowCount 以确保能正常导入数据
- 由于本模块是基于
shell
函数执行服务器解压缩 shell 命令,该过程会存在安全问题的风险,因此不建议直接基于本模块去解压缩以导入深交所数据;若需要基于本模块解压缩深交所源文件,需要提前配置enableShellFunction=true
- 若服务器为 ARM 版本,解压深交所文件时调用的shell命令需要指定7zz命令的绝对路径,7zz解压时需要替换 ExchData 模块下的prepare.dos文件的7zz命令,需要替换 prepare.dos 的
unzipFile
中为实际使用的7zz命令路径(例如,/usr/local/bin/7zz x …… -o…… -y) - 导入深交所文件时,需要注意解压的文件是否存在分卷解压的情况,若存在需要确保各卷文件未存在数据缺失,导致解压失败
8. 总结
DolphinDB ExchData 模块为用户导入和处理沪深交易所 Level-2 行情数据提供了一套完整的解决方案, 本文介绍了模块的功能、行情文件结构及表结构、使用示例、数据校验等方面。用户基于本模块自动化的流程以及完整的校验机制,可以提高 Level-2 行情数据导入的效率以及数据完整性。
附录
- ExchData 导入模块见:ExchData 交易所历史股票数据自动化导入功能模块使用教程 (dolphindb.cn)
- 未压缩的文件结构:
SH
├── 2015
│ └── 20150105
│ ├── Entrust.csv
│ ├── Snapshot.csv
│ └── Tick.csv
| ……
├── 2020
│ └── 20200104
│ ├── Entrust.csv
│ ├── Snapshot.csv
│ └── Tick.csv
| ……
└── 2023
│ └── 20231205
│ ├── Snapshot.csv
│ └── StockTick.csv
| ……
SZ
├── 2016
│ ├── 0506
│ │ ├── SZL2_ORDER_20160506.7z.001
│ │ ├── SZL2_SNAPSHOT_20160506.7z.001
│ │ ├── SZL2_SNAPSHOTDW_20160506.7z.001
│ │ └── SZL2_TRADE_20160506.7z.001
│ └── 0509
│ ├── am_hq_order_spot.7z.001
│ ├── am_hq_snap_spot.7z.001
│ ├── am_hq_trade_spot.7z.001
│ ├── am_snap_level_spot.7z.001
│ ├── pm_hq_order_spot.7z.001
│ ├── pm_hq_snap_spot.7z.001
│ ├── pm_hq_trade_spot.7z.001
│ └── pm_snap_level_spot.7z.001
| ……
相关文章:
交易所 Level-2 历史行情数据自动化导入攻略
用户部署完 DolphinDB 后,需要将历史股票数据批量导入数据库,再进行数据查询、计算和分析等操作。DolphinDB 开发了 ExchData 模块,主要用于沪深交易所 Level-2 行情原始数据的自动化导入,目前已支持的数据源包括: 沪…...
从 scratch开始构建一个最小化的 Hello World Docker 镜像-docker的镜像源头
在这篇文章中,我们将学习如何从零开始构建一个最小化的 Docker 镜像,基于 scratch 镜像,并在其中运行一个简单的 “Hello World” 程序。 Scratch 是一个空白的基础镜像,适用于构建轻量化、独立的容器。由于 scratch 不包含任何系…...
【openGauss︱PostgreSQL】openGauss或PostgreSQL查表、索引、序列、权限、函数
【openGauss︱PostgreSQL】openGauss或PostgreSQL查表、索引、序列、权限、函数 一、openGauss查表二、openGauss查索引三、openGauss查序列四、openGauss查权限五、openGauss或PostgreSQL查函数六、PostgreSQL查表七、PostgreSQL查索引八、PostgreSQL查序列九、PostgreSQL查权…...
MySQL - 性能优化
使用 Explain 进行分析 Explain 用来分析 SELECT 查询语句,开发人员可以通过分析 Explain 结果来优化查询语句。 比较重要的字段有: select_type : 查询类型,有简单查询、联合查询、子查询等 key : 使用的索引 rows : 扫描的行数 type :…...
数据结构:二叉树遍历
在 JavaScript 中实现二叉树的遍历,可以使用递归或迭代的方式。以下是三种常见的遍历方式:前序遍历(Pre-order)、中序遍历(In-order)和后序遍历(Post-order)。 定义二叉树节点类 c…...
【热门主题】000075 探索嵌入式硬件设计的奥秘
前言:哈喽,大家好,今天给大家分享一篇文章!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏关注哦 💕 目录 【热…...
mac启动jmeter
// 设置使用java8,使用21版本会有问题 export JAVA_HOME/Library/Java/JavaVirtualMachines/jdk1.8.0_221.jdk/Contents/Home/ export PATH$JAVA_HOME/bin:$PATH cd /Users/user/software/apache-jmeter-5.1.1 //设置不使用代理 sh jmeter -Jhttp.proxyHost -J…...
JavaScript的作用域与闭包
文章目录 一. 什么是作用域?二. var a 2是如何赋值并添加到作用域中的?三. 作用域链四. js中的各种作用域五. 闭包?六. 参考 今天开始读了《你所不知道的JavaScript(上卷)》的一部分, 自己对于 JS 的理解还是非常浅薄的; 本着学习与分享的目的, 对这本书的第一章的内容进行…...
Qt入门7——Qt事件
目录 1. Qt事件介绍: 2. 事件的处理 示例1:鼠标进入(enterEvent)与离开事件(leaveEvent) 示例2:鼠标点击事件(mousePressEvent) 示例3:鼠标移动事件(mouseMoveEvent) 3. 按键事件 4. 定时器 5. 窗口事件 1. Qt事件介绍&a…...
【Linux操作系统】多线程控制(创建,等待,终止、分离)
目录 一、线程与轻量级进程的关系二、进程创建1.线程创建线程创建函数(pthread)查看和理解线程id主线程与其他线程之间的关系 三、线程等待(回收)四、线程退出线程退出情况线程退出方法 五、线程分离线程的优点线程的缺点 一、线程…...
VR眼镜可视化编程:开启医疗信息系统新纪元
一、引言 随着科技的飞速发展,VR 可视化编程在医疗信息系统中的应用正逐渐成为医疗领域的新趋势。它不仅为医疗教育、手术培训、疼痛管理等方面带来了新的机遇,还在提升患者体验、推动医疗信息系统智能化等方面发挥着重要作用。 在当今医疗领域…...
数据结构自测题6
第7章 图 自测卷解答 一、单选题(每题1分,共16分) ( C )1. 在一个图中,所有顶点的度数之和等于图的边数的 倍。 A.1/2 B. 1 C. 2 D. 4 ( B )2. 在一个有向图中࿰…...
Marvell第四季度营收预计超预期,定制芯片需求激增
芯片制造商Marvell Technology(美满电子科技)(MRVL)在周二发布了强劲的业绩预告,预计第四季度的营收将超过市场预期,得益于企业对其定制人工智能芯片的需求激增。随着人工智能技术的快速发展,特…...
从智能合约到去中心化AI:Web3的技术蓝图
Web3正在成为互联网发展的重要方向,其核心理念是去中心化、用户主权和自治。随着区块链技术、智能合约以及人工智能(AI)等技术的发展,Web3不仅重新定义了数据存储和交易方式,还为更智能化、去中心化的数字生态系统铺平…...
opencvocr识别手机摄像头拍摄的指定区域文字,文字符合规则就语音报警
安装python,pycharm,自行安装。 Python下安装OpenCv 2.1 打开cmd,先安装opencv-python pip install opencv-python --user -i https://pypi.tuna.tsinghua.edu.cn/simple2.2 再安装opencv-contrib-python pip install opencv-contrib-python --user …...
python 笔记之线程同步和死锁
同步: 共享数据: 如果多个线程共同对某个数据修改,则可能出现不可预测的结果,为了保证数据的正确性,需要对多个数据进行同步 同步:一个一个的完成,一个做完另一个才能进来 效率会降低 使用Thre…...
解决Error resolving plugin xxx
问题信息 Error resolving plugin [id: com.android.library, version: 8.6.0] > The request for this plugin could not be satisfied because the plugin is already on the classpath with an unknown version, so compatibility cannot be checked.* Try: > Run wi…...
Word2vec、词向量是什么? |Gensim中word2vec模型的参数定义
前言: 最近在忙毕设,要学习一些AI的技术。很多资料看来看去,感觉只是在大脑皮层表面略过了一下,遂还是决定采用老方法,写博客!!!对了,我也只是一个萌新,博客的…...
<工具 Claude Desktop> 配置 MCP server 连接本地 SQLite, 本机文件夹(目录) 网络驱动器 Windows 11 系统
也是在学习中... 起因: 抖音博客 艾克AI分享 他的视频 #143《Claude开源MCP彻底打破AI的信息孤岛》 提到: Claude开源的MCP太强了,视频后面是快速演示,反正看了好几遍也没弄明白。菜单都不一样,感觉用的不是同一家 Claude. 探…...
Android10 设备死机的问题分析和解决
最近客户反馈一个问题,设备偶现死机。最后解决,在此记录。 目录 一死机的现象 二死机的类型 三 死机问题分析 1 死机现象的梳理 2 死机日志 1)日志分析一 2 日志分析二(正确方案) 一死机的现象 设备死机&#x…...
Linux操作系统性能优化
Linux操作系统性能优化 1. TCP连接出现大量ESTABLISHED连接解决方法 1. TCP连接出现大量ESTABLISHED连接解决方法 TCP协议规定,对于已经建立的连接,网络双方要进行四次握手才能成功断开连接,如果缺少了其中某个步骤,将会使连接处于…...
【图像处理】用Python和OpenCV实现简单的图像增强与特征提取
《Python OpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门! 图像处理是计算机视觉领域的重要基础,而图像增强和特征提取是其中的关键技术。本文将详细探讨如何使用 Python 和 OpenCV 实现图像增强与特征提取。通过具体示例,我们将介绍滤波、直方图均衡化、边缘检测…...
【技术学习网站】
小黄鸭:面试鸭 - 程序员求职面试刷题神器,高频编程题目免费刷 编程导航:编程导航 - 程序员一站式编程学习交流社区,做您编程学习路上的导航员 博客园:博客园 - 开发者的网上家园 前端开发:HTTP 缓存 - H…...
程序员需要具备哪些知识?
程序员需要掌握的知识广泛而深厚,这主要取决于具体从事的领域和技术方向。不过,有些核心知识是共通的,就像建房子的地基一样,下面来讲讲这些关键领域: 1. 编程语言: 无论你是搞前端、后端、移动开发还是嵌…...
架构10-可观测性
零、文章目录 架构10-可观测性 1、可观测性 (1)可观测性的背景 **历史沿革:**可观测性最初由匈牙利数学家鲁道夫卡尔曼提出,用于线性动态控制系统。后来,该概念被引入到计算机科学中。**现代意义:**在分…...
Active RIS-Aided ISAC Systems: Beamforming Design and Performance Analysis
文章目录 II. SYSTEM MODELC. Active RIS Model III. PROBLEM FORMULATIONA. Radar Performance MetricC. Optimize Φ V. PERFORMANCE ANALYSIS OF THE RADAR SINR IN ACTIVE RIS-AIDED SENSING SYSTEMSA. Simplified System SettingB. Power Scaling Law AnalysisC. Active R…...
oracle 11g中如何快速设置表分区的自动增加
在很多业务系统中,一些大表一般通过分区表的形式来实现数据的分离管理,进而加快数据查询的速度。分区表运维管理的时候,由于人为操作容易忘记添加分区,导致业务数据写入报错。所以我们一般通过配置脚本或者利用oracle内置功能实现…...
HCIA-openGauss_1_4基本功能介绍
openGauss支持标准SQL SQL是用于访问和处理数据库的标准计算机语言,SQL标准的定义分成核心特性以及可选特性,绝大部分的数据库都没有100%支撑SQL标准。openGuass支持SQL2003标准语法,支持主备部署的高性能可用关系型数据库。openGauss数据库…...
el-menu导航三级数据结构及数据展示
1:数据展示 <el-col><el-menu:default-active"$route.path"class"el-menu-vertical-demo"routerunique-openedbackground-color"#545c64"text-color"#fff"active-text-color"#ffd04b"><div v-for"item …...
全面解析 Transformer:改变深度学习格局的神经网络架构
目录 一、什么是 Transformer? 二、Transformer 的结构解析 1. 编码器(Encoder) 2. 解码器(Decoder) 3. Transformer 模型结构图 三、核心技术:注意力机制与多头注意力 1. 注意力机制 2. 多头注意力&…...
R语言机器学习论文(二):数据准备
禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍加载R包数据下载导入数据一、数据描述二、数据预处理(一)修改元素名称(二)剔除无关变量(三)缺失值检查(四)重复值检查(五)异常值检查三、描述性统计(一)连续变量数据情…...
Linux之socket编程(一)
前言 网络通信的目的 我们已经大致了解了网络通信的过程: 如果主机A想发送数据给主机B, 就需要不断地对本层的协议数据单元(PDU)封装, 然后经过交换设备的转发发送给目的主机, 最终解封装获取数据. 那么网络传输的意义只是将数据由一台主机发送到另一台主机吗? …...
STM32之SDIO通讯接口和SD卡(九)
STM32F407 系列文章 - SDIO-To-SD Card(九) 目录 前言 一、SDIO接口 二、SD卡 三、实现程序 1.SD卡结构体参数说明 2.头文件定义 3.函数sd_init() 4.函数HAL_SD_MspInit() 5.函数get_sd_card_info() 6.函数get_sd_card_state() 7.函数sd_read…...
【Rust在WASM中实现pdf文件的生成】
Rust在WASM中实现pdf文件的生成 前言概念和依赖问题描述分步实现pdf转Blob生成URL两种方式利用localstorage传递参数处理图片Vec<u8>到pdf格式的Vec<u8>使用rust创建iframe显示pdf的Blob最后 前言 实现了一个通用的前端jpg转pdf的wasm,因为动态响应框架无法直接打…...
蓝桥杯真题——砍竹子(C语言)
问题描述 这天, 小明在砍竹子, 他面前有 n 棵竹子排成一排, 一开始第 ii 棵竹子的 高度为 .他觉得一棵一棵砍太慢了, 决定使用魔法来砍竹子。魔法可以对连续的一 段相同高度的竹子使用, 假设这一段竹子的高度为 H, 那么用一次魔法可以,把这一段竹子的高度都变为, 其中 [x]表…...
技术栈4:Docker入门 Linux入门指令
目录 1.Linux系统目录结构 2.处理目录的常用命令 3.Docker概述 4.Docker历史 5.Docker基本组成 6.Docker底层原理 7.Docker修改镜像源 8.Docker基本命令 在学习docker之前我们先要熟悉Linux系统,推荐阅读:Linux笔记(狂神说࿰…...
项目开发之Docker
文章目录 基础核心概念常用命令 实操1 windows11 docker mysql2 docker部署 xxljob3 container间调用异常问题4 部署mysql数据库5 docker desktop unexpected wsl error 基础 核心概念 其中的三个核心概念:dockerfile image/镜像 container/容器 image:…...
状态模式的理解和实践
在软件开发中,我们经常遇到需要根据对象的不同状态执行不同行为的情况。如果直接将这些状态判断和行为逻辑写在同一个类中,会导致该类变得臃肿且难以维护。为了解决这个问题,状态模式(State Pattern)应运而生。状态模式…...
正点原子imx6ull配置MQTT客户端上传数据到Ubuntu MQTT服务器
目录 使用QT自带的MQTT模块部署客户端创建一个class专门用于MQTT客户端通讯使用QT在ui界面上生成按钮在Windows上订阅相应主题测试在imx6ull上订阅Windows发布的消息 在上一篇中介绍了在Ubuntu22.04的Docker中部署MQTT服务器,然后在window上测试订阅和发布ÿ…...
【联表查询】.NET开源 ORM 框架 SqlSugar 系列
.NET开源 ORM 框架 SqlSugar 系列 【开篇】.NET开源 ORM 框架 SqlSugar 系列【入门必看】.NET开源 ORM 框架 SqlSugar 系列【实体配置】.NET开源 ORM 框架 SqlSugar 系列【Db First】.NET开源 ORM 框架 SqlSugar 系列【Code First】.NET开源 ORM 框架 SqlSugar 系列【数据事务…...
CAN接口设计
CAN总线的拓扑结构 CAN总线的拓扑结构有点像485总线,都是差分的传输方式,总线上都可以支持多个设备,端接匹配电阻都是120Ω。 485和CAN通信方面最大的区别:网络特性。485是一主多从的通讯方式,CAN是多主通讯,多个设备都可以做主机。那多个设备都相要控制总线呢?…...
基于遗传优化SVM的电机参数预测matlab仿真
目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 4.1 数据收集与预处理 4.2模型构建与训练 5.算法完整程序工程 1.算法运行效果图预览 (完整程序运行后无水印) 输入:电机结构参数x1 x2 x3 x4 x5(分别是铁心高度 铁心厚度 绕组…...
C++设计模式之代理模式
动机 在面向对象系统中,有些对象由于某种原因(比如对象创建的开销很大,或者某些操作需要安全控制,或者需要进程外的访问等),直接访问会给使用者、或者系统结构带来很多麻烦。 如何在不失去透明操作对象的…...
多线程JUC 第2季 控制线程的执行顺序,依次,交替,同时
一 场景1 交替执行 1.1 方案1使用completablefuture public class TestA {public static void main(String[] args) {for(int k0;k<10;k) {CompletableFuture<Void> t1 CompletableFuture.runAsync(() -> {System.out.println("A: >" Thread.curr…...
数据分析(一): 掌握STDF 掌握金钥匙-码农切入半导体的捷径
中国的半导体行业必然崛起!看清这个大势,就会有很多机会。 今天,我们一起来了解一下半导体行业的一朵金花:STDF。 实际上这只是一种文件格式,但是当你熟练掌握解析这种文件的时候,你就已经打开在这个基础…...
NPM镜像详解
NPM镜像详解 什么是NPM镜像 NPM镜像(NPM Mirror)是一个完整的NPM包的副本服务器。由于npm的官方registry服务器部署在国外,国内访问可能会比较慢,因此使用镜像可以加快包的下载速度。 常用的NPM镜像源 npm官方镜像 https://reg…...
【springboot】 多数据源实现
文章目录 1. 引言:多数据源的必要性和应用场景**为什么需要多数据源?****应用场景** 2. Spring Boot中的数据源配置2.1 默认数据源配置简介2.2 如何在Spring Boot中配置多个数据源 3. 整合MyBatis与多数据源**配置MyBatis使用多数据源****Mapper接口的数…...
Zephyr 入门-设备树与设备驱动模型
学习链接:https://www.bilibili.com/video/BV1L94y1F7qS/?spm_id_from333.337.search-card.all.click&vd_source031c58084cf824f3b16987292f60ed3c 讲解清晰,逻辑清楚。 1. 设备树概述(语法,如何配置硬件,c代码如…...
css实现圆周运动效果
在CSS中可以通过 keyframes 动画 和 transform 属性实现元素的圆周运动。以下是一个示例代码: 示例代码 <!DOCTYPE html> <html lang"en"> <head> <meta charset"UTF-8"> <meta name"viewport" content…...
乐鑫科技嵌入式面试题及参考答案(3万字长文)
嵌入式开发为什么用 C 语言,而不用 C++ 语言? 在嵌入式开发中,C 语言被广泛使用而 C++ 相对少用有以下一些原因。 首先,C 语言具有更高的效率。嵌入式系统通常资源受限,包括处理器速度、内存容量等。C 语言的代码生成效率高,能够生成紧凑的机器码,占用较少的内存空间和处…...