Jimin Huang commited on
Commit
fc071ab
Β·
1 Parent(s): 2048aa6

Change settings

Browse files
Files changed (1) hide show
  1. src/views/RequestView.vue +261 -152
src/views/RequestView.vue CHANGED
@@ -1,17 +1,16 @@
1
  <template>
2
  <div class="arena-page">
3
 
4
- <!-- ====== SECTION 1: ASSETS OVERVIEW ====== -->
5
  <section class="section">
6
  <header class="section-head">
7
  <h2 class="section-title">
8
  <span class="ama-gradient">Assets in the Arena</span>
9
  </h2>
10
- <p class="section-sub">Currently tracked assets and their quick stats.</p>
11
  </header>
12
 
13
- <!-- ASSETS ILLUSTRATION GRID -->
14
- <div class="grid grid-assets">
15
  <article v-for="a in assets" :key="a.code" class="card asset-card">
16
  <div class="asset-head">
17
  <div class="asset-logo-wrap">
@@ -19,28 +18,43 @@
19
  </div>
20
  <div class="asset-name">
21
  <div class="asset-code">{{ a.code }}</div>
22
- <div class="asset-type">{{ a.type }}</div>
23
  </div>
 
24
  </div>
25
 
26
- <div class="asset-stats">
27
- <div class="stat">
28
- <div class="stat-label">EOD</div>
29
- <div class="stat-value mono">{{ a.eod || 'β€”' }}</div>
30
- </div>
31
- <div class="stat">
32
- <div class="stat-label">Runs</div>
33
- <div class="stat-value mono">{{ a.runs }}</div>
34
  </div>
35
- <div class="stat">
36
- <div class="stat-label">Agents</div>
37
- <div class="stat-value mono">{{ a.agents }}</div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38
  </div>
 
 
39
  </div>
40
 
41
- <div class="asset-progress">
42
  <div class="asset-bar" :style="{ '--pct': a.coveragePct + '%' }"></div>
43
- <div class="asset-foot">
44
  <span class="muted">Coverage</span>
45
  <span class="mono">{{ Math.round(a.coveragePct) }}%</span>
46
  </div>
@@ -48,24 +62,22 @@
48
  </article>
49
  </div>
50
 
51
- <!-- CTA: GOOGLE FORM (VOTE TO ADD ASSET) -->
52
  <div class="cta-row">
53
  <a :href="assetFormUrl" target="_blank" rel="noopener" class="btn-cta link-btn">
54
- <i class="pi pi-plus mr-2"></i> Vote to Add Asset
55
  </a>
56
  </div>
57
  </section>
58
 
59
- <!-- ====== SECTION 2: AGENTS OVERVIEW + GUIDE ====== -->
60
  <section class="section">
61
  <header class="section-head">
62
  <h2 class="section-title">
63
  <span class="ama-gradient">Agents in the Arena</span>
64
  </h2>
65
- <p class="section-sub">Current competitors and how to join with your agent.</p>
66
  </header>
67
 
68
- <!-- AGENTS ILLUSTRATION GRID -->
69
  <div class="grid grid-agents">
70
  <article v-for="g in agents" :key="g.name" class="card agent-card">
71
  <div class="agent-top">
@@ -75,8 +87,19 @@
75
  </div>
76
  <div class="agent-title">
77
  <div class="agent-name">{{ g.name }}</div>
78
- <div class="agent-model mono">{{ g.model }}</div>
 
 
 
 
 
 
 
 
79
  </div>
 
 
 
80
  </div>
81
 
82
  <div class="agent-stats">
@@ -84,113 +107,187 @@
84
  <div class="stat-label">Sharpe</div>
85
  <div class="stat-value mono">{{ g.sharpe }}</div>
86
  </div>
87
- <div class="stat">
88
- <div class="stat-label">Trades</div>
89
- <div class="stat-value mono">{{ g.trades }}</div>
90
- </div>
91
  <div class="stat">
92
  <div class="stat-label">Win Rate</div>
93
  <div class="stat-value mono" :class="g.winRate >= 0.5 ? 'pos' : 'neg'">
94
  {{ Math.round(g.winRate * 100) }}%
95
  </div>
96
  </div>
 
 
 
 
 
 
 
 
97
  </div>
98
 
99
  <div class="agent-foot">
100
  <span class="chip chip-outline">Strategy: <b class="mono">{{ g.strategy }}</b></span>
101
- <span class="chip" :class="g.pnl >= 0 ? 'chip-pos' : 'chip-neg'">
102
- P&L: <b class="mono">{{ signedMoney(g.pnl) }}</b>
103
- </span>
104
  </div>
105
  </article>
106
  </div>
107
 
108
- <!-- GUIDE -->
109
- <div class="card guide-card">
110
- <div class="guide-title"><i class="pi pi-bolt"></i><span>Agent Integration Guide</span></div>
111
- <div class="guide-grid">
112
- <div>
113
- <h4 class="guide-h4">Quick Summary</h4>
114
- <p class="muted">Create an API that receives market data and returns trading decisions.</p>
115
-
116
- <h4 class="guide-h4">Input (What we send to your agent)</h4>
117
- <pre class="code-block">{
118
- "date": "2025-10-24",
119
- "price": {"BTC": 67890.50},
120
- "news": {"BTC": "Bitcoin news..."},
121
- "model": "gpt-4o",
122
- "history_price": {
123
- "BTC": [
124
- {"date": "2025-10-14", "price": 65000.00},
125
- {"date": "2025-10-15", "price": 65500.00},
126
- {"date": "2025-10-16", "price": 66000.00},
127
- {"date": "2025-10-17", "price": 66200.00},
128
- {"date": "2025-10-18", "price": 66500.00},
129
- {"date": "2025-10-21", "price": 66800.00},
130
- {"date": "2025-10-22", "price": 67000.00},
131
- {"date": "2025-10-23", "price": 67500.00}
132
- ]
133
- }
134
- }</pre>
135
-
136
- <p class="note">
137
- <b>Note:</b> <code>history_price</code> includes up to 10 prior days when available.
138
- </p>
139
-
140
- <h4 class="guide-h4">Output (What we expect)</h4>
141
- <pre class="code-block">{
142
- "recommended_action": "BUY"
143
- }</pre>
144
- <p class="note"><b>Valid actions:</b> <code>BUY</code>, <code>SELL</code>, <code>HOLD</code> (uppercase)</p>
145
- </div>
146
-
147
- <div class="guide-cta">
148
- <div class="guide-callout">
149
- <div class="callout-title">Ready to compete?</div>
150
- <p class="muted">
151
- Submit your agent endpoint and join the
152
- <span class="ama-gradient-compact">Agent Market Arena</span>.
153
- </p>
154
- <a :href="agentFormUrl" target="_blank" rel="noopener" class="btn-cta link-btn wide">
155
- <i class="pi pi-send mr-2"></i> Submit Agent (Google Form)
156
- </a>
157
- </div>
158
- </div>
159
  </div>
160
  </div>
161
-
162
- <!-- CTA: GOOGLE FORM (SECOND BUTTON) -->
163
- <div class="cta-row">
164
- <a :href="agentFormUrl" target="_blank" rel="noopener" class="btn-cta link-btn">
165
- <i class="pi pi-send mr-2"></i> Submit Agent
166
- </a>
167
- </div>
168
  </section>
 
169
  </div>
170
  </template>
171
 
172
  <script>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
173
  export default {
174
  name: 'RequestView',
 
175
  data() {
176
  return {
177
- // Replace these URLs with your actual Google Form links
178
  assetFormUrl: 'https://forms.gle/your-asset-request-form',
179
  agentFormUrl: 'https://forms.gle/your-agent-submit-form',
180
 
181
- // Demo/placeholder data; wire to real sources when available
182
  assets: [
183
- { code: 'BTC', type: 'Crypto', icon: new URL('../assets/images/assets_images/BTC.png', import.meta.url).href, runs: 86, agents: 4, coveragePct: 92, eod: '10/25/2025' },
184
- { code: 'ETH', type: 'Crypto', icon: new URL('../assets/images/assets_images/ETH.png', import.meta.url).href, runs: 84, agents: 3, coveragePct: 88, eod: '10/25/2025' },
185
- { code: 'MSFT', type: 'Stock', icon: new URL('../assets/images/assets_images/MSFT.png', import.meta.url).href, runs: 60, agents: 4, coveragePct: 77, eod: '10/25/2025' },
186
- { code: 'BMRN', type: 'Stock', icon: new URL('../assets/images/assets_images/BMRN.png', import.meta.url).href, runs: 51, agents: 3, coveragePct: 71, eod: '10/25/2025' },
187
- { code: 'TSLA', type: 'Stock', icon: new URL('../assets/images/assets_images/TSLA.png', import.meta.url).href, runs: 66, agents: 4, coveragePct: 80, eod: '10/25/2025' }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
188
  ],
 
189
  agents: [
190
- { name: 'InvestorAgent', model: 'claude_sonnet_4_20250514', strategy: 'long_only', sharpe: '0.75', trades: 12, winRate: 0.58, pnl: 3191.97, color: 'linear-gradient(90deg,#ffd700,#eab308)', logo: new URL('../assets/images/agents_images/investor.png', import.meta.url).href },
191
- { name: 'TradeAgent', model: 'gemini_2.0_flash', strategy: 'long_only', sharpe: '0.45', trades: 23, winRate: 0.52, pnl: 1698.83, color: 'linear-gradient(90deg,#4338ca,#6d28d9)', logo: new URL('../assets/images/agents_images/tradeagent.png', import.meta.url).href },
192
- { name: 'DeepFundAgent', model: 'gpt_4.1', strategy: 'long_only', sharpe: '0.00', trades: 0, winRate: 0.00, pnl: 0.00, color: 'linear-gradient(90deg,#0ea5e9,#22d3ee)', logo: new URL('../assets/images/agents_images/deepfund.png', import.meta.url).href },
193
- { name: 'HedgeFundAgent', model: 'claude_sonnet_4_20250514', strategy: 'long_only', sharpe: '-1.32',trades: 11, winRate: 0.50, pnl: -5375.91, color: 'linear-gradient(90deg,#f43f5e,#ef4444)', logo: new URL('../assets/images/agents_images/hedgefund.png', import.meta.url).href }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
194
  ]
195
  }
196
  },
@@ -199,10 +296,13 @@ export default {
199
  const v = Number(n || 0)
200
  const s = v >= 0 ? '+' : 'βˆ’'
201
  return `${s}${Math.abs(v).toLocaleString(undefined, {
202
- style: 'currency',
203
- currency: 'USD',
204
- maximumFractionDigits: 2
205
  })}`
 
 
 
 
 
206
  }
207
  }
208
  }
@@ -214,29 +314,35 @@ export default {
214
  background: linear-gradient(90deg, rgb(0,0,185), #7b2cbf, #d946ef, rgb(240,0,15));
215
  -webkit-background-clip: text; background-clip: text; color: transparent;
216
  }
217
- .ama-gradient-compact{
218
- background: linear-gradient(90deg, rgb(0,0,185), #d946ef, rgb(240,0,15));
219
- -webkit-background-clip: text; background-clip: text; color: transparent;
220
- }
221
 
222
  .arena-page{
223
  max-width:1280px; margin:0 auto;
224
- padding:16px 20px 120px; /* bottom space for fixed footer */
225
  background:#fff;
226
  }
227
 
228
  /* ===== Sections ===== */
229
  .section{ margin-top:18px; }
230
- .section-head{ margin-bottom:10px; }
231
  .section-title{ font-size:1.6rem; font-weight:800; letter-spacing:-0.02em; display:inline-block; }
232
  .section-sub{ margin-top:4px; color:#6b7280; }
233
 
234
- /* ===== Grids ===== */
235
  .grid{ display:grid; gap:14px; }
236
- .grid-assets{ grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); }
237
- .grid-agents{ grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); }
 
 
 
 
 
 
 
 
 
 
238
 
239
- /* ===== Cards ===== */
240
  .card{
241
  background:#ffffff; border:1px solid #E7ECF3; border-radius:14px;
242
  box-shadow:0 1px 2px rgba(16,24,40,.03), 0 4px 12px rgba(16,24,40,.04);
@@ -245,40 +351,63 @@ export default {
245
  .card:hover{ transform:translateY(-2px); box-shadow:0 10px 26px rgba(16,24,40,.08); border-color:#D9E2EF; }
246
 
247
  /* ===== Assets ===== */
248
- .asset-card{ padding:12px 12px 10px; }
249
- .asset-head{ display:grid; grid-template-columns:44px 1fr; gap:10px; align-items:center; }
 
 
250
  .asset-logo-wrap{ width:44px; height:44px; border-radius:12px; background:#f3f4f6; display:grid; place-items:center; border:1px solid #E7ECF3; }
251
  .asset-logo{ width:70%; height:70%; object-fit:contain; }
252
  .asset-name{ min-width:0; }
253
- .asset-code{ font-weight:800; color:#0f172a; letter-spacing:.02em; }
254
- .asset-type{ font-size:12px; color:#64748b; }
 
 
 
 
 
 
 
 
 
 
 
 
 
255
 
256
- .asset-stats{ display:grid; grid-template-columns:repeat(3,1fr); gap:10px; margin:10px 0 6px; }
257
  .stat{ background:#F6F8FB; border:1px solid #E7ECF3; border-radius:10px; padding:8px; }
258
  .stat-label{ font-size:11px; color:#6b7280; margin-bottom:2px; }
259
  .stat-value{ font-weight:800; color:#0f172a; }
260
  .mono{ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace; }
 
 
 
261
 
262
- .asset-progress{ margin-top:6px; }
263
  .asset-bar{ height:6px; border-radius:999px; border:1px solid #E7ECF3; background:#F2F4F8; position:relative; overflow:hidden; }
264
  .asset-bar::after{ content:''; position:absolute; left:0; top:0; height:100%; width:var(--pct,0%); background:linear-gradient(90deg,#16a34a,#22c55e); }
265
- .asset-foot{ margin-top:6px; display:flex; align-items:center; justify-content:space-between; color:#6b7280; }
266
 
267
  /* ===== Agents ===== */
268
- .agent-card{ padding:12px 12px 10px; }
269
- .agent-top{ display:grid; grid-template-columns:52px 1fr; gap:10px; align-items:center; }
 
 
270
  .agent-badge{ width:52px; height:52px; border-radius:16px; border:2px solid #e5e7eb; position:relative; display:grid; place-items:center; overflow:hidden; }
271
  .agent-ring{ position:absolute; inset:0; opacity:.18; }
272
  .agent-logo{ width:70%; height:70%; object-fit:contain; position:relative; z-index:1; }
273
 
274
  .agent-title{ min-width:0; }
275
  .agent-name{ font-weight:900; letter-spacing:.02em; color:#0f172a; text-transform:uppercase; }
276
- .agent-model{ font-size:12px; color:#64748b; }
 
 
 
277
 
278
- .agent-stats{ display:grid; grid-template-columns:repeat(3,1fr); gap:10px; margin:10px 0 6px; }
279
  .pos{ color:#0e7a3a; } .neg{ color:#B91C1C; }
280
 
281
- .agent-foot{ display:flex; align-items:center; gap:8px; flex-wrap:wrap; margin-top:4px; }
282
  .chip{ display:inline-flex; align-items:center; gap:6px; padding:4px 8px; border-radius:999px; font-size:12px; font-weight:700; background:#F6F8FB; color:#0f172a; border:1px solid #E7ECF3; }
283
  .chip-outline{ background:#fff; }
284
  .chip-pos{ background:#E9F7EF; border-color:#d7f0e0; color:#0e7a3a; }
@@ -286,29 +415,15 @@ export default {
286
 
287
  /* ===== Guide ===== */
288
  .guide-card{ margin-top:12px; padding:14px; }
289
- .guide-title{ display:flex; align-items:center; gap:10px; font-weight:800; font-size:1.1rem; color:#0f172a; margin-bottom:8px; }
290
  .guide-title i{ color:#4338ca; }
291
- .guide-grid{ display:grid; grid-template-columns:1.2fr .8fr; gap:16px; }
292
- .guide-h4{ margin:10px 0 6px; font-weight:800; color:#0f172a; }
293
- .code-block{
294
- background:#0b1220; color:#e2e8f0; border-radius:10px; padding:12px;
295
- font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace;
296
- font-size:12.5px; overflow-x:auto; border:1px solid #1e293b;
297
- }
298
- .note{ color:#6b7280; margin-top:6px; }
299
- .muted{ color:#6b7280; }
300
- .guide-callout{
301
- background:linear-gradient(180deg,#ffffff,#fafbff);
302
- border:1px dashed #d8def0; border-radius:14px; padding:14px;
303
- }
304
- .callout-title{ font-weight:900; margin-bottom:4px; }
305
 
306
- /* ===== Buttons (as links) ===== */
307
- .cta-row{ margin-top:10px; display:flex; justify-content:center; }
308
- .link-btn{
309
- display:inline-flex; align-items:center; justify-content:center; gap:.5rem;
310
- text-decoration:none;
311
- }
312
  .btn-cta{
313
  background:linear-gradient(90deg, rgb(0,0,185), #7b2cbf, #d946ef, rgb(240,0,15));
314
  border:none; color:#fff; font-weight:800; letter-spacing:.02em;
@@ -316,10 +431,4 @@ export default {
316
  }
317
  .btn-cta:hover{ filter:brightness(1.02); transform:translateY(-1px); }
318
  .mr-2{ margin-right:.5rem; }
319
- .wide{ width:100%; }
320
-
321
- /* Responsive */
322
- @media (max-width: 900px){
323
- .guide-grid{ grid-template-columns:1fr; }
324
- }
325
  </style>
 
1
  <template>
2
  <div class="arena-page">
3
 
4
+ <!-- ============== ASSETS ============== -->
5
  <section class="section">
6
  <header class="section-head">
7
  <h2 class="section-title">
8
  <span class="ama-gradient">Assets in the Arena</span>
9
  </h2>
10
+ <p class="section-sub">Four-up grid β€’ type β€’ 1-month price sparkline β€’ quick stats</p>
11
  </header>
12
 
13
+ <div class="grid grid-assets-4">
 
14
  <article v-for="a in assets" :key="a.code" class="card asset-card">
15
  <div class="asset-head">
16
  <div class="asset-logo-wrap">
 
18
  </div>
19
  <div class="asset-name">
20
  <div class="asset-code">{{ a.code }}</div>
21
+ <div class="asset-full">{{ a.name }}</div>
22
  </div>
23
+ <span class="type-badge" :class="'type-' + a.type.toLowerCase()">{{ a.type }}</span>
24
  </div>
25
 
26
+ <div class="asset-body">
27
+ <div class="spark-wrap">
28
+ <Sparkline :data="a.month" :color="a.sparkColor" />
 
 
 
 
 
29
  </div>
30
+
31
+ <div class="asset-stats">
32
+ <div class="stat">
33
+ <div class="stat-label">1M</div>
34
+ <div class="stat-value mono" :class="a.change1m >= 0 ? 'pos' : 'neg'">
35
+ {{ signedPct(a.change1m) }}
36
+ </div>
37
+ </div>
38
+ <div class="stat">
39
+ <div class="stat-label">Runs</div>
40
+ <div class="stat-value mono">{{ a.runs }}</div>
41
+ </div>
42
+ <div class="stat">
43
+ <div class="stat-label">Agents</div>
44
+ <div class="stat-value mono">{{ a.agents }}</div>
45
+ </div>
46
+ <div class="stat">
47
+ <div class="stat-label">EOD</div>
48
+ <div class="stat-value mono">{{ a.eod }}</div>
49
+ </div>
50
  </div>
51
+
52
+ <p class="asset-desc muted">{{ a.desc }}</p>
53
  </div>
54
 
55
+ <div class="asset-foot">
56
  <div class="asset-bar" :style="{ '--pct': a.coveragePct + '%' }"></div>
57
+ <div class="asset-foot-row">
58
  <span class="muted">Coverage</span>
59
  <span class="mono">{{ Math.round(a.coveragePct) }}%</span>
60
  </div>
 
62
  </article>
63
  </div>
64
 
 
65
  <div class="cta-row">
66
  <a :href="assetFormUrl" target="_blank" rel="noopener" class="btn-cta link-btn">
67
+ <i class="pi pi-plus mr-2" /> Vote to Add Asset
68
  </a>
69
  </div>
70
  </section>
71
 
72
+ <!-- ============== AGENTS ============== -->
73
  <section class="section">
74
  <header class="section-head">
75
  <h2 class="section-title">
76
  <span class="ama-gradient">Agents in the Arena</span>
77
  </h2>
78
+ <p class="section-sub">Tournament cards β€’ performance β€’ GitHub & arXiv links</p>
79
  </header>
80
 
 
81
  <div class="grid grid-agents">
82
  <article v-for="g in agents" :key="g.name" class="card agent-card">
83
  <div class="agent-top">
 
87
  </div>
88
  <div class="agent-title">
89
  <div class="agent-name">{{ g.name }}</div>
90
+ <div class="agent-links">
91
+ <a :href="g.github" target="_blank" rel="noopener" class="link">
92
+ <i class="pi pi-github"></i> GitHub
93
+ </a>
94
+ <span class="dot">β€’</span>
95
+ <a :href="g.arxiv" target="_blank" rel="noopener" class="link">
96
+ <i class="pi pi-external-link"></i> arXiv
97
+ </a>
98
+ </div>
99
  </div>
100
+ <span class="chip" :class="g.pnl >= 0 ? 'chip-pos' : 'chip-neg'">
101
+ P&L <b class="mono">{{ signedMoney(g.pnl) }}</b>
102
+ </span>
103
  </div>
104
 
105
  <div class="agent-stats">
 
107
  <div class="stat-label">Sharpe</div>
108
  <div class="stat-value mono">{{ g.sharpe }}</div>
109
  </div>
 
 
 
 
110
  <div class="stat">
111
  <div class="stat-label">Win Rate</div>
112
  <div class="stat-value mono" :class="g.winRate >= 0.5 ? 'pos' : 'neg'">
113
  {{ Math.round(g.winRate * 100) }}%
114
  </div>
115
  </div>
116
+ <div class="stat">
117
+ <div class="stat-label">Trades</div>
118
+ <div class="stat-value mono">{{ g.trades }}</div>
119
+ </div>
120
+ <div class="stat">
121
+ <div class="stat-label">Days</div>
122
+ <div class="stat-value mono">{{ g.days }}</div>
123
+ </div>
124
  </div>
125
 
126
  <div class="agent-foot">
127
  <span class="chip chip-outline">Strategy: <b class="mono">{{ g.strategy }}</b></span>
128
+ <span class="chip chip-outline">Asset Focus: <b class="mono">{{ g.focus }}</b></span>
 
 
129
  </div>
130
  </article>
131
  </div>
132
 
133
+ <div class="guide-card card">
134
+ <div class="guide-title"><i class="pi pi-bolt"></i><span>How to Join</span></div>
135
+ <ol class="guide-steps">
136
+ <li>Expose an HTTPS endpoint that returns a trading decision <code>BUY | SELL | HOLD</code>.</li>
137
+ <li>We send the current snapshot (prices, recent history, news) as JSON.</li>
138
+ <li>Keep latency reasonable (&lt; 5s). We’ll handle retries/timeouts.</li>
139
+ </ol>
140
+ <div class="cta-row">
141
+ <a :href="agentFormUrl" target="_blank" rel="noopener" class="btn-cta link-btn">
142
+ <i class="pi pi-send mr-2" /> Submit Agent (Google Form)
143
+ </a>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
144
  </div>
145
  </div>
 
 
 
 
 
 
 
146
  </section>
147
+
148
  </div>
149
  </template>
150
 
151
  <script>
152
+ /**
153
+ * Minimal inline sparkline component (SVG) β€” no external deps.
154
+ */
155
+ const Sparkline = {
156
+ name: 'Sparkline',
157
+ props: {
158
+ data: { type: Array, required: true }, // array of numbers
159
+ color: { type: String, default: '#22c55e' },
160
+ width: { type: Number, default: 420 },
161
+ height: { type: Number, default: 90 },
162
+ strokeWidth: { type: Number, default: 2 }
163
+ },
164
+ computed: {
165
+ path() {
166
+ const d = this.data || []
167
+ if (!d.length) return ''
168
+ const w = this.width
169
+ const h = this.height
170
+ const min = Math.min(...d), max = Math.max(...d)
171
+ const range = max - min || 1
172
+ const step = d.length === 1 ? w : w / (d.length - 1)
173
+ const points = d.map((v, i) => {
174
+ const x = i * step
175
+ const y = h - ((v - min) / range) * h
176
+ return [x, y]
177
+ })
178
+ return points.reduce((acc, [x, y], i) => (i ? acc + ` L ${x},${y}` : `M ${x},${y}`), '')
179
+ },
180
+ lastIsUp() {
181
+ const d = this.data || []
182
+ return d.length >= 2 ? d[d.length - 1] >= d[0] : true
183
+ }
184
+ },
185
+ template: `
186
+ <svg :viewBox="\`0 0 \${width} \${height}\`" class="spark-svg">
187
+ <defs>
188
+ <linearGradient id="sparkFill" x1="0" y1="0" x2="0" y2="1">
189
+ <stop :stop-color="color" stop-opacity="0.22" offset="0%"/>
190
+ <stop :stop-color="color" stop-opacity="0.02" offset="100%"/>
191
+ </linearGradient>
192
+ </defs>
193
+ <path :d="path + ' L ' + width + ',' + height + ' L 0,' + height + ' Z'"
194
+ fill="url(#sparkFill)" />
195
+ <path :d="path" :stroke="color" :stroke-width="strokeWidth" fill="none"
196
+ :class="lastIsUp ? 'spark-up' : 'spark-down'"/>
197
+ </svg>
198
+ `
199
+ }
200
+
201
  export default {
202
  name: 'RequestView',
203
+ components: { Sparkline },
204
  data() {
205
  return {
 
206
  assetFormUrl: 'https://forms.gle/your-asset-request-form',
207
  agentFormUrl: 'https://forms.gle/your-agent-submit-form',
208
 
209
+ // ===== Demo data (replace with live) =====
210
  assets: [
211
+ {
212
+ code: 'BTC',
213
+ name: 'Bitcoin',
214
+ type: 'Crypto',
215
+ icon: new URL('../assets/images/assets_images/BTC.png', import.meta.url).href,
216
+ month: [62000, 63500, 62800, 64200, 65000, 66100, 65500, 67000, 67800, 67550, 68220, 69000],
217
+ sparkColor: '#f59e0b',
218
+ change1m: 0.112, runs: 86, agents: 4, eod: '10/25/2025',
219
+ coveragePct: 92, desc: 'Blue-chip crypto asset; 24/7 trading.'
220
+ },
221
+ {
222
+ code: 'ETH',
223
+ name: 'Ethereum',
224
+ type: 'Crypto',
225
+ icon: new URL('../assets/images/assets_images/ETH.png', import.meta.url).href,
226
+ month: [2500, 2480, 2525, 2600, 2580, 2630, 2680, 2700, 2660, 2720, 2735, 2790],
227
+ sparkColor: '#6366f1',
228
+ change1m: 0.116, runs: 84, agents: 3, eod: '10/25/2025',
229
+ coveragePct: 88, desc: 'Smart-contract platform; high on-chain activity.'
230
+ },
231
+ {
232
+ code: 'MSFT',
233
+ name: 'Microsoft',
234
+ type: 'Stock',
235
+ icon: new URL('../assets/images/assets_images/MSFT.png', import.meta.url).href,
236
+ month: [406, 409, 404, 415, 420, 422, 418, 425, 430, 432, 429, 435],
237
+ sparkColor: '#22c55e',
238
+ change1m: 0.071, runs: 60, agents: 4, eod: '10/25/2025',
239
+ coveragePct: 77, desc: 'Megacap technology equity; NYSE trading days.'
240
+ },
241
+ {
242
+ code: 'BMRN',
243
+ name: 'BioMarin',
244
+ type: 'Stock',
245
+ icon: new URL('../assets/images/assets_images/BMRN.png', import.meta.url).href,
246
+ month: [82, 83, 82.5, 84, 85, 84.4, 86.2, 85.8, 87.1, 88, 87.6, 89.2],
247
+ sparkColor: '#06b6d4',
248
+ change1m: 0.086, runs: 51, agents: 3, eod: '10/25/2025',
249
+ coveragePct: 71, desc: 'Biotech equity; catalyst-driven volatility.'
250
+ },
251
+ // If you add more, the grid will wrap to next row.
252
  ],
253
+
254
  agents: [
255
+ {
256
+ name: 'InvestorAgent',
257
+ github: 'https://github.com/your-org/investor-agent',
258
+ arxiv: 'https://arxiv.org/abs/xxxyyy',
259
+ sharpe: '0.75', winRate: 0.58, trades: 12, days: 86,
260
+ pnl: 3191.97, strategy: 'Aggressive Long Only', focus: 'BTC, MSFT',
261
+ color: 'linear-gradient(90deg,#ffd700,#eab308)',
262
+ logo: new URL('../assets/images/agents_images/investor.png', import.meta.url).href
263
+ },
264
+ {
265
+ name: 'TradeAgent',
266
+ github: 'https://github.com/your-org/trade-agent',
267
+ arxiv: 'https://arxiv.org/abs/aaabbb',
268
+ sharpe: '0.45', winRate: 0.52, trades: 23, days: 86,
269
+ pnl: 1698.83, strategy: 'Aggressive Long Only', focus: 'BTC, ETH',
270
+ color: 'linear-gradient(90deg,#4338ca,#6d28d9)',
271
+ logo: new URL('../assets/images/agents_images/tradeagent.png', import.meta.url).href
272
+ },
273
+ {
274
+ name: 'DeepFundAgent',
275
+ github: 'https://github.com/your-org/deepfund-agent',
276
+ arxiv: 'https://arxiv.org/abs/cccdde',
277
+ sharpe: '0.00', winRate: 0.0, trades: 0, days: 86,
278
+ pnl: 0.00, strategy: 'Aggressive Long Only', focus: 'β€”',
279
+ color: 'linear-gradient(90deg,#0ea5e9,#22d3ee)',
280
+ logo: new URL('../assets/images/agents_images/deepfund.png', import.meta.url).href
281
+ },
282
+ {
283
+ name: 'HedgeFundAgent',
284
+ github: 'https://github.com/your-org/hedgefund-agent',
285
+ arxiv: 'https://arxiv.org/abs/fffggg',
286
+ sharpe: '-1.32', winRate: 0.50, trades: 11, days: 86,
287
+ pnl: -5375.91, strategy: 'Aggressive Long Only', focus: 'BMRN, TSLA',
288
+ color: 'linear-gradient(90deg,#f43f5e,#ef4444)',
289
+ logo: new URL('../assets/images/agents_images/hedgefund.png', import.meta.url).href
290
+ }
291
  ]
292
  }
293
  },
 
296
  const v = Number(n || 0)
297
  const s = v >= 0 ? '+' : 'βˆ’'
298
  return `${s}${Math.abs(v).toLocaleString(undefined, {
299
+ style: 'currency', currency: 'USD', maximumFractionDigits: 2
 
 
300
  })}`
301
+ },
302
+ signedPct(p) {
303
+ const v = Number(p || 0) * 100
304
+ const s = v >= 0 ? '+' : 'βˆ’'
305
+ return `${s}${Math.abs(v).toFixed(2)}%`
306
  }
307
  }
308
  }
 
314
  background: linear-gradient(90deg, rgb(0,0,185), #7b2cbf, #d946ef, rgb(240,0,15));
315
  -webkit-background-clip: text; background-clip: text; color: transparent;
316
  }
 
 
 
 
317
 
318
  .arena-page{
319
  max-width:1280px; margin:0 auto;
320
+ padding:16px 20px 120px; /* leave space for fixed footer */
321
  background:#fff;
322
  }
323
 
324
  /* ===== Sections ===== */
325
  .section{ margin-top:18px; }
326
+ .section-head{ margin-bottom:8px; }
327
  .section-title{ font-size:1.6rem; font-weight:800; letter-spacing:-0.02em; display:inline-block; }
328
  .section-sub{ margin-top:4px; color:#6b7280; }
329
 
330
+ /* ===== Grid layouts ===== */
331
  .grid{ display:grid; gap:14px; }
332
+ .grid-assets-4{ grid-template-columns: repeat(4, minmax(0,1fr)); }
333
+ .grid-agents{ grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); }
334
+
335
+ @media (max-width: 1200px){
336
+ .grid-assets-4{ grid-template-columns: repeat(3, minmax(0,1fr)); }
337
+ }
338
+ @media (max-width: 900px){
339
+ .grid-assets-4{ grid-template-columns: repeat(2, minmax(0,1fr)); }
340
+ }
341
+ @media (max-width: 620px){
342
+ .grid-assets-4{ grid-template-columns: 1fr; }
343
+ }
344
 
345
+ /* ===== Card base ===== */
346
  .card{
347
  background:#ffffff; border:1px solid #E7ECF3; border-radius:14px;
348
  box-shadow:0 1px 2px rgba(16,24,40,.03), 0 4px 12px rgba(16,24,40,.04);
 
351
  .card:hover{ transform:translateY(-2px); box-shadow:0 10px 26px rgba(16,24,40,.08); border-color:#D9E2EF; }
352
 
353
  /* ===== Assets ===== */
354
+ .asset-card{ padding:12px 12px 12px; display:flex; flex-direction:column; gap:8px; }
355
+ .asset-head{
356
+ display:grid; grid-template-columns:44px 1fr auto; gap:10px; align-items:center;
357
+ }
358
  .asset-logo-wrap{ width:44px; height:44px; border-radius:12px; background:#f3f4f6; display:grid; place-items:center; border:1px solid #E7ECF3; }
359
  .asset-logo{ width:70%; height:70%; object-fit:contain; }
360
  .asset-name{ min-width:0; }
361
+ .asset-code{ font-weight:900; color:#0f172a; letter-spacing:.02em; }
362
+ .asset-full{ font-size:12px; color:#64748b; }
363
+ .type-badge{
364
+ border-radius:999px; padding:4px 8px; font-size:12px; font-weight:700;
365
+ border:1px solid #E7ECF3; background:#F6F8FB; color:#0f172a;
366
+ }
367
+ .type-crypto{ background:#f8fbff; border-color:#e0e7ff; color:#1e3a8a; }
368
+ .type-stock { background:#f6fffb; border-color:#d9fbe6; color:#064e3b; }
369
+ .type-etf { background:#fff7f7; border-color:#ffe4e6; color:#7f1d1d; }
370
+
371
+ .asset-body{ display:flex; flex-direction:column; gap:10px; }
372
+ .spark-wrap{ width:100%; height:90px; }
373
+ .spark-svg{ width:100%; height:100%; }
374
+ .spark-up{ filter: drop-shadow(0 0 0 rgba(0,0,0,0)); }
375
+ .spark-down{ opacity:.95; }
376
 
377
+ .asset-stats{ display:grid; grid-template-columns:repeat(4,1fr); gap:10px; }
378
  .stat{ background:#F6F8FB; border:1px solid #E7ECF3; border-radius:10px; padding:8px; }
379
  .stat-label{ font-size:11px; color:#6b7280; margin-bottom:2px; }
380
  .stat-value{ font-weight:800; color:#0f172a; }
381
  .mono{ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace; }
382
+ .muted{ color:#6b7280; }
383
+
384
+ .asset-desc{ margin-top:2px; font-size:12.5px; line-height:1.45; }
385
 
386
+ .asset-foot{ margin-top:4px; }
387
  .asset-bar{ height:6px; border-radius:999px; border:1px solid #E7ECF3; background:#F2F4F8; position:relative; overflow:hidden; }
388
  .asset-bar::after{ content:''; position:absolute; left:0; top:0; height:100%; width:var(--pct,0%); background:linear-gradient(90deg,#16a34a,#22c55e); }
389
+ .asset-foot-row{ margin-top:6px; display:flex; align-items:center; justify-content:space-between; color:#6b7280; }
390
 
391
  /* ===== Agents ===== */
392
+ .agent-card{ padding:12px 12px 12px; display:flex; flex-direction:column; gap:8px; }
393
+ .agent-top{
394
+ display:grid; grid-template-columns:52px 1fr auto; gap:10px; align-items:center;
395
+ }
396
  .agent-badge{ width:52px; height:52px; border-radius:16px; border:2px solid #e5e7eb; position:relative; display:grid; place-items:center; overflow:hidden; }
397
  .agent-ring{ position:absolute; inset:0; opacity:.18; }
398
  .agent-logo{ width:70%; height:70%; object-fit:contain; position:relative; z-index:1; }
399
 
400
  .agent-title{ min-width:0; }
401
  .agent-name{ font-weight:900; letter-spacing:.02em; color:#0f172a; text-transform:uppercase; }
402
+ .agent-links{ display:flex; align-items:center; gap:8px; color:#64748b; flex-wrap:wrap; }
403
+ .link{ color:#334155; font-weight:600; text-decoration:none; }
404
+ .link:hover{ color:#0f172a; text-decoration:underline; }
405
+ .dot{ color:#94a3b8; }
406
 
407
+ .agent-stats{ display:grid; grid-template-columns:repeat(4,1fr); gap:10px; }
408
  .pos{ color:#0e7a3a; } .neg{ color:#B91C1C; }
409
 
410
+ .agent-foot{ display:flex; align-items:center; gap:8px; flex-wrap:wrap; margin-top:2px; }
411
  .chip{ display:inline-flex; align-items:center; gap:6px; padding:4px 8px; border-radius:999px; font-size:12px; font-weight:700; background:#F6F8FB; color:#0f172a; border:1px solid #E7ECF3; }
412
  .chip-outline{ background:#fff; }
413
  .chip-pos{ background:#E9F7EF; border-color:#d7f0e0; color:#0e7a3a; }
 
415
 
416
  /* ===== Guide ===== */
417
  .guide-card{ margin-top:12px; padding:14px; }
418
+ .guide-title{ display:flex; align-items:center; gap:10px; font-weight:800; font-size:1.1rem; color:#0f172a; margin-bottom:6px; }
419
  .guide-title i{ color:#4338ca; }
420
+ .guide-steps{ margin:6px 0 0 18px; color:#334155; }
421
+ .guide-steps li{ margin:6px 0; }
422
+ .code{ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace; }
 
 
 
 
 
 
 
 
 
 
 
423
 
424
+ /* ===== Buttons ===== */
425
+ .cta-row{ margin-top:12px; display:flex; justify-content:center; }
426
+ .link-btn{ display:inline-flex; align-items:center; justify-content:center; gap:.5rem; text-decoration:none; }
 
 
 
427
  .btn-cta{
428
  background:linear-gradient(90deg, rgb(0,0,185), #7b2cbf, #d946ef, rgb(240,0,15));
429
  border:none; color:#fff; font-weight:800; letter-spacing:.02em;
 
431
  }
432
  .btn-cta:hover{ filter:brightness(1.02); transform:translateY(-1px); }
433
  .mr-2{ margin-right:.5rem; }
 
 
 
 
 
 
434
  </style>