전략편집기 기준값 보조지표 설정값 동기화
This commit is contained in:
@@ -34,6 +34,7 @@ import {
|
||||
updateStartCandleTypes,
|
||||
type EditorConditionState,
|
||||
} from '../utils/strategyConditionSerde';
|
||||
import { migrateLogicRootForEditor } from '../utils/strategyConditionNormalize';
|
||||
import { persistStrategyEvaluationTimeframes } from '../utils/strategyTimeframeSync';
|
||||
import {
|
||||
START_NODE_ID,
|
||||
@@ -141,7 +142,7 @@ export default function StrategyEditorPage({ theme }: Props) {
|
||||
() => buildStrategyEditorDefFromSettings(getParams, getVisualConfig),
|
||||
[getParams, getVisualConfig, settingsRevision],
|
||||
);
|
||||
const settingsSyncRef = useRef(0);
|
||||
const settingsSyncRef = useRef(-1);
|
||||
|
||||
const [strategies, setStrategies] = useState<StrategyDto[]>(() => loadStratsLocal());
|
||||
const [selectedId, setSelectedId] = useState<number | null>(null);
|
||||
@@ -289,6 +290,7 @@ export default function StrategyEditorPage({ theme }: Props) {
|
||||
|
||||
/** 보조지표 설정 변경 시 오버라이드되지 않은 조건 노드·캔버스 기준값 동기화 */
|
||||
useEffect(() => {
|
||||
if (!settingsLoaded) return;
|
||||
if (settingsRevision <= settingsSyncRef.current) return;
|
||||
settingsSyncRef.current = settingsRevision;
|
||||
|
||||
@@ -316,7 +318,7 @@ export default function StrategyEditorPage({ theme }: Props) {
|
||||
extraRoots: syncExtraRoots(prev.extraRoots ?? {}, 'sell'),
|
||||
}));
|
||||
bumpLayoutSeed(layoutStrategyKey, signalTab);
|
||||
}, [settingsRevision, DEF, layoutStrategyKey, signalTab, bumpLayoutSeed]);
|
||||
}, [settingsLoaded, settingsRevision, DEF, layoutStrategyKey, signalTab, bumpLayoutSeed]);
|
||||
|
||||
const resetFlowLayout = useCallback((strategyKey: string, tab: 'buy' | 'sell' = 'buy') => {
|
||||
const emptyBuy = emptySignalFlowLayout();
|
||||
@@ -553,15 +555,18 @@ export default function StrategyEditorPage({ theme }: Props) {
|
||||
const sellDecoded = decodeConditionForEditor(s.sellCondition ?? null);
|
||||
const stored = loadStrategyFlowLayout(String(s.id));
|
||||
|
||||
const buyMigrated = migrateLogicRootForEditor(buyDecoded.root, stored?.buy.orphans ?? [], DEF, 'buy');
|
||||
const sellMigrated = migrateLogicRootForEditor(sellDecoded.root, stored?.sell.orphans ?? [], DEF, 'sell');
|
||||
|
||||
const buySynced = syncLogicRootWithGlobalDef(
|
||||
buyDecoded.root,
|
||||
stored?.buy.orphans ?? [],
|
||||
buyMigrated.root,
|
||||
buyMigrated.orphans,
|
||||
DEF,
|
||||
'buy',
|
||||
);
|
||||
const sellSynced = syncLogicRootWithGlobalDef(
|
||||
sellDecoded.root,
|
||||
stored?.sell.orphans ?? [],
|
||||
sellMigrated.root,
|
||||
sellMigrated.orphans,
|
||||
DEF,
|
||||
'sell',
|
||||
);
|
||||
|
||||
@@ -511,7 +511,7 @@ const IndDropdown: React.FC<IndDropdownProps> = ({
|
||||
onHeaderPointerDown, headerTouchStyle,
|
||||
panelStyle,
|
||||
headerCursor,
|
||||
} = useDraggablePanel({ centerOnMount: true, initialPosition: { x: 0, y: 56 } });
|
||||
} = useDraggablePanel({ centerOnMount: true });
|
||||
|
||||
return (
|
||||
// 배경 클릭 시 닫힘
|
||||
|
||||
@@ -6,6 +6,8 @@ import {
|
||||
getCompositeRightCandleType,
|
||||
getConditionRightPeriod,
|
||||
getConditionThreshold,
|
||||
getChartReferenceThreshold,
|
||||
isThresholdOverridden,
|
||||
getConditionValuePeriod,
|
||||
getCompositePeriodPresetOptions,
|
||||
getPeriodPresetOptions,
|
||||
@@ -52,8 +54,9 @@ export default function ConditionNodeSettings({
|
||||
}, [onClose]);
|
||||
|
||||
const inheritedThreshold = getDefaultConditionFields(condition.indicatorType, signalType, def).r;
|
||||
const rightThreshold = getConditionThreshold(condition, 'right', inheritedThreshold);
|
||||
const showThreshold = hasEditableThreshold(condition) && rightThreshold != null;
|
||||
const chartRef = getChartReferenceThreshold(condition, 'right', inheritedThreshold, def);
|
||||
const strategyThreshold = getConditionThreshold(condition, 'right', inheritedThreshold, def);
|
||||
const showThreshold = hasEditableThreshold(condition) && chartRef != null;
|
||||
const periodPresets = getPeriodPresetOptions(condition.indicatorType, def);
|
||||
const thresholdPresets = getThresholdPresetOptions(condition.indicatorType);
|
||||
const thresholdBounds = getThresholdBounds(condition.indicatorType);
|
||||
@@ -139,18 +142,24 @@ export default function ConditionNodeSettings({
|
||||
/>
|
||||
</label>
|
||||
) : null}
|
||||
{showThreshold && rightThreshold != null && (
|
||||
<label className="se-flow-settings-field">
|
||||
<span>임계값</span>
|
||||
<ComboNumberInput
|
||||
value={rightThreshold}
|
||||
options={thresholdPresets}
|
||||
min={thresholdBounds.min}
|
||||
max={thresholdBounds.max}
|
||||
allowDecimal
|
||||
onChange={v => onChange(setConditionThreshold(condition, 'right', v))}
|
||||
/>
|
||||
</label>
|
||||
{showThreshold && chartRef != null && (
|
||||
<>
|
||||
<label className="se-flow-settings-field se-flow-settings-field--readonly">
|
||||
<span>차트 기준값 (보조지표 설정)</span>
|
||||
<output className="se-flow-settings-readout">{chartRef}</output>
|
||||
</label>
|
||||
<label className="se-flow-settings-field">
|
||||
<span>전략 조건값{isThresholdOverridden(condition) ? ' (전용)' : ''}</span>
|
||||
<ComboNumberInput
|
||||
value={strategyThreshold ?? chartRef}
|
||||
options={thresholdPresets}
|
||||
min={thresholdBounds.min}
|
||||
max={thresholdBounds.max}
|
||||
allowDecimal
|
||||
onChange={v => onChange(setConditionThreshold(condition, 'right', v, def))}
|
||||
/>
|
||||
</label>
|
||||
</>
|
||||
)}
|
||||
{condition.composite && (
|
||||
<p className="se-flow-settings-hint">{compositeDisplayName(condition.indicatorType)}</p>
|
||||
|
||||
Reference in New Issue
Block a user