수정
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
||||
|
||||
export const COMBO_FIELD_CUSTOM = '__field_custom__';
|
||||
|
||||
@@ -117,6 +117,22 @@ export default function ComboFieldSelect({
|
||||
setDraft(String(clamped));
|
||||
}, [draft, allowDecimal, min, max, onCustomNumberChange, customNumber]);
|
||||
|
||||
const commitRef = useRef(commitCustom);
|
||||
commitRef.current = commitCustom;
|
||||
|
||||
// 직접입력 blur 전 탭 전환·저장 시 값 유실 방지
|
||||
useEffect(() => () => { commitRef.current(); }, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (!focused || mode !== 'custom') return;
|
||||
const parsed = parseDraft(draft, allowDecimal);
|
||||
if (parsed == null) return;
|
||||
const clamped = clampValue(parsed, min, max, allowDecimal);
|
||||
if (clamped === customNumber) return;
|
||||
const t = window.setTimeout(() => onCustomNumberChange(clamped), 400);
|
||||
return () => window.clearTimeout(t);
|
||||
}, [draft, focused, mode, allowDecimal, min, max, customNumber, onCustomNumberChange]);
|
||||
|
||||
return (
|
||||
<div className={`se-combo-field${mode === 'custom' ? ' se-combo-field--custom-only' : ''}`}>
|
||||
<select
|
||||
|
||||
@@ -382,7 +382,7 @@ const StrategyEvaluationChart: React.FC<Props> = ({
|
||||
}
|
||||
void runSignalScanForBars(bars);
|
||||
return () => { ++backtestGenRef.current; };
|
||||
}, [strategy?.id, market, timeframe, paramsRevision, bars, loading, runSignalScanForBars]);
|
||||
}, [strategy?.id, strategy?.buyCondition, market, timeframe, paramsRevision, bars, loading, runSignalScanForBars]);
|
||||
|
||||
useEffect(() => {
|
||||
applyMarkers();
|
||||
|
||||
@@ -11,11 +11,11 @@ import {
|
||||
} from './conditionPeriods';
|
||||
import {
|
||||
defaultInheritedThresholdField,
|
||||
inferThresholdSymbolFromLegacy,
|
||||
inferThresholdSymbolFromLegacyExact,
|
||||
isThresholdFieldOrSymbol,
|
||||
isThresholdSymbol,
|
||||
} from './thresholdSymbols';
|
||||
import { parseThresholdField, setDirectThreshold } from './conditionPeriods';
|
||||
import { repairPriceExtremePairForest } from './priceExtremeBreakoutPair';
|
||||
|
||||
function isConditionCarrier(node: LogicNode): node is LogicNode & { condition: ConditionDSL } {
|
||||
@@ -34,8 +34,16 @@ function migrateConditionThreshold(
|
||||
|
||||
let rightField = cond.rightField;
|
||||
if (rightField?.startsWith('K_')) {
|
||||
rightField = inferThresholdSymbolFromLegacyExact(rightField, cond.indicatorType, {})
|
||||
?? inferThresholdSymbolFromLegacy(rightField, cond.indicatorType, {});
|
||||
const exact = inferThresholdSymbolFromLegacyExact(rightField, cond.indicatorType, def.hlThresh);
|
||||
if (exact) {
|
||||
rightField = exact;
|
||||
} else {
|
||||
// K_55 등 비표준값 — 가장 가까운 HL_* 로 접지 않고 숫자 스냅샷 유지
|
||||
const val = parseThresholdField(rightField);
|
||||
if (val != null) {
|
||||
return migrateConditionPeriod(setDirectThreshold(cond, 'right', val));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!rightField || (!isThresholdSymbol(rightField) && !rightField.startsWith('K_'))) {
|
||||
const defaults = getDefaultConditionFields(cond.indicatorType, signalType, def);
|
||||
|
||||
@@ -1135,6 +1135,9 @@ export const CondEditor: React.FC<CondEditorProps> = ({
|
||||
};
|
||||
const getRightValue = () => {
|
||||
const raw = normalized.rightField;
|
||||
if (isThresholdOverridden(normalized) && raw?.startsWith('K_')) {
|
||||
return raw;
|
||||
}
|
||||
const v = isThresholdOverridden(normalized)
|
||||
? resolveFieldOptionValue(normalized.indicatorType, raw)
|
||||
: (isThresholdFieldOrSymbol(raw)
|
||||
|
||||
Reference in New Issue
Block a user