我们将解释如何在以下场景中使用批量计算来计算 OHLC 柱:
- 需要指定 OHLC 窗口的启动时间;
- 一天中有多个交易时段,包括隔夜时段;
- 重叠 OHLC 窗口;
- OHLC 窗口根据交易量划分。
如果数据量非常大,需要将结果写入数据库,我们可以使用 DolphinDB 内置的 Map-Reduce 功能进行并行计算。
- 有实时数据
使用 API 实时接收市场数据,并使用 DolphinDB 内置的时序引擎进行实时计算。
1.用历史数据计算(批量计算)
要使用历史数据计算 OHLC 柱,您可以使用 DolphinDB 的内置函数bar, dailyAlignedBar
1.1 不指定 OHLC Windows 的启动时间
函数bar
一般用于根据指定的区间对数据进行分组。
date = 09:32m 09:33m 09:45m 09:49m 09:56m 09:56m;
bar(date, 5);
结果是:
[09:30m,09:30m,09:45m,09:45m,09:55m,09:55m]
示例 1:
n = 1000000
date = take(2019.11.07 2019.11.08, n)
time = (09:30:00.000 + rand(int(6.5*60*60*1000), n)).sort!()
timestamp = concatDateTime(date, time)
price = 100+cumsum(rand(0.02, n)-0.01)
volume = rand(1000, n)
symbol = rand(`AAPL`FB`AMZN`MSFT, n)
trade = table(symbol, date, time, timestamp, price, volume).sortBy!(`symbol`timestamp)
undef(`date`time`timestamp`price`volume`symbol);
计算 5 分钟 OHLC 柱:
barMinutes = 5m
OHLC = select first(price) as open, max(price) as high, min(price) as low, last(price) as close, sum(volume) as volume from trade group by symbol, date, bar(time, barMinutes) as barStart
函数参数intervalbar
支持DURATION类型。这里的“5m”表示5分钟。
1.2 需要指定OHLC窗口的启动时间
使用函数dailyAlignedBar
指定 OHLC 窗口的开始时间。此功能可以容纳每天多个交易时段以及隔夜时段。
请注意,对于 function dailyAlignedBar
,时间列的数据类型可以是 SECOND、TIME、NANOTIME、DATETIME、TIMESTAMP 和 NANOTIMESTAMP。指定每个交易时段开始时间的参数timeOffset必须具有相应的数据类型:分别为 SECOND、TIME 或 NANOTIME。
示例 2(每天一个交易时段):使用示例 1 中的相同表格“交易”计算 7 分钟 OHLC 柱。
barMinutes = 7m
OHLC = select first(price) as open, max(price) as high, min(price) as low, last(price) as close, sum(volume) as volume from trade group by symbol, dailyAlignedBar(timestamp, 09:30:00.000, barMinutes) as barStart
例3(每天两个交易时段):中国股市每天有两个交易时段,上午9:30-11:30,下午13:00-15:00。
使用以下脚本生成模拟数据:
n = 1000000
date = take(2019.11.07 2019.11.08, n)
time = (09:30:00.000 + rand(2*60*60*1000, n/2)).sort!() join (13:00:00.000 + rand(2*60*60*1000, n/2)).sort!()
timestamp = concatDateTime(date, time)
price = 100+cumsum(rand(0.02, n)-0.01)
volume = rand(1000, n)
symbol = rand(`600519`000001`600000`601766, n)
trade = table(symbol, timestamp, price, volume).sortBy!(`symbol`timestamp)
undef(`date`time`timestamp`price`volume`symbol)
计算 7 分钟 OHLC 柱:
barMinutes = 7m
sessionsStart=09:30:00.000 13:00:00.000
sessionsEnd=11:30:00.000 15:00:00.000
OHLC = select first(price) as open, max(price) as high, min(price) as low, last(price) as close, sum(volume) as volume from trade group by symbol, dailyAlignedBar(timestamp, sessionsStart, barMinutes, sessionsEnd) as barStart
示例 4(每天两个交易时段,隔夜时段):一些期货每天有多个交易时段,包括隔夜时段。在这个例子中,第一个交易时段是从上午 8:45 到下午 13:45,另一个时段是从下午 15:00 到第二天凌晨 05:00 的隔夜时段。
使用以下脚本生成模拟数据:
daySession = 08:45:00.000 : 13:45:00.000
nightSession = 15:00:00.000 : 05:00:00.000
n = 1000000
timestamp = rand(concatDateTime(2019.11.06, daySession[0]) .. concatDateTime(2019.11.08, nightSession[1]), n).sort!()
price = 100+cumsum(rand(0.02, n)-0.01)
volume = rand(1000, n)
symbol = rand(`A120001`A120002`A120003`A120004, n)
trade = select * from table(symbol, timestamp, price, volume) where timestamp.time() between daySession or timestamp.time()>=nightSession[0] or timestamp.time()<nightSession[1] order by symbol, timestamp
undef(`timestamp`price`volume`symbol);
计算 7 分钟 OHLC 柱:
barMinutes = 7
sessionsStart = [daySession[0], nightSession[0]]
OHLC = select first(price) as open, max(price) as high, min(price) as low, last(price) as close, sum(volume) as volume from trade group by symbol, dailyAlignedBar(timestamp, sessionsStart, barMinutes*60*1000) as barStart;
1.3 重叠 OHLC 窗口
在上述示例中,OHLC 窗口不重叠。要计算重叠的 OHLC 窗口,我们可以使用函数wj
(窗口连接)。使用该wj
函数,左表的每一行对应右表的一个窗口,可以在这个窗口上进行计算。
示例 5: 每天两个交易时段,OHLC 窗口重叠
模拟中国股市数据,每 5 分钟计算一个 30 分钟 OHLC 柱。
n = 1000000
sampleDate = 2019.11.07
symbols = `600519`000001`600000`601766
trade = table(take(sampleDate, n) as date,
(09:30:00.000 + rand(7200000, n/2)).sort!() join (13:00:00.000 + rand(7200000, n/2)).sort!() as time,
rand(symbols, n) as symbol,
100+cumsum(rand(0.02, n)-0.01) as price,
rand(1000, n) as volume)
首先生成 OHLC 窗口,然后使用函数cj
(交叉连接)生成股票代码和 OHLC 窗口的组合。
barWindows = table(symbols as symbol).cj(table((09:30:00.000 + 0..23 * 300000).join(13:00:00.000 + 0..23 * 300000) as time))
然后使用函数wj
计算具有重叠窗口的 OHLC 条:
OHLC = wj(barWindows, trade, 0:(30*60*1000),
<[first(price) as open, max(price) as high, min(price) as low, last(price) as close, sum(volume) as volume]>, `symbol`time)
1.4 根据交易量确定窗口
上述所有示例中的窗口都是随时间确定的。您还可以希望使用其他变量(例如交易量)作为确定窗口的基础。
示例 6:每次交易量增加 1,000,000 时计算 OHLC 柱。
n = 1000000
sampleDate = 2019.11.07
symbols = `600519`000001`600000`601766
trade = table(take(sampleDate, n) as date,
(09:30:00.000 + rand(7200000, n/2)).sort!() join (13:00:00.000 + rand(7200000, n/2)).sort!() as time,
rand(symbols, n) as symbol,
100+cumsum(rand(0.02, n)-0.01) as price,
rand(1000, n) as volume)
volThreshold = 1000000
t = select first(time) as barStart, first(price) as open, max(price) as high, min(price) as low, last(price) as close, last(cumvol) as cumvol
from (select symbol, time, price, cumsum(volume) as cumvol from trade context by symbol)
group by symbol, bar(cumvol, volThreshold) as volBar;
1.5 使用 MapReduce 加速计算
如果您需要从数据库中提取大规模的历史数据,计算出OHLC柱,然后将它们保存到数据库中,您可以使用内置的MapReduce函数mr
进行并行加载和计算。这种方法可以显着提高速度。
此示例使用美国股市交易数据。原始数据存储在数据库“dfs://TAQ”中的“trades”表中,具有复合分区:基于交易日期的值分区和基于股票代码的范围分区。
(1) 将磁盘上表的元数据加载到内存中:
login(`admin, `123456)
db = database("dfs://TAQ")
trades = db.loadTable("trades")
(2) 创建一个模板表'model',然后根据模板表的schema在数据库“dfs://TAQ”中创建一个空表'OHLC'来存储结果:
model=select top 1 Symbol, Date, Time.second() as bar, PRICE as open, PRICE as high, PRICE as low, PRICE as close, SIZE as volume from trades where Date=2007.08.01, Symbol=`EBAY
if(existsTable("dfs://TAQ", "OHLC"))
db.dropTable("OHLC")
db.createPartitionedTable(model, `OHLC, `Date`Symbol)
(3) 使用函数mr
计算 OHLC 柱并将结果写入表 'OHLC':
- 'ds' 是函数生成的一系列数据源
sqlDS
。每个数据源代表一个分区中的数据。 - Function
calcOHLC
是 MapReduce 中的映射函数。它从每个数据源计算 OHLC 柱,将结果写入数据库并返回写入数据库的行数。 - “+”是 MapReduce 中的 reduce 函数。它将所有映射函数的结果(写入数据库的行数)相加,以返回写入数据库的总行数。