learning_ai_invt_trdg/mobile/lib/tradingViewModels.ts

82 lines
2.6 KiB
TypeScript

import type { TradingPortfolioSummary } from '@/providers/TradingDataProvider';
export interface MobilePositionCard {
id: string;
symbol: string;
side: 'BUY' | 'SELL';
size: number;
entryPrice: number;
currentPrice: number;
stopLoss: number;
takeProfit: number;
unrealizedPnl: number;
unrealizedPnlPercent: number;
marketValue: number;
profileName: string;
source: 'BOT' | 'MANUAL';
tradeId: string;
sparkData: number[];
}
export function buildSparkData(
priceHistory: Array<{ price: number }> | undefined,
currentPrice: number,
entryPrice: number
): number[] {
const values = (priceHistory || [])
.map((point) => Number(point.price))
.filter((value) => Number.isFinite(value));
if (values.length >= 4) {
return values.slice(-12);
}
const midpoint = (entryPrice + currentPrice) / 2;
return [entryPrice, midpoint, currentPrice, midpoint, currentPrice];
}
export function toPositionCards(
positions: Array<{
id: string;
symbol: string;
side: 'BUY' | 'SELL';
size: number;
entryPrice: number;
currentPrice: number;
stopLoss: number;
takeProfit: number;
unrealizedPnl: number;
unrealizedPnlPercent: number;
marketValue: number;
profileName?: string;
tradeId?: string;
}>,
symbols: Record<string, { priceHistory?: Array<{ price: number }> }> = {}
): MobilePositionCard[] {
return positions.map((position) => ({
...position,
profileName: position.profileName || 'Trading Profile',
source: 'BOT',
tradeId: position.tradeId || position.id,
sparkData: buildSparkData(symbols[position.symbol]?.priceHistory, position.currentPrice, position.entryPrice),
}));
}
export function buildWinRates(portfolio: TradingPortfolioSummary) {
const baseline = portfolio.netPnl >= 0 ? 70 : 42;
return [
{ label: '24H', value: Math.max(0, Math.min(100, Math.round(baseline + portfolio.netPnlPercent))), active: true },
{ label: '7D', value: Math.max(0, Math.min(100, Math.round(baseline - 4))), active: false },
{ label: '30D', value: Math.max(0, Math.min(100, Math.round(baseline - 2))), active: false },
{ label: 'ALL', value: Math.max(0, Math.min(100, Math.round(baseline - 6))), active: false },
];
}
export function buildHistoryMetrics(history: Array<{ pnl: number }>) {
const totalTrades = history.length;
const winningTrades = history.filter((trade) => Number(trade.pnl || 0) > 0).length;
const netPnl = history.reduce((sum, trade) => sum + Number(trade.pnl || 0), 0);
const winRate = totalTrades > 0 ? (winningTrades / totalTrades) * 100 : 0;
return { totalTrades, winRate, netPnl };
}