전략편집기 메뉴 추가
This commit is contained in:
@@ -0,0 +1,121 @@
|
||||
import React from 'react';
|
||||
import type { LogicNode } from '../../utils/strategyTypes';
|
||||
import { nodeToText, type DefType } from '../../utils/strategyEditorShared';
|
||||
import { getIndicatorPaletteCategory } from './paletteCategories';
|
||||
|
||||
interface Props {
|
||||
buyCondition: LogicNode | null;
|
||||
sellCondition: LogicNode | null;
|
||||
orphanCount: number;
|
||||
def: DefType;
|
||||
}
|
||||
|
||||
function renderCondition(node: LogicNode, def: DefType): React.ReactNode {
|
||||
const full = nodeToText(node, def);
|
||||
const ind = node.condition?.indicatorType ?? '';
|
||||
const tail = ind && full.startsWith(`${ind} -`) ? full.slice(ind.length) : full;
|
||||
const cat = getIndicatorPaletteCategory(ind);
|
||||
|
||||
return (
|
||||
<>
|
||||
<span className="se-formula-punc">(</span>
|
||||
{ind ? (
|
||||
<>
|
||||
<span className={`se-formula-ind se-formula-ind--${cat}`}>{ind}</span>
|
||||
{tail ? <span className="se-formula-detail">{tail}</span> : null}
|
||||
</>
|
||||
) : (
|
||||
<span className="se-formula-detail">{full || '?'}</span>
|
||||
)}
|
||||
<span className="se-formula-punc">)</span>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function renderNode(node: LogicNode, def: DefType): React.ReactNode {
|
||||
if (node.type === 'CONDITION') return renderCondition(node, def);
|
||||
|
||||
if (node.type === 'AND') {
|
||||
const children = node.children ?? [];
|
||||
if (children.length === 0) return <span className="se-formula-empty">(빈 AND)</span>;
|
||||
return (
|
||||
<>
|
||||
<span className="se-formula-punc">(</span>
|
||||
{children.map((child, i) => (
|
||||
<React.Fragment key={child.id}>
|
||||
{i > 0 ? <span className="se-formula-logic se-formula-logic--and"> AND </span> : null}
|
||||
{renderNode(child, def)}
|
||||
</React.Fragment>
|
||||
))}
|
||||
<span className="se-formula-punc">)</span>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
if (node.type === 'OR') {
|
||||
const children = node.children ?? [];
|
||||
if (children.length === 0) return <span className="se-formula-empty">(빈 OR)</span>;
|
||||
return (
|
||||
<>
|
||||
<span className="se-formula-punc">(</span>
|
||||
{children.map((child, i) => (
|
||||
<React.Fragment key={child.id}>
|
||||
{i > 0 ? <span className="se-formula-logic se-formula-logic--or"> OR </span> : null}
|
||||
{renderNode(child, def)}
|
||||
</React.Fragment>
|
||||
))}
|
||||
<span className="se-formula-punc">)</span>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
if (node.type === 'NOT') {
|
||||
const child = node.children?.[0];
|
||||
return child ? (
|
||||
<>
|
||||
<span className="se-formula-logic se-formula-logic--not">NOT </span>
|
||||
{renderNode(child, def)}
|
||||
</>
|
||||
) : (
|
||||
<span className="se-formula-empty">(빈 NOT)</span>
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
export default function LogicExpressionPreview({
|
||||
buyCondition,
|
||||
sellCondition,
|
||||
orphanCount,
|
||||
def,
|
||||
}: Props) {
|
||||
const hasBody = buyCondition || sellCondition;
|
||||
|
||||
return (
|
||||
<div className="se-terminal-text se-terminal-text--rich">
|
||||
{!hasBody && (
|
||||
<span className="se-formula-empty">(연결된 조건을 구성하세요)</span>
|
||||
)}
|
||||
{buyCondition && (
|
||||
<div className="se-formula-line">
|
||||
<span className="se-formula-signal se-formula-signal--buy">[매수]</span>
|
||||
{' '}
|
||||
{renderNode(buyCondition, def)}
|
||||
</div>
|
||||
)}
|
||||
{sellCondition && (
|
||||
<div className="se-formula-line">
|
||||
<span className="se-formula-signal se-formula-signal--sell">[매도]</span>
|
||||
{' '}
|
||||
{renderNode(sellCondition, def)}
|
||||
</div>
|
||||
)}
|
||||
{orphanCount > 0 && (
|
||||
<div className="se-formula-line se-formula-comment">
|
||||
{'// 미연결 요소 '}{orphanCount}{'개 — 전략 코드 미포함'}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user