解压并读取 Dukascopy .bi5 tick 文件
Decompress and read Dukascopy .bi5 tick files
我需要打开一个 .bi5
文件并阅读其中的内容,长话短说。问题:我有数以万计的 .bi5
文件,其中包含我需要解压缩和处理的时间序列数据(读取,转储到 pandas)。
我最终安装了 Python 3(我通常使用 2.7)专门用于 lzma
库,因为我 运行 使用 lzma
back- Python 2.7 的端口,所以我承认 运行 和 Python 3,但没有成功。问题多到无法吐露,没人看长题!
我已经包含了其中一个 .bi5
文件,如果有人能够设法将其放入 Pandas Dataframe 并向我展示他们是如何做到的,那就太理想了。
ps文件只有几kb,一秒下载。首先十分感谢。
下面的代码应该可以解决问题。首先,它打开一个文件并在 lzma and then uses struct 中对其进行解码以解压缩二进制数据。
import lzma
import struct
import pandas as pd
def bi5_to_df(filename, fmt):
chunk_size = struct.calcsize(fmt)
data = []
with lzma.open(filename) as f:
while True:
chunk = f.read(chunk_size)
if chunk:
data.append(struct.unpack(fmt, chunk))
else:
break
df = pd.DataFrame(data)
return df
最重要的是了解正确的格式。我四处搜索并尝试猜测 '>3i2f'
(或 >3I2f
)效果很好。 (它是 big endian 3 ints 2 floats。你的建议是:'i4f'
不会产生合理的浮点数 - 无论是 big endian 还是 little endian。)对于 struct
和格式语法,请参阅 docs。
df = bi5_to_df('13h_ticks.bi5', '>3i2f')
df.head()
Out[177]:
0 1 2 3 4
0 210 110218 110216 1.87 1.12
1 362 110219 110216 1.00 5.85
2 875 110220 110217 1.00 1.12
3 1408 110220 110218 1.50 1.00
4 1884 110221 110219 3.94 1.00
更新
比较 bi5_to_df
和 https://github.com/ninety47/dukascopy 的输出,
我从那里编译并 运行 test_read_bi5
。输出的第一行是:
time, bid, bid_vol, ask, ask_vol
2012-Dec-03 01:00:03.581000, 131.945, 1.5, 131.966, 1.5
2012-Dec-03 01:00:05.142000, 131.943, 1.5, 131.964, 1.5
2012-Dec-03 01:00:05.202000, 131.943, 1.5, 131.964, 2.25
2012-Dec-03 01:00:05.321000, 131.944, 1.5, 131.964, 1.5
2012-Dec-03 01:00:05.441000, 131.944, 1.5, 131.964, 1.5
和 bi5_to_df
在同一个输入文件上给出:
bi5_to_df('01h_ticks.bi5', '>3I2f').head()
Out[295]:
0 1 2 3 4
0 3581 131966 131945 1.50 1.5
1 5142 131964 131943 1.50 1.5
2 5202 131964 131943 2.25 1.5
3 5321 131964 131944 1.50 1.5
4 5441 131964 131944 1.50 1.5
所以一切似乎都很好(ninety47 的代码重新排序列)。
此外,使用 '>3I2f'
而不是 '>3i2f'
可能更准确(即 unsigned int
而不是 int
)。
在将数据传输到 pandas 之前,您是否尝试过使用 numpy 来解析数据。也许是一个漫长的解决方案,但我会允许您在使用 Panda 进行分析之前操作和清理数据,而且它们之间的集成非常简单,
import requests
import struct
from lzma import LZMADecompressor, FORMAT_AUTO
# for download compressed EURUSD 2020/06/15/10h_ticks.bi5 file
res = requests.get("https://www.dukascopy.com/datafeed/EURUSD/2020/06/15/10h_ticks.bi5", stream=True)
print(res.headers.get('content-type'))
rawdata = res.content
decomp = LZMADecompressor(FORMAT_AUTO, None, None)
decompresseddata = decomp.decompress(rawdata)
firstrow = struct.unpack('!IIIff', decompresseddata[0: 20])
print("firstrow:", firstrow)
# firstrow: (436, 114271, 114268, 0.9399999976158142, 0.75)
# time = 2020/06/15/10h + (1 month) + 436 milisecond
secondrow = struct.unpack('!IIIff', decompresseddata[20: 40])
print("secondrow:", secondrow)
# secondrow: (537, 114271, 114267, 4.309999942779541, 2.25)
# time = 2020/06/15/10h + (1 month) + 537 milisecond
# ask = 114271 / 100000 = 1.14271
# bid = 114267 / 100000 = 1.14267
# askvolume = 4.31
# bidvolume = 2.25
# note that 00 -> is january
# "https://www.dukascopy.com/datafeed/EURUSD/2020/00/15/10h_ticks.bi5" for january
# "https://www.dukascopy.com/datafeed/EURUSD/2020/01/15/10h_ticks.bi5" for february
# iterating
print(len(decompresseddata), int(len(decompresseddata) / 20))
for i in range(0, int(len(decompresseddata) / 20)):
print(struct.unpack('!IIIff', decompresseddata[i * 20: (i + 1) * 20]))
我需要打开一个 .bi5
文件并阅读其中的内容,长话短说。问题:我有数以万计的 .bi5
文件,其中包含我需要解压缩和处理的时间序列数据(读取,转储到 pandas)。
我最终安装了 Python 3(我通常使用 2.7)专门用于 lzma
库,因为我 运行 使用 lzma
back- Python 2.7 的端口,所以我承认 运行 和 Python 3,但没有成功。问题多到无法吐露,没人看长题!
我已经包含了其中一个 .bi5
文件,如果有人能够设法将其放入 Pandas Dataframe 并向我展示他们是如何做到的,那就太理想了。
ps文件只有几kb,一秒下载。首先十分感谢。
下面的代码应该可以解决问题。首先,它打开一个文件并在 lzma and then uses struct 中对其进行解码以解压缩二进制数据。
import lzma
import struct
import pandas as pd
def bi5_to_df(filename, fmt):
chunk_size = struct.calcsize(fmt)
data = []
with lzma.open(filename) as f:
while True:
chunk = f.read(chunk_size)
if chunk:
data.append(struct.unpack(fmt, chunk))
else:
break
df = pd.DataFrame(data)
return df
最重要的是了解正确的格式。我四处搜索并尝试猜测 '>3i2f'
(或 >3I2f
)效果很好。 (它是 big endian 3 ints 2 floats。你的建议是:'i4f'
不会产生合理的浮点数 - 无论是 big endian 还是 little endian。)对于 struct
和格式语法,请参阅 docs。
df = bi5_to_df('13h_ticks.bi5', '>3i2f')
df.head()
Out[177]:
0 1 2 3 4
0 210 110218 110216 1.87 1.12
1 362 110219 110216 1.00 5.85
2 875 110220 110217 1.00 1.12
3 1408 110220 110218 1.50 1.00
4 1884 110221 110219 3.94 1.00
更新
比较 bi5_to_df
和 https://github.com/ninety47/dukascopy 的输出,
我从那里编译并 运行 test_read_bi5
。输出的第一行是:
time, bid, bid_vol, ask, ask_vol
2012-Dec-03 01:00:03.581000, 131.945, 1.5, 131.966, 1.5
2012-Dec-03 01:00:05.142000, 131.943, 1.5, 131.964, 1.5
2012-Dec-03 01:00:05.202000, 131.943, 1.5, 131.964, 2.25
2012-Dec-03 01:00:05.321000, 131.944, 1.5, 131.964, 1.5
2012-Dec-03 01:00:05.441000, 131.944, 1.5, 131.964, 1.5
和 bi5_to_df
在同一个输入文件上给出:
bi5_to_df('01h_ticks.bi5', '>3I2f').head()
Out[295]:
0 1 2 3 4
0 3581 131966 131945 1.50 1.5
1 5142 131964 131943 1.50 1.5
2 5202 131964 131943 2.25 1.5
3 5321 131964 131944 1.50 1.5
4 5441 131964 131944 1.50 1.5
所以一切似乎都很好(ninety47 的代码重新排序列)。
此外,使用 '>3I2f'
而不是 '>3i2f'
可能更准确(即 unsigned int
而不是 int
)。
在将数据传输到 pandas 之前,您是否尝试过使用 numpy 来解析数据。也许是一个漫长的解决方案,但我会允许您在使用 Panda 进行分析之前操作和清理数据,而且它们之间的集成非常简单,
import requests
import struct
from lzma import LZMADecompressor, FORMAT_AUTO
# for download compressed EURUSD 2020/06/15/10h_ticks.bi5 file
res = requests.get("https://www.dukascopy.com/datafeed/EURUSD/2020/06/15/10h_ticks.bi5", stream=True)
print(res.headers.get('content-type'))
rawdata = res.content
decomp = LZMADecompressor(FORMAT_AUTO, None, None)
decompresseddata = decomp.decompress(rawdata)
firstrow = struct.unpack('!IIIff', decompresseddata[0: 20])
print("firstrow:", firstrow)
# firstrow: (436, 114271, 114268, 0.9399999976158142, 0.75)
# time = 2020/06/15/10h + (1 month) + 436 milisecond
secondrow = struct.unpack('!IIIff', decompresseddata[20: 40])
print("secondrow:", secondrow)
# secondrow: (537, 114271, 114267, 4.309999942779541, 2.25)
# time = 2020/06/15/10h + (1 month) + 537 milisecond
# ask = 114271 / 100000 = 1.14271
# bid = 114267 / 100000 = 1.14267
# askvolume = 4.31
# bidvolume = 2.25
# note that 00 -> is january
# "https://www.dukascopy.com/datafeed/EURUSD/2020/00/15/10h_ticks.bi5" for january
# "https://www.dukascopy.com/datafeed/EURUSD/2020/01/15/10h_ticks.bi5" for february
# iterating
print(len(decompresseddata), int(len(decompresseddata) / 20))
for i in range(0, int(len(decompresseddata) / 20)):
print(struct.unpack('!IIIff', decompresseddata[i * 20: (i + 1) * 20]))