Skip to main content
The Analytics Dashboard is your central hub for understanding trading performance on Solana. It provides real-time insights into profitability, risk metrics, trading behavior, and fee analysis.

Win Rate & Performance Metrics

Track your trading success with comprehensive win rate statistics:
src/lib/tradeFilters.ts
export function calculateWinRate(trades: Trade[]) {
    if (trades.length === 0) {
        return { winRate: '0', wins: 0, losses: 0 };
    }

    const wins = trades.filter(t => t.isWin).length;
    const losses = trades.length - wins;
    const winRate = ((wins / trades.length) * 100).toFixed(1);

    return { winRate, wins, losses };
}
What you’ll see:
  • Overall win rate percentage
  • Win/loss breakdown (e.g., “145W / 95L”)
  • Period-over-period comparison
A win rate above 50% indicates positive trading performance, but always consider it alongside average win/loss size.

Average Win vs. Average Loss

Understand the quality of your trades beyond just win rate:
src/lib/tradeFilters.ts
export function calculateAvgWin(trades: Trade[]): number {
    const winningTrades = trades.filter(t => t.isWin);
    if (winningTrades.length === 0) return 0;

    const totalWinPnL = winningTrades.reduce((sum, t) => sum + t.pnl, 0);
    return totalWinPnL / winningTrades.length;
}

export function calculateAvgLoss(trades: Trade[]): number {
    const losingTrades = trades.filter(t => t.pnl < 0);
    if (losingTrades.length === 0) return 0;

    const totalLossPnL = losingTrades.reduce((sum, t) => sum + t.pnl, 0);
    return totalLossPnL / losingTrades.length;
}
Key Insight: A positive profit factor means your average win is larger than your average loss, which is crucial for long-term profitability.

PnL Chart & Equity Curve

Visualize your cumulative performance over time:
PnL Analysis Chart
Features:
  • Daily PnL aggregation from src/lib/mockData.ts:231
  • Color-coded bars (green for profits, red for losses)
  • Cumulative equity curve overlay
  • Drawdown visualization toggle
src/lib/mockData.ts
export function calculateDailyPnL(trades: Trade[]): DailyPnL[] {
    const dailyMap = new Map<string, DailyPnL>();

    trades.forEach(trade => {
        const dateKey = format(startOfDay(trade.closedAt), 'yyyy-MM-dd');

        if (!dailyMap.has(dateKey)) {
            dailyMap.set(dateKey, {
                date: dateKey,
                pnl: 0,
                trades: 0,
                wins: 0,
                losses: 0,
            });
        }

        const daily = dailyMap.get(dateKey)!;
        daily.pnl += trade.pnl;
        daily.trades += 1;
        if (trade.isWin) daily.wins += 1;
        else daily.losses += 1;
    });

    return Array.from(dailyMap.values()).sort((a, b) => a.date.localeCompare(b.date));
}
Toggle “Show Drawdown on Chart” to visualize periods where your equity was below its peak value.

Fee Breakdown Analysis

Understand exactly where your trading fees go:
src/lib/mockData.ts
export function calculateFeeBreakdown(trades: Trade[]): FeeComposition[] {
    const protocolMaker = trades
        .filter(t => t.isMaker)
        .reduce((sum, t) => sum + (t.feeBreakdown?.[0]?.amount || 0), 0);

    const protocolTaker = trades
        .filter(t => !t.isMaker)
        .reduce((sum, t) => sum + (t.feeBreakdown?.[0]?.amount || 0), 0);

    const network = trades
        .reduce((sum, t) => sum + (t.feeBreakdown?.[1]?.amount || 0), 0);

    const total = protocolMaker + protocolTaker + network;

    return [
        {
            type: 'Protocol (Maker)',
            amount: protocolMaker,
            percent: total > 0 ? (protocolMaker / total) * 100 : 0,
        },
        {
            type: 'Protocol (Taker)',
            amount: protocolTaker,
            percent: total > 0 ? (protocolTaker / total) * 100 : 0,
        },
        {
            type: 'Network',
            amount: network,
            percent: total > 0 ? (network / total) * 100 : 0,
        },
    ];
}
Fee Categories:
  • Protocol (Maker): Fees paid when providing liquidity (0.025% default)
  • Protocol (Taker): Fees paid when taking liquidity (0.05% default)
  • Network: Solana transaction fees
High taker fees can significantly impact profitability. Consider using limit orders to qualify for maker rates.

Long/Short Ratio

Analyze your directional bias in perpetual trading:
src/lib/tradeFilters.ts
export function calculateLongShortRatio(trades: Trade[]) {
    const perpTrades = trades.filter(t => t.side === 'long' || t.side === 'short');

    if (perpTrades.length === 0) {
        return { longPercent: 50, shortPercent: 50, longCount: 0, shortCount: 0 };
    }

    const longCount = perpTrades.filter(t => t.side === 'long').length;
    const shortCount = perpTrades.filter(t => t.side === 'short').length;

    const longPercent = Math.round((longCount / perpTrades.length) * 100);
    const shortPercent = 100 - longPercent;

    return { longPercent, shortPercent, longCount, shortCount };
}
Displayed as:
  • Long: 62% (148 trades)
  • Short: 38% (92 trades)
A balanced long/short ratio indicates market-neutral trading, while heavy directional bias may expose you to market trend risk.

Leverage Analysis

Track leverage usage across perpetual positions:
src/lib/mockData.ts
export function calculateAverageLeverage(trades: Trade[]): number {
    const perpTrades = trades.filter(t => t.leverage !== undefined);
    if (perpTrades.length === 0) return 1;

    const totalLeverage = perpTrades.reduce((sum, t) => sum + (t.leverage || 1), 0);
    return totalLeverage / perpTrades.length;
}

export function calculateLeverageVsWinRate(trades: Trade[]) {
    const leverageMap = new Map<number, { wins: number; total: number }>();

    trades
        .filter(t => t.leverage !== undefined)
        .forEach(trade => {
            const lev = trade.leverage!;
            if (!leverageMap.has(lev)) {
                leverageMap.set(lev, { wins: 0, total: 0 });
            }
            const data = leverageMap.get(lev)!;
            data.total += 1;
            if (trade.isWin) data.wins += 1;
        });

    return Array.from(leverageMap.entries())
        .map(([leverage, data]) => ({
            leverage,
            winRate: data.total > 0 ? data.wins / data.total : 0,
            trades: data.total,
        }))
        .sort((a, b) => a.leverage - b.leverage);
}
Insights provided:
  • Average leverage across all perp trades
  • Win rate distribution by leverage level (1x, 2x, 3x, 5x, 8x, 10x)
  • Risk exposure per leverage tier
Higher leverage amplifies both gains and losses. The analytics show if your win rate decreases at higher leverage levels.

Time-Based Performance

Identify when you trade most profitably:

Session Analysis

src/lib/mockData.ts
export function calculateSessionPerformance(trades: Trade[]): SessionBucket[] {
    const sessions: Record<string, { pnl: number; trades: number; wins: number }> = {
        morning: { pnl: 0, trades: 0, wins: 0 },
        afternoon: { pnl: 0, trades: 0, wins: 0 },
        evening: { pnl: 0, trades: 0, wins: 0 },
        night: { pnl: 0, trades: 0, wins: 0 },
    };

    trades.forEach(trade => {
        const hour = trade.closedAt.getHours();
        let session: 'morning' | 'afternoon' | 'evening' | 'night';

        if (hour >= 6 && hour < 12) session = 'morning';
        else if (hour >= 12 && hour < 18) session = 'afternoon';
        else if (hour >= 18 && hour < 22) session = 'evening';
        else session = 'night';

        sessions[session].pnl += trade.pnl;
        sessions[session].trades += 1;
        if (trade.isWin) sessions[session].wins += 1;
    });

    return Object.entries(sessions).map(([session, data]) => ({
        session: session as 'morning' | 'afternoon' | 'evening' | 'night',
        pnl: data.pnl,
        trades: data.trades,
        winRate: data.trades > 0 ? data.wins / data.trades : 0,
    }));
}
Time Periods:
  • Morning: 6:00 AM - 12:00 PM
  • Afternoon: 12:00 PM - 6:00 PM
  • Evening: 6:00 PM - 10:00 PM
  • Night: 10:00 PM - 6:00 AM
Use this data to identify your most profitable trading hours and avoid sessions where you consistently underperform.

Time Filters

Analyze performance across different timeframes:
src/lib/tradeFilters.ts
export function filterTradesByDate(trades: Trade[], filter: FilterType): Trade[] {
    const now = new Date();

    switch (filter) {
        case 'Today':
            return trades.filter(t => isToday(t.closedAt));

        case 'Yesterday':
            return trades.filter(t => isYesterday(t.closedAt));

        case 'This Week':
            // Last 7 days (rolling)
            const sevenDaysAgo = startOfDay(subDays(now, 7));
            return trades.filter(t => t.closedAt >= sevenDaysAgo);

        case 'This Month':
            // Last 30 days (rolling)
            const thirtyDaysAgo = startOfDay(subDays(now, 30));
            return trades.filter(t => t.closedAt >= thirtyDaysAgo);

        case 'This Year':
            // Last 365 days (rolling)
            const yearAgo = startOfDay(subDays(now, 365));
            return trades.filter(t => t.closedAt >= yearAgo);

        case 'All':
        default:
            return trades;
    }
}
Available filters: Today, Yesterday, This Week (7 days), This Month (30 days), This Year (365 days), All

Trading Volume

Monitor your total market activity:
src/lib/tradeFilters.ts
export function calculateTradingVolume(trades: Trade[]): number {
    return trades.reduce((sum, t) => sum + t.notional, 0);
}

export function formatCompactNumber(value: number): string {
    const absValue = Math.abs(value);
    const sign = value >= 0 ? '' : '-';

    if (absValue >= 1_000_000) {
        return `${sign}$${(absValue / 1_000_000).toFixed(2)}M`;
    } else if (absValue >= 1_000) {
        return `${sign}$${(absValue / 1_000).toFixed(2)}K`;
    } else {
        return `${sign}$${absValue.toFixed(2)}`;
    }
}
Displayed as: 1.23M,1.23M, 456.78K, or $12.34 depending on magnitude
Higher trading volume doesn’t always mean better performance. Focus on profitability per trade.

Next Steps

Trade Journaling

Add notes and lessons learned to your trades

Trade History

Explore detailed trade-by-trade history

Build docs developers (and LLMs) love