직접입력값 평가오류

This commit is contained in:
Macbook
2026-06-17 23:45:39 +09:00
parent 3130de113b
commit d4b5814bbc
7 changed files with 220 additions and 24 deletions
+8 -1
View File
@@ -266,7 +266,7 @@ export function getConditionThreshold(
}
export type SetConditionThresholdOptions = {
/** true: 직접입력 — K_+targetValue+thresholdOverride 유지 (프리셋 HL_* 로 접지 않음) */
/** true: 직접입력 모드 — hline 역할과 일치하지 않는 값만 K_ 스냅샷 유지 */
directInput?: boolean;
};
@@ -294,6 +294,13 @@ export function setConditionThreshold(
const current = cond[fieldKey];
if (!isThresholdFieldOrSymbol(current)) {
if (side === 'right' && INDICATORS_WITH_RIGHT_THRESHOLD_INPUT.has(cond.indicatorType)) {
const matchedRole = def
? inferThresholdRoleForValue(value, cond.indicatorType, def.hlThresh)
: null;
if (matchedRole != null) {
const { targetValue: _t, ...rest } = cond;
return { ...rest, [fieldKey]: matchedRole, thresholdOverride: false };
}
return {
...cond,
[fieldKey]: thresholdField(value),
@@ -26,7 +26,24 @@ function migrateConditionThreshold(
def: DefType,
signalType: 'buy' | 'sell',
): ConditionDSL {
if (isThresholdOverridden(cond)) return cond;
if (isThresholdOverridden(cond)) {
const val = cond.targetValue ?? parseThresholdField(cond.rightField);
if (val != null && Number.isFinite(val)) {
const role = inferThresholdRoleForValue(val, cond.indicatorType, def.hlThresh);
if (role != null) {
const { targetValue: _t, ...rest } = cond;
return migrateConditionPeriod({ ...rest, rightField: role, thresholdOverride: false });
}
}
if (cond.rightField?.startsWith('K_')) {
const role = inferThresholdSymbolFromLegacyExact(cond.rightField, cond.indicatorType, def.hlThresh);
if (role != null) {
const { targetValue: _t, ...rest } = cond;
return migrateConditionPeriod({ ...rest, rightField: role, thresholdOverride: false });
}
}
return cond;
}
let rightField = cond.rightField;
if (rightField?.startsWith('K_')) {
+3 -2
View File
@@ -5,6 +5,7 @@ import type { LogicNode } from './strategyTypes';
import type { StrategyDto } from './backendApi';
import { extractVirtualConditions } from './virtualStrategyConditions';
import { decodeConditionForEditor, encodeConditionForSave } from './strategyConditionSerde';
import { normalizeLogicRootForPersistence } from './strategyConditionNormalize';
import type { StrategyFlowLayoutStore } from './strategyEditorLayoutStorage';
export function asLogicNode(raw: unknown): LogicNode | null {
@@ -34,8 +35,8 @@ export function hydrateStrategyDto(strategy: StrategyDto): StrategyDto {
const sell = asLogicNode(strategy.sellCondition);
let next: StrategyDto = {
...strategy,
buyCondition: buy ?? undefined,
sellCondition: sell ?? undefined,
buyCondition: normalizeLogicRootForPersistence(buy) ?? buy ?? undefined,
sellCondition: normalizeLogicRootForPersistence(sell) ?? sell ?? undefined,
};
if (extractVirtualConditions(next).length > 0) return next;