Multi-Task Learning for Simultaneous Price, Volume, and Volatility Prediction
Көптапсырмалы оқыту (MTL) әдетте мынадай тұжырыммен ұсынылады: өзара байланысты мақсаттар үшін бір кодерді бөліссеңіз, негізгі тапсырманың нәтижесі жақсарады. Саудада өзара байланысты мақсаттар анық — кірістілік, көлем және іске асқан құбылмалылықтың бәрі бір order flow-дан шығады — бірақ бұл тұжырым дерлік ешқашан тексерілмейді. Қызықты сұрақ тапсырмалардың өзара байланысты-болмағаны емес. Мәселе ортақ градиенттердің келісуінде және олар келіспейтін fold-тарда не болатынында.
Бұл мақала MTL туралы жазбалардың көпшілігі ескертпе ретінде ғана қарастыратын екі нәрсені ортаға қояды:
- Loss balancing — егжей-тегжей емес, эксперимент. Fixed weights, Kendall uncertainty weighting және GradNorm — үш түрлі model. Үшеуін бірдей fold-тарда іске қосып, әрқайсысы үшін learned weights-ті primary-task metric-пен бірге хабарлаңыз.
- Negative transfer-ді metric-ті көрмей тұрып өлшеуге болады. Shared encoder-дегі task gradient-терінің cosine similarity-і training кезінде auxiliary task-тер representation-ды primary task қажет ететін бағыттан алыстатып жатқанын көрсетеді. Cosine таңбасын жазып алып, оның сол fold-тағы нәтижені болжағанын тексеріңіз.
Pipeline-ның қалған бөлігі — volatility process, training loop, leakage controls және validation protocol — блогтың басқа материалдарында қамтылған, сондықтан мұнда қайта шығарылмай, сілтеме арқылы берілген.
Баптау

Input features (OHLCV, technical indicators, order flow) берілсін, үш target бар:
- Task 1 (primary): келесі period return
- Task 2 (auxiliary): келесі period log volume
- Task 3 (auxiliary): келесі period realized volatility
Multi-task model үшеуін бір уақытта шығарады, , ал multi-task risk әр task risk-інің weighted sum-ы болады:
Мақаланың негізгі тақырыбы — және әр task-тің gradient-тері бір-біріне қалай әсер ететіні.
Бірлескен training неге көмектесуі мүмкін — бір абзацта. Auxiliary task-тер shared representation-ды бірнеше нарықтық құбылысты түсіндіруге мәжбүрлейді, бұл бір мезетте capacity control да, inductive bias та болады; volume мен volatility тікелей бақыланатын, ал "expected return" бақыланбайтындықтан, auxiliary head-тер primary head-ке қарағанда тазарақ gradient signal береді. Бір model-дің көп output шығаруының пайдасы — interpretability machinery-мен бірге — көп горизонтты болжауға арналған temporal fusion transformer-лер материалында егжей-тегжейлі талқыланған; ол multi-horizon quantile-дері үшін дәл осы shared encoder және көп head идеясын қолданады.
Архитектураға қысқаша шолу
Hard parameter sharing: shared encoder task-specific head -ті қоректендіреді, сондықтан . Бұл жерде өлшенетін нұсқа осы, өйткені дәл осы нұсқада бойынша gradient conflict анық мағынаға ие.
Soft parameter sharing әр task-ке coupling penalty-і бар жеке encoder береді — parameter көбірек, икемділік жоғарырақ, бірақ conflict өлшенетін бір shared parameter vector жоқ. Cross-stitch networks осы екі тәсілдің арасында тұрады: әр level-де learned matrix арқылы task-specific feature-лерді араластырады. Hard sharing conflict көрсетсе, екеуін де сынап көруге болады, бірақ төмендегі measurement scope-ына екеуі де кірмейді.
Маңызды эксперимент: loss balancing-тің үш схемасы

Naive loss scale-ға сезімтал. Return loss шамамен , ал volume loss шамамен болса, gradient-ті volume иеленеді де, return head gradient signal-сыз қалады. Үш жауап бар:
Fixed weights. Әр target-ты standardize еткеннен кейін деп қойыңыз. Бұл — адал baseline: егер ол жеңсе, adaptive scheme-дер тек рәсім болып шығады.
Uncertainty weighting (Kendall et al., 2018). Әр task үшін homoscedastic noise scale -ті үйреніңіз:
Uncertainty-і жоғары task-тер автоматты түрде төмен weight алады; мүшесі тривиалды шешіміне жол бермейді. Бұл predictive interval емес, training кезіндегі loss-weighting құралы екенін ескеріңіз — position size есептеуге болатын uncertainty үшін conformal prediction материалын қараңыз.
GradNorm (Chen et al., 2018). Loss scale-дерін емес, gradient magnitude-терін теңестіріңіз. Әр қадамда және орташа мәнін, relative training rate мәнін есептеп, жаңартуын жасаңыз. Сонда loss scale-іне қарамастан барлық task салыстырмалы жылдамдықпен training-нен өтеді.
MTL-ге тән code — head-тер, list қайтаратын forward және loss aggregation. Linear/BatchNorm/ReLU/Dropout stack-і, Adam/cosine/clip boilerplate-і және epoch loop-ы DeepLOB материалында көрсетілген стандартты pattern, сондықтан мұнда қысқартылды.
import torch
import torch.nn as nn
class MultiTaskTradingModel(nn.Module):
"""Hard parameter sharing: one encoder, K heads."""
def __init__(self, encoder: nn.Module, repr_dim: int, n_tasks: int = 3):
super().__init__()
self.shared_encoder = encoder # any MLP/CNN/GRU trunk
self.task_heads = nn.ModuleList(
nn.Linear(repr_dim, 1) for _ in range(n_tasks)
)
def forward(self, x):
h = self.shared_encoder(x)
return [head(h).squeeze(-1) for head in self.task_heads]
def shared_repr(self, x):
return self.shared_encoder(x)
class UncertaintyWeightedLoss(nn.Module):
"""Kendall et al. (2018) homoscedastic weighting."""
def __init__(self, n_tasks: int = 3):
super().__init__()
self.log_vars = nn.Parameter(torch.zeros(n_tasks)) # log(sigma^2)
def forward(self, losses: list) -> torch.Tensor:
return sum(
torch.exp(-self.log_vars[i]) * loss + self.log_vars[i]
for i, loss in enumerate(losses)
)
def get_weights(self) -> list:
with torch.no_grad():
return [torch.exp(-lv).item() for lv in self.log_vars]
UncertaintyWeightedLoss parameter-лерге ие, сондықтан ол model-мен бірге optimizer-ге қосылуы керек: optim.Adam(list(model.parameters()) + list(uw.parameters()), ...). Мұны ұмыту — "uncertainty weighting іске қосылды" деп ойлап, іс жүзінде fixed weights-ті үнсіз іске қосудың ең жиі кездесетін жолы.
Нені хабарлау керек
Әр scheme үшін, әр fold-та: learned final task weights, primary-task metric және weighting scheme model choice болғандықтан, біреуін таңдағанға дейін қанша scheme салыстырылғаны.
| Схема | Single-task-пен салыстырғандағы primary-task metric | |||
|---|---|---|---|---|
| Fixed () | 1.00 | 1.00 | 1.00 | — |
| Uncertainty weighting | — | — | — | — |
| GradNorm | — | — | — | — |
Үш scheme-ді бірнеше fold-та сынау — шағын model search-тің өзі. Мұнда хабарланған кез келген improvement ештеңе білдірмес бұрын deflated Sharpe және multiple testing материалында сипатталған multiple-testing correction-нан өтуі керек.
Теріс тасымал: градиент таңбасын белгілеу

Сақтауға тұрарлық бөлік осы. Negative transfer — auxiliary task-тер primary task нәтижесін нашарлататын жағдай, оның тікелей диагностикасы бар: shared parameter space ішіндегі task gradient-тері арасындағы бұрыш.
Өлшемді тек shared encoder-де жасаңыз — head-тер құрылымы бойынша task-specific және сондықтан әрқашан тривиалды түрде "келіседі".
import torch.nn.functional as F
def shared_grad(model, x, y, task_idx, criterion=nn.MSELoss()):
"""Gradient of task `task_idx` w.r.t. the shared encoder, flattened."""
model.zero_grad(set_to_none=True)
loss = criterion(model(x)[task_idx], y)
loss.backward()
return torch.cat([
p.grad.detach().flatten()
for p in model.shared_encoder.parameters()
if p.grad is not None
])
def task_conflict(model, x, y_by_task, task_names):
"""Pairwise cosine similarity between per-task shared-encoder gradients."""
grads = {
name: shared_grad(model, x, y_by_task[name], i)
for i, name in enumerate(task_names)
}
return {
(a, b): F.cosine_similarity(
grads[a].unsqueeze(0), grads[b].unsqueeze(0)
).item()
for i, a in enumerate(task_names)
for b in task_names[i + 1:]
}
Мұны training соңында бір рет емес, training кезінде fixed cadence бойынша held-out batch-та есептеңіз. Encoder маманданған сайын жұп бастапқыда aligned болып, кейін diverge етуі мүмкін; training соңындағы жалғыз сан мұны жасырады.
Ізделетін және кез келген нәтиже жағдайында жарияланатын finding:
| Жұп | cos sim, ерте training | cos sim, кеш training | MTL primary task-ке көмектесті ме? |
|---|---|---|---|
| return ↔ volume | — | — | — |
| return ↔ volatility | — | — | — |
| volume ↔ volatility | — | — | — |
Егер volume және volatility gradient-тері өзара келісіп, екеуі де return gradient-іне қайшы келсе, дұрыс қорытынды — екі auxiliary task return task кірмейтін coherent block құрайды; шешім capacity-ді ұлғайту емес, task grouping болады. Conflict нақты болса, стандартты remedy-лер: PCGrad (Yu et al., 2020), ол қайшылықты gradient-ті екіншісінің normal plane-іне project етеді; CAGrad (Liu et al., 2021), ол ешбір task-ке зиян келтірмейтін descent direction іздейді; немесе auxiliary task-ті толық алып тастау.
Әдейі жоқ нәрсеге назар аударыңыз: target value бойынша боялған shared representation-ның t-SNE plot-ы. Ол тек сәндік — жоғарыдағы cosine сандары embedding нені меңзейтін болса, соның бәрін сан ретінде айтып тұр.
Валидация протоколы

Жоғарыдағы measurement салақ protocol жағдайында түкке тұрмайды, ал MTL әдеттегі қателерді күшейтеді, өйткені бір target орнына leakage-ке ұшырайтын үшеуі бар.
Simulator емес, real data. Target-тер нақты OHLCV/trade data-дан алынуы керек. Hardcoded GARCH toy return-мен құрылымы бойынша корреляцияланған volatility жасайды, ал бұл дәл тексеріліп отырған нәрсе — experiment өз generator-ін өлшейтін болады. Fitted volatility process қажет болса, crypto үшін GARCH volatility forecasting real BTC/ETH-те maximum likelihood арқылы GARCH(1,1)-ді fit жасап, standardized residual-дерді тексереді, ал asymmetric GARCH және leverage effect Gaussian symmetric-response simulator-дің crypto volatility-ді неге бұрмалайтынын түсіндіреді. Synthetic data controlled ground truth бергенде ғана орынды — яғни қалпына келтіргіңіз келетін, автор алдын ала орнатқан белгілі task correlation болғанда; бұл мұндағы experiment-тен бөлек.
Scalers тек train-ге fit етіледі. Feature scaler-ді және үш target scaler-дің бәрін әр training fold ішінде fit жасап, validation-ға қолданыңыз; split-ке дейін жасалған global fit_transform test-set moments-ін training-ге leakage етеді. Бұл нақты қате look-ahead bias taxonomy материалында сипатталған.
Purged, embargo-сы бар walk-forward fold-тар. Бір 80/20 chronological split MTL improvement-ін fold effect-тен ажырата алмайды — walk-forward optimization дәл осыны талдап, үш split үш түрлі conclusion беретінін көрсетеді. Machine learning арқылы spread modeling материалындағы expanding-window purged_walk_forward generator-ін қайта пайдаланыңыз: ол әр boundary-дің екі жағынан horizon жолдық gap алып тастайды, бұл жерде маңызды, өйткені overlapping realized-volatility window-лері return target leakage жасамаса да boundary арқылы leakage жасайды.
Classical baseline. Үш single-task net-тен жақсы MTL net per-target gradient-boosting немесе ridge model-і төрт модельдің бәрін жеңсе, ештеңе дәлелдемейді. Сол fold-тар мен сол feature-лерде әр target үшін LightGBM немесе ridge арқылы жеке model fit жасап, оны сол table-де хабарлаңыз.
| Үлгі | Primary-task metric | Ескертпелер |
|---|---|---|
| Ridge, per target | — | Классикалық baseline |
| LightGBM, per target | — | Классикалық baseline |
| Single-task MLP, per target | — | Үш бөлек net |
| MTL, best loss scheme | — | Бір net, үш head |
Бұл жерде MTL қашан ақталады

MTL жоғарыдағы fold-тарда checklist ретінде емес, тексерілетін hypothesis ретінде жеңуі тиіс жағдайлар:
- Auxiliary label-дер primary label-ден таза. Volume тікелей бақыланады, ал "expected return" бақыланбайды. Return head негізінен noise-ты fit жасап жатса, auxiliary head-терден келетін gradient signal objective-тің дұрыс қойылған жалғыз бөлігі болады.
- Training data encoder capacity-іне қарағанда аз, сондықтан auxiliary constraint parameter үшін жай бәсекелеспей, шынайы regularization жасайды.
- Inference latency маңызды және бір forward pass үшеуінен жылдам.
Қарсы жағдай да дәл сондай тексеріледі: өлшенген cos_sim(return, ·) мәндері тұрақты түрде теріс болса, shared encoder primary task-тен алыстатылып жатыр, ал auxiliary head-тер regularizer емес, қосымша шығын болып тұр.
Қорытынды

Return, volume және volatility бір microstructure-дан шығады, сондықтан shared representation — орынды prior; бірақ prior нәтиже емес. Бұл setup нақты анықтай алатын екі нәрсе: data қай loss-balancing scheme-ді қалайтыны (тек жеңімпазды атау емес, learned weights-ті хабарлау арқылы) және target-тердің correlation-ына сүйенбей, training бойы өлшенген shared encoder-дегі task gradient-терінің келісуі.
Егер purged walk-forward fold-тар MTL net-і per-target gradient-boosting model-ін жеңе алмайтынын көрсетсе, бұл — finding және оны сол күйінде жариялау керек: үлгі ретінде адал теріс нәтиже материалын қараңыз. Negative transfer бойынша negative result те negative transfer туралы нәтиже болып қала береді.
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.