exponenta event banner

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

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

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

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

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

Файлы данных

В этом примере используется один торговый день обмена данными NASDAQ [2] по одной безопасности (INTC) в образце, предоставленном LOBSTER [1] и включенном с финансовым 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,'_'); 

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

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

Использовать 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"];

Создание объединенного хранилища данных путем выбора 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);         

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

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).

Высокие массивы и расписания

Массивы Tall работают с данными вне памяти, поддерживаемыми хранилищем данных с помощью метода MapReduce (см. раздел Массивы Tall для данных из памяти). При использовании MapReduce массивы tall остаются невысокими до тех пор, пока не будут выполнены определенные вычисления, использующие данные.

Установите среду выполнения для MapReduce в локальный сеанс MATLAB вместо использования Toolbox™ параллельных вычислений путем вызова mapreducer(0). Затем создайте массив высокого уровня из хранилища данных 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                                                

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

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

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

Недорогой 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 вычисляет несколько предварительно обработанных выражений за один проход через хранилище данных.

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

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

Есть 23 клещей в течение одной секунды 11 утра. Для снимка используйте галочку, ближайшую к среднему времени.

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.

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

Некоторые функции визуализации работают непосредственно с массивами tall и не требуют использования gather (см. Визуализация массивов Tall). Функции автоматически производят выборку данных для уменьшения плотности пикселей. Визуализация внутридневной глубины рынка уровня 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. gather функция переносит данные в рабочую область для вычисления и дальнейшего анализа. В этом примере показано, как визуализировать данные посредством выборки данных или с помощью функций печати MATLAB, которые работают непосредственно с данными, не находящимися в памяти.

Ссылки

[1] Данные книги лимитов LOBSTER. Берлин: frischedaten UG (haftungsbeschränkt).

[2] Исторические данные NASDAQ TotalView-ITCH. Нью-Йорк: Nasdaq, Inc.

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

Связанные темы