Irregular Time in Tick Models: Continuous-Time Encodings vs. Plain Positional Embeddings
Убакыт барлары окуялардын убактысын жок кылган ыктыярдуу кысуу болуп саналат, ошондуктан барлардын чек арасын активдүүлүк аныкташы керек. Бул жүйө 17 бар түрү жана иштеген генераторлору менен Алгоритмдик соода үчүн бар түрлөрү жана агрегация ыкмалары макаласында толук берилген. Бул макала ошол жерден кийинки кадамдан, эч ким чече элек бөлүктөн башталат: тик, көлөм же дисбаланс барларына өткөндөн кийин да, аларды кабыл алган модель аралыкты бир калыпта деп эсептейт. Үйрөтүлүүчү позициялык эмбеддинги бар nn.TransformerEncoder 7-позицияны "жетинчи орун" деп кабыл алат; ал тик 6-позициядан 200 микросекунддан кийин келсе да, 40 секунддан кийин келсе да айырмасы жок. Активдүүлүк барлары сакташы керек болгон окуялар аралык убакыт кириш катмарында кайрадан жоголот.
Демек, бул макаланын суроосу тар жана текшерүүгө болот: тизмектүү моделге тиктин чындыгында качан болгонун кантип көрсөтүү керек жана татаал жооп жөнөкөй жооптон ашып түшөбү?
Керектүү баштапкы билим

Төмөнкүлөрдүн баары ушул блогдо мурда камтылган өбөлгөлөр; бул жерде алардын эч бири кайра чыгарылбайт:
- Микротүзүлүштөгү ызы-чуу жана bid-ask секириги. Roll'дун жашыруун спред модели тиктик кирешелердеги терс сериялык ковариацияны баа бирдиктеринде биринчи принциптерден чыгарат; кеңири тараган ишке ашыруу катасы да көрсөтүлгөн: ML менен bid-ask спредин моделдөө.
- Ордер китебинин белгилери. Китеп дисбалансы, салмакталган орто баа, 1-5 деңгээлдердеги тереңдик катышы, китеп басымы жана спред/тик катышы ошол эле макалада таблицага түшүрүлгөн; OBI жана көлөм менен салмакталган орто баанын чыгарылыштары — салмакталган орто баа Stoikov'дун микробаасы эмес деген эскертүү менен — DeepLOB: Лимиттик ордер китептерин терең үйрөнүү макаласында берилген.
- Ордер агымы жана соода интенсивдүүлүгү. Соода дисбалансы, VPIN жана Kyle'дын лямбдасы спредди моделдөө макаласында; ордерлер аралык интервал жана Hawkes'тин өзүн-өзү козгоочу интенсивдүүлүгү убакыт белгилери катары Санариптик из: трейдерди аныктоо макаласында бар. Бул нобай башында сунуштаган жөнөкөй
1/dtинтенсивдүүлүгү ал жактагы Hawkes формулировкасынын алсызыраак түрү. - Күндүн ичиндеги стационардык эместик. Көлөмдүн U сымал үлгүсү, тынч мезгилдерде спреддин кеңейиши жана сутка убактысынын sin/cos коддолушу спредди моделдөөдө рынок режими белгилери катары берилген.
- Маркалар. Эки тегиздөө келишими (келечектеги орточо менен учурдагы баа, келечектеги орточо менен мурунку орточо), босогосу бар үч класстуу дискреттештирүү жана LOBFrame'дин марканын жана параметрлерине сезимталдыгы тууралуу эскертүүсү DeepLOB макаласында бар.
- Класстардын тең салмаксыздыгы. Өлүк зона болгондо FLAT классы басымдуулук кылат, ошондуктан отчет берилчү метрика тактык эмес, F1 — ошол эле макаладагыдай.
- Барды толтуруу узактыгы. Көлөм бары толгонго кеткен дубал саатынын убактысы тик модели үчүн колдонулуучу белги; аны чыгарган генераторлор Бар түрлөрү жана агрегация ыкмалары макаласында берилген.
Баштапкы нобайдын катасынан улам бир нерсени ачык айтуу керек: багыттык тактыктын 50,0%дан 50,5%га өсүшү өзүнөн-өзү пайдалуу дегенди билдирбейт. DeepLOB макаласында талкууланган LOBFrame'дин негизги ою — болжолдонгон кыймыл спредден өтүүгө жетишерлик чоң болушу керек, ошондо гана тактык мааниге ээ болот; бул блогдогу чынчыл терс натыйжа тескерисинче жоромол кылганда эмне болорун көрсөтөт.
Базалык модель

Базалык коддоочу катары DeepLOB стилиндеги CNN-Inception-LSTMди кабыл алалы; архитектура, текшерилген FI-2010 Setup 2 сандары ( болгондо F1 83,40 / тактык 84,47), LOBFrame эскертүүлөрү жана иштеген PyTorch кайра ишке ашыруусу DeepLOB: Лимиттик ордер китептерин терең үйрөнүү макаласында бар. Төмөндө бул коддоочу өзгөрбөйт — суроо анын кириш өкүлчүлүгүнө эмне кошулары жөнүндө.
Бир калыпта эмес убакытты коддоонун үч жолу

A варианты: delta_t жөнөкөй белги катары
Эң жөнөкөй жооп. OFI жана китеп дисбалансы менен катар feature векторуна маанисин (лог-түрдө өзгөртүлгөн, z-стандартташтырылган) дагы бир тилке катары кошуп, стандарттуу үйрөтүлүүчү позициялык эмбеддингди калтырыңыз. Эч кандай чыгымсыз бир кириш өлчөмүн кошот жана өндүрүштөгү тик моделдердин көбү иш жүзүндө ушундай кылат.
Бул — бардык кооз сунуштар жеңиши керек болгон вариант жана татаал альтернативаларды сунуштаган макалаларда калтырылып кеткен вариант.
B варианты: үзгүлтүксүз убакыттын позициялык коддолушу
Дискреттүү позициялык эмбеддингди үйрөтүлүүчү убакыт масштабдарындагы өткөн убакыттын синусоидалык функциясы менен алмаштырыңыз:
мында — микросекунддан секундга чейинки аралыкта логарифм боюнча жайгаштырылып баштапкы маани берилген үйрөтүлүүчү убакыт масштабы параметрлери. Максат — attention окуяларды орун индекси боюнча эмес, убакыттык маанилүүлүгү боюнча салмактай алышы: 200 микросекунд мурдагы чоң соодага 50 миллисекунд мурдагы кичине соодадан башкача жетүү мүмкүн болушу керек.
Үйрөтүлүүчү бөлүк — кызыктуу бөлүк. Эгер убакыт масштабдарын 1 микросекунддан 10 секундга чейин логарифм боюнча жайгаштырып баштапкы маани берип, үйрөтсөңүз, масштабдардын кайда жайгашканынын өзү өлчөм: эгер алар миллисекунддар тарабына жыйналса, модель бир нече миллисекунддан кийинкинин баары бири-бирин алмаштыра алат деп айтып жатат. Бул архитектура тууралуу эмес, рынок тууралуу жыйынтык.
import numpy as np
import torch
import torch.nn as nn
class ContinuousTimeEncoding(nn.Module):
"""Sinusoidal encoding for irregular inter-arrival times."""
def __init__(self, d_model: int, num_timescales: int = 64):
super().__init__()
log_timescales = torch.linspace(
np.log(1e-6), np.log(10.0), num_timescales
)
self.log_timescales = nn.Parameter(log_timescales)
self.proj = nn.Linear(num_timescales * 2, d_model)
def forward(self, delta_t: torch.Tensor) -> torch.Tensor:
"""
Args:
delta_t: (batch, seq_len) inter-arrival times in seconds
Returns:
(batch, seq_len, d_model) time encoding
"""
timescales = torch.exp(self.log_timescales) # (num_timescales,)
scaled = delta_t.unsqueeze(-1) / timescales.unsqueeze(0).unsqueeze(0)
encoding = torch.cat([torch.sin(scaled), torch.cos(scaled)], dim=-1)
return self.proj(encoding)
Кадимки коддоочуга киргизилгенде, ал так бир сапты — позициялык эмбеддингди кошууну — алмаштырат:
class TickTransformer(nn.Module):
def __init__(self, input_dim: int, d_model: int = 128,
nhead: int = 8, num_layers: int = 4, num_classes: int = 3):
super().__init__()
self.feature_proj = nn.Linear(input_dim, d_model)
self.time_encoding = ContinuousTimeEncoding(d_model)
encoder_layer = nn.TransformerEncoderLayer(
d_model=d_model, nhead=nhead,
dim_feedforward=d_model * 4,
dropout=0.1, batch_first=True
)
self.encoder = nn.TransformerEncoder(
encoder_layer, num_layers=num_layers
)
self.head = nn.Linear(d_model, num_classes)
def forward(self, features: torch.Tensor,
delta_t: torch.Tensor) -> torch.Tensor:
h = self.feature_proj(features) + self.time_encoding(delta_t)
h = self.encoder(h)
return self.head(h[:, -1, :])
Коддоочунун негизги шаблону жаңы эмес — ошол эле nn.TransformerEncoderLayer каркасы спредди моделдөө макаласында 2-архитектура катары жарыяланган. Жаңылык бул жерде ContinuousTimeEncoding жана үйрөтүлүүчү убакыт масштабдары тууралуу жүйөдө гана.
C варианты: тиктердин ортосундагы үзгүлтүксүз жашыруун абал (ODE-RNN)
Эң принциптүү вариант жашыруун абалды Neural ODE аркылуу моделденген үзгүлтүксүз убакыт процесси катары карайт (Chen жана башкалар, 2018). Тиктердин ортосунда жашыруун абал үйрөтүлүүчү дифференциалдык теңдемеге ылайык өзгөрөт:
Тик келгенде абал байкоо менен жаңыланат:
Бул — ODE-RNN каркасы. Ал бир калыпта эмес аралыкты кириш белгиси катары эмес, түзүлүштүк түрдө иштетет: чечүүчү система окуялардын ортосунда так убакытка интегралдайт, толтуруусуз, интерполяциясыз жана маалыматты жоготкон кайра үлгүлөө кадамысыз.
Баасы — эсептөө татаалдыгы. ODE чечкичтери ырааттуу жана параллелдештирүү кыйын, ошондуктан бул latency бюджетинен өтүп кетиши эң мүмкүн болгон вариант — мындай дооматтарды жарыялоодон мурун кантип өлчөө керектигин IPC салыгы жана бэктест кыймылдаткычынын ылдамдык тепкичи материалдарындагы latency тартибинен көрүңүз. Бул жерде ал жайылтуу үчүн талапкер катары эмес, убакытты ачык моделдөө бере турган нерсенин жогорку чеги катары киргизилди.
Окуя салмагы бар attention

Экинчи, ортогоналдык идея: бардык тиктер бирдей маалыматтуу эмес. Bidдеги 100 акциялык соода — кадимки көрүнүш. Үч баа деңгээлин шыпырып өткөн соода — режимдин өзгөрүшү. Бул априордук маалыматты түздөн-түз attention-ге киргизе алабыз. Окуянын маанилүүлүк упайын аныктайлы:
мында — сооданын көлөмү, — баанын өзгөрүшү, — акыркы волатилдүүлүк, ал эми бир нече деңгээлдүү шыпырууну белгилейт. Аны softmax алдында attention логиттерине кошуңуз:
мында . Модель каалаган attention үлгүлөрүн үйрөнүү жөндөмүн сактайт, бирок башында рынокту жылдырган соодаларга көбүрөөк басым жасайт.
Бул ойлоп табылган формула. Функционалдык түрү да, үч мүчөнүн тандалышы да, softplus да — болжолдор; бул жерде мындай ыктоо кубаттуулукту гана коротпостон, чындап жардам берерин көрсөткөн эч нерсе жок.
Көп горизонттуу баштар

Ар башка горизонттор ар башка чечимдерге маалымат берет, бир нече горизонт чыгышы бар жалпы коддоочу ар бир горизонт үчүн өзүнчө моделдерден жакшы, ал эми биргелешкен loss регуляризациялайт — бул жүйө, ошондой эле квантилдик чыгыштар жана интерпретациялануучулук Соода үчүн Temporal Fusion Transformer макаласында берилген. Тикке тиешелүү жалгыз бөлүк — горизонттордун топтому: күндөр эмес, 1, 10, 50 жана 100 окуя. Демек, дүрбөлөң учурунда горизонттор дубал сааты боюнча катуу кабатташат, ал эми тынч учурда дээрлик кабатташпайт — күндүк горизонт адабиятында кездешпеген татаалдык.
Purging окуялар менен өлчөнүшү керек

Purged walk-forward валидациясы Walk-Forward Optimization материалында башынан аягына чейин камтылган (anchored, rolling, combinatorial purged CV, WFER, degradation rate), ал эми ачык purge жана embargo аралыгы бар иштеген purged_walk_forward() спредди моделдөө материалында берилген. Look-ahead bias таксономиясы мындай агып кетүүлөрдүн отчеттогу Sharpe-ге эмне кыларын сандык баалайт.
Тик маалыматтарына мүнөздүү нерсе: миллисекунддар менен ажыратылган коңшу тиктер дээрлик бирдей, ошондуктан күндөр менен өлчөнгөн purge аралыгы бир секундга 500 окшош үлгү баткан дүрбөлөңдө маанисиз. Аралык окуялар менен өлчөнүшү керек, ал эми туура өлчөм — кагаздан көчүрүлө турган туруктуу сан эмес, инструментиңиздин дүрбөлөң түзүлүшү тууралуу эмпирикалык суроо.
Бул дооматты текшерүү арзан — окуялардагы purge аралыгын өзгөртүп, валидациялык F1ди ага каршы чийиңиз. Эгер аралык кеңейгенде валидациялык F1 төмөндөп, андан кийин тегизделсе, тегизделген чекит сиздин аралык; эгер ал эч качан төмөндөбөсө, коңшу тиктердин агып кетиши көйгөй деп жаңылгансыз.
Муну чечүүчү эксперимент

Жогорудагылардын баары архитектура. Алардын бири да далил эмес. Төмөнкү иштетүүлөр аткарылмайынча макала бул блогдун талабынан өтпөйт:
Баптоо. Бир маалымат топтомун (BTC/USDT соодасы — негизги маалымат топтому), бир коддоочуну, бир марка аныктамасын жана бир purged split'ти бекитиңиз. Так бир нерсени гана өзгөртүңүз.
Үч вариант.
| Вариант | Убакыт маалыматы | Позициялык коддолушу |
|---|---|---|
| A | чийки кириш белгиси катары | жөнөкөй үйрөтүлүүчү позициялык эмбеддинг |
| B | коддолуштан тышкары убакыт маалыматы жок | ContinuousTimeEncoding (үйрөтүлүүчү убакыт масштабдары) |
| C | белги жана үзгүлтүксүз убакыт коддолушу катары | ContinuousTimeEncoding |
Эмне тууралуу отчет берүү керек.
- Ар бир класс үчүн F1, тактык эмес — dead-zone маркасында FLAT классы басымдуу, ал эми тактык DeepLOB макаласындагы себептен маалыматсыз.
- Ишеним аралыгы, ар башка seed менен кайталанган иштетүүлөрдөн алынган. Варианттар ортосундагы 0,4 пункттук F1 айырмасы бирисиз эч нерсени билдирбейт.
- Үйрөтүлгөн убакыт масштабдары. Үйрөтүүдөн кийин
torch.exp(model.time_encoding.log_timescales)маанисин басып чыгарыңыз. Алардын кайда токтогону — эксперименттеги эң кызыктуу сан, аны алуу үчүн бир сап жетиштүү. - Ар бир варианттын аппараттык каражаттары жана дубал сааты боюнча баасы, IPC салыгы стилинде — өлчөнгөн, жарыяланган аппаратта, N боюнча медиана. Эгер B вариантынын inference убактысы Aдан 3 эсе көп болуп, F1дин бир бөлүгүн гана берсе, жооп ошол.
Терс натыйжа болсо, аны да отчет кылыңыз. "30 күндүк BTC тиктеринде үзгүлтүксүз убакыт коддолушу ни белги катары берүүдөн артык эч нерсе бербейт" — эч ким өлчөбөгөн үч архитектуранын баяндамасынан пайдалуураак пост. Бул блогдогу кылдат курулган edge-дер чынчыл валидацияда жок болуп кетүүгө жакын деген жалпы жыйынтыкка да туура келет.
Бул кайсы деңгээлде турат

Ачык калган суроо чыныгы: бирдей эмес аралыктагы окуялар берилген тизмектүү моделдер убакыттын ордуна позицияны коддойт, ал эми блогдун учурдагы камтуусу — спредди моделдөөдөгү Transformer коддоочусун кошкондо — жөнөкөй үйрөтүлүүчү позициялык эмбеддингди колдонот. Үзгүлтүксүз убакыт коддолушу, ODE-RNN жашыруун абалы жана окуя салмагы бар attention — муну оңдоонун үч жолу.
Жетишпегени — муну оңдоонун маанилүү экенине далил. Үчөөнүн баары азырынча табылга эмес, тема гана. Чечүүчү өлчөм — туруктуу коддоочу жана туруктуу purged split менен үч варианттуу ablation; анда класстар боюнча F1, ишеним аралыгы жана үйрөтүлгөн убакыт масштабдары отчеттолушу керек — ал азырынча жүргүзүлө элек.
Authors
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.