page.tsx 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. import { getPnLData } from '@/lib/queries';
  2. import { PnLClient } from './PnLClient';
  3. function MetricCard({
  4. label,
  5. value,
  6. color = 'text-white',
  7. }: {
  8. label: string;
  9. value: string;
  10. color?: string;
  11. }) {
  12. return (
  13. <div className="card">
  14. <p className="text-sm text-slate-400 mb-1">{label}</p>
  15. <p className={`text-2xl font-bold ${color}`}>{value}</p>
  16. </div>
  17. );
  18. }
  19. export const dynamic = 'force-dynamic';
  20. export default async function PnLPage() {
  21. const { data, metrics } = await getPnLData();
  22. return (
  23. <div className="space-y-8">
  24. <div>
  25. <h1 className="text-2xl font-bold">Profit &amp; Loss</h1>
  26. <p className="text-sm text-slate-400 mt-1">
  27. Performance metrics and PnL tracking
  28. </p>
  29. </div>
  30. {/* Metrics Row */}
  31. <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
  32. <MetricCard
  33. label="Total PnL"
  34. value={`$${metrics.totalPnl.toFixed(2)}`}
  35. color={metrics.totalPnl >= 0 ? 'text-green-400' : 'text-red-400'}
  36. />
  37. <MetricCard
  38. label="Win Rate"
  39. value={metrics.totalTrades > 0 ? `${(metrics.winRate * 100).toFixed(1)}%` : '—'}
  40. color="text-blue-400"
  41. />
  42. <MetricCard
  43. label="Sharpe Ratio"
  44. value={metrics.totalTrades > 0 ? metrics.sharpe.toFixed(2) : '—'}
  45. color={metrics.sharpe > 1 ? 'text-green-400' : 'text-yellow-400'}
  46. />
  47. <MetricCard
  48. label="Max Drawdown"
  49. value={metrics.totalTrades > 0 ? `$${metrics.maxDrawdown.toFixed(2)}` : '—'}
  50. color="text-red-400"
  51. />
  52. </div>
  53. {/* Trade Stats */}
  54. <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
  55. <div className="card">
  56. <p className="text-sm text-slate-400 mb-1">Total Trades</p>
  57. <p className="text-2xl font-bold text-white">{metrics.totalTrades}</p>
  58. </div>
  59. <div className="card">
  60. <p className="text-sm text-slate-400 mb-1">Winning Trades</p>
  61. <p className="text-2xl font-bold text-green-400">{metrics.winningTrades}</p>
  62. </div>
  63. </div>
  64. {/* Charts */}
  65. {data.length > 0 ? (
  66. <PnLClient data={data} />
  67. ) : (
  68. <div className="card">
  69. <p className="text-slate-500 text-center py-8">
  70. No PnL data yet. Metrics will appear after the bot completes trades.
  71. </p>
  72. </div>
  73. )}
  74. </div>
  75. );
  76. }