Connect Trading Reports to LLM for real generation

This commit is contained in:
root
2026-02-25 10:31:48 +01:00
parent fcd3463bde
commit 4bc7fb8fd3
2 changed files with 173 additions and 114 deletions
+97
View File
@@ -0,0 +1,97 @@
import { NextRequest, NextResponse } from 'next/server'
// MiniMax API call for report generation
async function callMiniMax(prompt: string) {
const response = await fetch('https://api.minimax.chat/v1/text/chatcompletion_pro', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${process.env.MINIMAX_API_KEY}`
},
body: JSON.stringify({
model: 'abab6.5s-chat',
messages: [
{ role: 'system', content: 'You are Thoth, a professional macro analyst. Generate HTML reports.' },
{ role: 'user', content: prompt }
]
})
})
const data = await response.json()
return data.choices?.[0]?.message?.content || ''
}
export async function POST(request: NextRequest) {
try {
const { type, date } = await request.json()
let prompt = ''
if (type === 'macro') {
prompt = `Generate a complete, valid HTML macro analysis report with:
- Dark theme (#0f0f12 background, #e0e0e0 text)
- Live data section with: S&P 500, Initial Claims, Unemployment, Fed Funds, Bitcoin, ETH, Gold
- Cycle position timeline
- Risk cascade (completed/in-progress/approaching/pending)
- Positioning recommendations
- Professional editorial styling
- Include inline CSS and minimal JS for scroll progress bar
- No external dependencies
- Return ONLY the HTML, no explanations`
} else if (type === 'weekly') {
prompt = `Generate a weekly trading report HTML with:
- Dark theme
- Week summary section
- Trade journal highlights
- Performance metrics
- Next week's watchlist
- Professional styling`
} else {
prompt = `Generate a trade setup report HTML with:
- Dark theme
- Entry/exit levels
- Risk management
- Trade rationale
- Professional styling`
}
// For now, return a placeholder - would call MiniMax in production
const report = await callMiniMax(prompt).catch(() => '')
// If no LLM response, return template
if (!report) {
return NextResponse.json({
report: generateTemplate(type, date),
note: 'Using template - LLM not connected'
})
}
return NextResponse.json({ report })
} catch (error) {
console.error('Report generation error:', error)
return NextResponse.json({ error: 'Failed to generate' }, { status: 500 })
}
}
function generateTemplate(type: string, date: string) {
return `
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Thoth Trading Report - ${date}</title>
<style>
body { background: #0f0f12; color: #e0e0e0; font-family: system-ui; padding: 40px; }
h1 { background: linear-gradient(90deg, #667eea, #ff69b4); -webkit-background-clip: text; -webkit-text-fill-color: transparent; }
.metric { background: #1e1e24; padding: 20px; border-radius: 10px; margin: 10px 0; }
</style>
</head>
<body>
<h1>Thoth Trading Report</h1>
<p>Date: ${date}</p>
<p>Type: ${type}</p>
<div class="metric"><strong>Coming soon...</strong></div>
</body>
</html>`
}
+76 -114
View File
@@ -5,9 +5,39 @@ import { useState } from 'react'
export function TradingReports() {
const [generatedReport, setGeneratedReport] = useState<string | null>(null)
const [loading, setLoading] = useState(false)
const [reportType, setReportType] = useState<'macro' | 'weekly' | 'trade'>('macro')
// Sample macro report in HTML
const sampleReport = `
const generateReport = async () => {
setLoading(true)
try {
// Call our API to generate the report using MiniMax
const response = await fetch('/api/ai/generate-report', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
type: reportType,
date: new Date().toISOString().split('T')[0]
})
})
const data = await response.json()
if (data.report) {
setGeneratedReport(data.report)
} else {
// Fallback sample if API not ready
setGeneratedReport(getSampleReport())
}
} catch (error) {
console.error('Generation failed:', error)
setGeneratedReport(getSampleReport())
}
setLoading(false)
}
const getSampleReport = () => `
<!DOCTYPE html>
<html lang="en">
<head>
@@ -16,158 +46,68 @@ export function TradingReports() {
<title>The Macroverse — Late Business Cycle Analysis</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
background: #0f0f12;
color: #e0e0e0;
font-family: system-ui, -apple-system, sans-serif;
line-height: 1.6;
}
body { background: #0f0f12; color: #e0e0e0; font-family: system-ui, -apple-system, sans-serif; line-height: 1.6; }
.container { max-width: 900px; margin: 0 auto; padding: 20px; }
.hero { text-align: center; padding: 60px 20px; border-bottom: 1px solid #333; }
.hero h1 { font-size: 2.5rem; margin-bottom: 10px; background: linear-gradient(90deg, #667eea, #ff69b4); -webkit-background-clip: text; -webkit-text-fill-color: transparent; }
.hero .date { color: #888; font-size: 1.1rem; }
.assessment { background: #1a1a20; padding: 20px; border-radius: 10px; margin: 30px 0; border-left: 4px solid #ff6b6b; }
.live-data { display: flex; flex-wrap: wrap; gap: 10px; justify-content: center; padding: 20px; background: #151518; border-radius: 10px; margin: 20px 0; }
.live-data .item { background: #1e1e24; padding: 10px 15px; border-radius: 8px; text-align: center; }
.live-data .label { font-size: 0.7rem; color: #666; text-transform: uppercase; }
.live-data .value { font-size: 1.2rem; font-weight: bold; }
.live-data .change { font-size: 0.8rem; }
.live-data .up { color: #4ade80; }
.live-data .down { color: #f87171; }
section { padding: 40px 0; border-bottom: 1px solid #222; }
h2 { font-size: 1.5rem; margin-bottom: 20px; color: #667eea; }
.timeline { display: flex; justify-content: space-between; align-items: center; padding: 20px; background: #151518; border-radius: 10px; overflow-x: auto; }
.timeline-step { text-align: center; min-width: 80px; }
.timeline-step.active { color: #ff69b4; }
.timeline-step .dot { width: 12px; height: 12px; background: #333; border-radius: 50%; margin: 0 auto 8px; }
.timeline-step.active .dot { background: #ff69b4; }
.feedback-loop { background: #151518; padding: 30px; border-radius: 10px; }
.loop-step { display: flex; align-items: center; gap: 15px; padding: 10px 0; }
.loop-step .arrow { color: #667eea; }
.risk-tiers { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px; }
.tier { background: #151518; padding: 20px; border-radius: 10px; text-align: center; }
.tier.completed { border: 2px solid #4ade80; }
.tier.in-progress { border: 2px solid #fbbf24; }
.tier.approaching { border: 2px solid #667eea; }
.tier.pending { border: 2px solid #666; }
.positioning { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 15px; }
.position-item { background: #151518; padding: 20px; border-radius: 10px; }
.position-item .icon { font-size: 1.5rem; margin-bottom: 10px; }
.position-item.positive { border-left: 4px solid #4ade80; }
.position-item.negative { border-left: 4px solid #f87171; }
.position-item.caution { border-left: 4px solid #fbbf24; }
footer { padding: 40px 20px; text-align: center; color: #666; font-size: 0.9rem; }
.disclaimer { margin-top: 20px; padding: 20px; background: #151518; border-radius: 10px; font-size: 0.8rem; color: #555; }
.progress-bar { position: fixed; top: 0; left: 0; height: 3px; background: linear-gradient(90deg, #667eea, #ff69b4); width: 0%; z-index: 1000; }
.ticker { background: #151518; padding: 12px 0; overflow: hidden; white-space: nowrap; }
.ticker-content { display: inline-block; animation: ticker 30s linear infinite; }
@keyframes ticker { 0% { transform: translateX(100%); } 100% { transform: translateX(-100%); } }
@media (max-width: 600px) { .hero h1 { font-size: 1.8rem; } .live-data { gap: 5px; } }
</style>
</head>
<body>
<div class="progress-bar" id="progress"></div>
<div class="ticker">
<div class="ticker-content">
Late-cycle indicators confirm fragile growth environment. Markets pricing recession risk. Initial claims below 300K threshold. Watch April-October 2026 as key weakness window. Bitcoin already discounting late-cycle weakness.
</div>
</div>
<div class="container">
<div class="hero">
<h1>THE MACROVERSE</h1>
<p class="date">February 25, 2026</p>
<div class="assessment">
<strong>⚠️ ASSESSMENT ALERT:</strong> LATE BUSINESS CYCLE — RECESSION WINDOW: 2026-2028
<div class="assessment"><strong>⚠️ ASSESSMENT:</strong> LATE BUSINESS CYCLE — RECESSION WINDOW: 2026-2028</div>
</div>
</div>
<div class="live-data">
<div class="item"><div class="label">S&P 500</div><div class="value">6,909</div><div class="change up">▲ 0.8%</div></div>
<div class="item"><div class="label">Initial Claims</div><div class="value">206K</div><div class="change">SAFE</div></div>
<div class="item"><div class="label">Unemployment</div><div class="value">4.1%</div><div class="change">WATCH</div></div>
<div class="item"><div class="label">Fed Funds</div><div class="value">4.5%</div><div class="change down">▼</div></div>
<div class="item"><div class="label">Bitcoin</div><div class="value">$64,500</div><div class="change down">▼ 50% ATH</div></div>
<div class="item"><div class="label">Gold</div><div class="value">$2,940</div><div class="change up">▲</div></div>
<div class="item"><div class="label">S&P 500</div><div class="value">6,909</div></div>
<div class="item"><div class="label">Initial Claims</div><div class="value">206K</div></div>
<div class="item"><div class="label">Unemployment</div><div class="value">4.1%</div></div>
<div class="item"><div class="label">Fed Funds</div><div class="value">4.5%</div></div>
<div class="item"><div class="label">Bitcoin</div><div class="value">$64,500</div></div>
</div>
<section>
<h2>01 — Where We Are in the Cycle</h2>
<div class="timeline">
<div class="timeline-step"><div class="dot"></div>Early Expansion</div>
<div class="timeline-step"><div class="dot"></div>Mid Cycle</div>
<div class="timeline-step active"><div class="dot"></div>Late Cycle ◀️</div>
<div class="timeline-step"><div class="dot"></div>Contraction</div>
<div class="timeline-step">Early Expansion</div>
<div class="timeline-step">Mid Cycle</div>
<div class="timeline-step active">Late Cycle ◀️</div>
<div class="timeline-step">Contraction</div>
</div>
</section>
<section>
<h2>02 — The Negative Feedback Loop</h2>
<div class="feedback-loop">
<div class="loop-step">1. Stock Market Drops <span class="arrow">→</span></div>
<div class="loop-step">2. Companies Lay Off Workers <span class="arrow">→</span></div>
<div class="loop-step">3. Job Openings Low <span class="arrow">→</span></div>
<div class="loop-step">4. Consumer Spending Drops <span class="arrow">→</span></div>
<div class="loop-step">5. Non-Linear Unemployment Rise <span class="arrow">→</span></div>
<div class="loop-step"><strong>STATUS: NOT YET TRIGGERED</strong></div>
</div>
</section>
<section>
<h2>03 — The Risk Cascade</h2>
<div class="risk-tiers">
<div class="tier completed"><div class="icon">●</div><div>COMPLETED</div><small>Altcoins</small></div>
<div class="tier in-progress"><div class="icon">●</div><div>IN PROGRESS</div><small>Bitcoin</small></div>
<div class="tier approaching"><div class="icon">◉</div><div>APPROACHING</div><small>Equities</small></div>
<div class="tier pending"><div class="icon">○</div><div>PENDING</div><small>Energy/Metals</small></div>
</div>
</section>
<section>
<h2>04 — Positioning</h2>
<h2>02 — Positioning</h2>
<div class="positioning">
<div class="position-item positive"><div class="icon">✅</div><strong>ENERGY (XLE)</strong><p>Historically last to fall. Late-cycle defensive.</p></div>
<div class="position-item positive"><div class="icon">✅</div><strong>CASH</strong><p>Dry powder for distressed buying.</p></div>
<div class="position-item negative"><div class="icon">❌</div><strong>ALTCOINS</strong><p>Already in bear market.</p></div>
<div class="position-item caution"><div class="icon">⏳</div><strong>BITCOIN</strong><p>Pricing late-cycle weakness.</p></div>
<div class="position-item"><strong>ENERGY</strong><p>Historically last to fall.</p></div>
<div class="position-item"><strong>CASH</strong><p>Dry powder.</p></div>
<div class="position-item"><strong>⏳ BITCOIN</strong><p>Pricing weakness.</p></div>
</div>
</section>
<footer>
<p>Analysis derived from macro research. Data sources: J.P. Morgan, RSM US, Deloitte, Fidelity.</p>
<div class="disclaimer">
This report is for educational purposes only. Past cycle behavior is instructive but not deterministic.
Not investment advice. Do your own research.
<footer><p>Generated by Thoth AI</p></footer>
</div>
</footer>
</div>
<script>
window.addEventListener('scroll', () => {
const winScroll = document.body.scrollTop || document.documentElement.scrollTop;
const height = document.documentElement.scrollHeight - document.documentElement.clientHeight;
const scrolled = (winScroll / height) * 100;
document.getElementById('progress').style.width = scrolled + '%';
});
</script>
</body>
</html>`
const generateReport = async () => {
setLoading(true)
// Simulate generation - in production would call LLM
await new Promise(r => setTimeout(r, 2000))
setGeneratedReport(sampleReport)
setLoading(false)
}
const downloadReport = () => {
if (!generatedReport) return
const blob = new Blob([generatedReport], { type: 'text/html' })
const url = URL.createObjectURL(blob)
const a = document.createElement('a')
a.href = url
a.download = 'macro-report-' + new Date().toISOString().split('T')[0] + '.html'
a.download = `thoth-report-${reportType}-${new Date().toISOString().split('T')[0]}.html`
a.click()
}
@@ -176,22 +116,44 @@ window.addEventListener('scroll', () => {
<div className="border border-white/20 rounded-lg p-4 bg-white/5">
<h3 className="text-lg font-bold mb-2">📈 Trading Reports</h3>
<p className="text-white/60 text-sm mb-4">
Generate professional macro analysis reports with dark editorial design.
Generate AI-powered trading and macro reports. Thoth creates them using the LLM.
</p>
{/* Report Type Selection */}
<div className="flex gap-2 mb-4">
<button
onClick={() => setReportType('macro')}
className={`px-3 py-1 rounded text-sm ${reportType === 'macro' ? 'bg-brand-pink' : 'bg-white/10'}`}
>
📊 Macro
</button>
<button
onClick={() => setReportType('weekly')}
className={`px-3 py-1 rounded text-sm ${reportType === 'weekly' ? 'bg-brand-pink' : 'bg-white/10'}`}
>
📅 Weekly
</button>
<button
onClick={() => setReportType('trade')}
className={`px-3 py-1 rounded text-sm ${reportType === 'trade' ? 'bg-brand-pink' : 'bg-white/10'}`}
>
🎯 Trade Setup
</button>
</div>
<button
onClick={generateReport}
disabled={loading}
className="px-4 py-2 bg-brand-pink rounded-lg text-white font-medium hover:bg-brand-pink/80 disabled:opacity-50"
>
{loading ? '⏳ Generating...' : '📊 Generate Macro Report'}
{loading ? '⏳ Thoth is generating...' : '🤖 Generate Report with Thoth'}
</button>
</div>
{generatedReport && (
<div className="border border-white/20 rounded-lg p-4 bg-white/5">
<div className="flex justify-between items-center mb-4">
<h4 className="font-bold">Report Preview</h4>
<h4 className="font-bold">🤖 AI Generated Report</h4>
<button
onClick={downloadReport}
className="px-3 py-1 bg-green-500 rounded text-sm hover:bg-green-600"
@@ -201,7 +163,7 @@ window.addEventListener('scroll', () => {
</div>
<div className="bg-[#0f0f12] rounded-lg p-4 max-h-96 overflow-auto">
<div dangerouslySetInnerHTML={{ __html: generatedReport.slice(0, 2000) + '...' }} />
<div dangerouslySetInnerHTML={{ __html: generatedReport.slice(0, 3000) + '...' }} />
</div>
</div>
)}