ai 전략 기능 추가

This commit is contained in:
Macbook
2026-06-30 21:59:13 +09:00
parent f9447ea52f
commit 25cbadbffb
18 changed files with 2446 additions and 3 deletions
+48 -1
View File
@@ -47,6 +47,7 @@ import {
} from '../utils/strategyStartNodes';
import IndicatorPaletteTab from './strategyEditor/IndicatorPaletteTab';
import TemplatePaletteTab, { type TemplatePaletteRow } from './strategyEditor/TemplatePaletteTab';
import AiStrategyPanel, { type AiStrategyContext } from './strategyEditor/AiStrategyPanel';
import SidewaysFilterPaletteTab from './strategyEditor/SidewaysFilterPaletteTab';
import TrendLinePaletteTab from './strategyEditor/TrendLinePaletteTab';
import { buildTrendLineConditionNode } from '../utils/trendLinePalette';
@@ -320,7 +321,7 @@ export default function StrategyEditorPage({
const [buyCondition, setBuyCondition] = useState<LogicNode | null>(null);
const [sellCondition, setSellCondition] = useState<LogicNode | null>(null);
const [signalTab, setSignalTab] = useState<SignalTab>('buy');
const [rightTab, setRightTab] = useState<'indicators' | 'templates'>('indicators');
const [rightTab, setRightTab] = useState<'indicators' | 'templates' | 'ai'>('indicators');
const [indicatorSubTab, setIndicatorSubTab] = useState<'auxiliary' | 'composite' | 'range' | 'trendline'>('auxiliary');
const [auxiliaryPalette, setAuxiliaryPalette] = useState<PaletteItem[]>(() => loadPaletteItems('auxiliary'));
const [compositePalette, setCompositePalette] = useState<PaletteItem[]>(() => loadPaletteItems('composite'));
@@ -1463,6 +1464,45 @@ export default function StrategyEditorPage({
[templateRows, templateSearch],
);
const buildAiContext = useCallback((): AiStrategyContext => {
const buyEncoded = encodeConditionForSave(buyEditorState);
const sellEncoded = encodeConditionForSave(sellEditorState);
return {
buyCondition: buyEncoded,
sellCondition: sellEncoded,
signalTab: buySellTab(signalTab),
candleType: currentEditorState.startMeta[START_NODE_ID]?.candleType,
};
}, [buyEditorState, sellEditorState, signalTab, currentEditorState]);
const applyAiStrategy = useCallback((buyDsl: LogicNode | null, sellDsl: LogicNode | null) => {
if (editorMode === 'graph') layoutFlushRef.current?.();
const buyDecoded = decodeConditionForEditor(buyDsl);
const sellDecoded = decodeConditionForEditor(sellDsl);
setBuyCondition(buyDecoded.root);
setSellCondition(sellDecoded.root);
setBuyOrphans([]);
setSellOrphans([]);
setSelectedNodeId(null);
setBuyLayout(prev => ({
...prev,
startCombineOp: normalizeStartCombineOp(buyDecoded.startCombineOp),
}));
setSellLayout(prev => ({
...prev,
startCombineOp: normalizeStartCombineOp(sellDecoded.startCombineOp),
}));
resetFlowLayout(layoutStrategyKey, 'buy');
resetFlowLayout(layoutStrategyKey, 'sell');
const targetTab: BuySellTab = buyDsl ? 'buy' : (sellDsl ? 'sell' : buySellTab(signalTab));
if (targetTab !== signalTab) setSignalTab(targetTab);
scheduleStrategyPersist();
}, [editorMode, layoutStrategyKey, resetFlowLayout, signalTab, scheduleStrategyPersist]);
const handleTemplate = useCallback((tmpl: StrategyTemplateDef) => {
if (editorMode === 'graph') layoutFlushRef.current?.();
@@ -2418,6 +2458,7 @@ export default function StrategyEditorPage({
<div className="se-right-tabs">
<button type="button" className={rightTab === 'indicators' ? 'se-right-tab se-right-tab--on' : 'se-right-tab'} onClick={() => setRightTab('indicators')}></button>
<button type="button" className={rightTab === 'templates' ? 'se-right-tab se-right-tab--on' : 'se-right-tab'} onClick={() => setRightTab('templates')}>릿</button>
<button type="button" className={rightTab === 'ai' ? 'se-right-tab se-right-tab--on' : 'se-right-tab'} onClick={() => setRightTab('ai')}>AI </button>
</div>
<div className="se-right-body">
{rightTab === 'indicators' && (
@@ -2593,6 +2634,12 @@ export default function StrategyEditorPage({
onDelete={handleTemplateToolbarDelete}
/>
)}
{rightTab === 'ai' && (
<AiStrategyPanel
getContext={buildAiContext}
onApplyStrategy={applyAiStrategy}
/>
)}
</div>
</div>
</aside>