← Мақалаларға оралу
May 26, 2026
5 мин оқу

DeepLOB: Лимиттік Тапсырыстар Кітабындағы Терең Оқыту

DeepLOB: Лимиттік Тапсырыстар Кітабындағы Терең Оқыту
#deep-learning
#order-book
#LOB
#microstructure
#HFT
#market-making
📖
Part 5 of 6 · Collection
Order Book & Market Microstructure

Лимиттік тапсырыстар кітабы (limit order book) қазіргі электронды нарықтардың орталық деректер құрылымы болып табылады. Әрбір сатып алу ұсынысы, әрбір сату ұсынысы, әрбір күшін жою — бәрі LOB-та өмір сүреді. Ондаған жылдар бойы сандық зерттеушілер осы деректерден белгілерді (features) қолмен жасап келді: тапсырыс теңгерімсіздігі коэффициенттері, өлшенген орта бағалар, кезек позициясы сигналдары. DeepLOB басқа жолды таңдады — ол гибридті CNN-LSTM архитектурасын пайдалана отырып, осы белгілерді тікелей шикі тапсырыстар кітабы снапшоттарынан үйренеді.

2019 жылы Oxford-Man институтында Zhang, Zohren және Roberts жариялаған DeepLOB бір ғана терең желі, шикі кітап деректерінде ұштан-ұшқа (end-to-end) оқытылған, орта баға қозғалысын болжауда мықты классикалық негіздермен (baseline) бәсекеге қабілетті немесе олардан жақсы екенін көрсетті. Дегенмен, дәлелдер туралы дәл болу керек. Көптеген мақалалар келтіретін эталондық FI-2010 деректер жиынын авторлардың өздері жеткіліксіз деп санайды — "тым қысқа, дискретизацияланған (downsampled) және өтімділігі аз нарықтан алынған" — және өздерінің күштірек нәтижесі ретінде Лондон қор биржасы (LSE) деректеріндегі екінші, әлдеқайда үлкен бағалауды ұсынады. Ол LSE зерттеуі бес оқыту акциясы мен бес тест акциясы бойынша шамамен бір жылды қамтиды, шамамен 100 миллионнан астам үлгі, және трансферлік оқытуды (transfer learning) көрсетеді: акциялардың бір жиынында оқытылған модель бұрын көрмеген акцияларда әлі де болжайды. Дәл сол трансфер нәтижесі, FI-2010 рейтингі емес, мақаланың нағыз басты тұжырымы. Бұл жазба архитектураны, математиканы, нақты сандарды және жұмыс істейтін PyTorch қайта іске асыруын талдайды.

Деректер Құрылымы ретіндегі Лимиттік Тапсырыстар Кітабы

Лимиттік тапсырыстар кітабының изометриялық көрінісі: орта баға айналасында тереңдік тензорын құрайтын жинақталған сатып алу және сату көлемі деңгейлері

Лимиттік тапсырыстар кітабы екі сұрыпталған тізімді сақтайды — bid (сатып алу тапсырыстары) және ask (сату тапсырыстары) — әрқайсысы баға деңгейі бойынша ұйымдастырылған. Әрбір деңгейде кітап бағаны және орындалмаған тапсырыстардың жиынтық көлемін тіркейді.

LL деңгейлі тапсырыстар кітабы үшін tt уақытындағы бір снапшот 4L4L мәннің векторы болып табылады:

xt=[p1a,v1a,p1b,v1b,p2a,v2a,p2b,v2b,,pLa,vLa,pLb,vLb]\mathbf{x}_t = [p_1^{a}, v_1^{a}, p_1^{b}, v_1^{b}, p_2^{a}, v_2^{a}, p_2^{b}, v_2^{b}, \ldots, p_L^{a}, v_L^{a}, p_L^{b}, v_L^{b}]

мұндағы piap_i^{a} және viav_i^{a}ii деңгейіндегі сату бағасы мен көлемі, ал pibp_i^{b}, vibv_i^{b} — сатып алу жағының сәйкес мәндері. 1-деңгейде ең жақсы bid және ең жақсы ask (BBO) болады; олардың айырмасы bid-ask спрэді.

FI-2010 эталондық деректер жиынында L=10L = 10, бұл снапшот үшін 40 белгі береді. FI-2010 NASDAQ Nordic-те (Kesko, Outokumpu, Sampo, Rautaruukki, Wartsila) бес фин акциясының шамамен 4 миллион шикі лимиттік тапсырыс хабарламасынан, 2010 жылдың 1-14 маусымы аралығындағы он кету сауда күнінде құрылған. Маңыздысы, DeepLOB 4 миллион снапшотта оқытылмайды: эталон бұл хабарламаларды (әр 10 оқиға сайын) 394,337 үлгіден тұратын қалыпқа келтірілген көрінісіне дейін дискретизациялайды (downsample). Дәл сол дискретизацияланған, қалыпқа келтірілген түр моделдің нақты көретіні болып табылады — авторлардың FI-2010-ды соңғы сөз ретінде қарастырудан сақтандыратын себептерінің бірі осы.

Орта Баға және Оның Қозғалыстары

tt уақытындағы орта баға ең жақсы bid пен ask-тың орташасы болып табылады:

ptmid=p1a(t)+p1b(t)2p_t^{mid} = \frac{p_1^{a}(t) + p_1^{b}(t)}{2}

DeepLOB kk оқиғаның болашақ көкжиегінде орта баға қозғалысының бағытын болжайды. Белгі (label) тегістелген табыс (return) болып табылады, бірақ әдебиетте екі тегістеу конвенциясы бар екенін ескеру керек, олар өзара ауыстырылмайды:

  • Болашақ орташа vs. ағымдағы баға (Tsantekidis et al.): келесі kk оқиға бойынша орташа орта бағаны шикі ағымдағы орта бағамен салыстырады.
  • Болашақ орташа vs. алдыңғы орташа (Ntakaris et al., канондық FI-2010 белгісі, сонымен қатар DeepLOB өзінің LSE деректері үшін пайдаланған): анықтама (reference) де, мақсат (target) те тегістеледі.
lt(k)=m+(t)m(t)m(t),m(t)=1ki=0k1ptimid,m+(t)=1ki=1kpt+imidl_t(k) = \frac{m_+(t) - m_-(t)}{m_-(t)}, \qquad m_-(t) = \frac{1}{k}\sum_{i=0}^{k-1} p_{t-i}^{mid}, \quad m_+(t) = \frac{1}{k}\sum_{i=1}^{k} p_{t+i}^{mid}

Анықтаманы тегістеу (тек болашақты ғана емес) жалғыз тик ауытқуларынан туындайтын белгі шуылын айтарлықтай азайтады, сондықтан алдыңғы/келесі орташа формасы артық көрінеді. Қайсысын қолданса да, үздіксіз табыс ±α\pm\alpha тұрақты шектерін пайдалана отырып үш класқа дискретизацияланады — өсу, түсу, тұрақты:

yt={1егер lt(k)>α0егер lt(k)α1егер lt(k)<αy_t = \begin{cases} 1 & \text{егер } l_t(k) > \alpha \\ 0 & \text{егер } |l_t(k)| \leq \alpha \\ -1 & \text{егер } l_t(k) < -\alpha \end{cases}

FI-2010 деректер жиыны бес болжам көкжиегі үшін белгілер ұсынады: k{10,20,30,50,100}k \in \{10, 20, 30, 50, 100\} оқиға.

Дәстүрлі LOB Белгілері

Терең оқытуға дейін зерттеушілер қолмен жасалған белгілерге сүйенді. Мұны түсіну маңызды, себебі DeepLOB әдейі олардың көбіне ұқсас болатындай құрылымдалған — оның архитектурасы бұл шамаларды дәл қайталамаса да, олармен негізделген.

Тапсырыстар Кітабы Теңгерімсіздігі (OBI)

Ең кеңінен қолданылатын микроқұрылым сигналы. Кітаптың жоғарғы жағында:

OBI1=v1bv1av1b+v1a\text{OBI}_1 = \frac{v_1^{b} - v_1^{a}}{v_1^{b} + v_1^{a}}

Сату көлеміне қатысты сатып алу көлемінің көбірек болуы жоғары қарай қысымды білдіреді. Көп деңгейлі теңгерімсіздік LL деңгей бойынша жиынтықталады:

OBIL=i=1Lvibi=1Lviai=1Lvib+i=1Lvia\text{OBI}_L = \frac{\sum_{i=1}^{L} v_i^{b} - \sum_{i=1}^{L} v_i^{a}}{\sum_{i=1}^{L} v_i^{b} + \sum_{i=1}^{L} v_i^{a}}

Көлеммен Өлшенген Орта Баға

Стандартты орта баға екі жақты бірдей өлшейді. Көлеммен өлшенген орта баға (сонымен қатар өлшенген орта, немесе VAMP деп аталады) кітаптың ауырырақ жағына қарай ауытқиды. Кітаптың жоғарғы жағының теңгерімсіздігін I=v1b/(v1b+v1a)I = v_1^{b}/(v_1^{b}+v_1^{a}) деп жазсақ, бұл екі бағаның теңгерімсіздікпен өлшенген орташасы:

pwmid=Ip1a+(1I)p1b=v1bp1a+v1ap1bv1b+v1ap^{wmid} = I\, p_1^{a} + (1 - I)\, p_1^{b} = \frac{v_1^{b}\, p_1^{a} + v_1^{a}\, p_1^{b}}{v_1^{b} + v_1^{a}}

Кросс-өлшеуге назар аударыңыз: ask бағасы bid көлемімен өлшенеді және керісінше. Bid көлемі басым болғанда (I1I \to 1), өлшенген орта ask жағына ауысады — бұл теңгерімсіз кітаптың ауырырақ жаққа қарай жылжу арқылы шешілетінін көрсетеді.

Атаудың дәлдігі туралы ескерту. Бұл статикалық, көлеммен өлшенген орта Stoikov-тың микробағасы емес. Stoikov-тың микробағасы (2018) — спрэд пен теңгерімсіздіктің қалай дамитынын рекурсивті түзету арқылы алынған мартингейлмен түзетілген бағалаушы Mt+g(I,S)M_t + g(I, S) — Stoikov-тың бүкіл негізгі ойы наивті өлшенген орта біржақты (biased) екені және мартингейл емес екені. Бұл екі бөлек нәрсе; біз мұнда өлшенген ортаны оның қарапайымдылығы үшін пайдаланамыз, микробаға орнына емес.

Тереңдік Теңгерімсіздігі

BBO-дан тыс кітаптың пішінін өлшейді:

DIi=vibviavib+via,i=1,,L\text{DI}_i = \frac{v_i^{b} - v_i^{a}}{v_i^{b} + v_i^{a}}, \quad i = 1, \ldots, L

Спрэд және Салыстырмалы Спрэд

st=p1a(t)p1b(t),strel=stptmids_t = p_1^{a}(t) - p_1^{b}(t), \qquad s_t^{rel} = \frac{s_t}{p_t^{mid}}

Бұл белгілер қуатты, бірақ шектеулі. Оларды жобалау үшін домендік сараптама қажет, күрделі сызықтық емес өзара әрекеттесулерді қамтымайды және дәйекті снапшоттар арасындағы уақыттық динамиканы елемейді. DeepLOB осы үш шектеуді де шешеді.

DeepLOB Архитектурасы

DeepLOB архитектурасы: конволюциялық қабаттар, inception модулі және LSTM арқылы ағатын шикі тапсырыстар кітабы тензоры

Архитектурада үш блок бар, әрқайсысының өзіндік рөлі бар:

  1. Конволюциялық блок — тапсырыстар кітабы снапшотынан кеңістіктік белгілерді алады
  2. Inception модулі — көп масштабты уақыттық үлгілерді (patterns) қамтиды
  3. LSTM блогы — уақыт бойынша тізбектелген тәуелділіктерді модельдейді

Желінің кірісі (T,L×4)(T, L \times 4) пішінді тензор болып табылады, мұндағы TT — ретроспективті терезе (мақалада 100 уақыт қадамы), ал L×4=40L \times 4 = 40 — екі жақта да баға мен көлемнің 10 деңгейі үшін.

Блок 1: Конволюциялық Белгі Алу

Алғашқы конволюциялық қабаттар әрбір деңгейде баға мен көлем арасындағы өзара әрекеттесуді үйрену үшін белгі өлшемі бойымен жұмыс істейді.

1-қабат: Әрбір баға-көлем жұбына қолданылатын 1×21 \times 2 фильтр өлшемі мен (1,2)(1, 2) қадамдағы конволюция. Бұл әрбір (pi,vi)(p_i, v_i) жұбын бір белгіге жинақтайды — әрбір деңгейде "баға-көлем өзара әрекеттесуін" есептеуге ұқсас. Ені 40-тан 20-ға дейін кішірейеді.

2-қабат: Сол деңгейдегі сәйкестендірілген bid-ask жұптары бойынша жұмыс істейтін 1×21 \times 2, (1,2)(1, 2) қадамды конволюция. Бұл деңгей бойынша спрэд пен теңгерімсіздік ақпаратын қамтиды. Ені 20-дан 10-ға дейін кішірейеді.

3-қабат: Барлық 10 деңгей бойынша интеграцияланатын 1×101 \times 10 конволюция, тереңдік өлшемін 1 еніне дейін жинақтайды. Бұл толық тереңдік профилін кодтайтын әрбір уақыт қадамы үшін бір жинақталған белгі шығарады.

Әрбір 1×21 \times 2 / 1×101 \times 10 қадамынан кейін уақыт осі бойымен екі (4,1)(4, 1) конволюция жүреді, әрқайсысы LeakyReLU активациясымен және пакеттік нормализациямен (batch normalization). padding=(1, 0) бар бұл (4,1)(4, 1) конволюциялары уақыт өлшемін сақтамайтынын ескеріңіз: әрқайсысы оны бір қадамға қысқартады (Tout=Tin1T_{\text{out}} = T_{\text{in}} - 1). 1-3 блоктардағы осындай алты қабат бойынша уақыт осі inception модуліне дейін 100-ден 94-ке дейін кішірейеді — бұл төмендегі кодтағы пішін түсініктемелерінде айқын көрсетілген.

Дизайн әдейі үлкен кеңістіктік фильтрлерден аулақ болады. 1×21 \times 2 фильтрлер LOB деректерінің табиғи жұптасу құрылымын құрметтейді — баға көлеммен, bid ask-пен. Бұл индуктивті бейімделу (inductive bias) шешуші: 3×33 \times 3 фильтр қаржылық мағынасы жоқ тәсілмен көрші деңгейлер мен жақтарды араластырар еді.

Блок 2: Inception Модулі

Конволюциялық блок 40 белгіні ықшам кеңістіктік көрінісіне (ені 1) дейін азайтқаннан кейін, inception модулі бірнеше уақыттық масштабта бір мезгілде үлгілерді қамту үшін уақыт өлшемі бойымен жұмыс істейді.

DeepLOB inception модулінде төрт параллель жол бар, әрқайсысы 32 арна шығарады, барлығы біріктірілген:

  • 1×11 \times 1 тар өткел (bottleneck) \to 3×13 \times 1 уақыттық конволюция: қысқа мерзімді уақыттық үлгілер (3 уақыт қадамы)
  • 1×11 \times 1 тар өткел \to 5×15 \times 1 уақыттық конволюция: орта мерзімді уақыттық үлгілер (5 уақыт қадамы)
  • 3×13 \times 1 max-pool \to 1×11 \times 1 конволюция: тегістелген, дискретизацияланған көріністі сақтайтын пулинг жолы
  • (1×11 \times 1 азайтулары уақыттық конволюциялардан бұрын нүктелік-уақыттағы тар өткелдер ретінде әрекет етеді)

Әрбір уақыттық жол симметриялы толтыруды (padding) пайдаланады, осылайша уақыт өлшемі inception блогының ішінде сақталады (жоғарыдағы конволюциялық блоктардан айырмашылығы). Шығыстар арна өлшемі бойынша біріктіріледі, бұл желіге бір уақытта көп масштабты уақыттық белгілерге қол жеткізуге мүмкіндік береді.

Бұл GoogLeNet inception архитектурасынан шабыттандырылған, бірақ 2D суреттер орнына 1D уақыттық деректерге бейімделген. Негізгі түсінік мынада: LOB динамикасы бірнеше уақыт масштабында жұмыс істейді: тиктен-тикке шу, қысқа мерзімді импульс (momentum) және ұзақ мерзімді орташаға қайту (mean reversion) бәрі бірге өмір сүреді.

Төмендегі PyTorch қайта іске асыруы жеңілдетілген үш жолды нұсқаны ұсынады (екі уақыттық конволюция плюс 1×11\times1 жол), осылайша код оқуға оңай болып қалады; ол max-pool жолын алып тастайды. Біз мұны нақты атап көрсетеміз, себебі бұл мақаладан ауытқу, түпнұсқа модуль емес.

Блок 3: LSTM Тізбек Модельдеу

Inception модулінің шығысы толық TT-ұзындықты тізбекті өңдейтін LSTM қабатына беріледі. LSTM конволюциялар өз бетінше жіберіп алатын алыс қашықтықтағы уақыттық тәуелділіктерді қамтиды — режим өзгерістері, тәулік уақыты әсерлері және дамып жатқан нарық жағдайлары.

LSTM-нің соңғы жасырын күйі үш класс (өсу, түсу, тұрақты) бойынша ықтималдық үлестірімін шығару үшін softmax активациясы бар толық байланысқан қабат арқылы өтеді.

Шығын Функциясы

Модель категориялық кросс-энтропиямен оқытылады:

L=1Ni=1Nc=13yi,clog(y^i,c)\mathcal{L} = -\frac{1}{N} \sum_{i=1}^{N} \sum_{c=1}^{3} y_{i,c} \log(\hat{y}_{i,c})

мұндағы yi,cy_{i,c} — one-hot кодталған шынайы белгі, y^i,c\hat{y}_{i,c}cc класы үшін болжанған ықтималдық.

PyTorch Қайта Іске Асыруы

Түпнұсқа DeepLOB TensorFlow негізінде Keras-та құрылған; авторлардың репозиторийі (zcakhaa) кейінірек PyTorch портын қосты. Төмендегі код — біздің өзіміздің көрнекі PyTorch қайта іске асыруымыз, ресми емес. Ол мақаладан екі жолмен ауытқиды, оларды inline белгілейміз: ол inception max-pool жолын алып тастайды (төрттің орнына үш жол), және арна санын арттырады. Мақала конволюциялық блоктар бойында 16 фильтр және inception жолы бойынша 32 фильтр пайдаланады (LSTM кірісі 3×32=963 \times 32 = 96), бұл шамамен 60 мың параметрлі ықшам модель береді. Төмендегі үзінді 32 конв / 64 inception фильтрін пайдаланады (LSTM кірісі 192) — ішкі жағынан үйлесімді және іске қосуға болады, бірақ түпнұсқадан ауырырақ. Мақалаға сәйкес келу үшін конв арналарын 16-ға, inception арналарын 32-ге, ал input_size=96 етіп орнатыңыз.

import torch
import torch.nn as nn


class DeepLOB(nn.Module):
    """
    DeepLOB-style CNN-Inception-LSTM for limit order books.
    Reimplementation inspired by Zhang, Zohren, Roberts (2019),
    IEEE Transactions on Signal Processing, arXiv:1808.03668.

    NOTE: this is an illustrative reimplementation, NOT the official model.
    Differences from the paper:
      - inception has 3 paths here vs 4 in the paper (max-pool path omitted);
      - channel counts are scaled up (paper: 16 conv / 32 inception, input 96).

    Input shape: (batch_size, 1, T, 40)
        T = lookback window (e.g. 100)
        40 = 10 levels x 4 features (ask_price, ask_vol, bid_price, bid_vol)
    """

    def __init__(self, num_classes: int = 3, T: int = 100):
        super().__init__()
        self.num_classes = num_classes

        self.conv1 = nn.Sequential(
            nn.Conv2d(1, 32, kernel_size=(1, 2), stride=(1, 2)),
            nn.LeakyReLU(negative_slope=0.01),
            nn.BatchNorm2d(32),
            nn.Conv2d(32, 32, kernel_size=(4, 1), padding=(1, 0)),  # time -1
            nn.LeakyReLU(negative_slope=0.01),
            nn.BatchNorm2d(32),
            nn.Conv2d(32, 32, kernel_size=(4, 1), padding=(1, 0)),  # time -1
            nn.LeakyReLU(negative_slope=0.01),
            nn.BatchNorm2d(32),
        )

        self.conv2 = nn.Sequential(
            nn.Conv2d(32, 32, kernel_size=(1, 2), stride=(1, 2)),
            nn.LeakyReLU(negative_slope=0.01),
            nn.BatchNorm2d(32),
            nn.Conv2d(32, 32, kernel_size=(4, 1), padding=(1, 0)),  # time -1
            nn.LeakyReLU(negative_slope=0.01),
            nn.BatchNorm2d(32),
            nn.Conv2d(32, 32, kernel_size=(4, 1), padding=(1, 0)),  # time -1
            nn.LeakyReLU(negative_slope=0.01),
            nn.BatchNorm2d(32),
        )

        self.conv3 = nn.Sequential(
            nn.Conv2d(32, 32, kernel_size=(1, 10)),
            nn.LeakyReLU(negative_slope=0.01),
            nn.BatchNorm2d(32),
            nn.Conv2d(32, 32, kernel_size=(4, 1), padding=(1, 0)),  # time -1
            nn.LeakyReLU(negative_slope=0.01),
            nn.BatchNorm2d(32),
            nn.Conv2d(32, 32, kernel_size=(4, 1), padding=(1, 0)),  # time -1
            nn.LeakyReLU(negative_slope=0.01),
            nn.BatchNorm2d(32),
        )

        self.inp1 = nn.Sequential(
            nn.Conv2d(32, 64, kernel_size=(1, 1), padding=(0, 0)),
            nn.LeakyReLU(negative_slope=0.01),
            nn.BatchNorm2d(64),
        )
        self.inp2 = nn.Sequential(
            nn.Conv2d(32, 64, kernel_size=(1, 1), padding=(0, 0)),
            nn.LeakyReLU(negative_slope=0.01),
            nn.BatchNorm2d(64),
            nn.Conv2d(64, 64, kernel_size=(3, 1), padding=(1, 0)),
            nn.LeakyReLU(negative_slope=0.01),
            nn.BatchNorm2d(64),
        )
        self.inp3 = nn.Sequential(
            nn.Conv2d(32, 64, kernel_size=(1, 1), padding=(0, 0)),
            nn.LeakyReLU(negative_slope=0.01),
            nn.BatchNorm2d(64),
            nn.Conv2d(64, 64, kernel_size=(5, 1), padding=(2, 0)),
            nn.LeakyReLU(negative_slope=0.01),
            nn.BatchNorm2d(64),
        )

        self.lstm = nn.LSTM(
            input_size=192,  # 64 * 3 paths from the simplified inception
            hidden_size=64,
            num_layers=1,
            batch_first=True,
        )

        self.fc = nn.Linear(64, num_classes)

    def forward(self, x: torch.Tensor) -> torch.Tensor:
        """
        Args:
            x: Tensor of shape (batch, 1, T, 40)
        Returns:
            Tensor of shape (batch, num_classes)
        """
        h = self.conv1(x)   # (batch, 32, T-2, 20)
        h = self.conv2(h)   # (batch, 32, T-4, 10)
        h = self.conv3(h)   # (batch, 32, T-6, 1)   e.g. T=100 -> 94

        h_inp1 = self.inp1(h)  # (batch, 64, T-6, 1)
        h_inp2 = self.inp2(h)  # (batch, 64, T-6, 1)
        h_inp3 = self.inp3(h)  # (batch, 64, T-6, 1)
        h = torch.cat([h_inp1, h_inp2, h_inp3], dim=1)  # (batch, 192, T-6, 1)

        h = h.squeeze(-1)          # (batch, 192, T-6)
        h = h.permute(0, 2, 1)     # (batch, T-6, 192)

        h, _ = self.lstm(h)
        h = h[:, -1, :]  # take last hidden state

        out = self.fc(h)
        return out

Деректерді Алдын Ала Өңдеу

FI-2010 деректер жиыны z-score бойынша қалыпқа келтірілген түрде жеткізіледі. Тірі (live) тапсырыстар кітабы деректері үшін ұқсас түрде қалыпқа келтіру қажет:

import numpy as np
from torch.utils.data import Dataset


class LOBDataset(Dataset):
    """Dataset for limit order book snapshots."""

    def __init__(
        self,
        data: np.ndarray,
        labels: np.ndarray,
        T: int = 100,
    ):
        """
        Args:
            data: shape (num_snapshots, 40), raw LOB features
            labels: shape (num_snapshots,), class labels {0, 1, 2}
            T: lookback window length
        """
        self.data = data
        self.labels = labels
        self.T = T

        self.mean = data[:len(data) // 2].mean(axis=0)
        self.std = data[:len(data) // 2].std(axis=0)
        self.std[self.std == 0] = 1.0
        self.data = (self.data - self.mean) / self.std

    def __len__(self) -> int:
        return len(self.data) - self.T

    def __getitem__(self, idx: int):
        x = self.data[idx : idx + self.T].reshape(1, self.T, 40)
        y = self.labels[idx + self.T - 1]
        return torch.tensor(x, dtype=torch.float32), torch.tensor(
            y, dtype=torch.long
        )

Оқыту Циклі

def train_deeplob(
    model: DeepLOB,
    train_loader,
    val_loader,
    epochs: int = 50,
    lr: float = 0.01,
    device: str = "cuda",
):
    model = model.to(device)
    criterion = nn.CrossEntropyLoss()
    optimizer = torch.optim.Adam(model.parameters(), lr=lr, eps=1)

    best_val_f1 = 0.0
    for epoch in range(epochs):
        model.train()
        train_loss = 0.0
        for x_batch, y_batch in train_loader:
            x_batch = x_batch.to(device)
            y_batch = y_batch.to(device)

            optimizer.zero_grad()
            logits = model(x_batch)
            loss = criterion(logits, y_batch)
            loss.backward()
            optimizer.step()
            train_loss += loss.item()

        model.eval()
        all_preds, all_labels = [], []
        with torch.no_grad():
            for x_val, y_val in val_loader:
                x_val = x_val.to(device)
                preds = model(x_val).argmax(dim=1).cpu()
                all_preds.extend(preds.numpy())
                all_labels.extend(y_val.numpy())

        from sklearn.metrics import f1_score
        val_f1 = f1_score(all_labels, all_preds, average="weighted")

        print(
            f"Epoch {epoch+1}/{epochs} | "
            f"Train Loss: {train_loss/len(train_loader):.4f} | "
            f"Val F1: {val_f1:.4f}"
        )

        if val_f1 > best_val_f1:
            best_val_f1 = val_f1
            torch.save(model.state_dict(), "deeplob_best.pt")

Түпнұсқа мақаладан алынған негізгі оқыту гиперпараметрлері:

  • Оптимизатор: ϵ=1\epsilon = 1 бар Adam (әдеттен тыс үлкен — шулы қаржылық деректердегі жаңартуларды тұрақтандыруға көмектеседі)
  • Оқу жылдамдығы: 0.01
  • Пакет өлшемі: 32
  • Ретроспективті терезе: T=100T = 100 уақыт қадамы

Біз валидацияда дәлдіктің (accuracy) орнына өлшенген F1-ді қадағалаймыз, себебі үш класс теңгерімсіз — және келесі бөлім көрсеткендей, F1 — түпнұсқа мақала дәл осы себеппен баса көрсетілетін метрика.

DeepLOB Нені Қамту Үшін Құрылған

DeepLOB үйренетін микроқұрылым сигналдары: тапсырыстар ағынының теңгерімсіздігі, кезек динамикасы, және көлеммен өлшенген орта баға қысымы

DeepLOB-тың тартымды бір қыры — оның блоктары жоғарыдағы қолмен жасалған белгілермен қаншалықты тығыз негізделгені. Мұнда сақ болу керек: мақала мұны дизайн интуициясы ретінде ұсынады, оқытылған желінің дәлелденген қасиеттері ретінде емес. Ол фильтр визуализацияларын, активация-теңгерімсіздік корреляцияларын немесе LSTM неге назар аударатыны туралы талдауды жарияламайды. Сондықтан төмендегіні өлшенген нәтижелер емес, архитектуралық ниет ретінде оқыңыз.

Бірінші конволюциялық блок. 1×21 \times 2 фильтрлер әрбір деңгейде бағаны көлеммен жұптастырады. Құрылымдық тұрғыдан, бұл көлеммен өлшенген бағаны құрайтын операциямен бірдей — мақала бірінші қабатты оның белгі карталары микробаға тәрізді шаманы құрайтынын атап көрсету арқылы негіздейді. Желі сол отбасыдағы бір нәрсені қалпына келтіру үшін құрылған; біз оның қандай да бір нақты бағалаушыны дәлелді түрде қайта ашатынын мәлімдемейміз.

Екінші конволюциялық блок. Bid-ask жұптары бойынша жұмыс істей отырып, бұл фильтрлер бірнеше деңгейде теңгерімсіздікке ұқсас белгілерді үйренуге бағытталған — қайтадан, дәлелденген корреляциямен емес, құрылым бойынша.

Inception модулі. Көп масштабты уақыттық конволюциялар түрлі жиіліктердегі импульсті (momentum) қамтуға арналған: 1×11\times1 жол нүктелік-уақыттағы құрылымға жауап береді, 3×13\times1 жол қысқа мерзімді трендтерге, 5×15\times1 жол сәл ұзағырақ трендтерге, ал (толық модульде) max-pool жолы тегістелген көрініске.

LSTM қабаты. Қайталанатын компонент конволюциялар көрсете алмайтын алыс қашықтықтағы тәуелділіктердің жадын қосады — режим ауысулары мен тәулік уақыты әсерлері. Біз күштірек мәлімдемелерден аулақ боламыз (мысалы, LSTM тұрақсыз режимдерде соңғы деректерді қайта өлшейтін "бейімделгіш назар" (adaptive attention) енгізеді дегендей); мақала мұны көрсетпейді.

FI-2010 бойынша Өнімділік

Түпнұсқа мақала екі хаттаманы бағалайды. Setup 1 деректер жиынының ертерек нормализация бөлінуін пайдаланады; Setup 2 — көптеген кейінгі жұмыстар салыстыратын терең оқыту орнатуы. FI-2010 класс теңгерімсіз болғандықтан, мақала дәлдікті емес F1-ді баса көрсетеді, және нейрондық емес негіздер (SVM, MLP) үшін precision/recall негізіндегі сандарды хабарлайды. Міне, нақты Setup 2 сандары (F1, %):

Көкжиек (k) SVM MLP CNN-I LSTM DeepLOB
10 35.88 48.27 55.21 66.33 83.40
20 72.82
50 80.35

k=10k = 10 кезінде DeepLOB сонымен қатар 83.40 F1-мен қатар 84.47% дәлдікті хабарлайды. Setup 2 тек k{10,20,50}k \in \{10, 20, 50\} хабарлайды — мұнда k=100k = 100 жолы жоқ. (Setup 1 k{10,50,100}k \in \{10, 50, 100\} хабарлайды, сәйкесінше 77.66 / 74.96 / 76.58 DeepLOB F1 мәндерімен.) Жоғарыдағы сызықшалар мақаланың бұл хаттамада сол көкжиектерде кестелемейтін негіз ұяшықтарын белгілейді.

Бірнеше бақылау көзге түседі:

  1. DeepLOB қысқа көкжиекте негіздерден үлкен айырмашылықпен озады. k=10k = 10 кезінде оның F1 (83.40) LSTM (66.33), CNN-I (55.21), MLP (48.27) және SVM (35.88)-ден анағұрлым жоғары. Сапалық реттілік — қарапайым CNN, MLP және SVM-нен жоғары терең қайталанатын-конволюциялық модельдер — берік қорытынды болып табылады.
  2. Көкжиек тренді монотонды емес, "ұзағырақ оңайырақ" емес. Setup 2 бойынша, DeepLOB-тың F1-і kk 10205010 \to 20 \to 50 дейін жылжыған сайын 83.4072.8280.3583.40 \to 72.82 \to 80.35 болады — U-тәрізді үлгі, k=20k=20 ең қиыны, таза жоғары қарай жүру емес. Көкжиек "оңай" ма деген мәселе орнатуға, α\alpha шегіне, және белгі-тегістеу схемасына қатты байланысты; біз бұл сандардан әмбебап заң оқымауымыз керек.
  3. DeepLOB әр ұяшықта әрбір классикалық әдісті басып озбайды. C(TABL) сияқты мықты негіздерге қарсы кейбір көкжиектерде айырмашылықтар тарылады, сондықтан "барлық жерде барлық классикалық тәсілдерден асып түседі" деген мәлімдеме жағдайды асыра көрсетеді. Қорғауға болатын мәлімдеме — ол бәсекеге қабілеттіден ең жақсыға дейін, және қысқа көкжиекте анық ең жақсы.

Және тағы да: мақаланың өз көзқарасы бойынша FI-2010 мәселені шешу үшін тым кіші және тым дискретизацияланған. Оның күштірек дәлелі — DeepLOB акциялардың бір жиынында оқытылып, бұрын көрмеген акцияларда әлі де болжайтын LSE зерттеуі — FI-2010 көрсете алмайтын трансферлік оқыту нәтижесі.

LOBFrame және Қайта Жаңғырту Дағдарысы

Тапсырыстар кітабы терең оқытуының қайта жаңғырту дағдарысын көрсететін іріктеме ішіндегі (in-sample) және іріктемеден тыс (out-of-sample) ауытқитын қисықтар

LOBFrame эталондық жүйесі (Briola, Bartolucci, Aste, 2024) бұл нәтижелерге сергітетін толықтыру ұсынады. DeepLOB-тың архитектурасы дұрыс болғанымен, жүйе бірнеше маңызды ескертулерді атап көрсетеді:

Микроқұрылымға тәуелділік. Модель өнімділігі әртүрлі микроқұрылымдық сипаттамалары бар акциялар арасында айтарлықтай өзгереді. Өтімді, ірі-тикті акцияларды өтімсіз, кіші-тикті құралдарға қарағанда болжау оңайырақ. Бір акцияда мықты көрінетін модель басқасында айтарлықтай нашарлауы мүмкін.

Болжам мен пайда. Жоғары жіктеу дәлдігі автоматты түрде сауда пайдасына айналмайды. LOBFrame болжанған қозғалыстың bid-ask спрэдін жеңу үшін жеткілікті үлкен-үлкен еместігіне байланысты метрикаларды баса көрсетеді. Модель спрэдті жеңу үшін жеткілікті жиі, және жеткілікті үлкен қозғалыстарда дұрыс болуы керек — ал тар спрэдті акциялар үшін бұл межесі жоғары.

Белгіге сезімталдық. α\alpha шегі мен kk көкжиегін таңдау хабарланған дәлдікке де, болжамдардың практикалық құндылығына да айтарлықтай әсер етеді. Тым тар белгілер шулы мақсаттар туғызады; тым кең белгілер тривиалды түрде "дәл", бірақ пайдасыз болжамдар туғызады.

DeepLOB-тан Тыс: Қазіргі Ландшафт

Түпнұсқа DeepLOB моделінің айналасында айналатын заманауи тапсырыстар кітабы болжау тәсілдерінің шоғыры

DeepLOB жарияланғаннан бері бірнеше кеңейту пайда болды:

Лимиттік тапсырыстар кітаптары үшін трансформерлер (Wallbridge, 2020). Кейінгі әдебиетте жиі бос түрде "TransLOB" деп аталатын модель өзі маскаланған көп бас өзіндік назардан (self-attention) кейінгі себепті/дилатацияланған конволюциялық белгі алушы болып табылады — жай ғана LSTM Трансформерге ауыстырылған DeepLOB емес; ол inception+конв стегін қайта пайдаланбайды. Ол өз уақыты үшін FI-2010 бойынша жаңа заманауи деңгейді (state of the art) хабарлады.

Крипто-домен нұсқалары. Бірнеше топ DeepLOB стиліндегі архитектураларды тапсырыстар кітабы динамикасы акциялардан айтарлықтай ерекшеленетін криптовалюта нарықтарына қолданады — кеңірек спрэдтер, 24/7 сауда, және барлығы қайта оқытуды талап ететін басқа қатысушылар қоспасы.

Назармен күшейтілген нұсқалар. Бір жұмыс желісі inception және LSTM блоктары арасында көп бас назарды енгізеді, бұл желіге ағымдағы болжам үшін ең ақпараттық деңгейлерге немесе уақыт қадамдарына назар аударуға мүмкіндік береді.

LOB-Bench (Nagy, Frey, Li, Sarkar, Vyetrenko, Zohren, Calinescu, Foerster, 2025). Бұл эталон назарды болжамнан генерацияға аударады, тапсырыстар кітабы деректерінің генеративті модельдерінің қаншалықты шынайы екенін бағалайды — бағыттық болжамнан гөрі бэктестинг пен агентті оқытуға қатысты.

Өндіріс үшін Практикалық Ойлар

Егер сіз тірі (live) сауда жүйесінде DeepLOB стиліндегі модельді орналастыруды қарастырып жатсаңыз, бірнеше инженерлік мәселелер туындайды:

Кідіріс (Latency)

Модель сіздің сауда жүйеңіздің кідіріс бюджеті шеңберінде болжамдар шығаруы керек. Миллисекундтан аз кідірісте жұмыс істейтін HFT жүйелері үшін тіпті оңтайландырылған PyTorch қорытынды шығару да тым баяу болуы мүмкін. Опциялар мыналарды қамтиды:

  • TensorRT оңтайландыруымен ONNX экспорты
  • INT8-ге кванттау
  • Кідіріске ең сезімтал қолданбалар үшін FPGA орналастыру

Деректер Құбыры

Модель тұрақты жиілікте нормаланған, туралы тапсырыстар кітабы снапшоттарын күтеді. Тәжірибе жүзінде, LOB жаңартулары асинхронды түрде келеді. Сізге қажет:

  • Кітаптың ағымдағы күйін сақтайтын снапшот қайта құру қозғалтқышы
  • (T,40)(T, 40) кіріс тензорын шығаратын тұрақты жиіліктегі сэмплер
  • Жылжымалы статистиканы пайдаланатын онлайн нормализация

Белгінің Тұрақтылығы

Оқыту деректерінде есептелген z-score нормализация параметрлері уақыт өте келе ауытқиды. Бағалар өзгереді, құбылмалылық режимдері ауысады, нарық құрылымы дамиды. Өндірістік жүйеге мыналар қажет:

  • Жылжымалы нормализация терезелері (мысалы, статистиканы күн сайын қайта есептеу)
  • Модельді қайта оқытуды іске қосу үшін режимді анықтау
  • Кіріс үлестірімінің ауысуын бақылау

Микроқұрылымға Асыра Бейімделу (Overfitting)

LOB үлгілері алаңға (venue) және құралға тән. NASDAQ акцияларында оқытылған модель қайта оқытусыз Binance BTC/USDT-де жұмыс істемейді. Тіпті сол алаңның ішінде де, модельдер мыналарға асыра бейімделуі мүмкін:

  • Тик өлшемі режимі (ірі-тикті vs кіші-тикті акциялар)
  • Тәулік уақыты үлгілері (ашылу аукционы, түскі тыныштық, жабылу кросы)
  • Уақыт өте келе өзгеретін маркет-мейкер мінез-құлқы

Қорытынды

DeepLOB нарық микроқұрылымына терең оқытудың таза, жақсы негізделген қолданбасын білдіреді. Оның үш блокты архитектурасы — кеңістіктік белгілер үшін CNN, көп масштабты уақыттық үлгілер үшін inception, тізбектелген тәуелділіктер үшін LSTM — лимиттік тапсырыстар кітабы деректерінің құрылымына табиғи түрде сәйкес келеді.

Негізгі түсінік тек терең модель қолмен жасалған белгілерге сай келе алады немесе олардан асып түсе алады дегенде ғана емес, сонымен қатар архитектураның индуктивті бейімделулері — 1×21 \times 2 фильтрлер, inception параллелизмі, қайталанатын жад — тапсырыстар кітаптары қалай жұмыс істейтіні туралы шынайы домендік білімді кодтайтынында. Бұл қаржылық деректерге лақтырылған жалпы терең желі емес; бұл лимиттік тапсырыстар кітабының нақты геометриясы айналасында жобаланған архитектура. Және оның ең сенімді дәлелі авторлардың өздері сенбейтін FI-2010 рейтингі емес, LSE деректерінің бір жылы бойынша трансферлік оқыту нәтижесі.

Практиктер үшін DeepLOB мықты негіз және пайдалы құрылыс блогы болып табылады. Зерттеушілер үшін ол құрылымдалған қаржылық деректердегі өнімділікті тек модель ауқымы емес, ойлы архитектура дизайны айдайтынын көрсетеді. Тек нақты сандарды келтіруді, белгі схемасын бақылауды, және жіктеу дәлдігін сауда пайдасынан әлі де алшақ нәрсе ретінде қарастыруды ұмытпаңыз.


Сілтемелер

  1. Zhang, Z., Zohren, S., & Roberts, S. (2019). DeepLOB: Deep Convolutional Neural Networks for Limit Order Books. IEEE Transactions on Signal Processing, 67(11), 3001-3012. arXiv:1808.03668

  2. Ntakaris, A., Magris, M., Kanniainen, J., Gabbouj, M., & Iosifidis, A. (2018). Benchmark Dataset for Mid-Price Forecasting of Limit Order Book Data with Machine Learning Methods. Journal of Forecasting, 37(8), 852-866. arXiv:1705.03233

  3. Briola, A., Bartolucci, S., & Aste, T. (2024). Deep Limit Order Book Forecasting (LOBFrame). arXiv:2403.09267

  4. Wallbridge, J. (2020). Transformers for Limit Order Books. arXiv:2003.00130

  5. Cont, R., Kukanov, A., & Stoikov, S. (2014). The Price Impact of Order Book Events. Journal of Financial Econometrics, 12(1), 47-88.

  6. Stoikov, S. (2018). The Micro-Price: A High-Frequency Estimator of Future Prices. Quantitative Finance, 18(12), 1959-1966.

  7. Nagy, P., Frey, S., Li, K., Sarkar, B., Vyetrenko, S., Zohren, S., Calinescu, A., & Foerster, J. (2025). LOB-Bench: Benchmarking Generative AI for Finance — an Application to Limit Order Book Data. ICML 2025. arXiv:2502.09172

  8. DeepLOB code (original in Keras/TensorFlow; the repository also provides a PyTorch port): github.com/zcakhaa/DeepLOB-Deep-Convolutional-Neural-Networks-for-Limit-Order-Books

blog.disclaimer

Authors

Eugen Soloviov
Eugen Soloviov

Trading-systems engineer

Trading-systems engineer building bots since 2017: cross-exchange arbitrage (connected up to 30 venues), cointegration-based pairs arbitrage across spot and futures, scalping, news and sentiment-driven strategies, trend algorithms, and portfolio management and balancing algorithms. Also builds sub-millisecond order execution, big-data warehouses, backtesting engines, AI agents, and trading interfaces (incl. open-source profitmaker.cc). Stack: JS/TS, Python, Rust/Zig/Go, DevOps, backend, frontend, architecture.

Newsletter

Нарықтан бір қадам алда болыңыз

AI сауда талдаулары, нарық аналитикасы және платформа жаңалықтары үшін біздің ақпараттық бюллетеньге жазылыңыз.

Біз сіздің жекелігіңізді құрметтейміз. Кез келген уақытта жазылымнан шығуға болады.