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/public/landing.html
CHANGED
|
@@ -1,870 +1,1217 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
<
|
|
4
|
-
|
|
5
|
-
<meta
|
|
6
|
-
<
|
|
7
|
-
<
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
--
|
|
11
|
-
--
|
|
12
|
-
--panel
|
|
13
|
-
--
|
|
14
|
-
--line
|
|
15
|
-
--
|
|
16
|
-
--
|
|
17
|
-
--
|
|
18
|
-
--
|
|
19
|
-
--
|
|
20
|
-
--
|
|
21
|
-
--
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
radial-gradient(
|
|
41
|
-
radial-gradient(
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
linear-gradient(to
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
.
|
|
61
|
-
.brand-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
.nav-links
|
|
69
|
-
.nav-links a
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
.ticker-item
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
.btn.
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
.btn.
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
.
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
.hero-
|
|
137
|
-
.
|
|
138
|
-
.mini-
|
|
139
|
-
.mini-stat .
|
|
140
|
-
.
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
.
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
border
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
.
|
|
153
|
-
.dots
|
|
154
|
-
.
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
.sig-bar
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
.tag-pill
|
|
163
|
-
.tag-pill.
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
border
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
.bot-
|
|
176
|
-
.bot-
|
|
177
|
-
.bot-btn
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
.sec-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
.
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
.bcard:
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
.bcard
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
.
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
.sc-
|
|
222
|
-
.sc-
|
|
223
|
-
.sc-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
.period-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
.
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
.
|
|
266
|
-
.
|
|
267
|
-
.
|
|
268
|
-
.
|
|
269
|
-
.
|
|
270
|
-
.
|
|
271
|
-
|
|
272
|
-
}
|
|
273
|
-
.
|
|
274
|
-
.
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
.
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
}
|
|
286
|
-
.
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
<
|
|
329
|
-
<
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
<div>
|
|
337
|
-
<
|
|
338
|
-
<
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
</
|
|
350
|
-
|
|
351
|
-
<
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
<
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
</div>
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
<div
|
|
387
|
-
|
|
388
|
-
<div class="
|
|
389
|
-
<
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
<div class="
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
<
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
<
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
<div class="
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
<
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
<
|
|
483
|
-
<
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
<
|
|
488
|
-
<
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
<
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
<div class="
|
|
512
|
-
<
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
<
|
|
519
|
-
</div>
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
</
|
|
533
|
-
<button
|
|
534
|
-
</div>
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
<
|
|
539
|
-
<div class="
|
|
540
|
-
<
|
|
541
|
-
|
|
542
|
-
<li
|
|
543
|
-
<li
|
|
544
|
-
<li
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
<
|
|
672
|
-
<
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
</
|
|
677
|
-
<
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
<
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
}
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
</
|
|
1
|
+
<!-- Copyright (c) 2026 Roman A. Perepelkin. All rights reserved. Proprietary software. -->
|
|
2
|
+
<!doctype html>
|
|
3
|
+
<html lang="ru">
|
|
4
|
+
<head>
|
|
5
|
+
<meta charset="utf-8">
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
7
|
+
<title>НейроАльфа — ИИ-автопилот для рынка акций</title>
|
|
8
|
+
<style>
|
|
9
|
+
:root {
|
|
10
|
+
--bg: #060911;
|
|
11
|
+
--bg2: #0b101d;
|
|
12
|
+
--panel: rgba(17, 24, 39, 0.72);
|
|
13
|
+
--panel-solid: #111827;
|
|
14
|
+
--line: rgba(255, 255, 255, 0.08);
|
|
15
|
+
--line-bright: rgba(96, 165, 250, 0.38);
|
|
16
|
+
--text: #f8fafc;
|
|
17
|
+
--muted: #94a3b8;
|
|
18
|
+
--accent: #3b82f6;
|
|
19
|
+
--accent2: #6366f1;
|
|
20
|
+
--cyan: #06b6d4;
|
|
21
|
+
--green: #10b981;
|
|
22
|
+
--red: #f43f5e;
|
|
23
|
+
}
|
|
24
|
+
* { box-sizing: border-box; }
|
|
25
|
+
html { scroll-behavior: smooth; }
|
|
26
|
+
body {
|
|
27
|
+
margin: 0;
|
|
28
|
+
background: var(--bg);
|
|
29
|
+
color: var(--text);
|
|
30
|
+
font: 16px/1.6 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
|
|
31
|
+
overflow-x: hidden;
|
|
32
|
+
}
|
|
33
|
+
a { color: inherit; text-decoration: none; }
|
|
34
|
+
.wrap { max-width: 1200px; margin: 0 auto; padding: 0 24px; position: relative; z-index: 2; }
|
|
35
|
+
|
|
36
|
+
/* ---------- Фоновое свечение и сетка ---------- */
|
|
37
|
+
.ambient {
|
|
38
|
+
position: fixed; inset: 0; pointer-events: none; z-index: 0;
|
|
39
|
+
background:
|
|
40
|
+
radial-gradient(650px circle at 18% 12%, rgba(59, 130, 246, 0.16), transparent 60%),
|
|
41
|
+
radial-gradient(600px circle at 82% 22%, rgba(99, 102, 241, 0.14), transparent 60%),
|
|
42
|
+
radial-gradient(700px circle at 50% 85%, rgba(6, 182, 212, 0.09), transparent 65%);
|
|
43
|
+
}
|
|
44
|
+
.grid-bg {
|
|
45
|
+
position: fixed; inset: 0; pointer-events: none; z-index: 0;
|
|
46
|
+
background-image:
|
|
47
|
+
linear-gradient(to right, rgba(255,255,255,0.025) 1px, transparent 1px),
|
|
48
|
+
linear-gradient(to bottom, rgba(255,255,255,0.025) 1px, transparent 1px);
|
|
49
|
+
background-size: 48px 48px;
|
|
50
|
+
mask-image: radial-gradient(ellipse at 50% 30%, #000 35%, transparent 80%);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/* ---------- Шапка и бегущая строка ---------- */
|
|
54
|
+
header {
|
|
55
|
+
position: sticky; top: 0; z-index: 40;
|
|
56
|
+
background: rgba(6, 9, 17, 0.78);
|
|
57
|
+
backdrop-filter: blur(16px);
|
|
58
|
+
border-bottom: 1px solid var(--line);
|
|
59
|
+
}
|
|
60
|
+
.nav { height: 68px; display: flex; align-items: center; justify-content: space-between; gap: 16px; }
|
|
61
|
+
.brand { display: flex; align-items: center; gap: 10px; font-weight: 800; font-size: 20px; letter-spacing: -0.3px; }
|
|
62
|
+
.brand-icon {
|
|
63
|
+
width: 34px; height: 34px; border-radius: 9px;
|
|
64
|
+
background: linear-gradient(135deg, var(--accent), var(--accent2));
|
|
65
|
+
display: inline-flex; align-items: center; justify-content: center;
|
|
66
|
+
color: #fff; font-size: 18px; box-shadow: 0 4px 18px rgba(59, 130, 246, 0.4);
|
|
67
|
+
}
|
|
68
|
+
.nav-links { display: flex; gap: 26px; font-size: 14.5px; color: var(--muted); font-weight: 500; }
|
|
69
|
+
.nav-links a { transition: color .15s; }
|
|
70
|
+
.nav-links a:hover { color: #fff; }
|
|
71
|
+
@media (max-width: 820px) { .nav-links { display: none; } }
|
|
72
|
+
|
|
73
|
+
.ticker-wrap {
|
|
74
|
+
border-bottom: 1px solid var(--line);
|
|
75
|
+
background: rgba(11, 16, 29, 0.65);
|
|
76
|
+
overflow: hidden; white-space: nowrap; height: 36px; display: flex; align-items: center;
|
|
77
|
+
position: relative; z-index: 2;
|
|
78
|
+
}
|
|
79
|
+
.ticker-track {
|
|
80
|
+
display: inline-flex; gap: 32px;
|
|
81
|
+
animation: tickerMove 38s linear infinite;
|
|
82
|
+
font-size: 12.5px; color: var(--muted);
|
|
83
|
+
}
|
|
84
|
+
.ticker-item { display: inline-flex; align-items: center; gap: 6px; }
|
|
85
|
+
.ticker-item b { color: var(--text); font-weight: 600; }
|
|
86
|
+
@keyframes tickerMove { 0% { transform: translateX(0); } 100% { transform: translateX(-50%); } }
|
|
87
|
+
|
|
88
|
+
/* ---------- Кнопки ---------- */
|
|
89
|
+
.btn {
|
|
90
|
+
display: inline-flex; align-items: center; justify-content: center; gap: 8px;
|
|
91
|
+
padding: 11px 22px; border-radius: 10px; border: 1px solid var(--line);
|
|
92
|
+
background: rgba(255, 255, 255, 0.04); color: var(--text);
|
|
93
|
+
font-weight: 600; font-size: 14.5px; cursor: pointer;
|
|
94
|
+
transition: transform .18s ease, border-color .18s ease, box-shadow .18s ease, background .18s ease;
|
|
95
|
+
}
|
|
96
|
+
.btn:hover { border-color: var(--line-bright); background: rgba(255, 255, 255, 0.08); transform: translateY(-1px); }
|
|
97
|
+
.btn.primary {
|
|
98
|
+
background: linear-gradient(135deg, var(--accent), var(--accent2));
|
|
99
|
+
border-color: transparent; color: #fff;
|
|
100
|
+
box-shadow: 0 8px 26px -4px rgba(59, 130, 246, 0.55);
|
|
101
|
+
}
|
|
102
|
+
.btn.primary:hover { box-shadow: 0 12px 32px -2px rgba(99, 102, 241, 0.7); transform: translateY(-2px); }
|
|
103
|
+
.btn.lg { padding: 14px 28px; font-size: 15.5px; border-radius: 12px; }
|
|
104
|
+
|
|
105
|
+
/* ---------- Hero ---------- */
|
|
106
|
+
.hero { position: relative; padding: 64px 0 56px; overflow: hidden; }
|
|
107
|
+
#hero-canvas {
|
|
108
|
+
position: absolute; inset: 0; width: 100%; height: 100%;
|
|
109
|
+
pointer-events: none; z-index: 1; opacity: 0.55;
|
|
110
|
+
}
|
|
111
|
+
.hero-grid {
|
|
112
|
+
display: grid; grid-template-columns: 1.12fr 0.88fr; gap: 44px; align-items: center;
|
|
113
|
+
position: relative; z-index: 2;
|
|
114
|
+
}
|
|
115
|
+
@media (max-width: 960px) { .hero-grid { grid-template-columns: 1fr; } }
|
|
116
|
+
.pill-badge {
|
|
117
|
+
display: inline-flex; align-items: center; gap: 8px;
|
|
118
|
+
padding: 6px 14px; border-radius: 999px;
|
|
119
|
+
background: rgba(59, 130, 246, 0.12); border: 1px solid rgba(59, 130, 246, 0.3);
|
|
120
|
+
color: #93c5fd; font-size: 13px; font-weight: 500; margin-bottom: 20px;
|
|
121
|
+
}
|
|
122
|
+
.pulse-dot {
|
|
123
|
+
width: 8px; height: 8px; border-radius: 50%; background: var(--green);
|
|
124
|
+
box-shadow: 0 0 10px var(--green); animation: pulseDot 2s infinite;
|
|
125
|
+
}
|
|
126
|
+
@keyframes pulseDot { 0%, 100% { opacity: 1; transform: scale(1); } 50% { opacity: .45; transform: scale(1.25); } }
|
|
127
|
+
|
|
128
|
+
h1 {
|
|
129
|
+
font-size: clamp(36px, 4.6vw, 56px); line-height: 1.08; margin: 0 0 20px;
|
|
130
|
+
letter-spacing: -1.4px; font-weight: 800;
|
|
131
|
+
}
|
|
132
|
+
.grad-text {
|
|
133
|
+
background: linear-gradient(135deg, #ffffff 20%, #93c5fd 65%, #818cf8 100%);
|
|
134
|
+
-webkit-background-clip: text; -webkit-text-fill-color: transparent;
|
|
135
|
+
}
|
|
136
|
+
.hero-sub { font-size: 18px; color: var(--muted); margin: 0 0 30px; max-width: 600px; line-height: 1.6; }
|
|
137
|
+
.hero-actions { display: flex; gap: 14px; flex-wrap: wrap; margin-bottom: 36px; }
|
|
138
|
+
.mini-stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; border-top: 1px solid var(--line); padding-top: 24px; }
|
|
139
|
+
.mini-stat .num { font-size: 26px; font-weight: 800; letter-spacing: -0.5px; }
|
|
140
|
+
.mini-stat .lbl { font-size: 12.5px; color: var(--muted); line-height: 1.35; margin-top: 2px; }
|
|
141
|
+
.pos { color: var(--green); } .neg { color: var(--red); }
|
|
142
|
+
|
|
143
|
+
/* ---------- Живой макет терминала и мессенджера в Hero ---------- */
|
|
144
|
+
.mockup-stack { position: relative; }
|
|
145
|
+
.term-card {
|
|
146
|
+
background: linear-gradient(180deg, rgba(23, 32, 52, 0.86), rgba(13, 18, 30, 0.92));
|
|
147
|
+
border: 1px solid rgba(255, 255, 255, 0.12);
|
|
148
|
+
border-radius: 16px; padding: 18px 20px;
|
|
149
|
+
backdrop-filter: blur(20px);
|
|
150
|
+
box-shadow: 0 24px 60px rgba(0, 0, 0, 0.65), 0 0 40px rgba(59, 130, 246, 0.12);
|
|
151
|
+
}
|
|
152
|
+
.term-top { display: flex; justify-content: space-between; align-items: center; margin-bottom: 14px; padding-bottom: 10px; border-bottom: 1px solid var(--line); font-size: 12.5px; }
|
|
153
|
+
.dots { display: flex; gap: 6px; }
|
|
154
|
+
.dots i { width: 9px; height: 9px; border-radius: 50%; display: inline-block; }
|
|
155
|
+
.sig-row {
|
|
156
|
+
display: grid; grid-template-columns: 70px 1fr 68px 72px; align-items: center; gap: 10px;
|
|
157
|
+
padding: 8px 0; border-bottom: 1px solid rgba(255,255,255,0.05); font-size: 13px;
|
|
158
|
+
}
|
|
159
|
+
.sig-bar { height: 6px; background: rgba(255,255,255,0.06); border-radius: 999px; overflow: hidden; }
|
|
160
|
+
.sig-bar div { height: 100%; border-radius: 999px; background: linear-gradient(90deg, var(--accent), var(--green)); animation: barGrow 2.4s ease-out forwards; }
|
|
161
|
+
@keyframes barGrow { from { width: 0; } }
|
|
162
|
+
.tag-pill { display: inline-block; padding: 2px 8px; border-radius: 999px; font-size: 11px; font-weight: 600; text-align: center; }
|
|
163
|
+
.tag-pill.buy { background: rgba(16, 185, 129, 0.15); color: var(--green); border: 1px solid rgba(16, 185, 129, 0.35); }
|
|
164
|
+
.tag-pill.quar { background: rgba(244, 63, 94, 0.14); color: var(--red); border: 1px solid rgba(244, 63, 94, 0.3); }
|
|
165
|
+
|
|
166
|
+
.bot-float {
|
|
167
|
+
margin-top: 14px;
|
|
168
|
+
background: linear-gradient(135deg, rgba(30, 41, 59, 0.95), rgba(15, 23, 42, 0.98));
|
|
169
|
+
border: 1px solid var(--line-bright);
|
|
170
|
+
border-radius: 14px; padding: 14px 16px;
|
|
171
|
+
box-shadow: 0 16px 40px rgba(0, 0, 0, 0.55);
|
|
172
|
+
animation: floatY 5s ease-in-out infinite;
|
|
173
|
+
}
|
|
174
|
+
@keyframes floatY { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-5px); } }
|
|
175
|
+
.bot-head { display: flex; justify-content: space-between; align-items: center; font-size: 12px; color: #93c5fd; margin-bottom: 6px; font-weight: 600; }
|
|
176
|
+
.bot-btns { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-top: 10px; }
|
|
177
|
+
.bot-btn { padding: 7px 10px; border-radius: 8px; font-size: 12.5px; font-weight: 600; text-align: center; border: 1px solid var(--line); }
|
|
178
|
+
.bot-btn.ok { background: rgba(16, 185, 129, 0.18); border-color: rgba(16, 185, 129, 0.45); color: #34d399; }
|
|
179
|
+
|
|
180
|
+
/* ---------- Секции и Bento-карточки ---------- */
|
|
181
|
+
section { padding: 72px 0; position: relative; z-index: 2; }
|
|
182
|
+
.sec-head { text-align: center; max-width: 720px; margin: 0 auto 44px; }
|
|
183
|
+
.sec-tag { color: #60a5fa; font-size: 13px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; margin-bottom: 8px; }
|
|
184
|
+
h2 { font-size: clamp(26px, 3.5vw, 38px); margin: 0 0 12px; letter-spacing: -0.8px; line-height: 1.18; }
|
|
185
|
+
.sec-sub { color: var(--muted); margin: 0; font-size: 16.5px; }
|
|
186
|
+
|
|
187
|
+
.bento { display: grid; grid-template-columns: repeat(12, 1fr); gap: 20px; }
|
|
188
|
+
.bcard {
|
|
189
|
+
grid-column: span 4;
|
|
190
|
+
background: var(--panel); border: 1px solid var(--line);
|
|
191
|
+
border-radius: 16px; padding: 26px;
|
|
192
|
+
backdrop-filter: blur(12px);
|
|
193
|
+
transition: transform .22s ease, border-color .22s ease, box-shadow .22s ease;
|
|
194
|
+
position: relative; overflow: hidden;
|
|
195
|
+
}
|
|
196
|
+
.bcard.wide { grid-column: span 6; }
|
|
197
|
+
@media (max-width: 900px) { .bcard, .bcard.wide { grid-column: span 12; } }
|
|
198
|
+
.bcard:hover {
|
|
199
|
+
transform: translateY(-4px);
|
|
200
|
+
border-color: var(--line-bright);
|
|
201
|
+
box-shadow: 0 20px 44px -15px rgba(59, 130, 246, 0.25);
|
|
202
|
+
}
|
|
203
|
+
.bicon {
|
|
204
|
+
width: 42px; height: 42px; border-radius: 10px;
|
|
205
|
+
background: rgba(59, 130, 246, 0.14); border: 1px solid rgba(59, 130, 246, 0.3);
|
|
206
|
+
display: inline-flex; align-items: center; justify-content: center;
|
|
207
|
+
font-size: 20px; margin-bottom: 14px; color: #60a5fa;
|
|
208
|
+
}
|
|
209
|
+
.bcard h3 { margin: 0 0 8px; font-size: 19px; letter-spacing: -0.3px; }
|
|
210
|
+
.bcard p { margin: 0; color: var(--muted); font-size: 14.5px; line-height: 1.55; }
|
|
211
|
+
|
|
212
|
+
/* ---------- Живая витрина стратегий ---------- */
|
|
213
|
+
.showcase-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 22px; align-items: stretch; }
|
|
214
|
+
@media (max-width: 960px) { .showcase-grid { grid-template-columns: 1fr; } }
|
|
215
|
+
.sc-card {
|
|
216
|
+
background: var(--panel); border: 1px solid var(--line);
|
|
217
|
+
border-radius: 18px; padding: 24px;
|
|
218
|
+
display: flex; flex-direction: column; gap: 14px;
|
|
219
|
+
transition: border-color .2s, transform .2s;
|
|
220
|
+
}
|
|
221
|
+
.sc-card:hover { border-color: var(--line-bright); transform: translateY(-3px); }
|
|
222
|
+
.sc-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 12px; }
|
|
223
|
+
.sc-ret { font-size: 30px; font-weight: 800; letter-spacing: -0.8px; line-height: 1; }
|
|
224
|
+
.sc-kpis { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; background: rgba(0,0,0,0.28); border-radius: 10px; padding: 10px 12px; font-size: 12.5px; }
|
|
225
|
+
.sc-kpis b { display: block; font-size: 14.5px; color: var(--text); }
|
|
226
|
+
|
|
227
|
+
/* ---------- Тарифы ---------- */
|
|
228
|
+
.period-wrap { display: flex; justify-content: center; margin-bottom: 32px; }
|
|
229
|
+
.period-seg { display: inline-flex; background: var(--panel); border: 1px solid var(--line); border-radius: 12px; padding: 4px; gap: 4px; }
|
|
230
|
+
.period-seg button {
|
|
231
|
+
border: 0; background: transparent; color: var(--muted);
|
|
232
|
+
padding: 8px 18px; border-radius: 8px; cursor: pointer; font-weight: 600; font-size: 14px; transition: .15s;
|
|
233
|
+
}
|
|
234
|
+
.period-seg button.active { background: linear-gradient(135deg, var(--accent), var(--accent2)); color: #fff; }
|
|
235
|
+
.plans { display: grid; grid-template-columns: repeat(3, 1fr); gap: 22px; align-items: stretch; }
|
|
236
|
+
@media (max-width: 960px) { .plans { grid-template-columns: 1fr; } }
|
|
237
|
+
.plan {
|
|
238
|
+
background: var(--panel); border: 1px solid var(--line);
|
|
239
|
+
border-radius: 18px; padding: 30px 26px;
|
|
240
|
+
display: flex; flex-direction: column; position: relative;
|
|
241
|
+
transition: transform .2s, border-color .2s;
|
|
242
|
+
}
|
|
243
|
+
.plan:hover { transform: translateY(-4px); }
|
|
244
|
+
.plan.featured {
|
|
245
|
+
background: linear-gradient(180deg, rgba(30, 58, 138, 0.32), rgba(17, 24, 39, 0.88));
|
|
246
|
+
border-color: rgba(96, 165, 250, 0.55);
|
|
247
|
+
box-shadow: 0 20px 50px -12px rgba(37, 99, 235, 0.35);
|
|
248
|
+
}
|
|
249
|
+
.plan-vip-wide {
|
|
250
|
+
margin-top: 22px;
|
|
251
|
+
background: linear-gradient(135deg, rgba(120, 53, 15, 0.22), rgba(17, 24, 39, 0.94));
|
|
252
|
+
border: 1px solid rgba(245, 158, 11, 0.5);
|
|
253
|
+
border-radius: 18px; padding: 28px 32px;
|
|
254
|
+
display: grid; grid-template-columns: 1fr 1.3fr auto; gap: 28px; align-items: center;
|
|
255
|
+
position: relative;
|
|
256
|
+
box-shadow: 0 20px 50px -15px rgba(217, 119, 6, 0.25);
|
|
257
|
+
}
|
|
258
|
+
@media (max-width: 960px) { .plan-vip-wide { grid-template-columns: 1fr; } }
|
|
259
|
+
.pop-ribbon {
|
|
260
|
+
position: absolute; top: 14px; right: 16px;
|
|
261
|
+
background: linear-gradient(135deg, var(--accent), var(--accent2));
|
|
262
|
+
color: #fff; font-size: 11px; font-weight: 700; padding: 3px 10px; border-radius: 999px;
|
|
263
|
+
text-transform: uppercase; letter-spacing: 0.5px;
|
|
264
|
+
}
|
|
265
|
+
.plan h3, .plan-vip-wide h3 { margin: 0 0 4px; font-size: 21px; }
|
|
266
|
+
.plan-desc { font-size: 13.5px; color: var(--muted); margin-bottom: 14px; }
|
|
267
|
+
.price { font-size: 38px; font-weight: 800; margin: 6px 0 18px; letter-spacing: -1px; }
|
|
268
|
+
.price span { font-size: 14px; font-weight: 400; color: var(--muted); letter-spacing: 0; }
|
|
269
|
+
.plan ul, .plan-vip-wide ul { list-style: none; padding: 0; margin: 0 0 26px; font-size: 14.5px; color: #cbd5e1; flex: 1; }
|
|
270
|
+
.plan-vip-wide ul { margin: 0; display: grid; grid-template-columns: 1fr 1fr; gap: 10px 20px; }
|
|
271
|
+
@media (max-width: 720px) { .plan-vip-wide ul { grid-template-columns: 1fr; } }
|
|
272
|
+
.plan li, .plan-vip-wide li { margin: 10px 0; position: relative; padding-left: 22px; line-height: 1.45; }
|
|
273
|
+
.plan-vip-wide li { margin: 0; }
|
|
274
|
+
.plan li::before, .plan-vip-wide li::before { content: "✓"; color: var(--green); font-weight: 800; position: absolute; left: 0; top: 0; }
|
|
275
|
+
|
|
276
|
+
/* ---------- Анимация появления при прокрутке ---------- */
|
|
277
|
+
.reveal { opacity: 0; transform: translateY(22px); transition: opacity .6s ease, transform .6s ease; }
|
|
278
|
+
.reveal.in { opacity: 1; transform: translateY(0); }
|
|
279
|
+
|
|
280
|
+
footer { padding: 40px 0; border-top: 1px solid var(--line); color: var(--muted); font-size: 13px; position: relative; z-index: 2; }
|
|
281
|
+
.modal { position: fixed; inset: 0; background: rgba(3, 6, 12, 0.78); backdrop-filter: blur(8px); display: flex; align-items: center; justify-content: center; z-index: 100; padding: 16px; }
|
|
282
|
+
.modal[hidden] { display: none; }
|
|
283
|
+
.modal-box { background: var(--panel-solid); border: 1px solid var(--line-bright); border-radius: 16px; padding: 28px; width: 100%; max-width: 430px; box-shadow: 0 24px 60px #000a; }
|
|
284
|
+
.modal-box h3 { margin: 0 0 16px; font-size: 21px; }
|
|
285
|
+
.modal-box form { display: grid; gap: 12px; }
|
|
286
|
+
.modal-box input[type=email], .modal-box input[type=password], .modal-box input[name=name] {
|
|
287
|
+
width: 100%; padding: 11px 14px; border-radius: 10px; border: 1px solid var(--line); background: var(--bg); color: var(--text); font: inherit;
|
|
288
|
+
}
|
|
289
|
+
.err { color: var(--red); font-size: 13.5px; min-height: 18px; }
|
|
290
|
+
.cli-box {
|
|
291
|
+
background: #070b14; border: 1px solid var(--line-bright); border-radius: 14px; padding: 16px 20px;
|
|
292
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 14px; color: #e2e8f0;
|
|
293
|
+
display: flex; align-items: center; justify-content: space-between; gap: 14px; flex-wrap: wrap;
|
|
294
|
+
box-shadow: 0 14px 36px rgba(0, 0, 0, 0.5);
|
|
295
|
+
}
|
|
296
|
+
.cli-box code { color: #38bdf8; word-break: break-all; }
|
|
297
|
+
.cab-card {
|
|
298
|
+
background: linear-gradient(135deg, rgba(30, 58, 138, 0.28), rgba(15, 23, 42, 0.92));
|
|
299
|
+
border: 1px solid var(--line-bright); border-radius: 18px; padding: 26px 28px; margin-top: 28px;
|
|
300
|
+
box-shadow: 0 20px 50px rgba(0, 0, 0, 0.45);
|
|
301
|
+
}
|
|
302
|
+
.cab-grid { display: grid; grid-template-columns: 1.2fr 0.8fr; gap: 24px; align-items: center; }
|
|
303
|
+
@media (max-width: 860px) { .cab-grid { grid-template-columns: 1fr; } }
|
|
304
|
+
.key-pill {
|
|
305
|
+
display: inline-flex; align-items: center; gap: 10px; background: rgba(0, 0, 0, 0.45);
|
|
306
|
+
border: 1px solid var(--line); border-radius: 10px; padding: 8px 14px; font-family: monospace; font-size: 14px; color: #93c5fd;
|
|
307
|
+
}
|
|
308
|
+
.oauth-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 9px; margin-bottom: 14px; }
|
|
309
|
+
.oauth-btn {
|
|
310
|
+
display: inline-flex; align-items: center; justify-content: center; gap: 9px;
|
|
311
|
+
padding: 10px 12px; border-radius: 10px; border: 1px solid var(--line);
|
|
312
|
+
background: rgba(255, 255, 255, 0.04); color: var(--text); font-weight: 600; font-size: 13.5px;
|
|
313
|
+
cursor: pointer; transition: border-color .15s, background .15s, transform .15s;
|
|
314
|
+
}
|
|
315
|
+
.oauth-btn:hover { border-color: var(--line-bright); background: rgba(255, 255, 255, 0.09); transform: translateY(-1px); }
|
|
316
|
+
.oauth-btn.full { grid-column: span 2; }
|
|
317
|
+
.oauth-ico { width: 18px; height: 18px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; font-weight: 800; font-size: 11px; flex: none; }
|
|
318
|
+
.or-sep { display: flex; align-items: center; gap: 10px; color: var(--muted); font-size: 12px; margin: 4px 0 12px; }
|
|
319
|
+
.or-sep::before, .or-sep::after { content: ''; flex: 1; height: 1px; background: var(--line); }
|
|
320
|
+
</style>
|
|
321
|
+
</head>
|
|
322
|
+
<body>
|
|
323
|
+
<div class="ambient"></div>
|
|
324
|
+
<div class="grid-bg"></div>
|
|
325
|
+
|
|
326
|
+
<header>
|
|
327
|
+
<div class="wrap nav">
|
|
328
|
+
<a class="brand" href="/landing"><span class="brand-icon">◈</span><span>НейроАльфа</span></a>
|
|
329
|
+
<nav class="nav-links">
|
|
330
|
+
<a href="#showcase">Результаты</a>
|
|
331
|
+
<a href="#how">Технология</a>
|
|
332
|
+
<a href="#paas-sec">Как работает PaaS</a>
|
|
333
|
+
<a href="#brokers">Брокеры и мессенджеры</a>
|
|
334
|
+
<a href="#pricing">Тарифы</a>
|
|
335
|
+
</nav>
|
|
336
|
+
<div style="display:flex;gap:10px" id="nav-auth">
|
|
337
|
+
<button class="btn" id="btn-login-open">Войти</button>
|
|
338
|
+
<a class="btn primary" href="#pricing" id="btn-nav-cta">Открыть терминал →</a>
|
|
339
|
+
</div>
|
|
340
|
+
</div>
|
|
341
|
+
</header>
|
|
342
|
+
|
|
343
|
+
<div class="ticker-wrap">
|
|
344
|
+
<div class="ticker-track" id="ticker-track">
|
|
345
|
+
<span class="ticker-item"><b>SBER</b> <span class="pos">+0,92%</span> · импульс от финансового кластера</span>
|
|
346
|
+
<span class="ticker-item"><b>LKOH</b> <span class="pos">+0,74%</span> · переток за Brent и экспортёрами</span>
|
|
347
|
+
<span class="ticker-item"><b>YDEX</b> <span class="pos">+1,18%</span> · сильнее широкого рынка</span>
|
|
348
|
+
<span class="ticker-item"><b>PLZL</b> <span class="pos">+0,65%</span> · поддержка от макро-токена золота</span>
|
|
349
|
+
<span class="ticker-item"><b>TATN</b> <span class="pos">+0,58%</span> · влияние LKOH, ROSN</span>
|
|
350
|
+
<span class="ticker-item"><b>SGZH</b> <span class="neg">карантин</span> · отсеяна самообучением правил</span>
|
|
351
|
+
<span class="ticker-item"><b>NVTK</b> <span class="pos">+0,61%</span> · возврат к среднему по карте</span>
|
|
352
|
+
<span class="ticker-item"><b>SBER</b> <span class="pos">+0,92%</span> · импульс от финансового кластера</span>
|
|
353
|
+
<span class="ticker-item"><b>LKOH</b> <span class="pos">+0,74%</span> · переток за Brent и экспортёрами</span>
|
|
354
|
+
<span class="ticker-item"><b>YDEX</b> <span class="pos">+1,18%</span> · сильнее широкого рынка</span>
|
|
355
|
+
<span class="ticker-item"><b>PLZL</b> <span class="pos">+0,65%</span> · поддержка от макро-токена золота</span>
|
|
356
|
+
<span class="ticker-item"><b>TATN</b> <span class="pos">+0,58%</span> · влияние LKOH, ROSN</span>
|
|
357
|
+
<span class="ticker-item"><b>SGZH</b> <span class="neg">карантин</span> · отсеяна самообучением правил</span>
|
|
358
|
+
</div>
|
|
359
|
+
</div>
|
|
360
|
+
|
|
361
|
+
<div class="hero">
|
|
362
|
+
<canvas id="hero-canvas"></canvas>
|
|
363
|
+
<div class="wrap hero-grid">
|
|
364
|
+
<div>
|
|
365
|
+
<div class="pill-badge"><span class="pulse-dot"></span><span>Московская биржа · ~100 ликвидных акций · Т-Банк · БКС · Финам · Алор</span></div>
|
|
366
|
+
<h1><span class="grad-text">ИИ-автопилот,</span> который читает рынок акций как единый язык</h1>
|
|
367
|
+
<p class="hero-sub">Платформа находит опережающие волны капитала между связанными бумагами, сама адаптирует пороги под комиссию вашего брокера и присылает готовые заявки в <b>Telegram и MAX</b> с подтверждением в 1 клик.</p>
|
|
368
|
+
<div class="hero-actions">
|
|
369
|
+
<button class="btn primary lg" id="btn-hero-start">Попробовать бесплатно</button>
|
|
370
|
+
<a class="btn lg" href="#pricing">Выбрать тариф PaaS →</a>
|
|
371
|
+
</div>
|
|
372
|
+
<div class="mini-stats">
|
|
373
|
+
<div class="mini-stat"><div class="num pos">+95% … +422%</div><div class="lbl">на истории 2024–2026 против −23,6% у индекса Мосбиржи</div></div>
|
|
374
|
+
<div class="mini-stat"><div class="num pos">144 из 144</div><div class="lbl">недель подряд прогноз опережал случайный выбор</div></div>
|
|
375
|
+
<div class="mini-stat"><div class="num">1 клик</div><div class="lbl">подтверждение лимитных заявок в лотах из Telegram и MAX</div></div>
|
|
376
|
+
</div>
|
|
377
|
+
</div>
|
|
378
|
+
|
|
379
|
+
<div class="mockup-stack">
|
|
380
|
+
<div class="term-card">
|
|
381
|
+
<div class="term-top">
|
|
382
|
+
<div class="dots"><i style="background:#f43f5e"></i><i style="background:#f59e0b"></i><i style="background:#10b981"></i></div>
|
|
383
|
+
<span style="color:var(--muted)">НейроАльфа · Прогноз на 2 часа · Самообучение: вкл.</span>
|
|
384
|
+
<span class="pos" style="font-weight:700">● Live</span>
|
|
385
|
+
</div>
|
|
386
|
+
<div class="sig-row">
|
|
387
|
+
<b>LKOH</b>
|
|
388
|
+
<div class="sig-bar"><div style="width:88%"></div></div>
|
|
389
|
+
<span class="pos" style="text-align:right;font-weight:700">+0,84%</span>
|
|
390
|
+
<span class="tag-pill buy">купить</span>
|
|
391
|
+
</div>
|
|
392
|
+
<div class="sig-row">
|
|
393
|
+
<b>SBER</b>
|
|
394
|
+
<div class="sig-bar"><div style="width:79%"></div></div>
|
|
395
|
+
<span class="pos" style="text-align:right;font-weight:700">+0,71%</span>
|
|
396
|
+
<span class="tag-pill buy">купить</span>
|
|
397
|
+
</div>
|
|
398
|
+
<div class="sig-row">
|
|
399
|
+
<b>YDEX</b>
|
|
400
|
+
<div class="sig-bar"><div style="width:72%"></div></div>
|
|
401
|
+
<span class="pos" style="text-align:right;font-weight:700">+0,64%</span>
|
|
402
|
+
<span class="tag-pill buy">купить</span>
|
|
403
|
+
</div>
|
|
404
|
+
<div class="sig-row" style="border-bottom:0">
|
|
405
|
+
<b>SGZH</b>
|
|
406
|
+
<div class="sig-bar"><div style="width:25%;background:var(--red)"></div></div>
|
|
407
|
+
<span class="neg" style="text-align:right">−0,52%</span>
|
|
408
|
+
<span class="tag-pill quar">карантин</span>
|
|
409
|
+
</div>
|
|
410
|
+
</div>
|
|
411
|
+
|
|
412
|
+
<div class="bot-float">
|
|
413
|
+
<div class="bot-head"><span>⚡ Бот НейроАльфа · Telegram / MAX</span><span>только что</span></div>
|
|
414
|
+
<div style="font-size:13px;color:#e2e8f0">Счёт «Т-Банк Основной»: рассчитан пакет лимитных заявок (в целых лотах Мосбиржи):<br>• <b>Купить LKOH</b> — 7 лотов по 7 142,5 ₽<br>• <b>Купить SBER</b> — 16 лотов по 284,80 ₽</div>
|
|
415
|
+
<div class="bot-btns">
|
|
416
|
+
<div class="bot-btn ok">✓ Исполнить заявки (2)</div>
|
|
417
|
+
<div class="bot-btn" style="color:var(--muted)">✕ Отклонить</div>
|
|
418
|
+
</div>
|
|
419
|
+
</div>
|
|
420
|
+
</div>
|
|
421
|
+
</div>
|
|
422
|
+
</div>
|
|
423
|
+
|
|
424
|
+
<div class="wrap">
|
|
425
|
+
<div id="cabinet-box" hidden></div>
|
|
426
|
+
|
|
427
|
+
<section id="showcase" class="reveal">
|
|
428
|
+
<div class="sec-head">
|
|
429
|
+
<div class="sec-tag">Проверено пошагово без заглядывания в будущее</div>
|
|
430
|
+
<h2>Живая витрина эталонных стратегий</h2>
|
|
431
|
+
<p class="sec-sub">Каждая точка графика получена строгим скользящим обучением: модель учится на прошлом окне и торгует следующий месяц, которого ещё не видела, с учётом комиссий и дивидендов.</p>
|
|
432
|
+
</div>
|
|
433
|
+
<div class="showcase-grid" id="showcase-list">
|
|
434
|
+
<div class="bcard wide"><p>Загружаем актуальные графики с сервера…</p></div>
|
|
435
|
+
</div>
|
|
436
|
+
</section>
|
|
437
|
+
|
|
438
|
+
<section id="how" class="reveal">
|
|
439
|
+
<div class="sec-head">
|
|
440
|
+
<div class="sec-tag">Архитектура нового поколения</div>
|
|
441
|
+
<h2>Почему «НейроАльфа» обыгрывает классические индикаторы</h2>
|
|
442
|
+
<p class="sec-sub">Вместо взгляда на одну бумагу в изоляции система видит весь рынок целиком и сама подстраивает правила торговли.</p>
|
|
443
|
+
</div>
|
|
444
|
+
<div class="bento">
|
|
445
|
+
<div class="bcard wide">
|
|
446
|
+
<div class="bicon">◈</div>
|
|
447
|
+
<h3>Принцип языковых моделей (LLM) для котировок</h3>
|
|
448
|
+
<p>Акции выступают как слова в тексте: система строит многомерную карту рынка по совместным движениям цен и 20 фундаментальным свойствам бизнеса, улавливая переток капитала от лидеров к связанным бумагам.</p>
|
|
449
|
+
</div>
|
|
450
|
+
<div class="bcard wide">
|
|
451
|
+
<div class="bicon">⚡</div>
|
|
452
|
+
<h3>Самообучение правил и карантин «акций-убийц»</h3>
|
|
453
|
+
<p>Вам не нужно крутить десятки настроек. Алгоритм сам калибрует порог выхода под комиссию вашего брокера и автоматически блокирует бумаги, где сигнал деградировал или идёт новостной обвал.</p>
|
|
454
|
+
</div>
|
|
455
|
+
<div class="bcard">
|
|
456
|
+
<div class="bicon">🛡</div>
|
|
457
|
+
<h3>Стресс-тест на 5 сдвигах истории</h3>
|
|
458
|
+
<p>Любая стратегия проверяется серией сдвигов исторического окна: вы видите медиану и худший сценарий до запуска на деньгах.</p>
|
|
459
|
+
</div>
|
|
460
|
+
<div class="bcard">
|
|
461
|
+
<div class="bicon">🎙</div>
|
|
462
|
+
<h3>Голосовой ИИ-управляющий «Стратег»</h3>
|
|
463
|
+
<p>Общайтесь с платформой голосом или текстом: Стратег сам ставит эксперименты, ведёт журнал гипотез и объясняет каждую сделку простыми словами.</p>
|
|
464
|
+
</div>
|
|
465
|
+
<div class="bcard">
|
|
466
|
+
<div class="bicon">📰</div>
|
|
467
|
+
<h3>Фильтр свежих новостей и макро-факторов</h3>
|
|
468
|
+
<p>Учитывает нефть Brent, золото, юань, индекс гособлигаций RGBI и каждые 10 минут размечает новости компаний, блокируя входы против негатива.</p>
|
|
469
|
+
</div>
|
|
470
|
+
</div>
|
|
471
|
+
</section>
|
|
472
|
+
|
|
473
|
+
<section id="paas-sec" class="reveal">
|
|
474
|
+
<div class="sec-head">
|
|
475
|
+
<div class="sec-tag">Облачная PaaS-инфраструктура · Без установки на компьютер</div>
|
|
476
|
+
<h2>От исследования стратегии до реальных заявок за 1 минуту</h2>
|
|
477
|
+
<p class="sec-sub">Вся вычислительная мощность и ИИ-управляющий «Стратег» работают в защищённом облаке 24/7. Вы управляете счетами прямо из браузера или со смартфона в Telegram и MAX.</p>
|
|
478
|
+
</div>
|
|
479
|
+
<div class="bento">
|
|
480
|
+
<div class="bcard">
|
|
481
|
+
<div class="bicon">1</div>
|
|
482
|
+
<h3>Тестируйте без ограничений</h3>
|
|
483
|
+
<p>Даже на бесплатном тарифе вы можете проводить эксперименты на полной мощности ядра, проверять стратегии на сдвигах истории и видеть весь потенциал доходности.</p>
|
|
484
|
+
</div>
|
|
485
|
+
<div class="bcard">
|
|
486
|
+
<div class="bicon">2</div>
|
|
487
|
+
<h3>Выберите мощность тарифа</h3>
|
|
488
|
+
<p>От консервативного тарифа «Инвестор» (работа только в рост до 50% годовых) и «Профи» (покупки + шорты до 100% годовых) до полного форсажа «VIP» без потолка доходности.</p>
|
|
489
|
+
</div>
|
|
490
|
+
<div class="bcard">
|
|
491
|
+
<div class="bicon">3</div>
|
|
492
|
+
<h3>Торгуйте с жёсткими предохранителями</h3>
|
|
493
|
+
<p>Подключите счёт Т-Банка, БКС, Финам или Алор в режиме «Подтверждение в 1 клик в Telegram / MAX» или «Полный автомат» с защитой стартового портфеля.</p>
|
|
494
|
+
</div>
|
|
495
|
+
</div>
|
|
496
|
+
</section>
|
|
497
|
+
|
|
498
|
+
<section id="brokers" class="reveal">
|
|
499
|
+
<div class="sec-head">
|
|
500
|
+
<div class="sec-tag">Безопасность и полный контроль</div>
|
|
501
|
+
<h2>Подключение к вашему брокеру и управление из Telegram и MAX</h2>
|
|
502
|
+
<p class="sec-sub">Деньги всегда остаются на вашем личном счёте в Т-Банке, БКС, Финаме или Алоре. Ключи зашифрованы по стандарту AES-256-GCM.</p>
|
|
503
|
+
</div>
|
|
504
|
+
<div class="bento">
|
|
505
|
+
<div class="bcard">
|
|
506
|
+
<div class="bicon">👁</div>
|
|
507
|
+
<h3>1. Режим «Только чтение»</h3>
|
|
508
|
+
<p>Безопасное знакомство: платформа синхронизирует ваш реальный портфель и показывает расхождение с модельным прогнозом без отправки заявок.</p>
|
|
509
|
+
</div>
|
|
510
|
+
<div class="bcard">
|
|
511
|
+
<div class="bicon">📲</div>
|
|
512
|
+
<h3>2. Подтверждение в 1 клик в мессенджере</h3>
|
|
513
|
+
<p>По закрытию свечи сервер сам считает целые лоты Мосбиржи и присылает карточку в Telegram и MAX. Вы нажимаете «Исполнить» прямо с телефона.</p>
|
|
514
|
+
</div>
|
|
515
|
+
<div class="bcard">
|
|
516
|
+
<div class="bicon">🤖</div>
|
|
517
|
+
<h3>3. Полный автомат с предохранителями</h3>
|
|
518
|
+
<p>Лимитные заявки с защитным отступом цены, жёстким лимитом выделенной суммы, дневным стопом по просадке и пропуском первых/последних 10 минут сессии.</p>
|
|
519
|
+
</div>
|
|
520
|
+
</div>
|
|
521
|
+
</section>
|
|
522
|
+
|
|
523
|
+
<section id="pricing" class="reveal">
|
|
524
|
+
<div class="sec-head">
|
|
525
|
+
<div class="sec-tag">Прозрачные условия</div>
|
|
526
|
+
<h2>Тарифные планы</h2>
|
|
527
|
+
<p class="sec-sub">Начните с бесплатного доступа к витрине и демо-счёту или подключите полный автопилот для своих брокерских счетов.</p>
|
|
528
|
+
</div>
|
|
529
|
+
<div class="period-wrap">
|
|
530
|
+
<div class="period-seg" id="months-seg">
|
|
531
|
+
<button data-m="1" class="active">1 месяц</button>
|
|
532
|
+
<button data-m="3">3 месяца (−10%)</button>
|
|
533
|
+
<button data-m="12">12 месяцев (−20%)</button>
|
|
534
|
+
</div>
|
|
535
|
+
</div>
|
|
536
|
+
<div class="plans">
|
|
537
|
+
<div class="plan">
|
|
538
|
+
<h3>Старт (Тест-драйв)</h3>
|
|
539
|
+
<div class="plan-desc">Для тестирования любых стратегий и проверки сигналов на виртуальном счёте без реальной торговли</div>
|
|
540
|
+
<div class="price">0 ₽ <span>/ бесплатно</span></div>
|
|
541
|
+
<ul>
|
|
542
|
+
<li><b>Полный доступ к Экспериментам</b>: тестируйте стратегии любой доходности</li>
|
|
543
|
+
<li>1 виртуальный демо-счёт в реальном времени со сверкой коридора</li>
|
|
544
|
+
<li>Карта рынка, новости Мосбиржи и ИИ-управляющий «Стратег»</li>
|
|
545
|
+
<li>Без подключения реальных брокерских счетов</li>
|
|
546
|
+
</ul>
|
|
547
|
+
<button class="btn" type="button" id="btn-free-start">Начать тестирование</button>
|
|
548
|
+
</div>
|
|
549
|
+
|
|
550
|
+
<div class="plan">
|
|
551
|
+
<h3>Инвестор</h3>
|
|
552
|
+
<div class="plan-desc">Консервативная реальная торговля только от покупки (без шортов)</div>
|
|
553
|
+
<div class="price" id="price-investor">3 900 ₽ <span>/ мес</span></div>
|
|
554
|
+
<ul>
|
|
555
|
+
<li>До <b>2 брокерских счетов</b> (Т-Банк, БКС, Финам, Алор)</li>
|
|
556
|
+
<li>Лимит капитала в торговле: <b>до 1 000 000 ₽</b> на каждом счёте</li>
|
|
557
|
+
<li>Режим <b>«Только в рост (без шорта)»</b>, консервативный слот</li>
|
|
558
|
+
<li>Предельный уровень доходности стратегии: <b>до 50% годовых</b></li>
|
|
559
|
+
<li>Подтверждение заявок в 1 клик в <b>Telegram и MAX</b></li>
|
|
560
|
+
</ul>
|
|
561
|
+
<button class="btn primary" data-buy="investor">Оформить «Инвестор»</button>
|
|
562
|
+
</div>
|
|
563
|
+
|
|
564
|
+
<div class="plan featured">
|
|
565
|
+
<div class="pop-ribbon">Оптимальный выбор</div>
|
|
566
|
+
<h3>Профи</h3>
|
|
567
|
+
<div class="plan-desc">Заработок и на росте, и на падении акций (с шортами)</div>
|
|
568
|
+
<div class="price" id="price-pro">9 900 ₽ <span>/ мес</span></div>
|
|
569
|
+
<ul>
|
|
570
|
+
<li>До <b>5 брокерских счетов</b> параллельно</li>
|
|
571
|
+
<li>Лимит капитала в торговле: <b>до 10 000 000 ₽</b> на каждом счёте</li>
|
|
572
|
+
<li>Режим <b>«В рост и в падение (с шортом)»</b> с адаптацией к индексу</li>
|
|
573
|
+
<li>Предельный уровень доходности стратегии: <b>до 100% годовых</b></li>
|
|
574
|
+
<li>До 5 виртуальных счетов и 500 экспериментов в сутки</li>
|
|
575
|
+
</ul>
|
|
576
|
+
<button class="btn primary" data-buy="pro">Оформить «Профи»</button>
|
|
577
|
+
</div>
|
|
578
|
+
</div>
|
|
579
|
+
|
|
580
|
+
<div class="plan-vip-wide">
|
|
581
|
+
<div>
|
|
582
|
+
<span class="pop-ribbon" style="position:static;display:inline-block;margin-bottom:8px;background:linear-gradient(135deg,#d97706,#f59e0b)">Полная институциональная мощность</span>
|
|
583
|
+
<h3 style="font-size:24px;margin-bottom:6px">👑 Тариф VIP (Без ограничений)</h3>
|
|
584
|
+
<div class="plan-desc" style="margin-bottom:10px">Индивидуальный контур без ограничений по доходности, числу счетов и объёму капитала</div>
|
|
585
|
+
<div style="font-size:26px;font-weight:800;color:#fbbf24">По согласованию</div>
|
|
586
|
+
</div>
|
|
587
|
+
<ul>
|
|
588
|
+
<li><b>Без ограничений</b> по числу брокерских счетов и сумме капитала на каждом счёте</li>
|
|
589
|
+
<li><b>Без потолка годовой доходности</b> (100% мощности лучших экспериментов)</li>
|
|
590
|
+
<li>Включён <b>VIP-форсаж</b>: внутричасовой перехват <code>H/2</code> + динамическая концентрация <code>Conviction Sizing</code></li>
|
|
591
|
+
<li>Персональный VIP-токен активации от администратора платформы</li>
|
|
592
|
+
</ul>
|
|
593
|
+
<div style="display:flex;flex-direction:column;gap:10px;min-width:220px">
|
|
594
|
+
<button class="btn primary" type="button" id="btn-vip-req" style="background:linear-gradient(135deg,#d97706,#f59e0b);justify-content:center">Согласовать условия VIP</button>
|
|
595
|
+
<button class="btn" type="button" id="btn-vip-token-open" style="font-size:13px;padding:9px 14px;justify-content:center">У меня есть VIP-токен</button>
|
|
596
|
+
</div>
|
|
597
|
+
</div>
|
|
598
|
+
</section>
|
|
599
|
+
|
|
600
|
+
<footer>
|
|
601
|
+
<div style="display:flex;justify-content:space-between;flex-wrap:wrap;gap:12px">
|
|
602
|
+
<div>© 2026 Автор и правообладатель: Перепелкин Р.А. · Оператор платформы: ООО «БИС» («Бизнес Интер Софт», г. Рязань) · Все права защищены</div>
|
|
603
|
+
<div style="display:flex;gap:18px">
|
|
604
|
+
<a href="/legal#offer" style="color:#93c5fd">Публичная оферта</a>
|
|
605
|
+
<a href="/legal#privacy" style="color:#93c5fd">Политика конфиденциальности</a>
|
|
606
|
+
<a href="/legal#risks" style="color:#93c5fd">Декларация о рисках</a>
|
|
607
|
+
</div>
|
|
608
|
+
</div>
|
|
609
|
+
<div style="margin-top:8px">Проприетарное программное обеспечение (PaaS). Сервис является аналитическим программно-вычислительным комплексом и не является индивидуальной инвестиционной рекомендацией или доверительным управлением. Результаты на исторических данных не гарантируют доходности в будущем.</div>
|
|
610
|
+
</footer>
|
|
611
|
+
</div>
|
|
612
|
+
|
|
613
|
+
<div class="modal" id="auth-modal" hidden>
|
|
614
|
+
<div class="modal-box">
|
|
615
|
+
<h3 id="auth-title">Вход в НейроАльфа</h3>
|
|
616
|
+
<div id="tg-bot-login-box" hidden style="margin-bottom:8px">
|
|
617
|
+
<button type="button" class="oauth-btn full" id="btn-tg-bot-login" style="width:100%;background:rgba(36, 161, 222, 0.16);border-color:rgba(36, 161, 222, 0.45);color:#7dd3fc">
|
|
618
|
+
<span class="oauth-ico" style="background:#24a1de;color:#fff">✈</span>
|
|
619
|
+
<span id="btn-tg-bot-lbl">Войти в 1 клик через Telegram-бота</span>
|
|
620
|
+
</button>
|
|
621
|
+
</div>
|
|
622
|
+
<div id="max-bot-login-box" hidden style="margin-bottom:12px">
|
|
623
|
+
<button type="button" class="oauth-btn full" id="btn-max-bot-login" style="width:100%;background:rgba(139, 92, 246, 0.16);border-color:rgba(139, 92, 246, 0.45);color:#c4b5fd">
|
|
624
|
+
<span class="oauth-ico" style="background:#7c3aed;color:#fff">M</span>
|
|
625
|
+
<span id="btn-max-bot-lbl">Войти в 1 клик через мессенджер MAX</span>
|
|
626
|
+
</button>
|
|
627
|
+
</div>
|
|
628
|
+
<div class="oauth-grid" id="oauth-btns" hidden>
|
|
629
|
+
<button type="button" class="oauth-btn" data-oauth="yandex" hidden>
|
|
630
|
+
<span class="oauth-ico" style="background:#fc3f1d;color:#fff">Я</span>
|
|
631
|
+
<span>Яндекс ID</span>
|
|
632
|
+
</button>
|
|
633
|
+
<button type="button" class="oauth-btn" data-oauth="sber" hidden>
|
|
634
|
+
<span class="oauth-ico" style="background:#21a038;color:#fff">С</span>
|
|
635
|
+
<span>Сбер ID</span>
|
|
636
|
+
</button>
|
|
637
|
+
<button type="button" class="oauth-btn" data-oauth="tbank" hidden>
|
|
638
|
+
<span class="oauth-ico" style="background:#ffdd2d;color:#111">Т</span>
|
|
639
|
+
<span>T-ID (Т-Банк)</span>
|
|
640
|
+
</button>
|
|
641
|
+
<button type="button" class="oauth-btn" data-oauth="google" hidden>
|
|
642
|
+
<span class="oauth-ico" style="background:#fff;color:#2563eb">G</span>
|
|
643
|
+
<span>Google</span>
|
|
644
|
+
</button>
|
|
645
|
+
<button type="button" class="oauth-btn full" data-oauth="vk" hidden>
|
|
646
|
+
<span class="oauth-ico" style="background:#0077ff;color:#fff">VK</span>
|
|
647
|
+
<span>Войти через VK ID</span>
|
|
648
|
+
</button>
|
|
649
|
+
</div>
|
|
650
|
+
<div class="or-sep" id="oauth-or-sep" hidden>или по Email и паролю</div>
|
|
651
|
+
<form id="auth-form">
|
|
652
|
+
<input name="name" id="auth-name" placeholder="Ваше имя" hidden>
|
|
653
|
+
<input name="email" type="email" required placeholder="Email">
|
|
654
|
+
<input name="password" type="password" required minlength="6" placeholder="Пароль (не короче 6 символов)">
|
|
655
|
+
<label style="display:flex;gap:8px;align-items:flex-start;font-size:12.5px;color:var(--muted)"><input type="checkbox" required checked style="width:16px;height:16px;margin-top:2px"><span>Принимаю условия <a href="/legal#offer" target="_blank" style="color:#93c5fd">Публичной оферты</a>, <a href="/legal#privacy" target="_blank" style="color:#93c5fd">Политики конфиденциальности</a> и <a href="/legal#risks" target="_blank" style="color:#93c5fd">Декларации о рисках</a></span></label>
|
|
656
|
+
<div class="err" id="auth-err"></div>
|
|
657
|
+
<button class="btn primary" type="submit" id="auth-submit">Войти</button>
|
|
658
|
+
<button class="btn" type="button" id="auth-toggle">Нет аккаунта? Зарегистрироваться</button>
|
|
659
|
+
<button class="btn" type="button" id="auth-close" style="border:0;color:var(--muted)">Закрыть</button>
|
|
660
|
+
</form>
|
|
661
|
+
</div>
|
|
662
|
+
</div>
|
|
663
|
+
|
|
664
|
+
<!-- Модальное окно подписания Договора-оферты и Декларации о рисках перед подпиской -->
|
|
665
|
+
<div class="modal" id="offer-modal" hidden>
|
|
666
|
+
<div class="modal-box" style="max-width:660px">
|
|
667
|
+
<h3>Договор публичной оферты и Декларация о рисках</h3>
|
|
668
|
+
<div style="background:#070b14;border:1px solid var(--line);border-radius:10px;padding:14px 16px;max-height:260px;overflow-y:auto;font-size:13px;line-height:1.55;color:#cbd5e1;margin-bottom:14px">
|
|
669
|
+
<p style="margin-top:0"><b>1. Предмет договора:</b> Настоящая Публичная оферта регулирует предоставление доступа к облачной аналитической платформе «НейроАльфа» (PaaS/SaaS) согласно выбранному тарифному плану («Старт», «Инвестор», «Профи», «VIP»).</p>
|
|
670
|
+
<p><b>2. Правовой статус (отсутствие ИИР и ДУ):</b> Сервис является исключительно программно-техническим средством (калькулятором статистических закономерностей). Исполнитель <b>не осуществляет инвестиционное консультирование</b>, не даёт индивидуальных инвестиционных рекомендаций (ФЗ № 39-ФЗ) и не осуществляет доверительное управление. Все сделки совершаются Пользователем самостоятельно на его личном брокерском счёте.</p>
|
|
671
|
+
<p><b>3. Параметры тарифов и предельные уровни доходности:</b>
|
|
672
|
+
<br>• <b>«Старт» (0 ₽)</b> — тестирование в Экспериментах и виртуальный счёт без реальной торговли;
|
|
673
|
+
<br>• <b>«Инвестор»</b> — до 2 брокерских счетов, лимит до 1 000 000 ₽ на каждом, торговля только от покупки («Только в рост (без шорта)»), предельный целевой темп доходности стратегии до 50% годовых;
|
|
674
|
+
<br>• <b>«Профи»</b> — до 5 брокерских счетов, лимит до 10 000 000 ₽ на каждом, торговля в рост и в падение (с шортами), предельный целевой темп доходности до 100% годовых;
|
|
675
|
+
<br>• <b>«VIP»</b> — по индивидуальному согласованию (VIP-токен), без ограничений по числу счетов, сумме капитала и потолку годовой доходности (включая полушаговое сопровождение H/2 и динамическую концентрацию слота).
|
|
676
|
+
</p>
|
|
677
|
+
<p><b>4. Запрет автоследования и ретрансляции сигналов:</b> Пользователю строго запрещается подключать к платформе счета, участвующие в сервисах автоследования или копирования сделок (как в роли ведущего/автора стратегии, так и в роли подписчика), а также передавать или перепродавать сигналы третьим лицам. При обнаружении признаков автоследования счёт автоматически блокируется.</p>
|
|
678
|
+
<p style="margin-bottom:0"><b>5. Декларация о рисках:</b> Торговля ценными бумагами сопряжена с риском потери части или всего инвестированного капитала. Результаты на исторических данных не гарантируют доходности в будущем. Полный текст: <a href="/legal" target="_blank" style="color:#93c5fd">открыть в новой вкладке →</a></p>
|
|
679
|
+
</div>
|
|
680
|
+
<div style="display:grid;gap:10px;font-size:13px;color:#e2e8f0;margin-bottom:16px">
|
|
681
|
+
<label style="display:flex;gap:10px;align-items:flex-start;cursor:pointer">
|
|
682
|
+
<input type="checkbox" id="offer-chk-1" style="width:17px;height:17px;margin-top:2px;flex:none">
|
|
683
|
+
<span>Я прочитал(а) и безоговорочно принимаю условия <a href="/legal#offer" target="_blank" style="color:#93c5fd">Договора публичной оферты</a> и <a href="/legal#privacy" target="_blank" style="color:#93c5fd">Политики обработки персональных данных</a>.</span>
|
|
684
|
+
</label>
|
|
685
|
+
<label style="display:flex;gap:10px;align-items:flex-start;cursor:pointer">
|
|
686
|
+
<input type="checkbox" id="offer-chk-2" style="width:17px;height:17px;margin-top:2px;flex:none">
|
|
687
|
+
<span>Я ознакомлен(а) с <a href="/legal#risks" target="_blank" style="color:#93c5fd">Декларацией о рисках</a>, понимаю, что сервис не является индивидуальной инвестиционной рекомендацией, и обязуюсь <b>не использовать автоследование</b> на подключаемых счетах.</span>
|
|
688
|
+
</label>
|
|
689
|
+
</div>
|
|
690
|
+
<div style="display:flex;gap:10px;justify-content:flex-end;flex-wrap:wrap">
|
|
691
|
+
<button class="btn" type="button" id="btn-offer-decline">Отказ (Отмена)</button>
|
|
692
|
+
<button class="btn primary" type="button" id="btn-offer-accept" disabled>Подписать оферту и продолжить →</button>
|
|
693
|
+
</div>
|
|
694
|
+
</div>
|
|
695
|
+
</div>
|
|
696
|
+
|
|
697
|
+
<!-- Модальное окно согласования VIP и ввода VIP-токена -->
|
|
698
|
+
<div class="modal" id="vip-modal" hidden>
|
|
699
|
+
<div class="modal-box" style="max-width:480px">
|
|
700
|
+
<h3>Тариф VIP · Индивидуальные условия</h3>
|
|
701
|
+
<p style="font-size:13.5px;color:var(--muted);margin:0 0 14px">Тариф VIP снимает все ограничения по числу счетов, объёму торгового капитала и потолку годовой доходности, активируя полный форсаж ядра (<code>H/2</code> + <code>Conviction Sizing</code>).</p>
|
|
702
|
+
<form id="vip-req-form" style="margin-bottom:18px;padding-bottom:16px;border-bottom:1px solid var(--line)">
|
|
703
|
+
<div style="font-size:13px;font-weight:600;color:#f59e0b">1. Оставить заявку на согласование условий VIP:</div>
|
|
704
|
+
<input name="name" placeholder="Ваше имя" style="width:100%;padding:10px 12px;border-radius:9px;border:1px solid var(--line);background:var(--bg);color:var(--text)">
|
|
705
|
+
<input name="contact" required placeholder="Ваш Telegram (@username) или телефон для связи" style="width:100%;padding:10px 12px;border-radius:9px;border:1px solid var(--line);background:var(--bg);color:var(--text)">
|
|
706
|
+
<input name="capitalRub" placeholder="Планируемый объём капитала (например, 25 млн ₽)" style="width:100%;padding:10px 12px;border-radius:9px;border:1px solid var(--line);background:var(--bg);color:var(--text)">
|
|
707
|
+
<button class="btn primary" type="submit" style="background:linear-gradient(135deg,#d97706,#f59e0b)">Отправить заявку администратору</button>
|
|
708
|
+
</form>
|
|
709
|
+
<form id="vip-token-form">
|
|
710
|
+
<div style="font-size:13px;font-weight:600;color:#93c5fd">2. Уже получили персональный VIP-токен от администратора?</div>
|
|
711
|
+
<div style="display:flex;gap:8px">
|
|
712
|
+
<input name="code" required placeholder="VIP-…" style="flex:1;padding:10px 12px;border-radius:9px;border:1px solid var(--line);background:var(--bg);color:var(--text)">
|
|
713
|
+
<button class="btn primary" type="submit">Активировать VIP</button>
|
|
714
|
+
</div>
|
|
715
|
+
</form>
|
|
716
|
+
<div style="margin-top:12px;text-align:right">
|
|
717
|
+
<button class="btn" type="button" id="btn-vip-close" style="border:0;color:var(--muted)">Закрыть</button>
|
|
718
|
+
</div>
|
|
719
|
+
</div>
|
|
720
|
+
</div>
|
|
721
|
+
|
|
722
|
+
<script>
|
|
723
|
+
// ---------- 1. Анимированный граф перетоков капитала на фоне Hero ----------
|
|
724
|
+
(() => {
|
|
725
|
+
const cv = document.getElementById('hero-canvas');
|
|
726
|
+
if (!cv) return;
|
|
727
|
+
const ctx = cv.getContext('2d');
|
|
728
|
+
const tickers = ['SBER','LKOH','YDEX','ROSN','NVTK','GMKN','TATN','PLZL','CHMF','GAZP','SNGS','MOEX','T','PHOR','NLMK','ALRS'];
|
|
729
|
+
let W = 0, H = 0;
|
|
730
|
+
const resize = () => { W = cv.width = cv.offsetWidth; H = cv.height = cv.offsetHeight; };
|
|
731
|
+
window.addEventListener('resize', resize);
|
|
732
|
+
resize();
|
|
733
|
+
const nodes = tickers.map((sym, i) => ({
|
|
734
|
+
sym,
|
|
735
|
+
x: (0.1 + 0.8 * ((i * 0.618) % 1)) * (W || 1200),
|
|
736
|
+
y: (0.15 + 0.7 * (((i * 0.382) + 0.2) % 1)) * (H || 600),
|
|
737
|
+
vx: (Math.random() - 0.5) * 0.35,
|
|
738
|
+
vy: (Math.random() - 0.5) * 0.35,
|
|
739
|
+
r: i < 5 ? 5 : 3.5,
|
|
740
|
+
}));
|
|
741
|
+
const pulses = [];
|
|
742
|
+
setInterval(() => {
|
|
743
|
+
if (pulses.length < 8) {
|
|
744
|
+
const a = Math.floor(Math.random() * nodes.length);
|
|
745
|
+
const b = (a + 1 + Math.floor(Math.random() * (nodes.length - 1))) % nodes.length;
|
|
746
|
+
pulses.push({ a, b, t: 0 });
|
|
747
|
+
}
|
|
748
|
+
}, 450);
|
|
749
|
+
|
|
750
|
+
function frame() {
|
|
751
|
+
ctx.clearRect(0, 0, W, H);
|
|
752
|
+
for (const n of nodes) {
|
|
753
|
+
n.x += n.vx; n.y += n.vy;
|
|
754
|
+
if (n.x < 40 || n.x > W - 40) n.vx *= -1;
|
|
755
|
+
if (n.y < 30 || n.y > H - 30) n.vy *= -1;
|
|
756
|
+
}
|
|
757
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
758
|
+
for (let j = i + 1; j < nodes.length; j++) {
|
|
759
|
+
const dx = nodes[i].x - nodes[j].x, dy = nodes[i].y - nodes[j].y;
|
|
760
|
+
const d = Math.hypot(dx, dy);
|
|
761
|
+
if (d < 220) {
|
|
762
|
+
ctx.strokeStyle = `rgba(96, 165, 250, ${(1 - d / 220) * 0.22})`;
|
|
763
|
+
ctx.lineWidth = 1;
|
|
764
|
+
ctx.beginPath(); ctx.moveTo(nodes[i].x, nodes[i].y); ctx.lineTo(nodes[j].x, nodes[j].y); ctx.stroke();
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
for (let k = pulses.length - 1; k >= 0; k--) {
|
|
769
|
+
const p = pulses[k];
|
|
770
|
+
p.t += 0.018;
|
|
771
|
+
if (p.t >= 1) { pulses.splice(k, 1); continue; }
|
|
772
|
+
const na = nodes[p.a], nb = nodes[p.b];
|
|
773
|
+
const px = na.x + (nb.x - na.x) * p.t, py = na.y + (nb.y - na.y) * p.t;
|
|
774
|
+
ctx.fillStyle = '#38bdf8';
|
|
775
|
+
ctx.beginPath(); ctx.arc(px, py, 3, 0, Math.PI * 2); ctx.fill();
|
|
776
|
+
}
|
|
777
|
+
for (const n of nodes) {
|
|
778
|
+
ctx.fillStyle = '#60a5fa';
|
|
779
|
+
ctx.beginPath(); ctx.arc(n.x, n.y, n.r, 0, Math.PI * 2); ctx.fill();
|
|
780
|
+
ctx.fillStyle = 'rgba(203, 213, 225, 0.55)';
|
|
781
|
+
ctx.font = '600 11px system-ui';
|
|
782
|
+
ctx.fillText(n.sym, n.x + 8, n.y + 4);
|
|
783
|
+
}
|
|
784
|
+
requestAnimationFrame(frame);
|
|
785
|
+
}
|
|
786
|
+
requestAnimationFrame(frame);
|
|
787
|
+
})();
|
|
788
|
+
|
|
789
|
+
// ---------- 2. Плавное появление секций при прокрутке ----------
|
|
790
|
+
const io = new IntersectionObserver((entries) => {
|
|
791
|
+
entries.forEach((e) => { if (e.isIntersecting) e.target.classList.add('in'); });
|
|
792
|
+
}, { threshold: 0.12 });
|
|
793
|
+
document.querySelectorAll('.reveal').forEach((el) => io.observe(el));
|
|
794
|
+
|
|
795
|
+
// ---------- 3. Витрина, тарифы и авторизация ----------
|
|
796
|
+
const fmt = (v, d = 1) => (v > 0 ? '+' : '') + Number(v || 0).toFixed(d).replace('.', ',');
|
|
797
|
+
let selectedMonths = 1;
|
|
798
|
+
let isReg = false;
|
|
799
|
+
let pendingPlan = null;
|
|
800
|
+
let currentUser = null;
|
|
801
|
+
|
|
802
|
+
function sparkSvg(curve, mktCurve, id) {
|
|
803
|
+
if (!curve || curve.length < 2) return '';
|
|
804
|
+
const W = 460, H = 130;
|
|
805
|
+
const norm = (arr) => arr.map((p) => (p.equity / arr[0].equity) * 100);
|
|
806
|
+
const a = norm(curve), m = mktCurve?.length > 1 ? norm(mktCurve) : [];
|
|
807
|
+
const all = [...a, ...m];
|
|
808
|
+
const lo = Math.min(...all), hi = Math.max(...all, lo + 1);
|
|
809
|
+
const xy = (arr) => arr.map((v, i) => [((i / (arr.length - 1)) * W), (H - 10 - ((v - lo) / (hi - lo)) * (H - 20))]);
|
|
810
|
+
const pts = (arr) => xy(arr).map(([x, y]) => `${x.toFixed(1)},${y.toFixed(1)}`).join(' ');
|
|
811
|
+
const areaPts = `0,${H} ${pts(a)} ${W},${H}`;
|
|
812
|
+
return `<svg viewBox="0 0 ${W} ${H}" width="100%" height="${H}" style="overflow:visible">
|
|
813
|
+
<defs>
|
|
814
|
+
<linearGradient id="g${id}" x1="0" y1="0" x2="0" y2="1">
|
|
815
|
+
<stop offset="0%" stop-color="#3b82f6" stop-opacity="0.38"/>
|
|
816
|
+
<stop offset="100%" stop-color="#3b82f6" stop-opacity="0.0"/>
|
|
817
|
+
</linearGradient>
|
|
818
|
+
</defs>
|
|
819
|
+
<polygon points="${areaPts}" fill="url(#g${id})"/>
|
|
820
|
+
${m.length ? `<polyline points="${pts(m)}" fill="none" stroke="#64748b" stroke-width="1.6" stroke-dasharray="4 3"/>` : ''}
|
|
821
|
+
<polyline points="${pts(a)}" fill="none" stroke="#3b82f6" stroke-width="2.8"/>
|
|
822
|
+
</svg>`;
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
function renderCabinet() {
|
|
826
|
+
const cab = document.getElementById('cabinet-box');
|
|
827
|
+
if (!cab) return;
|
|
828
|
+
if (!currentUser) {
|
|
829
|
+
cab.hidden = true;
|
|
830
|
+
return;
|
|
831
|
+
}
|
|
832
|
+
cab.hidden = false;
|
|
833
|
+
const navCta = document.getElementById('btn-nav-cta');
|
|
834
|
+
if (navCta) {
|
|
835
|
+
if (currentUser.role === 'admin') {
|
|
836
|
+
navCta.href = '/admin';
|
|
837
|
+
navCta.textContent = 'Панель админа →';
|
|
838
|
+
} else {
|
|
839
|
+
navCta.href = '/';
|
|
840
|
+
navCta.textContent = 'Открыть терминал →';
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
const untilStr = currentUser.planUntil > Date.now()
|
|
844
|
+
? `оплачен до ${new Date(currentUser.planUntil).toLocaleDateString('ru-RU')}`
|
|
845
|
+
: 'бессрочно';
|
|
846
|
+
const capLim = currentUser.limits?.maxCapitalPerAccountRub
|
|
847
|
+
? (currentUser.limits.maxCapitalPerAccountRub >= 100000000 ? 'без ограничений' : `до ${(currentUser.limits.maxCapitalPerAccountRub / 1000000).toLocaleString('ru-RU')} млн ₽/счёт`)
|
|
848
|
+
: 'демо-режим';
|
|
849
|
+
const retLim = currentUser.limits?.maxAnnualReturnPct > 0
|
|
850
|
+
? `до ${currentUser.limits.maxAnnualReturnPct}% годовых`
|
|
851
|
+
: 'без ограничений (VIP-форсаж)';
|
|
852
|
+
cab.innerHTML = `<div class="cab-card">
|
|
853
|
+
<div class="cab-grid">
|
|
854
|
+
<div>
|
|
855
|
+
<div class="sec-tag" style="margin-bottom:4px">Личный кабинет PaaS · Аккаунт активен</div>
|
|
856
|
+
<h3 style="margin:0 0 8px;font-size:22px">${currentUser.name} <span style="color:var(--muted);font-weight:400;font-size:15px">(${currentUser.email})</span></h3>
|
|
857
|
+
<div style="margin-bottom:14px;font-size:14.5px;color:#cbd5e1">
|
|
858
|
+
Тариф: <b class="pos">${currentUser.planName}</b> (${untilStr}) · Брокерских счетов: до <b>${currentUser.limits?.maxBrokerAccounts ?? 0}</b> (${capLim}) · Предел доходности стратегии: <b>${retLim}</b> · Режим: <b>${currentUser.limits?.allowShorts ? 'в рост и в падение (с шортом)' : 'только в рост (без шорта)'}</b>.
|
|
859
|
+
</div>
|
|
860
|
+
<div style="display:flex;gap:8px;flex-wrap:wrap;align-items:center">
|
|
861
|
+
<input id="cab-promo-in" placeholder="Промокод или VIP-токен" style="padding:8px 12px;border-radius:9px;border:1px solid var(--line);background:var(--bg);color:var(--text);font-size:13.5px;width:220px">
|
|
862
|
+
<button type="button" class="btn" id="cab-promo-btn" style="padding:8px 14px;font-size:13px">Активировать код</button>
|
|
863
|
+
</div>
|
|
864
|
+
</div>
|
|
865
|
+
<div style="display:flex;flex-direction:column;gap:10px">
|
|
866
|
+
<a class="btn primary lg" href="/" style="justify-content:center">Перейти в торговый терминал →</a>
|
|
867
|
+
<div style="display:flex;gap:10px;flex-wrap:wrap">
|
|
868
|
+
<a class="btn" href="#pricing" style="flex:1">Сменить / продлить тариф</a>
|
|
869
|
+
${currentUser.role === 'admin' ? '<a class="btn" href="/admin">Консоль админа →</a>' : ''}
|
|
870
|
+
</div>
|
|
871
|
+
</div>
|
|
872
|
+
</div>
|
|
873
|
+
</div>`;
|
|
874
|
+
|
|
875
|
+
document.getElementById('cab-promo-btn')?.addEventListener('click', () => {
|
|
876
|
+
const code = document.getElementById('cab-promo-in')?.value.trim();
|
|
877
|
+
if (!code) return;
|
|
878
|
+
requireOfferAgreement(async () => {
|
|
879
|
+
const r = await fetch('/api/auth/redeem-promo', {
|
|
880
|
+
method: 'POST',
|
|
881
|
+
headers: { 'Content-Type': 'application/json' },
|
|
882
|
+
body: JSON.stringify({ code }),
|
|
883
|
+
});
|
|
884
|
+
const j = await r.json();
|
|
885
|
+
if (!r.ok) return alert(j.error || 'Ошибка активации кода');
|
|
886
|
+
currentUser = j.user;
|
|
887
|
+
renderCabinet();
|
|
888
|
+
alert(`Код успешно активирован! Ваш тариф: ${currentUser.planName}`);
|
|
889
|
+
});
|
|
890
|
+
});
|
|
891
|
+
}
|
|
892
|
+
|
|
893
|
+
document.getElementById('oauth-btns')?.addEventListener('click', (e) => {
|
|
894
|
+
const b = e.target.closest('button[data-oauth]');
|
|
895
|
+
if (!b) return;
|
|
896
|
+
const prov = b.dataset.oauth;
|
|
897
|
+
location.href = `/api/auth/oauth/${encodeURIComponent(prov)}/start${pendingPlan ? `?plan=${encodeURIComponent(pendingPlan)}` : ''}`;
|
|
898
|
+
});
|
|
899
|
+
|
|
900
|
+
let tgPollTimer = null;
|
|
901
|
+
async function startBotLogin(channel) {
|
|
902
|
+
try {
|
|
903
|
+
const res = await fetch('/api/auth/telegram/start', {
|
|
904
|
+
method: 'POST',
|
|
905
|
+
headers: { 'Content-Type': 'application/json' },
|
|
906
|
+
body: JSON.stringify({ channel }),
|
|
907
|
+
});
|
|
908
|
+
const j = await res.json();
|
|
909
|
+
if (!res.ok) throw new Error(j.error || 'Не удалось запустить вход через мессенджер');
|
|
910
|
+
window.open(j.botUrl, '_blank');
|
|
911
|
+
const lbl = document.getElementById(channel === 'max' ? 'btn-max-bot-lbl' : 'btn-tg-bot-lbl');
|
|
912
|
+
if (lbl) lbl.textContent = `Нажмите «Начать / Запустить» в открывшемся ${channel === 'max' ? 'MAX' : 'Telegram'}…`;
|
|
913
|
+
clearInterval(tgPollTimer);
|
|
914
|
+
tgPollTimer = setInterval(async () => {
|
|
915
|
+
const pr = await fetch(`/api/auth/telegram/poll?code=${encodeURIComponent(j.code)}`).then((r) => r.json()).catch(() => ({}));
|
|
916
|
+
if (pr.status === 'done' && pr.user) {
|
|
917
|
+
clearInterval(tgPollTimer);
|
|
918
|
+
currentUser = pr.user;
|
|
919
|
+
document.getElementById('auth-modal').hidden = true;
|
|
920
|
+
document.getElementById('btn-login-open').textContent = `${currentUser.name} · ${currentUser.planName}`;
|
|
921
|
+
renderCabinet();
|
|
922
|
+
if (pendingPlan) {
|
|
923
|
+
const p = pendingPlan;
|
|
924
|
+
pendingPlan = null;
|
|
925
|
+
await startCheckout(p);
|
|
926
|
+
} else {
|
|
927
|
+
document.getElementById('cabinet-box')?.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
|
928
|
+
}
|
|
929
|
+
} else if (pr.status === 'expired') {
|
|
930
|
+
clearInterval(tgPollTimer);
|
|
931
|
+
if (lbl) lbl.textContent = channel === 'max' ? 'Войти в 1 клик через мессенджер MAX' : 'Войти в 1 клик через Telegram-бота';
|
|
932
|
+
}
|
|
933
|
+
}, 2000);
|
|
934
|
+
} catch (e) {
|
|
935
|
+
document.getElementById('auth-err').textContent = e.message;
|
|
936
|
+
}
|
|
937
|
+
}
|
|
938
|
+
document.getElementById('btn-tg-bot-login')?.addEventListener('click', () => startBotLogin('tg'));
|
|
939
|
+
document.getElementById('btn-max-bot-login')?.addEventListener('click', () => startBotLogin('max'));
|
|
940
|
+
|
|
941
|
+
async function loadShowcase() {
|
|
942
|
+
try {
|
|
943
|
+
const me = await (await fetch('/api/auth/me')).json();
|
|
944
|
+
currentUser = me.user;
|
|
945
|
+
let hasAnyFastLogin = false;
|
|
946
|
+
if (me.notify?.tgBotName && me.notify?.hasTgToken) {
|
|
947
|
+
document.getElementById('tg-bot-login-box').hidden = false;
|
|
948
|
+
hasAnyFastLogin = true;
|
|
949
|
+
}
|
|
950
|
+
if (me.notify?.maxBotName && me.notify?.hasMaxToken) {
|
|
951
|
+
document.getElementById('max-bot-login-box').hidden = false;
|
|
952
|
+
hasAnyFastLogin = true;
|
|
953
|
+
}
|
|
954
|
+
const oa = me.oauth || {};
|
|
955
|
+
let enabledOauthCount = 0;
|
|
956
|
+
document.querySelectorAll('#oauth-btns [data-oauth]').forEach((b) => {
|
|
957
|
+
const on = Boolean(oa[b.dataset.oauth]?.enabled);
|
|
958
|
+
b.hidden = !on;
|
|
959
|
+
if (on) enabledOauthCount++;
|
|
960
|
+
});
|
|
961
|
+
if (enabledOauthCount > 0) {
|
|
962
|
+
document.getElementById('oauth-btns').hidden = false;
|
|
963
|
+
hasAnyFastLogin = true;
|
|
964
|
+
}
|
|
965
|
+
document.getElementById('oauth-or-sep').hidden = !hasAnyFastLogin;
|
|
966
|
+
|
|
967
|
+
const up = new URLSearchParams(location.search);
|
|
968
|
+
if (up.get('oauth_error')) {
|
|
969
|
+
openAuth(false);
|
|
970
|
+
document.getElementById('auth-err').textContent = up.get('oauth_error');
|
|
971
|
+
}
|
|
972
|
+
if (currentUser) {
|
|
973
|
+
document.getElementById('btn-login-open').textContent = `${currentUser.name} · ${currentUser.planName}`;
|
|
974
|
+
renderCabinet();
|
|
975
|
+
if (up.get('buy_plan')) {
|
|
976
|
+
startCheckout(up.get('buy_plan'));
|
|
977
|
+
} else if (up.get('oauth_ok') === '1') {
|
|
978
|
+
document.getElementById('cabinet-box')?.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
|
979
|
+
}
|
|
980
|
+
}
|
|
981
|
+
const { runs } = await (await fetch('/api/public/showcase')).json();
|
|
982
|
+
const box = document.getElementById('showcase-list');
|
|
983
|
+
if (!runs?.length) return;
|
|
984
|
+
const uniqueRuns = [];
|
|
985
|
+
const seenRet = new Set();
|
|
986
|
+
for (const x of runs) {
|
|
987
|
+
const rk = Math.round(Number(x.metrics?.returnPct || 0));
|
|
988
|
+
if (seenRet.has(rk)) continue;
|
|
989
|
+
seenRet.add(rk);
|
|
990
|
+
uniqueRuns.push(x);
|
|
991
|
+
if (uniqueRuns.length >= 3) break;
|
|
992
|
+
}
|
|
993
|
+
uniqueRuns.sort((a, b) => Number(a.metrics?.returnPct || 0) - Number(b.metrics?.returnPct || 0));
|
|
994
|
+
box.innerHTML = uniqueRuns.map((r, idx) => {
|
|
995
|
+
const from = r.period?.from || 0, till = r.period?.till || 0;
|
|
996
|
+
const years = Math.max(0.5, (till - from) / (365.25 * 86400000));
|
|
997
|
+
const ret = Number(r.metrics.returnPct || 0);
|
|
998
|
+
const cagr = years >= 0.25 && ret > -99 ? ((Math.pow(1 + ret / 100, 1 / years) - 1) * 100) : (ret / years);
|
|
999
|
+
const mktPct = Number(r.metrics.marketPct || -22.3);
|
|
1000
|
+
const isLong = r.params.modelDirection === 'long' || cagr <= 52;
|
|
1001
|
+
const isPro = !isLong && cagr <= 105;
|
|
1002
|
+
const tColor = r.tierColor || (isLong ? 'blue' : isPro ? 'indigo' : 'gold');
|
|
1003
|
+
const tBadge = r.tierBadge || (isLong ? 'Для тарифа «Инвестор»' : isPro ? 'Для тарифа «Профи»' : '👑 Для тарифа «VIP»');
|
|
1004
|
+
const tNote = r.tierNote || (isLong
|
|
1005
|
+
? 'Торговля только от покупки (без шортов) · потолок тарифа до 50% годовых · до 1 млн ₽/счёт'
|
|
1006
|
+
: isPro
|
|
1007
|
+
? 'Заработок на росте и падении акций (с шортами) · потолок тарифа до 100% годовых · до 10 млн ₽/счёт'
|
|
1008
|
+
: 'Полная мощность без потолка доходности · форсаж H/2 + концентрация слота Conviction Sizing');
|
|
1009
|
+
const badgeStyle = tColor === 'gold'
|
|
1010
|
+
? 'background:rgba(245,158,11,0.18);border:1px solid rgba(245,158,11,0.5);color:#fbbf24'
|
|
1011
|
+
: tColor === 'indigo'
|
|
1012
|
+
? 'background:rgba(99,102,241,0.2);border:1px solid rgba(129,140,248,0.5);color:#a5b4fc'
|
|
1013
|
+
: 'background:rgba(59,130,246,0.16);border:1px solid rgba(96,165,250,0.45);color:#93c5fd';
|
|
1014
|
+
const cardBorder = tColor === 'gold' ? 'border-color:rgba(245,158,11,0.4)' : '';
|
|
1015
|
+
return `<div class="sc-card" style="${cardBorder}">
|
|
1016
|
+
<div style="margin-bottom:8px;display:flex;justify-content:space-between;align-items:center;gap:8px">
|
|
1017
|
+
<span style="display:inline-block;padding:3px 10px;border-radius:999px;font-size:11.5px;font-weight:700;letter-spacing:0.3px;${badgeStyle}">${tBadge}</span>
|
|
1018
|
+
<span style="font-size:12px;color:var(--muted)">Бумаг в портфеле: ${r.params.modelTopK || 2}</span>
|
|
1019
|
+
</div>
|
|
1020
|
+
<div class="sc-head">
|
|
1021
|
+
<div>
|
|
1022
|
+
<div style="font-weight:700;font-size:17px">${r.title}</div>
|
|
1023
|
+
<div style="font-size:12.5px;color:var(--muted);margin-top:3px">${tNote}</div>
|
|
1024
|
+
</div>
|
|
1025
|
+
<div style="text-align:right;flex:none">
|
|
1026
|
+
<div class="sc-ret pos">${fmt(cagr, 1)}% <span style="font-size:13px;font-weight:600">/ год</span></div>
|
|
1027
|
+
<div style="font-size:12px;color:var(--muted)">всего ${fmt(ret, 1)}% за ${years.toFixed(1).replace('.', ',')} г.</div>
|
|
1028
|
+
</div>
|
|
1029
|
+
</div>
|
|
1030
|
+
${sparkSvg(r.curve, r.marketCurve, idx)}
|
|
1031
|
+
<div class="sc-kpis">
|
|
1032
|
+
<div><span class="muted">Индекс Мосбиржи</span><b class="${mktPct >= 0 ? 'pos' : 'neg'}">${fmt(mktPct, 1)}%</b></div>
|
|
1033
|
+
<div><span class="muted">Макс. просадка</span><b>${fmt(r.metrics.maxDrawdownPct, 1).replace('+','')}%</b></div>
|
|
1034
|
+
<div><span class="muted">На 1 ₽ убытка</span><b>${fmt(r.metrics.profitFactor, 2).replace('+','')} ₽</b></div>
|
|
1035
|
+
</div>
|
|
1036
|
+
<a class="btn" href="#pricing">Выбрать этот профиль в облаке →</a>
|
|
1037
|
+
</div>`;
|
|
1038
|
+
}).join('');
|
|
1039
|
+
} catch {}
|
|
1040
|
+
}
|
|
1041
|
+
|
|
1042
|
+
function updatePrices() {
|
|
1043
|
+
const disc = selectedMonths >= 12 ? 0.8 : selectedMonths >= 3 ? 0.9 : 1;
|
|
1044
|
+
const inv = Math.round(3900 * selectedMonths * disc);
|
|
1045
|
+
const pro = Math.round(9900 * selectedMonths * disc);
|
|
1046
|
+
const lbl = selectedMonths === 1 ? '/ мес' : `за ${selectedMonths} мес.`;
|
|
1047
|
+
document.getElementById('price-investor').innerHTML = `${inv.toLocaleString('ru-RU')} ₽ <span>${lbl}</span>`;
|
|
1048
|
+
document.getElementById('price-pro').innerHTML = `${pro.toLocaleString('ru-RU')} ₽ <span>${lbl}</span>`;
|
|
1049
|
+
}
|
|
1050
|
+
|
|
1051
|
+
document.getElementById('months-seg').addEventListener('click', (e) => {
|
|
1052
|
+
const b = e.target.closest('button[data-m]');
|
|
1053
|
+
if (!b) return;
|
|
1054
|
+
selectedMonths = Number(b.dataset.m);
|
|
1055
|
+
document.querySelectorAll('#months-seg button').forEach((x) => x.classList.toggle('active', x === b));
|
|
1056
|
+
updatePrices();
|
|
1057
|
+
});
|
|
1058
|
+
|
|
1059
|
+
function openAuth(reg = false) {
|
|
1060
|
+
isReg = reg;
|
|
1061
|
+
document.getElementById('auth-modal').hidden = false;
|
|
1062
|
+
document.getElementById('auth-name').hidden = !reg;
|
|
1063
|
+
document.getElementById('auth-title').textContent = reg ? 'Регистрация в НейроАльфа' : 'Вход в НейроАльфа';
|
|
1064
|
+
document.getElementById('auth-submit').textContent = reg ? 'Создать аккаунт' : 'Войти';
|
|
1065
|
+
document.getElementById('auth-toggle').textContent = reg ? 'Уже есть аккаунт? Войти' : 'Нет аккаунта? Зарегистрироваться';
|
|
1066
|
+
document.getElementById('auth-err').textContent = '';
|
|
1067
|
+
}
|
|
1068
|
+
|
|
1069
|
+
document.getElementById('btn-login-open').addEventListener('click', () => openAuth(false));
|
|
1070
|
+
document.getElementById('btn-hero-start').addEventListener('click', () => currentUser ? document.getElementById('cabinet-box')?.scrollIntoView({ behavior: 'smooth', block: 'center' }) : openAuth(true));
|
|
1071
|
+
document.getElementById('btn-free-start')?.addEventListener('click', () => currentUser ? document.getElementById('cabinet-box')?.scrollIntoView({ behavior: 'smooth', block: 'center' }) : openAuth(true));
|
|
1072
|
+
document.getElementById('auth-close').addEventListener('click', () => { document.getElementById('auth-modal').hidden = true; });
|
|
1073
|
+
document.getElementById('auth-toggle').addEventListener('click', () => openAuth(!isReg));
|
|
1074
|
+
|
|
1075
|
+
let onOfferAccepted = null;
|
|
1076
|
+
const offerModal = document.getElementById('offer-modal');
|
|
1077
|
+
const offerChk1 = document.getElementById('offer-chk-1');
|
|
1078
|
+
const offerChk2 = document.getElementById('offer-chk-2');
|
|
1079
|
+
const offerAcceptBtn = document.getElementById('btn-offer-accept');
|
|
1080
|
+
|
|
1081
|
+
function syncOfferBtn() {
|
|
1082
|
+
if (offerAcceptBtn) offerAcceptBtn.disabled = !(offerChk1?.checked && offerChk2?.checked);
|
|
1083
|
+
}
|
|
1084
|
+
offerChk1?.addEventListener('change', syncOfferBtn);
|
|
1085
|
+
offerChk2?.addEventListener('change', syncOfferBtn);
|
|
1086
|
+
|
|
1087
|
+
function requireOfferAgreement(actionFn) {
|
|
1088
|
+
onOfferAccepted = actionFn;
|
|
1089
|
+
if (offerChk1) offerChk1.checked = false;
|
|
1090
|
+
if (offerChk2) offerChk2.checked = false;
|
|
1091
|
+
syncOfferBtn();
|
|
1092
|
+
offerModal.hidden = false;
|
|
1093
|
+
}
|
|
1094
|
+
|
|
1095
|
+
document.getElementById('btn-offer-decline')?.addEventListener('click', () => {
|
|
1096
|
+
offerModal.hidden = true;
|
|
1097
|
+
onOfferAccepted = null;
|
|
1098
|
+
});
|
|
1099
|
+
offerAcceptBtn?.addEventListener('click', async () => {
|
|
1100
|
+
offerAcceptBtn.disabled = true;
|
|
1101
|
+
try {
|
|
1102
|
+
await fetch('/api/auth/accept-offer', { method: 'POST' }).catch(() => {});
|
|
1103
|
+
offerModal.hidden = true;
|
|
1104
|
+
if (onOfferAccepted) await onOfferAccepted();
|
|
1105
|
+
} finally {
|
|
1106
|
+
onOfferAccepted = null;
|
|
1107
|
+
syncOfferBtn();
|
|
1108
|
+
}
|
|
1109
|
+
});
|
|
1110
|
+
|
|
1111
|
+
async function startCheckout(plan) {
|
|
1112
|
+
requireOfferAgreement(async () => {
|
|
1113
|
+
try {
|
|
1114
|
+
const res = await fetch('/api/billing/checkout', {
|
|
1115
|
+
method: 'POST',
|
|
1116
|
+
headers: { 'Content-Type': 'application/json' },
|
|
1117
|
+
body: JSON.stringify({ plan, months: selectedMonths, returnOrigin: location.origin }),
|
|
1118
|
+
});
|
|
1119
|
+
const j = await res.json();
|
|
1120
|
+
if (!res.ok) throw new Error(j.error || 'Ошибка перехода к оплате');
|
|
1121
|
+
if (j.confirmationUrl) location.href = j.confirmationUrl;
|
|
1122
|
+
} catch (e) {
|
|
1123
|
+
alert(e.message);
|
|
1124
|
+
}
|
|
1125
|
+
});
|
|
1126
|
+
}
|
|
1127
|
+
|
|
1128
|
+
document.getElementById('btn-vip-req')?.addEventListener('click', () => {
|
|
1129
|
+
document.getElementById('vip-modal').hidden = false;
|
|
1130
|
+
});
|
|
1131
|
+
document.getElementById('btn-vip-token-open')?.addEventListener('click', () => {
|
|
1132
|
+
if (!currentUser) { openAuth(true); return; }
|
|
1133
|
+
document.getElementById('vip-modal').hidden = false;
|
|
1134
|
+
document.querySelector('#vip-token-form input[name=code]')?.focus();
|
|
1135
|
+
});
|
|
1136
|
+
document.getElementById('btn-vip-close')?.addEventListener('click', () => {
|
|
1137
|
+
document.getElementById('vip-modal').hidden = true;
|
|
1138
|
+
});
|
|
1139
|
+
document.getElementById('vip-req-form')?.addEventListener('submit', async (e) => {
|
|
1140
|
+
e.preventDefault();
|
|
1141
|
+
const f = e.target.elements;
|
|
1142
|
+
const res = await fetch('/api/auth/vip-request', {
|
|
1143
|
+
method: 'POST',
|
|
1144
|
+
headers: { 'Content-Type': 'application/json' },
|
|
1145
|
+
body: JSON.stringify({ name: f.name.value, contact: f.contact.value, capitalRub: f.capitalRub.value }),
|
|
1146
|
+
});
|
|
1147
|
+
const j = await res.json();
|
|
1148
|
+
if (!res.ok) return alert(j.error || 'Ошибка отправки заявки');
|
|
1149
|
+
document.getElementById('vip-modal').hidden = true;
|
|
1150
|
+
alert('Заявка на тариф VIP отправлена администратору! Мы свяжемся с вами для согласования условий и выдачи персонального VIP-токена.');
|
|
1151
|
+
});
|
|
1152
|
+
document.getElementById('vip-token-form')?.addEventListener('submit', (e) => {
|
|
1153
|
+
e.preventDefault();
|
|
1154
|
+
const code = e.target.elements.code.value.trim();
|
|
1155
|
+
if (!code) return;
|
|
1156
|
+
if (!currentUser) {
|
|
1157
|
+
document.getElementById('vip-modal').hidden = true;
|
|
1158
|
+
openAuth(true);
|
|
1159
|
+
return;
|
|
1160
|
+
}
|
|
1161
|
+
document.getElementById('vip-modal').hidden = true;
|
|
1162
|
+
requireOfferAgreement(async () => {
|
|
1163
|
+
const r = await fetch('/api/auth/redeem-promo', {
|
|
1164
|
+
method: 'POST',
|
|
1165
|
+
headers: { 'Content-Type': 'application/json' },
|
|
1166
|
+
body: JSON.stringify({ code }),
|
|
1167
|
+
});
|
|
1168
|
+
const j = await r.json();
|
|
1169
|
+
if (!r.ok) return alert(j.error || 'Не удалось активировать VIP-токен');
|
|
1170
|
+
currentUser = j.user;
|
|
1171
|
+
renderCabinet();
|
|
1172
|
+
alert(`Персональный VIP-токен активирован! Ваш тариф: ${currentUser.planName}`);
|
|
1173
|
+
});
|
|
1174
|
+
});
|
|
1175
|
+
|
|
1176
|
+
document.querySelectorAll('[data-buy]').forEach((b) => b.addEventListener('click', () => {
|
|
1177
|
+
const plan = b.dataset.buy;
|
|
1178
|
+
if (!currentUser) {
|
|
1179
|
+
pendingPlan = plan;
|
|
1180
|
+
openAuth(true);
|
|
1181
|
+
return;
|
|
1182
|
+
}
|
|
1183
|
+
startCheckout(plan);
|
|
1184
|
+
}));
|
|
1185
|
+
|
|
1186
|
+
document.getElementById('auth-form').addEventListener('submit', async (e) => {
|
|
1187
|
+
e.preventDefault();
|
|
1188
|
+
const f = e.target.elements;
|
|
1189
|
+
const url = isReg ? '/api/auth/register' : '/api/auth/login';
|
|
1190
|
+
try {
|
|
1191
|
+
const res = await fetch(url, {
|
|
1192
|
+
method: 'POST',
|
|
1193
|
+
headers: { 'Content-Type': 'application/json' },
|
|
1194
|
+
body: JSON.stringify({ name: f.name.value, email: f.email.value, password: f.password.value }),
|
|
1195
|
+
});
|
|
1196
|
+
const j = await res.json();
|
|
1197
|
+
if (!res.ok) throw new Error(j.error || 'Ошибка авторизации');
|
|
1198
|
+
currentUser = j.user;
|
|
1199
|
+
document.getElementById('auth-modal').hidden = true;
|
|
1200
|
+
document.getElementById('btn-login-open').textContent = `${currentUser.name} · ${currentUser.planName}`;
|
|
1201
|
+
renderCabinet();
|
|
1202
|
+
if (pendingPlan) {
|
|
1203
|
+
const p = pendingPlan;
|
|
1204
|
+
pendingPlan = null;
|
|
1205
|
+
await startCheckout(p);
|
|
1206
|
+
} else {
|
|
1207
|
+
document.getElementById('cabinet-box')?.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
|
1208
|
+
}
|
|
1209
|
+
} catch (err) {
|
|
1210
|
+
document.getElementById('auth-err').textContent = err.message;
|
|
1211
|
+
}
|
|
1212
|
+
});
|
|
1213
|
+
|
|
1214
|
+
loadShowcase();
|
|
1215
|
+
</script>
|
|
1216
|
+
</body>
|
|
1217
|
+
</html>
|