전략평가 화면 전략 일괄평가 기능
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
import type { OHLCVBar } from '../types';
|
||||
import type { StrategyDto } from './backendApi';
|
||||
import { fetchLiveConditionScanSignals } from './backendApi';
|
||||
import { buildEvalParamsFromStrategy } from './strategyEvaluationParams';
|
||||
import { buildStrategyEvaluationToolbarSummary } from './strategyEvaluationReport';
|
||||
|
||||
export interface StrategyBulkEvalResult {
|
||||
fullBuyReturnPct: number;
|
||||
splitBuyReturnPct: number;
|
||||
}
|
||||
|
||||
export interface StrategyBulkEvalContext {
|
||||
market: string;
|
||||
timeframe: string;
|
||||
windowEndTimeSec: number | null;
|
||||
evaluationBarCount: number;
|
||||
barsFingerprint: string;
|
||||
}
|
||||
|
||||
export function buildStrategyBulkEvalScanKey(ctx: StrategyBulkEvalContext): string {
|
||||
const windowKey = ctx.windowEndTimeSec ?? 'latest';
|
||||
return `${ctx.market}|${ctx.timeframe}|${windowKey}|${ctx.evaluationBarCount}|${ctx.barsFingerprint}`;
|
||||
}
|
||||
|
||||
export function buildBarsFingerprint(bars: OHLCVBar[]): string {
|
||||
if (bars.length === 0) return '0';
|
||||
const first = bars[0];
|
||||
const last = bars[bars.length - 1];
|
||||
return `${bars.length}:${first.time}:${last.time}`;
|
||||
}
|
||||
|
||||
export const strategyBulkEvalKeys = {
|
||||
all: ['strategyBulkEval'] as const,
|
||||
returns: (scanKey: string, strategyId: number) =>
|
||||
[...strategyBulkEvalKeys.all, scanKey, strategyId] as const,
|
||||
};
|
||||
|
||||
export async function evaluateStrategyBulkReturns(opts: {
|
||||
strategy: StrategyDto;
|
||||
market: string;
|
||||
timeframe: string;
|
||||
bars: OHLCVBar[];
|
||||
evaluationBarCount: number;
|
||||
initialCapital: number;
|
||||
getParams: (type: string) => Record<string, number | string | boolean>;
|
||||
}): Promise<StrategyBulkEvalResult> {
|
||||
const strategyId = opts.strategy.id;
|
||||
if (!strategyId || opts.bars.length < 10) {
|
||||
throw new Error('평가 데이터 부족');
|
||||
}
|
||||
|
||||
const indicatorParams = buildEvalParamsFromStrategy(opts.strategy, opts.getParams);
|
||||
const signals = await fetchLiveConditionScanSignals(
|
||||
opts.market,
|
||||
strategyId,
|
||||
opts.bars.map(b => ({
|
||||
time: b.time,
|
||||
open: b.open,
|
||||
high: b.high,
|
||||
low: b.low,
|
||||
close: b.close,
|
||||
volume: b.volume,
|
||||
})),
|
||||
opts.timeframe,
|
||||
indicatorParams,
|
||||
opts.evaluationBarCount,
|
||||
);
|
||||
|
||||
const summary = buildStrategyEvaluationToolbarSummary(signals, {
|
||||
initialCapital: opts.initialCapital,
|
||||
symbol: opts.market.replace(/^KRW-/, ''),
|
||||
});
|
||||
|
||||
return {
|
||||
fullBuyReturnPct: summary.fullBuyReturnPct,
|
||||
splitBuyReturnPct: summary.splitBuyReturnPct,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user