전략평가 MA 참조에러 수정
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
/**
|
||||
* MA/EMA DSL 필드 — MA1~MA11 슬롯 ↔ SMA period1~11 (보조지표 설정과 동일)
|
||||
*
|
||||
* - MA3 → period3 (예: 20일)
|
||||
* - MA20 → 레거시: 숫자>11 이면 기간 20일 그대로
|
||||
*/
|
||||
import { SMA_DEFAULT_PERIODS, SMA_MA_COUNT } from './smaConfig';
|
||||
|
||||
export const MA_DSL_SLOT_MAX = SMA_MA_COUNT;
|
||||
|
||||
export function buildMaLinesFromSmaParams(
|
||||
params?: Record<string, number | string | boolean>,
|
||||
): number[] {
|
||||
const lines: number[] = [];
|
||||
for (let slot = 1; slot <= SMA_MA_COUNT; slot++) {
|
||||
const raw = params?.[`period${slot}`];
|
||||
const p = typeof raw === 'number' && raw > 0
|
||||
? Math.floor(raw)
|
||||
: SMA_DEFAULT_PERIODS[slot - 1];
|
||||
lines.push(p);
|
||||
}
|
||||
return lines;
|
||||
}
|
||||
|
||||
/** DSL MA/EMA 필드 → 실제 SMA/EMA 계산 기간 */
|
||||
export function resolveMaDslFieldPeriod(
|
||||
field: string | undefined,
|
||||
smaParams?: Record<string, number | string | boolean>,
|
||||
): number | null {
|
||||
if (!field) return null;
|
||||
const ma = /^MA(\d+)$/.exec(field);
|
||||
if (ma && !field.startsWith('MACD')) {
|
||||
const n = parseInt(ma[1], 10);
|
||||
if (!Number.isFinite(n) || n <= 0) return null;
|
||||
if (n <= MA_DSL_SLOT_MAX) return buildMaLinesFromSmaParams(smaParams)[n - 1];
|
||||
return n;
|
||||
}
|
||||
const ema = /^EMA(\d+)$/.exec(field);
|
||||
if (ema) {
|
||||
const n = parseInt(ema[1], 10);
|
||||
if (!Number.isFinite(n) || n <= 0) return null;
|
||||
if (n <= MA_DSL_SLOT_MAX) return buildMaLinesFromSmaParams(smaParams)[n - 1];
|
||||
return n;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/** UI·해석용 라벨 — MA5(60일) */
|
||||
export function formatMaDslFieldLabel(
|
||||
field: string | undefined,
|
||||
smaParams?: Record<string, number | string | boolean>,
|
||||
): string {
|
||||
if (!field) return '';
|
||||
const period = resolveMaDslFieldPeriod(field, smaParams);
|
||||
if (period == null) return field;
|
||||
const ma = /^MA(\d+)$/.exec(field);
|
||||
if (ma && !field.startsWith('MACD')) {
|
||||
const n = parseInt(ma[1], 10);
|
||||
if (n >= 1 && n <= MA_DSL_SLOT_MAX) return `MA${n}(${period}일)`;
|
||||
return `MA(${period}일)`;
|
||||
}
|
||||
const ema = /^EMA(\d+)$/.exec(field);
|
||||
if (ema) {
|
||||
const n = parseInt(ema[1], 10);
|
||||
if (n >= 1 && n <= MA_DSL_SLOT_MAX) return `EMA${n}(${period}일)`;
|
||||
return `EMA(${period}일)`;
|
||||
}
|
||||
return field;
|
||||
}
|
||||
|
||||
export function buildMaFieldOptions(
|
||||
maLines: number[],
|
||||
): { value: string; label: string }[] {
|
||||
return Array.from({ length: SMA_MA_COUNT }, (_, i) => {
|
||||
const slot = i + 1;
|
||||
const p = maLines[i] ?? SMA_DEFAULT_PERIODS[i];
|
||||
return { value: `MA${slot}`, label: `MA${slot}(${p}일)` };
|
||||
});
|
||||
}
|
||||
|
||||
export function buildEmaFieldOptions(
|
||||
maLines: number[],
|
||||
maxSlots = 4,
|
||||
): { value: string; label: string }[] {
|
||||
const n = Math.min(maxSlots, SMA_MA_COUNT);
|
||||
return Array.from({ length: n }, (_, i) => {
|
||||
const slot = i + 1;
|
||||
const p = maLines[i] ?? SMA_DEFAULT_PERIODS[i];
|
||||
return { value: `EMA${slot}`, label: `EMA${slot}(${p}일)` };
|
||||
});
|
||||
}
|
||||
|
||||
/** 레거시 MA20·MA60(기간 인코딩) 옵션 유지 */
|
||||
export function appendLegacyMaFieldOption(
|
||||
opts: { value: string; label: string }[],
|
||||
field: string | undefined,
|
||||
): { value: string; label: string }[] {
|
||||
if (!field || opts.some(o => o.value === field)) return opts;
|
||||
const period = resolveMaDslFieldPeriod(field);
|
||||
if (period == null) return opts;
|
||||
const ma = /^MA(\d+)$/.exec(field);
|
||||
if (ma && !field.startsWith('MACD')) {
|
||||
const n = parseInt(ma[1], 10);
|
||||
if (n > MA_DSL_SLOT_MAX) {
|
||||
return [...opts, { value: field, label: `MA(${period}일)` }];
|
||||
}
|
||||
}
|
||||
const ema = /^EMA(\d+)$/.exec(field);
|
||||
if (ema) {
|
||||
const n = parseInt(ema[1], 10);
|
||||
if (n > MA_DSL_SLOT_MAX) {
|
||||
return [...opts, { value: field, label: `EMA(${period}일)` }];
|
||||
}
|
||||
}
|
||||
return opts;
|
||||
}
|
||||
Reference in New Issue
Block a user