가상수정2
This commit is contained in:
@@ -51,7 +51,7 @@ function walk(
|
||||
seen.add(key);
|
||||
|
||||
const condLabel = CONDITION_LABEL[c.conditionType] ?? c.conditionType;
|
||||
const target = c.targetValue ?? c.compareValue ?? null;
|
||||
const target = coerceFiniteNumber(c.targetValue ?? c.compareValue ?? null);
|
||||
const plotKey = c.leftField && c.leftField !== 'none' ? c.leftField : c.indicatorType;
|
||||
|
||||
out.push({
|
||||
@@ -71,6 +71,14 @@ function walk(
|
||||
node.children?.forEach(c => walk(c, timeframe, side, out, seen));
|
||||
}
|
||||
|
||||
/** API·DSL에서 문자열로 올 수 있는 값을 안전하게 숫자로 변환 */
|
||||
export function coerceFiniteNumber(v: unknown): number | null {
|
||||
if (v == null || v === '') return null;
|
||||
if (typeof v === 'number') return Number.isFinite(v) ? v : null;
|
||||
const n = Number(v);
|
||||
return Number.isFinite(n) ? n : null;
|
||||
}
|
||||
|
||||
export function extractVirtualConditions(strategy: StrategyDto | null | undefined): VirtualConditionRow[] {
|
||||
if (!strategy) return [];
|
||||
const out: VirtualConditionRow[] = [];
|
||||
@@ -83,23 +91,26 @@ export function extractVirtualConditions(strategy: StrategyDto | null | undefine
|
||||
/** 조건 충족 여부 (단순 임계값 비교) */
|
||||
export function isConditionMet(
|
||||
conditionType: string,
|
||||
current: number | null,
|
||||
target: number | null,
|
||||
current: number | null | unknown,
|
||||
target: number | null | unknown,
|
||||
): boolean | null {
|
||||
if (current == null || target == null) return null;
|
||||
const cur = coerceFiniteNumber(current);
|
||||
const tgt = coerceFiniteNumber(target);
|
||||
if (cur == null || tgt == null) return null;
|
||||
switch (conditionType) {
|
||||
case 'GT': case 'CROSS_UP': return current > target;
|
||||
case 'LT': case 'CROSS_DOWN': return current < target;
|
||||
case 'GTE': return current >= target;
|
||||
case 'LTE': return current <= target;
|
||||
case 'EQ': return Math.abs(current - target) < 1e-6;
|
||||
case 'NEQ': return Math.abs(current - target) >= 1e-6;
|
||||
case 'GT': case 'CROSS_UP': return cur > tgt;
|
||||
case 'LT': case 'CROSS_DOWN': return cur < tgt;
|
||||
case 'GTE': return cur >= tgt;
|
||||
case 'LTE': return cur <= tgt;
|
||||
case 'EQ': return Math.abs(cur - tgt) < 1e-6;
|
||||
case 'NEQ': return Math.abs(cur - tgt) >= 1e-6;
|
||||
default: return null;
|
||||
}
|
||||
}
|
||||
|
||||
export function formatIndicatorValue(v: number | null): string {
|
||||
if (v == null || Number.isNaN(v)) return '—';
|
||||
if (Math.abs(v) >= 1000) return v.toLocaleString(undefined, { maximumFractionDigits: 0 });
|
||||
return v.toFixed(2);
|
||||
export function formatIndicatorValue(v: number | null | unknown): string {
|
||||
const n = coerceFiniteNumber(v);
|
||||
if (n == null) return '—';
|
||||
if (Math.abs(n) >= 1000) return n.toLocaleString(undefined, { maximumFractionDigits: 0 });
|
||||
return n.toFixed(2);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user