Files
trading_bot_v4/app/projection/page.tsx
mindesbunister b4bcde942a critical: Fix entry AND exit prices to use actual Drift fills (Bug #89)
- Extended getActualFillPriceFromTx() to also extract entry fill prices
- openPosition() now uses actual fill from tx logs (was using oracle price)
- closePosition() already fixed to use actual exit fills
- Both prices now extracted via Drift SDK LogParser OrderActionRecord events
- Eliminates ~0.08% entry and exit price discrepancies vs Drift UI
- P&L calculations now 100% accurate to actual execution prices

Files changed:
- lib/drift/orders.ts (entry extraction in openPosition)
- docs/COMMON_PITFALLS.md (updated Pitfall #89)

Expected impact: Entry AND exit prices match Drift exactly on all future trades
2026-01-12 08:32:48 +01:00

395 lines
17 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
}
export default function ProjectionPage() {
const [currentCapital, setCurrentCapital] = useState<number>(0)
const [loading, setLoading] = useState(true)
const [selectedScenario, setSelectedScenario] = useState<number>(70)
// Strategy Parameters (Jan 2026)
const STARTING_CAPITAL = 1400
const TRADING_CAP = 50000
const BTC_MONTHLY_GROWTH = 0.05 // 5% per month (60% annual)
const START_DATE = new Date('2026-01-15')
// 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 fetchCurrentCapital() {
try {
const response = await fetch('/api/drift/account-summary')
const data = await response.json()
if (data.success) {
setCurrentCapital(data.freeCollateral || 0)
}
} catch (error) {
console.error('Failed to fetch capital:', error)
} finally {
setLoading(false)
}
}
fetchCurrentCapital()
}, [])
// 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>
{/* 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>
)
}