neuroalpha 0.2.0 → 0.3.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +17 -0
- package/README.md +9 -3
- package/bin/cli.js +69 -69
- package/config/seed-run.json +1 -0
- package/config/strategy.json +4 -10
- package/deploy/install.sh +128 -0
- package/docs//320/224/320/225/320/237/320/233/320/236/320/231.md +103 -0
- package/docs//320/230/320/235/320/241/320/242/320/240/320/243/320/232/320/246/320/230/320/257.md +1 -1
- package/docs//320/234/320/225/320/245/320/220/320/235/320/230/320/232/320/220_/320/230_/320/237/320/220/320/240/320/220/320/234/320/225/320/242/320/240/320/253.md +171 -0
- package/package.json +15 -5
- package/public/admin.html +449 -0
- package/public/app.js +1182 -379
- package/public/index.html +87 -22
- package/public/landing.html +1217 -870
- package/public/legal.html +51 -8
- package/public/styles.css +71 -16
- package/server/api/routes.js +220 -35
- package/server/auth/index.js +633 -340
- package/server/billing/yookassa.js +1 -0
- package/server/brokers/index.js +1369 -645
- package/server/config.js +6 -4
- package/server/data/moex.js +1 -0
- package/server/db.js +69 -4
- package/server/hub.js +1 -0
- package/server/index.js +10 -2
- package/server/llm/client.js +1 -0
- package/server/llm/providers.js +50 -3
- package/server/model/dataset.js +362 -352
- package/server/model/forecast.js +202 -37
- package/server/model/linalg.js +1 -0
- package/server/model/live.js +476 -486
- package/server/model/metrics.js +1 -0
- package/server/model/models.js +31 -21
- package/server/model/profiles.js +1 -0
- package/server/model/research.js +128 -205
- package/server/model/vocab.js +1 -0
- package/server/news/index.js +1 -0
- package/server/notify/index.js +304 -168
- package/server/params-meta.js +22 -26
- package/server/settings.js +1 -0
- package/server/strategist/analytics.js +2 -1
- package/server/strategist/index.js +7 -7
- package/server/strategist/tools.js +2 -1
- package/server/util.js +1 -0
- package/server/model/gpu-worker.html +0 -11
- package/server/model/gpu-worker.js +0 -60
- package/server/model/tf-node.js +0 -26
- package/server/model/transformer-core.js +0 -330
- package/server/model/transformer-gpu.js +0 -221
- package/server/model/transformer-pool.js +0 -200
- package/server/model/transformer-worker.js +0 -28
- package/server/model/transformer.js +0 -57
package/server/model/metrics.js
CHANGED
package/server/model/models.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// Copyright (c) 2026 Roman A. Perepelkin. All rights reserved. Proprietary software.
|
|
1
2
|
import { eigenSym, ridgeSolve, matrix, spearman, kmeans } from './linalg.js';
|
|
2
3
|
import { BAR_INTERVAL } from './dataset.js';
|
|
3
4
|
|
|
@@ -19,11 +20,13 @@ for (const k of KINDS) for (const s of SCALES) for (const b of BETAS) HEADS.push
|
|
|
19
20
|
// trainStart..testStart — окно обучения; testStart..testEnd — месяц прогноза.
|
|
20
21
|
// Все массивы «по времени»: [u*N + i], u = t - lo.
|
|
21
22
|
// textWeight (0..1) — вес «текстовой» близости по профилям бизнеса; profiles — Map(тикер → 20 чисел), загружается один раз на исследование.
|
|
22
|
-
export function buildFold(ds, { trainStart, testStart, testEnd, H, embedDim, textWeight = 0, profiles = null }) {
|
|
23
|
+
export function buildFold(ds, { trainStart, testStart, testEnd, H, embedDim, textWeight = 0, profiles = null, multiHorizon = false }) {
|
|
23
24
|
const { tokens, mret, T } = ds;
|
|
24
25
|
const N = tokens.length;
|
|
26
|
+
const Hfast = Math.max(2, Math.round(H * 0.6));
|
|
27
|
+
const Hslow = Math.round(H * 1.4);
|
|
25
28
|
const lo = Math.max(1, trainStart - FEATURE_WARMUP);
|
|
26
|
-
const hi = Math.min(T, testEnd + H + 2);
|
|
29
|
+
const hi = Math.min(T, testEnd + (multiHorizon ? Hslow : H) + 2);
|
|
27
30
|
const W = hi - lo;
|
|
28
31
|
|
|
29
32
|
// чувствительность к рынку и обычный размах — только по окну обучения
|
|
@@ -80,20 +83,35 @@ export function buildFold(ds, { trainStart, testStart, testEnd, H, embedDim, tex
|
|
|
80
83
|
}
|
|
81
84
|
});
|
|
82
85
|
// цель: остаточное (без рынка) движение, которое реально можно получить: решение на закрытии свечи t,
|
|
83
|
-
// вход по цене открытия t+1, выход по цене открытия t+1+H
|
|
86
|
+
// вход по цене открытия t+1, выход по цене открытия t+1+H (в режиме multiHorizon — взвешенная траектория 0.6H / 1.0H / 1.4H)
|
|
84
87
|
const { mopen } = ds;
|
|
85
88
|
const yz = new Float64Array(W * N), yraw = new Float64Array(W * N), yok = new Uint8Array(W);
|
|
89
|
+
const invFast = 1 / Math.sqrt(Hfast), invMid = 1 / Math.sqrt(H), invSlow = 1 / Math.sqrt(Hslow);
|
|
86
90
|
for (let u = 0; u + 1 + H < W; u++) {
|
|
87
91
|
const t = lo + u;
|
|
88
92
|
const ma = mopen[t + 1], mb = mopen[t + 1 + H];
|
|
89
93
|
if (!(ma > 0 && mb > 0)) continue;
|
|
90
94
|
yok[u] = 1;
|
|
91
|
-
const
|
|
95
|
+
const mMid = Math.log(mb / ma);
|
|
96
|
+
const hasMulti = multiHorizon && (t + 1 + Hslow < T) && mopen[t + 1 + Hfast] > 0 && mopen[t + 1 + Hslow] > 0;
|
|
97
|
+
const mFast = hasMulti ? Math.log(mopen[t + 1 + Hfast] / ma) : 0;
|
|
98
|
+
const mSlow = hasMulti ? Math.log(mopen[t + 1 + Hslow] / ma) : 0;
|
|
92
99
|
for (let i = 0; i < N; i++) {
|
|
93
|
-
const
|
|
94
|
-
const
|
|
95
|
-
|
|
96
|
-
|
|
100
|
+
const opn = tokens[i].open;
|
|
101
|
+
const a = opn[t + 1], b = opn[t + 1 + H];
|
|
102
|
+
const rMid = a > 0 && b > 0 ? Math.log(b / a) - beta[i] * mMid : 0;
|
|
103
|
+
yraw[u * N + i] = rMid;
|
|
104
|
+
const sig = sigma[i];
|
|
105
|
+
const zMid = Math.max(-8, Math.min(8, (rMid / sig) * invMid));
|
|
106
|
+
if (hasMulti && a > 0 && opn[t + 1 + Hfast] > 0 && opn[t + 1 + Hslow] > 0) {
|
|
107
|
+
const rFast = Math.log(opn[t + 1 + Hfast] / a) - beta[i] * mFast;
|
|
108
|
+
const rSlow = Math.log(opn[t + 1 + Hslow] / a) - beta[i] * mSlow;
|
|
109
|
+
const zFast = Math.max(-8, Math.min(8, (rFast / sig) * invFast));
|
|
110
|
+
const zSlow = Math.max(-8, Math.min(8, (rSlow / sig) * invSlow));
|
|
111
|
+
yz[u * N + i] = 0.25 * zFast + 0.50 * zMid + 0.25 * zSlow;
|
|
112
|
+
} else {
|
|
113
|
+
yz[u * N + i] = zMid;
|
|
114
|
+
}
|
|
97
115
|
}
|
|
98
116
|
}
|
|
99
117
|
|
|
@@ -196,7 +214,7 @@ export function buildFold(ds, { trainStart, testStart, testEnd, H, embedDim, tex
|
|
|
196
214
|
if (list.length) macro = { list };
|
|
197
215
|
}
|
|
198
216
|
|
|
199
|
-
return { N, lo, hi, W, trainStart, testStart, testEnd, H, beta, sigma, z, has, liq, X, yz, yraw, yok, emb, embN, cos, eigenvalues: eigVals, macro };
|
|
217
|
+
return { N, lo, hi, W, trainStart, testStart, testEnd, H, Hfast, Hslow, multiHorizon, beta, sigma, z, has, liq, X, yz, yraw, yok, emb, embN, cos, eigenvalues: eigVals, macro };
|
|
200
218
|
}
|
|
201
219
|
|
|
202
220
|
// Ликвидная акция: сделки хотя бы в 15 из последних 20 свечей
|
|
@@ -205,7 +223,8 @@ export const LIQ_MIN = 15;
|
|
|
205
223
|
// В обучение — только моменты, цель которых целиком лежит в окне обучения (без заглядывания в месяц прогноза)
|
|
206
224
|
export const trainUs = (f) => {
|
|
207
225
|
const us = [];
|
|
208
|
-
|
|
226
|
+
const maxH = f.multiHorizon ? f.Hslow : f.H;
|
|
227
|
+
for (let t = f.trainStart + FEATURE_WARMUP; t < f.testStart - maxH - 1; t++) { const u = t - f.lo; if (f.yok[u]) us.push(u); }
|
|
209
228
|
return us;
|
|
210
229
|
};
|
|
211
230
|
|
|
@@ -386,19 +405,10 @@ export const MODELS = {
|
|
|
386
405
|
inertia: { label: 'Своя инерция', fit: fitInertia, predict: predictInertia },
|
|
387
406
|
leadlag: { label: 'Кто за кем ходит', fit: fitLeadLag, predict: (m, f, u) => predictLin(m.W, f, u) },
|
|
388
407
|
attention: { label: 'Внимание через карту', fit: fitAttention, predict: predictAttention },
|
|
389
|
-
// ступень 3: нейросеть с вниманием между акциями (tfjs грузится только при первом обучении);
|
|
390
|
-
// fit асинхронный, после использования модель нужно освободить: model.dispose()
|
|
391
|
-
transformer: {
|
|
392
|
-
label: 'Трансформер',
|
|
393
|
-
fit: async (f, opts) => (await import('./transformer.js')).fitTransformer(f, opts),
|
|
394
|
-
predict: (m, f, u) => m.predictOne(m, f, u),
|
|
395
|
-
predictMany: (m, f, us) => m.predictMany(m, f, us),
|
|
396
|
-
heavy: true,
|
|
397
|
-
},
|
|
398
408
|
};
|
|
399
409
|
|
|
400
|
-
// Какие модели обучать: три базовые
|
|
401
|
-
export const modelNames = (
|
|
410
|
+
// Какие модели обучать: три базовые модели
|
|
411
|
+
export const modelNames = () => Object.keys(MODELS);
|
|
402
412
|
|
|
403
413
|
// Объяснение прогноза «внимания»: вклад каждого соседа в прогноз акции j
|
|
404
414
|
export function explainAttention(m, f, u, j, top = 3) {
|
package/server/model/profiles.js
CHANGED