@timmeck/trading-brain 2.31.10 → 2.31.11
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/dashboard.html +486 -486
- package/dist/cli/commands/paper.d.ts +2 -0
- package/dist/cli/commands/paper.js +108 -0
- package/dist/cli/commands/paper.js.map +1 -0
- package/dist/config.js +22 -0
- package/dist/config.js.map +1 -1
- package/dist/dashboard/renderer.d.ts +2 -0
- package/dist/dashboard/renderer.js +23 -0
- package/dist/dashboard/renderer.js.map +1 -1
- package/dist/db/migrations/010_paper_trading.d.ts +2 -0
- package/dist/db/migrations/010_paper_trading.js +71 -0
- package/dist/db/migrations/010_paper_trading.js.map +1 -0
- package/dist/db/migrations/index.js +8 -6
- package/dist/db/migrations/index.js.map +1 -1
- package/dist/db/repositories/paper.repository.d.ts +43 -0
- package/dist/db/repositories/paper.repository.js +201 -0
- package/dist/db/repositories/paper.repository.js.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/ipc/router.d.ts +1 -0
- package/dist/ipc/router.js +8 -0
- package/dist/ipc/router.js.map +1 -1
- package/dist/mcp/tools.js +21 -0
- package/dist/mcp/tools.js.map +1 -1
- package/dist/paper/__tests__/indicators.test.d.ts +1 -0
- package/dist/paper/__tests__/indicators.test.js +126 -0
- package/dist/paper/__tests__/indicators.test.js.map +1 -0
- package/dist/paper/decision-engine.d.ts +41 -0
- package/dist/paper/decision-engine.js +151 -0
- package/dist/paper/decision-engine.js.map +1 -0
- package/dist/paper/indicators.d.ts +26 -0
- package/dist/paper/indicators.js +134 -0
- package/dist/paper/indicators.js.map +1 -0
- package/dist/paper/paper-engine.d.ts +31 -0
- package/dist/paper/paper-engine.js +175 -0
- package/dist/paper/paper-engine.js.map +1 -0
- package/dist/paper/paper.service.d.ts +30 -0
- package/dist/paper/paper.service.js +56 -0
- package/dist/paper/paper.service.js.map +1 -0
- package/dist/paper/portfolio-manager.d.ts +32 -0
- package/dist/paper/portfolio-manager.js +113 -0
- package/dist/paper/portfolio-manager.js.map +1 -0
- package/dist/paper/price-fetcher.d.ts +24 -0
- package/dist/paper/price-fetcher.js +189 -0
- package/dist/paper/price-fetcher.js.map +1 -0
- package/dist/paper/types.d.ts +82 -0
- package/dist/paper/types.js +2 -0
- package/dist/paper/types.js.map +1 -0
- package/dist/trading-core.d.ts +1 -0
- package/dist/trading-core.js +15 -0
- package/dist/trading-core.js.map +1 -1
- package/dist/types/config.types.d.ts +17 -0
- package/package.json +1 -1
package/dashboard.html
CHANGED
|
@@ -1,486 +1,486 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="UTF-8">
|
|
5
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
-
<title>Trading Brain — Dashboard</title>
|
|
7
|
-
<style>
|
|
8
|
-
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800;900&display=swap');
|
|
9
|
-
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
|
|
10
|
-
:root{
|
|
11
|
-
--bg:#04060e;--bg2:rgba(10,12,24,.7);--bg3:rgba(20,24,50,.6);--bg4:rgba(30,35,70,.5);
|
|
12
|
-
--glass:rgba(15,18,40,.55);--glass-border:rgba(100,120,255,.12);--glass-hover:rgba(100,120,255,.2);
|
|
13
|
-
--text:#e8eaf6;--text2:#8b8fb0;--text3:#4a4d6e;
|
|
14
|
-
--blue:#5b9cff;--red:#ff5577;--green:#3dffa0;
|
|
15
|
-
--purple:#b47aff;--orange:#ffb347;--cyan:#47e5ff;
|
|
16
|
-
--accent:linear-gradient(135deg,#3dffa0,#47e5ff,#5b9cff);
|
|
17
|
-
--radius:16px;--radius-sm:10px;
|
|
18
|
-
}
|
|
19
|
-
html{scroll-behavior:smooth}
|
|
20
|
-
body{font-family:'Inter',system-ui,sans-serif;background:var(--bg);color:var(--text);line-height:1.6;min-height:100vh;overflow-x:hidden}
|
|
21
|
-
|
|
22
|
-
#neural-bg{position:fixed;top:0;left:0;width:100%;height:100%;z-index:0;pointer-events:none}
|
|
23
|
-
|
|
24
|
-
.orb{position:fixed;border-radius:50%;filter:blur(120px);opacity:.12;pointer-events:none;z-index:0}
|
|
25
|
-
.orb-1{width:600px;height:600px;background:var(--green);top:-200px;left:-100px;animation:orb-float 20s ease-in-out infinite}
|
|
26
|
-
.orb-2{width:500px;height:500px;background:var(--cyan);bottom:-150px;right:-100px;animation:orb-float 25s ease-in-out infinite reverse}
|
|
27
|
-
.orb-3{width:400px;height:400px;background:var(--blue);top:40%;left:50%;animation:orb-float 18s ease-in-out infinite 5s}
|
|
28
|
-
@keyframes orb-float{0%,100%{transform:translate(0,0) scale(1)}33%{transform:translate(60px,-40px) scale(1.1)}66%{transform:translate(-40px,60px) scale(.9)}}
|
|
29
|
-
|
|
30
|
-
.container{max-width:1400px;margin:0 auto;padding:0 28px;position:relative;z-index:1}
|
|
31
|
-
|
|
32
|
-
.reveal{opacity:0;transform:translateY(30px);transition:opacity .6s ease,transform .6s ease}
|
|
33
|
-
.reveal.visible{opacity:1;transform:translateY(0)}
|
|
34
|
-
.reveal-delay-1{transition-delay:.1s}.reveal-delay-2{transition-delay:.2s}
|
|
35
|
-
.reveal-delay-3{transition-delay:.3s}.reveal-delay-4{transition-delay:.4s}
|
|
36
|
-
.reveal-delay-5{transition-delay:.5s}
|
|
37
|
-
|
|
38
|
-
section{margin-bottom:56px}
|
|
39
|
-
|
|
40
|
-
header{padding:60px 0 24px;text-align:center;position:relative}
|
|
41
|
-
.logo{display:flex;align-items:center;justify-content:center;gap:20px;margin-bottom:12px}
|
|
42
|
-
.logo-icon{
|
|
43
|
-
width:68px;height:68px;border-radius:18px;
|
|
44
|
-
background:linear-gradient(135deg,var(--green),var(--cyan),var(--blue));
|
|
45
|
-
display:flex;align-items:center;justify-content:center;font-size:32px;
|
|
46
|
-
box-shadow:0 0 60px rgba(61,255,160,.35),0 0 120px rgba(71,229,255,.15);
|
|
47
|
-
animation:icon-breathe 4s ease-in-out infinite;position:relative;
|
|
48
|
-
}
|
|
49
|
-
.logo-icon::after{
|
|
50
|
-
content:'';position:absolute;inset:-3px;border-radius:20px;
|
|
51
|
-
background:linear-gradient(135deg,var(--green),var(--cyan));
|
|
52
|
-
opacity:.4;filter:blur(8px);z-index:-1;animation:icon-breathe 4s ease-in-out infinite reverse;
|
|
53
|
-
}
|
|
54
|
-
@keyframes icon-breathe{0%,100%{box-shadow:0 0 60px rgba(61,255,160,.35),0 0 120px rgba(71,229,255,.15)}50%{box-shadow:0 0 80px rgba(61,255,160,.5),0 0 160px rgba(71,229,255,.25)}}
|
|
55
|
-
.logo h1{font-size:2.8rem;font-weight:900;letter-spacing:-1px;background:linear-gradient(135deg,#fff 0%,var(--green) 50%,var(--cyan) 100%);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text}
|
|
56
|
-
.tagline{color:var(--text2);font-size:1.05rem;font-weight:300;letter-spacing:.5px}
|
|
57
|
-
|
|
58
|
-
.activity{display:inline-flex;align-items:center;gap:10px;margin-top:16px;padding:8px 20px;border-radius:30px;background:var(--glass);border:1px solid var(--glass-border);backdrop-filter:blur(20px)}
|
|
59
|
-
.activity-dot{width:8px;height:8px;border-radius:50%;background:var(--green);box-shadow:0 0 12px var(--green);animation:pulse-dot 2s ease-in-out infinite}
|
|
60
|
-
@keyframes pulse-dot{0%,100%{opacity:1;box-shadow:0 0 12px var(--green)}50%{opacity:.5;box-shadow:0 0 20px var(--green)}}
|
|
61
|
-
.activity-text{font-size:.8rem;color:var(--text2);font-weight:500}
|
|
62
|
-
.activity-bar{width:80px;height:4px;border-radius:2px;background:var(--bg4);overflow:hidden}
|
|
63
|
-
.activity-fill{height:100%;border-radius:2px;background:linear-gradient(90deg,var(--green),var(--cyan));transition:width 1.5s ease}
|
|
64
|
-
|
|
65
|
-
nav{display:flex;justify-content:center;gap:8px;flex-wrap:wrap;padding:20px 0;margin-bottom:40px}
|
|
66
|
-
nav a{color:var(--text2);text-decoration:none;padding:8px 18px;border-radius:24px;font-size:.85rem;font-weight:500;transition:all .3s ease;border:1px solid transparent;backdrop-filter:blur(10px)}
|
|
67
|
-
nav a:hover{color:var(--text);background:var(--glass);border-color:var(--glass-border);transform:translateY(-1px)}
|
|
68
|
-
nav a.research{background:var(--glass);color:var(--cyan);border-color:rgba(71,229,255,.25);font-weight:600;box-shadow:0 0 20px rgba(71,229,255,.1)}
|
|
69
|
-
|
|
70
|
-
.stats-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:18px}
|
|
71
|
-
.stat-card{
|
|
72
|
-
background:var(--glass);border:1px solid var(--glass-border);border-radius:var(--radius);
|
|
73
|
-
padding:28px 22px;text-align:center;position:relative;overflow:hidden;
|
|
74
|
-
transition:all .35s ease;backdrop-filter:blur(20px);
|
|
75
|
-
}
|
|
76
|
-
.stat-card:hover{transform:translateY(-4px);border-color:var(--glass-hover);box-shadow:0 20px 60px rgba(0,0,0,.3)}
|
|
77
|
-
.stat-card::before{content:'';position:absolute;top:0;left:0;right:0;height:2px}
|
|
78
|
-
.stat-card::after{content:'';position:absolute;top:0;left:0;right:0;bottom:0;background:radial-gradient(ellipse at 50% 0%,rgba(255,255,255,.03),transparent 70%);pointer-events:none}
|
|
79
|
-
.stat-card.blue::before{background:linear-gradient(90deg,transparent,var(--blue),transparent)}
|
|
80
|
-
.stat-card.purple::before{background:linear-gradient(90deg,transparent,var(--purple),transparent)}
|
|
81
|
-
.stat-card.red::before{background:linear-gradient(90deg,transparent,var(--red),transparent)}
|
|
82
|
-
.stat-card.green::before{background:linear-gradient(90deg,transparent,var(--green),transparent)}
|
|
83
|
-
.stat-card.orange::before{background:linear-gradient(90deg,transparent,var(--orange),transparent)}
|
|
84
|
-
.stat-card.cyan::before{background:linear-gradient(90deg,transparent,var(--cyan),transparent)}
|
|
85
|
-
.stat-number{font-size:2.6rem;font-weight:900;letter-spacing:-2px}
|
|
86
|
-
.stat-card.blue .stat-number{color:var(--blue)}.stat-card.purple .stat-number{color:var(--purple)}
|
|
87
|
-
.stat-card.red .stat-number{color:var(--red)}.stat-card.green .stat-number{color:var(--green)}
|
|
88
|
-
.stat-card.orange .stat-number{color:var(--orange)}.stat-card.cyan .stat-number{color:var(--cyan)}
|
|
89
|
-
.stat-label{color:var(--text2);font-size:.82rem;margin-top:6px;font-weight:500;letter-spacing:.3px;text-transform:uppercase}
|
|
90
|
-
|
|
91
|
-
.section-title{font-size:1.5rem;font-weight:700;margin-bottom:24px;display:flex;align-items:center;gap:12px}
|
|
92
|
-
.section-title .icon{font-size:1.2rem;width:38px;height:38px;border-radius:var(--radius-sm);display:flex;align-items:center;justify-content:center;backdrop-filter:blur(10px)}
|
|
93
|
-
|
|
94
|
-
/* Win rate gauge */
|
|
95
|
-
.gauge-container{display:flex;justify-content:center;padding:20px 0}
|
|
96
|
-
.gauge{position:relative;width:200px;height:120px}
|
|
97
|
-
.gauge svg{width:200px;height:120px}
|
|
98
|
-
.gauge-bg{fill:none;stroke:var(--bg4);stroke-width:12;stroke-linecap:round}
|
|
99
|
-
.gauge-fill{fill:none;stroke-width:12;stroke-linecap:round;transition:stroke-dashoffset 1.5s ease;filter:drop-shadow(0 0 8px var(--green))}
|
|
100
|
-
.gauge-value{position:absolute;bottom:8px;left:50%;transform:translateX(-50%);font-size:2.2rem;font-weight:900;color:var(--green)}
|
|
101
|
-
.gauge-label{text-align:center;color:var(--text2);font-size:.85rem;margin-top:8px;font-weight:500}
|
|
102
|
-
|
|
103
|
-
/* Recent trades */
|
|
104
|
-
.trade-list{display:grid;grid-template-columns:repeat(auto-fill,minmax(340px,1fr));gap:14px}
|
|
105
|
-
.trade-card{
|
|
106
|
-
background:var(--glass);border:1px solid var(--glass-border);border-radius:var(--radius-sm);
|
|
107
|
-
padding:18px;border-left:3px solid var(--text3);transition:all .25s ease;backdrop-filter:blur(20px);
|
|
108
|
-
}
|
|
109
|
-
.trade-card:hover{transform:translateX(6px);border-color:var(--glass-hover);box-shadow:0 8px 30px rgba(0,0,0,.2)}
|
|
110
|
-
.trade-card.win{border-left-color:var(--green)}.trade-card.loss{border-left-color:var(--red)}
|
|
111
|
-
.trade-meta{display:flex;align-items:center;gap:8px;margin-bottom:8px;flex-wrap:wrap}
|
|
112
|
-
.trade-result{font-size:.72rem;padding:3px 10px;border-radius:12px;text-transform:uppercase;font-weight:700;letter-spacing:.5px}
|
|
113
|
-
.trade-result.win{background:rgba(61,255,160,.15);color:var(--green);border:1px solid rgba(61,255,160,.25)}
|
|
114
|
-
.trade-result.loss{background:rgba(255,85,119,.15);color:var(--red);border:1px solid rgba(255,85,119,.25)}
|
|
115
|
-
.trade-card p{color:var(--text2);font-size:.85rem;line-height:1.5}
|
|
116
|
-
.trade-details{display:flex;gap:16px;margin-top:10px;font-size:.78rem;color:var(--text3)}
|
|
117
|
-
.trade-details span{display:flex;align-items:center;gap:4px}
|
|
118
|
-
|
|
119
|
-
/* Chain badges */
|
|
120
|
-
.chain-list{display:grid;grid-template-columns:repeat(auto-fill,minmax(260px,1fr));gap:14px}
|
|
121
|
-
.chain-card{
|
|
122
|
-
background:var(--glass);border:1px solid var(--glass-border);border-radius:var(--radius-sm);
|
|
123
|
-
padding:16px;transition:all .25s ease;backdrop-filter:blur(20px);display:flex;align-items:center;gap:14px;
|
|
124
|
-
}
|
|
125
|
-
.chain-card:hover{transform:translateX(4px);border-color:var(--glass-hover)}
|
|
126
|
-
.chain-icon{font-size:1.5rem}
|
|
127
|
-
.chain-info{flex:1}
|
|
128
|
-
.chain-pair{font-weight:700;font-size:.95rem}
|
|
129
|
-
.chain-type{font-size:.78rem;color:var(--text2)}
|
|
130
|
-
.chain-length{font-size:1.3rem;font-weight:900;min-width:40px;text-align:center}
|
|
131
|
-
.chain-length.win{color:var(--green)}.chain-length.loss{color:var(--red)}
|
|
132
|
-
|
|
133
|
-
/* Insight tabs */
|
|
134
|
-
.tab-bar{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:24px}
|
|
135
|
-
.tab-btn{
|
|
136
|
-
padding:10px 20px;border-radius:24px;border:1px solid var(--glass-border);
|
|
137
|
-
background:var(--glass);color:var(--text2);cursor:pointer;font-size:.85rem;font-weight:500;
|
|
138
|
-
transition:all .3s ease;backdrop-filter:blur(10px);font-family:inherit;
|
|
139
|
-
}
|
|
140
|
-
.tab-btn:hover{border-color:var(--glass-hover);color:var(--text);transform:translateY(-1px)}
|
|
141
|
-
.tab-btn.active{border-color:rgba(71,229,255,.35);color:var(--cyan);background:rgba(71,229,255,.08);box-shadow:0 0 20px rgba(71,229,255,.1)}
|
|
142
|
-
.tab-btn .count{background:var(--bg4);padding:2px 8px;border-radius:12px;font-size:.72rem;margin-left:6px;font-weight:600}
|
|
143
|
-
.tab-panel{display:none}.tab-panel.active{display:block}
|
|
144
|
-
.insight-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(380px,1fr));gap:14px}
|
|
145
|
-
.insight-card{
|
|
146
|
-
background:var(--glass);border:1px solid var(--glass-border);border-radius:var(--radius-sm);
|
|
147
|
-
padding:18px;border-left:3px solid var(--text3);transition:all .25s ease;backdrop-filter:blur(20px);
|
|
148
|
-
}
|
|
149
|
-
.insight-card:hover{transform:translateX(6px);border-color:var(--glass-hover);box-shadow:0 8px 30px rgba(0,0,0,.2)}
|
|
150
|
-
.insight-card.cyan{border-left-color:var(--cyan)}.insight-card.orange{border-left-color:var(--orange)}
|
|
151
|
-
.insight-card.green{border-left-color:var(--green)}.insight-card.red{border-left-color:var(--red)}
|
|
152
|
-
.insight-card.purple{border-left-color:var(--purple)}.insight-card.blue{border-left-color:var(--blue)}
|
|
153
|
-
.insight-header{display:flex;align-items:center;gap:8px;margin-bottom:8px;flex-wrap:wrap}
|
|
154
|
-
.insight-card p{color:var(--text2);font-size:.85rem;line-height:1.5}
|
|
155
|
-
.prio{font-size:.68rem;padding:3px 10px;border-radius:12px;text-transform:uppercase;font-weight:700;letter-spacing:.5px}
|
|
156
|
-
.prio-high{background:rgba(255,179,71,.15);color:var(--orange);border:1px solid rgba(255,179,71,.25)}
|
|
157
|
-
.prio-medium{background:rgba(91,156,255,.15);color:var(--blue);border:1px solid rgba(91,156,255,.25)}
|
|
158
|
-
.prio-low{background:rgba(139,143,176,.1);color:var(--text2);border:1px solid rgba(139,143,176,.2)}
|
|
159
|
-
.empty{color:var(--text3);font-style:italic;padding:24px}
|
|
160
|
-
|
|
161
|
-
/* Rules */
|
|
162
|
-
.rules-list{display:grid;grid-template-columns:repeat(auto-fill,minmax(340px,1fr));gap:14px}
|
|
163
|
-
.rule-card{
|
|
164
|
-
background:var(--glass);border:1px solid var(--glass-border);border-radius:var(--radius-sm);
|
|
165
|
-
padding:16px;transition:all .25s ease;backdrop-filter:blur(20px);
|
|
166
|
-
}
|
|
167
|
-
.rule-card:hover{transform:translateX(4px);border-color:var(--glass-hover)}
|
|
168
|
-
.rule-pattern{font-size:.75rem;color:var(--cyan);font-weight:600;margin-bottom:6px;font-family:'Fira Code',monospace}
|
|
169
|
-
.rule-recommendation{color:var(--text2);font-size:.85rem}
|
|
170
|
-
.rule-confidence{display:inline-flex;align-items:center;gap:6px;margin-top:8px;font-size:.75rem;color:var(--text3)}
|
|
171
|
-
.confidence-bar{width:60px;height:4px;border-radius:2px;background:var(--bg4);overflow:hidden}
|
|
172
|
-
.confidence-fill{height:100%;border-radius:2px;background:var(--green)}
|
|
173
|
-
|
|
174
|
-
/* Synapse graph */
|
|
175
|
-
.graph-container{position:relative;background:var(--glass);border:1px solid var(--glass-border);border-radius:var(--radius);overflow:hidden;backdrop-filter:blur(20px)}
|
|
176
|
-
#synapse-graph{width:100%;height:650px;display:block;cursor:grab}
|
|
177
|
-
#synapse-graph:active{cursor:grabbing}
|
|
178
|
-
.graph-legend{display:flex;gap:16px;flex-wrap:wrap;padding:12px 20px;border-top:1px solid var(--glass-border);font-size:.8rem;color:var(--text2)}
|
|
179
|
-
.legend-dot{display:inline-block;width:10px;height:10px;border-radius:50%;margin-right:6px;vertical-align:middle}
|
|
180
|
-
.graph-tooltip{position:absolute;display:none;background:var(--bg2);border:1px solid var(--glass-border);border-radius:8px;padding:8px 14px;font-size:.8rem;color:var(--text);pointer-events:none;z-index:10;backdrop-filter:blur(20px);box-shadow:0 8px 30px rgba(0,0,0,.3)}
|
|
181
|
-
|
|
182
|
-
/* Calibration */
|
|
183
|
-
.cal-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:14px}
|
|
184
|
-
.cal-card{background:var(--glass);border:1px solid var(--glass-border);border-radius:var(--radius-sm);padding:18px;text-align:center;backdrop-filter:blur(20px)}
|
|
185
|
-
.cal-value{font-size:1.6rem;font-weight:800;color:var(--cyan)}
|
|
186
|
-
.cal-label{font-size:.78rem;color:var(--text2);margin-top:4px;text-transform:uppercase;letter-spacing:.3px}
|
|
187
|
-
|
|
188
|
-
footer{text-align:center;padding:40px 0;border-top:1px solid var(--glass-border)}
|
|
189
|
-
footer p{color:var(--text3);font-size:.8rem}
|
|
190
|
-
footer code{background:var(--glass);padding:3px 10px;border-radius:6px;font-size:.78rem;border:1px solid var(--glass-border)}
|
|
191
|
-
|
|
192
|
-
@media(max-width:600px){.stats-grid{grid-template-columns:1fr 1fr}.insight-grid{grid-template-columns:1fr}.trade-list{grid-template-columns:1fr}.logo h1{font-size:2rem}}
|
|
193
|
-
</style>
|
|
194
|
-
</head>
|
|
195
|
-
<body>
|
|
196
|
-
|
|
197
|
-
<canvas id="neural-bg"></canvas>
|
|
198
|
-
<div class="orb orb-1"></div>
|
|
199
|
-
<div class="orb orb-2"></div>
|
|
200
|
-
<div class="orb orb-3"></div>
|
|
201
|
-
|
|
202
|
-
<div class="container">
|
|
203
|
-
<header class="reveal">
|
|
204
|
-
<div class="logo">
|
|
205
|
-
<div class="logo-icon">💹</div>
|
|
206
|
-
<h1>Trading Brain</h1>
|
|
207
|
-
</div>
|
|
208
|
-
<p class="tagline">Adaptive Trading Intelligence & Signal Learning</p>
|
|
209
|
-
<div class="activity">
|
|
210
|
-
<span class="activity-dot"></span>
|
|
211
|
-
<span class="activity-text">Trading Intelligence</span>
|
|
212
|
-
<div class="activity-bar"><div class="activity-fill" style="width:0%" data-target="{{ACTIVITY}}"></div></div>
|
|
213
|
-
<span class="activity-text" style="color:var(--cyan);font-weight:700">{{ACTIVITY}}%</span>
|
|
214
|
-
</div>
|
|
215
|
-
</header>
|
|
216
|
-
|
|
217
|
-
<nav class="reveal reveal-delay-1">
|
|
218
|
-
<a href="#stats">Stats</a>
|
|
219
|
-
<a href="#ecosystem">Ecosystem</a>
|
|
220
|
-
<a href="#winrate">Win Rate</a>
|
|
221
|
-
<a href="#trades">Recent Trades</a>
|
|
222
|
-
<a href="#chains">Chains</a>
|
|
223
|
-
<a href="#network">🔬 Network</a>
|
|
224
|
-
<a href="#rules">Rules</a>
|
|
225
|
-
<a href="#calibration">Calibration</a>
|
|
226
|
-
<a href="#research" class="research">💡 Research</a>
|
|
227
|
-
</nav>
|
|
228
|
-
|
|
229
|
-
<section id="stats" class="reveal reveal-delay-2">
|
|
230
|
-
<div class="section-title"><div class="icon" style="background:rgba(61,255,160,.1)">📊</div> Trading Status</div>
|
|
231
|
-
<div class="stats-grid">
|
|
232
|
-
<div class="stat-card green"><div class="stat-number">{{TRADES}}</div><div class="stat-label">Trades</div></div>
|
|
233
|
-
<div class="stat-card blue"><div class="stat-number">{{RULES}}</div><div class="stat-label">Rules</div></div>
|
|
234
|
-
<div class="stat-card cyan"><div class="stat-number">{{CHAINS}}</div><div class="stat-label">Chains</div></div>
|
|
235
|
-
<div class="stat-card orange"><div class="stat-number">{{INSIGHTS}}</div><div class="stat-label">Insights</div></div>
|
|
236
|
-
<div class="stat-card purple"><div class="stat-number">{{SYNAPSES}}</div><div class="stat-label">Synapses</div></div>
|
|
237
|
-
<div class="stat-card red"><div class="stat-number">{{GRAPH_NODES}}</div><div class="stat-label">Graph Nodes</div></div>
|
|
238
|
-
</div>
|
|
239
|
-
</section>
|
|
240
|
-
|
|
241
|
-
<section id="ecosystem" class="reveal reveal-delay-3">
|
|
242
|
-
<div class="section-title"><div class="icon" style="background:rgba(180,122,255,.1)">🌐</div> Ecosystem Peers</div>
|
|
243
|
-
<div class="stats-grid">{{ECOSYSTEM_PEERS}}</div>
|
|
244
|
-
</section>
|
|
245
|
-
|
|
246
|
-
<section id="winrate" class="reveal reveal-delay-3">
|
|
247
|
-
<div class="section-title"><div class="icon" style="background:rgba(61,255,160,.1)">🏆</div> Win Rate</div>
|
|
248
|
-
<div class="gauge-container">
|
|
249
|
-
<div>
|
|
250
|
-
<div class="gauge">
|
|
251
|
-
<svg viewBox="0 0 200 120">
|
|
252
|
-
<path class="gauge-bg" d="M 20 100 A 80 80 0 0 1 180 100"/>
|
|
253
|
-
<path class="gauge-fill" d="M 20 100 A 80 80 0 0 1 180 100" stroke="url(#gaugeGrad)" stroke-dasharray="251.2" stroke-dashoffset="{{GAUGE_OFFSET}}"/>
|
|
254
|
-
<defs><linearGradient id="gaugeGrad" x1="0" y1="0" x2="1" y2="0"><stop offset="0%" stop-color="var(--red)"/><stop offset="50%" stop-color="var(--orange)"/><stop offset="100%" stop-color="var(--green)"/></linearGradient></defs>
|
|
255
|
-
</svg>
|
|
256
|
-
<div class="gauge-value">{{WIN_RATE}}%</div>
|
|
257
|
-
</div>
|
|
258
|
-
<div class="gauge-label">Recent Win Rate</div>
|
|
259
|
-
</div>
|
|
260
|
-
</div>
|
|
261
|
-
</section>
|
|
262
|
-
|
|
263
|
-
<section id="trades" class="reveal reveal-delay-3">
|
|
264
|
-
<div class="section-title"><div class="icon" style="background:rgba(91,156,255,.1)">📈</div> Recent Trades</div>
|
|
265
|
-
<div class="trade-list">{{RECENT_TRADES}}</div>
|
|
266
|
-
</section>
|
|
267
|
-
|
|
268
|
-
<section id="chains" class="reveal reveal-delay-4">
|
|
269
|
-
<div class="section-title"><div class="icon" style="background:rgba(255,179,71,.1)">⛓</div> Active Chains</div>
|
|
270
|
-
<div class="chain-list">{{CHAINS_LIST}}</div>
|
|
271
|
-
</section>
|
|
272
|
-
|
|
273
|
-
<section id="network" class="reveal reveal-delay-4">
|
|
274
|
-
<div class="section-title"><div class="icon" style="background:rgba(71,229,255,.1)">🔬</div> Synapse Network</div>
|
|
275
|
-
<div class="graph-container">
|
|
276
|
-
<canvas id="synapse-graph"></canvas>
|
|
277
|
-
<div class="graph-legend">
|
|
278
|
-
<span><span class="legend-dot" style="background:#3dffa0"></span> signal</span>
|
|
279
|
-
<span><span class="legend-dot" style="background:#5b9cff"></span> combo</span>
|
|
280
|
-
<span><span class="legend-dot" style="background:#b47aff"></span> outcome</span>
|
|
281
|
-
<span><span class="legend-dot" style="background:#ffb347"></span> pair</span>
|
|
282
|
-
<span><span class="legend-dot" style="background:#ff5577"></span> regime</span>
|
|
283
|
-
<span><span class="legend-dot" style="background:#47e5ff"></span> strategy</span>
|
|
284
|
-
</div>
|
|
285
|
-
<div id="graph-tooltip" class="graph-tooltip"></div>
|
|
286
|
-
</div>
|
|
287
|
-
</section>
|
|
288
|
-
|
|
289
|
-
<section id="rules" class="reveal reveal-delay-5">
|
|
290
|
-
<div class="section-title"><div class="icon" style="background:rgba(255,179,71,.1)">📋</div> Learned Rules</div>
|
|
291
|
-
<div class="rules-list">{{RULES_LIST}}</div>
|
|
292
|
-
</section>
|
|
293
|
-
|
|
294
|
-
<section id="calibration" class="reveal reveal-delay-5">
|
|
295
|
-
<div class="section-title"><div class="icon" style="background:rgba(180,122,255,.1)">⚙</div> Adaptive Calibration</div>
|
|
296
|
-
<div class="cal-grid">
|
|
297
|
-
<div class="cal-card"><div class="cal-value">{{CAL_STAGE}}</div><div class="cal-label">Stage</div></div>
|
|
298
|
-
<div class="cal-card"><div class="cal-value">{{CAL_LEARNING_RATE}}</div><div class="cal-label">Learning Rate</div></div>
|
|
299
|
-
<div class="cal-card"><div class="cal-value">{{CAL_WILSON_Z}}</div><div class="cal-label">Wilson Z</div></div>
|
|
300
|
-
<div class="cal-card"><div class="cal-value">{{CAL_DECAY}}</div><div class="cal-label">Decay Half-Life</div></div>
|
|
301
|
-
</div>
|
|
302
|
-
</section>
|
|
303
|
-
|
|
304
|
-
<section id="research" class="reveal reveal-delay-5">
|
|
305
|
-
<div class="section-title"><div class="icon" style="background:rgba(71,229,255,.1)">🔬</div> Research Insights</div>
|
|
306
|
-
<div class="tab-bar">
|
|
307
|
-
<button class="tab-btn active" data-tab="trends">📈 Trends <span class="count">{{TRENDS_COUNT}}</span></button>
|
|
308
|
-
<button class="tab-btn" data-tab="gaps">⚠️ Gaps <span class="count">{{GAPS_COUNT}}</span></button>
|
|
309
|
-
<button class="tab-btn" data-tab="synergies">⚡ Synergies <span class="count">{{SYNERGIES_COUNT}}</span></button>
|
|
310
|
-
<button class="tab-btn" data-tab="performance">🏆 Performance <span class="count">{{PERFORMANCE_COUNT}}</span></button>
|
|
311
|
-
<button class="tab-btn" data-tab="regimes">🔄 Regime Shifts <span class="count">{{REGIMES_COUNT}}</span></button>
|
|
312
|
-
</div>
|
|
313
|
-
<div class="tab-panel active" id="tab-trends"><div class="insight-grid">{{TRENDS}}</div></div>
|
|
314
|
-
<div class="tab-panel" id="tab-gaps"><div class="insight-grid">{{GAPS}}</div></div>
|
|
315
|
-
<div class="tab-panel" id="tab-synergies"><div class="insight-grid">{{SYNERGIES}}</div></div>
|
|
316
|
-
<div class="tab-panel" id="tab-performance"><div class="insight-grid">{{PERFORMANCE}}</div></div>
|
|
317
|
-
<div class="tab-panel" id="tab-regimes"><div class="insight-grid">{{REGIMES}}</div></div>
|
|
318
|
-
</section>
|
|
319
|
-
|
|
320
|
-
<footer class="reveal reveal-delay-5">
|
|
321
|
-
<p>Trading Brain v{{VERSION}} — <code>trading dashboard</code></p>
|
|
322
|
-
</footer>
|
|
323
|
-
</div>
|
|
324
|
-
|
|
325
|
-
<script>
|
|
326
|
-
// Neural Network Canvas
|
|
327
|
-
(function(){
|
|
328
|
-
const canvas = document.getElementById('neural-bg');
|
|
329
|
-
const ctx = canvas.getContext('2d');
|
|
330
|
-
let W, H, nodes = [], mouse = {x:-1000,y:-1000};
|
|
331
|
-
function resize(){ W = canvas.width = window.innerWidth; H = canvas.height = window.innerHeight; }
|
|
332
|
-
resize();
|
|
333
|
-
window.addEventListener('resize', resize);
|
|
334
|
-
document.addEventListener('mousemove', e => { mouse.x = e.clientX; mouse.y = e.clientY; });
|
|
335
|
-
const NODE_COUNT = Math.min(80, Math.floor(window.innerWidth / 18));
|
|
336
|
-
for(let i = 0; i < NODE_COUNT; i++){
|
|
337
|
-
nodes.push({ x: Math.random()*W, y: Math.random()*H, vx: (Math.random()-.5)*.4, vy: (Math.random()-.5)*.4, r: Math.random()*2+1, pulse: Math.random()*Math.PI*2 });
|
|
338
|
-
}
|
|
339
|
-
function draw(){
|
|
340
|
-
ctx.clearRect(0,0,W,H);
|
|
341
|
-
for(let i=0;i<nodes.length;i++){
|
|
342
|
-
for(let j=i+1;j<nodes.length;j++){
|
|
343
|
-
const dx=nodes[i].x-nodes[j].x,dy=nodes[i].y-nodes[j].y,dist=Math.sqrt(dx*dx+dy*dy);
|
|
344
|
-
if(dist<180){ctx.strokeStyle='rgba(61,255,160,'+(1-dist/180)*.15+')';ctx.lineWidth=.5;ctx.beginPath();ctx.moveTo(nodes[i].x,nodes[i].y);ctx.lineTo(nodes[j].x,nodes[j].y);ctx.stroke();}
|
|
345
|
-
}
|
|
346
|
-
const mdx=nodes[i].x-mouse.x,mdy=nodes[i].y-mouse.y,mDist=Math.sqrt(mdx*mdx+mdy*mdy);
|
|
347
|
-
if(mDist<200){ctx.strokeStyle='rgba(71,229,255,'+(1-mDist/200)*.4+')';ctx.lineWidth=1;ctx.beginPath();ctx.moveTo(nodes[i].x,nodes[i].y);ctx.lineTo(mouse.x,mouse.y);ctx.stroke();}
|
|
348
|
-
}
|
|
349
|
-
const time=Date.now()*.001;
|
|
350
|
-
for(const n of nodes){
|
|
351
|
-
ctx.fillStyle='rgba(61,255,160,'+(0.4+Math.sin(time*1.5+n.pulse)*.3)+')';ctx.beginPath();ctx.arc(n.x,n.y,n.r,0,Math.PI*2);ctx.fill();
|
|
352
|
-
n.x+=n.vx;n.y+=n.vy;if(n.x<0||n.x>W)n.vx*=-1;if(n.y<0||n.y>H)n.vy*=-1;
|
|
353
|
-
}
|
|
354
|
-
requestAnimationFrame(draw);
|
|
355
|
-
}
|
|
356
|
-
draw();
|
|
357
|
-
})();
|
|
358
|
-
|
|
359
|
-
// Reveal on scroll
|
|
360
|
-
const observer = new IntersectionObserver(entries => { entries.forEach(e => { if(e.isIntersecting) e.target.classList.add('visible'); }); }, {threshold: 0.1});
|
|
361
|
-
document.querySelectorAll('.reveal').forEach(el => observer.observe(el));
|
|
362
|
-
|
|
363
|
-
// Tab switching
|
|
364
|
-
document.querySelectorAll('.tab-btn').forEach(btn => {
|
|
365
|
-
btn.addEventListener('click', () => {
|
|
366
|
-
document.querySelectorAll('.tab-btn').forEach(b => b.classList.remove('active'));
|
|
367
|
-
document.querySelectorAll('.tab-panel').forEach(p => p.classList.remove('active'));
|
|
368
|
-
btn.classList.add('active');
|
|
369
|
-
document.getElementById('tab-' + btn.dataset.tab).classList.add('active');
|
|
370
|
-
});
|
|
371
|
-
});
|
|
372
|
-
|
|
373
|
-
// Animate stat numbers
|
|
374
|
-
const numObserver = new IntersectionObserver(entries => {
|
|
375
|
-
entries.forEach(e => {
|
|
376
|
-
if(!e.isIntersecting) return;
|
|
377
|
-
const el = e.target; if(el.dataset.animated) return; el.dataset.animated = '1';
|
|
378
|
-
const target = parseInt(el.textContent.replace(/\D/g,''), 10);
|
|
379
|
-
if(isNaN(target) || target === 0) return;
|
|
380
|
-
const start = performance.now();
|
|
381
|
-
function tick(now){ const t = Math.min((now-start)/1200,1); el.textContent = Math.round(target*(1-Math.pow(1-t,3))).toLocaleString(); if(t<1) requestAnimationFrame(tick); }
|
|
382
|
-
requestAnimationFrame(tick);
|
|
383
|
-
});
|
|
384
|
-
}, {threshold: 0.5});
|
|
385
|
-
document.querySelectorAll('.stat-number').forEach(el => numObserver.observe(el));
|
|
386
|
-
|
|
387
|
-
// Activity bar + confidence bars
|
|
388
|
-
setTimeout(() => { document.querySelectorAll('.activity-fill').forEach(el => { el.style.width = el.dataset.target + '%'; }); }, 500);
|
|
389
|
-
setTimeout(() => { document.querySelectorAll('.confidence-fill').forEach(el => { el.style.width = el.dataset.width + '%'; }); }, 600);
|
|
390
|
-
|
|
391
|
-
// Synapse Force-Directed Graph
|
|
392
|
-
(function(){
|
|
393
|
-
const edges = {{GRAPH_EDGES}};
|
|
394
|
-
const canvas = document.getElementById('synapse-graph');
|
|
395
|
-
if (!canvas || !edges.length) return;
|
|
396
|
-
const ctx = canvas.getContext('2d');
|
|
397
|
-
const container = canvas.parentElement;
|
|
398
|
-
let W, H, dpr, frame = 0;
|
|
399
|
-
|
|
400
|
-
const NODE_COLORS = { signal:'#3dffa0', combo:'#5b9cff', outcome:'#b47aff', pair:'#ffb347', regime:'#ff5577', strategy:'#47e5ff' };
|
|
401
|
-
const DEFAULT_COLOR = '#47e5ff';
|
|
402
|
-
|
|
403
|
-
const nodeMap = new Map();
|
|
404
|
-
const graphEdges = [];
|
|
405
|
-
for (const e of edges) {
|
|
406
|
-
if (!nodeMap.has(e.s)) nodeMap.set(e.s, { id:e.s, type:e.s.split(':')[0], x:0, y:0, vx:0, vy:0, connections:0 });
|
|
407
|
-
if (!nodeMap.has(e.t)) nodeMap.set(e.t, { id:e.t, type:e.t.split(':')[0], x:0, y:0, vx:0, vy:0, connections:0 });
|
|
408
|
-
nodeMap.get(e.s).connections++; nodeMap.get(e.t).connections++;
|
|
409
|
-
graphEdges.push({ source:nodeMap.get(e.s), target:nodeMap.get(e.t), type:e.type, weight:e.w });
|
|
410
|
-
}
|
|
411
|
-
const nodes = [...nodeMap.values()];
|
|
412
|
-
|
|
413
|
-
function resize() {
|
|
414
|
-
dpr = window.devicePixelRatio||1; W = container.clientWidth; H = 650;
|
|
415
|
-
canvas.width = W*dpr; canvas.height = H*dpr;
|
|
416
|
-
canvas.style.width = W+'px'; canvas.style.height = H+'px';
|
|
417
|
-
ctx.setTransform(dpr,0,0,dpr,0,0);
|
|
418
|
-
}
|
|
419
|
-
resize(); window.addEventListener('resize', resize);
|
|
420
|
-
|
|
421
|
-
const typeGroups = {};
|
|
422
|
-
for (const n of nodes) { if(!typeGroups[n.type]) typeGroups[n.type]=[]; typeGroups[n.type].push(n); }
|
|
423
|
-
const types = Object.keys(typeGroups);
|
|
424
|
-
types.forEach((t,i) => {
|
|
425
|
-
const angle = (i/types.length)*Math.PI*2;
|
|
426
|
-
const cx = W/2+Math.cos(angle)*W*.2, cy = H/2+Math.sin(angle)*H*.2;
|
|
427
|
-
for (const n of typeGroups[t]) { n.x = cx+(Math.random()-.5)*W*.25; n.y = cy+(Math.random()-.5)*H*.25; }
|
|
428
|
-
});
|
|
429
|
-
|
|
430
|
-
let hovered=null, dragging=null, dragOff={x:0,y:0};
|
|
431
|
-
function simulate() {
|
|
432
|
-
for(let i=0;i<nodes.length;i++) for(let j=i+1;j<nodes.length;j++){
|
|
433
|
-
let dx=nodes[i].x-nodes[j].x,dy=nodes[i].y-nodes[j].y,dist=Math.sqrt(dx*dx+dy*dy)||1;
|
|
434
|
-
let f=4000/(dist*dist),fx=(dx/dist)*f,fy=(dy/dist)*f;
|
|
435
|
-
nodes[i].vx+=fx;nodes[i].vy+=fy;nodes[j].vx-=fx;nodes[j].vy-=fy;
|
|
436
|
-
}
|
|
437
|
-
for(const e of graphEdges){
|
|
438
|
-
let dx=e.target.x-e.source.x,dy=e.target.y-e.source.y,dist=Math.sqrt(dx*dx+dy*dy)||1;
|
|
439
|
-
let f=(dist-120)*.006*e.weight,fx=(dx/dist)*f,fy=(dy/dist)*f;
|
|
440
|
-
e.source.vx+=fx;e.source.vy+=fy;e.target.vx-=fx;e.target.vy-=fy;
|
|
441
|
-
}
|
|
442
|
-
for(const n of nodes){n.vx+=(W/2-n.x)*.0015;n.vy+=(H/2-n.y)*.0015;}
|
|
443
|
-
for(const n of nodes){
|
|
444
|
-
if(n===dragging) continue;
|
|
445
|
-
n.vx*=.88;n.vy*=.88;n.x+=n.vx;n.y+=n.vy;
|
|
446
|
-
n.x=Math.max(30,Math.min(W-30,n.x));n.y=Math.max(30,Math.min(H-30,n.y));
|
|
447
|
-
}
|
|
448
|
-
}
|
|
449
|
-
function getR(n){return Math.min(20,4+Math.sqrt(n.connections)*3.5);}
|
|
450
|
-
function draw(){
|
|
451
|
-
frame++; ctx.clearRect(0,0,W,H);
|
|
452
|
-
for(const e of graphEdges){
|
|
453
|
-
const a=.1+e.weight*.4;
|
|
454
|
-
ctx.strokeStyle='rgba(71,229,255,'+Math.min(.7,a)+')';
|
|
455
|
-
ctx.lineWidth=.5+e.weight*2.5;ctx.beginPath();ctx.moveTo(e.source.x,e.source.y);ctx.lineTo(e.target.x,e.target.y);ctx.stroke();
|
|
456
|
-
}
|
|
457
|
-
for(const n of nodes){
|
|
458
|
-
const r=getR(n),color=NODE_COLORS[n.type]||DEFAULT_COLOR,isH=n===hovered||n===dragging,isHub=n.connections>=5;
|
|
459
|
-
ctx.shadowColor=color;ctx.shadowBlur=isH?30:(isHub?15+Math.sin(frame*.03+n.x)*5:8);
|
|
460
|
-
if(isHub||isH){ctx.strokeStyle=color;ctx.globalAlpha=isH?.6:.25;ctx.lineWidth=1.5;ctx.beginPath();ctx.arc(n.x,n.y,r+3,0,Math.PI*2);ctx.stroke();}
|
|
461
|
-
ctx.globalAlpha=isH?1:.85;ctx.fillStyle=color;ctx.beginPath();ctx.arc(n.x,n.y,r,0,Math.PI*2);ctx.fill();
|
|
462
|
-
ctx.globalAlpha=.3;ctx.fillStyle='#fff';ctx.beginPath();ctx.arc(n.x-r*.25,n.y-r*.25,r*.4,0,Math.PI*2);ctx.fill();
|
|
463
|
-
ctx.globalAlpha=1;ctx.shadowBlur=0;
|
|
464
|
-
if(isH||n.connections>=4){ctx.fillStyle='#e8eaf6';ctx.font=(isH?'bold 12px':'10px')+' Inter,system-ui,sans-serif';ctx.textAlign='center';ctx.globalAlpha=isH?1:.7;ctx.fillText(isH?n.id:n.type,n.x,n.y-r-8);ctx.globalAlpha=1;}
|
|
465
|
-
}
|
|
466
|
-
simulate(); requestAnimationFrame(draw);
|
|
467
|
-
}
|
|
468
|
-
draw();
|
|
469
|
-
|
|
470
|
-
const tooltip=document.getElementById('graph-tooltip');
|
|
471
|
-
function getNodeAt(mx,my){for(let i=nodes.length-1;i>=0;i--){const n=nodes[i];if(Math.hypot(mx-n.x,my-n.y)<=getR(n)+4)return n;}return null;}
|
|
472
|
-
function getPos(e){const r=canvas.getBoundingClientRect();return{x:e.clientX-r.left,y:e.clientY-r.top};}
|
|
473
|
-
canvas.addEventListener('mousemove',function(e){
|
|
474
|
-
const p=getPos(e);
|
|
475
|
-
if(dragging){dragging.x=p.x+dragOff.x;dragging.y=p.y+dragOff.y;dragging.vx=0;dragging.vy=0;return;}
|
|
476
|
-
const n=getNodeAt(p.x,p.y);hovered=n;canvas.style.cursor=n?'pointer':'grab';
|
|
477
|
-
if(n){const conns=graphEdges.filter(e=>e.source===n||e.target===n);tooltip.innerHTML='<strong>'+n.id+'</strong><br>'+conns.length+' connections';tooltip.style.display='block';tooltip.style.left=(p.x+15)+'px';tooltip.style.top=(p.y-10)+'px';}
|
|
478
|
-
else{tooltip.style.display='none';}
|
|
479
|
-
});
|
|
480
|
-
canvas.addEventListener('mousedown',function(e){const p=getPos(e);const n=getNodeAt(p.x,p.y);if(n){dragging=n;dragOff={x:n.x-p.x,y:n.y-p.y};canvas.style.cursor='grabbing';}});
|
|
481
|
-
canvas.addEventListener('mouseup',function(){dragging=null;});
|
|
482
|
-
canvas.addEventListener('mouseleave',function(){dragging=null;hovered=null;tooltip.style.display='none';});
|
|
483
|
-
})();
|
|
484
|
-
</script>
|
|
485
|
-
</body>
|
|
486
|
-
</html>
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>Trading Brain — Dashboard</title>
|
|
7
|
+
<style>
|
|
8
|
+
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800;900&display=swap');
|
|
9
|
+
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
|
|
10
|
+
:root{
|
|
11
|
+
--bg:#04060e;--bg2:rgba(10,12,24,.7);--bg3:rgba(20,24,50,.6);--bg4:rgba(30,35,70,.5);
|
|
12
|
+
--glass:rgba(15,18,40,.55);--glass-border:rgba(100,120,255,.12);--glass-hover:rgba(100,120,255,.2);
|
|
13
|
+
--text:#e8eaf6;--text2:#8b8fb0;--text3:#4a4d6e;
|
|
14
|
+
--blue:#5b9cff;--red:#ff5577;--green:#3dffa0;
|
|
15
|
+
--purple:#b47aff;--orange:#ffb347;--cyan:#47e5ff;
|
|
16
|
+
--accent:linear-gradient(135deg,#3dffa0,#47e5ff,#5b9cff);
|
|
17
|
+
--radius:16px;--radius-sm:10px;
|
|
18
|
+
}
|
|
19
|
+
html{scroll-behavior:smooth}
|
|
20
|
+
body{font-family:'Inter',system-ui,sans-serif;background:var(--bg);color:var(--text);line-height:1.6;min-height:100vh;overflow-x:hidden}
|
|
21
|
+
|
|
22
|
+
#neural-bg{position:fixed;top:0;left:0;width:100%;height:100%;z-index:0;pointer-events:none}
|
|
23
|
+
|
|
24
|
+
.orb{position:fixed;border-radius:50%;filter:blur(120px);opacity:.12;pointer-events:none;z-index:0}
|
|
25
|
+
.orb-1{width:600px;height:600px;background:var(--green);top:-200px;left:-100px;animation:orb-float 20s ease-in-out infinite}
|
|
26
|
+
.orb-2{width:500px;height:500px;background:var(--cyan);bottom:-150px;right:-100px;animation:orb-float 25s ease-in-out infinite reverse}
|
|
27
|
+
.orb-3{width:400px;height:400px;background:var(--blue);top:40%;left:50%;animation:orb-float 18s ease-in-out infinite 5s}
|
|
28
|
+
@keyframes orb-float{0%,100%{transform:translate(0,0) scale(1)}33%{transform:translate(60px,-40px) scale(1.1)}66%{transform:translate(-40px,60px) scale(.9)}}
|
|
29
|
+
|
|
30
|
+
.container{max-width:1400px;margin:0 auto;padding:0 28px;position:relative;z-index:1}
|
|
31
|
+
|
|
32
|
+
.reveal{opacity:0;transform:translateY(30px);transition:opacity .6s ease,transform .6s ease}
|
|
33
|
+
.reveal.visible{opacity:1;transform:translateY(0)}
|
|
34
|
+
.reveal-delay-1{transition-delay:.1s}.reveal-delay-2{transition-delay:.2s}
|
|
35
|
+
.reveal-delay-3{transition-delay:.3s}.reveal-delay-4{transition-delay:.4s}
|
|
36
|
+
.reveal-delay-5{transition-delay:.5s}
|
|
37
|
+
|
|
38
|
+
section{margin-bottom:56px}
|
|
39
|
+
|
|
40
|
+
header{padding:60px 0 24px;text-align:center;position:relative}
|
|
41
|
+
.logo{display:flex;align-items:center;justify-content:center;gap:20px;margin-bottom:12px}
|
|
42
|
+
.logo-icon{
|
|
43
|
+
width:68px;height:68px;border-radius:18px;
|
|
44
|
+
background:linear-gradient(135deg,var(--green),var(--cyan),var(--blue));
|
|
45
|
+
display:flex;align-items:center;justify-content:center;font-size:32px;
|
|
46
|
+
box-shadow:0 0 60px rgba(61,255,160,.35),0 0 120px rgba(71,229,255,.15);
|
|
47
|
+
animation:icon-breathe 4s ease-in-out infinite;position:relative;
|
|
48
|
+
}
|
|
49
|
+
.logo-icon::after{
|
|
50
|
+
content:'';position:absolute;inset:-3px;border-radius:20px;
|
|
51
|
+
background:linear-gradient(135deg,var(--green),var(--cyan));
|
|
52
|
+
opacity:.4;filter:blur(8px);z-index:-1;animation:icon-breathe 4s ease-in-out infinite reverse;
|
|
53
|
+
}
|
|
54
|
+
@keyframes icon-breathe{0%,100%{box-shadow:0 0 60px rgba(61,255,160,.35),0 0 120px rgba(71,229,255,.15)}50%{box-shadow:0 0 80px rgba(61,255,160,.5),0 0 160px rgba(71,229,255,.25)}}
|
|
55
|
+
.logo h1{font-size:2.8rem;font-weight:900;letter-spacing:-1px;background:linear-gradient(135deg,#fff 0%,var(--green) 50%,var(--cyan) 100%);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text}
|
|
56
|
+
.tagline{color:var(--text2);font-size:1.05rem;font-weight:300;letter-spacing:.5px}
|
|
57
|
+
|
|
58
|
+
.activity{display:inline-flex;align-items:center;gap:10px;margin-top:16px;padding:8px 20px;border-radius:30px;background:var(--glass);border:1px solid var(--glass-border);backdrop-filter:blur(20px)}
|
|
59
|
+
.activity-dot{width:8px;height:8px;border-radius:50%;background:var(--green);box-shadow:0 0 12px var(--green);animation:pulse-dot 2s ease-in-out infinite}
|
|
60
|
+
@keyframes pulse-dot{0%,100%{opacity:1;box-shadow:0 0 12px var(--green)}50%{opacity:.5;box-shadow:0 0 20px var(--green)}}
|
|
61
|
+
.activity-text{font-size:.8rem;color:var(--text2);font-weight:500}
|
|
62
|
+
.activity-bar{width:80px;height:4px;border-radius:2px;background:var(--bg4);overflow:hidden}
|
|
63
|
+
.activity-fill{height:100%;border-radius:2px;background:linear-gradient(90deg,var(--green),var(--cyan));transition:width 1.5s ease}
|
|
64
|
+
|
|
65
|
+
nav{display:flex;justify-content:center;gap:8px;flex-wrap:wrap;padding:20px 0;margin-bottom:40px}
|
|
66
|
+
nav a{color:var(--text2);text-decoration:none;padding:8px 18px;border-radius:24px;font-size:.85rem;font-weight:500;transition:all .3s ease;border:1px solid transparent;backdrop-filter:blur(10px)}
|
|
67
|
+
nav a:hover{color:var(--text);background:var(--glass);border-color:var(--glass-border);transform:translateY(-1px)}
|
|
68
|
+
nav a.research{background:var(--glass);color:var(--cyan);border-color:rgba(71,229,255,.25);font-weight:600;box-shadow:0 0 20px rgba(71,229,255,.1)}
|
|
69
|
+
|
|
70
|
+
.stats-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:18px}
|
|
71
|
+
.stat-card{
|
|
72
|
+
background:var(--glass);border:1px solid var(--glass-border);border-radius:var(--radius);
|
|
73
|
+
padding:28px 22px;text-align:center;position:relative;overflow:hidden;
|
|
74
|
+
transition:all .35s ease;backdrop-filter:blur(20px);
|
|
75
|
+
}
|
|
76
|
+
.stat-card:hover{transform:translateY(-4px);border-color:var(--glass-hover);box-shadow:0 20px 60px rgba(0,0,0,.3)}
|
|
77
|
+
.stat-card::before{content:'';position:absolute;top:0;left:0;right:0;height:2px}
|
|
78
|
+
.stat-card::after{content:'';position:absolute;top:0;left:0;right:0;bottom:0;background:radial-gradient(ellipse at 50% 0%,rgba(255,255,255,.03),transparent 70%);pointer-events:none}
|
|
79
|
+
.stat-card.blue::before{background:linear-gradient(90deg,transparent,var(--blue),transparent)}
|
|
80
|
+
.stat-card.purple::before{background:linear-gradient(90deg,transparent,var(--purple),transparent)}
|
|
81
|
+
.stat-card.red::before{background:linear-gradient(90deg,transparent,var(--red),transparent)}
|
|
82
|
+
.stat-card.green::before{background:linear-gradient(90deg,transparent,var(--green),transparent)}
|
|
83
|
+
.stat-card.orange::before{background:linear-gradient(90deg,transparent,var(--orange),transparent)}
|
|
84
|
+
.stat-card.cyan::before{background:linear-gradient(90deg,transparent,var(--cyan),transparent)}
|
|
85
|
+
.stat-number{font-size:2.6rem;font-weight:900;letter-spacing:-2px}
|
|
86
|
+
.stat-card.blue .stat-number{color:var(--blue)}.stat-card.purple .stat-number{color:var(--purple)}
|
|
87
|
+
.stat-card.red .stat-number{color:var(--red)}.stat-card.green .stat-number{color:var(--green)}
|
|
88
|
+
.stat-card.orange .stat-number{color:var(--orange)}.stat-card.cyan .stat-number{color:var(--cyan)}
|
|
89
|
+
.stat-label{color:var(--text2);font-size:.82rem;margin-top:6px;font-weight:500;letter-spacing:.3px;text-transform:uppercase}
|
|
90
|
+
|
|
91
|
+
.section-title{font-size:1.5rem;font-weight:700;margin-bottom:24px;display:flex;align-items:center;gap:12px}
|
|
92
|
+
.section-title .icon{font-size:1.2rem;width:38px;height:38px;border-radius:var(--radius-sm);display:flex;align-items:center;justify-content:center;backdrop-filter:blur(10px)}
|
|
93
|
+
|
|
94
|
+
/* Win rate gauge */
|
|
95
|
+
.gauge-container{display:flex;justify-content:center;padding:20px 0}
|
|
96
|
+
.gauge{position:relative;width:200px;height:120px}
|
|
97
|
+
.gauge svg{width:200px;height:120px}
|
|
98
|
+
.gauge-bg{fill:none;stroke:var(--bg4);stroke-width:12;stroke-linecap:round}
|
|
99
|
+
.gauge-fill{fill:none;stroke-width:12;stroke-linecap:round;transition:stroke-dashoffset 1.5s ease;filter:drop-shadow(0 0 8px var(--green))}
|
|
100
|
+
.gauge-value{position:absolute;bottom:8px;left:50%;transform:translateX(-50%);font-size:2.2rem;font-weight:900;color:var(--green)}
|
|
101
|
+
.gauge-label{text-align:center;color:var(--text2);font-size:.85rem;margin-top:8px;font-weight:500}
|
|
102
|
+
|
|
103
|
+
/* Recent trades */
|
|
104
|
+
.trade-list{display:grid;grid-template-columns:repeat(auto-fill,minmax(340px,1fr));gap:14px}
|
|
105
|
+
.trade-card{
|
|
106
|
+
background:var(--glass);border:1px solid var(--glass-border);border-radius:var(--radius-sm);
|
|
107
|
+
padding:18px;border-left:3px solid var(--text3);transition:all .25s ease;backdrop-filter:blur(20px);
|
|
108
|
+
}
|
|
109
|
+
.trade-card:hover{transform:translateX(6px);border-color:var(--glass-hover);box-shadow:0 8px 30px rgba(0,0,0,.2)}
|
|
110
|
+
.trade-card.win{border-left-color:var(--green)}.trade-card.loss{border-left-color:var(--red)}
|
|
111
|
+
.trade-meta{display:flex;align-items:center;gap:8px;margin-bottom:8px;flex-wrap:wrap}
|
|
112
|
+
.trade-result{font-size:.72rem;padding:3px 10px;border-radius:12px;text-transform:uppercase;font-weight:700;letter-spacing:.5px}
|
|
113
|
+
.trade-result.win{background:rgba(61,255,160,.15);color:var(--green);border:1px solid rgba(61,255,160,.25)}
|
|
114
|
+
.trade-result.loss{background:rgba(255,85,119,.15);color:var(--red);border:1px solid rgba(255,85,119,.25)}
|
|
115
|
+
.trade-card p{color:var(--text2);font-size:.85rem;line-height:1.5}
|
|
116
|
+
.trade-details{display:flex;gap:16px;margin-top:10px;font-size:.78rem;color:var(--text3)}
|
|
117
|
+
.trade-details span{display:flex;align-items:center;gap:4px}
|
|
118
|
+
|
|
119
|
+
/* Chain badges */
|
|
120
|
+
.chain-list{display:grid;grid-template-columns:repeat(auto-fill,minmax(260px,1fr));gap:14px}
|
|
121
|
+
.chain-card{
|
|
122
|
+
background:var(--glass);border:1px solid var(--glass-border);border-radius:var(--radius-sm);
|
|
123
|
+
padding:16px;transition:all .25s ease;backdrop-filter:blur(20px);display:flex;align-items:center;gap:14px;
|
|
124
|
+
}
|
|
125
|
+
.chain-card:hover{transform:translateX(4px);border-color:var(--glass-hover)}
|
|
126
|
+
.chain-icon{font-size:1.5rem}
|
|
127
|
+
.chain-info{flex:1}
|
|
128
|
+
.chain-pair{font-weight:700;font-size:.95rem}
|
|
129
|
+
.chain-type{font-size:.78rem;color:var(--text2)}
|
|
130
|
+
.chain-length{font-size:1.3rem;font-weight:900;min-width:40px;text-align:center}
|
|
131
|
+
.chain-length.win{color:var(--green)}.chain-length.loss{color:var(--red)}
|
|
132
|
+
|
|
133
|
+
/* Insight tabs */
|
|
134
|
+
.tab-bar{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:24px}
|
|
135
|
+
.tab-btn{
|
|
136
|
+
padding:10px 20px;border-radius:24px;border:1px solid var(--glass-border);
|
|
137
|
+
background:var(--glass);color:var(--text2);cursor:pointer;font-size:.85rem;font-weight:500;
|
|
138
|
+
transition:all .3s ease;backdrop-filter:blur(10px);font-family:inherit;
|
|
139
|
+
}
|
|
140
|
+
.tab-btn:hover{border-color:var(--glass-hover);color:var(--text);transform:translateY(-1px)}
|
|
141
|
+
.tab-btn.active{border-color:rgba(71,229,255,.35);color:var(--cyan);background:rgba(71,229,255,.08);box-shadow:0 0 20px rgba(71,229,255,.1)}
|
|
142
|
+
.tab-btn .count{background:var(--bg4);padding:2px 8px;border-radius:12px;font-size:.72rem;margin-left:6px;font-weight:600}
|
|
143
|
+
.tab-panel{display:none}.tab-panel.active{display:block}
|
|
144
|
+
.insight-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(380px,1fr));gap:14px}
|
|
145
|
+
.insight-card{
|
|
146
|
+
background:var(--glass);border:1px solid var(--glass-border);border-radius:var(--radius-sm);
|
|
147
|
+
padding:18px;border-left:3px solid var(--text3);transition:all .25s ease;backdrop-filter:blur(20px);
|
|
148
|
+
}
|
|
149
|
+
.insight-card:hover{transform:translateX(6px);border-color:var(--glass-hover);box-shadow:0 8px 30px rgba(0,0,0,.2)}
|
|
150
|
+
.insight-card.cyan{border-left-color:var(--cyan)}.insight-card.orange{border-left-color:var(--orange)}
|
|
151
|
+
.insight-card.green{border-left-color:var(--green)}.insight-card.red{border-left-color:var(--red)}
|
|
152
|
+
.insight-card.purple{border-left-color:var(--purple)}.insight-card.blue{border-left-color:var(--blue)}
|
|
153
|
+
.insight-header{display:flex;align-items:center;gap:8px;margin-bottom:8px;flex-wrap:wrap}
|
|
154
|
+
.insight-card p{color:var(--text2);font-size:.85rem;line-height:1.5}
|
|
155
|
+
.prio{font-size:.68rem;padding:3px 10px;border-radius:12px;text-transform:uppercase;font-weight:700;letter-spacing:.5px}
|
|
156
|
+
.prio-high{background:rgba(255,179,71,.15);color:var(--orange);border:1px solid rgba(255,179,71,.25)}
|
|
157
|
+
.prio-medium{background:rgba(91,156,255,.15);color:var(--blue);border:1px solid rgba(91,156,255,.25)}
|
|
158
|
+
.prio-low{background:rgba(139,143,176,.1);color:var(--text2);border:1px solid rgba(139,143,176,.2)}
|
|
159
|
+
.empty{color:var(--text3);font-style:italic;padding:24px}
|
|
160
|
+
|
|
161
|
+
/* Rules */
|
|
162
|
+
.rules-list{display:grid;grid-template-columns:repeat(auto-fill,minmax(340px,1fr));gap:14px}
|
|
163
|
+
.rule-card{
|
|
164
|
+
background:var(--glass);border:1px solid var(--glass-border);border-radius:var(--radius-sm);
|
|
165
|
+
padding:16px;transition:all .25s ease;backdrop-filter:blur(20px);
|
|
166
|
+
}
|
|
167
|
+
.rule-card:hover{transform:translateX(4px);border-color:var(--glass-hover)}
|
|
168
|
+
.rule-pattern{font-size:.75rem;color:var(--cyan);font-weight:600;margin-bottom:6px;font-family:'Fira Code',monospace}
|
|
169
|
+
.rule-recommendation{color:var(--text2);font-size:.85rem}
|
|
170
|
+
.rule-confidence{display:inline-flex;align-items:center;gap:6px;margin-top:8px;font-size:.75rem;color:var(--text3)}
|
|
171
|
+
.confidence-bar{width:60px;height:4px;border-radius:2px;background:var(--bg4);overflow:hidden}
|
|
172
|
+
.confidence-fill{height:100%;border-radius:2px;background:var(--green)}
|
|
173
|
+
|
|
174
|
+
/* Synapse graph */
|
|
175
|
+
.graph-container{position:relative;background:var(--glass);border:1px solid var(--glass-border);border-radius:var(--radius);overflow:hidden;backdrop-filter:blur(20px)}
|
|
176
|
+
#synapse-graph{width:100%;height:650px;display:block;cursor:grab}
|
|
177
|
+
#synapse-graph:active{cursor:grabbing}
|
|
178
|
+
.graph-legend{display:flex;gap:16px;flex-wrap:wrap;padding:12px 20px;border-top:1px solid var(--glass-border);font-size:.8rem;color:var(--text2)}
|
|
179
|
+
.legend-dot{display:inline-block;width:10px;height:10px;border-radius:50%;margin-right:6px;vertical-align:middle}
|
|
180
|
+
.graph-tooltip{position:absolute;display:none;background:var(--bg2);border:1px solid var(--glass-border);border-radius:8px;padding:8px 14px;font-size:.8rem;color:var(--text);pointer-events:none;z-index:10;backdrop-filter:blur(20px);box-shadow:0 8px 30px rgba(0,0,0,.3)}
|
|
181
|
+
|
|
182
|
+
/* Calibration */
|
|
183
|
+
.cal-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:14px}
|
|
184
|
+
.cal-card{background:var(--glass);border:1px solid var(--glass-border);border-radius:var(--radius-sm);padding:18px;text-align:center;backdrop-filter:blur(20px)}
|
|
185
|
+
.cal-value{font-size:1.6rem;font-weight:800;color:var(--cyan)}
|
|
186
|
+
.cal-label{font-size:.78rem;color:var(--text2);margin-top:4px;text-transform:uppercase;letter-spacing:.3px}
|
|
187
|
+
|
|
188
|
+
footer{text-align:center;padding:40px 0;border-top:1px solid var(--glass-border)}
|
|
189
|
+
footer p{color:var(--text3);font-size:.8rem}
|
|
190
|
+
footer code{background:var(--glass);padding:3px 10px;border-radius:6px;font-size:.78rem;border:1px solid var(--glass-border)}
|
|
191
|
+
|
|
192
|
+
@media(max-width:600px){.stats-grid{grid-template-columns:1fr 1fr}.insight-grid{grid-template-columns:1fr}.trade-list{grid-template-columns:1fr}.logo h1{font-size:2rem}}
|
|
193
|
+
</style>
|
|
194
|
+
</head>
|
|
195
|
+
<body>
|
|
196
|
+
|
|
197
|
+
<canvas id="neural-bg"></canvas>
|
|
198
|
+
<div class="orb orb-1"></div>
|
|
199
|
+
<div class="orb orb-2"></div>
|
|
200
|
+
<div class="orb orb-3"></div>
|
|
201
|
+
|
|
202
|
+
<div class="container">
|
|
203
|
+
<header class="reveal">
|
|
204
|
+
<div class="logo">
|
|
205
|
+
<div class="logo-icon">💹</div>
|
|
206
|
+
<h1>Trading Brain</h1>
|
|
207
|
+
</div>
|
|
208
|
+
<p class="tagline">Adaptive Trading Intelligence & Signal Learning</p>
|
|
209
|
+
<div class="activity">
|
|
210
|
+
<span class="activity-dot"></span>
|
|
211
|
+
<span class="activity-text">Trading Intelligence</span>
|
|
212
|
+
<div class="activity-bar"><div class="activity-fill" style="width:0%" data-target="{{ACTIVITY}}"></div></div>
|
|
213
|
+
<span class="activity-text" style="color:var(--cyan);font-weight:700">{{ACTIVITY}}%</span>
|
|
214
|
+
</div>
|
|
215
|
+
</header>
|
|
216
|
+
|
|
217
|
+
<nav class="reveal reveal-delay-1">
|
|
218
|
+
<a href="#stats">Stats</a>
|
|
219
|
+
<a href="#ecosystem">Ecosystem</a>
|
|
220
|
+
<a href="#winrate">Win Rate</a>
|
|
221
|
+
<a href="#trades">Recent Trades</a>
|
|
222
|
+
<a href="#chains">Chains</a>
|
|
223
|
+
<a href="#network">🔬 Network</a>
|
|
224
|
+
<a href="#rules">Rules</a>
|
|
225
|
+
<a href="#calibration">Calibration</a>
|
|
226
|
+
<a href="#research" class="research">💡 Research</a>
|
|
227
|
+
</nav>
|
|
228
|
+
|
|
229
|
+
<section id="stats" class="reveal reveal-delay-2">
|
|
230
|
+
<div class="section-title"><div class="icon" style="background:rgba(61,255,160,.1)">📊</div> Trading Status</div>
|
|
231
|
+
<div class="stats-grid">
|
|
232
|
+
<div class="stat-card green"><div class="stat-number">{{TRADES}}</div><div class="stat-label">Trades</div></div>
|
|
233
|
+
<div class="stat-card blue"><div class="stat-number">{{RULES}}</div><div class="stat-label">Rules</div></div>
|
|
234
|
+
<div class="stat-card cyan"><div class="stat-number">{{CHAINS}}</div><div class="stat-label">Chains</div></div>
|
|
235
|
+
<div class="stat-card orange"><div class="stat-number">{{INSIGHTS}}</div><div class="stat-label">Insights</div></div>
|
|
236
|
+
<div class="stat-card purple"><div class="stat-number">{{SYNAPSES}}</div><div class="stat-label">Synapses</div></div>
|
|
237
|
+
<div class="stat-card red"><div class="stat-number">{{GRAPH_NODES}}</div><div class="stat-label">Graph Nodes</div></div>
|
|
238
|
+
</div>
|
|
239
|
+
</section>
|
|
240
|
+
|
|
241
|
+
<section id="ecosystem" class="reveal reveal-delay-3">
|
|
242
|
+
<div class="section-title"><div class="icon" style="background:rgba(180,122,255,.1)">🌐</div> Ecosystem Peers</div>
|
|
243
|
+
<div class="stats-grid">{{ECOSYSTEM_PEERS}}</div>
|
|
244
|
+
</section>
|
|
245
|
+
|
|
246
|
+
<section id="winrate" class="reveal reveal-delay-3">
|
|
247
|
+
<div class="section-title"><div class="icon" style="background:rgba(61,255,160,.1)">🏆</div> Win Rate</div>
|
|
248
|
+
<div class="gauge-container">
|
|
249
|
+
<div>
|
|
250
|
+
<div class="gauge">
|
|
251
|
+
<svg viewBox="0 0 200 120">
|
|
252
|
+
<path class="gauge-bg" d="M 20 100 A 80 80 0 0 1 180 100"/>
|
|
253
|
+
<path class="gauge-fill" d="M 20 100 A 80 80 0 0 1 180 100" stroke="url(#gaugeGrad)" stroke-dasharray="251.2" stroke-dashoffset="{{GAUGE_OFFSET}}"/>
|
|
254
|
+
<defs><linearGradient id="gaugeGrad" x1="0" y1="0" x2="1" y2="0"><stop offset="0%" stop-color="var(--red)"/><stop offset="50%" stop-color="var(--orange)"/><stop offset="100%" stop-color="var(--green)"/></linearGradient></defs>
|
|
255
|
+
</svg>
|
|
256
|
+
<div class="gauge-value">{{WIN_RATE}}%</div>
|
|
257
|
+
</div>
|
|
258
|
+
<div class="gauge-label">Recent Win Rate</div>
|
|
259
|
+
</div>
|
|
260
|
+
</div>
|
|
261
|
+
</section>
|
|
262
|
+
|
|
263
|
+
<section id="trades" class="reveal reveal-delay-3">
|
|
264
|
+
<div class="section-title"><div class="icon" style="background:rgba(91,156,255,.1)">📈</div> Recent Trades</div>
|
|
265
|
+
<div class="trade-list">{{RECENT_TRADES}}</div>
|
|
266
|
+
</section>
|
|
267
|
+
|
|
268
|
+
<section id="chains" class="reveal reveal-delay-4">
|
|
269
|
+
<div class="section-title"><div class="icon" style="background:rgba(255,179,71,.1)">⛓</div> Active Chains</div>
|
|
270
|
+
<div class="chain-list">{{CHAINS_LIST}}</div>
|
|
271
|
+
</section>
|
|
272
|
+
|
|
273
|
+
<section id="network" class="reveal reveal-delay-4">
|
|
274
|
+
<div class="section-title"><div class="icon" style="background:rgba(71,229,255,.1)">🔬</div> Synapse Network</div>
|
|
275
|
+
<div class="graph-container">
|
|
276
|
+
<canvas id="synapse-graph"></canvas>
|
|
277
|
+
<div class="graph-legend">
|
|
278
|
+
<span><span class="legend-dot" style="background:#3dffa0"></span> signal</span>
|
|
279
|
+
<span><span class="legend-dot" style="background:#5b9cff"></span> combo</span>
|
|
280
|
+
<span><span class="legend-dot" style="background:#b47aff"></span> outcome</span>
|
|
281
|
+
<span><span class="legend-dot" style="background:#ffb347"></span> pair</span>
|
|
282
|
+
<span><span class="legend-dot" style="background:#ff5577"></span> regime</span>
|
|
283
|
+
<span><span class="legend-dot" style="background:#47e5ff"></span> strategy</span>
|
|
284
|
+
</div>
|
|
285
|
+
<div id="graph-tooltip" class="graph-tooltip"></div>
|
|
286
|
+
</div>
|
|
287
|
+
</section>
|
|
288
|
+
|
|
289
|
+
<section id="rules" class="reveal reveal-delay-5">
|
|
290
|
+
<div class="section-title"><div class="icon" style="background:rgba(255,179,71,.1)">📋</div> Learned Rules</div>
|
|
291
|
+
<div class="rules-list">{{RULES_LIST}}</div>
|
|
292
|
+
</section>
|
|
293
|
+
|
|
294
|
+
<section id="calibration" class="reveal reveal-delay-5">
|
|
295
|
+
<div class="section-title"><div class="icon" style="background:rgba(180,122,255,.1)">⚙</div> Adaptive Calibration</div>
|
|
296
|
+
<div class="cal-grid">
|
|
297
|
+
<div class="cal-card"><div class="cal-value">{{CAL_STAGE}}</div><div class="cal-label">Stage</div></div>
|
|
298
|
+
<div class="cal-card"><div class="cal-value">{{CAL_LEARNING_RATE}}</div><div class="cal-label">Learning Rate</div></div>
|
|
299
|
+
<div class="cal-card"><div class="cal-value">{{CAL_WILSON_Z}}</div><div class="cal-label">Wilson Z</div></div>
|
|
300
|
+
<div class="cal-card"><div class="cal-value">{{CAL_DECAY}}</div><div class="cal-label">Decay Half-Life</div></div>
|
|
301
|
+
</div>
|
|
302
|
+
</section>
|
|
303
|
+
|
|
304
|
+
<section id="research" class="reveal reveal-delay-5">
|
|
305
|
+
<div class="section-title"><div class="icon" style="background:rgba(71,229,255,.1)">🔬</div> Research Insights</div>
|
|
306
|
+
<div class="tab-bar">
|
|
307
|
+
<button class="tab-btn active" data-tab="trends">📈 Trends <span class="count">{{TRENDS_COUNT}}</span></button>
|
|
308
|
+
<button class="tab-btn" data-tab="gaps">⚠️ Gaps <span class="count">{{GAPS_COUNT}}</span></button>
|
|
309
|
+
<button class="tab-btn" data-tab="synergies">⚡ Synergies <span class="count">{{SYNERGIES_COUNT}}</span></button>
|
|
310
|
+
<button class="tab-btn" data-tab="performance">🏆 Performance <span class="count">{{PERFORMANCE_COUNT}}</span></button>
|
|
311
|
+
<button class="tab-btn" data-tab="regimes">🔄 Regime Shifts <span class="count">{{REGIMES_COUNT}}</span></button>
|
|
312
|
+
</div>
|
|
313
|
+
<div class="tab-panel active" id="tab-trends"><div class="insight-grid">{{TRENDS}}</div></div>
|
|
314
|
+
<div class="tab-panel" id="tab-gaps"><div class="insight-grid">{{GAPS}}</div></div>
|
|
315
|
+
<div class="tab-panel" id="tab-synergies"><div class="insight-grid">{{SYNERGIES}}</div></div>
|
|
316
|
+
<div class="tab-panel" id="tab-performance"><div class="insight-grid">{{PERFORMANCE}}</div></div>
|
|
317
|
+
<div class="tab-panel" id="tab-regimes"><div class="insight-grid">{{REGIMES}}</div></div>
|
|
318
|
+
</section>
|
|
319
|
+
|
|
320
|
+
<footer class="reveal reveal-delay-5">
|
|
321
|
+
<p>Trading Brain v{{VERSION}} — <code>trading dashboard</code></p>
|
|
322
|
+
</footer>
|
|
323
|
+
</div>
|
|
324
|
+
|
|
325
|
+
<script>
|
|
326
|
+
// Neural Network Canvas
|
|
327
|
+
(function(){
|
|
328
|
+
const canvas = document.getElementById('neural-bg');
|
|
329
|
+
const ctx = canvas.getContext('2d');
|
|
330
|
+
let W, H, nodes = [], mouse = {x:-1000,y:-1000};
|
|
331
|
+
function resize(){ W = canvas.width = window.innerWidth; H = canvas.height = window.innerHeight; }
|
|
332
|
+
resize();
|
|
333
|
+
window.addEventListener('resize', resize);
|
|
334
|
+
document.addEventListener('mousemove', e => { mouse.x = e.clientX; mouse.y = e.clientY; });
|
|
335
|
+
const NODE_COUNT = Math.min(80, Math.floor(window.innerWidth / 18));
|
|
336
|
+
for(let i = 0; i < NODE_COUNT; i++){
|
|
337
|
+
nodes.push({ x: Math.random()*W, y: Math.random()*H, vx: (Math.random()-.5)*.4, vy: (Math.random()-.5)*.4, r: Math.random()*2+1, pulse: Math.random()*Math.PI*2 });
|
|
338
|
+
}
|
|
339
|
+
function draw(){
|
|
340
|
+
ctx.clearRect(0,0,W,H);
|
|
341
|
+
for(let i=0;i<nodes.length;i++){
|
|
342
|
+
for(let j=i+1;j<nodes.length;j++){
|
|
343
|
+
const dx=nodes[i].x-nodes[j].x,dy=nodes[i].y-nodes[j].y,dist=Math.sqrt(dx*dx+dy*dy);
|
|
344
|
+
if(dist<180){ctx.strokeStyle='rgba(61,255,160,'+(1-dist/180)*.15+')';ctx.lineWidth=.5;ctx.beginPath();ctx.moveTo(nodes[i].x,nodes[i].y);ctx.lineTo(nodes[j].x,nodes[j].y);ctx.stroke();}
|
|
345
|
+
}
|
|
346
|
+
const mdx=nodes[i].x-mouse.x,mdy=nodes[i].y-mouse.y,mDist=Math.sqrt(mdx*mdx+mdy*mdy);
|
|
347
|
+
if(mDist<200){ctx.strokeStyle='rgba(71,229,255,'+(1-mDist/200)*.4+')';ctx.lineWidth=1;ctx.beginPath();ctx.moveTo(nodes[i].x,nodes[i].y);ctx.lineTo(mouse.x,mouse.y);ctx.stroke();}
|
|
348
|
+
}
|
|
349
|
+
const time=Date.now()*.001;
|
|
350
|
+
for(const n of nodes){
|
|
351
|
+
ctx.fillStyle='rgba(61,255,160,'+(0.4+Math.sin(time*1.5+n.pulse)*.3)+')';ctx.beginPath();ctx.arc(n.x,n.y,n.r,0,Math.PI*2);ctx.fill();
|
|
352
|
+
n.x+=n.vx;n.y+=n.vy;if(n.x<0||n.x>W)n.vx*=-1;if(n.y<0||n.y>H)n.vy*=-1;
|
|
353
|
+
}
|
|
354
|
+
requestAnimationFrame(draw);
|
|
355
|
+
}
|
|
356
|
+
draw();
|
|
357
|
+
})();
|
|
358
|
+
|
|
359
|
+
// Reveal on scroll
|
|
360
|
+
const observer = new IntersectionObserver(entries => { entries.forEach(e => { if(e.isIntersecting) e.target.classList.add('visible'); }); }, {threshold: 0.1});
|
|
361
|
+
document.querySelectorAll('.reveal').forEach(el => observer.observe(el));
|
|
362
|
+
|
|
363
|
+
// Tab switching
|
|
364
|
+
document.querySelectorAll('.tab-btn').forEach(btn => {
|
|
365
|
+
btn.addEventListener('click', () => {
|
|
366
|
+
document.querySelectorAll('.tab-btn').forEach(b => b.classList.remove('active'));
|
|
367
|
+
document.querySelectorAll('.tab-panel').forEach(p => p.classList.remove('active'));
|
|
368
|
+
btn.classList.add('active');
|
|
369
|
+
document.getElementById('tab-' + btn.dataset.tab).classList.add('active');
|
|
370
|
+
});
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
// Animate stat numbers
|
|
374
|
+
const numObserver = new IntersectionObserver(entries => {
|
|
375
|
+
entries.forEach(e => {
|
|
376
|
+
if(!e.isIntersecting) return;
|
|
377
|
+
const el = e.target; if(el.dataset.animated) return; el.dataset.animated = '1';
|
|
378
|
+
const target = parseInt(el.textContent.replace(/\D/g,''), 10);
|
|
379
|
+
if(isNaN(target) || target === 0) return;
|
|
380
|
+
const start = performance.now();
|
|
381
|
+
function tick(now){ const t = Math.min((now-start)/1200,1); el.textContent = Math.round(target*(1-Math.pow(1-t,3))).toLocaleString(); if(t<1) requestAnimationFrame(tick); }
|
|
382
|
+
requestAnimationFrame(tick);
|
|
383
|
+
});
|
|
384
|
+
}, {threshold: 0.5});
|
|
385
|
+
document.querySelectorAll('.stat-number').forEach(el => numObserver.observe(el));
|
|
386
|
+
|
|
387
|
+
// Activity bar + confidence bars
|
|
388
|
+
setTimeout(() => { document.querySelectorAll('.activity-fill').forEach(el => { el.style.width = el.dataset.target + '%'; }); }, 500);
|
|
389
|
+
setTimeout(() => { document.querySelectorAll('.confidence-fill').forEach(el => { el.style.width = el.dataset.width + '%'; }); }, 600);
|
|
390
|
+
|
|
391
|
+
// Synapse Force-Directed Graph
|
|
392
|
+
(function(){
|
|
393
|
+
const edges = {{GRAPH_EDGES}};
|
|
394
|
+
const canvas = document.getElementById('synapse-graph');
|
|
395
|
+
if (!canvas || !edges.length) return;
|
|
396
|
+
const ctx = canvas.getContext('2d');
|
|
397
|
+
const container = canvas.parentElement;
|
|
398
|
+
let W, H, dpr, frame = 0;
|
|
399
|
+
|
|
400
|
+
const NODE_COLORS = { signal:'#3dffa0', combo:'#5b9cff', outcome:'#b47aff', pair:'#ffb347', regime:'#ff5577', strategy:'#47e5ff' };
|
|
401
|
+
const DEFAULT_COLOR = '#47e5ff';
|
|
402
|
+
|
|
403
|
+
const nodeMap = new Map();
|
|
404
|
+
const graphEdges = [];
|
|
405
|
+
for (const e of edges) {
|
|
406
|
+
if (!nodeMap.has(e.s)) nodeMap.set(e.s, { id:e.s, type:e.s.split(':')[0], x:0, y:0, vx:0, vy:0, connections:0 });
|
|
407
|
+
if (!nodeMap.has(e.t)) nodeMap.set(e.t, { id:e.t, type:e.t.split(':')[0], x:0, y:0, vx:0, vy:0, connections:0 });
|
|
408
|
+
nodeMap.get(e.s).connections++; nodeMap.get(e.t).connections++;
|
|
409
|
+
graphEdges.push({ source:nodeMap.get(e.s), target:nodeMap.get(e.t), type:e.type, weight:e.w });
|
|
410
|
+
}
|
|
411
|
+
const nodes = [...nodeMap.values()];
|
|
412
|
+
|
|
413
|
+
function resize() {
|
|
414
|
+
dpr = window.devicePixelRatio||1; W = container.clientWidth; H = 650;
|
|
415
|
+
canvas.width = W*dpr; canvas.height = H*dpr;
|
|
416
|
+
canvas.style.width = W+'px'; canvas.style.height = H+'px';
|
|
417
|
+
ctx.setTransform(dpr,0,0,dpr,0,0);
|
|
418
|
+
}
|
|
419
|
+
resize(); window.addEventListener('resize', resize);
|
|
420
|
+
|
|
421
|
+
const typeGroups = {};
|
|
422
|
+
for (const n of nodes) { if(!typeGroups[n.type]) typeGroups[n.type]=[]; typeGroups[n.type].push(n); }
|
|
423
|
+
const types = Object.keys(typeGroups);
|
|
424
|
+
types.forEach((t,i) => {
|
|
425
|
+
const angle = (i/types.length)*Math.PI*2;
|
|
426
|
+
const cx = W/2+Math.cos(angle)*W*.2, cy = H/2+Math.sin(angle)*H*.2;
|
|
427
|
+
for (const n of typeGroups[t]) { n.x = cx+(Math.random()-.5)*W*.25; n.y = cy+(Math.random()-.5)*H*.25; }
|
|
428
|
+
});
|
|
429
|
+
|
|
430
|
+
let hovered=null, dragging=null, dragOff={x:0,y:0};
|
|
431
|
+
function simulate() {
|
|
432
|
+
for(let i=0;i<nodes.length;i++) for(let j=i+1;j<nodes.length;j++){
|
|
433
|
+
let dx=nodes[i].x-nodes[j].x,dy=nodes[i].y-nodes[j].y,dist=Math.sqrt(dx*dx+dy*dy)||1;
|
|
434
|
+
let f=4000/(dist*dist),fx=(dx/dist)*f,fy=(dy/dist)*f;
|
|
435
|
+
nodes[i].vx+=fx;nodes[i].vy+=fy;nodes[j].vx-=fx;nodes[j].vy-=fy;
|
|
436
|
+
}
|
|
437
|
+
for(const e of graphEdges){
|
|
438
|
+
let dx=e.target.x-e.source.x,dy=e.target.y-e.source.y,dist=Math.sqrt(dx*dx+dy*dy)||1;
|
|
439
|
+
let f=(dist-120)*.006*e.weight,fx=(dx/dist)*f,fy=(dy/dist)*f;
|
|
440
|
+
e.source.vx+=fx;e.source.vy+=fy;e.target.vx-=fx;e.target.vy-=fy;
|
|
441
|
+
}
|
|
442
|
+
for(const n of nodes){n.vx+=(W/2-n.x)*.0015;n.vy+=(H/2-n.y)*.0015;}
|
|
443
|
+
for(const n of nodes){
|
|
444
|
+
if(n===dragging) continue;
|
|
445
|
+
n.vx*=.88;n.vy*=.88;n.x+=n.vx;n.y+=n.vy;
|
|
446
|
+
n.x=Math.max(30,Math.min(W-30,n.x));n.y=Math.max(30,Math.min(H-30,n.y));
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
function getR(n){return Math.min(20,4+Math.sqrt(n.connections)*3.5);}
|
|
450
|
+
function draw(){
|
|
451
|
+
frame++; ctx.clearRect(0,0,W,H);
|
|
452
|
+
for(const e of graphEdges){
|
|
453
|
+
const a=.1+e.weight*.4;
|
|
454
|
+
ctx.strokeStyle='rgba(71,229,255,'+Math.min(.7,a)+')';
|
|
455
|
+
ctx.lineWidth=.5+e.weight*2.5;ctx.beginPath();ctx.moveTo(e.source.x,e.source.y);ctx.lineTo(e.target.x,e.target.y);ctx.stroke();
|
|
456
|
+
}
|
|
457
|
+
for(const n of nodes){
|
|
458
|
+
const r=getR(n),color=NODE_COLORS[n.type]||DEFAULT_COLOR,isH=n===hovered||n===dragging,isHub=n.connections>=5;
|
|
459
|
+
ctx.shadowColor=color;ctx.shadowBlur=isH?30:(isHub?15+Math.sin(frame*.03+n.x)*5:8);
|
|
460
|
+
if(isHub||isH){ctx.strokeStyle=color;ctx.globalAlpha=isH?.6:.25;ctx.lineWidth=1.5;ctx.beginPath();ctx.arc(n.x,n.y,r+3,0,Math.PI*2);ctx.stroke();}
|
|
461
|
+
ctx.globalAlpha=isH?1:.85;ctx.fillStyle=color;ctx.beginPath();ctx.arc(n.x,n.y,r,0,Math.PI*2);ctx.fill();
|
|
462
|
+
ctx.globalAlpha=.3;ctx.fillStyle='#fff';ctx.beginPath();ctx.arc(n.x-r*.25,n.y-r*.25,r*.4,0,Math.PI*2);ctx.fill();
|
|
463
|
+
ctx.globalAlpha=1;ctx.shadowBlur=0;
|
|
464
|
+
if(isH||n.connections>=4){ctx.fillStyle='#e8eaf6';ctx.font=(isH?'bold 12px':'10px')+' Inter,system-ui,sans-serif';ctx.textAlign='center';ctx.globalAlpha=isH?1:.7;ctx.fillText(isH?n.id:n.type,n.x,n.y-r-8);ctx.globalAlpha=1;}
|
|
465
|
+
}
|
|
466
|
+
simulate(); requestAnimationFrame(draw);
|
|
467
|
+
}
|
|
468
|
+
draw();
|
|
469
|
+
|
|
470
|
+
const tooltip=document.getElementById('graph-tooltip');
|
|
471
|
+
function getNodeAt(mx,my){for(let i=nodes.length-1;i>=0;i--){const n=nodes[i];if(Math.hypot(mx-n.x,my-n.y)<=getR(n)+4)return n;}return null;}
|
|
472
|
+
function getPos(e){const r=canvas.getBoundingClientRect();return{x:e.clientX-r.left,y:e.clientY-r.top};}
|
|
473
|
+
canvas.addEventListener('mousemove',function(e){
|
|
474
|
+
const p=getPos(e);
|
|
475
|
+
if(dragging){dragging.x=p.x+dragOff.x;dragging.y=p.y+dragOff.y;dragging.vx=0;dragging.vy=0;return;}
|
|
476
|
+
const n=getNodeAt(p.x,p.y);hovered=n;canvas.style.cursor=n?'pointer':'grab';
|
|
477
|
+
if(n){const conns=graphEdges.filter(e=>e.source===n||e.target===n);tooltip.innerHTML='<strong>'+n.id+'</strong><br>'+conns.length+' connections';tooltip.style.display='block';tooltip.style.left=(p.x+15)+'px';tooltip.style.top=(p.y-10)+'px';}
|
|
478
|
+
else{tooltip.style.display='none';}
|
|
479
|
+
});
|
|
480
|
+
canvas.addEventListener('mousedown',function(e){const p=getPos(e);const n=getNodeAt(p.x,p.y);if(n){dragging=n;dragOff={x:n.x-p.x,y:n.y-p.y};canvas.style.cursor='grabbing';}});
|
|
481
|
+
canvas.addEventListener('mouseup',function(){dragging=null;});
|
|
482
|
+
canvas.addEventListener('mouseleave',function(){dragging=null;hovered=null;tooltip.style.display='none';});
|
|
483
|
+
})();
|
|
484
|
+
</script>
|
|
485
|
+
</body>
|
|
486
|
+
</html>
|