Я читаю эту книгу Практическое машинное обучение для алгоритмов c Торговля , и я наткнулся на скрипт, который должен анализировать большой .bin
двоичный файл и преобразовывать его в .h5
. Этот файл состоит из так называемых данных ITCH, техническую документацию данных можно найти здесь . Сценарий очень неэффективен, он читает файл размером 12 ГБ (12952050754 байта) по 2 байта за раз, что очень медленно (может занять до 4 часов на каком-нибудь приличном экземпляре GCP с 4 процессорами), что неудивительно. Вы можете найти всю записную книжку здесь .
Моя проблема в том, что я не понимаю, как читается этот .bin
файл. Я имею в виду, что я не понимаю, где необходимость чтения файл 2 байта за раз, я думаю, что есть способ читать при большом размере буфера, но я не уверен, как это сделать, или даже преобразовать скрипт в c ++, если после оптимизации этого скрипта он все еще работает медленно что я могу сделать, если я понимаю внутреннюю работу этого процесса ввода-вывода, есть ли у кого-нибудь предложения?
вот ссылка на файл источник данных ITCH, вы можете найти небольшие файлы (300 МБ или меньше), которые предназначены для меньших периодов времени, если вам нужно поэкспериментировать с кодом.
Узкое место:
with file_name.open('rb') as data:
while True:
# determine message size in bytes
message_size = int.from_bytes(data.read(2), byteorder='big', signed=False)
# get message type by reading first byte
message_type = data.read(1).decode('ascii')
message_type_counter.update([message_type])
# read & store message
record = data.read(message_size - 1)
message = message_fields[message_type]._make(unpack(fstring[message_type], record))
messages[message_type].append(message)
# deal with system events
if message_type == 'S':
seconds = int.from_bytes(message.timestamp, byteorder='big') * 1e-9
print('\n', event_codes.get(message.event_code.decode('ascii'), 'Error'))
print(f'\t{format_time(seconds)}\t{message_count:12,.0f}')
if message.event_code.decode('ascii') == 'C':
store_messages(messages)
break
message_count += 1
if message_count % 2.5e7 == 0:
seconds = int.from_bytes(message.timestamp, byteorder='big') * 1e-9
d = format_time(time() - start)
print(f'\t{format_time(seconds)}\t{message_count:12,.0f}\t{d}')
res = store_messages(messages)
if res == 1:
print(pd.Series(dict(message_type_counter)).sort_values())
break
messages.clear()
А вот функция store_messages()
:
def store_messages(m):
"""Handle occasional storing of all messages"""
with pd.HDFStore(itch_store) as store:
for mtype, data in m.items():
# convert to DataFrame
data = pd.DataFrame(data)
# parse timestamp info
data.timestamp = data.timestamp.apply(int.from_bytes, byteorder='big')
data.timestamp = pd.to_timedelta(data.timestamp)
# apply alpha formatting
if mtype in alpha_formats.keys():
data = format_alpha(mtype, data)
s = alpha_length.get(mtype)
if s:
s = {c: s.get(c) for c in data.columns}
dc = ['stock_locate']
if m == 'R':
dc.append('stock')
try:
store.append(mtype,
data,
format='t',
min_itemsize=s,
data_columns=dc)
except Exception as e:
print(e)
print(mtype)
print(data.info())
print(pd.Series(list(m.keys())).value_counts())
data.to_csv('data.csv', index=False)
return 1
return 0