315 lines
9.0 KiB
TypeScript
315 lines
9.0 KiB
TypeScript
import type React from 'react';
|
|
import type { WidgetCategory } from '../types/widgetDashboard';
|
|
import CandleChartWidgetHost from './hosts/CandleChartWidgetHost';
|
|
import StrategyChartWidgetHost from './hosts/StrategyChartWidgetHost';
|
|
import MiniChartWidgetHost from './hosts/MiniChartWidgetHost';
|
|
import MarketListWidgetHost from './hosts/MarketListWidgetHost';
|
|
import MarketMoversWidgetHost from './hosts/MarketMoversWidgetHost';
|
|
import TickerTapeWidgetHost from './hosts/TickerTapeWidgetHost';
|
|
import QuoteWidgetHost from './hosts/QuoteWidgetHost';
|
|
import WatchlistWidgetHost from './hosts/WatchlistWidgetHost';
|
|
import MarketHeatmapWidgetHost from './hosts/MarketHeatmapWidgetHost';
|
|
import MarketSummaryWidgetHost from './hosts/MarketSummaryWidgetHost';
|
|
import BuySellWidgetHost from './hosts/BuySellWidgetHost';
|
|
import OrderbookWidgetHost from './hosts/OrderbookWidgetHost';
|
|
import DepthChartWidgetHost from './hosts/DepthChartWidgetHost';
|
|
import TimeSalesWidgetHost from './hosts/TimeSalesWidgetHost';
|
|
import TradeHistoryWidgetHost from './hosts/TradeHistoryWidgetHost';
|
|
import PendingOrdersWidgetHost from './hosts/PendingOrdersWidgetHost';
|
|
import PositionsWidgetHost from './hosts/PositionsWidgetHost';
|
|
import AccountBalanceWidgetHost from './hosts/AccountBalanceWidgetHost';
|
|
import NotificationListWidgetHost from './hosts/NotificationListWidgetHost';
|
|
import StrategyListWidgetHost from './hosts/StrategyListWidgetHost';
|
|
import BacktestListWidgetHost from './hosts/BacktestListWidgetHost';
|
|
import PaperKpiWidgetHost from './hosts/PaperKpiWidgetHost';
|
|
import SignalSummaryWidgetHost from './hosts/SignalSummaryWidgetHost';
|
|
import SignalMatchWidgetHost from './hosts/SignalMatchWidgetHost';
|
|
import StrategyConditionWidgetHost from './hosts/StrategyConditionWidgetHost';
|
|
import BacktestSignalsWidgetHost from './hosts/BacktestSignalsWidgetHost';
|
|
import IndicatorStatusWidgetHost from './hosts/IndicatorStatusWidgetHost';
|
|
|
|
export type WidgetGroupId =
|
|
| 'chart'
|
|
| 'market'
|
|
| 'trade'
|
|
| 'portfolio'
|
|
| 'strategy'
|
|
| 'analysis'
|
|
| 'alert';
|
|
|
|
export interface WidgetDefinition {
|
|
type: string;
|
|
label: string;
|
|
description: string;
|
|
category: WidgetCategory;
|
|
group: WidgetGroupId;
|
|
defaultConfig?: Record<string, unknown>;
|
|
Host: React.FC<{ config?: Record<string, unknown> }>;
|
|
}
|
|
|
|
export const WIDGET_GROUP_LABELS: Record<WidgetGroupId, string> = {
|
|
chart: '차트',
|
|
market: '시세·종목',
|
|
trade: '매매·호가',
|
|
portfolio: '계좌·포트폴리오',
|
|
strategy: '전략·분석',
|
|
analysis: '매매 시그널',
|
|
alert: '알림',
|
|
};
|
|
|
|
export const WIDGET_REGISTRY: WidgetDefinition[] = [
|
|
{
|
|
type: 'chart.candle',
|
|
label: '캔들 차트',
|
|
description: '종목 검색 + 좌·우 툴바 실시간 캔들',
|
|
category: 'center',
|
|
group: 'chart',
|
|
Host: CandleChartWidgetHost,
|
|
},
|
|
{
|
|
type: 'chart.strategy',
|
|
label: '전략 분석 차트',
|
|
description: '선택 전략 백테스트 시그널 차트',
|
|
category: 'center',
|
|
group: 'chart',
|
|
Host: StrategyChartWidgetHost,
|
|
},
|
|
{
|
|
type: 'chart.mini',
|
|
label: '미니 차트',
|
|
description: '선택 종목 소형 캔들 차트',
|
|
category: 'center',
|
|
group: 'chart',
|
|
Host: MiniChartWidgetHost,
|
|
},
|
|
{
|
|
type: 'market.list',
|
|
label: '종목 목록',
|
|
description: 'KRW·BTC·보유·관심 종목',
|
|
category: 'side',
|
|
group: 'market',
|
|
Host: MarketListWidgetHost,
|
|
},
|
|
{
|
|
type: 'market.watchlist',
|
|
label: '관심종목',
|
|
description: '즐겨찾기 종목 컴팩트 목록',
|
|
category: 'side',
|
|
group: 'market',
|
|
Host: WatchlistWidgetHost,
|
|
},
|
|
{
|
|
type: 'market.movers',
|
|
label: '급등·급락',
|
|
description: '상승·하락·거래대금 TOP 종목',
|
|
category: 'side',
|
|
group: 'market',
|
|
Host: MarketMoversWidgetHost,
|
|
},
|
|
{
|
|
type: 'market.tickerTape',
|
|
label: '티커 테이프',
|
|
description: '주요 종목 시세 흐름 스크롤',
|
|
category: 'side',
|
|
group: 'market',
|
|
Host: TickerTapeWidgetHost,
|
|
},
|
|
{
|
|
type: 'market.quote',
|
|
label: '종목 시세',
|
|
description: '선택 종목 상세 시세·OHLC',
|
|
category: 'side',
|
|
group: 'market',
|
|
Host: QuoteWidgetHost,
|
|
},
|
|
{
|
|
type: 'market.heatmap',
|
|
label: '히트맵',
|
|
description: '등락률 색상 그리드',
|
|
category: 'side',
|
|
group: 'market',
|
|
Host: MarketHeatmapWidgetHost,
|
|
},
|
|
{
|
|
type: 'market.summary',
|
|
label: '시장 요약',
|
|
description: '상승/하락 종목 수·주요 지수',
|
|
category: 'side',
|
|
group: 'market',
|
|
Host: MarketSummaryWidgetHost,
|
|
},
|
|
{
|
|
type: 'trade.buySell',
|
|
label: '매수·매도',
|
|
description: '모의 매매 주문 패널',
|
|
category: 'side',
|
|
group: 'trade',
|
|
Host: BuySellWidgetHost,
|
|
},
|
|
{
|
|
type: 'trade.orderbook',
|
|
label: '호가',
|
|
description: '실시간 호가·체결',
|
|
category: 'side',
|
|
group: 'trade',
|
|
Host: OrderbookWidgetHost,
|
|
},
|
|
{
|
|
type: 'trade.depth',
|
|
label: '호가 깊이',
|
|
description: '매수·매도 호가 깊이 차트',
|
|
category: 'side',
|
|
group: 'trade',
|
|
Host: DepthChartWidgetHost,
|
|
},
|
|
{
|
|
type: 'trade.timeSales',
|
|
label: '체결',
|
|
description: '실시간 체결(Time & Sales)',
|
|
category: 'side',
|
|
group: 'trade',
|
|
Host: TimeSalesWidgetHost,
|
|
},
|
|
{
|
|
type: 'trade.history',
|
|
label: '거래 내역',
|
|
description: '모의·가상 체결 이력',
|
|
category: 'side',
|
|
group: 'trade',
|
|
Host: TradeHistoryWidgetHost,
|
|
},
|
|
{
|
|
type: 'trade.pendingOrders',
|
|
label: '미체결 주문',
|
|
description: '대기 중인 모의 주문',
|
|
category: 'side',
|
|
group: 'trade',
|
|
Host: PendingOrdersWidgetHost,
|
|
},
|
|
{
|
|
type: 'paper.kpi',
|
|
label: '투자 KPI',
|
|
description: '총자산·수익률·예수금',
|
|
category: 'side',
|
|
group: 'portfolio',
|
|
Host: PaperKpiWidgetHost,
|
|
},
|
|
{
|
|
type: 'paper.balance',
|
|
label: '계좌 잔고',
|
|
description: '예수금·평가·손익 상세',
|
|
category: 'side',
|
|
group: 'portfolio',
|
|
Host: AccountBalanceWidgetHost,
|
|
},
|
|
{
|
|
type: 'paper.positions',
|
|
label: '보유 종목',
|
|
description: '포지션·평가손익',
|
|
category: 'side',
|
|
group: 'portfolio',
|
|
Host: PositionsWidgetHost,
|
|
},
|
|
{
|
|
type: 'notification.list',
|
|
label: '알림 목록',
|
|
description: '매매 시그널 알림',
|
|
category: 'side',
|
|
group: 'alert',
|
|
Host: NotificationListWidgetHost,
|
|
},
|
|
{
|
|
type: 'strategy.list',
|
|
label: '전략 목록',
|
|
description: '등록된 투자 전략',
|
|
category: 'side',
|
|
group: 'strategy',
|
|
Host: StrategyListWidgetHost,
|
|
},
|
|
{
|
|
type: 'backtest.list',
|
|
label: '백테스트 목록',
|
|
description: '백테스팅·실시간 매매 실행',
|
|
category: 'side',
|
|
group: 'strategy',
|
|
Host: BacktestListWidgetHost,
|
|
},
|
|
{
|
|
type: 'analysis.signalSummary',
|
|
label: '매매 시그널 요약',
|
|
description: '선택 종목·전략 실시간 신호 카드',
|
|
category: 'side',
|
|
group: 'analysis',
|
|
Host: SignalSummaryWidgetHost,
|
|
},
|
|
{
|
|
type: 'analysis.signalMatch',
|
|
label: '조건 일치율',
|
|
description: '매수·매도 조건별 지표 충족률',
|
|
category: 'side',
|
|
group: 'analysis',
|
|
Host: SignalMatchWidgetHost,
|
|
},
|
|
{
|
|
type: 'analysis.strategyCondition',
|
|
label: '전략 조건',
|
|
description: '매수·매도 DSL 조건 트리',
|
|
category: 'side',
|
|
group: 'analysis',
|
|
Host: StrategyConditionWidgetHost,
|
|
},
|
|
{
|
|
type: 'analysis.backtestSignals',
|
|
label: '백테스트 시그널',
|
|
description: '최근 캔들 구간 매매 시그널 목록',
|
|
category: 'side',
|
|
group: 'analysis',
|
|
Host: BacktestSignalsWidgetHost,
|
|
},
|
|
{
|
|
type: 'analysis.indicatorDetail',
|
|
label: '지표별 상태',
|
|
description: '조건별 현재값·충족 여부 상세',
|
|
category: 'side',
|
|
group: 'analysis',
|
|
Host: IndicatorStatusWidgetHost,
|
|
},
|
|
];
|
|
|
|
const byType = new Map(WIDGET_REGISTRY.map(w => [w.type, w]));
|
|
|
|
export function getWidgetDefinition(type: string | null | undefined): WidgetDefinition | undefined {
|
|
if (!type) return undefined;
|
|
return byType.get(type);
|
|
}
|
|
|
|
export function widgetsForCategory(category: WidgetCategory): WidgetDefinition[] {
|
|
return WIDGET_REGISTRY.filter(w => w.category === category);
|
|
}
|
|
|
|
export function widgetsByGroup(category: WidgetCategory): { group: WidgetGroupId; label: string; items: WidgetDefinition[] }[] {
|
|
const items = widgetsForCategory(category);
|
|
const order: WidgetGroupId[] = category === 'center'
|
|
? ['chart']
|
|
: ['market', 'trade', 'portfolio', 'strategy', 'analysis', 'alert'];
|
|
return order
|
|
.map(group => ({
|
|
group,
|
|
label: WIDGET_GROUP_LABELS[group],
|
|
items: items.filter(w => w.group === group),
|
|
}))
|
|
.filter(g => g.items.length > 0);
|
|
}
|
|
|
|
/** 플로팅 위젯 — 메인·패널 위젯 전체 */
|
|
export function widgetsByGroupAll(): { group: WidgetGroupId; label: string; items: WidgetDefinition[] }[] {
|
|
return [
|
|
...widgetsByGroup('center'),
|
|
...widgetsByGroup('side'),
|
|
];
|
|
}
|
|
|
|
export function widgetLabel(type: string | null | undefined): string {
|
|
return getWidgetDefinition(type)?.label ?? '위젯 선택';
|
|
}
|