Files
trading_bot_v4/app/projection/page.tsx
mindesbunister ed18c9e70f docs: Document projection page v11.2 filter and cleanup trade exclusion (Jan 13, 2026)
- STARTING_CAPITAL set to 1437 (actual v11.2 start capital)
- START_DATE set to Jan 6, 2026 (v11.2 production start)
- getTradingStats filters for v11.2 indicator + recent manual trades
- Excludes cleanup trades (DUPLICATE_CLEANUP, PHANTOM_CLEANUP, phantom)
- Current v11.2 performance: 6 trades, 83.3% WR, +$406.04 P&L
2026-01-13 11:12:53 +01:00

512 lines
24 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
'use client'
import { useEffect, useState } from 'react'
interface ProjectionMonth {
month: number
date: string
startCapital: number
profit: number
withdrawal: number
btcSweep: number
endCapital: number
btcHoldings: number
totalCashOut: number
netWorth: number
}
interface ScenarioResult {
monthlyRate: number
label: string
finalNetWorth: number
finalTrading: number
finalBTC: number
totalCashOut: number
color: string
}
interface TradingStats {
totalPnL: number
totalTrades: number
winners: number
losers: number
winRate: number
monthlyPnL: { month: string; pnl: number; trades: number }[]
}
export default function ProjectionPage() {
const [currentCapital, setCurrentCapital] = useState<number>(0)
const [loading, setLoading] = useState(true)
const [selectedScenario, setSelectedScenario] = useState<number>(70)
const [tradingStats, setTradingStats] = useState<TradingStats | null>(null)
const [totalDeposits, setTotalDeposits] = useState<number>(0)
// Strategy Parameters (Jan 2026)
const STARTING_CAPITAL = 1437 // Actual starting balance when v11.2 went live
const TRADING_CAP = 50000
const BTC_MONTHLY_GROWTH = 0.05 // 5% per month (60% annual)
const START_DATE = new Date('2026-01-06') // When v11.2 went live
// Tiered Withdrawal Rules
const getWithdrawal = (capital: number): number => {
if (capital >= 30000) return 1200
if (capital >= 10000) return 600
if (capital >= 3000) return 300
if (capital >= 1500) return 100
return 0
}
useEffect(() => {
async function fetchData() {
try {
// Fetch account summary
const accountResponse = await fetch('/api/drift/account-summary')
const accountData = await accountResponse.json()
if (accountData.success) {
setCurrentCapital(accountData.drift?.freeCollateral || accountData.freeCollateral || 0)
// Total deposits from Drift
if (accountData.spotPositions?.usdc?.cumulativeDeposits) {
setTotalDeposits(parseInt(accountData.spotPositions.usdc.cumulativeDeposits) / 1e6)
}
}
// Fetch trading stats (all time, not just 30 days)
const statsResponse = await fetch('/api/analytics/stats?days=365')
const statsData = await statsResponse.json()
if (statsData.success && statsData.stats) {
const stats = statsData.stats.realTrades
setTradingStats({
totalPnL: parseFloat(stats.totalPnL?.replace('$', '') || '0'),
totalTrades: stats.total || 0,
winners: stats.winning || 0,
losers: stats.losing || 0,
winRate: parseFloat(stats.winRate?.replace('%', '') || '0'),
monthlyPnL: [] // Would need separate endpoint for monthly breakdown
})
}
} catch (error) {
console.error('Failed to fetch data:', error)
} finally {
setLoading(false)
}
}
fetchData()
}, [])
// Generate projection for a given monthly rate
const generateProjection = (monthlyRate: number): ProjectionMonth[] => {
const months: ProjectionMonth[] = []
let tradingCapital = STARTING_CAPITAL
let btcHoldings = 0
let totalCashOut = 0
for (let month = 1; month <= 12; month++) {
const monthDate = new Date(START_DATE)
monthDate.setMonth(START_DATE.getMonth() + month - 1)
const startCapital = tradingCapital
const profit = tradingCapital * monthlyRate
tradingCapital += profit
// Tiered withdrawal
const withdrawal = getWithdrawal(tradingCapital)
tradingCapital -= withdrawal
totalCashOut += withdrawal
// BTC sweep (excess over $50k)
let btcSweep = 0
if (tradingCapital > TRADING_CAP) {
btcSweep = tradingCapital - TRADING_CAP
tradingCapital = TRADING_CAP
}
// BTC holdings grow + new sweep
btcHoldings = btcHoldings * (1 + BTC_MONTHLY_GROWTH) + btcSweep
const netWorth = tradingCapital + btcHoldings + totalCashOut
months.push({
month,
date: monthDate.toLocaleDateString('en-US', { month: 'short', year: 'numeric' }),
startCapital,
profit,
withdrawal,
btcSweep,
endCapital: tradingCapital,
btcHoldings,
totalCashOut,
netWorth
})
}
return months
}
// Pre-calculate all scenarios
const scenarios: ScenarioResult[] = [
{ monthlyRate: 0.50, label: '50%/mo (Very Conservative)', finalNetWorth: 0, finalTrading: 0, finalBTC: 0, totalCashOut: 0, color: 'text-gray-400' },
{ monthlyRate: 0.70, label: '70%/mo (Base Case)', finalNetWorth: 0, finalTrading: 0, finalBTC: 0, totalCashOut: 0, color: 'text-green-400' },
{ monthlyRate: 0.90, label: '90%/mo (Optimistic)', finalNetWorth: 0, finalTrading: 0, finalBTC: 0, totalCashOut: 0, color: 'text-blue-400' },
{ monthlyRate: 1.10, label: '110%/mo (Strong)', finalNetWorth: 0, finalTrading: 0, finalBTC: 0, totalCashOut: 0, color: 'text-purple-400' },
{ monthlyRate: 1.50, label: '150%/mo (Exceptional)', finalNetWorth: 0, finalTrading: 0, finalBTC: 0, totalCashOut: 0, color: 'text-yellow-400' },
].map(scenario => {
const projection = generateProjection(scenario.monthlyRate)
const final = projection[projection.length - 1]
return {
...scenario,
finalNetWorth: final.netWorth,
finalTrading: final.endCapital,
finalBTC: final.btcHoldings,
totalCashOut: final.totalCashOut
}
})
const currentProjection = generateProjection(selectedScenario / 100)
const finalMonth = currentProjection[currentProjection.length - 1]
const formatCurrency = (value: number) => {
return new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD',
minimumFractionDigits: 0,
maximumFractionDigits: 0
}).format(value)
}
return (
<div className="min-h-screen bg-gray-900 text-white p-8">
<div className="max-w-7xl mx-auto">
{/* Header */}
<div className="mb-8">
<h1 className="text-4xl font-bold mb-2">📈 Financial Projection</h1>
<p className="text-gray-400">12-Month Strategy: Tiered Withdrawals + $50k Cap + BTC Sweep</p>
</div>
{/* Strategy Rules Card */}
<div className="bg-gray-800 rounded-lg p-6 mb-8 border border-gray-700">
<h2 className="text-xl font-semibold mb-4 text-yellow-400"> Strategy Rules</h2>
<div className="grid grid-cols-1 md:grid-cols-4 gap-4">
<div className="bg-gray-700 rounded p-4">
<div className="text-sm text-gray-400">Trading Cap</div>
<div className="text-2xl font-bold text-green-400">$50,000</div>
<div className="text-xs text-gray-500">Max active trading capital</div>
</div>
<div className="bg-gray-700 rounded p-4">
<div className="text-sm text-gray-400">Excess Strategy</div>
<div className="text-2xl font-bold text-orange-400"> BTC</div>
<div className="text-xs text-gray-500">Monthly sweep to Bitcoin</div>
</div>
<div className="bg-gray-700 rounded p-4">
<div className="text-sm text-gray-400">BTC Growth</div>
<div className="text-2xl font-bold text-blue-400">5%/mo</div>
<div className="text-xs text-gray-500">60% annual appreciation</div>
</div>
<div className="bg-gray-700 rounded p-4">
<div className="text-sm text-gray-400">Withdrawals</div>
<div className="text-2xl font-bold text-purple-400">Tiered</div>
<div className="text-xs text-gray-500">$100$300$600$1,200</div>
</div>
</div>
</div>
{/* Tiered Withdrawal Rules */}
<div className="bg-gray-800 rounded-lg p-6 mb-8 border border-gray-700">
<h2 className="text-xl font-semibold mb-4 text-purple-400">💸 Tiered Withdrawal Schedule</h2>
<div className="grid grid-cols-2 md:grid-cols-4 gap-4">
<div className="text-center p-3 bg-gray-700 rounded">
<div className="text-sm text-gray-400">Capital &lt; $3k</div>
<div className="text-xl font-bold text-red-400">$100/mo</div>
</div>
<div className="text-center p-3 bg-gray-700 rounded">
<div className="text-sm text-gray-400">Capital &lt; $10k</div>
<div className="text-xl font-bold text-yellow-400">$300/mo</div>
</div>
<div className="text-center p-3 bg-gray-700 rounded">
<div className="text-sm text-gray-400">Capital &lt; $30k</div>
<div className="text-xl font-bold text-blue-400">$600/mo</div>
</div>
<div className="text-center p-3 bg-gray-700 rounded">
<div className="text-sm text-gray-400">Capital $30k</div>
<div className="text-xl font-bold text-green-400">$1,200/mo</div>
</div>
</div>
</div>
{/* Current Status */}
<div className="bg-gray-800 rounded-lg p-6 mb-8 border border-green-500/30">
<h2 className="text-xl font-semibold mb-4 text-green-400">📊 Current Status</h2>
<div className="grid grid-cols-2 md:grid-cols-4 gap-4">
<div>
<div className="text-sm text-gray-400">Starting Capital</div>
<div className="text-2xl font-bold">{formatCurrency(STARTING_CAPITAL)}</div>
</div>
<div>
<div className="text-sm text-gray-400">Live Capital</div>
<div className="text-2xl font-bold text-green-400">
{loading ? '...' : formatCurrency(currentCapital)}
</div>
</div>
<div>
<div className="text-sm text-gray-400">Strategy</div>
<div className="text-2xl font-bold text-blue-400">ML v11.2</div>
</div>
<div>
<div className="text-sm text-gray-400">Pyramiding</div>
<div className="text-2xl font-bold text-purple-400">7x + 7x</div>
</div>
</div>
</div>
{/* ACTUAL PROGRESS vs PLAN */}
<div className="bg-gray-800 rounded-lg p-6 mb-8 border border-yellow-500/30">
<h2 className="text-xl font-semibold mb-4 text-yellow-400">📈 Actual Progress vs Plan</h2>
{/* Summary Stats */}
<div className="grid grid-cols-2 md:grid-cols-5 gap-4 mb-6">
<div className="bg-gray-700 rounded p-4">
<div className="text-sm text-gray-400">Total P&L</div>
<div className={`text-2xl font-bold ${tradingStats?.totalPnL && tradingStats.totalPnL >= 0 ? 'text-green-400' : 'text-red-400'}`}>
{loading ? '...' : tradingStats ? formatCurrency(tradingStats.totalPnL) : '$0'}
</div>
</div>
<div className="bg-gray-700 rounded p-4">
<div className="text-sm text-gray-400">Total Trades</div>
<div className="text-2xl font-bold text-blue-400">
{loading ? '...' : tradingStats?.totalTrades || 0}
</div>
</div>
<div className="bg-gray-700 rounded p-4">
<div className="text-sm text-gray-400">Win Rate</div>
<div className={`text-2xl font-bold ${tradingStats?.winRate && tradingStats.winRate >= 50 ? 'text-green-400' : 'text-yellow-400'}`}>
{loading ? '...' : tradingStats ? `${tradingStats.winRate.toFixed(1)}%` : '0%'}
</div>
</div>
<div className="bg-gray-700 rounded p-4">
<div className="text-sm text-gray-400">Capital Change</div>
<div className={`text-2xl font-bold ${currentCapital - STARTING_CAPITAL >= 0 ? 'text-green-400' : 'text-red-400'}`}>
{loading ? '...' : `${((currentCapital - STARTING_CAPITAL) / STARTING_CAPITAL * 100).toFixed(1)}%`}
</div>
</div>
<div className="bg-gray-700 rounded p-4">
<div className="text-sm text-gray-400">Net Profit</div>
<div className={`text-2xl font-bold ${currentCapital - STARTING_CAPITAL >= 0 ? 'text-green-400' : 'text-red-400'}`}>
{loading ? '...' : formatCurrency(currentCapital - STARTING_CAPITAL)}
</div>
</div>
</div>
{/* Plan Comparison */}
<div className="bg-gray-700/50 rounded-lg p-4">
<h3 className="text-md font-semibold mb-3 text-gray-300">Expected vs Actual (70%/mo target)</h3>
{(() => {
const daysElapsed = Math.max(0, Math.floor((new Date().getTime() - START_DATE.getTime()) / (1000 * 60 * 60 * 24)))
const monthsElapsed = daysElapsed / 30
const dailyRate = Math.pow(1.70, 1/30) - 1 // 70%/month converted to daily compound rate
const expectedCapital = STARTING_CAPITAL * Math.pow(1 + dailyRate, daysElapsed)
const expectedGain = expectedCapital - STARTING_CAPITAL
const actualGain = currentCapital - STARTING_CAPITAL
const onTrack = currentCapital >= expectedCapital
return (
<div className="space-y-2">
<div className="flex justify-between items-center">
<span className="text-gray-400">Days Since Start (Jan 6, 2026):</span>
<span className="text-blue-400 font-bold">{daysElapsed} days ({monthsElapsed.toFixed(1)} months)</span>
</div>
<div className="flex justify-between items-center">
<span className="text-gray-400">Expected Capital @ 70%/mo:</span>
<span className="text-yellow-400 font-bold">{formatCurrency(expectedCapital)} (+{formatCurrency(expectedGain)})</span>
</div>
<div className="flex justify-between items-center">
<span className="text-gray-400">Current Capital:</span>
<span className={`font-bold ${actualGain >= 0 ? 'text-green-400' : 'text-red-400'}`}>
{loading ? '...' : formatCurrency(currentCapital)} ({actualGain >= 0 ? '+' : ''}{formatCurrency(actualGain)})
</span>
</div>
<div className="flex justify-between items-center border-t border-gray-600 pt-2 mt-2">
<span className="text-gray-400">Status vs Plan:</span>
<span className={`font-bold ${onTrack ? 'text-green-400' : 'text-red-400'}`}>
{loading ? '...' : onTrack ? '✅ ON TRACK' : '⚠️ BEHIND'}
({formatCurrency(currentCapital - expectedCapital)}, {((currentCapital / expectedCapital - 1) * 100).toFixed(1)}%)
</span>
</div>
<div className="flex justify-between items-center">
<span className="text-gray-400">Actual Daily Return:</span>
<span className={`font-bold ${actualGain >= 0 ? 'text-green-400' : 'text-red-400'}`}>
{loading || daysElapsed === 0 ? '...' : `${((Math.pow(currentCapital / STARTING_CAPITAL, 1 / Math.max(1, daysElapsed)) - 1) * 100).toFixed(2)}%/day`}
{daysElapsed > 0 && !loading && ` (≈ ${((Math.pow(currentCapital / STARTING_CAPITAL, 30 / Math.max(1, daysElapsed)) - 1) * 100).toFixed(0)}%/mo)`}
</span>
</div>
</div>
)
})()}
</div>
</div>
{/* Scenario Selector */}
<div className="bg-gray-800 rounded-lg p-6 mb-8 border border-gray-700">
<h2 className="text-xl font-semibold mb-4">🎯 Select Monthly Return Scenario</h2>
<div className="flex flex-wrap gap-2 mb-6">
{[50, 70, 90, 110, 150].map(rate => (
<button
key={rate}
onClick={() => setSelectedScenario(rate)}
className={`px-4 py-2 rounded-lg font-semibold transition-all ${
selectedScenario === rate
? 'bg-green-600 text-white'
: 'bg-gray-700 text-gray-300 hover:bg-gray-600'
}`}
>
{rate}%/mo
</button>
))}
</div>
{/* Year-End Summary for Selected Scenario */}
<div className="bg-gray-700 rounded-lg p-4">
<h3 className="text-lg font-semibold mb-3 text-yellow-400">
Year 1 Result @ {selectedScenario}%/mo
</h3>
<div className="grid grid-cols-2 md:grid-cols-4 gap-4">
<div>
<div className="text-sm text-gray-400">Trading Account</div>
<div className="text-xl font-bold text-green-400">{formatCurrency(finalMonth.endCapital)}</div>
</div>
<div>
<div className="text-sm text-gray-400">BTC Holdings</div>
<div className="text-xl font-bold text-orange-400">{formatCurrency(finalMonth.btcHoldings)}</div>
</div>
<div>
<div className="text-sm text-gray-400">Cash Withdrawn</div>
<div className="text-xl font-bold text-purple-400">{formatCurrency(finalMonth.totalCashOut)}</div>
</div>
<div>
<div className="text-sm text-gray-400">Total Net Worth</div>
<div className="text-2xl font-bold text-white">{formatCurrency(finalMonth.netWorth)}</div>
</div>
</div>
</div>
</div>
{/* Scenario Comparison Table */}
<div className="bg-gray-800 rounded-lg p-6 mb-8 border border-gray-700">
<h2 className="text-xl font-semibold mb-4">📊 All Scenarios Comparison</h2>
<div className="overflow-x-auto">
<table className="w-full">
<thead>
<tr className="text-left text-gray-400 border-b border-gray-700">
<th className="pb-3">Scenario</th>
<th className="pb-3 text-right">Trading</th>
<th className="pb-3 text-right">BTC Holdings</th>
<th className="pb-3 text-right">Cash Out</th>
<th className="pb-3 text-right">Net Worth</th>
</tr>
</thead>
<tbody>
{scenarios.map((scenario, idx) => (
<tr
key={idx}
className={`border-b border-gray-700 ${
scenario.monthlyRate * 100 === selectedScenario ? 'bg-gray-700' : ''
}`}
>
<td className={`py-3 ${scenario.color} font-semibold`}>{scenario.label}</td>
<td className="py-3 text-right">{formatCurrency(scenario.finalTrading)}</td>
<td className="py-3 text-right text-orange-400">{formatCurrency(scenario.finalBTC)}</td>
<td className="py-3 text-right text-purple-400">{formatCurrency(scenario.totalCashOut)}</td>
<td className="py-3 text-right font-bold">{formatCurrency(scenario.finalNetWorth)}</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
{/* Monthly Breakdown Table */}
<div className="bg-gray-800 rounded-lg p-6 mb-8 border border-gray-700">
<h2 className="text-xl font-semibold mb-4">📅 Month-by-Month Breakdown @ {selectedScenario}%/mo</h2>
<div className="overflow-x-auto">
<table className="w-full text-sm">
<thead>
<tr className="text-left text-gray-400 border-b border-gray-700">
<th className="pb-3">Month</th>
<th className="pb-3 text-right">Start</th>
<th className="pb-3 text-right">Profit</th>
<th className="pb-3 text-right">Withdraw</th>
<th className="pb-3 text-right">BTC</th>
<th className="pb-3 text-right">End</th>
<th className="pb-3 text-right">BTC Total</th>
<th className="pb-3 text-right">Net Worth</th>
</tr>
</thead>
<tbody>
{currentProjection.map((month, idx) => (
<tr key={idx} className="border-b border-gray-700 hover:bg-gray-700">
<td className="py-2 font-semibold">{month.date}</td>
<td className="py-2 text-right text-gray-400">{formatCurrency(month.startCapital)}</td>
<td className="py-2 text-right text-green-400">+{formatCurrency(month.profit)}</td>
<td className="py-2 text-right text-purple-400">
{month.withdrawal > 0 ? `-${formatCurrency(month.withdrawal)}` : '-'}
</td>
<td className="py-2 text-right text-orange-400">
{month.btcSweep > 0 ? formatCurrency(month.btcSweep) : '-'}
</td>
<td className="py-2 text-right">{formatCurrency(month.endCapital)}</td>
<td className="py-2 text-right text-orange-400">{formatCurrency(month.btcHoldings)}</td>
<td className="py-2 text-right font-bold">{formatCurrency(month.netWorth)}</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
{/* Data Foundation */}
<div className="bg-gray-800 rounded-lg p-6 mb-8 border border-blue-500/30">
<h2 className="text-xl font-semibold mb-4 text-blue-400">🔬 Data Foundation</h2>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<div>
<h3 className="text-lg font-semibold mb-2">ML v11.2 Backtest Results</h3>
<ul className="space-y-1 text-gray-300">
<li> <span className="text-green-400 font-semibold">44 trades</span> over 8 days</li>
<li> <span className="text-green-400 font-semibold">84.09% win rate</span></li>
<li> <span className="text-green-400 font-semibold">3.061 profit factor</span></li>
<li> Extrapolated: ~176%/mo raw</li>
<li> Base case: 70%/mo (conservative)</li>
</ul>
</div>
<div>
<h3 className="text-lg font-semibold mb-2">Pyramiding Configuration</h3>
<ul className="space-y-1 text-gray-300">
<li> Base leverage: <span className="text-purple-400 font-semibold">7x</span></li>
<li> Stack leverage: <span className="text-purple-400 font-semibold">7x</span></li>
<li> Max total: <span className="text-purple-400 font-semibold">14x</span></li>
<li> Max pyramid levels: <span className="text-purple-400 font-semibold">2</span></li>
<li> Window: 4 hours (48 bars)</li>
</ul>
</div>
</div>
</div>
{/* Risk Disclaimer */}
<div className="bg-red-900/20 rounded-lg p-6 border border-red-500/30">
<h2 className="text-xl font-semibold mb-2 text-red-400"> Important Disclaimer</h2>
<p className="text-gray-300 text-sm">
These projections are based on backtested results and are NOT guaranteed. Past performance does not
guarantee future results. Cryptocurrency trading involves substantial risk of loss. The projections
assume consistent market conditions and strategy performance, which may not occur. Only trade with
capital you can afford to lose.
</p>
</div>
{/* Footer */}
<div className="mt-8 text-center text-gray-500 text-sm">
<p>Strategy: ML v11.2 + Pyramiding | Exchange: MEXC (SOL/USDT Perp)</p>
<p className="mt-1">Last Updated: January 2026</p>
</div>
</div>
</div>
)
}