Машинное обучение для статистического арбитража I: управление данными и визуализация

В этом примере показаны методы управления, обработки и визуализации больших объемов финансовых данных в MATLAB ®. Это часть серии связанных примеров машинного обучения для статистического арбитража (см. Приложения машинного обучения).

Работа с большими данными

Финансовые рынки, где электронные биржи, такие как NASDAQ, выполняют порядки во временной шкале миллисекунд, генерируют огромное количество данных. Потоки данных могут быть добыты для возможностей статистического арбитража, но традиционные методы обработки и хранения динамической аналитической информации могут быть перегружены большими данными. К счастью, появились новые вычислительные подходы, и MATLAB имеет массив инструментов для их реализации.

Основная память компьютера обеспечивает высокоскоростной доступ, но ограниченную емкость, в то время как внешняя память обеспечивает низкоскоростной доступ, но потенциально неограниченную емкость. Расчет происходит в памяти. Компьютер вызывает данные и результаты из внешнего хранилища.

Файлы данных

Этот пример использует один торговый день данных обмена NASDAQ [2] на одной безопасности (INTC) в выборке, предоставленной LOBSTER [1] и включенной с Financial Toolbox™ в zip- файла LOBSTER_SampleFile_INTC_2012-06-21_5.zip. Извлеките содержимое zip- файла в текущую папку. Расширенные файлы, включая два файла данных CSV и текстовый файл LOBSTER_SampleFiles_ReadMe.txt, потребляют 93,7 МБ памяти.

unzip("LOBSTER_SampleFile_INTC_2012-06-21_5.zip");

Данные описывают внутридневное развитие книги лимитных порядков (LOB), которая является записью рыночных порядков (лучшая цена), лимитных порядков (обозначенная цена) и получаемых закупок и продаж. Данные включают точное время этих событий с отслеживаемыми порядками от прибытия до отмены или выполнения. В каждый момент торгового дня порядки как на стороне покупки, так и на стороне продажи LOB существуют на различных уровнях вдали от средней цены между самым низким спросом (порядок на продажу) и самой высокой ставкой (порядок на покупку).

Данные уровня 5 (пять уровней вдали от среднего уровня с каждой стороны) содержатся в двух файлах CSV. Извлеките торговую дату из имени файла сообщения.

MSGFileName = "INTC_2012-06-21_34200000_57600000_message_5.csv";   % Message file (description of data)
LOBFileName = "INTC_2012-06-21_34200000_57600000_orderbook_5.csv"; % Data file

[ticker,rem] = strtok(MSGFileName,'_');
date = strtok(rem,'_'); 

Хранение данных

Ежедневные потоки данных накапливаются и должны храниться. Datastore является репозиторием для наборов данных, которые являются слишком большими, чтобы помещаться в памяти.

Использование tabularTextDatastore для создания хранилищ данных для файлов сообщений и данных. Поскольку файлы содержат данные с различными форматами, создайте хранилища данных отдельно. Игнорируйте типовые заголовки столбцов (для примера, VarName1) путем установки 'ReadVariableNames' аргумент пары "имя-значение" в false. Замените заголовки описательными именами переменных, полученными из LOBSTER_SampleFiles_ReadMe.txt. Установите 'ReadSize' аргумент пары "имя-значение" в 'file' позволяет добавлять файлы аналогичного формата к существующим хранилищам данных в конце каждого торгового дня.

DSMSG = tabularTextDatastore(MSGFileName,'ReadVariableNames',false,'ReadSize','file');
DSMSG.VariableNames = ["Time","Type","OrderID","Size","Price","Direction"];

DSLOB = tabularTextDatastore(LOBFileName,'ReadVariableNames',false,'ReadSize','file');
DSLOB.VariableNames = ["AskPrice1","AskSize1","BidPrice1","BidSize1",...
                       "AskPrice2","AskSize2","BidPrice2","BidSize2",...
                       "AskPrice3","AskSize3","BidPrice3","BidSize3",...
                       "AskPrice4","AskSize4","BidPrice4","BidSize4",...
                       "AskPrice5","AskSize5","BidPrice5","BidSize5"];

Создайте комбинированный datastore путем выбора Time и данные уровня 3.

TimeVariable = "Time";
DSMSG.SelectedVariableNames = TimeVariable;

LOB3Variables = ["AskPrice1","AskSize1","BidPrice1","BidSize1",...
                 "AskPrice2","AskSize2","BidPrice2","BidSize2",...
                 "AskPrice3","AskSize3","BidPrice3","BidSize3"];
DSLOB.SelectedVariableNames = LOB3Variables;
                               
DS = combine(DSMSG,DSLOB);         

Можно предворительно просмотреть первые несколько строк в комбинированном datastore, не загружая данные в память.

DSPreview = preview(DS);
LOBPreview = DSPreview(:,1:5)
LOBPreview=8×5 table
    Time     AskPrice1    AskSize1    BidPrice1    BidSize1
    _____    _________    ________    _________    ________

    34200    2.752e+05       66       2.751e+05      400   
    34200    2.752e+05      166       2.751e+05      400   
    34200    2.752e+05      166       2.751e+05      400   
    34200    2.752e+05      166       2.751e+05      400   
    34200    2.752e+05      166       2.751e+05      300   
    34200    2.752e+05      166       2.751e+05      300   
    34200    2.752e+05      166       2.751e+05      300   
    34200    2.752e+05      166       2.751e+05      300   

Предварительный просмотр показывает запросы и предложения на ощупь, что означает данные уровня 1, который ближе всего к середине периода. Временные модули указаны через секунды после полуночи, ценовые модули указаны в долларах США, умноженных на 10 000, и модули размера указаны количества акций (см. LOBSTER_SampleFiles_ReadMe.txt).

Длинные массивы и Timetables

Длинные массивы работают с данными , которыми не помещаютсями в память,, поддерживаемыми datastore с помощью метода MapReduce (см. «Длинные массивы для данных , которых не помещаютсь в память,»). Когда вы используете MapReduce, длинные массивы остаются недооцененными, пока вы не выполните определенные расчеты, которые используют данные.

Установите окружение выполнения для MapReduce в локальный сеанс сеанс работы с MATLAB вместо использования Parallel Computing Toolbox™ путем вызова mapreducer(0). Затем создайте длинный массив из datastore DS при помощи tall. Предварительный просмотр данных в длинный массив.

mapreducer(0)
DT = tall(DS);

DTPreview = DT(:,1:5)
DTPreview =

  Mx5 tall table

    Time     AskPrice1    AskSize1    BidPrice1    BidSize1
    _____    _________    ________    _________    ________

    34200    2.752e+05       66       2.751e+05      400   
    34200    2.752e+05      166       2.751e+05      400   
    34200    2.752e+05      166       2.751e+05      400   
    34200    2.752e+05      166       2.751e+05      400   
    34200    2.752e+05      166       2.751e+05      300   
    34200    2.752e+05      166       2.751e+05      300   
    34200    2.752e+05      166       2.751e+05      300   
    34200    2.752e+05      166       2.751e+05      300   
      :          :           :            :           :
      :          :           :            :           :

Расписания позволяют вам выполнять операции, характерные для временных рядов (см., Создание расписаний). Поскольку данные LOB состоят из параллельных временных рядов, преобразуйте DT к длинное расписание.

DT.Time = seconds(DT.Time); % Cast time as a duration from midnight.
DTT = table2timetable(DT);

DTTPreview = DTT(:,1:4)
DTTPreview =

  Mx4 tall timetable

      Time       AskPrice1    AskSize1    BidPrice1    BidSize1
    _________    _________    ________    _________    ________

    34200 sec    2.752e+05       66       2.751e+05      400   
    34200 sec    2.752e+05      166       2.751e+05      400   
    34200 sec    2.752e+05      166       2.751e+05      400   
    34200 sec    2.752e+05      166       2.751e+05      400   
    34200 sec    2.752e+05      166       2.751e+05      300   
    34200 sec    2.752e+05      166       2.751e+05      300   
    34200 sec    2.752e+05      166       2.751e+05      300   
    34200 sec    2.752e+05      166       2.751e+05      300   
        :            :           :            :           :
        :            :           :            :           :

Отобразите все переменные в рабочем пространстве MATLAB.

whos
  Name               Size            Bytes  Class                                       Attributes

  DS                 1x1                 8  matlab.io.datastore.CombinedDatastore                 
  DSLOB              1x1                 8  matlab.io.datastore.TabularTextDatastore              
  DSMSG              1x1                 8  matlab.io.datastore.TabularTextDatastore              
  DSPreview          8x13             4515  table                                                 
  DT                 Mx13             4950  tall                                                  
  DTPreview          Mx5              2840  tall                                                  
  DTT                Mx12             4746  tall                                                  
  DTTPreview         Mx4              2650  tall                                                  
  LOB3Variables      1x12              780  string                                                
  LOBFileName        1x1               234  string                                                
  LOBPreview         8x5              2203  table                                                 
  MSGFileName        1x1               230  string                                                
  TimeVariable       1x1               150  string                                                
  date               1x1               156  string                                                
  rem                1x1               222  string                                                
  ticker             1x1               150  string                                                

Поскольку все данные находятся в datastore, рабочая область использует мало памяти.

Предварительная обработка и оценка данных

Длинные массивы допускают предварительную обработку или постановку расчетов в очередь перед их оценкой, что улучшает управление памятью в рабочей области.

Средние S и индекс дисбаланса I используются для моделирования динамики LOB. Чтобы поставить их расчеты в очередь, задайте их и временную основу с точки зрения DTT.

timeBase = DTT.Time;
MidPrice = (DTT.BidPrice1 + DTT.AskPrice1)/2;

% LOB level 3 imbalance index:

lambda  = 0.5; % Hyperparameter
weights = exp(-(lambda)*[0 1 2]);
VAsk = weights(1)*DTT.AskSize1 + weights(2)*DTT.AskSize2 + weights(3)*DTT.AskSize3;
VBid = weights(1)*DTT.BidSize1 + weights(2)*DTT.BidSize2 + weights(3)*DTT.BidSize3;
ImbalanceIndex = (VBid-VAsk)./(VBid+VAsk);

Индекс дисбаланса является взвешенным средним значением объемов запросов и предложений по обеим сторонам средней цены [3]. Индекс дисбаланса является потенциальным показателем будущих изменений цен. Переменная lambda является гиперпараметром, который является параметром, заданным до обучения, а не оцененным алгоритмом машинного обучения. Гиперпараметр может повлиять на эффективность модели. Инженерия функций - это процесс выбора специфичных для области гиперпараметров для использования в алгоритмах машинного обучения. Вы можете настроить гиперпараметры, чтобы оптимизировать торговую стратегию.

Чтобы принести предварительно обработанные выражения в память и вычислить их, используйте gather функция. Этот процесс называется отсроченной оценкой.

[t,S,I] = gather(timeBase,MidPrice,ImbalanceIndex);
Evaluating tall expression using the Local MATLAB Session:
- Pass 1 of 1: Completed in 2.3 sec
Evaluation completed in 2.5 sec

Один вызов для gather вычисляет несколько предварительно обработанных выражений с одним проходом через datastore.

Определите размер выборки, которая является количеством тактов или обновлений в данных.

numTicks = length(t)
numTicks = 581030

Ежедневные данные LOB содержат 581 030 такты.

Данные контрольной точки

Можно сохранить как недооцененные, так и оцененные данные во внешнем хранилище для дальнейшего использования.

Подготовьте временную основу к дате и приведите результат к массиву datetime. Сохраните полученный массив datetime, MidPrice, и ImbalanceIndex в MAT-файл в указанном расположении.

dateTimeBase = datetime(date) + timeBase; 
Today = timetable(dateTimeBase,MidPrice,ImbalanceIndex)
Today =

  581,030x2 tall timetable

        dateTimeBase         MidPrice     ImbalanceIndex
    ____________________    __________    ______________

    21-Jun-2012 09:30:00    2.7515e+05         -0.205   
    21-Jun-2012 09:30:00    2.7515e+05       -0.26006   
    21-Jun-2012 09:30:00    2.7515e+05       -0.26006   
    21-Jun-2012 09:30:00    2.7515e+05      -0.086772   
    21-Jun-2012 09:30:00    2.7515e+05       -0.15581   
    21-Jun-2012 09:30:00    2.7515e+05       -0.35382   
    21-Jun-2012 09:30:00    2.7515e+05       -0.19084   
    21-Jun-2012 09:30:00    2.7515e+05       -0.19084   
             :                  :               :
             :                  :               :
location = fullfile(pwd,"ExchangeData",ticker,date);
write(location,Today,'FileType','mat')
Writing tall data to folder /tmp/BR2021ad_1655202_180016/mlx_to_docbook15/tp0c5070d3/finance-ex97702880/ExchangeData/INTC/2012-06-21
Evaluating tall expression using the Local MATLAB Session:
- Pass 1 of 1: Completed in 3.3 sec
Evaluation completed in 3.5 sec

Файл записывается один раз, в конце каждого торгового дня. Код сохраняет данные в файл в папке с меткой даты. Серия ExchangeData подпапки служат историческим данным репозиторием.

Кроме того, можно сохранить переменные рабочей области, оцененные с помощью gather непосредственно в MAT-файл в текущей папке.

save("LOBVars.mat","t","S","I")

В процессе подготовки к валидации модели позднее оцените и добавьте цены рыночного порядка к тому же файлу.

[MOBid,MOAsk] = gather(DTT.BidPrice1,DTT.AskPrice1);
Evaluating tall expression using the Local MATLAB Session:
- Pass 1 of 1: Completed in 2.1 sec
Evaluation completed in 2.2 sec
save("LOBVars.mat","MOBid","MOAsk","-append")

В оставшуюся часть этого примера используется только недооценённое длинное расписание DTT. Очистить другие переменные из рабочей области.

clearvars -except DTT 
whos
  Name            Size            Bytes  Class    Attributes

  DTT       581,030x12             4746  tall               

Визуализация данных

Чтобы визуализировать большие объемы данных, необходимо каким-либо образом суммировать, интервал, или отобразить данные, чтобы уменьшить число точек, нанесенных на экран.

Моментальный снимок LOB

Одним из методов визуализации является оценка только выбранной подвыборки данных. Создайте снимок LOB в определенное время суток (11 часов утра).

sampleTimeTarget = seconds(11*60*60);               % Seconds after midnight
sampleTimes = withtol(sampleTimeTarget,seconds(1)); % 1 second tolerance
sampleLOB = DTT(sampleTimes,:);

numTimes = gather(size(sampleLOB,1))
Evaluating tall expression using the Local MATLAB Session:
- Pass 1 of 1: Completed in 2.4 sec
Evaluation completed in 2.5 sec
numTimes = 23

В течение одной секунды с 11:00 до 23 тактов. Для моментального снимка используйте такт ближе всего к середине времени.

sampleLOB = sampleLOB(round(numTimes/2),:);
sampleTime = sampleLOB.Time;

sampleBidPrices = [sampleLOB.BidPrice1,sampleLOB.BidPrice2,sampleLOB.BidPrice3];
sampleBidSizes  = [sampleLOB.BidSize1,sampleLOB.BidSize2,sampleLOB.BidSize3];
sampleAskPrices = [sampleLOB.AskPrice1,sampleLOB.AskPrice2,sampleLOB.AskPrice3];
sampleAskSizes  = [sampleLOB.AskSize1,sampleLOB.AskSize2,sampleLOB.AskSize3];

[sampleTime,sampleBidPrices,sampleBidSizes,sampleAskPrices,sampleAskSizes] = ...
    gather(sampleTime,sampleBidPrices,sampleBidSizes,sampleAskPrices,sampleAskSizes);
Evaluating tall expression using the Local MATLAB Session:
- Pass 1 of 2: Completed in 2.4 sec
- Pass 2 of 2: Completed in 2.3 sec
Evaluation completed in 5.2 sec

Визуализируйте ограниченную выборку данных, возвращенную gather при помощи bar.

figure
hold on

bar((sampleBidPrices/10000),sampleBidSizes,'r')
bar((sampleAskPrices/10000),sampleAskSizes,'g')
hold off

xlabel("Price (Dollars)")
ylabel("Number of Shares")
legend(["Bid","Ask"],'Location','North')
title(strcat("Level 3 Limit Order Book: ",datestr(sampleTime,"HH:MM:SS")))

Figure contains an axes. The axes with title Level 3 Limit Order Book: 11:00:00 contains 2 objects of type bar. These objects represent Bid, Ask.

Глубина рынка

Некоторые функции визуализации работают непосредственно с длинные массивы и не требуют использования gather (см. «Визуализация длинных массивов»). Функции автоматически дискретизируют данные, чтобы уменьшить плотность пикселей. Визуализация уровня 3 внутридневной глубины рынка, которая показывает временную эволюцию ликвидности, с помощью plot с длинное расписание DTT.

figure
hold on

plot(DTT.Time,-DTT.BidSize1,'Color',[1.0 0 0],'LineWidth',2)
plot(DTT.Time,-DTT.BidSize2,'Color',[0.8 0 0],'LineWidth',2)
plot(DTT.Time,-DTT.BidSize3,'Color',[0.6 0 0],'LineWidth',2)

plot(DTT.Time,DTT.AskSize1,'Color',[0 1.0 0],'LineWidth',2)
plot(DTT.Time,DTT.AskSize2,'Color',[0 0.8 0],'LineWidth',2)
plot(DTT.Time,DTT.AskSize3,'Color',[0 0.6 0],'LineWidth',2)

hold off

xlabel("Time")
ylabel("Number of Shares")
title("Depth of Market: Intraday Evolution")
legend(["Bid1","Bid2","Bid3","Ask1","Ask2","Ask3"],'Location','NorthOutside','Orientation','Horizontal');

Figure contains an axes. The axes with title Depth of Market: Intraday Evolution contains 6 objects of type line. These objects represent Bid1, Bid2, Bid3, Ask1, Ask2, Ask3.

Для отображения подробных данных ограничьте временной интервал.

xlim(seconds([45000 45060]))
ylim([-35000 35000])
title("Depth of Market: One Minute")

Figure contains an axes. The axes with title Depth of Market: One Minute contains 6 objects of type line. These objects represent Bid1, Bid2, Bid3, Ask1, Ask2, Ask3.

Сводные данные

Этот пример представляет основы работы с большими данными, как в памяти, так и из памяти. В нем показано, как настроить, объединить и обновить внешние хранилища данных, а затем создать длинные массивы для предварительной обработки данных без выделения переменных в рабочем пространстве MATLAB. The gather функция переносит данные в рабочую область для расчетов и последующего анализа. Пример показов, как визуализировать данные с помощью выборки данных или функций построения графика MATLAB, которые работают непосредственно с данной , которой не помещаютсей в память,.

Ссылки

[1] LOBSTER Limit Order Book Data. Берлин: frischedaten UG (haftungsbeschränkt).

[2] Данные NASDAQ Historal TotalView-ITCH. Нью-Йорк: The Nasdaq, Inc.

[3] Рубисов, Антон Д. «Статистический арбитраж с использованием дисбаланса книги предельных порядков». Магистерская диссертация, Университет Торонто, 2015.

Похожие темы