initial backtests
This commit is contained in:
parent
fa70ada2bb
commit
5a3a23a2ba
6 changed files with 400 additions and 129 deletions
|
|
@ -32,40 +32,10 @@ export function BacktestPage() {
|
|||
// Current time is not available in the new API, so we'll estimate it based on progress
|
||||
const currentTime = null;
|
||||
|
||||
// Adapt the results when they come in
|
||||
// No adaptation needed - results are already in the correct format
|
||||
useEffect(() => {
|
||||
if (results && config) {
|
||||
setAdaptedResults({
|
||||
id: backtest?.id || '',
|
||||
config,
|
||||
metrics: {
|
||||
totalReturn: results.metrics.totalReturn,
|
||||
sharpeRatio: results.metrics.sharpeRatio,
|
||||
maxDrawdown: results.metrics.maxDrawdown,
|
||||
winRate: results.metrics.winRate,
|
||||
totalTrades: results.metrics.totalTrades,
|
||||
profitableTrades: Math.round(results.metrics.totalTrades * results.metrics.winRate / 100),
|
||||
},
|
||||
positions: [], // Not provided by current API
|
||||
trades: results.trades?.map(t => ({
|
||||
id: `${t.symbol}-${t.entryDate}`,
|
||||
timestamp: t.exitDate,
|
||||
symbol: t.symbol,
|
||||
side: t.pnl > 0 ? 'buy' : 'sell',
|
||||
quantity: t.quantity,
|
||||
price: t.exitPrice,
|
||||
commission: 0,
|
||||
pnl: t.pnl,
|
||||
})) || [],
|
||||
performanceData: results.equity.map(e => ({
|
||||
timestamp: e.date,
|
||||
portfolioValue: e.value,
|
||||
pnl: 0, // Would need to calculate from equity curve
|
||||
drawdown: 0, // Would need to calculate
|
||||
})),
|
||||
});
|
||||
}
|
||||
}, [results, config, backtest]);
|
||||
setAdaptedResults(results);
|
||||
}, [results]);
|
||||
|
||||
const handleConfigSubmit = useCallback(async (newConfig: BacktestConfig) => {
|
||||
setConfig(newConfig);
|
||||
|
|
|
|||
|
|
@ -13,11 +13,6 @@ interface BacktestResultsProps {
|
|||
}
|
||||
|
||||
export function BacktestResults({ status, results, currentTime }: BacktestResultsProps) {
|
||||
// Debug logging
|
||||
console.log('BacktestResults - results:', results);
|
||||
console.log('BacktestResults - ohlcData keys:', results?.ohlcData ? Object.keys(results.ohlcData) : 'No ohlcData');
|
||||
console.log('BacktestResults - first symbol data:', results?.ohlcData && Object.keys(results.ohlcData).length > 0 ? results.ohlcData[Object.keys(results.ohlcData)[0]] : 'No data');
|
||||
console.log('BacktestResults - equity data:', results?.equity);
|
||||
if (status === 'idle') {
|
||||
return (
|
||||
<div className="bg-surface-secondary p-8 rounded-lg border border-border h-full flex items-center justify-center">
|
||||
|
|
@ -125,14 +120,9 @@ export function BacktestResults({ status, results, currentTime }: BacktestResult
|
|||
const hasOhlcData = results.ohlcData && Object.keys(results.ohlcData).length > 0;
|
||||
const hasEquityData = results.equity && results.equity.length > 0;
|
||||
|
||||
console.log('Chart section - hasOhlcData:', hasOhlcData);
|
||||
console.log('Chart section - hasEquityData:', hasEquityData);
|
||||
|
||||
if (hasOhlcData) {
|
||||
const firstSymbol = Object.keys(results.ohlcData)[0];
|
||||
const ohlcData = results.ohlcData[firstSymbol];
|
||||
console.log('Chart section - using OHLC data for symbol:', firstSymbol);
|
||||
console.log('Chart section - OHLC data points:', ohlcData?.length);
|
||||
|
||||
return (
|
||||
<Chart
|
||||
|
|
@ -156,7 +146,6 @@ export function BacktestResults({ status, results, currentTime }: BacktestResult
|
|||
/>
|
||||
);
|
||||
} else if (hasEquityData) {
|
||||
console.log('Chart section - using equity data only');
|
||||
return (
|
||||
<Chart
|
||||
data={results.equity.map(point => ({
|
||||
|
|
@ -171,7 +160,6 @@ export function BacktestResults({ status, results, currentTime }: BacktestResult
|
|||
/>
|
||||
);
|
||||
} else {
|
||||
console.log('Chart section - showing no data message');
|
||||
return (
|
||||
<div className="h-96 bg-background rounded border border-border flex items-center justify-center">
|
||||
<p className="text-sm text-text-muted">
|
||||
|
|
@ -190,13 +178,13 @@ export function BacktestResults({ status, results, currentTime }: BacktestResult
|
|||
Trade History
|
||||
</h3>
|
||||
<TradeLog trades={results.trades.map(trade => ({
|
||||
id: crypto.randomUUID(),
|
||||
timestamp: trade.entryDate,
|
||||
id: trade.id,
|
||||
timestamp: trade.exitDate || trade.entryDate,
|
||||
symbol: trade.symbol,
|
||||
side: 'buy' as const,
|
||||
side: trade.side as 'buy' | 'sell',
|
||||
quantity: trade.quantity,
|
||||
price: trade.entryPrice,
|
||||
commission: 0,
|
||||
price: trade.exitPrice,
|
||||
commission: trade.commission,
|
||||
pnl: trade.pnl
|
||||
}))} />
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -24,26 +24,43 @@ export interface BacktestJob {
|
|||
}
|
||||
|
||||
export interface BacktestResult {
|
||||
// Identification
|
||||
backtestId: string;
|
||||
status: 'completed' | 'failed' | 'cancelled';
|
||||
completedAt: string;
|
||||
|
||||
// Configuration
|
||||
config: {
|
||||
name: string;
|
||||
strategy: string;
|
||||
symbols: string[];
|
||||
startDate: string;
|
||||
endDate: string;
|
||||
initialCapital: number;
|
||||
commission: number;
|
||||
slippage: number;
|
||||
dataFrequency: string;
|
||||
};
|
||||
|
||||
// Performance metrics
|
||||
metrics: {
|
||||
totalReturn: number;
|
||||
sharpeRatio: number;
|
||||
maxDrawdown: number;
|
||||
winRate: number;
|
||||
totalTrades: number;
|
||||
profitFactor?: number;
|
||||
profitFactor: number;
|
||||
profitableTrades: number;
|
||||
avgWin: number;
|
||||
avgLoss: number;
|
||||
expectancy: number;
|
||||
calmarRatio: number;
|
||||
sortinoRatio: number;
|
||||
};
|
||||
|
||||
// Chart data
|
||||
equity: Array<{ date: string; value: number }>;
|
||||
trades?: Array<{
|
||||
symbol: string;
|
||||
entryDate: string;
|
||||
exitDate: string;
|
||||
entryPrice: number;
|
||||
exitPrice: number;
|
||||
quantity: number;
|
||||
pnl: number;
|
||||
}>;
|
||||
ohlcData?: Record<string, Array<{
|
||||
ohlcData: Record<string, Array<{
|
||||
time: number;
|
||||
open: number;
|
||||
high: number;
|
||||
|
|
@ -51,6 +68,41 @@ export interface BacktestResult {
|
|||
close: number;
|
||||
volume?: number;
|
||||
}>>;
|
||||
|
||||
// Trade history
|
||||
trades: Array<{
|
||||
id: string;
|
||||
symbol: string;
|
||||
entryDate: string;
|
||||
exitDate: string | null;
|
||||
entryPrice: number;
|
||||
exitPrice: number;
|
||||
quantity: number;
|
||||
side: string;
|
||||
pnl: number;
|
||||
pnlPercent: number;
|
||||
commission: number;
|
||||
duration: number;
|
||||
}>;
|
||||
|
||||
// Positions
|
||||
positions: Array<{
|
||||
symbol: string;
|
||||
quantity: number;
|
||||
averagePrice: number;
|
||||
currentPrice: number;
|
||||
unrealizedPnl: number;
|
||||
realizedPnl: number;
|
||||
}>;
|
||||
|
||||
// Analytics
|
||||
analytics: {
|
||||
drawdownSeries: Array<{ timestamp: number; value: number }>;
|
||||
dailyReturns: number[];
|
||||
monthlyReturns: Record<string, number>;
|
||||
exposureTime: number;
|
||||
riskMetrics: Record<string, number>;
|
||||
};
|
||||
}
|
||||
|
||||
export const backtestApi = {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue