Skip to content

Commit e11d1a6

Browse files
committed
feat: Integrate arXiv research papers into the daily digest and UI, update AI prompt to synthesize academic findings, and refresh cache key.
1 parent 3978bfe commit e11d1a6

3 files changed

Lines changed: 317 additions & 95 deletions

File tree

app.js

Lines changed: 91 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ const CONFIG = {
77
arxivApi: 'https://export.arxiv.org/api/query',
88
apiKey: window.OPENROUTER_API_KEY || '',
99
updateInterval: 24 * 60 * 60 * 1000, // 24 hours (once daily)
10-
cacheKey: 'market_intelligence_data',
10+
cacheKey: 'market_intelligence_data_v2',
1111
lastUpdateKey: 'last_update_time',
1212
currentLang: localStorage.getItem('preferred_language') || 'en'
1313
};
@@ -176,7 +176,7 @@ class AIService {
176176
}
177177
}
178178

179-
static async generateDailyDigest(analysisData = null) {
179+
static async generateDailyDigest(analysisData = null, arxivPapers = []) {
180180
let analysisContext = "";
181181
if (analysisData) {
182182
analysisContext = `
@@ -191,10 +191,16 @@ MARKET ANALYSIS DATA (Moore Analysis / Implied Probability):
191191
`;
192192
}
193193

194+
let researchContext = "";
195+
if (arxivPapers && arxivPapers.length > 0) {
196+
researchContext = "\nLATEST ACADEMIC RESEARCH (arXiv):\n" + arxivPapers.map(p => `- ${p.title}: ${p.summary}`).join('\n');
197+
}
198+
194199
const prompt = `You are a senior financial analyst. Generate an EXTENSIVE, professional market intelligence report for ${new Date().toLocaleDateString()}.
195-
Use the provided Market Analysis Data to ground your predictions.
200+
Use the provided Market Analysis Data and Academic Research to ground your predictions.
196201
197202
${analysisContext}
203+
${researchContext}
198204
199205
REQUIRED SECTIONS:
200206
@@ -208,15 +214,19 @@ REQUIRED SECTIONS:
208214
- Specific company news with quantitative impact.
209215
- Connect macro events (Fed, Geopolitics) to market moves.
210216
211-
3. **🎯 Strategic Opportunities**
217+
3. **🔬 Research & Quantitative Edge**
218+
- Synthesize the provided arXiv research papers. How do these findings apply to current market conditions? (e.g., "New paper on volatility modeling suggests...")
219+
- Combine this with the Moore Analysis probability distribution.
220+
221+
4. **🎯 Strategic Opportunities**
212222
- Identify undervalued sectors based on the probability distribution.
213223
- Suggest risk-managed approaches (e.g., "Given the 68% range of X-Y, consider spreads...").
214224
215-
4. **⚠️ Risk & Scenario Analysis**
225+
5. **⚠️ Risk & Scenario Analysis**
216226
- Downside risks based on the lower bound of the expected range.
217227
- Tail risk events.
218228
219-
Format as Markdown. Be sophisticated, data-driven, and authoritative.`;
229+
Format as Markdown. Use clear headers, bullet points, and bold text for readability. Avoid long walls of text.`;
220230

221231
const content = await this.fetchInsights(prompt);
222232
return this.parseDigestContent(content);
@@ -301,6 +311,37 @@ Return as JSON array:
301311
return this.parseInsightsContent(content);
302312
}
303313

314+
static async fetchArxivData() {
315+
try {
316+
// Query for Quantitative Finance (q-fin) and Economics (econ)
317+
const query = 'cat:q-fin.ST OR cat:q-fin.GN OR cat:q-fin.RM OR cat:q-fin.PM';
318+
const url = `${CONFIG.arxivApi}?search_query=${encodeURIComponent(query)}&start=0&max_results=5&sortBy=submittedDate&sortOrder=descending`;
319+
320+
const response = await fetch(url);
321+
const str = await response.text();
322+
323+
// Simple XML parsing
324+
const parser = new DOMParser();
325+
const xmlDoc = parser.parseFromString(str, "text/xml");
326+
const entries = xmlDoc.getElementsByTagName("entry");
327+
328+
const papers = [];
329+
for (let i = 0; i < entries.length; i++) {
330+
const entry = entries[i];
331+
papers.push({
332+
title: entry.getElementsByTagName("title")[0].textContent.replace(/\n/g, ' ').trim(),
333+
summary: entry.getElementsByTagName("summary")[0].textContent.replace(/\n/g, ' ').trim().substring(0, 200) + "...",
334+
published: new Date(entry.getElementsByTagName("published")[0].textContent).toLocaleDateString(),
335+
link: entry.getElementsByTagName("id")[0].textContent
336+
});
337+
}
338+
return papers;
339+
} catch (error) {
340+
console.error('Error fetching arXiv data:', error);
341+
return [];
342+
}
343+
}
344+
304345
static parseDigestContent(content) {
305346
return content.replace(/```markdown\n?/g, '').replace(/```\n?/g, '');
306347
}
@@ -627,14 +668,18 @@ class UIController {
627668
});
628669
}
629670

630-
static renderAnalysis(analysisData) {
671+
static renderResearch(analysisData, papers) {
631672
const container = document.getElementById('analysis-container');
632-
if (!container || !analysisData) return;
673+
if (!container) return;
633674

634-
container.innerHTML = `
635-
<div class="analysis-card">
675+
let html = '<div class="research-grid">';
676+
677+
// 1. Moore Analysis Card
678+
if (analysisData) {
679+
html += `
680+
<div class="analysis-card moore-card">
636681
<div class="analysis-header">
637-
<h3>🔮 Moore Analysis: Market Implied Probability</h3>
682+
<h3>🔮 Moore Analysis: Market Probability</h3>
638683
<span class="tag ${analysisData.analysis.sentiment.toLowerCase()}">${analysisData.analysis.sentiment}</span>
639684
</div>
640685
<div class="analysis-content">
@@ -656,11 +701,34 @@ class UIController {
656701
<img src="./market_analysis_chart.png" alt="Market Probability Distribution" onerror="this.style.display='none'">
657702
</div>
658703
<p class="analysis-explainer">
659-
This heatmap represents the market's consensus on future price probability, derived from options pricing curvature (Breeden-Litzenberger).
704+
Market consensus derived from options pricing curvature (Breeden-Litzenberger).
660705
</p>
661706
</div>
662-
</div>
663-
`;
707+
</div>`;
708+
}
709+
710+
// 2. arXiv Research Card
711+
if (papers && papers.length > 0) {
712+
html += `
713+
<div class="analysis-card research-papers-card">
714+
<div class="analysis-header">
715+
<h3>🔬 Latest Quantitative Research (arXiv)</h3>
716+
<span class="tag neutral">${papers.length} Papers</span>
717+
</div>
718+
<div class="papers-list">
719+
${papers.map(p => `
720+
<div class="paper-item">
721+
<a href="${p.link}" target="_blank" class="paper-title">${p.title}</a>
722+
<span class="paper-date">${p.published}</span>
723+
<p class="paper-summary">${p.summary}</p>
724+
</div>
725+
`).join('')}
726+
</div>
727+
</div>`;
728+
}
729+
730+
html += '</div>';
731+
container.innerHTML = html;
664732
container.style.display = 'block';
665733
}
666734

@@ -711,9 +779,10 @@ class App {
711779

712780
UIController.updateStats(data);
713781
UIController.renderDigest(data.digest);
714-
if (data.analysis) {
715-
UIController.renderAnalysis(data.analysis);
716-
}
782+
783+
// Render combined research section
784+
UIController.renderResearch(data.analysis, data.research);
785+
717786
UIController.renderInsights(data.insights);
718787
if (data.stockPicks) {
719788
UIController.renderStockPicks(data.stockPicks);
@@ -741,13 +810,16 @@ class App {
741810
console.log('No local analysis data found');
742811
}
743812

813+
// Fetch arXiv data
814+
const arxivPapers = await AIService.fetchArxivData();
815+
744816
const [digest, insights, stockPicks] = await Promise.all([
745-
AIService.generateDailyDigest(analysisData),
817+
AIService.generateDailyDigest(analysisData, arxivPapers),
746818
AIService.generateInsights(),
747819
AIService.generateStockPicks()
748820
]);
749821

750-
return { digest, insights, stockPicks, analysis: analysisData };
822+
return { digest, insights, stockPicks, analysis: analysisData, research: arxivPapers };
751823
}
752824

753825
static setupEventListeners() {

index.html

Lines changed: 41 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,35 @@
11
<!DOCTYPE html>
22
<html lang="en">
3+
34
<head>
45
<meta charset="UTF-8">
56
<meta name="viewport" content="width=device-width, initial-scale=1.0">
67
<meta name="description" content="AI-Powered Market Intelligence Dashboard with Daily Updates">
78
<meta name="theme-color" content="#1a1a2e">
89
<meta name="apple-mobile-web-app-capable" content="yes">
910
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
10-
11+
1112
<title>Market Intelligence Dashboard</title>
12-
13+
1314
<!-- PWA Manifest -->
1415
<link rel="manifest" href="manifest.json">
15-
16+
1617
<!-- Icons -->
1718
<link rel="icon" type="image/png" sizes="192x192" href="icons/icon-192.png">
1819
<link rel="icon" type="image/png" sizes="512x512" href="icons/icon-512.png">
1920
<link rel="apple-touch-icon" href="icons/icon-192.png">
20-
21+
2122
<!-- Fonts -->
2223
<link rel="preconnect" href="https://fonts.googleapis.com">
2324
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
24-
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
25-
25+
<link
26+
href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap"
27+
rel="stylesheet">
28+
2629
<!-- Styles -->
2730
<link rel="stylesheet" href="styles.css">
2831
</head>
32+
2933
<body>
3034
<!-- Loading Screen -->
3135
<div id="loading-screen" class="loading-screen">
@@ -46,7 +50,8 @@ <h2 class="loading-text">Loading Intelligence...</h2>
4650
<div class="brand">
4751
<div class="brand-icon">
4852
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
49-
<path d="M13 2L3 14h8l-1 8 10-12h-8l1-8z" fill="url(#gradient)" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
53+
<path d="M13 2L3 14h8l-1 8 10-12h-8l1-8z" fill="url(#gradient)" stroke="currentColor"
54+
stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
5055
<defs>
5156
<linearGradient id="gradient" x1="0%" y1="0%" x2="100%" y2="100%">
5257
<stop offset="0%" style="stop-color:#00d4ff;stop-opacity:1" />
@@ -63,13 +68,23 @@ <h1>Market Intelligence</h1>
6368
<div class="header-actions">
6469
<button id="refresh-btn" class="icon-btn" title="Refresh Data">
6570
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor">
66-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"/>
71+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
72+
d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" />
6773
</svg>
6874
</button>
75+
<button id="lang-toggle" class="icon-btn" title="Switch Language">
76+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor">
77+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
78+
d="M3 5h12M9 3v2m1.048 9.5A18.022 18.022 0 016.412 9m6.088 9h7M11 21l5-10 5 10M12.751 5C11.783 10.77 8.07 15.61 3 18.129" />
79+
</svg>
80+
<span class="lang-text">AR</span>
81+
</button>
6982
<button id="settings-btn" class="icon-btn" title="Settings">
7083
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor">
71-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"/>
72-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/>
84+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
85+
d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z" />
86+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
87+
d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
7388
</svg>
7489
</button>
7590
</div>
@@ -87,7 +102,8 @@ <h1>Market Intelligence</h1>
87102
<div class="stat-card shimmer">
88103
<div class="stat-icon markets">
89104
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor">
90-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 12l3-3 3 3 4-4M8 21l4-4 4 4M3 4h18M4 4h16v12a1 1 0 01-1 1H5a1 1 0 01-1-1V4z"/>
105+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
106+
d="M7 12l3-3 3 3 4-4M8 21l4-4 4 4M3 4h18M4 4h16v12a1 1 0 01-1 1H5a1 1 0 01-1-1V4z" />
91107
</svg>
92108
</div>
93109
<div class="stat-content">
@@ -100,7 +116,8 @@ <h3>Market Trends</h3>
100116
<div class="stat-card shimmer">
101117
<div class="stat-icon insights">
102118
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor">
103-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z"/>
119+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
120+
d="M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z" />
104121
</svg>
105122
</div>
106123
<div class="stat-content">
@@ -113,7 +130,8 @@ <h3>AI Insights</h3>
113130
<div class="stat-card shimmer">
114131
<div class="stat-icon updates">
115132
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor">
116-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"/>
133+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
134+
d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" />
117135
</svg>
118136
</div>
119137
<div class="stat-content">
@@ -126,7 +144,8 @@ <h3>Updates</h3>
126144
<div class="stat-card shimmer">
127145
<div class="stat-icon sentiment">
128146
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor">
129-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14.828 14.828a4 4 0 01-5.656 0M9 10h.01M15 10h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/>
147+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
148+
d="M14.828 14.828a4 4 0 01-5.656 0M9 10h.01M15 10h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
130149
</svg>
131150
</div>
132151
<div class="stat-content">
@@ -142,7 +161,8 @@ <h3>Sentiment</h3>
142161
<div class="section-header">
143162
<h2>
144163
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor">
145-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 20H5a2 2 0 01-2-2V6a2 2 0 012-2h10a2 2 0 012 2v1m2 13a2 2 0 01-2-2V7m2 13a2 2 0 002-2V9a2 2 0 00-2-2h-2m-4-3H9M7 16h6M7 8h6v4H7V8z"/>
164+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
165+
d="M19 20H5a2 2 0 01-2-2V6a2 2 0 012-2h10a2 2 0 012 2v1m2 13a2 2 0 01-2-2V7m2 13a2 2 0 002-2V9a2 2 0 00-2-2h-2m-4-3H9M7 16h6M7 8h6v4H7V8z" />
146166
</svg>
147167
Daily Digest
148168
</h2>
@@ -167,7 +187,8 @@ <h2>
167187
<div class="section-header">
168188
<h2>
169189
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor">
170-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z"/>
190+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
191+
d="M13 10V3L4 14h7v7l9-11h-7z" />
171192
</svg>
172193
Latest Insights
173194
</h2>
@@ -189,7 +210,8 @@ <h2>
189210
<div id="install-prompt" class="install-prompt" style="display: none;">
190211
<div class="install-content">
191212
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor">
192-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4"/>
213+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
214+
d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4" />
193215
</svg>
194216
<div class="install-text">
195217
<h3>Install App</h3>
@@ -206,4 +228,5 @@ <h3>Install App</h3>
206228
<!-- Scripts -->
207229
<script src="app.js"></script>
208230
</body>
209-
</html>
231+
232+
</html>

0 commit comments

Comments
 (0)