- {activeTab === TAB_AI ? 'AI 투자 요약' : '쟁승토리 계좌 요약'}
-
- {activeTab === TAB_PORTFOLIO || activeTab === TAB_REPORT ? (
-
-
총 매입{formatNumber(pf.portfolioSummary.total_buy)}
-
총 평가{formatNumber(pf.portfolioSummary.total_eval)}
-
- 총 손익
-
- {formatNumber(pf.portfolioSummary.total_profit)}
- {pf.portfolioSummary.total_profit_rate != null && (
-
- ({formatPercent(pf.portfolioSummary.total_profit_rate)})
-
- )}
-
-
-
보유 종목{pf.portfolioHoldings.length}
- {pf.totalCash != null && (
-
예수금 합계{formatNumber(pf.totalCash)}원
- )}
- {pf.totalAssets != null && (
-
총 자산{formatNumber(pf.totalAssets)}원
- )}
+
쟁승토리 계좌 요약
+
+
총 매입{formatNumber(pf.portfolioSummary.total_buy)}
+
총 평가{formatNumber(pf.portfolioSummary.total_eval)}
+
+ 총 손익
+
+ {formatNumber(pf.portfolioSummary.total_profit)}
+ {pf.portfolioSummary.total_profit_rate != null && (
+
+ ({formatPercent(pf.portfolioSummary.total_profit_rate)})
+
+ )}
+
- ) : (
-
-
총 평가금액{formatNumber(aib.totalEval)}
-
예수금{formatNumber(aib.deposit)}
-
보유 종목{aib.holdings.length}
-
- )}
- {activeTab === TAB_AI && aib.summary.note ? (
-
{aib.summary.note}
- ) : null}
+
보유 종목{pf.portfolioHoldings.length}
+ {pf.totalCash != null && (
+
예수금 합계{formatNumber(pf.totalCash)}원
+ )}
+ {pf.totalAssets != null && (
+
총 자산{formatNumber(pf.totalAssets)}원
+ )}
+
@@ -182,11 +164,9 @@ const StockTrade = () => {
label: tabLabels[i],
content: tabId === TAB_PORTFOLIO
?
- : tabId === TAB_AI
- ?
- : tabId === TAB_REPORT
- ?
,
+ : tabId === TAB_REPORT
+ ?
,
}))}
activeIndex={tabIndex}
onTabChange={handleTabChange}
@@ -196,7 +176,6 @@ const StockTrade = () => {
{[
{ id: TAB_PORTFOLIO, icon: '💼', label: '쟁승토리 계좌', badge: pf.portfolioHoldings.length || null },
- { id: TAB_AI, icon: '🤖', label: 'AI 투자', sub: '모의투자' },
{ id: TAB_REPORT, icon: '📊', label: '리포트', sub: '분석·AI코치' },
{ id: TAB_ADVISOR, icon: '🧠', label: 'AI 어드바이저', sub: 'Gemini Pro', className: 'stock-main-tab--advisor' },
].map(({ id, icon, label, sub, badge, className: cls }) => (
@@ -217,7 +196,6 @@ const StockTrade = () => {
{activeTab === TAB_PORTFOLIO && (
)}
- {activeTab === TAB_AI &&
}
{activeTab === TAB_REPORT &&
}
{activeTab === TAB_ADVISOR &&
}
>
diff --git a/src/pages/stock/components/AiTradeTab.jsx b/src/pages/stock/components/AiTradeTab.jsx
deleted file mode 100644
index 4697468..0000000
--- a/src/pages/stock/components/AiTradeTab.jsx
+++ /dev/null
@@ -1,220 +0,0 @@
-import React from 'react';
-import {
- formatNumber, formatPercent,
- getQty, getBuyPrice, getCurrentPrice, getProfitRate, getProfitLoss,
- toNumeric, profitColorClass,
-} from '../stockUtils';
-
-const AiTradeTab = ({ aib }) => (
- <>
- {aib.balanceError ?
{aib.balanceError}
: null}
-
- {/* AI Balance section */}
-
-
-
-
AI 모의투자
-
보유 현황
-
- AI가 운용 중인 모의투자 계좌의 잔고와 보유 종목을 확인합니다.
-
-
-
- {aib.balanceLoading ? (
- 조회 중
- ) : null}
-
-
-
-
-
- {[
- { label: '총 평가', value: aib.totalEval },
- { label: '예수금', value: aib.deposit },
- ].map((item) => (
-
- {item.label}
- {formatNumber(item.value)}
-
- ))}
-
- {aib.holdings.length ? (
-
- {aib.holdings.map((item, idx) => {
- const profitLoss = getProfitLoss(item);
- const profitLossNumeric = toNumeric(profitLoss);
- const profitClass = profitColorClass(profitLossNumeric);
- const profitRate = getProfitRate(item);
- const profitRateNumeric = toNumeric(profitRate);
- const profitRateClass = profitColorClass(profitRateNumeric);
- return (
-
-
-
- {item.name ?? item.code ?? 'N/A'}
-
-
- {item.code ?? ''}
-
-
-
- 수량
- {formatNumber(getQty(item))}
-
-
- 매입가
- {formatNumber(getBuyPrice(item))}
-
-
- 현재가
- {formatNumber(getCurrentPrice(item))}
-
-
- 평가금액
-
- {getCurrentPrice(item) != null && getQty(item) != null
- ? formatNumber(toNumeric(getCurrentPrice(item)) * toNumeric(getQty(item)))
- : '-'}
-
-
-
- 수익률
-
- {formatPercent(profitRate)}
-
-
-
- 평가손익
-
- {formatNumber(profitLoss)}
-
-
-
- );
- })}
-
- ) : (
-
보유 종목이 없습니다.
- )}
-
-
-
- {/* Manual order section */}
-
-
-
-
수동 주문
-
직접 매수/매도
-
- 종목명 또는 종목코드를 입력하고 매수/매도 주문을 요청합니다.
-
-
-
-
-
-
- {/* KIS modal */}
- {aib.kisModal ? (
-
-
aib.setKisModal('')}
- />
-
-
-
주문 결과
-
-
-
{aib.kisModal}
-
-
- ) : null}
- >
-);
-
-export default AiTradeTab;
diff --git a/src/pages/stock/hooks/useAiBalance.js b/src/pages/stock/hooks/useAiBalance.js
deleted file mode 100644
index d700e1d..0000000
--- a/src/pages/stock/hooks/useAiBalance.js
+++ /dev/null
@@ -1,84 +0,0 @@
-import { useState, useCallback, useMemo } from 'react';
-import { getTradeBalance, createTradeOrder } from '../../../api';
-import { getQty, getBuyPrice, getCurrentPrice, getProfitRate, getProfitLoss } from '../stockUtils';
-
-export default function useAiBalance() {
- const [balance, setBalance] = useState(null);
- const [balanceLoading, setBalanceLoading] = useState(false);
- const [balanceError, setBalanceError] = useState('');
- const [balanceLoaded, setBalanceLoaded] = useState(false);
-
- const [manualForm, setManualForm] = useState({
- code: '',
- qty: 1,
- price: 0,
- type: 'buy',
- });
- const [manualLoading, setManualLoading] = useState(false);
- const [manualError, setManualError] = useState('');
- const [manualResult, setManualResult] = useState(null);
- const [kisModal, setKisModal] = useState('');
-
- const loadBalance = useCallback(async () => {
- setBalanceLoading(true);
- setBalanceError('');
- try {
- const data = await getTradeBalance();
- setBalance(data);
- setBalanceLoaded(true);
- } catch (err) {
- setBalanceError(err?.message ?? String(err));
- } finally {
- setBalanceLoading(false);
- }
- }, []);
-
- const submitManualOrder = async (event) => {
- event.preventDefault();
- setManualLoading(true);
- setManualError('');
- setManualResult(null);
- try {
- const payload = {
- ticker: manualForm.code.trim(),
- action: manualForm.type === 'sell' ? 'SELL' : 'BUY',
- quantity: Number(manualForm.qty),
- price: Number(manualForm.price),
- };
- const result = await createTradeOrder(payload);
- setManualResult(result ?? { ok: true });
- if (result?.kis_result !== undefined) {
- const message =
- typeof result.kis_result === 'string'
- ? result.kis_result
- : JSON.stringify(result.kis_result, null, 2);
- setKisModal(message);
- }
- await loadBalance();
- } catch (err) {
- setManualError(err?.message ?? String(err));
- } finally {
- setManualLoading(false);
- }
- };
-
- /* derived */
- const holdings = useMemo(() => {
- if (!balance) return [];
- if (Array.isArray(balance.holdings)) return balance.holdings;
- if (Array.isArray(balance.positions)) return balance.positions;
- if (Array.isArray(balance.items)) return balance.items;
- return [];
- }, [balance]);
-
- const summary = balance?.summary ?? {};
- const totalEval = summary.total_eval ?? balance?.total_eval ?? balance?.total_value;
- const deposit = summary.deposit ?? balance?.deposit ?? balance?.available_cash;
-
- return {
- balance, balanceLoading, balanceError, balanceLoaded, loadBalance,
- holdings, summary, totalEval, deposit,
- manualForm, setManualForm, manualLoading, manualError, manualResult,
- kisModal, setKisModal, submitManualOrder,
- };
-}
diff --git a/src/pages/stock/stockUtils.js b/src/pages/stock/stockUtils.js
index 15ebba7..8b0533f 100644
--- a/src/pages/stock/stockUtils.js
+++ b/src/pages/stock/stockUtils.js
@@ -128,6 +128,5 @@ export const emptySellForm = () => ({
/* ── TAB IDs ─────────────────────────────────────────────────────── */
export const TAB_PORTFOLIO = 'portfolio';
-export const TAB_AI = 'ai';
export const TAB_REPORT = 'report';
export const TAB_ADVISOR = 'advisor';