fix: Correct SQL column names and add navigation links

- Fixed tp1Hit/tp2Hit -> tp1Filled/tp2Filled in Runner Performance query
- Fixed atr -> atrAtEntry in ATR vs MFE Correlation and Data Collection queries
- Added Analytics card to homepage with link to /analytics/optimization
- Added Home button to optimization page header
- All 7 analyses now working without SQL errors
This commit is contained in:
mindesbunister
2025-11-23 20:28:33 +01:00
parent 11ae0938ba
commit 1e64e8145b
3 changed files with 51 additions and 14 deletions

View File

@@ -39,10 +39,20 @@ export default function OptimizationPage() {
<div className="max-w-7xl mx-auto">
{/* Header */}
<div className="mb-8">
<h1 className="text-4xl font-bold mb-2">🔬 Optimization Analytics Dashboard</h1>
<p className="text-slate-400">
Data-driven analysis for trading system improvements based on roadmaps and SQL queries
</p>
<div className="flex items-center justify-between">
<div>
<h1 className="text-4xl font-bold mb-2">🔬 Optimization Analytics Dashboard</h1>
<p className="text-slate-400">
Data-driven analysis for trading system improvements based on roadmaps and SQL queries
</p>
</div>
<a
href="/"
className="px-4 py-2 bg-slate-700 hover:bg-slate-600 rounded-lg transition-colors flex items-center gap-2"
>
Home
</a>
</div>
{lastRefresh && (
<p className="text-sm text-slate-500 mt-2">
Last refresh: {lastRefresh.toLocaleTimeString()}

View File

@@ -190,10 +190,10 @@ export async function GET() {
const runnerPerformance = await prisma.$queryRaw<any[]>`
SELECT
COUNT(*) as total_trades,
SUM(CASE WHEN "tp1Hit" = true THEN 1 ELSE 0 END) as tp1_hits,
SUM(CASE WHEN "tp2Hit" = true THEN 1 ELSE 0 END) as tp2_hits,
ROUND(100.0 * SUM(CASE WHEN "tp1Hit" = true THEN 1 ELSE 0 END) / COUNT(*)::numeric, 1) as tp1_rate,
ROUND(100.0 * SUM(CASE WHEN "tp2Hit" = true THEN 1 ELSE 0 END) / COUNT(*)::numeric, 1) as tp2_rate,
SUM(CASE WHEN "tp1Filled" = true THEN 1 ELSE 0 END) as tp1_hits,
SUM(CASE WHEN "tp2Filled" = true THEN 1 ELSE 0 END) as tp2_hits,
ROUND(100.0 * SUM(CASE WHEN "tp1Filled" = true THEN 1 ELSE 0 END) / COUNT(*)::numeric, 1) as tp1_rate,
ROUND(100.0 * SUM(CASE WHEN "tp2Filled" = true THEN 1 ELSE 0 END) / COUNT(*)::numeric, 1) as tp2_rate,
ROUND(AVG("maxFavorableExcursion")::numeric, 2) as avg_mfe,
ROUND(AVG("maxAdverseExcursion")::numeric, 2) as avg_mae
FROM "Trade"
@@ -244,9 +244,9 @@ export async function GET() {
const atrCorrelation = await prisma.$queryRaw<any[]>`
SELECT
CASE
WHEN atr < 0.3 THEN '<0.3 (Low Vol)'
WHEN atr < 0.5 THEN '0.3-0.5 (Med Vol)'
WHEN atr < 0.7 THEN '0.5-0.7 (High Vol)'
WHEN "atrAtEntry" < 0.3 THEN '<0.3 (Low Vol)'
WHEN "atrAtEntry" < 0.5 THEN '0.3-0.5 (Med Vol)'
WHEN "atrAtEntry" < 0.7 THEN '0.5-0.7 (High Vol)'
ELSE '0.7+ (Very High Vol)'
END as atr_range,
COUNT(*) as trades,
@@ -255,9 +255,9 @@ export async function GET() {
ROUND(100.0 * SUM(CASE WHEN "realizedPnL" > 0 THEN 1 ELSE 0 END) / COUNT(*)::numeric, 1) as win_rate
FROM "Trade"
WHERE "exitReason" IS NOT NULL
AND atr IS NOT NULL
AND "atrAtEntry" IS NOT NULL
GROUP BY atr_range
ORDER BY MIN(atr)
ORDER BY MIN("atrAtEntry")
`
const formattedData = atrCorrelation.map(row => ({
@@ -356,7 +356,7 @@ export async function GET() {
SELECT
COUNT(*) FILTER (WHERE "exitReason" IS NOT NULL) as completed_trades,
COUNT(*) FILTER (WHERE "signalQualityScore" IS NOT NULL) as with_quality,
COUNT(*) FILTER (WHERE atr IS NOT NULL) as with_atr,
COUNT(*) FILTER (WHERE "atrAtEntry" IS NOT NULL) as with_atr,
COUNT(*) FILTER (WHERE "maxFavorableExcursion" IS NOT NULL) as with_mfe,
COUNT(*) FILTER (WHERE "indicatorVersion" = 'v8') as v8_trades,
(SELECT COUNT(*) FROM "BlockedSignal" WHERE "blockReason" = 'QUALITY_SCORE_TOO_LOW') as blocked_quality

View File

@@ -124,6 +124,33 @@ export default function HomePage() {
</div>
</div>
</a>
{/* Analytics Card */}
<a
href="/analytics/optimization"
className="group relative bg-gradient-to-br from-gray-800/50 to-gray-900/50 backdrop-blur-sm rounded-2xl p-8 border border-gray-700/50 hover:border-gray-600 transition-all duration-300 hover:scale-105"
>
<div className="absolute inset-0 bg-gradient-to-br from-blue-500/10 to-purple-700/10 rounded-2xl opacity-0 group-hover:opacity-100 transition-opacity"></div>
<div className="relative">
<div className="w-16 h-16 bg-gradient-to-br from-blue-600 to-purple-800 rounded-xl flex items-center justify-center mb-6 group-hover:scale-110 transition-transform">
<span className="text-4xl">🔬</span>
</div>
<h3 className="text-2xl font-bold text-white mb-3">Analytics</h3>
<p className="text-gray-300 mb-6">
Data-driven optimization analysis with automated SQL insights
</p>
<div className="flex items-center text-gray-400 group-hover:text-gray-300">
<span className="font-medium">View Analytics</span>
<svg className="w-5 h-5 ml-2 group-hover:translate-x-1 transition-transform" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
</svg>
</div>
</div>
</a>
</div>
{/* Quick Stats */}