분석레포트 로직 수정

This commit is contained in:
Macbook
2026-06-08 10:08:39 +09:00
parent e11e1a46fa
commit c20c806c19
22 changed files with 254 additions and 108 deletions
+7 -34
View File
@@ -6,41 +6,17 @@ import type {
} from './backendApi';
import type { BacktestAnalysisReportModel } from '../components/backtest/BacktestAnalysisReportModal';
import type { LiveExecutionItem } from './liveExecutionGroups';
import { buildAnalysisFromPaperTrades } from './paperMetrics';
import { fmtListTimestamp, toUpbitMarket } from './backtestUiUtils';
import { getKoreanName } from './marketNameCache';
import { repairUtf8Mojibake } from './textEncoding';
/** 실시간 매매 탭 — KPI만 있는 경우 최소 분석 객체 */
/** 실시간 매매 탭 — 체결 이력 기반 분석 */
export function buildAnalysisFromLive(
item: LiveExecutionItem,
initialCapital = 10_000_000,
): BacktestAnalysis {
const finalEquity = initialCapital * (1 + item.totalReturnPct);
const winCount = Math.round(item.tradeCount * item.winRatePct);
return {
initialCapital,
finalEquity,
totalReturnPct: item.totalReturnPct,
totalProfitLoss: finalEquity - initialCapital,
grossProfit: 0,
grossLoss: 0,
avgReturnPct: item.tradeCount > 0 ? item.totalReturnPct / item.tradeCount : 0,
profitLossRatio: item.profitFactor,
numberOfPositions: item.tradeCount,
numberOfWinning: winCount,
numberOfLosing: Math.max(0, item.tradeCount - winCount),
numberOfBreakEven: 0,
winRate: item.winRatePct,
maxDrawdownPct: item.mddPct,
maxRunupPct: 0,
sharpeRatio: item.sharpeRatio,
sortinoRatio: 0,
calmarRatio: 0,
valueAtRisk95: 0,
expectedShortfall: 0,
buyAndHoldReturnPct: 0,
vsBuyAndHold: 0,
};
return buildAnalysisFromPaperTrades(item.trades, initialCapital);
}
function buildAnalysisFromStats(s: BacktestStats): BacktestAnalysis {
@@ -101,14 +77,11 @@ export function buildBacktestReportModel(
record: BacktestResultRecord,
analysis: BacktestAnalysis,
signals: BacktestSignal[],
strategyNamesById: Record<number, string> = {},
_strategyNamesById: Record<number, string> = {},
): BacktestAnalysisReportModel {
const market = toUpbitMarket(record.symbol);
const freshName = record.strategyId != null
? strategyNamesById[record.strategyId]
: undefined;
const strategyName = repairUtf8Mojibake(
freshName || record.strategyName || '전략 없음',
record.strategyName || '전략 없음',
);
return {
analysis,
@@ -126,10 +99,10 @@ export function buildBacktestReportModel(
export function buildLiveReportModel(
item: LiveExecutionItem,
signals: BacktestSignal[],
timeframe: string,
initialCapital = 10_000_000,
): BacktestAnalysisReportModel {
const market = toUpbitMarket(item.symbol);
const timeframe = item.timeframe !== 'unknown' ? item.timeframe : '—';
return {
analysis: buildAnalysisFromLive(item, initialCapital),
signals,
@@ -137,7 +110,7 @@ export function buildLiveReportModel(
symbol: item.symbol,
symbolKo: getKoreanName(market),
timeframe,
barCount: 300,
barCount: item.trades.length,
createdAt: item.createdAt ? fmtListTimestamp(item.createdAt) : undefined,
reportKind: 'live',
};