From e51d7678787bd633872b39d9e3d2861da83d1c59 Mon Sep 17 00:00:00 2001 From: "jihoon87.lee" Date: Thu, 12 Mar 2026 09:26:27 +0900 Subject: [PATCH] =?UTF-8?q?=EC=A0=84=EC=B2=B4=EC=A0=81=EC=9D=B8=20?= =?UTF-8?q?=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .agents/skills/dev-auto-pipeline/SKILL.md | 7 + .agents/skills/dev-refactor-polish/SKILL.md | 77 +- .env.example | 33 + AGENTS.md | 8 + app/(home)/page.tsx | 48 +- app/api/autotrade/_shared.ts | 227 ++ app/api/autotrade/sessions/active/route.ts | 25 + app/api/autotrade/sessions/heartbeat/route.ts | 73 + app/api/autotrade/sessions/start/route.ts | 77 + app/api/autotrade/sessions/stop/route.ts | 78 + app/api/autotrade/signals/generate/route.ts | 440 ++++ app/api/autotrade/strategies/compile/route.ts | 411 ++++ .../autotrade/strategies/validate/route.ts | 43 + app/api/autotrade/worker/tick/route.ts | 39 + app/api/kis/domestic/chart/route.ts | 3 + app/api/kis/domestic/market-hub/route.ts | 72 + app/api/kis/domestic/orderable-cash/route.ts | 124 + app/api/kis/indices/route.ts | 64 + app/globals.css | 10 +- app/layout.tsx | 32 +- .../autotrade-model-catalog-runbook.md | 82 + .../features/autotrade-prompt-flow-guide.md | 144 ++ .../autotrade-usage-security-guide.md | 407 ++++ common-docs/features/autotrade-worker-pm2.md | 269 ++ .../dev-plan-2026-02-26-autotrade-ai-mvp.md | 134 + ...n-2026-02-26-autotrade-cash-balance-fix.md | 50 + ...026-02-26-autotrade-cli-model-selection.md | 58 + ...02-26-autotrade-dashboard-ux-cli-models.md | 71 + ...-plan-2026-02-26-market-indices-display.md | 55 + ...dashboard-market-hub-and-orderbook-rate.md | 81 + ...4-dashboard-modern-brand-layout-refresh.md | 50 + ...05-autotrade-ai-context-layout-boxrange.md | 78 + ...-autotrade-observability-momentum-scalp.md | 87 + ...026-03-05-autotrade-risk-input-simplify.md | 63 + ...03-05-kis-remember-credentials-checkbox.md | 69 + ...3-05-trade-chart-timeframes-and-history.md | 71 + ...-2026-03-06-autotrade-ai-signal-context.md | 71 + ...-06-autotrade-real-execution-budget-tax.md | 126 + components/ui/animated-brand-tone.tsx | 55 +- features/auth/components/session-manager.tsx | 2 + features/autotrade/apis/autotrade.api.ts | 217 ++ .../components/AutotradeControlPanel.tsx | 1343 ++++++++++ .../components/AutotradeWarningBanner.tsx | 37 + .../autotrade/hooks/useAutotradeEngine.ts | 2166 +++++++++++++++++ .../stores/use-autotrade-engine-store.ts | 212 ++ features/autotrade/types/autotrade.types.ts | 482 ++++ features/dashboard/apis/dashboard.api.ts | 29 + .../dashboard/components/ActivitySection.tsx | 22 +- .../components/DashboardContainer.tsx | 210 +- .../dashboard/components/HoldingsList.tsx | 38 +- .../dashboard/components/MarketHubSection.tsx | 348 +++ .../dashboard/components/MarketSummary.tsx | 53 +- .../dashboard/components/StatusHeader.tsx | 269 +- .../components/StockDetailPreview.tsx | 10 +- .../dashboard/hooks/use-dashboard-data.ts | 29 +- features/dashboard/types/dashboard.types.ts | 54 + features/layout/components/Logo.tsx | 4 +- features/layout/components/header.tsx | 12 +- features/layout/components/market-indices.tsx | 74 + features/layout/components/user-menu.tsx | 2 + features/layout/hooks/use-market-indices.ts | 98 + .../layout/stores/market-indices-store.ts | 39 + features/settings/components/KisAuthForm.tsx | 156 +- .../settings/components/KisProfileForm.tsx | 60 +- features/settings/lib/kis-remember-storage.ts | 95 + features/trade/apis/kis-stock.api.ts | 33 + features/trade/components/TradeContainer.tsx | 16 +- .../trade/components/chart/StockLineChart.tsx | 142 +- .../trade/components/chart/chart-utils.ts | 27 +- .../components/chart/stock-line-chart-meta.ts | 29 + .../components/holdings/HoldingsPanel.tsx | 12 +- .../layout/TradeDashboardContent.tsx | 4 + features/trade/components/order/OrderForm.tsx | 162 +- .../orderbook/orderbook-sections.tsx | 10 +- .../components/orderbook/orderbook-utils.ts | 10 + features/trade/types/trade.types.ts | 33 +- lib/autotrade/cli-provider.ts | 649 +++++ lib/autotrade/executable-order-quantity.ts | 56 + lib/autotrade/execution-cost.ts | 94 + lib/autotrade/openai.ts | 293 +++ lib/autotrade/risk.ts | 289 +++ lib/autotrade/strategy.ts | 424 ++++ lib/kis/dashboard.ts | 451 +++- lib/kis/domestic-helpers.ts | 3 + lib/kis/domestic.ts | 65 +- lib/kis/trade.ts | 80 +- package-lock.json | 520 ++++ package.json | 8 + playwright-report/index.html | 85 + scripts/autotrade-dev-smoke.mjs | 153 ++ scripts/autotrade-session-e2e.mjs | 117 + scripts/autotrade-worker.mjs | 96 + scripts/pm2.autotrade-worker.config.cjs | 20 + test-results/.last-run.json | 4 + tests/autotrade/order-guard-cost.test.ts | 68 + tests/autotrade/risk-budget.test.ts | 82 + utils/supabase/middleware.ts | 6 + 97 files changed, 13651 insertions(+), 363 deletions(-) create mode 100644 app/api/autotrade/_shared.ts create mode 100644 app/api/autotrade/sessions/active/route.ts create mode 100644 app/api/autotrade/sessions/heartbeat/route.ts create mode 100644 app/api/autotrade/sessions/start/route.ts create mode 100644 app/api/autotrade/sessions/stop/route.ts create mode 100644 app/api/autotrade/signals/generate/route.ts create mode 100644 app/api/autotrade/strategies/compile/route.ts create mode 100644 app/api/autotrade/strategies/validate/route.ts create mode 100644 app/api/autotrade/worker/tick/route.ts create mode 100644 app/api/kis/domestic/market-hub/route.ts create mode 100644 app/api/kis/domestic/orderable-cash/route.ts create mode 100644 app/api/kis/indices/route.ts create mode 100644 common-docs/features/autotrade-model-catalog-runbook.md create mode 100644 common-docs/features/autotrade-prompt-flow-guide.md create mode 100644 common-docs/features/autotrade-usage-security-guide.md create mode 100644 common-docs/features/autotrade-worker-pm2.md create mode 100644 common-docs/improvement/plans/dev-plan-2026-02-26-autotrade-ai-mvp.md create mode 100644 common-docs/improvement/plans/dev-plan-2026-02-26-autotrade-cash-balance-fix.md create mode 100644 common-docs/improvement/plans/dev-plan-2026-02-26-autotrade-cli-model-selection.md create mode 100644 common-docs/improvement/plans/dev-plan-2026-02-26-autotrade-dashboard-ux-cli-models.md create mode 100644 common-docs/improvement/plans/dev-plan-2026-02-26-market-indices-display.md create mode 100644 common-docs/improvement/plans/dev-plan-2026-03-04-dashboard-market-hub-and-orderbook-rate.md create mode 100644 common-docs/improvement/plans/dev-plan-2026-03-04-dashboard-modern-brand-layout-refresh.md create mode 100644 common-docs/improvement/plans/dev-plan-2026-03-05-autotrade-ai-context-layout-boxrange.md create mode 100644 common-docs/improvement/plans/dev-plan-2026-03-05-autotrade-observability-momentum-scalp.md create mode 100644 common-docs/improvement/plans/dev-plan-2026-03-05-autotrade-risk-input-simplify.md create mode 100644 common-docs/improvement/plans/dev-plan-2026-03-05-kis-remember-credentials-checkbox.md create mode 100644 common-docs/improvement/plans/dev-plan-2026-03-05-trade-chart-timeframes-and-history.md create mode 100644 common-docs/improvement/plans/dev-plan-2026-03-06-autotrade-ai-signal-context.md create mode 100644 common-docs/improvement/plans/dev-plan-2026-03-06-autotrade-real-execution-budget-tax.md create mode 100644 features/autotrade/apis/autotrade.api.ts create mode 100644 features/autotrade/components/AutotradeControlPanel.tsx create mode 100644 features/autotrade/components/AutotradeWarningBanner.tsx create mode 100644 features/autotrade/hooks/useAutotradeEngine.ts create mode 100644 features/autotrade/stores/use-autotrade-engine-store.ts create mode 100644 features/autotrade/types/autotrade.types.ts create mode 100644 features/dashboard/components/MarketHubSection.tsx create mode 100644 features/layout/components/market-indices.tsx create mode 100644 features/layout/hooks/use-market-indices.ts create mode 100644 features/layout/stores/market-indices-store.ts create mode 100644 features/settings/lib/kis-remember-storage.ts create mode 100644 lib/autotrade/cli-provider.ts create mode 100644 lib/autotrade/executable-order-quantity.ts create mode 100644 lib/autotrade/execution-cost.ts create mode 100644 lib/autotrade/openai.ts create mode 100644 lib/autotrade/risk.ts create mode 100644 lib/autotrade/strategy.ts create mode 100644 playwright-report/index.html create mode 100644 scripts/autotrade-dev-smoke.mjs create mode 100644 scripts/autotrade-session-e2e.mjs create mode 100644 scripts/autotrade-worker.mjs create mode 100644 scripts/pm2.autotrade-worker.config.cjs create mode 100644 test-results/.last-run.json create mode 100644 tests/autotrade/order-guard-cost.test.ts create mode 100644 tests/autotrade/risk-budget.test.ts diff --git a/.agents/skills/dev-auto-pipeline/SKILL.md b/.agents/skills/dev-auto-pipeline/SKILL.md index c5342da..2fb6312 100644 --- a/.agents/skills/dev-auto-pipeline/SKILL.md +++ b/.agents/skills/dev-auto-pipeline/SKILL.md @@ -47,6 +47,8 @@ description: 기능 개발/버그 수정/리팩토링 같은 구현 요청에서 [3. 리팩토링/성능/가독성] - ... +- 파일 상단 역할 주석 반영 여부 +- 핵심 입력 데이터 흐름 추적표 포함 여부 [4. 테스트] - ... @@ -54,4 +56,9 @@ description: 기능 개발/버그 수정/리팩토링 같은 구현 요청에서 [5. 계획 대비 완료체크] - 완료/부분 완료/미완료 - 최종 판정: 배포 가능/보완 필요 + +[6. 핵심 입력 흐름 추적표] +- 입력값: (예: 전략 프롬프트) +- UI 입력 -> 핸들러 -> 훅/서비스 -> API -> route -> provider -> 결과 반영 +- 각 단계는 파일/라인 링크 포함 ``` diff --git a/.agents/skills/dev-refactor-polish/SKILL.md b/.agents/skills/dev-refactor-polish/SKILL.md index f21b70d..051b26a 100644 --- a/.agents/skills/dev-refactor-polish/SKILL.md +++ b/.agents/skills/dev-refactor-polish/SKILL.md @@ -96,12 +96,75 @@ description: 구현 완료 직후 가독성·데이터 흐름·성능을 다듬 1. 주석 보강 작업은 코드 로직(타입/런타임/동작/변수명/import)을 바꾸지 않는다. 2. 함수/API/쿼리 주석은 `[목적]`, `[사용처]`, `[데이터 흐름]` 중심으로 쉽게 쓴다. -3. 상태(`useState`, `useRef`, store)는 "화면에 어떤 영향을 주는지" 한 줄 주석을 단다. -4. 복잡한 로직/핸들러는 `1.`, `2.`, `3.` 단계 주석으로 흐름을 나눈다. +3. 상태(`useState`, `useRef`, `useMemo`, store 파생 상태)는 반드시 `[State]`, `[Ref]` 형식으로 역할 주석을 단다. + - 예: `// [State] 자동매매 실행 중 여부 (배너/버튼 상태에 사용)` + - 예: `// [Ref] 마지막 신호 요청 시각 (요청 과다 방지용)` +4. 복잡한 로직/핸들러는 반드시 `[Step 1]`, `[Step 2]`, `[Step 3]` 형식으로 흐름을 나눈다. + - 예: `// [Step 1] 입력값 유효성 검증` 5. 긴 JSX는 화면 구역 주석으로 나눠서 읽기 쉽게 만든다. - - 예: `{/* ===== 1. 상단: 페이지 제목 및 액션 버튼 ===== */}` -6. `@param`, `@see`, `@remarks` 같은 딱딱한 TSDoc 태그는 강제하지 않는다. -7. 결과 기준은 "주니어가 5분 내 파악 가능한지"로 잡는다. + - 예: `{/* ========== 1. 상단: 상태/액션 영역 ========== */}` +6. 데이터 흐름이 중요한 입력(UI prompt, 검색어, 주문 설정값)은 입력 지점에 "어디 API로 가는지"를 한 줄로 명시한다. + - 예: `// [데이터 흐름] textarea -> patchSetupForm -> compile API -> AI provider(OpenAI/CLI)` +7. `@param`, `@see`, `@remarks` 같은 딱딱한 TSDoc 태그는 강제하지 않는다. +8. 결과 기준은 "주니어가 5분 내 파악 가능한지"로 잡는다. + +### 파일 상단 역할 주석 (필수) + +1. 핵심 파일(`components`, `hooks`, `apis`, `lib`, `route.ts`)은 import 위(또는 `"use client"` 바로 아래)에 파일 역할 주석을 단다. +2. 형식은 아래 템플릿을 따른다. + +```ts +/** + * [파일 역할] + * 이 파일이 시스템에서 맡는 역할 + * + * [주요 책임] + * - 책임 1 + * - 책임 2 + * - 책임 3 + */ +``` + +### 흐름 추적 문서화 규칙 (필수) + +1. 사용자가 "이 값이 어디로 가는지"를 물으면 반드시 함수 체인을 파일/라인으로 답한다. +2. 형식은 `UI 입력 -> 핸들러 -> 훅/서비스 -> API 클라이언트 -> route -> provider -> 결과 반영` 순서를 유지한다. +3. 최종 답변에 최소 1개 이상의 "핵심 입력 흐름 추적표"를 포함한다. +4. 라인 표기는 `절대경로:라인` 링크 형식으로 제공한다. + +### 필수 주석 패턴 (컴포넌트/훅) + +1. State/Ref 선언부 + +```ts +// [State] 자동매매 설정 모달 열림 여부 +const [panelOpen, setPanelOpen] = useState(false); + +// [Ref] 최근 가격 캐시 (신호 생성용) +const recentPricesRef = useRef([]); +``` + +2. 핸들러/비즈니스 함수 + +```ts +const handleStart = async () => { + // [Step 1] 필수 입력값 검증 + // [Step 2] 전략 컴파일/검증 API 호출 + // [Step 3] 세션 시작 및 UI 상태 갱신 +}; +``` + +3. JSX 섹션 구분 + +```tsx +return ( + <> + {/* ========== 1. 상단: 상태 및 액션 ========== */} + {/* ========== 2. 본문: 설정 입력 영역 ========== */} + {/* ========== 3. 하단: 검증/시작 버튼 영역 ========== */} + +); +``` ## UI/브랜드/문구 규칙 @@ -134,6 +197,10 @@ description: 구현 완료 직후 가독성·데이터 흐름·성능을 다듬 [데이터 흐름 정리] - 어느 UI -> A 함수 호출 -> B 함수 호출 -> 리턴값 반영 +[핵심 입력 흐름 추적표] +- 입력값: (예: 전략 프롬프트) +- [파일:라인] -> 함수 -> 다음 호출 + [회귀 위험 점검] - ... ``` diff --git a/.env.example b/.env.example index 54fb7c7..aef12c7 100644 --- a/.env.example +++ b/.env.example @@ -7,3 +7,36 @@ NEXT_PUBLIC_SUPABASE_ANON_KEY= # 세션 타임아웃(분 단위) NEXT_PUBLIC_SESSION_TIMEOUT_MINUTES=30 + +# 자동매매/AI 설정 +OPENAI_API_KEY= +AUTOTRADE_AI_MODEL=gpt-4o-mini +# auto | openai_api | subscription_cli | rule_fallback +AUTOTRADE_AI_MODE=auto +# subscription_cli 모드에서 사용할 CLI 선택값(auto | gemini | codex) +AUTOTRADE_SUBSCRIPTION_CLI=auto +# subscription_cli 공통 모델(옵션): vendor 전용 설정이 없을 때 fallback으로 사용 +AUTOTRADE_SUBSCRIPTION_CLI_MODEL= +# Codex CLI 전용 모델(옵션): 예) gpt-5-codex +AUTOTRADE_CODEX_MODEL= +# Gemini CLI 전용 모델(옵션): 예) auto | pro | flash | flash-lite | gemini-2.5-pro +AUTOTRADE_GEMINI_MODEL= +# subscription_cli 호출 타임아웃(ms) +AUTOTRADE_SUBSCRIPTION_CLI_TIMEOUT_MS=60000 +# subscription_cli 디버그 로그(1/true/on): Next 서버 콘솔에 CLI 호출/시도 로그 출력 +AUTOTRADE_SUBSCRIPTION_CLI_DEBUG=0 +# Codex CLI 실행 파일 경로(옵션): PATH 인식 문제 시 절대경로 지정 +AUTOTRADE_CODEX_COMMAND= +# Gemini CLI 실행 파일 경로(옵션): PATH 인식 문제 시 절대경로 지정 +AUTOTRADE_GEMINI_COMMAND= +AUTOTRADE_HEARTBEAT_TTL_SEC=90 +AUTOTRADE_MAX_DAILY_ORDERS_DEFAULT=20 +AUTOTRADE_CONFIDENCE_THRESHOLD_DEFAULT=0.65 +AUTOTRADE_DEV_BYPASS_TOKEN=autotrade-dev-bypass +# 워커 인증 토큰: 직접 랜덤 문자열 생성해서 앱/워커에 동일하게 넣어 주세요. +# 예) openssl rand -hex 32 +AUTOTRADE_WORKER_TOKEN=autotrade-worker-local +# 워커 점검 주기(ms) +AUTOTRADE_WORKER_POLL_MS=5000 +# 워커가 호출할 Next.js 앱 주소 +AUTOTRADE_APP_URL=http://127.0.0.1:3001 diff --git a/AGENTS.md b/AGENTS.md index 1093eee..288b995 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -15,3 +15,11 @@ 4. `dev-test-gate` 5. `dev-plan-completion-checker` - 단순 설명/문서 요약/잡담 요청에는 파이프라인 스킬을 강제하지 않는다. + +## 설명 방식 규칙 + +- 사용자 설명은 어려운 용어보다 쉬운 한국어를 우선 사용한다. +- 기술 용어를 써야 할 때는 바로 아래 줄에 쉬운 말로 다시 풀어쓴다. +- 데이터 흐름 설명은 항상 `입력 -> 처리 -> 결과` 순서의 짧은 단계로 말한다. +- 사용자가 헷갈린 상황에서는 추상 설명보다 "지금 화면에서 확인할 것"을 먼저 안내한다. +- 요청/응답 설명 시에는 핵심 필드 3~5개만 먼저 보여주고, 필요 시 상세를 추가한다. diff --git a/app/(home)/page.tsx b/app/(home)/page.tsx index be6aeee..e54982b 100644 --- a/app/(home)/page.tsx +++ b/app/(home)/page.tsx @@ -21,21 +21,21 @@ interface StartStep { const START_STEPS: StartStep[] = [ { step: "01", - title: "1분이면 충분해요", + title: "앱키 연결, 1분이면 끝", description: - "복잡한 서류나 방문 없이, 쓰던 계좌 그대로 안전하게 연결할 수 있어요.", + "복잡한 절차 없이, 지금 쓰는 계좌로 바로 시작할 수 있어요.", }, { step: "02", - title: "내 스타일대로 골라보세요", + title: "투자금/손실선만 입력하세요", description: - "공격적인 투자부터 안정적인 관리까지, 나에게 딱 맞는 전략이 준비되어 있어요.", + "어렵게 계산할 필요 없이, 내가 감당 가능한 금액만 정하면 돼요.", }, { step: "03", - title: "이제 일상을 즐기세요", + title: "신호 확인 후 자동 실행", description: - "차트는 JOORIN-E가 하루 종일 보고 있을게요. 마음 편히 본업에 집중하세요.", + "차트 감시는 JOORIN-E가 맡고, 당신은 중요한 순간만 확인하면 됩니다.", }, ]; @@ -50,7 +50,7 @@ export default async function HomePage() { } = await supabase.auth.getUser(); const primaryCtaHref = user ? AUTH_ROUTES.DASHBOARD : AUTH_ROUTES.SIGNUP; - const primaryCtaLabel = user ? "시작하기" : "지금 무료로 시작하기"; + const primaryCtaLabel = user ? "내 전략 시작하기" : "무료로 시작하기"; return (
@@ -69,21 +69,21 @@ export default async function HomePage() {
- 자동 매매의 새로운 기준, JOORIN-E + 처음 하는 자동매매도 쉽게, JOORIN-E

- 주식, 이제는 + 복잡한 차트 대신
- 마음 편하게 하세요. + 쉬운 자동매매로 시작하세요.

- 어렵고 불안한 주식 투자, 혼자 고민하지 마세요. + 감으로 사고파는 불안한 투자, 이제 줄여보세요.
- 검증된 원칙으로 24시간 당신의 자산을 지켜드릴게요. + 예산과 손실선을 먼저 지키는 방식으로, 주식을 더 편하게 도와드립니다.

@@ -111,14 +111,14 @@ export default async function HomePage() {

- 설계부터 실행까지 + 주식이 처음이어도
- 단 3단계면 끝. + 3단계면 준비 끝.

- 복잡한 계산과 감시는 JOORIN-E가 대신할게요. + 앱키 연결 -> 투자금/손실선 설정 -> 시작 버튼.
- 당신은 가벼운 마음으로 '시작' 버튼만 누르세요. + 어려운 용어 없이, 필요한 것만 빠르게 설정해보세요.

@@ -166,20 +166,18 @@ export default async function HomePage() {

- 내 계좌 정보, 서버에 저장되지 않나요? + 계좌 키/정보, 어디에 저장되나요?

- 네, 절대 저장하지 않으니 안심하세요. + 핵심 정보는 내 브라우저에만 저장됩니다.
- JOORIN-E는 여러분의 계좌 비밀번호와 API 키를 서버로 전송하지 - 않습니다. + JOORIN-E는 계좌 비밀번호를 저장하지 않으며,
- 모든 중요 정보는 여러분의 기기(브라우저)에만 암호화되어 - 저장되며, + API 키도 장기 보관하지 않도록 최소 범위로만 사용합니다.
- 매매 실행 시에만 증권사와 직접 통신하는 데 사용됩니다. + 매매 요청은 필요한 순간에만 증권사와 통신합니다.

@@ -190,9 +188,9 @@ export default async function HomePage() {

- 더 이상 미루지 마세요. + 감으로 매매하던 습관에서
- 지금 바로 경험해보세요. + 오늘부터 규칙 매매로 바꿔보세요.

+ + {!isRunning ? ( + + ) : ( + + )} +
+
+ + {/* ===== 3. 상태 카드 영역 ===== */} +
+ + + + +
+ + {/* ===== 4. 최근 로그 요약 ===== */} + {(logs.length > 0 || isRunning || isStopping) && ( +
+
+

+ 실시간 자동매매 안내 +

+
+ {isLogPanelOpen && ( + + )} + +
+
+ +
+

+ 입력: + {" "} + {latestPromptText || "아직 AI 요청 전입니다."} + {(isRunning || isStopping || isSignalResponsePending) && ( + + )} +

+ {latestRequestDataText && ( +

+ 요청 데이터: + {" "} + {latestRequestDataText} +

+ )} +

+ 답변: + {" "} + {latestAiReasonText ?? "아직 응답이 없습니다."} + {isSignalResponsePending && ( + + (새 분석 진행 중...) + + )} +

+
+ + {isLogPanelOpen && ( +
    + {logs.slice(0, 10).map((log) => { + const friendly = toFriendlyLog(log); + return ( +
  • +
    + + {new Date(log.createdAt).toLocaleTimeString("ko-KR")} + + + {log.level.toUpperCase()} + + {log.stage && ( + + {resolveLogStageLabel(log.stage)} + + )} +
    + +

    + {friendly.primary} +

    + {friendly.secondary && ( +

    + {friendly.secondary} +

    + )} + + {showTechnicalLog && log.detail && ( +
    +                            {log.detail}
    +                          
    + )} +
  • + ); + })} +
+ )} +
+ )} +
+ + + {/* ===== 5. 설정 모달 ===== */} + {panelOpen && ( +
+
+ + +

+ 자동매매 간편 설정 +

+

+ 처음 쓰셔도 쉽게 맞출 수 있게 핵심만 모았습니다. +

+ +
+ + + +
+ +
+ + + +
+ +
+
+ {/* 좌측: 판단 소스/전략 설정 */} + {setupTab === "ai" && ( + <> + + + +

+ {resolveFriendlyAiModeDescription(setupForm.aiMode)} +

+ + {shouldShowSubscriptionCliConfig && ( +
+

+ 모델 선택 +

+ + + + {setupForm.subscriptionCliVendor === "auto" ? ( +

+ 자동 선택은 Codex를 먼저 시도하고, 안 되면 Gemini를 시도합니다. +

+ ) : ( + <> + + {(selectedCliModelSelectValue === "__custom__" || + normalizedSubscriptionCliModel.length > 0) && ( + + handleSubscriptionCliModelInputChange(event.target.value) + } + placeholder="예) gpt-5.4, gpt-5.3-codex, gpt-5-codex-mini" + /> + )} + + )} +
+ )} + + )} + + {setupTab === "quick" && ( + <> + + + {/* [프롬프트 흐름] 1) textarea 입력 -> handlePromptChange -> patchSetupForm(prompt) */} + {/* [프롬프트 흐름] 2) 시작/검증 클릭 -> startAutotrade or previewValidation -> prepareStrategy */} + {/* [프롬프트 흐름] 3) prepareStrategy -> compileAutotradeStrategy -> /api/autotrade/strategies/compile */} +