← Maqolalarga qaytish
August 6, 2026
5 daqiqa o'qish

Parametrik bo'lmagan narxlarni modellashtirish uchun Gauss jarayonlari

Parametrik bo'lmagan narxlarni modellashtirish uchun Gauss jarayonlari
#bayesian
#gaussian-process
#kernel
#uncertainty
#non-parametric

"Classic ML baselines" seriyasining bir qismi.

Ikki narsa Gauss jarayonini ushbu blogdagi alohida maqolaga arziydi va ularning hech biri "bu sizga noaniqlik beradi".

Birinchisi yadro dizayni. GPning butun induktiv moyilligi bitta funktsiyada yashaydi k(x,x)k(x, x'), va bu funktsiya siz ataylab yozadigan narsadir: yo'l qanchalik qo'pol, u takrorlanadimi, takrorlanish pasayadimi. Standart asboblar to'plamidagi boshqa hech narsa bozor dinamikasi haqida aniq va keyin unga mos keladigan tizimli gipotezani aytishga imkon bermaydi. Ikkinchisi, marginal ehtimollik — murakkablik jazosiga ega bo'lgan mashg'ulot maqsadi, ushlab turilgan to'plamdan emas, balki modelning o'zidan olingan. Ushbu blogdagi haddan tashqari moslamadagi boshqa har bir maqola (plateau tahlili, PBO, deflated Sharpe bir nechta qidiruv tizimi mavjud emasligi sababli. GP kerak emasligini da'vo qiladi. Ushbu da'voni sinab ko'rish mumkin va uni sinovdan o'tkazish boshqa noaniqlik o'lchovlari bo'yicha qo'llanmadan ko'ra qiziqroq.

Noaniqlikning o'zi bo'yicha: GP posterior dispersiyasi * tizimli * - u keyinchalik o'rnatilgan modelga o'ralib qolmasdan, o'rtacha qiymatni keltirib chiqaradigan bir xil xulosadan kelib chiqadi. Bu konformal bashorat bilan haqiqiy kontrast boʻlib, u ushbu blogda nima uchun noaniqlik pozitsiya oʻlchamiga toʻgʻri kirishi va agar mavjud boʻlsa, interval bilan nima qilish kerakligi haqida maʼlumot beradi. Ushbu maqola bu holatni qayta ko'rib chiqmaydi; u modeldan keyin ketadi.

Quyida yadro va xulosa chiqarish mexanizmlari, GPyTorch ilovasi va - oxirida aniq aytilgan - bu maqolada hali mavjud bo'lmagan o'lchovlar.

Gauss jarayoni nima?

GPlar allaqachon bu blogda Bayesian optimallashtirish surrogati sifatida Optuna vs. koordinata descent da bir xil belgi va bir xil past o'lchamli ogohlantirish bilan paydo bo'ladi. Bu erda GP giperparametrlarni qidirish yuzasiga emas, balki bozor ma'lumotlariga moslashtirilgan modelning o'zi, shuning uchun davolash chuqurroq bo'ladi.

Gauss jarayoni - tasodifiy o'zgaruvchilar yig'indisi bo'lib, ularning har qanday chekli soni qo'shma Gauss taqsimotiga ega. Bu parametrlar bo'yicha taqsimot emas, balki funktsiyalar bo'yicha taqsimotdir.

Rasmiy ravishda, funktsiya f:XRf: \mathcal{X} \to \mathbb{R} har qanday cheklangan ma'lumotlar to'plami uchun GPdan olinadi {x1,x2,,xn}X\{x_1, x_2, \ldots, x_n\} \subset \mathcal{X}:

(f(x1)f(x2)f(xn))N((m(x1)m(x2)m(xn)),(k(x1,x1)k(x1,xn)k(xn,x1)k(xn,xn)))\begin{pmatrix} f(x_1) \\ f(x_2) \\ \vdots \\ f(x_n) \end{pmatrix} \sim \mathcal{N}\left(\begin{pmatrix} m(x_1) \\ m(x_2) \\ \vdots \\ m(x_n) \end{pmatrix}, \begin{pmatrix} k(x_1, x_1) & \cdots & k(x_1, x_n) \\ \vdots & \ddots & \vdots \\ k(x_n, x_1) & \cdots & k(x_n, x_n) \end{pmatrix}\right)

qayerda m(x)=E[f(x)]m(x) = \mathbb{E}[f(x)] o'rtacha funktsiya va k(x,x)=Cov(f(x),f(x))k(x, x') = \text{Cov}(f(x), f(x')) kovariatsiya (yadro) funktsiyasidir. Biz buni ixcham tarzda yozamiz:

fGP(m(),k(,))f \sim \mathcal{GP}(m(\cdot), k(\cdot, \cdot))

O'rtacha funktsiya o'rtacha xatti-harakati haqida oldingi ishonchni kodlaydi ff. Savdoda biz odatda o'rnatamiz m(x)=0m(x) = 0, bizda daromadlar bo'yicha oldingi yo'nalishga ega emasligi haqidagi taxminni kodlash. Barcha struktura yadroga kiradi.

Nima uchun parametrik emas?

5 ta xususiyatga ega chiziqli regressiya modeli 6 ta parametrga ega. 64 birlikdan iborat ikkita yashirin qatlamga ega bo'lgan neyron tarmog'ida minglab. GPda qat'iy parametrlar soni yo'q - modelning murakkabligi ma'lumotlar bilan o'sib boradi. 10 ta kuzatuv bilan GP 10 o'lchovli Gaussni aniqlaydi. 10 000 ta kuzatuv bilan u 10 000 o'lchovli Gaussni aniqlaydi.

Bu shifokorlarning giperparametrlari yo'q degani emas. Yadro funktsiyasi oldingisidan olingan funktsiyalarning xususiyatlarini boshqaradigan giperparametrlarga (uzunlik shkalasi, amplitudalar, davriylik) ega. Ammo funktsional shaklning o'zi hech qachon o'zgarmasdir. GP etarli ma'lumotlar va to'g'ri yadro berilgan holda har qanday uzluksiz funktsiyani ifodalashi mumkin. Bu "parametrik bo'lmagan" degan ma'noni anglatadi - model chiziqli funktsiyalar yoki polinomlar kabi parametrik oila bilan chegaralanmagan.

Moliyaviy modellashtirish uchun bu qimmatlidir. Bozorlar o'zgaradi. Xususiyatlar va daromadlar o'rtasidagi munosabatlar chiziqli bo'lmagan, statsionar bo'lmagan va rejimga bog'liq. Parametrik modellar haqiqatga mos kelmasligi mumkin bo'lgan tuzilishni o'rnatadi. GPlar ma'lumotlarni gapirishga imkon beradi.

Yadro funktsiyalari: Bozor tuzilmasini kodlash

Yadro funktsiyasi k(x,x)k(x, x') Gauss jarayonining ruhidir. Har qanday ikkita kirish nuqtasida funktsiya qiymatlari o'rtasidagi kovariatsiyani ko'rsatish orqali qaysi funktsiyalar apriori bo'lishi mumkinligini aniqlaydi. Turli yadrolar silliqlik, davriylik va uzoq muddatli xatti-harakatlar haqida turli taxminlarni kodlaydi.

Radial asos funktsiyasi (RBF) / kvadratli eksponensial

RBF yadrosi eng keng tarqalgan boshlanish nuqtasidir:

kRBF(x,x)=σ2exp(xx222)k_{\text{RBF}}(x, x') = \sigma^2 \exp\left(-\frac{\|x - x'\|^2}{2\ell^2}\right)

qayerda σ2\sigma^2 signal dispersiyasi (chiqish shkalasi) va \ell uzunlik shkalasi hisoblanadi. RBF yadrosi bilan GPdan olingan funksiyalar cheksiz farqlanadi - juda silliq.

Savdo talqini: Uzunlik shkalasi \ell ikkita ma'lumot nuqtasi qanchalik uzoqda bo'lishi va korrelyatsiya qilinishi mumkinligini nazorat qiladi. Qisqa uzunlik shkalasi modelning mahalliy naqshlarga ta'sir qilishini anglatadi; uzoq uzunlik shkalasi keng tendentsiyalarni qamrab olishini anglatadi. Signalning o'zgarishi σ2\sigma^2 funksiyaning amplitudasini nazorat qiladi - bashorat qilingan daromadlar qanchalik katta bo'lishi mumkin.

Moliya muammosi: Cheksiz silliqlik haqiqiy emas. Moliyaviy daromadlarda sakrash, rejim o'zgarishi va uzilishlar mavjud. RBF yadrosi ushbu xususiyatlarni engib o'tishi mumkin, bu esa tizimli tanaffuslar yaqinida juda konservativ bashoratlarni keltirib chiqaradi.

Ona yadrosi

Ona sinfi silliqlik parametrini kiritish orqali RBFni umumlashtiradi ν\nu:

kMatern(x,x)=σ221νΓ(ν)(2νxx)νKν(2νxx)k_{\text{Matern}}(x, x') = \sigma^2 \frac{2^{1-\nu}}{\Gamma(\nu)} \left(\frac{\sqrt{2\nu}\|x - x'\|}{\ell}\right)^{\nu} K_{\nu}\left(\frac{\sqrt{2\nu}\|x - x'\|}{\ell}\right)

qayerda KνK_{\nu} ikkinchi turdagi o'zgartirilgan Bessel funktsiyasidir. Sifatida ν\nu \to \infty, ona yadrosi RBF ga yaqinlashadi. Umumiy tanlovlar:

  • ν=1/2\nu = 1/2: Ornshteyn-Ulenbek jarayoniga teng. Funktsiyalar uzluksiz, lekin farqlanmaydi - qo'pol, Broun harakati kabi.
  • ν=3/2\nu = 3/2: Funktsiyalar bir marta differentsiallanadi. Yumshoqlik va moslashuvchanlik o'rtasidagi yaxshi muvozanat.
  • ν=5/2\nu = 5/2: Funktsiyalar ikki marta farqlanadi. dan silliqroq 3/23/2 lekin RBF dan kamroq qattiq.

** Savdo talqini: ** The Mather-3/23/2 Yadro moliyaviy vaqt seriyalari uchun eng yaxshi standart hisoblanadi. Bu haqiqiy narx yo'llari tirnalgan holda namoyon bo'ladigan qo'pollik turiga imkon beradi ν=1/2\nu = 1/2. Bu "o'zgaruvchanlik qo'pol" adabiyotiga mos keladi (Gatheral, Jaisson, & Rosenbaum, 2018), bu empirik ravishda o'zgaruvchanlik yo'llari atrofida Hurst ko'rsatkichlariga ega ekanligini ko'rsatadi. H0.1H \approx 0.1, Broun harakatidan ancha qo'polroq.

Klassik volatillik modellarini mag'lub etgan ona yadrolarining asosiy nashr etilgan dalillari Rizvi va boshqalardir. (2017), ular MSE tasodifiy yurishdan taxminan 20% va GARCHdan 50% yaxshiroq — 2017 kunlik valyuta juftlik maʼlumotlari boʻyicha, kripto emas va bu yerda koʻpaytirilmagan. Buni mezon sifatida emas, balki yadroni sinab koʻrish uchun motivatsiya sifatida koʻring. Ljung-Box va ARCH-LM diagnostikasi bilan haqiqiy BTC kundalik ma'lumotlariga mos keladigan ushbu blogning o'z GARCH(1,1) Kripto uchun GARCH volatilite prognozi; bir xil namunadagi ona GP qarshi bosh-to-boshi halol taqqoslash bo'ladi, va u ishga tushirilmagan.

Davriy yadro

Moliyaviy bozorlarda tsiklik naqshlar mavjud: kun ichidagi hajm egri chiziqlari, haftaning kunlik ta'siri, oylik balanslash oqimlari, choraklik daromad fasllari. Davriy yadro quyidagilarni qamrab oladi:

kPeriodic(x,x)=σ2exp(2sin2(πxx/p)2)k_{\text{Periodic}}(x, x') = \sigma^2 \exp\left(-\frac{2\sin^2\left(\pi|x - x'|/p\right)}{\ell^2}\right)

qayerda pp davr hisoblanadi. Ushbu yadrodan olingan funksiyalar nuqta bilan takrorlanadi pp, uzunlik shkalasi bilan modulyatsiyalangan \ell bu korrelyatsiyaning bir davr ichida qanchalik tez pasayishini nazorat qiladi.

Savdo talqini: Belgilangan p=24p = 24 (soat) kun ichidagi naqshlarni qo'lga olish uchun yoki p=5p = 5 (savdo kunlari) haftalik mavsumiylik uchun. Furye xususiyatlaridan farqli o'laroq, davriy yadro harmonikaning qat'iy sonini o'z zimmasiga olmaydi - GP ma'lumotlardan tsiklning shaklini o'rganadi.

Yadrolarni birlashtirish: qo'shimcha va multiplikativ kompozitsiya

GP yadrolarining haqiqiy kuchi kompozitsiyada yotadi. Agar k1k_1 va k2k_2 Yaroqli yadrolar, shuning uchun:

  • sum: k1+k2k_1 + k_2 — funksiya mustaqil komponentlar yig‘indisi (qo‘shimchalar parchalanishi)
  • Mahsulot: k1×k2k_1 \times k_2 - komponentlar o'rtasidagi o'zaro ta'sirlar (masalan, mahalliy davriy xatti-harakatlar)

Moliyaviy daromad olish uchun foydali kompozit yadro:

k(x,x)=kMatern-3/2(x,x)+kPeriodic(x,x)kRBF(x,x)k(x, x') = k_{\text{Matern-3/2}}(x, x') + k_{\text{Periodic}}(x, x') \cdot k_{\text{RBF}}(x, x')

Bu signalni quyidagilarga ajratadi:

  1. Silliq bo'lmagan, aperiodik trend komponenti (Matern-3/2)
  2. Vaqt o'tishi bilan amplitudasi pasayadigan davriy komponent (Periodic ×\times RBF)

mahsulot kPeriodickRBFk_{\text{Periodic}} \cdot k_{\text{RBF}} mahalliy davriy yadro hosil qiladi: naqsh takrorlanadi, lekin uzoqdagi takrorlar yaqin atrofdagilarga qaraganda kamroq ta'sir qiladi. Bu bozor mikrotuzilmasi rivojlanishi bilan vaqt o'tishi bilan o'zgarib turadigan moliyaviy mavsumiylikka to'g'ri keladi.

Spektral aralashma yadrolari

Maksimal moslashuvchanlik uchun spektral aralash (SM) yadrosi (Wilson & Adams, 2013) yadroning spektral zichligini Gauss aralashmasi sifatida parametrlaydi:

kSM(x,x)=q=1Qwqexp(2π2xx2vq)cos(2πxxμq)k_{\text{SM}}(x, x') = \sum_{q=1}^{Q} w_q \exp\left(-2\pi^2 \|x - x'\|^2 v_q\right) \cos\left(2\pi \|x - x'\| \mu_q\right)

qayerda wqw_q aralashma og'irliklari, vqv_q spektral dispersiyadir va μq\mu_q spektral vositalar (chastotalar) hisoblanadi. Bochner teoremasi bo'yicha har qanday statsionar yadro shu tarzda ifodalanishi mumkin. SM yadrosi bir vaqtning o'zida davriy komponentlarni, uzoq muddatli tendentsiyalarni va qisqa masofali korrelyatsiyalarni aniqlay oladi - barchasi ma'lumotlardan.

Savdo talqini: SM yadrosi maʼlumotlarda qanday naqshlar mavjudligini bilmasangiz foydali boʻladi. U qaytish seriyalarida yashirin davriyliklarni aniqlashi mumkin (masalan, avtomatlashtirilgan qayta muvozanatlash orqali boshqariladigan kripto bozorlaridagi nozik 4 soatlik tsikllar). Salbiy tomoni ko'proq giperparametrlar va kichik ma'lumotlar to'plamlari bilan haddan tashqari moslashish xavfi.

Orqa xulosa: Oldindan bashorat qilishgacha

Ta'lim ma'lumotlari berilgan D={(xi,yi)}i=1n\mathcal{D} = \{(x_i, y_i)\}_{i=1}^n qayerda yi=f(xi)+ϵiy_i = f(x_i) + \epsilon_i va ϵiN(0,σn2)\epsilon_i \sim \mathcal{N}(0, \sigma_n^2), test nuqtalarida GP posterior XX_* yopiq shakldagi yechimga ega. Bu ko'pchilik Bayes modellariga nisbatan GPlarning asosiy hisoblash ustunligidir.

Orqa tenglamalar

Mayli K=k(X,X)K = k(X, X) bo'l n×nn \times n o'qitish kovarianti matritsasi, K=k(X,X)K_* = k(X_*, X) bo'l m×nm \times n o'zaro kovariatsiya matritsasi, va K=k(X,X)K_{**} = k(X_*, X_*) bo'l m×mm \times m test kovariant matritsasi. Orqa tomon:

fX,y,XN(fˉ,Cov(f))f_* | X, y, X_* \sim \mathcal{N}(\bar{f}_*, \text{Cov}(f_*))

qayerda:

fˉ=K(K+σn2I)1y\bar{f}_* = K_* (K + \sigma_n^2 I)^{-1} y

Cov(f)=KK(K+σn2I)1KT\text{Cov}(f_*) = K_{**} - K_* (K + \sigma_n^2 I)^{-1} K_*^T

Orqa ma'no fˉ\bar{f}_* Bu sinov va o'quv nuqtalari o'rtasidagi yadro o'xshashligi bilan og'irlashtirilgan o'quv maqsadlarining chiziqli birikmasidir. Orqa kovariatsiya Cov(f)\text{Cov}(f_*) oldingi kovariatsiyadan boshlanadi KK_{**} va o'quv ma'lumotlaridan olingan ma'lumotlarni ayiradi. Trening ma'lumotlari zich bo'lgan joyda, posterior dispersiya kichikdir. Trening ma'lumotlari siyrak bo'lsa, posterior dispersiya avvalgisiga qaytadi.

Marginal ehtimollik va sinovdan o'tishga arziydigan da'vo

Yadro giperparametrlari θ\theta (uzunlik shkalasi, farqlar, shovqin darajasi) logning chegaraviy ehtimolini maksimal darajada oshirish orqali o'rganiladi:

logp(yX,θ)=12yT(K+σn2I)1y12logK+σn2In2log2π\log p(y | X, \theta) = -\frac{1}{2} y^T (K + \sigma_n^2 I)^{-1} y - \frac{1}{2} \log |K + \sigma_n^2 I| - \frac{n}{2} \log 2\pi

Birinchi atama ma'lumotlarga mos atamadir (kuzatishlardan uzoqda bo'lgan bashoratlarni jazolaydi). Ikkinchi muddat - murakkablik jazosi (juda moslashuvchan modellarni jazolaydi - ya'ni yadro matritsasi katta determinantga ega). Uchinchi had - normalizatsiya konstantasi.

Bu avtomatik Occam ustarasi va bu GP savdo quvuriga olib keladigan eng qiziqarli narsa. Da'voning kuchli versiyasi shundan iboratki, tartibga solish uchun alohida tekshirish to'plami kerak emas — murakkablik jazosi maqsadning ichidadir, shuning uchun model moslashuvchanlik bilan fitni bepul sotib olmaydi.

Bu da'vo, ayniqsa, ushbu blogda shubhaga loyiqdir. Plato tahlili shuni ko'rsatadiki, bitta ballli tekshirish balli yomon tanlov mezonidir va mustahkamlik mahalla shaklida yashaydi; PBO namunadagi g'olibning namunadan tashqarida qanchalik tez-tez yutqazishini miqdoriy ko'rsatadi; deflated Sharpe sinovlar sonidagi narxlar. Marjinal ehtimollik hali ham yuqoriga ko'tariladigan namunadagi maqsaddir θ\theta — Occam omili ko'p o'rnatilgan yadrolar bo'yicha tanlash emas, balki sig'imiyat modelini jazolaydi. Agar siz o'n ikkita nomzod yadrosini o'rnatsangiz va eng yuqori ehtimollikka ega bo'lganini tanlasangiz, siz ko'p sinovli hududga qaytdingiz va deflyatsiya mantig'i o'zgarishsiz qo'llaniladi. Soxtalashtirilgan versiya: marginal ehtimollik tanlovi bir xil ma'lumotlar va bir xil yadro oilasidagi tekshirish to'plamini tanlashga qaraganda kichikroq namunadagi/namunadan tashqaridagi bo'shliqni keltirib chiqaradimi? Bu o'lchanadi va quyida o'lchanmaydi.

Marjinal ehtimollik yuzasi ham mahalliy optimaga ega. Bir nechta tasodifiy qayta ishga tushirish yoki ehtiyotkorlik bilan ishga tushirish masalasi - uzunlik shkalasini o'quv kirishlarining o'rtacha juftlik masofasiga va shovqin farqini nishonlarning namunaviy farqiga moslashtirish oqilona boshlanish nuqtasidir.

Hisoblash xarajati va miqyosi

To'siq teskari bo'ladi (K+σn2I)(K + \sigma_n^2 I), bu xarajat O(n3)O(n^3) vaqtida va O(n2)O(n^2) xotirada. Kub devori allaqachon bu blogda boshqa tomondan muhokama qilingan: qidiruv usuli va baholash narxi maqsad arzon bo'lsa, GP-ga asoslangan Bayesian optimallashtirishni to'g'ridan-to'g'ri diskvalifikatsiya qiladi, chunki surrogat tejagan baholardan ko'proq xarajat qiladi. Bu erda arifmetika bir xil; dastur boshqacha. Bozor ma'lumotlariga moslashtirilgan model sifatida kubik atama diskvalifikatsiya emas, balki byudjetdir: u mashg'ulot oynasida qattiq shiftni o'rnatadi.

Savdo ilovalari uchun miqyoslilik strategiyalari:

  1. Siyrak GP (induktsiya nuqtalari). ni almashtiring n×nn \times n bilan matritsa m×mm \times m matritsa qaerda mnm \ll n. Induktsiya nuqtalari Z={z1,,zm}Z = \{z_1, \ldots, z_m\} ta'lim ma'lumotlarini umumlashtiruvchi psevdo-kiritmalardir. Hensman va boshqalar tomonidan SVGP (Stokastik Variatsion GP) formulasi. (2013) xarajat bilan mini-partiyali o'qitish imkonini beradi O(nm2)O(nm^2) iteratsiya uchun. GPyTorch buni tabiiy ravishda qo'llab-quvvatlaydi.

  2. Tuzilgan yadro interpolyatsiyasi (SKI/KISS-GP). Kirishlar tarmoq ustida joylashganda yadro matritsasidagi Kronecker va Toeplitz tuzilmalaridan foydalanadi. Narxlarni kamaytiradi O(n+glogg)O(n + g \log g) qayerda gg panjara o'lchamidir. Muntazam tanlangan vaqt seriyalari uchun ideal (masalan, 1 daqiqali chiziqlar).

  3. Silmali oynalarda mahalliy GP. Alohida GPlarni faqat oxirgi maʼlumotlarga oʻrgating. Bu erda GPga xos cheklov tishlaydi: standart yadrolar statsionar (k(x,x)k(x,x') faqat bog'liq xxx - x') va bozorlar emas, shuning uchun odatiy javob aylanma oynadir - lekin deraza uzunligi yuqorida chegaralangan O(n3)O(n^3), faqat statistika bo'yicha emas. Oldinga yurishni optimallashtirish langar va aylanuvchi oynalarni, poyezd/sinov uzunligini va umuman qayta optimallashtirish chastotasini qamrab oladi; GP uchun oyna o'lchami statistik qaror kabi hisoblash qaroridir va langarlangan (doimiy o'sib boruvchi) oynani taxminan bir necha ming nuqtadan so'ng oddiygina qilib bo'lmaydi. Bu qayta ishlashning amaliy natijasidir: GP bilan siz "barcha tarixdan foydalanish" ni tanlay olmaysiz.

Qaytish bashorati uchun GP: Amaliy asos

Xususiyatlar dizayni: Nima uchun 500 emas, 5-20 xususiyat

Bozor ma'lumotlari ML uchun umumiy xususiyat taksonomiyasi - buyurtma kitobi nomutanosibligi, kitob bosimi, VPIN, Kayl lambdasi, amalga oshirilgan o'zgaruvchanlik xususiyatlari, tsiklik vaqtni kodlash, o'zaro aktivlar va moliyalashtirish tezligi signallari - allaqachon mashinani o'rganish bilan modellashtirishning tarqalishi da keltirilgan; ushbu ro'yxatdan foydalaning.

GPga xos bo'lgan narsa ro'yxatning * o'lchamidir. Yadro usullari yuqori o'lchamlarda yomonlashadi: masofalar konsentratsiyalanadi va statsionar yadro diskriminatsiyani yo'qotadi. Moliyaviy GP uchun amaliy diapazon 5-20 ta kirishni tashkil etadi, gradient bilan mustahkamlangan daraxt xursandchilik bilan iste'mol qiladigan yuzlab emas. Bu omon qolish mexanizmi ARD (Avtomatik muvofiqlikni aniqlash): har bir kirish o'lchamiga o'z uzunlik shkalasini bering. d\ell_d, va marginal-ehtimollik ta'lim surish d\ell_d \to \infty hech qanday signal o'tkazmaydigan o'lchamlar uchun, chunki cheksiz uzunlik shkalasi yadro bu koordinatani e'tiborsiz qoldirishini anglatadi. Xususiyatlarni tanlash moslashish va o'rganishning yon mahsulotiga aylanadi d\ell_d to'g'ridan-to'g'ri moslik reytingi sifatida o'qilishi mumkin - bu ham uni soxtalashtirishga imkon beradi: kompozit yadroni haqiqiy chiziqlarga moslang, uzunlik shkalasini chop eting va siz ishonadigan xususiyatlar model saqlaydimi yoki yo'qligini tekshiring.

Lavozimni aniqlash va betaraflik

GP posterior beradi σ(x)\sigma_*(x) to'g'ridan-to'g'ri, shuning uchun u to'g'ridan-to'g'ri oraliq kengligi bilan [Xavfni hisobga olgan holda pozitsiya o'lchami uchun mos bashorat] (/uz/blog/post/conformal-prediction-trading) da ishlab chiqilgan chekka nisbati va savdosiz filtriga tushadi. wt=2κσ(x)w_t = 2\kappa\sigma_*(x). Yagona farq - kelib chiqishi: GP kalibrlash to'plamidan emas, balki modelning o'zidan kenglikni ishlab chiqaradi, shuning uchun u o'tgan qoldiqlarning global miqdori bilan emas, balki o'quv ma'lumotlariga nisbatan sinov nuqtasi qaerda joylashganiga qarab o'zgaradi.

GPyTorch bilan amalga oshirish

GPyTorch - kengaytiriladigan GP xulosasi uchun PyTorch-ga asoslangan kutubxona. U GPU tezlashuvi, avtomatik farqlash va zamonaviy chiziqli algebra usullaridan (konjugat gradientlari, Lanczos dekompozitsiyasi) GPlarni soddalikdan tashqari masshtablash uchun foydalanadi. O(n3)O(n^3) chegara.

Qaytish bashorati uchun asosiy aniq GP

import torch
import gpytorch
import numpy as np
from torch.utils.data import TensorDataset, DataLoader


class ExactGPModel(gpytorch.models.ExactGP):
    """Exact GP with a composite kernel for financial returns."""

    def __init__(self, train_x, train_y, likelihood):
        super().__init__(train_x, train_y, likelihood)
        self.mean_module = gpytorch.means.ZeroMean()

        self.covar_matern = gpytorch.kernels.ScaleKernel(
            gpytorch.kernels.MaternKernel(nu=1.5, ard_num_dims=train_x.shape[1])
        )
        self.covar_periodic = gpytorch.kernels.ScaleKernel(
            gpytorch.kernels.PeriodicKernel()
        )
        self.covar_rbf_decay = gpytorch.kernels.ScaleKernel(
            gpytorch.kernels.RBFKernel()
        )

    def forward(self, x):
        mean = self.mean_module(x)
        covar = self.covar_matern(x) + self.covar_periodic(x) * self.covar_rbf_decay(x)
        return gpytorch.distributions.MultivariateNormal(mean, covar)

ard_num_dims Bu yuqorida muhokama qilingan har bir o'lchamdagi uzunlik shkalalariga imkon beradigan narsa. Treningdan so'ng, model.covar_matern.base_kernel.lengthscale o‘qiladigan vektor hisoblanadi.

O'quv tsikli

def train_gp(train_x, train_y, n_epochs=200, lr=0.05, device=None):
    """Train the GP by maximizing the marginal log-likelihood.

    Returns the device alongside the model so that callers move test
    tensors to the same place -- otherwise prediction crashes on GPU.
    """
    if device is None:
        device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

    train_x = train_x.to(device)
    train_y = train_y.to(device)

    likelihood = gpytorch.likelihoods.GaussianLikelihood().to(device)
    model = ExactGPModel(train_x, train_y, likelihood).to(device)

    model.train()
    likelihood.train()

    optimizer = torch.optim.Adam(model.parameters(), lr=lr)
    mll = gpytorch.mlls.ExactMarginalLogLikelihood(likelihood, model)

    losses = []
    for epoch in range(n_epochs):
        optimizer.zero_grad()
        output = model(train_x)
        loss = -mll(output, train_y)
        loss.backward()
        optimizer.step()
        losses.append(loss.item())

        if (epoch + 1) % 50 == 0:
            noise = likelihood.noise.item()
            print(
                f"Epoch {epoch+1}/{n_epochs} | "
                f"Loss: {loss.item():.4f} | "
                f"Noise: {noise:.6f}"
            )

    return model, likelihood, device, losses

Noaniqlik bilan bashorat qilish

def predict_with_uncertainty(model, likelihood, test_x, device):
    """Generate predictions with uncertainty estimates."""
    model.eval()
    likelihood.eval()

    test_x = test_x.to(device)

    with torch.no_grad(), gpytorch.settings.fast_pred_var():
        posterior = likelihood(model(test_x))

        mean = posterior.mean
        variance = posterior.variance
        lower, upper = posterior.confidence_region()  # 2-sigma bounds

    return {
        "mean": mean.cpu().numpy(),
        "std": variance.sqrt().cpu().numpy(),
        "lower_2sigma": lower.cpu().numpy(),
        "upper_2sigma": upper.cpu().numpy(),
    }

The fast_pred_var() kontekst menejeri prognozli farqlarni hisoblash uchun LOVE (Lanczos Variance Estimates) algoritmidan foydalanadi. O(n)O(n) o'rniga vaqt O(n2)O(n^2).

Oxir-oqibat savdo quvuri

Quyidagi xususiyat yaratuvchisiga e'tibor bering: har bir o'zgaruvchan statistika qat'iy orqaga qarashli bo'lishi kerak va kirish standartizatsiyasi faqat o'quv bo'limiga o'rnatilishi kerak. Bu ikkinchi nuqta umumiy gigiena emas - bu har bir oqish turi ishlab chiqaradigan Sharpe inflyatsiyasi haqida xabar beruvchi [oldinga qarash taksonomiyasi] (/uz/blog/post/look-ahead-bias-taxonomy) da ajratilgan va o'lchangan normalizatsiya oqish kanalidir. GP o'z kirishlarini qurilish bo'yicha standartlashtiradi, shuning uchun u eng ko'p ta'sir qiladigan oqishdir.

import pandas as pd


def build_features(df: pd.DataFrame, lookback: int = 10) -> pd.DataFrame:
    """Build features for GP-based return prediction."""
    features = pd.DataFrame(index=df.index)

    for lag in range(1, lookback + 1):
        features[f"ret_lag_{lag}"] = df["close"].pct_change().shift(lag)

    ret = df["close"].pct_change()
    features["vol_ratio"] = (
        ret.rolling(10).std() / ret.rolling(50).std()
    )

    features["vol_zscore"] = (
        (df["volume"] - df["volume"].rolling(50).mean())
        / df["volume"].rolling(50).std()
    )

    if "bid_vol" in df.columns and "ask_vol" in df.columns:
        features["obi"] = (
            (df["bid_vol"] - df["ask_vol"])
            / (df["bid_vol"] + df["ask_vol"])
        )

    if hasattr(df.index, "hour"):
        hours = df.index.hour + df.index.minute / 60.0
        features["time_sin"] = np.sin(2 * np.pi * hours / 24)
        features["time_cos"] = np.cos(2 * np.pi * hours / 24)

    features.dropna(inplace=True)
    return features


def run_gp_strategy(
    df: pd.DataFrame,
    train_window: int = 500,
    retrain_every: int = 50,
    confidence_threshold: float = 1.0,
    risk_fraction: float = 0.02,
    max_leverage: float = 1.0,
):
    """Walk-forward GP trading strategy with uncertainty-based sizing."""
    features = build_features(df)
    returns = df["close"].pct_change().reindex(features.index)
    target = returns.shift(-1)  # predict next-bar return

    mask = features.notna().all(axis=1) & target.notna()
    features = features[mask]
    target = target[mask]

    positions = pd.Series(0.0, index=features.index)
    predictions = pd.DataFrame(
        index=features.index, columns=["mean", "std"], dtype=float
    )

    model = likelihood = device = None
    x_mean = x_std = y_mean = y_std = None

    for i in range(train_window, len(features)):
        if model is None or (i - train_window) % retrain_every == 0:
            train_x = torch.tensor(
                features.iloc[i - train_window : i].values,
                dtype=torch.float32,
            )
            train_y = torch.tensor(
                target.iloc[i - train_window : i].values,
                dtype=torch.float32,
            )

            x_mean, x_std = train_x.mean(0), train_x.std(0) + 1e-8
            y_mean, y_std = train_y.mean(), train_y.std() + 1e-8
            train_x_norm = (train_x - x_mean) / x_std
            train_y_norm = (train_y - y_mean) / y_std

            model, likelihood, device, _ = train_gp(
                train_x_norm, train_y_norm, n_epochs=100
            )

        test_x = torch.tensor(
            features.iloc[i : i + 1].values, dtype=torch.float32
        )
        test_x_norm = (test_x - x_mean) / x_std

        pred = predict_with_uncertainty(model, likelihood, test_x_norm, device)

        pred_mean = pred["mean"][0] * y_std.item() + y_mean.item()
        pred_std = pred["std"][0] * y_std.item()

        predictions.iloc[i] = [pred_mean, pred_std]

        z_score = abs(pred_mean) / (pred_std + 1e-8)
        if z_score > confidence_threshold:
            size = min(z_score * risk_fraction, max_leverage)
            positions.iloc[i] = np.sign(pred_mean) * size

    strategy_returns = positions.shift(1) * returns
    return strategy_returns, predictions, positions

Noyob GPlar bilan kattaroq ma'lumotlar to'plamiga o'tkazish

Trening oynasi bir necha ming balldan oshib ketganda, GPning aniq xulosasi sekinlashadi. Variatsion siyrak GPga o'tish:

class SparseGPModel(gpytorch.models.ApproximateGP):
    """Sparse variational GP for large-scale return prediction."""

    def __init__(self, inducing_points):
        variational_distribution = (
            gpytorch.variational.CholeskyVariationalDistribution(
                inducing_points.size(0)
            )
        )
        variational_strategy = (
            gpytorch.variational.VariationalStrategy(
                self,
                inducing_points,
                variational_distribution,
                learn_inducing_locations=True,
            )
        )
        super().__init__(variational_strategy)
        self.mean_module = gpytorch.means.ZeroMean()
        self.covar_module = gpytorch.kernels.ScaleKernel(
            gpytorch.kernels.MaternKernel(nu=1.5)
        )

    def forward(self, x):
        mean = self.mean_module(x)
        covar = self.covar_module(x)
        return gpytorch.distributions.MultivariateNormal(mean, covar)


def train_sparse_gp(train_x, train_y, n_inducing=128, n_epochs=50, batch_size=256):
    """Train sparse GP with mini-batch stochastic variational inference."""
    indices = torch.randperm(train_x.size(0))[:n_inducing]
    inducing_points = train_x[indices]

    model = SparseGPModel(inducing_points)
    likelihood = gpytorch.likelihoods.GaussianLikelihood()

    model.train()
    likelihood.train()

    optimizer = torch.optim.Adam(
        [{"params": model.parameters()}, {"params": likelihood.parameters()}],
        lr=0.01,
    )
    mll = gpytorch.mlls.VariationalELBO(
        likelihood, model, num_data=train_y.size(0)
    )

    dataset = TensorDataset(train_x, train_y)
    loader = DataLoader(dataset, batch_size=batch_size, shuffle=True)

    for epoch in range(n_epochs):
        for x_batch, y_batch in loader:
            optimizer.zero_grad()
            output = model(x_batch)
            loss = -mll(output, y_batch)
            loss.backward()
            optimizer.step()

    return model, likelihood

128 ta induktsiya punkti bilan bir partiyaning narxi O(1282×batch_size)O(128^2 \times \text{batch\_size}) - har bir partiyaga taxminan 4 million operatsiya. Bu bitta GPUda 100 000 dan ortiq kuzatuvlar ma'lumotlar to'plamini osongina boshqaradi.

Yadroni chuqur o'rganish: GP neyron tarmoqlar bilan uchrashadi

Agar kirish maydoni katta o'lchamli bo'lsa yoki xususiyatlar va daromadlar o'rtasidagi munosabatlar juda nochiziqli bo'lsa, oddiy yadro qiyinlashishi mumkin. Chuqur yadroni o'rganish (DKL) GP yadrosini qo'llashdan oldin kirishlarni neyron tarmoq orqali o'tkazadi:

kDKL(x,x)=kbase(gϕ(x),gϕ(x))k_{\text{DKL}}(x, x') = k_{\text{base}}(g_\phi(x), g_\phi(x'))

qayerda gϕg_\phi parametrlarga ega neyron tarmoqdir ϕ\phi va kbasek_{\text{base}} standart yadrodir (masalan, Matern-3/2). Tarmoq GP yadrosi eng samarali bo'lgan xususiyat namoyishini o'rganadi. Butun model - tarmoq parametrlari va yadro giperparametrlari - chekka ehtimollikni maksimal darajada oshirish orqali oxirigacha o'qitiladi.

class DeepKernelGP(gpytorch.models.ExactGP):
    """GP with a neural network feature extractor."""

    def __init__(self, train_x, train_y, likelihood, input_dim):
        super().__init__(train_x, train_y, likelihood)
        self.mean_module = gpytorch.means.ZeroMean()

        self.feature_extractor = torch.nn.Sequential(
            torch.nn.Linear(input_dim, 8),
            torch.nn.ReLU(),
            torch.nn.Linear(8, 4),
            torch.nn.ReLU(),
            torch.nn.Linear(4, 2),
        )

        self.covar_module = gpytorch.kernels.ScaleKernel(
            gpytorch.kernels.MaternKernel(nu=1.5, ard_num_dims=2)
        )

    def forward(self, x):
        features = self.feature_extractor(x)
        mean = self.mean_module(features)
        covar = self.covar_module(features)
        return gpytorch.distributions.MultivariateNormal(mean, covar)

DKL neyron tarmoqlarni o'rganishni GPlarning noaniqlik miqdori bilan birlashtiradi. GP darajasi o'quv ma'lumotlaridan uzoqda bo'lgan bashoratlarning yuqori noaniqlikka ega bo'lishini ta'minlaydi - bu standart neyron tarmoqlari mashhur tarzda ta'minlay olmaydigan narsa. Shuni ham esda tutingki, DKL politsiya uchun chegara ehtimoli bo'lgan moslashuvchanlikni qaytadan kiritadi: Occam omili yadroni jazolaydi, lekin uning oldidagi tarmoq minglab bepul parametrlarga ega va bunday jazo yo'q.

Ludkovski va Risk (2025), Miqdoriy moliya uchun Gauss jarayon modellari, DKLni kengroq miqdoriy-moliyaviy kontekstda o'rganish, shu jumladan optsion narxlari va portfelni optimallashtirish; bu natijalar ularniki, ularning muammolari bo'yicha va kriptoning qaytishini bashorat qilish uchun dalil emas.

Diagnostika va tuzoqlar

Kalibrlash

Yaxshi kalibrlangan GP empirik qamrovga mos keladigan bashoratli intervallarga ega. Tekshiruv konformal bashorat da qoʻllaniladigan bir xil boʻlib, u nega chegaraviy qamrov shartli qamrov emasligi nazariyasini ham oʻz ichiga oladi, bu cheklov GP intervallari uchun ham amal qiladi:

from scipy.stats import norm

def calibration_report(predictions, actuals):
    """Check if GP uncertainty is well-calibrated."""
    z_scores = (actuals - predictions["mean"]) / (predictions["std"] + 1e-8)

    for sigma in [1, 2, 3]:
        expected_outside = 2 * (1 - norm.cdf(sigma))
        actual_outside = (np.abs(z_scores) > sigma).mean()
        print(
            f"{sigma}-sigma | Expected outside: {expected_outside:.3f} | "
            f"Actual outside: {actual_outside:.3f}"
        )

Kutilayotgan oshib ketish 1/2/3 sigmada 0,317 / 0,046 / 0,003 ni tashkil qiladi. Muhim ahamiyatga ega bo'lgan raqam - bu kripto barlar orqali oldinga siljishda nimani chop etishi va bu jadval hali bu maqolada yo'q. Oldindan taxmin qilish kerakki, GP o'ziga haddan tashqari ishonadi - yog 'dumli, statsionar bo'lmagan daromadlarning Gauss ehtimoli 3 sigmada yomon yashirin bo'lishi kerak, ammo "kerak" bu o'lchov emas.

Qolgan tuzoqlar

  1. Kirish masshtablash. Uzunlik shkalasi kiritish shkalasiga nisbatan, shuning uchun xususiyat oralig‘i [0,10000][0, 10000] va biri masofani bosib o'tdi [0,1][0, 1] mazmunli bo'lishi mumkin emas \ell; ARD - bu heterojen diapazonlarni qutqaradigan narsa va standartlashtirish - bu ARDni ishga tushirishni oqilona qiladi.

  2. Marjinal ehtimollikni haddan tashqari moslashtirish. Ko'p yadro giperparametrlari (ayniqsa, kompozit yoki spektral aralash yadrolari) bilan chegaraviy ehtimollik baribir haddan tashqari mos kelishi mumkin. Priorlardan foydalaning: o'rta juftlik masofasida markazlashtirilgan uzunlik shkalasi bo'yicha log-normal oldingi, dispersiyalardan oldingi yarim normal.

  3. Kovariance matritsasini shartlash. (K+σn2I)(K + \sigma_n^2 I) shovqin paydo bo'lganda sonli birlik bo'lishi mumkin σn2\sigma_n^2 juda kichik yoki mashg'ulot nuqtalari deyarli takrorlanganda. GPyTorch qo'shadi 10610^{-6} diagonalga jitter; yomon shartli moliyaviy ma'lumotlar ko'pincha ko'proq talab qilinadi.

  4. Oldinga qarash. Yuqorida va batafsil oʻlchov bilan oldinga qarash taksonomiyasida yoritilgan.

Qachon GP va boshqa modellardan foydalanish kerak

Mezon GP XGBoost Neyron tarmoq
O'rnatilgan noaniqlik Ha (strukturaviy) Yo'q (konformal/bootstrap kerak) Yo'q (MC tark/ansambli kerak)
Ma'lumotlar samaradorligi Zo'r (<1000 namuna) * *
Masshtablilik Yomon aniq, yaxshi siyrak * *
Nochiziqlilik Yadroga bog'liq * *
Talqin qilish imkoniyati Yadro parchalanishi + ARD uzunligi shkalasi * *
Statsionar bo'lmagan Sürgülü oyna yoki DKL talab qiladi * *

* XGBoost va neyron tarmoq ustunlari uchun bu yerda yangi tasdiqdan koʻra eʼlon qilingan taqqoslashlarga eʼtibor bering: mashina oʻrganish bilan yoyilgan modellashtirish gradient-boosting-vs-deep-learning (moliyaviy maʼlumotlar, qayta talqin qilish, talqin qilish uchun jadval) mavjud. moslashish, kechikish) va vaqtinchalik termoyadroviy transformatorlar TFT va LSTM vanil transformatoriga qarshi.

Ushbu shifokorlardan quyidagi hollarda foydalaning:

  • Sizda kichik va o'rta ma'lumotlar to'plami mavjud (har bir mashg'ulot oynasida ~10 000 kuzatuvdan kam)
  • Siz signal haqida aniq, tekshirilishi mumkin bo'lgan tizimli gipotezani xohlaysiz (trend + mavsumiylik + shovqin)
  • Noaniqlik nafaqat global qoldiq kvant bilan emas, balki o'quv ma'lumotlaridan masofaga qarab o'zgarishi kerak

** Quyidagi hollarda GP dan foydalanmang:**

  • Millionlab kuzatuvlar uchun sizga millisekunddan kichik xulosalar kerak
  • Kirish hajmi ~50 dan oshadi
  • Signal statsionar yadrolar ifodalay olmaydigan murakkab yuqori tartibli xususiyatlar o'zaro ta'sirida yashaydi (DKL Occam mulki hisobidan yordam beradi)

Ushbu maqola hali nimani o'lchamaydi

Yuqorida aytilganlarning barchasi namunaviy mashinalardir. Ularning hech biri shifokorning kriptodan pul topishiga dalil emas va bu blogning standarti maqolada o'z raqamlari mavjud. Ochiq elementlar, ular ishga tushirilishi kerak bo'lgan tartibda:

  1. Haqiqiy BTCUSDT 1m barlarda ARD uzunligi shkalasi. Kompozit yadroni joylashtiring, chop eting d\ell_d har bir xususiyat uchun. Bu to'g'ridan-to'g'ri "ARD o'rnatilgan xususiyat tanlovi" da'vosini sinovdan o'tkazadi va noto'g'ri xususiyatga tegishli reytingni ishlab chiqaradi.
  2. Oldinga yugurishda kalibrlash jadvali. Kutilayotgan va empirik oshib ketish 1/2/3 sigma darajasida, aniq ko'rsatilgan, shu jumladan GP o'ziga haddan tashqari ishongan holatda.
  3. Ishonch bilan himoyalangan strategiya, oldinga siljish, halol salbiy bilan bir xil beshta yo‘nalish bo‘yicha sinovlar soni uchun deflatsiya qilinadi. Muvaffaqiyatsiz bo‘lsa, u boshqa salbiy natija sifatida o‘sha qatorga kiradi.
  4. Devor soati O(n3)O(n^3) egri uchun n=250/500/1000/2000/5000n = 250 / 500 / 1000 / 2000 / 5000, aniq va SVGP, shuning uchun miqyoslash bo'limi tasdiqlash o'rniga diagrammaga tayanadi.

Xulosa

Savdoda Gauss jarayonlari uchun holat "ular sizga xato satrini beradi" emas - konformal bashorat sizga kamroq taqsimlash taxminlari bilan xato qatorlarini beradi va GPda yo'q qamrov kafolati. Vaziyat shundan iboratki, GP sizni tizimli gipotezangizni yadro sifatida yozishga majbur qiladi, uni o'ziga xos murakkablik darajasida baholanadigan maqsadga muvofiqlashtiradi va keyin ARD uzunlik shkalasi orqali u sizning qaysi xususiyatlaringizdan aslida foydalanganligini aytib beradi. Bu g'ayrioddiy tushunarli model.

Xarajatlar bir xil darajada aniq: mashg'ulot oynangizni yopadigan kub shkalasi, aylanma oyna faqat qisman tuzatadi, degan statsionarlik taxminlari, yog 'quyruqning qaytishi buzilishining Gauss ehtimoli va - chuqur yadroni o'rganishga erishganingizdan so'ng - birinchi navbatda marjinal ehtimollikka turtki bo'lgan Occam xususiyatining jimgina yo'qolishi. Qolgan narsa sotilishi mumkinmi yoki yo'qmi - bu empirik savol va yuqorida sanab o'tilgan to'rtta o'lchov bunga javob beradi.

Ma'lumotnomalar

  • Rasmussen, C. E. va Uilyams, C. K. I. (2006). Mashina o'rganish uchun Gauss jarayonlari. MIT matbuoti.
  • Uilson, A. va Adams, R. (2013). Naqshlarni topish va ekstrapolyatsiya qilish uchun Gauss jarayoni yadrolari. ICML.
  • Hensman, J., Fusi, N. va Lawrence, N. D. (2013). Katta ma'lumotlar uchun Gauss jarayonlari. UAI.
  • Gatheral, J., Jaisson, T., & Rosenbaum, M. (2018). O'zgaruvchanlik qo'pol. Miqdoriy moliya, 18(6).
  • Rizvi, S. A. A., Roberts, S. J., Osborn, M. A. va Nyikosa, F. (2017). Gauss jarayoni konvertlari bilan moliyaviy o'zgaruvchanlikni prognoz qilishning yangi yondashuvi. arXiv:1705.00891.
  • Ludkovski, M. va Risk, J. (2025). Miqdoriy moliya uchun Gauss jarayon modellari. Springer.
  • Gardner, J. R., Pleiss, G., Bindel, D., Weinberger, K. Q. va Uilson, A. G. (2018). GPyTorch: GPU tezlashuvi bilan Blackbox Matrix-Matrix Gauss jarayoni xulosasi. NeurIPS.
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

Bozordan bir qadam oldinda bo'ling

Sun'iy intellekt savdo tahlillari, bozor tahlili va platforma yangiliklari uchun bizning xabarnomaga obuna bo'ling.

Biz sizning maxfiyligingizni hurmat qilamiz. Istalgan vaqtda obunadan chiqishingiz mumkin.