neuroalpha 0.5.19 → 0.5.20
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/package.json +1 -1
- package/public/admin.html +2 -1
- package/public/app.js +10 -9
- package/public/landing.html +1207 -1499
- package/public/legal.html +6 -5
- package/server/api/routes.js +15 -3
- package/server/auth/index.js +23 -9
- package/server/brokers/index.js +4 -3
- package/server/model/edge.js +34 -1
- package/server/model/forecast.js +9 -6
- package/server/model/research.js +9 -4
- package/server/security.js +4 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "neuroalpha",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.20",
|
|
4
4
|
"description": "НейроАльфа — ИИ-автопилот для рынка акций Мосбиржи: эмбеддинги акций, самообучение правил, коннекторы Т-Банк / БКС / Финам / Алор и боты Telegram / MAX",
|
|
5
5
|
"author": "Roman A. Perepelkin",
|
|
6
6
|
"license": "UNLICENSED",
|
package/public/admin.html
CHANGED
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
--yellow: #eab308;
|
|
21
21
|
}
|
|
22
22
|
* { box-sizing: border-box; }
|
|
23
|
+
[hidden] { display: none !important; }
|
|
23
24
|
body { margin: 0; background: var(--bg); color: var(--text); font: 14px/1.55 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; }
|
|
24
25
|
a, a:visited { color: var(--accent); text-decoration: none; }
|
|
25
26
|
a.brand, a.brand:visited { color: var(--text); }
|
|
@@ -197,7 +198,7 @@
|
|
|
197
198
|
<section data-pane="oauth" hidden>
|
|
198
199
|
<div class="card">
|
|
199
200
|
<h2>Провайдеры быстрого входа (OAuth 2.0)</h2>
|
|
200
|
-
<p class="sub">Настройка кнопок входа в 1 клик на витрине <code>/landing</code>. Скопируйте Callback URL в настройки соответствующего провайдера.</p>
|
|
201
|
+
<p class="sub">Настройка кнопок входа в 1 клик на витрине <code>/landing</code>. Иностранные провайдеры (Google) автоматически скрываются для пользователей из российского сегмента в соответствии с ФЗ № 406-ФЗ / 149-ФЗ. Скопируйте Callback URL в настройки соответствующего провайдера.</p>
|
|
201
202
|
<form id="form-oauth" class="grid-form">
|
|
202
203
|
<div id="oauth-rows" class="grid-form"></div>
|
|
203
204
|
<div><button type="submit" class="primary">Сохранить OAuth-провайдеров</button></div>
|
package/public/app.js
CHANGED
|
@@ -1089,10 +1089,11 @@ async function loadForecast(force, silent = false) {
|
|
|
1089
1089
|
const thrVal = isShort
|
|
1090
1090
|
? (r.shortThresholdPct ?? (isT1 ? shortThr : shortThrT2))
|
|
1091
1091
|
: (r.buyThresholdPct ?? (isT1 ? buyThr : buyThrT2));
|
|
1092
|
-
const
|
|
1093
|
-
const
|
|
1094
|
-
|
|
1095
|
-
|
|
1092
|
+
const thrFmt = Number(thrVal || 0).toLocaleString('ru-RU', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
|
|
1093
|
+
const thrText = isShort ? `−${thrFmt}%` : `+${thrFmt}%`;
|
|
1094
|
+
const multStr = r.edgeMult ? `×${fmtNum(r.edgeMult, 2)}` : (isT1 ? '×1,00' : '×1,20');
|
|
1095
|
+
const sigStr = r.sigmaPct ? `, волатильность 10-мин свечи σ = ${fmtNum(r.sigmaPct, 2)}%` : '';
|
|
1096
|
+
const tierDesc = `${isT1 ? '1-й эшелон' : '2–3-й эшелон'}, индивидуальный множитель ${multStr}${sigStr}`;
|
|
1096
1097
|
const thrTitle = isShort
|
|
1097
1098
|
? `Индивидуальный порог шорта для ${r.symbol}: ниже −${fmtNum(thrVal, 2)}% (${tierDesc})`
|
|
1098
1099
|
: `Индивидуальный порог покупки для ${r.symbol}: выше ${fmtPct(thrVal, 2)} (${tierDesc})`;
|
|
@@ -1116,7 +1117,7 @@ async function loadForecast(force, silent = false) {
|
|
|
1116
1117
|
const fcTable = (title, rows, extraStyle = '', side = 'long') => `<table class="fc-table" style="table-layout:fixed;width:100%${extraStyle}">${colgroup}<thead><tr><th>${title}</th><th class="num">Цена</th><th class="num">Ожидание</th><th class="num">Динамика</th><th style="text-align:center">Сигнал</th><th>Под влиянием</th><th class="num" title="Индивидуальный порог входа с учётом ликвидности бумаги (1-й или 2–3-й эшелон) и тренда индекса">Порог</th></tr></thead><tbody>${rows.map((r) => row(r, side)).join('')}</tbody></table>`;
|
|
1117
1118
|
box.innerHTML = `<div style="overflow-x:auto">${fcTable('Сильнее рынка', shownRows.slice(0, 6), '', 'long')}
|
|
1118
1119
|
${fcTable('Слабее рынка', shortRows, ';margin-top:14px', 'short')}</div>
|
|
1119
|
-
<p class="muted small">Ожидание — движение относительно рынка в целом (авто-пересчёт каждые 15 сек по живым ценам Мосбиржи).
|
|
1120
|
+
<p class="muted small">Ожидание — движение относительно рынка в целом (авто-пересчёт каждые 15 сек по живым ценам Мосбиржи). Точный индивидуальный порог каждой акции рассчитывается в колонке <b>«Порог»</b> с учётом её ликвидности (оборота торгов), волатильности свечи и тренда индекса. <span style="color:var(--blocked-fg)">Розовым</span> отмечены строки, по которым вход запрещён (запрет шорта у брокера, отсечка дивидендов, фильтр новостей или экстремальная свеча ±4,5%).</p>`;
|
|
1120
1121
|
if (state.brokers?.accounts?.length) renderBrokers();
|
|
1121
1122
|
} catch (e) {
|
|
1122
1123
|
if (!silent) box.innerHTML = `<span class="neg">Не получилось: ${esc(e.message)}</span>`;
|
|
@@ -3703,10 +3704,10 @@ async function renderCloudPane() {
|
|
|
3703
3704
|
Брокерских счетов: до <b>${u.limits?.maxBrokerAccounts ?? 0}</b> (${capLimStr}) · Режим торговли: <b>${dirLimStr}</b>${u.planUntil ? ` · Оплачен до ${fmtDate(u.planUntil)}` : ''}.
|
|
3704
3705
|
</div>
|
|
3705
3706
|
</div>
|
|
3706
|
-
|
|
3707
|
-
|
|
3708
|
-
|
|
3709
|
-
</div
|
|
3707
|
+
<div class="row-gap" style="flex-wrap:wrap">
|
|
3708
|
+
${me.cloudMode ? `<button type="button" id="btn-cloud-verify">Проверить оплату</button>` : ''}
|
|
3709
|
+
${(me.cloudMode || me.role === 'instance' || !isDefaultLocal) ? `<button type="button" id="btn-cloud-logout">Выйти</button>` : ''}
|
|
3710
|
+
</div>
|
|
3710
3711
|
</div>
|
|
3711
3712
|
<div class="srow sblock">
|
|
3712
3713
|
<div class="stxt">
|