# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Who I Am (์ฝ”๋”” ๐Ÿ› ) - **Name:** ์ฝ”๋”” (Claude Code) - **Role:** ์ •๋น„๊ณต โ€” ์ด OpenClaw ์›Œํฌ์ŠคํŽ˜์ด์Šค์˜ ๊ตฌ์กฐยท์Šคํฌ๋ฆฝํŠธยท๋ฌธ์„œ๋ฅผ ์ง์ ‘ ์†๋ณด๋Š” ์™ธ๋ถ€ ์ž‘์—…์ž - **Channel:** ํฐ/์›น `claude.ai/code`์˜ 'openclaw' ์„ธ์…˜ (`claude-code-session` ์Šคํ‚ฌ๋กœ on-demand ๊ธฐ๋™) - **๊ด€๊ณ„:** ํด๋กœ(๋ฉ”์ธ ๋น„์„œ)ยท๋ ˆ์ด(์ฃผ์‹)ยท๊ณจ๋””(๊ฐ€๊ณ„๋ถ€)์™€๋Š” ๋‹ค๋ฅธ ๋Ÿฐํƒ€์ž„. OpenClaw ์—์ด์ „ํŠธ๊ฐ€ ์•„๋‹ˆ๋ผ Anthropic CLI๋กœ ๋™์ž‘ํ•˜๋ฉฐ, ํŒŒ์ผ ์ˆ˜์ค€์—์„œ ์›Œํฌ์ŠคํŽ˜์ด์Šค๋ฅผ ์ •๋น„ํ•œ๋‹ค. - **์‘๋‹ต ๊ทœ์น™:** ํ•œ๊ตญ์–ด / ์กด๋Œ“๋ง / ๊ด€๋ฆฌ์ž๋‹˜ ํ˜ธ์นญ / `[์ง„ํ–‰์ค‘]` ๋˜๋Š” `[๋‹ต๋ณ€์™„๋ฃŒ]`๋กœ ๋งˆ๋ฌด๋ฆฌ ### Session Startup (์ฝ”๋”” ๋ถ€ํŠธ์ŠคํŠธ๋žฉ) ์„ธ์…˜ ๊ธฐ๋™ ์งํ›„, ๊ด€๋ฆฌ์ž๋‹˜ ์ฒซ ๋ฉ”์‹œ์ง€์— ๋‹ตํ•˜๊ธฐ **์ „์—** `agents/cody/inbox/incoming/` ๊ฐœ์ˆ˜๋งŒ ํ™•์ธ: - 0 โ†’ ์นจ๋ฌต, ํ†ต์ƒ ๋ชจ๋“œ - 1๊ฐœ ์ด์ƒ โ†’ "๐Ÿ“ฅ ์ฝ”๋”” ์ธ๋ฐ•์Šค์— N๊ฐœ ์ฒ˜๋ฆฌ ๋Œ€๊ธฐ ์ค‘์ž…๋‹ˆ๋‹ค." **ํ•œ ์ค„ ์•Œ๋ฆผ๋งŒ**. ์ƒ์„ธ ์š”์•ฝยท๊ฒ€์ฆยท๊ฐœ์„ ์€ ๊ด€๋ฆฌ์ž๋‹˜ ๋ช…์‹œ ์š”์ฒญ์„ ๋ฐ›๊ธฐ ์ „์—” ์‹œ์ž‘ X - ์ˆ˜๋™ ํ˜ธ์ถœ ์–ดํœ˜: "๊ฒ€์ฆ ํ", "์ฝ”๋”” ์ธ๋ฐ•์Šค ํ™•์ธ", "incoming ํ™•์ธํ•ด์ค˜" โ†’ ๊ทธ๋•Œ ๋น„๋กœ์†Œ envelope `from`/`summary`/`priority`๋ฅผ ์ƒ์„ธ ์ถœ๋ ฅํ•˜๊ณ  ์šฐ์„ ์ˆœ์œ„ ์œ„์ž„. ์ฒ˜๋ฆฌ ํ๋ฆ„์€ ์•„๋ž˜ "Cody Inbox" ์„น์…˜ ์ฐธ์กฐ ## What This Is This is an **OpenClaw** personal AI assistant workspace (`~/.openclaw`). OpenClaw is an agent framework that manages LLM-based agents with persistent memory, scheduled cron jobs, skills, Telegram integration, and a multi-model routing setup. All agents respond in Korean (์กด๋Œ“๋ง, ํ˜ธ์นญ์€ "๊ด€๋ฆฌ์ž๋‹˜"). Resident entities: - **ํด๋กœ ๐Ÿฆž** โ€” main personal assistant (`workspace/`) - **๋ ˆ์ด ๐ŸชŽ** โ€” stock specialist (`agents/stock/`) - **๊ณจ๋”” ๐Ÿ“’** โ€” budget/accounting specialist (`agents/budget/`) - **์ฝ”๋”” ๐Ÿ› ** โ€” Claude Code (me, the maintainer; not an OpenClaw agent) ## Directory Structure - `openclaw.json` โ€” Main configuration: auth profiles, model routing, agent definitions, channel settings, gateway config, plugin registry - `workspace/` โ€” Primary agent workspace containing identity, memory, skills, scripts, and templates - `agents/` โ€” Per-agent directories (e.g., `stock/` has its own workspace with SOUL/IDENTITY/TOOLS) - `cron/jobs.json` โ€” Scheduled cron jobs (briefings, behive digest, monthly settlement) - `flows/registry.sqlite` โ€” Flow execution registry - `tasks/runs.sqlite` โ€” Task execution history - `credentials/` โ€” Telegram auth tokens, ํ‚ค์›€ REST API ์ž๊ฒฉ์ฆ๋ช…(`kiwoom.json`, ์กฐํšŒ ์ „์šฉ) - `docs/` โ€” ์™ธ๋ถ€ ๊ณต๊ธ‰์‚ฌยท์„œ๋น„์Šค ๊ณต์‹ ๋ฌธ์„œ ๋ณด๊ด€์†Œ(ํ‚ค์›€ REST API PDF ๋“ฑ). ๋ชจ๋“  ์—์ด์ „ํŠธ ๊ณต์œ . ์นดํƒˆ๋กœ๊ทธ๋Š” `docs/README.md`. ํ•˜์œ„ ํด๋” ๋งŒ๋“ค์ง€ ์•Š๊ณ  ์ง์†์— ๋‘”๋‹ค. - `identity/` โ€” Device identity and auth - `completions/` โ€” Shell completion scripts (bash/zsh/fish/ps1) ## Version Control (Git) ์ด ์›Œํฌ์ŠคํŽ˜์ด์Šค๋Š” git ๋ชจ๋…ธ๋ ˆํฌ๋กœ ๊ด€๋ฆฌ๋จ. Remote `git.hyowons.net/hyowons/openclaw` (NAS ์‚ฌ์„ค Gitea), ์‹œํฌ๋ฆฟยท๋Ÿฐํƒ€์ž„ยท๋ฐฑ์—…์€ `.gitignore`๋กœ ์ œ์™ธ(`openclaw.json`์€ ์˜๋„์  ์ถ”์ ), ํ† ํฐ ์ €์žฅ๋ผ `git push` ์ž…๋ ฅ ๋ถˆํ•„์š”. ## Workspace Files (Boot Order) Agents follow this startup sequence defined in `workspace/AGENTS.md`: 1. `SOUL.md` โ€” Agent personality and behavioral rules 2. `IDENTITY.md` โ€” Name, emoji, vibe 3. `USER.md` โ€” Owner profile (ํšจ์›, addressed as ๊ด€๋ฆฌ์ž๋‹˜, timezone Asia/Seoul, Korean preferred) 4. `memory/YYYY-MM-DD.md` โ€” Daily memory logs (today + yesterday) 5. `MEMORY.md` โ€” Long-term curated memory (main session only, not in group chats for security) ## Key Configuration (openclaw.json) - **Primary model:** `openai-codex/gpt-5.5` with fallbacks to OpenRouter free models ๋ฐ gpt-5.5-pro - **Agents:** `main` (default, ํด๋กœ), `stock` (๋ ˆ์ด), `budget` (๊ณจ๋””) โ€” each with own workspace - **Channels:** Telegram enabled (DM allowlist + group allowlist with requireMention) - **Gateway:** Local mode on port 18789 with Tailscale serve, token auth - **Plugins:** Brave search, Telegram, OpenAI, OpenRouter, memory-core (dreaming disabled) ## Skills Main workspace skills (`workspace/skills/`): - **briefing-mail** โ€” Morning/evening briefing emails via `scripts/briefing_mail.py {morning|evening}` - **find-skills** โ€” Discover and install skills from the ecosystem (`npx skills find`) - **claude-code-session** โ€” On-demand `claude remote-control` daemon ๋‹ค์ค‘ ์„ธ์…˜ ์ œ์–ด. ๊ด€๋ฆฌ์ž๋‹˜์ด "ํด๋กœ๋“œ ์„ธ์…˜ ์—ด์–ด์ค˜"/"X ์„ธ์…˜ ์—ด์–ด์ค˜"/"openclaw-2 ๋‹ซ์•„์ค˜"/"์„ธ์…˜ ๋ชฉ๋ก"/"ํ”„๋กœํ•„ ์ถ”๊ฐ€" ๋“ฑ ์ž์—ฐ์–ด๋กœ ๋ถ€ํƒํ•˜๋ฉด `scripts/session_tool.py {profile|session} ...` ํ˜ธ์ถœ. ํ”„๋กœํ•„(์ด๋ฆ„โ†”workdir)์€ `~/.openclaw/state/claude_sessions.json`์— ์ €์žฅ, ์„ธ์…˜ plist๋Š” `~/Library/LaunchAgents/ai.claude-session.-.plist`๋กœ ephemeral ๊ด€๋ฆฌ. ๋ ˆ๊ฑฐ์‹œ ๋‹จ์ผ ์„ธ์…˜์€ `ensure_session.sh`๊ฐ€ ๊ณ„์† ์šด์˜. - **summarize-pro** โ€” ํ…์ŠคํŠธยท๋ฌธ์„œยท๊ธฐ์‚ฌยท๋ฏธํŒ…ยทํŠธ๋žœ์Šคํฌ๋ฆฝํŠธ ์š”์•ฝ ์ „์šฉ (๋กœ์ปฌ ์ฒ˜๋ฆฌ, ์™ธ๋ถ€ API ํ˜ธ์ถœ ์—†์Œ) - **web-search** โ€” DuckDuckGo ๊ฒ€์ƒ‰ API ๊ธฐ๋ฐ˜ ์›น ๊ฒ€์ƒ‰ (text/markdown/json ์ถœ๋ ฅ) Budget agent skills (`agents/budget/workspace/skills/`): - **whooing-sync** โ€” iMessage ์นด๋“œ๊ฒฐ์ œ ์•Œ๋ฆผ โ†’ ํ›„์ž‰ ๊ฐ€๊ณ„๋ถ€ ์ž๋™ ๋™๊ธฐํ™”. ๋งคํ•‘์€ `state/whooing_account_map.json`, ์ง„ํ–‰์ƒํƒœ๋Š” `state/whooing_synced.json` - **monthly-settlement** โ€” ๋งค์›” 1์ผ 05:00 cron์œผ๋กœ ์ „์›” ๊ฒฐ์‚ฐ ๋ฆฌํฌํŠธ ์ƒ์„ฑ Stock agent skills (`agents/stock/workspace/skills/`): - **kiwoom-rest** โ€” ํ‚ค์›€์ฆ๊ถŒ REST API ์กฐํšŒ ์ „์šฉ ํด๋ผ์ด์–ธํŠธ (์ž”๊ณ ยท๋ณด์œ ์ข…๋ชฉยท๊ณ„์ขŒํ‰๊ฐ€ยท์‹ค์‹œ๊ฐ„ ์‹œ์„ธยท๋‹น์ผ๋งค๋งค์ผ์ง€ยท์ข…๋ชฉ์ฝ”๋“œ ๋งคํ•‘ยท๋ฏธ์ฒด๊ฒฐ ์กฐํšŒ). ์ฃผ๋ฌธ(๋งค์ˆ˜/๋งค๋„/์ •์ •/์ทจ์†Œ)์€ ๋ณ„๋„ `orders/kiwoom_order.py`. `scripts/kiwoom_client.py {token|summary|balance|positions|quote|resolve|refresh-codes|journal|open}`. ka10170 ๋‹น์ผ๋งค๋งค์ผ์ง€๋กœ round-tripยทํ’€๋งค๋„ ๊ฑฐ๋ž˜๊นŒ์ง€ ํฌ์ฐฉ (kt00018 ์ž”๊ณ ๋งŒ์œผ๋กœ๋Š” ๋ˆ„๋ฝ๋จ). ๋‹ค์ข…๋ชฉ ์‹œ์„ธ๋Š” `get_watchlist_quotes(codes)` ka10095 ํ•œ ์ฝœ๋กœ ์ฒ˜๋ฆฌ (๋‹จ๊ฑด ka10001 ร— N ๋Œ€๋น„ 100๋ฐฐ ๋น ๋ฆ„). ka10075 ๋ฏธ์ฒด๊ฒฐ ์กฐํšŒ๋กœ ์ •์ •/์ทจ์†Œ ๋Œ€์ƒ ์ž๋™ ์ถ”์ถœ - **stock-agent** โ€” Daily portfolio report (ํ‚ค์›€ REST ๊ธฐ๋ฐ˜, owner ๊ทธ๋ฃน(๋ณธ์ธ/๊ฐ€ํฌ)๋ณ„ ๋ธ”๋ก ํ‘œ์‹œ, `--by-account`๋Š” ๊ณ„์ขŒ๋ณ„ ์ถ”๊ฐ€ ๋ถ„๋ฆฌ) via `scripts/stock_portfolio_report.py {run|send} [--by-account]` - **behive-watchlist** โ€” ๋น„ํ•˜์ด๋ธŒ ์ข…๋ชฉ๋ถ„์„ ์š”์•ฝยท์ด๋ฉ”์ผยทํ…”๋ ˆ๊ทธ๋žจ ์•Œ๋ฆผ + ์ˆ˜๋™ ์›Œ์น˜๋ฆฌ์ŠคํŠธ ์ถ”๊ฐ€(`add`) + ์žฅ์ค‘ 15๋ถ„ ๊ฐ„๊ฒฉ ์‹œ์„ธ ๋ชจ๋‹ˆํ„ฐ๋ง(`scripts/watchlist_monitor.py check` โ€” buy/target/stop ํŠธ๋ฆฌ๊ฑฐ โ†’ ๋ ˆ์ด ํ…”๋ ˆ๊ทธ๋žจ, LLM ๊ฒฝ์œ  ์—†์Œ) + ์›น ๋ทฐ(`scripts/behive_web.py serve` โ€” `https://stock.hyowons.net/`, launchd ์ƒ์‹œ, ํŽ˜์ด์ง€ ๋กœ๋“œ ์‹œ์ ์— ํ‚ค์›€ ํ˜ธ์ถœ. CSS ๋ผ๋””์˜ค ํƒญ์œผ๋กœ `๊ฐ์‹œ์ข…๋ชฉ / ๊ด€๋ฆฌ์ž / ๊ฐ€ํฌ` 3๊ฐœ ํŒจ๋„: ์›Œ์น˜๋ฆฌ์ŠคํŠธ, ๋ณธ์ธยท๊ฐ€ํฌ ๊ณ„์ขŒํ˜„ํ™ฉ(KPIยท์˜ˆ์ˆ˜๊ธˆยท๋‹น์ผ์ •์‚ฐยท๋ณด์œ ์ข…๋ชฉ โ€” stock.briefing ๋ฉ”์ผ๊ณผ ๋™์ผ ๋ฐ์ดํ„ฐ). day_change ์ •ํ™•๋„์šฉ ka10001 ๋ณด์ •์€ web ๊ฒฝ๋กœ์—์„  ์ƒ๋žต, kt00018 raw ์‚ฌ์šฉ) ## Scripts Main workspace (`workspace/scripts/`), run with `python3`: - `briefing_mail.py` โ€” Gmail/Calendar/YouTube ๋‰ด์Šค ๋ธŒ๋ฆฌํ•‘ composer (๋„ค์ด๋ฒ„ ์ง€์ˆ˜ KOSPI/KOSDAQ/๋‚˜์Šค๋‹ฅ ์กฐํšŒ ํฌํ•จ, ์›”์š”์ผ ์˜ค์ „์—” stock agent์˜ `ipo_calendar_sync.py` ํ˜ธ์ถœ). **์˜ค์ „ ๋ธŒ๋ฆฌํ•‘์€ `us_market_digest`๋ฅผ importํ•ด ์ƒ๋‹จ์— ๐Ÿ‡บ๐Ÿ‡ธ ๋ฏธ๊ตญ์ฆ์‹œ ์š”์•ฝ ์นด๋“œ ์‚ฝ์ž…**. `prepare morning [--final]`์ด `us_market` ๋ธ”๋ก(available_todayยทrecap_expected_todayยทvideoยทtranscript)๊ณผ `us_send_directive`(proceed/wait)๋ฅผ ์‚ฐ์ถœ โ€” ์˜์ƒ ๊ฒŒ์‹œ๋์œผ๋ฉด proceed, KST ํ™”~ํ†  ๊ฒŒ์‹œ์˜ˆ์ •์ผ์ธ๋ฐ ๋ฏธ๊ฒŒ์‹œ๋ฉด wait(07:55 ์Šคํ‚ตโ†’08:30 ์žฌ์‹œ๋„), ์ฃผ๋ง/`--final`์€ proceed. cron์ด directive==wait๋ฉด ๋ฐœ์†ก ๋ณด๋ฅ˜. compose๊ฐ€ `us_market_summary`(LLM ์ž‘์„ฑ ํ‰๋ฌธ) ์žˆ์„ ๋•Œ๋งŒ ์นด๋“œ ๋ Œ๋” - `us_market_digest.py` โ€” ์˜ค์„ ์˜ ๋ฏธ๊ตญ ์ฆ์‹œ ๋ผ์ด๋ธŒ(@futuresnow, channel `UC_JJ_NhRqPKcIOj5Ko3W_3w`) '์˜ค๋Š˜์˜ ์š”์•ฝ' ์ตœ์‹  ์˜์ƒ ๊ฐ์ง€+์ž๋ง‰. `get_us_summary()`: ์ฑ„๋„ ์˜์ƒ ํŽ˜์ด์ง€ `lockupViewModel` ์Šคํฌ๋žฉ(RSS ํ”ผ๋“œ๋Š” IP 404 ์žฆ์•„ ๋ฏธ์‚ฌ์šฉ)์œผ๋กœ ์ตœ์‹  '์˜ค๋Š˜์˜ ์š”์•ฝ' ์˜์ƒ ์ฐพ๊ณ , watch ํŽ˜์ด์ง€ `publishDate`(์ ˆ๋Œ€์‹œ๊ฐ PTโ†’KST ๋ณ€ํ™˜)๋กœ ์˜ค๋Š˜ ๊ฒŒ์‹œ์—ฌ๋ถ€ ํŒ์ •(์ œ๋ชฉ ๋‚ ์งœ๋Š” ๋ฏธ๊ตญ ์„ธ์…˜์ผ์ด๋ผ ์‹ ๋ขฐX). ๋ฏธ๊ตญ์žฅ ๋งˆ๊ฐ ํ›„ ๋งค์ผ 07:20~08:30 KST ๊ฒŒ์‹œ. CLI: `python3 us_market_digest.py {latest|transcript}` Stock agent (`agents/stock/workspace/scripts/`), run with `python3`: - `kiwoom_client.py` โ€” ํ‚ค์›€ REST API ์กฐํšŒ ์ „์šฉ ํด๋ผ์ด์–ธํŠธ (๋ณธ์ธ 2๊ณ„์ขŒ ์ผ๋ฐ˜/ISA + ๊ฐ€ํฌ 2๊ณ„์ขŒ ๊ฐ€ํฌ_์ผ๋ฐ˜/๊ฐ€ํฌ_ISA, ํ† ํฐ ์บ์‹ฑ, ์ฃผ๋ฌธ ํ•จ์ˆ˜ ์—†์Œ). CLI: `token | summary | balance | positions | quote | resolve | refresh-codes | journal` - `fnguide_client.py` โ€” FnGuide ์ปดํผ๋‹ˆ๊ฐ€์ด๋“œ ํŽ€๋”๋ฉ˜ํ„ธ ์กฐํšŒ (์กฐํšŒ ์ „์šฉ, ํ‚ค์›€์— ์—†๋Š” ๋ฐ์ดํ„ฐ ๋ณด๊ฐ•). `Snapshot_all/{code}.xml`(EUC-KR, JS ๋ฏธ๊ฒฝ์œ  ์ง์ ‘ ํŒŒ์‹ฑ) 1์ฝœ โ†’ ์—ฐ๊ฐ„ ์žฌ๋ฌด ์‹œ๊ณ„์—ดยท๋งค์ถœ/EPS/์˜์—…์ด์ต ์ฆ๊ฐ€์œจยท์ปจ์„ผ์„œ์Šค(๋ชฉํ‘œ์ฃผ๊ฐ€ยทํˆฌ์ž์˜๊ฒฌยท์ถ”์ •EPS/PERยท์ฐธ์—ฌ๊ธฐ๊ด€์ˆ˜). `get_fundamentals(code)`, `state/fnguide_cache/{code}.json` 12h ์บ์‹œ, ์‹คํŒจยทETF๋Š” None (์ ˆ๋Œ€ raise X). โš ๏ธ FnGuide ์ €์ž‘๊ถŒ ํšŒ์ƒ‰์ง€๋Œ€ โ†’ ๋ณด์œ ยท๊ด€์‹ฌ ์ข…๋ชฉ on-demand๋งŒ. โš ๏ธ ํ˜„์žฌ ํ”ผ๋“œ๋Š” forward ์ถ”์ • EPS๊ฐ€ trailing ๋Œ€๋น„ ํฌ๊ฒŒ ๋†’๊ฒŒ ๋‚˜์˜ด(์˜ˆ ํ•˜์ด๋‹‰์Šค 2025 58,955โ†’2026E 297,725) โ€” ์ถ”์ • PER์ด ํ˜„์žฌ PER๋ณด๋‹ค ํ›จ์”ฌ ๋‚ฎ์€ ๊ฑด ์ด์ต ๊ธ‰์ฆ ๊ธฐ๋Œ€ ๋ฐ˜์˜์ด์ง€ ๋ฒ„๊ทธ ์•„๋‹˜. CLI: `python3 fnguide_client.py [--fresh]` - `wisereport_client.py` โ€” WISEreport(comp.wisereport.co.kr, FnGuide ๊ณ„์—ด ๋™์ผ ๋ฒค๋”) ์ปจ์„ผ์„œ์Šคยท์ฆ๊ถŒ์‚ฌ ๋ฆฌํฌํŠธ ์กฐํšŒ (์ˆœ์ˆ˜ JSON, encparam ๋ถˆํ•„์š”). `get_consensus(code)`: ์—ฐ๋„๋ณ„ ์ถ”์ • ์žฌ๋ฌด(IFRS์—ฐ๊ฒฐ A์‹ค์ /E์ถ”์ •, `c1050001_data.aspx flag=2`)ยท๋ชฉํ‘œ์ฃผ๊ฐ€+์ถ”์ •EPS 3๊ฐœ์›” ๋ฆฌ๋น„์ „ ์ถ”์ด(`cF5001`)ยท์–ด๋‹ ์„œํ”„๋ผ์ด์ฆˆ(`flag=5` ๋งค์ถœ/์˜์ต ์‹ค์  vs ์ง์ „ ์ปจ์„ผ์„œ์Šค ๊ดด๋ฆฌ์œจ). `get_reports(code)`: ์ตœ๊ทผ ์ฆ๊ถŒ์‚ฌ ๋ถ„์„๋ฆฌํฌํŠธ(`c1080001_data.aspx` โ€” ๋‚ ์งœยท์ฆ๊ถŒ์‚ฌยท์ œ๋ชฉยท๋ชฉํ‘œ๊ฐ€+์ƒํ–ฅ/ํ•˜ํ–ฅ ์•ก์…˜ยทํˆฌ์ž์˜๊ฒฌยท์• ๋„๋ฆฌ์ŠคํŠธยท์š”์•ฝ bullet, PDF ์›๋ฌธ์€ ๊ฒŒ์ดํŒ…ยท์ €์ž‘๊ถŒ์œผ๋กœ ์ œ์™ธ). `state/wisereport_cache/` ์บ์‹œ(์ปจ์„ผ์„œ์Šค 12hยท๋ฆฌํฌํŠธ 6h), ์‹คํŒจยทETF๋Š” None. ๋™์ผ ๋ฒค๋” ํšŒ์ƒ‰์ง€๋Œ€. CLI: ` [--fresh] [--reports]` - `stock_analysis.py` โ€” ์ข…๋ชฉ ๋ถ„์„ ๋ณด๊ณ ์„œ ์—”์ง„ (behive_web `/stock/`๊ฐ€ import, CLI ์—†์Œ). ํ‚ค์›€ ๊ธฐ๋ณธ์ •๋ณดยท์ผ๋ด‰ยท์ˆ˜๊ธ‰ + LLM ์ฝ”๋ฉ˜ํŠธ + SVG ์ฐจํŠธ + ํˆฌ์ž์˜๊ฒฌ ๊ฒŒ์ด์ง€ โ†’ ์ข…๋ชฉ๋ณ„ HTML ๋ณด๊ณ ์„œ(`state/stock_reports//`). FnGuide ์„ฑ์žฅ์„ฑยท์ปจ์„ผ์„œ์Šค + WISEreport ์ถ”์ •ยท๋ฆฌ๋น„์ „ยท์„œํ”„๋ผ์ด์ฆˆ ์„น์…˜ ํฌํ•จ(LLM ๋ฐ์ดํ„ฐ๋ธ”๋ก์—๋„ ์ฃผ์ž…). ๋ ˆ์ด์•„์›ƒ: ๊ฒฐ๋ก (ํˆฌ์ž์˜๊ฒฌ) ์ตœ์ƒ๋‹จ + ๋ณด์กฐ ์„น์…˜ 2๋‹จ ๊ทธ๋ฆฌ๋“œ(`.rpt-cols`), ์ง€ํ‘œ๋งˆ๋‹ค ํ‰์ดํ•œ ์บก์…˜(`.rpt-cap`) + โ“˜ ํƒญ ์„ค๋ช…(`_KV_HINTS`/`_lbl`). `enqueue` / `render_stock_page` / `add_peer`. ์ƒˆ ์„น์…˜์€ ์‹ ๊ทœ ์ƒ์„ฑ ๋ณด๊ณ ์„œ๋ถ€ํ„ฐ ๋ฐ˜์˜(๊ธฐ์กด ์ €์žฅ๋ณธ์€ ์˜› ๊ตฌ์กฐ). - `stock_portfolio_report.py` โ€” Daily portfolio report. ํ‚ค์›€ `kt00018`(๋ณด์œ )ยท`kt00001`(์˜ˆ์ˆ˜๊ธˆ)ยท`ka10170`(๋‹น์ผ๋งค๋งค์ผ์ง€) ground truth. `--by-account`๋กœ ๊ณ„์ขŒ ๋ถ„๋ฆฌ ๋ทฐ. ๋‹น์ผ์ •์‚ฐ(round-tripยทํ’€๋งค๋„)์€ ์ž”๊ณ ์— ์—†์–ด ๋ณ„๋„ [๋‹น์ผ์ •์‚ฐ] ์นด๋“œ๋กœ ํ‘œ์‹œ - `ipo_calendar_sync.py` โ€” Sync IPO subscription/listing dates to Google Calendar - `holiday_sync.py` โ€” investing.com์—์„œ ํ•œ๊ตญ(KRX) ํœด์žฅ์ผ fetch โ†’ `state/market_holidays.json`. behive_web.py ์ž๋™๊ฐฑ์‹  ํ† ๊ธ€์ด ํœด์žฅ์ผยทํ‰์ผยท์‹œ๊ฐ„๋Œ€๋กœ ๋น„ํ™œ์„ฑ ํŒ์ •. CLI: `python3 holiday_sync.py [--show]` - `behive_youtube_digest.py` โ€” ๋น„ํ•˜์ด๋ธŒ YouTube ์ข…๋ชฉ๋ถ„์„ ์ˆ˜์ง‘ยท์š”์•ฝยท๋ฐœ์†ก + ์ˆ˜๋™ ์›Œ์น˜๋ฆฌ์ŠคํŠธ ์ถ”๊ฐ€(`add`)/์กฐํšŒยท์‚ญ์ œ - `watchlist_monitor.py` โ€” ์›Œ์น˜๋ฆฌ์ŠคํŠธ ์ข…๋ชฉ ์žฅ์ค‘ 15๋ถ„ ์‹œ์„ธ ๊ฐ์‹œ, buy/target/stop ํŠธ๋ฆฌ๊ฑฐ ๋ฐœ์ƒ ์‹œ ๋ ˆ์ด ํ…”๋ ˆ๊ทธ๋žจ ์•Œ๋ฆผ (LLM ์—†์ด ๋™์ž‘). ๋ฏธ๋ณด์œ  ์ข…๋ชฉ์€ ka10095 batch 1์ฝœ + ๋‹จ๊ฑด ka10001 fallback. ๋ณด์œ  ์ข…๋ชฉ์€ kt00018 ์žฌํ™œ์šฉ - `behive_web.py` โ€” ์›Œ์น˜๋ฆฌ์ŠคํŠธ ์‹ค์‹œ๊ฐ„ ์›น ๋ทฐ + ๋งค๋งค ์ง„์ž…์ . `serve`(launchd, Tailscale IP 100.75.148.12:18790 ๋ฐ”์ธ๋“œ, ํŽ˜์ด์ง€ GET๋งˆ๋‹ค ํ‚ค์›€ ka10095 batch 1์ฝœ๋กœ ์›Œ์น˜๋ฆฌ์ŠคํŠธ ์‹œ์„ธ + kt00018ยทkt00001ยทka10170 ๋ณ‘๋ ฌ ํ˜ธ์ถœ ํ›„ HTML ์‘๋‹ต. RENDER ์บ์‹œ 10s, ์ข…๋ชฉ๋ณ„ quote ์บ์‹œ 30s) / `render`(๋””๋ฒ„๊น…์šฉ 1ํšŒ ๋ Œ๋”). ์™ธ๋ถ€ ๋…ธ์ถœ์€ NAS Synology reverse proxy(`stock.hyowons.net` โ†’ mac:18790) ๊ฒฝ์œ . ์ธ์ฆ ์—†์Œ โ€” Tailnet ๋‚ด๋ถ€๋ง ํ•œ์ • ์šด์˜. ๋ณด์œ ์ข…๋ชฉ day_change ๋ณด์ •์€ brifing ๊ณผ ๋™์ผ A-4 ์ •์ฑ…. KPI ์ˆœ์„œยท๋ผ๋ฒจ๋„ stock_portfolio_report ์™€ ํ†ต์ผ. ๋ณด์œ ์ข…๋ชฉ ํ–‰๋งˆ๋‹ค `๐Ÿ“‹ ๊ฑฐ๋ž˜๋‚ด์—ญ` + `๐Ÿ’ฐ ๊ฑฐ๋ž˜` ๋ฒ„ํŠผ. ์ž์‚ฐ์ •๋ณด ํƒญ sub-tab 3๊ฐœ (์ž์‚ฐ๋ณด๊ธฐยท์ฐจํŠธ๋ณด๊ธฐยท์‹œ์žฅ์ •๋ณด) + ์šฐ์ธก ๋ณ„๋„ `[๐Ÿ’ฐ ๊ฑฐ๋ž˜]` ๋ฒ„ํŠผ (๋ณธ์ธ ์ฒซ ๋ณด์œ ์ข…๋ชฉ ์ž๋™ ์„ ํƒ). ๊ด€์‹ฌยท๊ฐ์‹œ์ข…๋ชฉ ํ–‰์—๋„ `๐Ÿ’ฐ ๊ฑฐ๋ž˜` (๋ณด์œ  ๋ชจ๋“œ๋ฉด ๋งค๋„ default). **๊ฑฐ๋ž˜ ๋ชจ๋‹ฌ ์‹œ์Šคํ…œ (`order-modal` + `pin-modal` + `open-orders-modal`)** โ€” ๋งค๋งค ์ง„์ž…์ . ํ๋ฆ„: ์ข…๋ชฉ select(์ƒ๋‹จ, ๋ณด์œ /๊ด€์‹ฌ/๊ฐ์‹œ ํ†ตํ•ฉ) โ†’ ๋งค์ˆ˜ยท๋งค๋„ ํ† ๊ธ€ โ†’ ํ˜ธ๊ฐ€์ฐฝ(ka10004 10๋‹จ๊ณ„, 1์ดˆ polling, visibility ๊ฐ€๋“œ) + ์ž…๋ ฅ(๊ณ„์ขŒยท์ฃผ๋ฌธ์œ ํ˜• LIMIT/MARKETยท๋‹จ๊ฐ€ยท๊ธˆ์•ก(๋งค์ˆ˜๋งŒ ์–‘๋ฐฉํ–ฅ)ยท์ˆ˜๋Ÿ‰) โ†’ ๋งค์ˆ˜/๋งค๋„ ๋ฒ„ํŠผ โ†’ propose โ†’ PIN ๋ชจ๋‹ฌ(modal-top z-index) ์นด๋“œ ์š”์•ฝ + PIN ์ž…๋ ฅ(`autocomplete="one-time-code"`) + ๋งŒ๋ฃŒ ์นด์šดํŠธ๋‹ค์šด โ†’ verify โ†’ ๊ฒฐ๊ณผ ํ† ์ŠคํŠธ + ์ž๋™ ๋‹ซ๊ธฐ. `[๐Ÿ“‹ ์ง„ํ–‰์ค‘]` ํƒญ์€ ํ™œ์„ฑ PIN ์นด๋“œ โ†’ PIN ๋ชจ๋‹ฌ, ๋ฏธ์ฒด๊ฒฐ๋งŒ โ†’ open-orders ๋ชจ๋‹ฌ(4๊ณ„์ขŒ ํ†ตํ•ฉ + ํ–‰๋ณ„ ์ทจ์†Œ). ๋งค์ˆ˜ ์‹œ ๊ธˆ์•กโ†”์ˆ˜๋Ÿ‰ ์–‘๋ฐฉํ–ฅ ์ž๋™(programmatic .value, ๋ฌดํ•œ๋ฃจํ”„ X). ๋งค๋„ ํ† ๊ธ€ ์‹œ ์ˆ˜๋Ÿ‰ ์ž๋™ 100%(max_qty). ์‹œ์žฅ phase ๋ผ๋ฒจ + NXT ์‹œ๊ฐ„๋Œ€+`nxt_enable=false` ์‹œ `๐Ÿ“ต NXT ๊ฑฐ๋ž˜๋ถˆ๊ฐ€` + ๋งค์ˆ˜/๋งค๋„ ๋ฒ„ํŠผ disable. ์šฐ์ƒ๋‹จ X ์—†์Œ โ€” ํ•˜๋‹จ [๋‹ซ๊ธฐ]/[์ทจ์†Œ] + overlay ํด๋ฆญ. **2๊ณ„์ขŒ ๋™์‹œ ๋งค๋„**(2026-06-12): ๋งค๋„ ๋ฒ„ํŠผ ์‹œ **์ „๋Ÿ‰๋งค๋„(์ž…๋ ฅ ์ˆ˜๋Ÿ‰=max_qty)** ์ด๊ณ  ๊ฐ™์€ ์†Œ์œ ์ž ๊ทธ๋ฃน(๋ณธ์ธ ์ผ๋ฐ˜โ†”ISA / ๊ฐ€ํฌ๋ผ๋ฆฌ)์˜ ๋‹ค๋ฅธ ๊ณ„์ขŒ์—๋„ ๊ฐ™์€ ์ข…๋ชฉ ๋ณด์œ (`accStatus.trde_able_qty>0`)๋ฉด `sell-choice-modal` ํŒ์—… โ€” [๋‘ ๊ณ„์ขŒ ๋ชจ๋‘ ๋งค๋„](๋‘ ๊ณ„์ขŒ ๋ชจ๋‘ ๋งค๋„๊ฐ€๋Šฅ ์ „๋Ÿ‰, ๋‹จ๊ฐ€ ๋™์ผ) / [์„ ํƒ ๊ณ„์ขŒ๋งŒ] / [์ทจ์†Œ]. ์ผ๋ถ€๋งค๋„๋Š” ํŒ์—… ์—†์ด ๋‹จ์ผ ์ง„ํ–‰. ๋งค๋„ ์ •๋ณด์˜์—ญ์€ ๊ทธ๋ฃน ๋‚ด ๋‹ค๋ฅธ ๊ณ„์ขŒ๋„ ๋ณด์œ  ์‹œ `๋ณด์œ : 141์ฃผ / ์ „์ฒด 280์ฃผ` ๋ณ‘๊ธฐ. ๋ชจ๋‘ ๋งค๋„๋Š” `POST /api/order/propose_multi` โ†’ `handler.propose_trade_multi`(๋ ˆ๊ทธ๋ณ„ ๋…๋ฆฝ ๊ฒ€์ฆ, SELL+LIMIT/MARKET ํ•œ์ •, ๊ฐ™์€ ๊ทธ๋ฃน๋งŒ) โ†’ **์นด๋“œ 1์žฅ+PIN 1๊ฐœ**(iMessage `๋งค๋„(2๊ณ„์ขŒ)`)๊ฐ€ ๋‘ ๋ ˆ๊ทธ ์Šน์ธ โ†’ verify ์‹œ `_submit_multi_legs`๊ฐ€ ๋ ˆ๊ทธ ๋…๋ฆฝ ์ œ์ถœ(idem_hash ๊ณ„์ขŒ๋ณ„ ๋ถ„๋ฆฌ)ยท๋…๋ฆฝ fill_watcher, ํ•œ ๋ ˆ๊ทธ ์‹คํŒจํ•ด๋„ ๋‚˜๋จธ์ง€ ์‹œ๋„(ok=ํ•˜๋‚˜๋ผ๋„ ์ ‘์ˆ˜). **ํ…”๋ ˆ๊ทธ๋žจ ๋ฐœ์†ก ์ •์ฑ… (์›น ๋งค๋งค)** โ€” ๊ฑฐ๋ถ€ยท๊ฒ€์ฆ ์—๋Ÿฌ๋Š” ํ† ์ŠคํŠธ๋งŒ, **๋งค๋งค๋“ฑ๋ก(submit_with_pin ์„ฑ๊ณต)ยท๋งค๋งค์ฒด๊ฒฐ(fill_watcher)๋งŒ** ํ…”๋ ˆ๊ทธ๋žจ. PIN ๋ฉ”์‹œ์ง€๋Š” **iMessage** (Apple ๋„๋ฉ”์ธ ๋ฐ”์ธ๋”ฉ `@stock.hyowons.net #PIN`, iOS Safari OTP ์ž๋™์ž…๋ ฅ). `handler.send_imessage_pin` (fire-and-forget Popen, AppleEvent timeout -1712 ๋– ๋„ ๋ฉ”์‹œ์ง€๋Š” ํ๋กœ). credential `credentials/admin_imessage.json` `{"handle": "01012345678"}`. ์ž๊ธฐ ์ž์‹  iMessage self-send ๊ฐ€๋Šฅ (mac โ†’ ๋ณธ์ธ iCloud handle). **์‹ ๊ทœ endpoint**: `/api/quote_book?code` (ka10004 ํ˜ธ๊ฐ€ 10๋‹จ๊ณ„ + ka10001 ํ˜„์žฌ๊ฐ€ + `nxt_enable`), `/api/order/check?code&account&side&price` (์ž”์•กยท๋ณด์œ ยทmax_qtyยท๋งค๋„ ์†์ต ๋ฏธ๋ฆฌ๋ณด๊ธฐ), `POST /api/order/propose` (handler.propose_trade wrapper, ์„ฑ๊ณต ์‹œ๋งŒ ํ…”๋ ˆ๊ทธ๋žจยทiMessage), `POST /api/order/propose_multi` (2๊ณ„์ขŒ ๋™์‹œ ๋งค๋„ โ€” accounts/qtys ์ฝค๋งˆ ๋™์ˆ˜ ๋ฆฌ์ŠคํŠธ, handler.propose_trade_multi wrapper), `POST /api/order/verify` (handler.submit_with_pin wrapper, ์„ฑ๊ณต ์‹œ๋งŒ ํ…”๋ ˆ๊ทธ๋žจ), `POST /api/order/cancel` (handler.cancel_active_card, ํ…”๋ ˆ๊ทธ๋žจ X), `/api/order/active` (PinStore.peek + 4๊ณ„์ขŒ ๋ฏธ์ฒด๊ฒฐ ์นด์šดํŠธ), `/api/orders/open` (ka10075 4๊ณ„์ขŒ), `POST /api/orders/cancel?ord_no&account` (handler.cancel_open_order + ํ…”๋ ˆ๊ทธ๋žจ), `/api/market_state` (regular/nxt/closed/holiday/weekend phase), `/api/symbols/all` (๋ณด์œ +๊ด€์‹ฌ+๊ฐ์‹œ ํ†ตํ•ฉ dedup) **๊ธฐ์—…์ •๋ณด ๋ชจ๋‹ฌ (4ํƒญ)** โ€” ์ข…๋ชฉ ํ–‰ `๊ธฐ์—…์ •๋ณด` ๋ฒ„ํŠผ โ†’ `/api/stock_info?code`(ํ‚ค์›€ ka10001 + ๋„ค์ด๋ฒ„ ๋ถ„๊ธฐ์˜์—…์ด์ต + `fnguide_client` ํŽ€๋”๋ฉ˜ํ„ธยท์ปจ์„ผ์„œ์Šค + `wisereport_client` ๋ฆฌ๋น„์ „ยท์„œํ”„๋ผ์ด์ฆˆยท์ตœ๊ทผ๋ฆฌํฌํŠธ) fetch โ†’ ๋‹จ์ผ ์ข…๋ชฉ์€ 4ํƒญ ๋ Œ๋”: **์š”์•ฝ**(ํ˜„์žฌ๊ฐ€ยท๋ชฉํ‘œ์ฃผ๊ฐ€ยท๋ฆฌ๋น„์ „ยท์ฆ๊ฐ€์œจยท์„œํ”„๋ผ์ด์ฆˆ + ์ตœ์‹  ๋ฆฌํฌํŠธ 1๊ฑด) / **๊ธฐ์—…์ •๋ณดยท๊ฐ€์น˜**(PERยทPBRยทEPSยทBPSยทROEยท์˜์—…์ด์ตยท52์ฃผยท์œ ํ†ต๋น„์œจยท์™ธ๊ตญ์ธ) / **์„ฑ์žฅ์„ฑยท์ปจ์„ผ์„œ์Šค**(๋งค์ถœ/EPS ์ฆ๊ฐ€์œจยท๋ชฉํ‘œ์ฃผ๊ฐ€ยทํˆฌ์ž์˜๊ฒฌยท์ถ”์ •PERใ€”ํ˜„์žฌPER ๋ณ‘๊ธฐใ€•ยท๋ชฉํ‘œ๊ฐ€ ๋ฆฌ๋น„์ „ยท์„œํ”„๋ผ์ด์ฆˆ) / **ํˆฌ์ž๋ฆฌํฌํŠธ**(์ตœ๊ทผ ์ฆ๊ถŒ์‚ฌ ๋ฆฌํฌํŠธ ๋ชฉ๋ก, ๋ชฉํ‘œ๊ฐ€ โ–ฒ์ƒํ–ฅ/โ–ผํ•˜ํ–ฅ). ํƒญ์€ ๋ชจ๋‹ฌ ์ „์šฉ ํด๋ž˜์Šค(`.info-tabs/.info-tabbtn/.info-tabpanel` + `data-info-tab`/`data-info-panel`)์™€ ๋…๋ฆฝ ํ•ธ๋“ค๋Ÿฌ๋กœ ์ž์‚ฐํƒญ `.sub-tab`๊ณผ ๊ฒฉ๋ฆฌ(์ „์—ญ restoreSubs ์ถฉ๋Œ ํšŒํ”ผ). ํ•ญ๋ชฉ๋ณ„ โ“˜ ํƒญ ํŒ์—… ์„ค๋ช…(`INFO_SPECS`/`INFO_DESC`, document ์œ„์ž„ `.info-label`). ๋น„๊ต ๋ชจ๋“œ(์—ฌ๋Ÿฌ ์ข…๋ชฉ)๋Š” ํƒญ ์—†์ด ๊ธฐ์กด ๋น„๊ตํ‘œ ์œ ์ง€. ETF ๋“ฑ ๋ฐ์ดํ„ฐ ์—†์œผ๋ฉด ํ•ด๋‹น ํƒญ "๋ฐ์ดํ„ฐ ์—†์–ด์š”". - `send_balance_to_budget.py` โ€” ๋งค์›” 1์ผ 04:30 launchd. ๋ณธ์ธ ๊ณ„์ขŒ(๊ฐ€ํฌ ์ œ์™ธ)๋ณ„ ์ž”์•กยท์˜ˆ์ˆ˜๊ธˆยทํ‰๊ฐ€์•ก์„ ์ง‘๊ณ„ํ•ด `agents/budget/inbox/incoming/`์— envelope(`topic: securities_balance`)๋กœ ๋–จ์–ด๋œจ๋ฆฐ๋‹ค. ๊ณจ๋”” ์›”๊ฐ„ ๊ฒฐ์‚ฐ(05:00) ์ž…๋ ฅ. LLM ๋ฏธ๊ฒฝ์œ , ์‹คํŒจ ์‹œ ๋ ˆ์ด ํ…”๋ ˆ๊ทธ๋žจ์œผ๋กœ ์ž๊ฐ€ ์•Œ๋ฆผ. - `trade_journal.py` โ€” ์ข…๋ชฉ๋ณ„ ๋งค๋งค ๊ธฐ๋ก ๋ˆ„์ . ํ‚ค์›€ REST์— ๊ธฐ๊ฐ„ ๊ฑฐ๋ž˜๋‚ด์—ญ API ๋ถ€์žฌ โ†’ ํ‰์ผ 21:00 launchd(NXT ์•ผ๊ฐ„ ๋งˆ๊ฐ ํ›„)๋กœ ka10170 4๊ณ„์ขŒ ํ˜ธ์ถœํ•ด `state/trade_journal.jsonl`์— ์ ์žฌ. `(date, account)` ๋‹จ์œ„ idempotent, ํœด์žฅ์ผ/์ฃผ๋ง self-skip(`--force`๋กœ ์šฐํšŒ). ์ ์žฌ ์‹œ์ž‘์ผ 2026-05-13 ์ด์ „ ๋ณด์œ ๋ถ„์€ `seed` ๋ช…๋ น(1ํšŒ)์œผ๋กœ ํ˜„์žฌ ํ‰๋‹จ๊ฐ€ร—(๋ณด์œ -๋‹น์ผ๋งค์ˆ˜+๋‹น์ผ๋งค๋„) ๋‹จ์ผ ํ–‰์œผ๋กœ ์••์ถ• ์ ์žฌ๋จ(`seed=true` ํ”Œ๋ž˜๊ทธยท`*` ๋งˆ์ปค). CLI: `collect [--date YYYYMMDD]` / `seed` / `show ` / `query [--from --to --account --code]` - `market_indicators_sync.py` โ€” ์‹œ์žฅ ๋‹จ์œ„ ADRยทํˆฌ์ž์ž๋ณ„ ๋งค๋งค ๋ˆ„์ . ๋„ค์ด๋ฒ„ m.stock `/api/index/{KOSPI|KOSDAQ}/integration` ํ•œ ์ฝœ๋กœ dealTrendInfoยทupDownStockInfo ์ˆ˜์ง‘ โ†’ `state/market_indicators_history.jsonl`. `(date, market)` ๋‹จ์œ„ idempotent, ํœด์žฅ/์ฃผ๋ง self-skip(`--force`). ํ‰์ผ 21:00 stock.trade-journal launchd์— ํ†ตํ•ฉ ๋ฐœํ™” (๋ณ„๋„ plist ์—†์Œ). KRX ์ •๋ณด๋ฐ์ดํ„ฐ์‹œ์Šคํ…œ์€ ์‘๋‹ต ํŒจํ„ด ๋ณ€๊ฒฝ์œผ๋กœ ๋ฐฑํ•„ ๋ณด๋ฅ˜ โ€” ๋งค์ผ ๋ˆ„์ ๋งŒ ์‹œ์ž‘. behive_web ์ž์‚ฐ์ •๋ณด ํƒญ์˜ ์‹œ์žฅ์ •๋ณด sub-tab์ด sparkline ๋ฐ์ดํ„ฐ์›์œผ๋กœ ์‚ฌ์šฉ - `sim/` (์Šคํฌ๋ฆฝํŠธ ์•„๋‹Œ **๋ณ„๋„ ํŒจํ‚ค์ง€** โ€” `agents/stock/workspace/sim/`) โ€” **์ž๋™๋งค๋งค ์‹œ๋ฎฌ๋ ˆ์ด์…˜(ํŽ˜์ดํผ ํŠธ๋ ˆ์ด๋”ฉ) ์—”์ง„**. ์‹ค์ฃผ๋ฌธ `orders/`์™€ ์™„์ „ ๋ถ„๋ฆฌ, ๊ฐ€์ƒ์ž๋ณธ 1์–ต์œผ๋กœ๋งŒ ๋™์ž‘(`INITIAL_CAPITAL`, 2026-06-10 1์ฒœ๋งŒโ†’1์–ต). ๊ตฌ์„ฑ: `config.py`(ํŒŒ๋ผ๋ฏธํ„ฐ)ยท`indicators.py`(SMA/RSI/ATR/๊ณ ์ €/๊ฑฐ๋ž˜๋Ÿ‰ ์ˆœ์ˆ˜ํ•จ์ˆ˜)ยท`universe.py`(**๋ˆ„์  ๊ด€์ฐฐ๋ชฉ๋ก** `state/sim/watchlist.json` โ€” ๋น„ํ•˜์ด๋ธŒ ์›Œ์น˜+๊ด€์‹ฌ+๋ณธ์ธ๋ณด์œ ๋ฅผ ๋งค ์Šค์บ” **์ž๋™ ํŽธ์ž…**ํ•˜๋˜ **์ž๋™ ์‚ญ์ œ X**(์ˆ˜๋™๋งŒ). `sync_watchlist`/`add_manual`/`remove`)ยท`data.py`(์‹œ์„ธ batchยท์ผ๋ด‰ **์บ์‹œ ์šฐ์„ **ยท์ˆ˜๊ธ‰ 60m์บ์‹œยท์• ๋„ใ€”fnguide/wisereport 12h ์บ์‹œ, **์บ์‹œ ๋ฏธ์Šค ๋•Œ๋งŒ 0.4s ํŽ˜์ด์‹ฑ**์œผ๋กœ ์—ฐ์† ํฌ๋กค๋ง ์ฐจ๋‹จ ํšŒํ”ผใ€•)ยท`signals.py`(์ง„์ž…/์ฒญ์‚ฐ ๊ทœ์น™ + ์†์ ˆยท๋ชฉํ‘œ ๊ณ„์‚ฐ + dashboard์šฉ ์ฒดํฌ๋ฆฌ์ŠคํŠธ)ยท`portfolio.py`(๊ฐ€์ƒ ์ฒด๊ฒฐยท๋น„์šฉยท์†์ตยทMDD)ยท`engine.py`(์Šค์บ” ์˜ค์ผ€์ŠคํŠธ๋ ˆ์ด์…˜ โ€” `_gather(extra_codes)`๋กœ **๋ณด์œ  ์ข…๋ชฉ์€ ๊ด€์ฐฐ๋ชฉ๋ก์—์„œ ๋น ์ ธ๋„ ์ฒญ์‚ฐ ์ถ”์ **)ยท`benchmark.py`(**๊ธฐ์ค€์ง€์ˆ˜ ๋Œ€๋น„ ์•ŒํŒŒ** โ€” ๋„ค์ด๋ฒ„ m.stock ์ง€์ˆ˜ ์ผ๋ณ„์ข…๊ฐ€๋ฅผ `state/sim/index_history.json`์— ๋ˆ„์ ใ€”KOSPI/KOSDAQ, pageSizeโ‰ค50ใ€•, ๊ตฌ๊ฐ„ ๋“ฑ๋ฝ๋ฅ ยท์ดˆ๊ณผ์ˆ˜์ต ๊ณ„์‚ฐ. ์Šค์บ”๋งˆ๋‹ค `update_today` 1ํšŒ ๊ฐฑ์‹ , ์‹คํŒจ ๋ฌด์‹œ)ยท`__main__.py`(CLI)ยท`sim_web.py`(๋ณ„๋„ ๋Œ€์‹œ๋ณด๋“œ ์„œ๋ฒ„ 18792). ์ „๋žต: ๋ฐฉํ–ฅ=์• ๋„ ์•ฝํ•œ๊ฒŒ์ดํŠธ+๊ฐ€์ , ํƒ€์ด๋ฐ=์ˆ˜๊ธ‰ยท๊ธฐ์ˆ . **ETF/ETN์€ ์ž๋™๋งค์ˆ˜ ์ œ์™ธ**(2026-06-09 โ€” ๋ฐฉํ–ฅ์„ฑ ์—”์ง„์ธ ์• ๋„ ์ปจ์„ผ์„œ์Šค๊ฐ€ ETF์—” None์ด๋ผ ์ „๋žต ๋ถ€์ •ํ•ฉ. `universe.is_etf()`๊ฐ€ ์šด์šฉ์‚ฌ ํ”„๋ฆฌํ”ฝ์Šค(KODEX/TIGER/ACEโ€ฆ)๋กœ ํŒ๋ณ„, engine ๋ฏธ๋ณด์œ  ๋งค์ˆ˜ ๋ถ„๊ธฐ ์ง์ „์— `ETF โ€” ์ž๋™๋งค๋งค ์ œ์™ธ` SKIP. **๋ณด์œ  ETF๋Š” ์ฒญ์‚ฐ๊นŒ์ง€ ์ถ”์ **(๋งค์ˆ˜ ๋ถ„๊ธฐ ์ „ ์ฒ˜๋ฆฌ๋ผ ๋ฌด๊ด€)). ๋งค์ˆ˜=๊ฑฐ๋ž˜๋Ÿ‰+์ „๊ณ ์  ๋ŒํŒŒ ์ฆ‰์‹œ / ํ‰์†Œ ๋ˆŒ๋ฆผ๋ชฉ(max(20์ผ์„ , ์ „์ผ์ข…๊ฐ€โˆ’ATR)) ์ง€์ •๊ฐ€. **์‹œ์žฅ ๊ตญ๋ฉด ํ•„ํ„ฐ(6๋‹จ๊ณ„)**: `market_regime_map()`์ด ์ƒ์Šน๋น„์œจ(ํญ)+์ง€์ˆ˜์ถ”์„ธ(๋ฐฉํ–ฅ, 20์ผ์„ )+๋‹น์ผ๋“ฑ๋ฝ(๊ฐ•๋„)์„ ์กฐํ•ฉํ•ด `engine.REGIME` 6๋‹จ๊ณ„๋กœ ๋ถ„๋ฅ˜ โ€” ๐Ÿ”ฅ๊ฐ•์„ธยท๐Ÿ“ˆ๋ฐ˜๋“ฑ(์ƒ์Šน๋น„์œจโ†‘ & ์ง€์ˆ˜ 20์ผ์„  ์•„๋ž˜=์•ฝ์„ธํƒˆ์ถœ)ยท๐ŸŒค์™„๋งŒ์ƒ์Šน / โž–ํ˜ผ์กฐยท๐Ÿ“‰์•ฝ์„ธยทโ„๏ธ๊ธ‰๋ฝ. **์•ž 3๊ฐœ=๋งค์ˆ˜ํ—ˆ์šฉ, ๋’ค 3๊ฐœ=๋ณด๋ฅ˜**(`market_ok_map`์ด `REGIME[g][2]`๋กœ ํŒŒ์ƒ). ์ƒ์Šน๋น„์œจ์€ **ํ•ญ์ƒ ๋„ค์ด๋ฒ„ ์‹ค์‹œ๊ฐ„**(`_live_breadth` 60s ์บ์‹œ, ์‹คํŒจ ์‹œ EOD). ์•ฝ์„ธ์žฅ์ด์–ด๋„ **๋ŒํŒŒ ์ง„์ž…์€ ํ—ˆ์šฉ, ๋ˆŒ๋ฆผ๋ชฉ๋งŒ ๋ณด๋ฅ˜**(soft gate). ์‹œ์žฅํƒญ์— ๊ตญ๋ฉด ๋ฐฐ์ง€+์„ค๋ช… ํ‘œ์‹œ(๋งค์ˆ˜ํŒ๋‹จ๊ณผ ๋™์ผ ์†Œ์Šค). `code_market_map()`์ด ์ข…๋ชฉโ†’KOSPI/KOSDAQ ๋งคํ•‘. (2026-06-09 ๊ฐ•์„ธ/์•ฝ์„ธ 2๋‹จ๊ณ„โ†’6๋‹จ๊ณ„ ๊ตญ๋ฉด์œผ๋กœ ์„ธ๋ถ„ํ™”) **2026-06-09 4์ข… ์ถ”๊ฐ€**: โ“ **๋ฆฌ์Šคํฌ ๊ธฐ๋ฐ˜ ์‚ฌ์ด์ง•**(`signals.target_value` โ€” ์ˆ˜๋Ÿ‰=์ž์‚ฐร—`RISK_PER_TRADE_PCT` รท ์†์ ˆํญ, ๊ท ๋“ฑ๋น„์ค‘ ์ž์‚ฐ/`MAX_POSITIONS` ์ƒํ•œ ์บก, 0=๋”. ๋ณ€๋™์„ฑ ํฐ ์ข…๋ชฉ ์ž๋™ ์ถ•์†Œยท์ข…๋ชฉ๋‹น ๋ฆฌ์Šคํฌ ๊ท ๋“ฑํ™”. ์—”์ง„ยท๋ฐฑํ…Œ์ŠคํŠธ ๊ณต์šฉ) โ“‘ **RSI ํ•„ํ„ฐ**(`indicators.rsi` ํ™œ์„ฑํ™” โ€” ๋ŒํŒŒ ์‹œ `RSI_OVERBOUGHT`โ†‘ ๊ณผ์—ด ์ถ”๊ฒฉ ๋ณด๋ฅ˜ / ๋ˆŒ๋ฆผ๋ชฉ ์‹œ `RSI_OVERSOLD`โ†“ ๋‚™ํ•˜ ์ค‘ ๋ณด๋ฅ˜, ๋ฐ์ดํ„ฐ ์—†์œผ๋ฉด ํ†ต๊ณผ) โ“’ **์‹œ์žฅ ๊ตญ๋ฉด 6๋‹จ๊ณ„**(`market_regime_map`โ†’`engine.REGIME`, ์œ„ ์‹œ์žฅ ๊ตญ๋ฉด ํ•„ํ„ฐ ์ฐธ์กฐ. `_index_trend_ok`ยท`_index_daily_change` ๋ณด์กฐ. โš ๏ธ2026-06-09 ๊ฐ•์„ธ/์•ฝ์„ธ 2๋‹จ๊ณ„๊ฐ€ 84% ๋ฐ˜๋“ฑ์ผ์„ ์•ฝ์„ธ๋กœ ์˜คํŒํ•ด 6๋‹จ๊ณ„ ๊ตญ๋ฉด์œผ๋กœ ์„ธ๋ถ„ํ™”) โ““ **์‹œ๊ฐ„์†์ ˆ**(`MAX_HOLD_DAYS` ๊ฒฝ๊ณผ & ๋ฏธ์ง„์ „ใ€”ํŠธ๋ ˆ์ผ๋ง ์ „+์ง„์ž…๊ฐ€ ์ดํ•˜ใ€• ์‹œ ์ฒญ์‚ฐํ•ด ์ž๋ณธ ํšŒ์ „, `evaluate_holding(held_days)` โ€” ์—”์ง„=๋‹ฌ๋ ฅ์ผยท๋ฐฑํ…Œ์ŠคํŠธ=`entry_date` ๋‹ฌ๋ ฅ์ผ). โ“– **์Šค์บ” ๋ฉ”๋ชจ 4์ข…**(2026-06-10): ๋ณ€์ด ์ˆ˜๊ฐ€ ๋Š˜์–ด๋„ ์Šค์บ”์ด ์„ ํ˜• ํญ์ฆํ•˜์ง€ ์•Š๊ฒŒ โ€” ํ˜ธ๊ฐ€(`data._BOOK_MEMO`, ์ฒด๊ฒฐ ๊ณต์ •์„ฑ ๊ฒธ์šฉ)ยท์ผ๋ด‰(`engine._SCAN_CANDLES`)ยท์ง€ํ‘œ(`engine._IND_MEMO`, (code,์ง€ํ‘œํŒŒ๋ผ๋ฏธํ„ฐ) ํ‚ค)ยท์ˆ˜๊ธ‰/์• ๋„(`data._FLOW_MEMO_SCAN`/`_ANL_MEMO_SCAN`)์„ ์Šค์บ” 1ํšŒ ๋™์•ˆ ๊ณต์œ , `_gather`๊ฐ€ ๋งค ์Šค์บ” ๋ฆฌ์…‹. ํ•ต์‹ฌ์€ ์• ๋„ ์บ์‹œ stale ์‹œ 0.4s ํŽ˜์ด์‹ฑ์ด ๋ณ€์ด ์ˆ˜๋งŒํผ ๋ฐ˜๋ณต๋˜๋˜ ๊ฒƒ โ€” 108๊ณ„์ขŒ ํŒ๋‹จ 38sโ†’2s. โ“• **2026-06-10 ์ฝ”๋“œ๋ฆฌ๋ทฐ 3์ข…**: ์žฌ์ง„์ž… ์ฟจ๋‹ค์šด(์ „๋Ÿ‰์ฒญ์‚ฐ ์ข…๋ชฉ **๋‹น์ผ ์žฌ๋งค์ˆ˜ ๊ธˆ์ง€** โ€” `Portfolio.last_exit`/`exited_today`, backtest ๋™์ผ ๊ทœ์น™. ํœฉ์˜ churn ๋ฐฉ์ง€)ยท์žฅ์ค‘ ๊ฑฐ๋ž˜๋Ÿ‰ ํ™˜์‚ฐ(`_session_elapsed_frac` 0.15~1.0์„ `ind['vol_time_frac']`๋กœ ์ฃผ์ž… โ†’ signals๊ฐ€ ๋ŒํŒŒ ๊ฑฐ๋ž˜๋Ÿ‰ยทํšŒ์ „์œจ์„ ํ•˜๋ฃจ์น˜๋กœ ํ™˜์‚ฐ ๋น„๊ต, '(ํ™˜์‚ฐ)' ํ‘œ๊ธฐ. ์ด์ „์—” ์˜ค์ „ ๋ŒํŒŒ๊ฐ€ ๊ตฌ์กฐ์ ์œผ๋กœ ๋ถˆ๊ฐ€ํ–ˆ์Œ. backtest๋Š” 1.0=๋ฌด์˜ํ–ฅ)ยท์ผ๋ณ„ ์„ฑ๊ณผ์ด๋ ฅ(`state/sim/equity_history.json` โ€” ๋งค ์Šค์บ” ๋‹น์ผ ํ•ญ๋ชฉ ๋ฎ์–ด์จ EOD๊ฐ’ ๋ณด์กด, `{date:[{id,ph(ํŒŒ๋ผ๋ฏธํ„ฐํ•ด์‹œ),equity,ret}]}`. ๋ณ€์ด id ์žฌ์‚ฌ์šฉ๋ผ๋„ ph๋กœ ์‹๋ณ„. ๊ตญ๋ฉด๋ณ„ ์‚ฌํ›„๋ถ„์„์šฉ) โ“” **์ถ”์„ธ ์งˆ ๋ณด๊ฐ•**(2026-06-09 `trend_ok` ๊ฒŒ์ดํŠธ ๊ฐ•ํ™”: ๊ธฐ์กด ํ˜„์žฌ๊ฐ€>20์ผ์„ +์ •๋ฐฐ์—ด(5>20)์— ๋”ํ•ด โ‘ **20์ผ์„  ์šฐ์ƒํ–ฅ ๊ธฐ์šธ๊ธฐ**ใ€”`sma_long_slope_up`, `TREND_SLOPE_DAYS`์ „ ๋Œ€๋น„ใ€• โ‘ก**์ค‘๊ธฐ ์ •๋ฐฐ์—ด 5>`SMA_MID`(60)** โ€” ๋‘˜ ๋‹ค ์ข…๋ชฉ๋ฐ์ดํ„ฐ๋ผ **๋ฐฑํ…Œ์ŠคํŠธ ๋ฐ˜์˜**, ๋ฐ์ดํ„ฐ ๋ถ€์กฑ ์‹œ ํ†ต๊ณผ. โ‘ข**์ƒ๋Œ€๊ฐ•๋„**ใ€”`rel_strength`=์ข…๋ชฉโˆ’์ง€์ˆ˜ `REL_STRENGTH_DAYS`(20)์ผ ์ˆ˜์ต๋ฅ , engine์ด ์ฃผ์ž…ํ•˜๋Š” **๋ผ์ด๋ธŒ ์ „์šฉ**, ๋ฐฑํ…Œ์ŠคํŠธ None=์ค‘๋ฆฝ, ์ฒดํฌํ‘œ์‹œ๋งŒใ€•). **๋ถ„ํ• ๋งค์ˆ˜ยท์ถ”๊ฒฉ๋งค์ˆ˜**: ๋ชฉํ‘œ๋น„์ค‘์„ `ENTRY_TRANCHES`(๊ธฐ๋ณธ 3)๋กœ ๋‚˜๋ˆ  1/3์”ฉ ์ง„์ž…, ์ง์ „ ์ง„์ž…๊ฐ€+ATRร—`ADD_ATR_MULT` ๋ŒํŒŒ & ์ถ”์„ธ ์ง€์† ์‹œ ๋‹ค์Œ ํŠธ๋žœ์น˜ ์ถ”๊ฐ€๋งค์ˆ˜(ํ‰๋‹จ ๊ฐ€์ค‘ํ‰๊ท , ์†์ ˆ ์œ„๋กœ๋งŒ ๋ž˜์นซ)ยทํŠธ๋ ˆ์ผ๋ง/์ผ๋ถ€์ต์ ˆ ์‹œ์ž‘ ํ›„์—” ์ถ”๊ฐ€ ์ข…๋ฃŒ. ๋งค๋„=์†์ ˆ(max(์ง„์ž…โˆ’ATRร—2, 10์ผ์ €์ ))ยท**๋ถ„ํ• ๋งค๋„**(๋ชฉํ‘œ ๋„๋‹ฌ ์‹œ `SCALE_OUT_FRAC`(๊ธฐ๋ณธ 50%) ์ต์ ˆ ํ›„ ์ž”๋Ÿ‰ ํŠธ๋ ˆ์ผ๋ง(๊ณ ์ โˆ’ATRร—1.5))ยท์ถ”์„ธ์ˆ˜๊ธ‰ ์ดํƒˆ ์‹œ ์ „๋Ÿ‰ ์ฒญ์‚ฐ. ๋ถ€๋ถ„๋งค๋„๋Š” closed/win ๋ฏธ์นด์šดํŠธ(์ „๋Ÿ‰ ์ฒญ์‚ฐ ์‹œ๋งŒ ์นด์šดํŠธ). ๊ฒฐ์ •๋ก ์ (LLM ๋ฏธ๊ฒฝ์œ ). **๊ธฐ์ค€์ง€์ˆ˜ ๋Œ€๋น„(์•ŒํŒŒ)**: ๊ฐ€์ƒ๊ณ„์ขŒ/๋ฐฑํ…Œ์ŠคํŠธ ์ˆ˜์ต๋ฅ ์„ ๊ฐ™์€ ๊ธฐ๊ฐ„ KOSPIยทKOSDAQ '๋งค์ˆ˜ํ›„๋ณด์œ ' ๋Œ€๋น„๋กœ ํ‰๊ฐ€(์ˆ˜์ต๋ฅ ๋งŒ์œผ๋ก  ์ง€์ˆ˜ ๋ชป ์ด๊ธฐ๋ฉด ๋ฌด์˜๋ฏธํ•˜๋ฏ€๋กœ). ๋ผ์ด๋ธŒ๋Š” ๊ณ„์ขŒ ์‹œ์ž‘์ผ~์˜ค๋Š˜, ๋ฐฑํ…Œ์ŠคํŠธ๋Š” ์œˆ๋„์šฐ ๊ตฌ๊ฐ„ ๋Œ€๋น„. KPI '์ฝ”์Šคํ”ผ/์ฝ”์Šค๋‹ฅ ๋Œ€๋น„(์•ŒํŒŒ)' + ๋ฐฑํ…Œ์ŠคํŠธยท๋น„๊ต ํƒญ ์•ŒํŒŒ ํ–‰. ๊ฒฝ๊ณผ๊ธฐ๊ฐ„ 0(์‹œ์ž‘ ๋‹น์ผ)ยท์บ์‹œ ๋ถ€์žฌ ์‹œ None('๋ฐ์ดํ„ฐ ์—†์Œ'). ์ƒํƒœ `state/sim/{portfolio.json,trades.jsonl,last_scan.json,index_history.json}`. CLI: `python3 -m sim {scan [--force]|status|report|reset --yes|sweep [frac]|backtest|backfill [--pages N] [--force]|backfill-index [--pages N]|variants {seed N|list|reset|clear}}` (cwd=workspace). launchd `stock.sim-scan`(15๋ถ„)ยท`stock.sim-web`(์ƒ์‹œ). - **์ฒดํฌ๋ฆฌ์ŠคํŠธ ๋ผ๋ฒจ ๋™์ ํ™”**(2026-06-15): `์ถ”์„ธ(N์ผ์„  ์œ„)`ยท`์ •๋ฐฐ์—ด(5>N)`์˜ N์€ **๋ณ€์ด๋ณ„ `config.SMA_LONG`(10/20/40)**์„ ์ฝ์–ด ํ‘œ๊ธฐ. ์ด์ „์—” "20"์œผ๋กœ ํ•˜๋“œ์ฝ”๋”ฉ๋ผ SMA_LONG=10/40 ๋ณ€์ด๋„ "20์ผ์„ "์œผ๋กœ ๊ฑฐ์ง“ ํ‘œ๊ธฐ๋จ(์ฐจํŠธ์˜ 5>20 ์ •๋ฐฐ์—ด๊ณผ ์–ด๊ธ‹๋‚˜ ๋ณด์ด๋˜ ์›์ธ). ํ•˜๋“œ์ฝ”๋”ฉ์ด `signals.py`(buy_signalยทevaluate_holdingยทtrend ๋ณด๊ฐ•)์™€ **`engine.py` ์ถ”์„ธ๋ฏธ์ถฉ์กฑ ๋ถ„๊ธฐ** ๋‘ ๊ณณ์— ์žˆ์—ˆ์Œ. โš ๏ธ ๊ณผ๊ฑฐ `trades.jsonl` ํŒ๋‹จ๊ทผ๊ฑฐ๋Š” ๊ฑฐ๋ž˜ ์‹œ์  baked๋ผ ์˜› ๋ผ๋ฒจ ์ž”์กด(์ƒˆ ๊ฑฐ๋ž˜๋ถ€ํ„ฐ ์ •์ƒ). ๋ผ์ด๋ธŒ ํŒ๋‹จ์€ `judge_view`๊ฐ€ ๋ณ€์ด params ์ ์šฉ ํ›„ ๊ณ„์‚ฐํ•˜๋ฏ€๋กœ ์ฆ‰์‹œ ์ •ํ™•. ์ถ”์„ธ ์ฒดํฌ๋ฆฌ์ŠคํŠธ๋Š” `signals.trend_checks(ind)`๋กœ ์ถ”์ถœํ•ด ๋งค์ˆ˜ํŒ๋‹จยท์ œ์™ธ(SKIP)์นด๋“œ ๊ณต์œ (2026-06-15 โ€” ์ œ์™ธ ์นด๋“œ๊ฐ€ ์ถ”์„ธ/์ •๋ฐฐ์—ด 2๊ฐœ๋งŒ ๋ณด์—ฌ โ‘ โ‘กํ†ต๊ณผ์ธ๋ฐ ์™œ SKIP์ธ์ง€ ํ—ท๊ฐˆ๋ฆฌ๋˜ ๊ฒƒ โ†’ 4์กฐ๊ฑดใ€”ํ˜„์žฌ๊ฐ€>์žฅ๊ธฐ์„ ยท์ •๋ฐฐ์—ดยท์žฅ๊ธฐ์„  ๊ธฐ์šธ๊ธฐยท์ค‘๊ธฐ์ •๋ฐฐ์—ดใ€•+์ƒ๋Œ€๊ฐ•๋„ ์ „๋ถ€ ํ‘œ์‹œ). - **์ฆ‰์‹œ๋งค์ˆ˜ ํ† ๊ธ€ + 40์ผ์„  ์ œ๊ฑฐ**(2026-06-15): `IMMEDIATE_ENTRY`(๊ธฐ๋ณธ 0) โ€” ์ถ”์„ธยท์ •๋ฐฐ์—ดยท์ˆ˜๊ธ‰ยท์• ๋„ ๋‹ค ํ†ต๊ณผํ•œ ์ข…๋ชฉ์ด ๋ŒํŒŒยท๋ˆŒ๋ฆผ๋ชฉ ๋‘˜ ๋‹ค ์•„๋‹ˆ์–ด๋„(=์•ˆ ๋‚ด๋ ค์˜ค๋Š” ์ƒ์Šน ์ข…๋ชฉ) ๊ฐ•์„ธ์žฅยทRSI์ •์ƒ์ด๋ฉด ํ˜„์žฌ๊ฐ€ ์ฆ‰์‹œ ๋งค์ˆ˜(`signals` ๋ˆŒ๋ฆผ๋ชฉ WAIT ์ง์ „ ๋ถ„๊ธฐ, buy_path='immediate'). ๊พธ์ค€ํ•œ ์ƒ์Šน ๋†“์นจ ๋ฐฉ์ง€. 40์ผ์„  ์ถ”์„ธ์„  ์ œ๊ฑฐ(์–ด์ค‘๊ฐ„ยท๊ด€๋ฆฌ์ž๋‹˜ ์ง€์‹œ, ์Šค์œ• GRID๋„ `[10,20,60]`). ๋ณ€์ด: 40 โˆ’72 ํ›„, **๋ฐฑํ…Œ์ŠคํŠธ ๊ฒ€์ฆ ๊ฒฐ๊ณผ ์ฆ‰์‹œ๋งค์ˆ˜๊ฐ€ ๋ช…ํ™•ํžˆ ๋ถˆ๋ฆฌ**(์ „์ฒด๊ธฐ๊ฐ„ 10/20/60 ๋ชจ๋‘ ์ฆ‰์‹œON์ด ์ˆ˜์ต๋ฅ  1/3ยท์Šน๋ฅ  โˆ’10~25%pยทPF ๋ฐ˜ํ† ๋ง‰ยทMDDโ†‘ โ€” ๋ˆŒ๋ฆผ๋ชฉ/๋ŒํŒŒ ๊ธฐ๋‹ค๋ฆผ ๊ทœ์น™์ด ํ•ต์‹ฌ ์•ŒํŒŒ). ๊ทธ๋ž˜์„œ ์ฆ‰์‹œ๋งค์ˆ˜๋Š” ๋ผ์ด๋ธŒ ๊ฐ•์„ธ์žฅ ํ•œ์ • ํ™•์ธ์šฉ **3๊ฐœ๋งŒ**(10/20/60 ์•ˆ์ •ยท๋ณด์ˆ˜๊ฒŒ์ดํŠธ) ์œ ์ง€ โ†’ **์ด 219๊ฐœ**(๋น„์ฆ‰์‹œ216+์ฆ‰์‹œ3). ์ฆ‰์‹œ๋งค์ˆ˜๋Š” GRID ๋ฏธํฌํ•จ์ด๋ผ ๋ฐฑํ…Œ์ŠคํŠธ ๊ธฐ๋ณธ์€ OFF(๊ฒ€์ฆ์€ ์œ„ ์ˆ˜๋™ ๋น„๊ต๋กœ ์ˆ˜ํ–‰). ์›น ์ดˆ๋ก `์ฆ‰์‹œ` ์นฉ(`_immediate_chip_html`)ยท๋“œ๋กญ๋‹ค์šด `[์•ˆ์ • ์ฆ‰์‹œ]`. โš ๏ธ ๊ธฐ์กด 216์€ IMMEDIATE_ENTRY ๊ธฐ๋ณธ 0์ด๋ผ ๋ถˆ๋ณ€. - **๋ฌผํƒ€๊ธฐ(์• ๋ฒ„๋ฆฌ์ง•) ํ† ๊ธ€**(2026-06-16): `AVERAGING_ENTRY`(๊ธฐ๋ณธ 0)ยท`AVERAGING_DROP_PCT`(0.10)ยท`CRASH_DROP_PCT`(0.10). ์ผœ๋ฉด ๋ณด์œ  ์ค‘ ์ง์ „๋งค์ˆ˜๊ฐ€ ๋Œ€๋น„ -10% ํ•˜๋ฝ ์‹œ ์†์ ˆ ๋Œ€์‹  ์ถ”๊ฐ€๋งค์ˆ˜๋กœ ํ‰๋‹จโ†“(์ข…๋ชฉ๋‹น 10% ํ•œ๋„=ENTRY_TRANCHES ๋ถ„ํ• ). ๊ฐ€๋“œ: ๋‹น์ผ -10%โ†“ ๊ธ‰๋ฝ=๋ฌผํƒ€๊ธฐ ๊ธˆ์ง€ยท์†์ ˆ(๊ทธ๋ฆผ #3), ์•ฝ์„ธ์žฅ(market_ok=False)=๋ฌผํƒ€๊ธฐ ๊ธˆ์ง€(๊ทธ๋ฆผ #4). ์ฒซ ๋งค์ˆ˜๋Š” ๊ธฐ์กด ๊ฒ€์ฆ ์ง„์ž…(์ถ”์„ธยท์ •๋ฐฐ์—ด+๋ŒํŒŒ/๋ˆŒ๋ฆผ๋ชฉ) ๊ทธ๋Œ€๋กœ โ€” "์šฐ๋Ÿ‰์ฃผ๋งŒ ๋ฌผํƒ€๊ธฐ". `evaluate_holding(market_ok)` 0๋ฒˆ ๋ถ„๊ธฐ, **add_kind='down'์ด๋ฉด ์†์ ˆ์„ ์„ ๋‚ฎ์•„์ง„ ํ‰๋‹จ ๊ธฐ์ค€์œผ๋กœ ์žฌ์„ค์ •**(์ถ”๊ฒฉ๋งค์ˆ˜ up์€ ์œ„๋กœ๋งŒ ๋ž˜์นซ, engineยทbacktest ๊ณต์šฉ). **๋ฐฑํ…Œ์ŠคํŠธ ๊ฒ€์ฆ: ์ฆ‰์‹œ๋งค์ˆ˜์™€ ๋ฐ˜๋Œ€๋กœ ์œ ๋ฆฌ**(10/20/60 ๋ชจ๋‘ ์ˆ˜์ตยท์Šน๋ฅ โ†‘, MDD ๋น„์Šท โ€” ์šฐ๋Ÿ‰์ฃผ+10%ํ•œ๋„+๊ธ‰๋ฝ์†์ ˆ ๊ฐ€๋“œ ๋•). ๋ผ์ด๋ธŒ ๋ณ€์ด 3๊ฐœ ์ถ”๊ฐ€(v301/302/303=10/20/60 ์•ˆ์ •ยท๋ฌผํƒ€๊ธฐON) โ†’ **223๊ฐœ**. ์›น ๋…ธ๋ž‘ `๋ฌผํƒ€๊ธฐ` ์นฉ(`_avg_chip_html`). โš ๏ธ ๋ฐฑํ…Œ์ŠคํŠธ๋Š” ์‹œ์žฅ์ค‘๋ฆฝ์ด๋ผ ์•ฝ์„ธ์žฅ ๊ฐ€๋“œ ๋ฏธ๋ฐ˜์˜ โ€” ์ง„์งœ ํ•˜๋ฝ์žฅ์€ ๋ผ์ด๋ธŒ ๊ฒ€์ฆ. - **์ถ”์„ธ์„  60์ผ ์ถ”๊ฐ€**(2026-06-15): ์Šค์œ• GRID `SMA_LONG`์— 60 ์ถ”๊ฐ€(`[10,20,40,60]`, 1152โ†’1536์กฐํ•ฉ). 60์ผ์„  ์ƒ์œ„ 12์กฐํ•ฉ ร— ์•ฝ์„ธ๋Œ€์ฒ˜3 ร— ์ง„์ž…๊ฒŒ์ดํŠธ2 = 72๋ณ€์ด ์ถ”๊ฐ€ โ†’ **์ด 288๊ฐœ**(10/20/40/60 ๊ฐ 72). โš ๏ธ 60์ผ์„ ์€ base ์ •๋ฐฐ์—ด(5>60)์ด ์ค‘๊ธฐ๊ฒŒ์ดํŠธ(`SMA_MID=60`, 5>60)์™€ ๋™์ผ โ€” ์ค‘๊ธฐ๊ฒŒ์ดํŠธ๊ฐ€ ์ถ”๊ฐ€ ํ•„ํ„ฐ๋ง ์—†์Œ(๋ฌดํ•ด, ๊ด€๋ฆฌ์ž๋‹˜ ์ธ์ง€ยท์Šน์ธ). โš ๏ธ ์Šค์œ• ์ฒซ ์‹คํ–‰์ด ์›Œ์ปค ์กฐ์šฉํžˆ ์ฃฝ๋Š” ์ผํšŒ์„ฑ deadlock(๋ฉ”์ธ SN 0%CPUยท์›Œ์ปค0) โ†’ kill ํ›„ ์žฌ์‹คํ–‰์œผ๋กœ ์ •์ƒํ™”. ์žฅ์ค‘์—” sim-scan/web๊ณผ CPU ๊ฒฝ์Ÿ์œผ๋กœ 20๋ถ„+ ์†Œ์š”. - **์ถ”์„ธ ๊ฒŒ์ดํŠธ ์™„ํ™” ํ† ๊ธ€**(2026-06-15): `TREND_SLOPE_GATE`ยท`MID_ARRAY_GATE`(๊ธฐ๋ณธ 1=ํ˜„ํ–‰). `trend_ok`์ด `getattr`๋กœ ์ฐธ์กฐ โ€” 0์ด๋ฉด ์žฅ๊ธฐ์„  ์šฐ์ƒํ–ฅ/์ค‘๊ธฐ์ •๋ฐฐ์—ด(5>60) ๊ฒŒ์ดํŠธ ๋ฏธ์ ์šฉ. ๋ณด์ˆ˜์„ฑ(3๊ฑฐ๋ž˜์ผ ๋งค์ˆ˜ 2๊ฑด, ์ถ”์„ธ๋ฏธ์ถฉ์กฑ์ด ๋น„ETF์˜ 93% ์ฐจ๋‹จ) ์™„ํ™” ์‹คํ—˜์šฉ. **์™„ํ™” ๋ณ€์ด**(2026-06-15 ์ตœ์ข…: **๊ธฐ์šธ๊ธฐ ๊ฒŒ์ดํŠธ๋งŒ OFF, ์ค‘๊ธฐ์ •๋ฐฐ์—ด(5>60)์€ ์œ ์ง€** โ€” `TREND_SLOPE_GATE=0, MID_ARRAY_GATE=1`. ๊ด€๋ฆฌ์ž๋‹˜: "์ค‘๊ธฐ์ •๋ฐฐ์—ด์€ ์‚ด๋ ค์•ผ์ง€". 144๊ฐœ ์™„ํ™”๋ณ€์ด ์ „๋ถ€ ์ด ๊ทœ์น™, ๊ณ„์ขŒ ์ดˆ๊ธฐํ™”). ์›น: ๋ณด๋ผ `์™„ํ™”` ์นฉ(`_relax_chip_html`)ยท๋“œ๋กญ๋‹ค์šด `[์•ˆ์ • ์™„ํ™”]`. `trend_checks`๊ฐ€ ๊ฒŒ์ดํŠธ OFF ์กฐ๊ฑด์„ ok=None('๊ฒŒ์ดํŠธ ๋”')๋กœ ํ‘œ๊ธฐ. โš ๏ธ TUNABLE์— ์ถ”๊ฐ€๋ผ ๊ธฐ์กด 108๊ฐœ๋Š” apply_params์—์„œ ๊ธฐ๋ณธ 1(ํ˜„ํ–‰)๋กœ ์ ์šฉ๋ผ ๋ถˆ๋ณ€. - **๋Ÿฐํƒ€์ž„ ํŠœ๋‹**: `config.TUNABLE` 29๊ฐœ ํŒŒ๋ผ๋ฏธํ„ฐ(๋ถ„ํ• ๋งค์ˆ˜ ํšŸ์ˆ˜ยท์ถ”๊ฒฉ ATR ๋ฐฐ์ˆ˜ยท๋ถ„ํ• ๋งค๋„ ์ต์ ˆ ๋น„์œจยท์ข…๋ชฉ๋‹น ๋ฆฌ์Šคํฌ ๋น„์œจยทRSI ๊ณผ์—ด/๊ณผ๋งค๋„ ์ปทยท์‹œ๊ฐ„์†์ ˆ ์ผ์ˆ˜ยท**์•ฝ์„ธ์žฅ ๋งค์ˆ˜๋ชจ๋“œ**ใ€”`BEAR_ENTRY_MODE` 0ํ˜„๊ธˆํ™”/1๋ŒํŒŒ๋งŒ/2๋ˆŒ๋ฆผํ—ˆ์šฉ, signals์—์„œ `market_ok` False์ผ ๋•Œ ๋ถ„๊ธฐ, backtest๋Š” market์ค‘๋ฆฝ์ด๋ผ ๋ฌด์˜ํ–ฅ, ๋ณ‘๋ ฌ๋ณ€์ด๋กœ ๋ผ์ด๋ธŒ ๋น„๊ตใ€• ํฌํ•จ)๋ฅผ `state/sim/params.json`๋กœ ์˜ค๋ฒ„๋ผ์ด๋“œ(์›น ํŠœ๋‹ ํƒญ์—์„œ ์ €์žฅ). config import ์‹œ ๊ธฐ๋ณธ๊ฐ’ ์œ„์— ๋ฎ์–ด์จ ์—”์ง„์ด ๋‹ค์Œ ์Šค์บ”๋ถ€ํ„ฐ ๋ฐ˜์˜. `config._DEFAULTS`๊ฐ€ ์›๋ณธ ๊ธฐ๋ณธ๊ฐ’. `load_params/save_params/reset_params`. - **๋ฐฑํ…Œ์ŠคํŠธยท์Šค์œ•** (`backtest.py`/`sweep.py`): signals.py ๊ทธ๋Œ€๋กœ ์žฌ์‚ฌ์šฉํ•ด ๊ณผ๊ฑฐ ์ผ๋ด‰ ๋˜๊ฐ๊ธฐ(์ง€ํ‘œ t๊นŒ์ง€ยท์ข…๊ฐ€์ฒด๊ฒฐยท์• ๋„ ์ค‘๋ฆฝยท์ˆ˜๊ธ‰์€ flow_history ์‚ฌ์šฉ). `sweep`์€ 9ํŒŒ๋ผ๋ฏธํ„ฐ(SMA_LONGยทRRยทSTOP_ATRยทPULLBACK_ATRยทVOLUME_BREAKOUT + ์‹ ๊ทœ RSI_OVERBOUGHTยทRSI_OVERSOLDยทMAX_HOLD_DAYSยทRISK_PER_TRADE_PCT) **1152์กฐํ•ฉ**์„ ํ•™์Šต/๊ฒ€์ฆ(out-of-sample 0.7) ๋ถ„๋ฆฌ ๋น„๊ต (์• ๋„ยท์‹œ์žฅํ•„ํ„ฐ๋Š” backtest ์ค‘๋ฆฝ์ด๋ผ ์Šค์œ• ์ œ์™ธ) โ†’ `state/sim/backtest_results.json`. **์ฒด๊ฒฐ ํ˜„์‹คํ™”**(2026-06-10): backtest๊ฐ€ ๋‹น์ผ ์ข…๊ฐ€ ํŒ๋‹จโ†’**๋‹ค์Œ๋‚  ์‹œ๊ฐ€ ์ฒด๊ฒฐ**(pending ์ฃผ๋ฌธ ํ, look-ahead ์ œ๊ฑฐ) + `BT_SLIPPAGE` 0.2%(๋งค์ˆ˜ ๋น„์‹ธ๊ฒŒ/๋งค๋„ ์‹ธ๊ฒŒ). ์ฒด๊ฒฐ ๋‚™๊ด€๋ถ„ ~5%p ์ œ๊ฑฐ ํ™•์ธ. ๊ฑฐ๋ž˜ ์—†๋Š” ๋‚  ์ฃผ๋ฌธ์€ ์†Œ๋ฉธ(์‹ ํ˜ธ ์ง€์† ์‹œ ์žฌํ์ž‰). **3๋ถ„ํ•  ๊พธ์ค€ํ•จ ์ˆœ์œ„**(2026-06-10): ์ „์ฒด๊ธฐ๊ฐ„ 3๋ถ„ํ•  ๊ตฌ๊ฐ„๋ณ„ ์ˆ˜์ต(`windows`/`worst_ret`)์„ ์ธก์ •, ์ˆœ์œ„ 1์ˆœ์œ„=์ตœ์•…๊ตฌ๊ฐ„ ์ˆ˜์ต(ํ•œ ๊ตฌ๊ฐ„ ์šด๋นจ ๋ฐฐ์ œ)ยท2์ˆœ์œ„=๊ฒ€์ฆ์ˆ˜์ต. ์›น ํ–‰์— '๊ตฌ๊ฐ„๋ณ„ ๊ฒ€์ฆ(3๋ถ„ํ• )' ํ‘œ์‹œ. **๋ฉ€ํ‹ฐํ”„๋กœ์„ธ์‹ฑ**(2026-06-10): `sweep`์ด ์กฐํ•ฉ์„ ์ฝ”์–ด์— ๋ถ„๋ฐฐ(`get_context('spawn')`, ์›Œ์ปค=์ฝ”์–ดโˆ’2). ์ผ๋ด‰ยท์ˆ˜๊ธ‰์€ `_hist_cached`/`_flow_cached` ํ”„๋กœ์„ธ์Šค ๋ฉ”๋ชจ์ด์ฆˆ๋กœ ์ข…๋ชฉ๋‹น sqlite 1ํšŒ๋งŒ ์ฝ์Œ. **44๋ถ„ โ†’ ์•ฝ 5~7๋ถ„**(10์ฝ”์–ด ๊ธฐ์ค€). ๋ฐ์ดํ„ฐ๋Š” ์ด๋ฏธ sqlite ์บ์‹œ ์ „์šฉ(ํ‚ค์›€ API 0ํšŒ) โ€” ๋ณ‘๋ชฉ์€ ๋„คํŠธ์›Œํฌ๊ฐ€ ์•„๋‹ˆ๋ผ ์ง€ํ‘œ ์žฌ๊ณ„์‚ฐ(ํŒŒ์ด์ฌ). spawn์ด๋ผ ์›Œ์ปค๊ฐ€ ๋ฉ”์ธ ์žฌimportํ•˜์ง€๋งŒ `sim/__main__.py` ๊ฐ€๋“œ๋กœ ์•ˆ์ „. โš ๏ธ `GRID` ๋Š˜๋ฆด ๋•Œ ๊ณฑ์…ˆ ํญ๋ฐœ ์ฃผ์˜. โš ๏ธ ์ข…๊ฐ€์ฒด๊ฒฐยทํ˜„ ์›Œ์น˜๋ฆฌ์ŠคํŠธ(์ƒ์กดํŽธํ–ฅ)๋ผ ์ ˆ๋Œ€์ˆ˜์ต ์•„๋‹Œ ์ƒ๋Œ€์ˆœ์œ„๋กœ๋งŒ ํ•ด์„. 2026-06-09 ์Šค์œ•: ํ•ต์‹ฌ ๋ ˆ๋ฒ„๋Š” `VOLUME_BREAKOUT=1.3`(๊ฑฐ๋ž˜๋Ÿ‰ ๋ฌธํ„ฑ ๋‚ฎ์ถค, ์ค‘์•™ +19%) โ€” ์‹ ๊ทœ 4์ข…์€ ๊ฐ•์„ธ ๊ฒ€์ฆ์ฐฝ์—์„  ๋ฏธ๋ฏธ(RSIยท์‹œ๊ฐ„์†์ ˆ=ํ•˜๋ฝ์žฅ ๋ณดํ—˜). ์ ์šฉ ๊ท ํ˜•๊ฐ’ params.json ์ €์žฅ(RISK 0.01 ๋ณด์ˆ˜ ์œ ์ง€, 0.02 ๊ณ ์ˆ˜์ต์€ ๊ฐ•์„ธ์žฅ ๋ ˆ๋ฒ„๋ฆฌ์ง€๋ผ ์ฑ„ํƒ X). - **์ˆ˜๊ธ‰ ๋ฐฑํ•„** (`backfill_flow.py`): ka10059 ์—ฐ์†์กฐํšŒ๋กœ ์ข…๋ชฉ๋ณ„ ํˆฌ์ž์ž ์ˆœ๋งค์ˆ˜ ๋‹ค๋…„์น˜(๊ธฐ๋ณธ 6ํŽ˜์ด์ง€โ‰ˆ2.4๋…„) โ†’ `state/sim/flow_history.sqlite`(code,date,foreign_net,inst_net,indiv_net ์ฒœ์ฃผ). idempotentยทrate limit ํŽ˜์ด์‹ฑ+429 ๋ฐฑ์˜คํ”„. backtest๊ฐ€ ์ด DB๋กœ ์ˆ˜๊ธ‰(์™ธ/๊ธฐ) ๋ฐ˜์˜ (์—†์œผ๋ฉด ์ค‘๋ฆฝ). 2026-06-08 54์ข…๋ชฉ 3๋งŒํ–‰ 1ํšŒ ์ ์žฌ ์™„๋ฃŒ. - **๋ณ‘๋ ฌ ํŽ˜์ดํผ** (`variants.py` + `engine.scan_all`): ์Šค์œ• ์ƒ์œ„ ํŠœ๋‹๋“ค์„ ๊ฐ์ž ๊ฐ€์ƒ๊ณ„์ขŒ(`state/sim/variants//`)๋กœ ์‹ค์‹œ๊ฐ„ ๋™์‹œ ์šด์˜ โ†’ ๋น„๊ต(`variants_compare.json`). `scan_all`์ด ๋ผ์ด๋ธŒ ๋ฐ์ดํ„ฐ 1ํšŒ ์ˆ˜์ง‘ ํ›„ ๋ฉ”์ธ+๋ชจ๋“  ๋ณ€์ด๋ฅผ ๊ฐ™์€ ์‹œ์„ธ๋กœ ํ‰๊ฐ€(`_gather`+`_run_scan` ๋ถ„๋ฆฌ, Portfolio๊ฐ€ ๊ฒฝ๋กœ ์ธ์ž ๋ฐ›์Œ). ๋ณ€์ด๋Š” ์• ๋„ ๊ฒŒ์ดํŠธ๊นŒ์ง€ ์‹ค๋ฐ˜์˜(๋ฐฑํ…Œ์ŠคํŠธ๊ฐ€ ๋ชป ๋ณด๋Š” ๋ถ€๋ถ„). `variants seed N`์€ backtest_results ์ƒ์œ„ N๊ฐœ ๋“ฑ๋ก. **launchd `sim-scan`์€ ์ด์ œ `scan`โ†’๋‚ด๋ถ€์ ์œผ๋กœ `scan_all` ์‹คํ–‰**(๋ฉ”์ธ+๋ณ€์ด ๋งค ์Šค์บ” ๊ฐฑ์‹ , ํŠธ๋ฆฌ๊ฑฐยท๋ช…๋ น ๋™์ผ). - **์›น 3๋ฉ”์ธํƒญ**(sim_web โ€” **์ „๋žต/๊ด€์‹ฌ์ข…๋ชฉ/์‹œ์žฅ** ์ˆœ, ๊ธฐ๋ณธ=์ „๋žตยท๋น„๊ต. **๊ธฐ์ค€์ „๋žต(M) ํ์ง€**(2026-06-10): scan_all์˜ ๋ฉ”์ธ ํŒจ์Šค๋Š” `execute=False` ํŒ๋‹จ ์ „์šฉ(last_scan=ํ™”๋ฉดยท์ƒํƒœ์ ์šฉ, ๋ฉ”์ธ ๊ณ„์ขŒ ๋งค๋งค ๋™๊ฒฐ), ์‹ค๋งค๋งคยท๋น„๊ต๋Š” ๋ณ€์ด 36๊ฐœ๋งŒ. `sync_label_tops` ๋ฉ”์ธ ์ œ์™ธ ๊ทœ์น™ ์‚ญ์ œ(์œ ํ˜•๋ณ„ 1์œ„ ์ „๋ถ€ ๋ณ€์ด). ๋น„๊ตํƒญ ํ–‰๋งˆ๋‹ค **๋งˆํ‚น ์•„์ด์ฝ˜ ํ”ผ์ปค**(2026-06-10 โ˜†ํ† ๊ธ€โ†’6์ข… ์•„์ด์ฝ˜ โญ๐Ÿ”ฅ๐Ÿ’Ž๐ŸŽฏ๐Ÿ‘€๐Ÿš€ ์„ ํƒ, `FAV_ICONS`/`favorites.json`์€ `{์•„์ด์ฝ˜: vid}` โ€” **์•„์ด์ฝ˜ ํ•˜๋‚˜๋‹น ์ „๋žต 1๊ฐœ**(๋‹ค๋ฅธ ์ „๋žต์— ์“ฐ๋ฉด ์ด๋™)ยท์ „๋žต๋‹น ์•„์ด์ฝ˜ 1๊ฐœ. ์นฉ ํด๋ฆญโ†’๋ฐ”ํ…€์‹œํŠธ ํ”ผ์ปคโ†’`POST /fav_set`(fetch). ๊ตฌ๋ฒ„์ „ list๋Š” ์ž๋™ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜), ๊ด€์‹ฌ์ข…๋ชฉ ํƒญ ๊ธฐ๋ณธ ์‹œ๊ฐ = ์ฒซ ๋งˆํ‚น(FAV_ICONS ์ˆœ) โ†’ ์—†์œผ๋ฉด 1์œ„ ๋ณ€์ด. **์•ฝ์„ธ๋ชจ๋“œ ๋‹จ์–ด ์นฉ**(2026-06-10): ๋น„๊ต ํ–‰ vid ์˜† + ๋“œ๋กญ๋‹ค์šด + ํŽผ์นจ body '์•ฝ์„ธ์žฅ๋Œ€์ฒ˜' ํ–‰์— ํšŒํ”ผ(0 ํ˜„๊ธˆํ™”)/์•ˆ์ •(1 ๋ŒํŒŒ๋งŒยท๊ธฐ๋ณธ, 2026-06-11 '๋ŒํŒŒ'โ†’'์•ˆ์ •' ๊ฐœ๋ช… โ€” ์ ๊ทน๊ณผ ํ˜ผ๋™)/์ ๊ทน(2 ๋ˆŒ๋ฆผํ—ˆ์šฉ) ์ƒ‰ ์นฉ(`_BEAR_WORD`/`_bear_chip_html`, ํด๋ฆญ ์‹œ ์„ค๋ช… ํ† ์ŠคํŠธ. ์•„์ด์ฝ˜โ†’๋‹จ์–ด๋Š” ๊ด€๋ฆฌ์ž๋‹˜ ์š”์ฒญ). **์ „๋žต ์ด๋ฆ„ = 4์นดํ…Œ๊ณ ๋ฆฌ ๋‘๊ธ€์ž**(2026-06-15 `_cat_name`/`_cat_labels` โ€” ์ถ”์„ธใ€”๋ฏผ๊ฐ10/ํ‘œ์ค€20/๋‘”๊ฐ40/์žฅ๊ธฐ60ใ€•ยท์ง„์ž…ใ€”์ ๊ทน volโ‰ค1.5/์‹ ์ค‘ใ€•ยท๋งค๋„ใ€”ํ•œ๋ฐฉ RRโ‰ฅ2.5/๊ท ํ˜•/๋‹จํƒ€ RRโ‰ค1.5ใ€•ยท๋ฒ ํŒ…ใ€”์ง‘์ค‘ riskโ‰ฅ2%/๋ถ„์‚ฐใ€•. ์˜ˆ 'ํ‘œ์ค€ยท์ ๊ทนยท๊ท ํ˜•ยท๋ถ„์‚ฐ'). ๋น„๊ต ํ–‰ยท๋“œ๋กญ๋‹ค์šดยท์ƒ์„ธ ํ—ค๋”์— ์ ์šฉ. ํŽผ์นจ/์ƒ์„ธ์— **`_cat_detail_html`** 4์š”์†Œ ํ’€์ด(๋ผ๋ฒจ+์‹ค์ œ๊ฐ’+์‰ฌ์šด์„ค๋ช…). ๊ธด ๋ฌธ์žฅํ˜• `_market_fit_summary`(์ƒ์Šน์žฅ์— ๊ฐ•ํ•œโ€ฆ)๋Š” '์‹œ์žฅ์ ํ•ฉ' ํ–‰ โ“˜๋กœ ์œ ์ง€. **bt๋งค์นญ์€ `_btkey`(swept_params๋งŒ)** โ€” BEAR_ENTRY_MODE ๋“ฑ ๋ฐฑํ…Œ์ŠคํŠธ ์ค‘๋ฆฝ ํ‚ค๊ฐ€ params์— ์žˆ์–ด๋„ ๊ฐ™์€ btํ–‰์— ๋งค์นญ(๋ชจ๋“œ 3ํ˜•์ œ๋Š” bt์ˆœ์œ„ ๊ณต์œ , ๋ฐฑํ…Œ์ŠคํŠธ ํƒญ์€ 36์ข…๋งŒ ํ‘œ์‹œ๊ฐ€ ์ •์ƒ). ํ—ค๋” ์ƒํƒœ์  ์ž์‚ฐ์ค„์€ '์ „๋žต N๊ฐœ ยท ํ‰๊ท /1์œ„ ์ˆ˜์ต๋ฅ '. 2026-06-10 ๋‚ด๊ณ„์ขŒ ํƒญ ์‚ญ์ œใ€”๊ณ„์ขŒ ์ •๋ณด๋Š” ๋น„๊ตํƒญ ๋ฉ”์ธ ํ–‰์œผ๋กœใ€•ยทํŠœ๋‹ ๋ณด์กฐํƒญ ์‚ญ์ œใ€”params ๋ณ€๊ฒฝ์€ ๋ฐฑํ…Œ์ŠคํŠธ "์ด ํŠœ๋‹ ์ ์šฉ"์œผ๋กœ๋งŒ, `/save_params` ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ๋„ s=btใ€•. ํƒญ ๋ผ์šฐํŒ… `?t=`+๋ณด์กฐํƒญ `?s=`, ๋ ˆ๊ฑฐ์‹œ t=acct/tuneโ†’lab): ํ—ค๋” ํƒ€์ดํ‹€ ์˜† **์‹œ๋ฎฌ ์ƒํƒœ์ **(`_engine_status`โ†’`#health` ์ : ๐ŸŸข ์žฅ์ค‘ ๊ฐ€๋™(์ตœ๊ทผ ์Šค์บ” โ‰ค12๋ถ„)ยท๐ŸŸก ์žฅ์™ธ ๋Œ€๊ธฐยท๐Ÿ”ด ์žฅ์ค‘ ๋ฉˆ์ถค ์˜์‹ฌ, ํด๋ฆญ ์‹œ ์ƒํƒœ ํ† ์ŠคํŠธ). **๊ด€์‹ฌ์ข…๋ชฉ**(์ข…๋ชฉ๋ณ„ ์‹ ํ˜ธ ์ฒดํฌ๋ฆฌ์ŠคํŠธ + ๊ฐ ํ‰๊ฐ€ํ•ญ๋ชฉ **โ“˜ ๋ฒ„ํŠผ โ†’ ์‰ฌ์šด ์„ค๋ช… ํ† ์ŠคํŠธ**ใ€”`_CHK_HELP`/`_chk_key`/`_CHK_HELP_JS`, ๋ฐ”ํ…€์‹œํŠธ `#chk-toast`, ์—ด๋ ค์žˆ์œผ๋ฉด ์ž๋™์ƒˆ๋กœ๊ณ ์นจ ๋ฉˆ์ถคใ€• + ์ƒ๋‹จ **์ข…๋ชฉ ์ถ”๊ฐ€ ํผ**ใ€”์ฝ”๋“œ/์ด๋ฆ„ใ€• + ์นด๋“œ๋ณ„ **โœ• ์‚ญ์ œ**ใ€”์ˆ˜๋™๋งŒ, ๋ณด์œ  ์ค‘์ด๋ฉด ์ฒญ์‚ฐ ์ถ”์ ใ€• + origin ๋ผ๋ฒจใ€”์›Œ์น˜/๊ด€์‹ฌ/๋ณด์œ /์ˆ˜๋™ใ€• + ๋ฏธ์Šค์บ”๋ถ„ '์Šค์บ” ๋Œ€๊ธฐ' ํ‘œ์‹œ) ยท **์‹œ์žฅ**(์ง€์ˆ˜ยทADRยท์ƒ์Šนํ•˜๋ฝยทํˆฌ์ž์ž ์ˆœ๋งค์ˆ˜ โ€” **ํ•ญ์ƒ ๋„ค์ด๋ฒ„ m.stock ์‹ค์‹œ๊ฐ„**ใ€”`_get_live_market` 60s ์บ์‹œ, `market_indicators_sync.fetch_market` ์žฌ์‚ฌ์šฉ. ๋„ค์ด๋ฒ„๊ฐ€ ์žฅ ๋งˆ๊ฐ ํ›„์—๋„ ๋‹น์ผ ์ตœ์ข…๊ฐ’ ์ œ๊ณตํ•˜๋ฏ€๋กœ ์„ธ์…˜ ๋ฌด๊ด€ ์ตœ์‹  ์‚ฌ์šฉใ€•, **์กฐํšŒ ์‹คํŒจ ์‹œ์—๋งŒ** `market_indicators_history.jsonl` EOD ํด๋ฐฑ. note๋Š” ์žฅ์ค‘='์žฅ์ค‘ ์‹ค์‹œ๊ฐ„'ยท์žฅ์™ธ='์ง์ „ ์žฅ ๋งˆ๊ฐ ๊ธฐ์ค€'. 2026-06-09 ์ดˆ๊ธฐ์—” ์žฅ์ค‘๋งŒ ์‹ค์‹œ๊ฐ„์ด๋ผ ๋งˆ๊ฐ ํ›„ ์–ด์ œ EOD๋ฅผ ๋ณด์ด๋˜ ๋นˆํ‹ˆ์„ ํ•ญ์ƒ-์‹ค์‹œ๊ฐ„์œผ๋กœ ์ˆ˜์ •) ยท **์ „๋žต**(2026-06-11 ๋ณด์กฐํƒญ ๋ฒ„ํŠผ ์ œ๊ฑฐ โ€” ๊ธฐ๋ณธ=๋น„๊ต๋งŒ ํ‘œ์‹œ, ๋ฐฑํ…Œ์ŠคํŠธ๋Š” ๋น„๊ต ํƒ€์ดํ‹€ ์šฐ์ธก **[๐Ÿ“Š ๋ชจ์˜๊ฒฐ๊ณผ๋ณด๊ธฐ]** ๋ผ๋ฒจ(๋ผ๋””์˜ค `sub-bt` ํ† ๊ธ€)๋กœ ์ง„์ž…ยทbt ํŒจ๋„ ์ƒ๋‹จ [โ† ๋น„๊ต๋กœ]๋กœ ๋ณต๊ท€. ๊ทธ ์˜† **[๐Ÿ“‹ ๊ฑฐ๋ž˜๋ชฉ๋ก]**(`sub-day`/`_day_trades_panel(sel_date)` โ€” ์ „ ์ „๋žต ๊ฑฐ๋ž˜๋ฅผ **๋‹ฌ๋ ฅํ˜• ๋‚ ์งœ ์„ ํƒ**(`_DAY_CAL_JS` โ€” ๊ฑฐ๋ž˜์ผ๋งŒ ๋ฐ๊ฒŒยทํด๋ฆญ๊ฐ€๋Šฅ, ๋น„๊ฑฐ๋ž˜์ผ ์–ด๋‘ก๊ฒŒ, ์›” ์ด๋™ JS ํด๋ผ์ด์–ธํŠธใ€”๋ฒ”์œ„ ๋ฐ– โ€นโ€บdisabledใ€•, ์˜ค๋Š˜ ๊ฐ•์กฐ. ์ปดํŒฉํŠธ max-width 300px. ๋‚ ์งœ ํด๋ฆญ ์‹œ **๋‹ฌ๋ ฅ ์•ˆ ๋‹ซ๊ณ  fetch๋กœ #day-rowsยท#day-subยท๋ผ๋ฒจ๋งŒ ๊ฐฑ์‹ **ใ€”history.replaceState๋กœ `?d=` ๋ณด์กดใ€•, ๋ณ„๋„ [๋‹ซ๊ธฐ] ๋ฒ„ํŠผ. ์ ‘์ด์‹ details, **๊ธฐ๋ณธ=์˜ค๋Š˜(๊ฑฐ๋ž˜ ์—†์–ด๋„ ์ž๋™์„ ํƒยทํด๋ฆญ๊ฐ€๋Šฅ, `today-open` ์ ์„  ์…€)**, 2026-06-15. ๋นˆ ๋‚ ๋„ #day-rows ์ปจํ…Œ์ด๋„ˆ ์œ ์ง€ํ•ด fetch ์ „ํ™˜ ์ •์ƒ)์œผ๋กœ **(์ข…๋ชฉ,๋ฐฉํ–ฅ)๋ณ„ ์•„์ดํ…œ**(๊ฐ™์€ ์ข…๋ชฉ ๋งค์ˆ˜ยท๋งค๋„ ๋™์‹œ๋ฉด 2์•„์ดํ…œ ๋ถ„๋ฆฌ, ์š”์•ฝ=์ข…๋ชฉ๋ช…+๐ŸŸข๋งค์ˆ˜/๐Ÿ”ด๋งค๋„ ๋ฐฐ์ง€+์ „๋žต์ˆ˜)์œผ๋กœ ์ง‘๊ณ„: ์ „๋žต์ˆ˜ยท์ „๋žต๋ฒˆํ˜ธ์นฉ(์ƒ์„ธ๋งํฌ)ยท๊ฐ€๊ฒฉ๋Œ€ยทํ‰๊ท ์†์ตยท์‚ฌ์œ . ๋‚ ์งœ๋Š” simURL์ด `&d=`๋กœ ๋ณด์กด). `?s=bt` ๋ผ์šฐํŒ…ยท60s ์ƒˆ๋กœ๊ณ ์นจ ๋ผ๋””์˜ค ๋ณด์กด์€ ์œ ์ง€. ๊ตฌ์„ฑ 2: **๋ฐฑํ…Œ์ŠคํŠธ**ใ€”**์œ ํ˜•๋ณ„(์„ธ๋ถ€ ๋ผ๋ฒจ ~36์ข…) ๋Œ€ํ‘œ ์š”์•ฝ** โ€” 2026-06-10 ๋‹จ์ˆœํ™”: ์‹œ์žฅ ์„ฑ๊ฒฉ๋ณ„ ๊ทธ๋ฃน(์ƒ์Šน์žฅ/์ถ”์„ธ์žฅ/์กฐ์ •์žฅ/์ถœ๋ ์ด๋Š” ์žฅ/๋ณดํ†ต ์žฅ์— ๊ฐ•ํ•œ ์œ ํ˜•) ์•ˆ์— ๊ฐ ์œ ํ˜• 1์œ„๋งŒ ํ‘œ์‹œ(๊พธ์ค€ํ•จ=worst_ret ์ˆœ), ํ–‰=์ œ๋ชฉ+์ตœ์•…ยท๊ฒ€์ฆ์ˆ˜์ต, ํŽผ์น˜๋ฉด ๊ตฌ๊ฐ„๋ณ„ ๊ฒ€์ฆยทMDDยท์Šน๋ฅ ยทPFยท์•ŒํŒŒยทํŒŒ๋ผ๋ฏธํ„ฐยท๐ŸŒ. **๋น„๊ต๊ตฐ ์ถ”๊ฐ€/์ œ๊ฑฐยท์ด ํŠœ๋‹ ์ ์šฉ ๋ฒ„ํŠผ ์ œ๊ฑฐ**(์ฝ๊ธฐ์ „์šฉ) โ€” `variants.sync_label_tops()`๋Š” **์ˆ˜๋™ ์ „์šฉ**(2026-06-10 ์ž๋™ ๋™๊ธฐํ™” ๋” โ€” sweep์€ ๊ฒฐ๊ณผ ํŒŒ์ผ๋งŒ ๊ฐฑ์‹ , ๋น„๊ต๊ตฐ ๋ณ€๊ฒฝ์€ ๊ด€๋ฆฌ์ž๋‹˜ ๋ช…์‹œ ์š”์ฒญ ์‹œ `python3 -m sim variants sync` ๋˜๋Š” ์ฝ”๋””๊ฐ€ ์ˆ˜๋™ ๋“ฑ๋ก)(๊ฐ™์€ params ๋ณ€์ด๋Š” ๊ณ„์ขŒ ์œ ์ง€ยท์‹ ๊ทœ ์ถ”๊ฐ€ยทํƒˆ๋ฝ ์‚ญ์ œ, ๋ฉ”์ธ ์กฐํ•ฉ ์ œ์™ธ). ๋ฉ”์ธ ๋ณ€๊ฒฝ์€ ์ฝ”๋””/CLI๋กœ๋งŒ. + **'โ†ป ๋‹ค์‹œ ๊ณ„์‚ฐ'**ใ€”๋ฐฑ๊ทธ๋ผ์šด๋“œ sweep โ€” ๊ฒฐ๊ณผ ํŒŒ์ผ๋งŒ ๊ฐฑ์‹ , ๋น„๊ต๊ตฐ์€ ๋ถˆ๋ณ€ใ€•ใ€•/**๋น„๊ต**ใ€”๋ณ‘๋ ฌ ๋ณ€์ด ์‹ค์‹œ๊ฐ„ ์„ฑ์ , ๋ณ€์ด๋ณ„ ์„ฑ์ ์ดˆ๊ธฐํ™”/์‚ญ์ œ + **์ „์ฒด ์‚ญ์ œ(๋ฉ”์ธ ์ œ์™ธ)** `/variants_clear_all`โ†’`vmod.clear()`. ํŽผ์นจ body ์ฒซ ํ–‰=**์œ ํ˜•**(๊ธด ๋ฌธ์žฅํ˜•+โ“˜โ†’๐ŸŒ ์‹œ์žฅ์ ํ•ฉ ํ† ์ŠคํŠธ, 2026-06-10 ํ•˜๋‹จ ๐ŸŒ ๋ฒ„ํŠผ ๋Œ€์ฒด)โ†’๋‘˜์งธ ํ–‰ **์•ฝ์„ธ์žฅ๋Œ€์ฒ˜**(`๋ŒํŒŒ (๊ธฐ๋ณธ)` ๋ชจ๋“œ๋ช…๋งŒ+โ“˜ ํ† ์ŠคํŠธ). bt ๋“ฑ๋ก๊ทผ๊ฑฐ ํ–‰์€ **๋ชจ์˜ํ‰๊ฐ€**๋กœ ๊ฐœ๋ช…(1ํ–‰ `N์œ„/36`+2ํ–‰ ์ตœ์•…๊ตฌ๊ฐ„ยท๊ฒ€์ฆ, ๋ชจ๋“œ 3ํ˜•์ œ๋Š” `_btkey`๋กœ ๊ฐ™์€ btํ–‰ ๊ณต์œ ). **์ „๋žต ์ƒ์„ธ ํŽ˜์ด์ง€**(2026-06-11): ํ–‰ ํŽผ์นจ [๐Ÿ“ˆ ์ž์„ธํžˆ๋ณด๊ธฐ] โ†’ `GET /strategy?id=vN` ๋…๋ฆฝ ํŽ˜์ด์ง€ โ€” ์ผ๋ณ„ ์ˆ˜์ต๋ฅ  SVG ์ฐจํŠธ(`equity_history` id+ph ๋งค์นญ, KOSPI ๊ฐ™์€ ๊ตฌ๊ฐ„ ์ ์„  ์˜ค๋ฒ„๋ ˆ์ด) + ๊ฒฐ์ •๋ก  ์ข…ํ•ฉ ์ฝ”๋ฉ˜ํŠธ(์ˆœ์œ„ยท์•ŒํŒŒยท๊ณผ์ตœ์  ๊ฒฝ๊ณ ) + ํ˜„์žฌ ์„ฑ์ ยท๋ชจ์˜ํ‰๊ฐ€ยท์ „๋žต ์„ฑ๊ฒฉยท์•ฝ์„ธ์žฅ๋Œ€์ฒ˜ยทํŒŒ๋ผ๋ฏธํ„ฐ ํ‘œ(`_TUNE_HELP` ๋ผ๋ฒจ)ยท๋ณด์œ /๊ด€์‹ฌ/๊ฑฐ๋ž˜. ํ‰๊ฐ€์ˆœ ์ •๋ ฌ์€ ๊ณ ์œ ๋ฒˆํ˜ธ ์˜ค๋ฆ„์ฐจ์ˆœ(#1โ†’#108). ํ–‰ ํ‘œ๊ธฐ(2026-06-10): **์ˆœ์œ„ ๋ฐฐ์ง€ `N์œ„`๊ฐ€ ์•ž, ๊ณ ์œ ๋ฒˆํ˜ธ๋Š” `#N`**(`_vid_disp` โ€” 'v37'โ†’'#37' ํ‘œ์‹œ ์ „์šฉ, ๋‚ด๋ถ€ idยทURL์€ raw. ๋“œ๋กญ๋‹ค์šดยท๐Ÿ‘ํ† ์ŠคํŠธยท์‚ฌ์œ  ๋ผ๋ฒจ ๋™์ผ ํ‘œ๊ธฐ)ใ€•). ๐ŸŒ๋Š” `data-detail` ํ†ตํ•ฉ ํ† ์ŠคํŠธ ํ•ธ๋“ค๋Ÿฌ๋กœ ํ—ค๋” ์ƒํƒœ์ (`#health`)๊ณผ ๊ณต์œ . sticky ํ—ค๋”, ๋‹น๊ฒจ์„œ ์ƒˆ๋กœ๊ณ ์นจ. **์ƒˆ๋กœ๊ณ ์นจ ์ƒํƒœ ๋ณด์กด**(2026-06-10): 60s ์ž๋™์ƒˆ๋กœ๊ณ ์นจ์ด ์ „์ฒด ๋ฆฌ๋กœ๋“œ์ง€๋งŒ ํŽผ์นจ(details open)ยท์Šคํฌ๋กค์„ sessionStorage(`simOpen`/`simScroll`, key=ํŒจ๋„id+summaryํ…์ŠคํŠธ)๋กœ ์ €์žฅยท๋ณต์›ํ•ด ๋ณด๋˜ ํ™”๋ฉด ์œ ์ง€. ์ž…๋ ฅ ์ค‘ยทํ† ์ŠคํŠธ ์—ด๋ฆผ์—” ์ƒˆ๋กœ๊ณ ์นจ ๋ฉˆ์ถค. **ํƒญ ๋ณด์กด**(2026-06-11): ํƒญ/์„œ๋ธŒํƒญ ๋ผ๋””์˜ค ๋ณ€๊ฒฝ ์‹œ URL ์ฆ‰์‹œ ๋™๊ธฐํ™”(`window._simURL`+history.replaceState) โ€” ๋‹น๊ฒจ์„œยท๋ธŒ๋ผ์šฐ์ €ยท๋งˆํ‚น์ €์žฅ ๋“ฑ ๋ชจ๋“  ๋ฆฌ๋กœ๋“œ๊ฐ€ ๋ณด๋˜ ํƒญ์— ์ฐฉ์ง€. HTML ์‘๋‹ต์— `Cache-Control: no-store`(Safari ํœด๋ฆฌ์Šคํ‹ฑ ์บ์‹ฑ์ด ์˜› JS๋ฅผ ์žฌ์‚ฌ์šฉํ•ด ํƒญ ๋ณต์›์ด ์•ˆ ๋จน๋˜ ๋ฌธ์ œ). **๊นœ๋นก์ž„ ์ œ๊ฑฐ**(2026-06-12): ํ™œ์„ฑ ํƒญ/์„œ๋ธŒํƒญ์„ `render_html(tab,sub)`์ด ๋ผ๋””์˜ค `checked`๋กœ ์„œ๋ฒ„์—์„œ ๋ฏธ๋ฆฌ ๋ฐ•์Œ(GET์ด `?t/?s` ํŒŒ์‹ฑ+๋ ˆ๊ฑฐ์‹œ ๋ณด์ •) โ€” ์ด์ „์—” ๊ธฐ๋ณธํƒญ ๋ Œ๋”โ†’JS๊ฐ€ ๋กœ๋“œ ํ›„ ์ „ํ™˜ํ•˜๋ฉฐ ๊นœ๋นก์˜€์Œ. `do_POST`: `/save_params`ยท`/run_sweep`ยท`/variants_{add,reset_one,remove,clear_all}`ยท`/watch_{add,remove}`ยท`/fav_set`(๋งˆํ‚น ์•„์ด์ฝ˜ ์ง€์ •/์ด๋™/ํ•ด์ œ โ†’ `state/sim/favorites.json`) (๊ทธ ์™ธ ์ฝ๊ธฐ์ „์šฉ) - Portfolio data: `memory/portfolio.json` (v2 ์Šคํ‚ค๋งˆ ์ฐธ๊ณ ์šฉ ์Šค๋ƒ…์ƒท, `accounts.{์ผ๋ฐ˜,ISA}.positions`), `state/portfolio_daily_snapshot.json`, `state/kiwoom_tokens/{์ผ๋ฐ˜,ISA}.json`, `state/stock_codes.json`(ํ‚ค์›€ ka10099 lazy ์บ์‹œ), `state/watchlist_alerts.json`(์•Œ๋ฆผ ์ค‘๋ณต ๋ฐฉ์ง€), `state/ipo_calendar_sync.json`, `state/behive_*.json`, `state/fnguide_cache/{code}.json`(FnGuide ํŽ€๋”๋ฉ˜ํ„ธ 12h), `state/wisereport_cache/{code}.json`ยท`{code}_reports.json`(์ปจ์„ผ์„œ์Šค 12hยท๋ฆฌํฌํŠธ 6h), `state/stock_reports//`(๋ถ„์„ ๋ณด๊ณ ์„œ HTML) ## Scheduled Jobs OpenClaw ์ž๋™ํ™”๋Š” ๋‘ ๊ฐˆ๋ž˜๋กœ ๋™์ž‘ํ•œ๋‹ค (๋ชจ๋‘ Asia/Seoul): ### Cron (`cron/jobs.json`, OpenClaw ์—์ด์ „ํŠธ ์„ธ์…˜ โ€” LLM ๊ฒฝ์œ ) - **์˜ค์ „ ๋ธŒ๋ฆฌํ•‘** (main) โ€” Daily 07:55 โ€” ๋‰ด์Šค ๋ธŒ๋ฆฌํ•‘ ๋ฉ”์ผ + ๐Ÿ‡บ๐Ÿ‡ธ ๋ฏธ๊ตญ์ฆ์‹œ ์š”์•ฝ(@futuresnow). ์˜์ƒ์ด 07:55์— ์•„์ง ๋ฏธ๊ฒŒ์‹œ๋ฉด(KST ํ™”~ํ†  ๊ฒŒ์‹œ์˜ˆ์ •์ผ) ๋ฐœ์†ก ๋ณด๋ฅ˜ - **์˜ค์ „ ๋ธŒ๋ฆฌํ•‘ (fallback 0830)** (main) โ€” Daily 08:30 โ€” 07:55์— ๋ฏธ๊ตญ์ฆ์‹œ ์š”์•ฝ ๋ฏธ๊ฒŒ์‹œ๋กœ ๋ณด๋ฅ˜๋œ ๊ฒฝ์šฐ ๋ณด์™„ ๋ฐœ์†ก(`prepare morning --final`). `already_sent` ๊ฐ€๋“œ๋กœ idempotent โ€” 07:55์— ์ •์ƒ ๋ฐœ์†ก๋์œผ๋ฉด ์Šคํ‚ต - **์˜คํ›„ ๋ธŒ๋ฆฌํ•‘** (main) โ€” Daily 19:00 โ€” ๋‰ด์Šค ๋ธŒ๋ฆฌํ•‘ ๋ฉ”์ผ - **๋น„ํ•˜์ด๋ธŒ ์ข…๋ชฉ๋ถ„์„ ์š”์•ฝ** (stock) โ€” Weekdays 07/12/18์‹œ - **์›”๊ฐ„ ๊ฒฐ์‚ฐ** (budget) โ€” ๋งค์›” 1์ผ 05:00 โ€” ์ž์‚ฐ ๋ณ€๋™ ๋ฉ”์ผ + ๊ณจ๋”” ํ…”๋ ˆ๊ทธ๋žจ ### launchd (`~/Library/LaunchAgents/ai.openclaw.*.plist` โ€” LLM ๋ฏธ๊ฒฝ์œ , ์ง์ ‘ ์‹คํ–‰) - **gateway** โ€” ์ƒ์‹œ daemon (ํฌํŠธ 18789) - **claude-remote-control** โ€” on-demand daemon (์ฝ”๋”” ์„ธ์…˜, `claude-code-session` ์Šคํ‚ฌ์ด ๋„์›€) - **stock.behive-web** โ€” ์ƒ์‹œ daemon (์›Œ์น˜๋ฆฌ์ŠคํŠธ ์›น๋ทฐ, Tailscale 18790) - **stock.briefing** โ€” ํ‰์ผ 20:10 โ€” ์ผ์ผ ํฌํŠธํด๋ฆฌ์˜ค ๋ฆฌํฌํŠธ ๋ฉ”์ผ - **stock.briefing-fallback-2030** โ€” ํ‰์ผ 20:30 โ€” ์˜ค๋Š˜ ์Šค๋ƒ…์ƒท ์—†์œผ๋ฉด stock.briefing ์žฌ์‹คํ–‰ (idempotent) - **stock.briefing-fallback-2100** โ€” ํ‰์ผ 21:00 โ€” **๋ฌด์กฐ๊ฑด fresh fetch๋กœ ์Šค๋ƒ…์ƒท ๊ฐฑ์‹ ** (`briefing_fallback.py force` โ†’ ์Šค๋ƒ…์ƒท ์žˆ์œผ๋ฉด `stock_portfolio_report.py run` ๋ฉ”์ผยทํ…”๋ ˆ๊ทธ๋žจ X, ์—†์œผ๋ฉด `send` ํด๋ฐฑ + ์‹คํŒจ ์‹œ ์•Œ๋ฆผ). 20:10 ๋ฐ์ดํ„ฐ ๋ถ€์ •ํ™• ์ผ€์ด์Šค ๋ณด์™„์šฉ - **stock.watchlist-monitor** โ€” ํ‰์ผ 10:00 / 12:00 / 14:00 โ€” ์›Œ์น˜๋ฆฌ์ŠคํŠธ buy/target/stop ์•Œ๋ฆผ (2026-05-12: 15๋ถ„ ๊ฐ„๊ฒฉ โ†’ 3ํšŒ๋กœ ์ถ•์†Œ) - **stock.ipo-calendar-sync** โ€” ๋งค์ฃผ ๊ธˆ์š”์ผ 17:00 โ€” IPO ์ฒญ์•ฝยท์ƒ์žฅ ์ผ์ • ์บ˜๋ฆฐ๋” ๋“ฑ๋ก - **stock.holiday-sync** โ€” ๋งค์ฃผ ์ผ์š”์ผ 03:00 โ€” investing.com KRX ํœด์žฅ์ผ โ†’ `state/market_holidays.json` (behive_web ์ž๋™๊ฐฑ์‹  ํ† ๊ธ€์ด ์ฐธ์กฐ) - **stock.send-balance** โ€” ๋งค์›” 1์ผ 04:30 โ€” ๋ณธ์ธ ์ž”์•ก โ†’ ๊ณจ๋”” inbox (`securities_balance`) - **stock.trade-journal** โ€” ํ‰์ผ 21:00 โ€” EOD ๋ฐ์ดํ„ฐ ๋ˆ„์  ๋ฌถ์Œ. ProgramArguments๋Š” `/bin/sh -c` wrapper๋กœ ์„ธ ๋ช…๋ น sequential ์‹คํ–‰: โ‘ `trade_journal.py collect` (ka10170 4๊ณ„์ขŒ โ†’ `state/trade_journal.jsonl`) โ‘ก`market_indicators_sync.py collect` (๋„ค์ด๋ฒ„ m.stock KOSPI/KOSDAQ ADRยทํˆฌ์ž์ž๋ณ„ ๋งค๋งค โ†’ `state/market_indicators_history.jsonl`) โ‘ข`cd workspace && python3 -m sim.backfill_flow --pages 1 --force` (์ˆ˜๊ธ‰ DB `flow_history.sqlite` ์ผ์ผ ์ฆ๋ถ„ โ€” 2026-06-10 ์ถ”๊ฐ€, 1ํšŒ์„ฑ ๋ฐฑํ•„ ํ›„ staleํ•ด์ ธ ๋ฐฑํ…Œ์ŠคํŠธ ์ˆ˜๊ธ‰๊ฒŒ์ดํŠธ๊ฐ€ ์ค‘๋ฆฝ์œผ๋กœ ๋น„ํ™œ์„ฑ๋˜๋˜ ๋ฌธ์ œ ํ•ด์†Œ. INSERT OR REPLACE idempotent, ํ–‰์ˆ˜๊ธฐ์ค€ skip์ด๋ผ `--force` ํ•„์ˆ˜) โ‘ฃ`python3 -m sim universe all` (2026-06-15 ์ถ”๊ฐ€ โ€” sim ๊ด€์ฐฐ๋ชฉ๋ก ์ž๋™ํŽธ์ž…+์ž๋™์ œ์™ธ. ํ‚ค์›€ ์ˆœ์œ„์ •๋ณด ka90009 ์™ธ์ธยท๊ธฐ๊ด€ ์ˆœ๋งค์ˆ˜ + ka10023 ๊ฑฐ๋ž˜๋Ÿ‰๊ธ‰์ฆ ์ƒ์œ„์—์„œ ETFยทํ•˜๋ฝยท๊ธ‰์ฆ๋ฅ  ์ด์ƒ์น˜ ์ œ์™ธํ•˜๊ณ  ๊ฐ 15๊ฐœยท์ด 120 ์ƒํ•œ ํŽธ์ž…(origin='auto'), origin=autoยท๋ฏธ๋ณด์œ ยท10๊ฑฐ๋ž˜์ผ ๋ฌด์‹ ํ˜ธ๋Š” ์ž๋™ ์ œ์™ธ. ๋ณด์œ ยทwatchยทinterestยทmanual์€ ๋ถˆ๊ฐ€์นจ. ์‹ ํ˜ธ์ถ”์ ์€ scan_all์ด `universe.mark_signals`๋กœ `state/sim/auto_seen.json`์— ๊ธฐ๋ก). ํ•˜๋‚˜ ์‹คํŒจํ•ด๋„ ๋‚˜๋จธ์ง€ ์‹œ๋„. ๋กœ๊ทธ๋Š” `logs/stock-trade-journal.{log,err.log}` ํ•œ ๊ณณ์— ํ•ฉ์ณ์ง. - **stock.sim-scan** โ€” ํ‰์ผ 09:00โ€“15:30 **๋งค 5๋ถ„** (`StartCalendarInterval` 79์—”ํŠธ๋ฆฌ, ์—”์ง„์ด ์žฅ์™ธ/ํœด์žฅ self-skip) โ€” **์ž๋™๋งค๋งค ์‹œ๋ฎฌ(ํŽ˜์ดํผ)** 1ํšŒ ์Šค์บ”. (2026-06-09 15๋ถ„โ†’5๋ถ„ ๋‹จ์ถ•) โš ๏ธ 2026-06-09 `StartInterval` 900s โ†’ `StartCalendarInterval` ์ „ํ™˜: GUI LaunchAgent์˜ StartInterval์€ ์„ธ์…˜ idle/๋””์Šคํ”Œ๋ ˆ์ด sleep ์‹œ timer coalescing์œผ๋กœ ๋ฐœํ™”๊ฐ€ ๋ณด๋ฅ˜(`pended`)๋ผ ์žฅ์ค‘์— ์•ˆ ๋„๋Š” ๋ฌธ์ œ ๋ฐœ๊ฒฌ (calendar ์žก์ธ git-autopush๋Š” ์ƒˆ๋ฒฝ 02:00์—๋„ ์ •์ƒ ๋ฐœํ™”ํ•˜๋Š” ๊ฒŒ ๋น„๊ต ์ฆ๊ฑฐ). ์›”์‹œ๊ฐ„ ๊ธฐ์ค€์ด๋ผ idle ์ง€์—ฐ ์—†์Œ. `python3 -m sim scan` (cwd `agents/stock/workspace`). ๊ฐ€์ƒ์ž๋ณธ 1์–ต, ๊ทœ์น™ ์—”์ง„(LLM ๋ฏธ๊ฒฝ์œ ). universe=๋ˆ„์  ๊ด€์ฐฐ๋ชฉ๋ก(์›Œ์น˜+๊ด€์‹ฌ+๋ณด์œ  ์ž๋™ํŽธ์ž…ยท์ˆ˜๋™์‚ญ์ œ), ๋ฐฉํ–ฅ=์• ๋„ ์•ฝํ•œ๊ฒŒ์ดํŠธ+๊ฐ€์ , ํƒ€์ด๋ฐ=์ˆ˜๊ธ‰ยท๊ธฐ์ˆ . ๊ฒฐ๊ณผ `state/sim/`. ์‹ค์ฃผ๋ฌธ `orders/` ๋ถˆ๊ฐ€์นจ. ์ƒ์„ธ๋Š” ์•„๋ž˜ sim ๋ชจ๋“ˆ ์„น์…˜ยท๋ ˆ์ด MEMORY.md - **stock.sim-web** โ€” ์ƒ์‹œ (`KeepAlive`) โ€” ์‹œ๋ฎฌ ๋Œ€์‹œ๋ณด๋“œ **๋ณ„๋„ ์„œ๋ฒ„ ํฌํŠธ 18792** (behive-web 18790๊ณผ ๋ถ„๋ฆฌ). `python3 -m sim.sim_web serve`. sim state ์ฝ๊ธฐ์ „์šฉ ๋ Œ๋”. `sim.hyowons.net` โ†’ mac:18792 (Synology reverse proxy, **์ˆ˜๋™ ๋“ฑ๋ก ๋Œ€๊ธฐ**). โš ๏ธ 18791์€ node ์ ์œ ๋ผ 18792 ์‚ฌ์šฉ - **git-autopush** โ€” ๋งค์ผ 02:00 โ€” `scripts/git_autopush.sh`: ๋ณ€๊ฒฝ ์žˆ์œผ๋ฉด `git add -A` + ์ž๋™ ์ปค๋ฐ‹ + `git push origin main`. ๋ณ€๊ฒฝ ์—†์œผ๋ฉด skip(๋นˆ ์ปค๋ฐ‹ X). ์ธ์ฆ์€ HTTPS + `credential.helper=store`(`~/.git-credentials`), GUI ํ‚ค์ฒด์ธ ๋ถˆํ•„์š”. ๋กœ๊ทธ `logs/git-autopush.{log,err.log}`. ์›Œํฌ์ŠคํŽ˜์ด์Šค ๋ฒ„์ „๊ด€๋ฆฌ ๋ฐฑ์—…์šฉ (์‹œํฌ๋ฆฟยทsqlite๋Š” .gitignore ์ œ์™ธ๋ผ ๋ณ„๋„ ๋ฐฑ์—… ํ•„์š”) - **budget.whooing-sync** โ€” ๋งค์‹œ 0/15/30/45๋ถ„ โ€” iMessage ๊ฒฐ์ œ๋ฌธ์ž โ†’ ํ›„์ž‰. ๋งค ์‚ฌ์ดํด ๋์— `gahee_reminder.run` ์ถ”๊ฐ€ ํ˜ธ์ถœ (๋งค์›” 25์ผ 10:00 KST ์ดํ›„ ๊ฐ€ํฌ๋‹˜๊ป˜ iMessage ๋ฆฌ๋งˆ์ธ๋” 1ํšŒ ๋ฐœ์‹  โ†’ ๋‹ต์‹  ํด๋ง โ†’ ํ…์ŠคํŠธ๋ฉด ํ›„์ž‰ `๊ฐ€ํฌ์ฃผ๋จธ๋‹ˆ` ์ฐจ์•ก ์ž๋™๋ถ„๊ฐœ, ์ด๋ฏธ์ง€๋ฉด ๊ณจ๋”” ํ…”๋ ˆ๊ทธ๋žจ ์•Œ๋ฆผ). ๋ณ„๋„ plist ์—†์Œ ## Agent Inbox Convention ์—์ด์ „ํŠธ ๊ฐ„ ๋ฐ์ดํ„ฐ hand-off๋Š” **ํŒŒ์ผ ๊ธฐ๋ฐ˜ inbox**๋กœ๋งŒ ํ•œ๋‹ค. LLM-to-LLM ์ž์—ฐ์–ด ํ†ต์‹ ์€ ํ”„๋กฌํ”„ํŠธ ์ธ์ ์…˜ยทํ• ๋ฃจ์‹œ๋„ค์ด์…˜ ์ฆํญ ์œ„ํ—˜์ด ์žˆ์–ด ๊ธˆ์ง€. ### ๋””๋ ‰ํ„ฐ๋ฆฌ ๊ตฌ์กฐ (์ˆ˜์‹ ์ž ์†Œ์œ ) ``` agents//inbox/ โ”œโ”€ incoming/ โ† ์ƒˆ ๋ฉ”์‹œ์ง€ โ”œโ”€ processed/ โ† ์ฒ˜๋ฆฌ ์™„๋ฃŒ ํ›„ ์ด๋™ โ””โ”€ failed/ โ† ์ฒ˜๋ฆฌ ์‹คํŒจ (์Šคํ‚ค๋งˆ ์˜ค๋ฅ˜ยท๋ฏธ๋“ฑ๋ก topic ๋“ฑ) ``` ์ˆ˜์‹ ์ž๋Š” ์ž๊ธฐ inbox๋ฅผ ์ฑ…์ž„์ง„๋‹ค (์ •๊ธฐ ํด๋งยท์ฒญ์†Œยท๊ฐ์‚ฌ). ์†ก์‹ ์ž๋Š” `incoming/`์— ์“ฐ๋Š” ๊ฒƒ๊นŒ์ง€๋งŒ. ### Envelope (๋ถˆ๋ณ€ โ€” v1) ```json { "message_id": "uuid", "from": "stock", "to": "budget", "topic": "securities_balance", "created_at": "2026-04-26T20:10:00+09:00", "schema_version": 1, "payload": { ... } } ``` ํŒŒ์ผ๋ช…: `____.json` (์ •๋ ฌยท๊ฒ€์ƒ‰ ์šฉ์ด) ### ์›์น™ - **payload๋Š” ์ˆœ์ˆ˜ ๋ฐ์ดํ„ฐ** โ€” ์ž์—ฐ์–ด ์ง€์‹œ๋ฌธ ๊ธˆ์ง€ (ํ”„๋กฌํ”„ํŠธ ์ธ์ ์…˜ ์ฐจ๋‹จ) - **idempotency** โ€” ์ˆ˜์‹ ์ž๋Š” `message_id` ์ค‘๋ณต ์ฒ˜๋ฆฌ ์•ˆ ํ•จ - **์ƒˆ topic์€ `INBOX_TOPICS.md`์— ๋“ฑ๋ก ํ•„์ˆ˜** โ€” ๋ฏธ๋“ฑ๋ก topic์€ ์ž๋™ `failed/` - **์‘๋‹ต ํ•„์š” ์‹œ** โ€” ์ˆ˜์‹ ์ž๊ฐ€ ์†ก์‹ ์ž inbox์— ์ƒˆ ๋ฉ”์‹œ์ง€ ์ž‘์„ฑ (์–‘๋ฐฉํ–ฅ ack ๋ฉ”์ปค๋‹ˆ์ฆ˜ ์—†์Œ) - **GC** โ€” `processed/`๋Š” 30์ผ ํ›„ ์ •๋ฆฌ, `failed/`๋Š” ์‚ฌ๋žŒ์ด ๊ฒ€ํ† ํ•ด์„œ ์ˆ˜๋™ ์‚ญ์ œ ์ƒ์„ธํ•œ topic ์Šคํ‚ค๋งˆ์™€ ์šด์˜ ๊ทœ์น™์€ `INBOX_TOPICS.md` ์ฐธ์กฐ. ### Cody Inbox (`agents/cody/inbox/`) ์ฝ”๋””๋Š” OpenClaw ์—์ด์ „ํŠธ๊ฐ€ ์•„๋‹ˆ์ง€๋งŒ ํ•œ ๊ฐ€์ง€ ์˜ˆ์™ธ๋กœ inbox๋ฅผ ๊ฐ€์ง„๋‹ค. **์—์ด์ „ํŠธ๊ฐ€ ์ž์ฒด ๊ฐœ์„ ํ•œ ๊ฒฐ๊ณผ๋ฅผ ์ฝ”๋””์—๊ฒŒ ๊ฒ€์ฆยทํ›„์† ๊ฐœ์„  ์œ„ํƒ**ํ•˜๋Š” ๋‹จ๋ฐฉํ–ฅ ์ฑ„๋„์ด๋‹ค. - **ํ† ํ”ฝ:** `improvement_review` (์Šคํ‚ค๋งˆ๋Š” `INBOX_TOPICS.md`) - **์ž์—ฐ์–ด ํ—ˆ์šฉ ์˜ˆ์™ธ:** payload `summary`/`rationale`/`self_review_notes`/`concerns[].question`์€ ์ž์—ฐ์–ด OK. ๋‹จ "X ํ•ด์ค˜" ๋ฅ˜ ์ง€์‹œ๋ฌธ ๊ธˆ์ง€, ์‚ฌ์‹คยท๊ด€์ฐฐยท์šฐ๋ ค๋งŒ - **์ฒ˜๋ฆฌ ํ๋ฆ„:** 1. ์ฝ”๋”” ์„ธ์…˜ ๊ธฐ๋™ ์‹œ `incoming/` ๊ฐœ์ˆ˜๋งŒ ํ™•์ธ โ†’ 1๊ฐœ ์ด์ƒ์ด๋ฉด ํ•œ ์ค„ ์•Œ๋ฆผ ("๐Ÿ“ฅ ์ฝ”๋”” ์ธ๋ฐ•์Šค์— N๊ฐœ ์ฒ˜๋ฆฌ ๋Œ€๊ธฐ ์ค‘์ž…๋‹ˆ๋‹ค.") 2. **๊ด€๋ฆฌ์ž๋‹˜ ๋ช…์‹œ ์š”์ฒญ ์ „์—” ์ƒ์„ธ ๋ณด๊ณ ยท๊ฒ€์ฆยท๊ฐœ์„  ์‹œ์ž‘ X** โ€” ์ž๋™ ์ฒ˜๋ฆฌ ๊ธˆ์ง€ 3. ๊ด€๋ฆฌ์ž๋‹˜์ด "๊ฒ€์ฆ ํ ํ™•์ธํ•ด์ค˜" ๋“ฑ ํ˜ธ์ถœํ•˜๋ฉด ๊ทธ๋•Œ envelope ์ƒ์„ธ ์š”์•ฝ โ†’ ์šฐ์„ ์ˆœ์œ„ ์œ„์ž„ 4. ์ฝ”๋””๊ฐ€ `changed_paths` ๊ฒ€์ฆ โ†’ ํ•„์š” ์‹œ ์ง์ ‘ ๊ฐœ์„  (์œ„ํ—˜ ์ž‘์—…์€ ๋ณ„๋„ ์ปจํŽŒ) 5. envelope์„ `processed/`๋กœ ์ด๋™, ๊ฐ™์€ basename + `_report.md`์— ๊ฒ€์ฆ ๊ฒฐ๊ณผยทํ›„์† ๊ฐœ์„ ยท์ž”์—ฌ ์œ„ํ—˜ ๊ธฐ๋ก 6. **GC (๊ฐ™์€ ์‹œ์ ):** `processed/`์˜ mtime 7์ผ ์ดˆ๊ณผ ํ•ญ๋ชฉ์„ `trash`๋กœ ์ •๋ฆฌ (envelope JSON + report MD ์ง์œผ๋กœ). `failed/`๋Š” ์†๋Œ€์ง€ ์•Š๋Š”๋‹ค 7. ์Šคํ‚ค๋งˆ ์œ„๋ฐ˜์€ `failed/`๋กœ ์ด๋™ ํ›„ ๊ด€๋ฆฌ์ž๋‹˜์—๊ฒŒ ๋ณด๊ณ  - **ํ—ฌํผ ๋ฏธ์ •:** ์†ก์‹ ์ธก์€ ์—์ด์ „ํŠธ๊ฐ€ ์ง์ ‘ envelope JSON ์ž‘์„ฑ. ํŒจํ„ด ๊ตณ์œผ๋ฉด ์ถ”ํ›„ ์ถ”์ถœ - **ํšŒ์‹  envelope ์—†์Œ:** ๊ฒฐ๊ณผ๋Š” `processed/`์˜ report ํŒŒ์ผ๋กœ๋งŒ ๋‚จ๋Š”๋‹ค. ์†ก์‹  ์—์ด์ „ํŠธ๊ฐ€ ํ›„์† ์‚ฌ์ดํด์—์„œ ์ง์ ‘ ์กฐํšŒ ## Communication Rules - Respond in Korean (ํ•œ๊ธ€) - Use polite speech (์กด๋Œ“๋ง) - Address the owner as ๊ด€๋ฆฌ์ž๋‹˜ - End responses with status on a new line: `[์ง„ํ–‰์ค‘]` or `[๋‹ต๋ณ€์™„๋ฃŒ]` - Keep responses short, action-oriented, result-first - Avoid unnecessary explanation โ€” How > Why - Use `trash` over `rm` for deletions ## Coding Behavior Rules LLM ํ”ํ•œ ์‹ค์ˆ˜๋ฅผ ์ค„์ด๊ธฐ ์œ„ํ•œ ํ–‰๋™ ๊ทœ์น™. ์‚ฌ์†Œํ•œ ์ž‘์—…์€ ํŒ๋‹จ์œผ๋กœ ์ƒ๋žต ๊ฐ€๋Šฅํ•˜์ง€๋งŒ, ๋ถˆํ™•์‹คํ•˜๋ฉด caution ์ชฝ์œผ๋กœ ๊ธฐ์šด๋‹ค. ### 1. ์ฝ”๋”ฉ ์ „์— ์ƒ๊ฐ (Think Before Coding) **๊ฐ€์ •ํ•˜์ง€ ๋ง๊ณ , ํ˜ผ๋™์„ ์ˆจ๊ธฐ์ง€ ๋ง๊ณ , ํŠธ๋ ˆ์ด๋“œ์˜คํ”„๋ฅผ ๋“œ๋Ÿฌ๋‚ผ ๊ฒƒ.** - ๊ฐ€์ •์€ ๋ช…์‹œ์ ์œผ๋กœ ๋งํ•œ๋‹ค. ๋ถˆํ™•์‹คํ•˜๋ฉด ์งˆ๋ฌธํ•œ๋‹ค. - ํ•ด์„์ด ์—ฌ๋Ÿฌ ๊ฐœ๋ฉด ์ „๋ถ€ ์ œ์‹œํ•œ๋‹ค โ€” ์กฐ์šฉํžˆ ํ•˜๋‚˜ ๊ณ ๋ฅด์ง€ ์•Š๋Š”๋‹ค. - ๋” ๋‹จ์ˆœํ•œ ๊ธธ์ด ๋ณด์ด๋ฉด ๋จผ์ € ๋งํ•œ๋‹ค. ์ •๋‹นํ•˜๋ฉด ๋ฐ˜๋ฐ•ํ•œ๋‹ค. - ๋ชจํ˜ธํ•˜๋ฉด ๋ฉˆ์ถ˜๋‹ค. ๋ฌด์—‡์ด ํ—ท๊ฐˆ๋ฆฌ๋Š”์ง€ ์ด๋ฆ„ ๋ถ™์ด๊ณ  ๋ฌป๋Š”๋‹ค. (์„ ํƒ์ง€๋Š” `AskUserQuestion`) ### 2. ๋‹จ์ˆœํ•จ ์šฐ์„  (Simplicity First) **๋ฌธ์ œ๋ฅผ ํ‘ธ๋Š” ์ตœ์†Œ ์ฝ”๋“œ. ์ถ”์ธก์„ฑ ์ฝ”๋“œ ๊ธˆ์ง€.** - ์š”์ฒญ ๋ฒ”์œ„๋ฅผ ๋ฒ—์–ด๋‚œ ๊ธฐ๋Šฅ X - 1ํšŒ์šฉ ์ฝ”๋“œ์˜ ์ถ”์ƒํ™” X - ์š”์ฒญ๋˜์ง€ ์•Š์€ "์œ ์—ฐ์„ฑ"ยท"์„ค์ • ๊ฐ€๋Šฅ์„ฑ" X - ์ผ์–ด๋‚  ์ˆ˜ ์—†๋Š” ์ƒํ™ฉ ๋Œ€๋น„ ์—๋Ÿฌ ํ•ธ๋“ค๋ง X - 200์ค„ ์ง  ๊ฒŒ 50์ค„๋กœ ์ค„๊ฒ ๋‹ค ์‹ถ์œผ๋ฉด ๋‹ค์‹œ ์“ด๋‹ค. ์ž๋ฌธ: "์‹œ๋‹ˆ์–ด ์—”์ง€๋‹ˆ์–ด๊ฐ€ ์ด๊ฑฐ ๊ณผ์„ค๊ณ„๋ผ ํ• ๊นŒ?" ๊ทธ๋ ‡๋‹ค๋ฉด ๋‹จ์ˆœํ™”. ### 3. ์™ธ๊ณผ์  ๋ณ€๊ฒฝ (Surgical Changes) **ํ•„์š”ํ•œ ๊ฒƒ๋งŒ ๊ฑด๋“œ๋ฆฐ๋‹ค. ์ž๊ธฐ๊ฐ€ ๋งŒ๋“  ์ž”์žฌ๋งŒ ์ •๋ฆฌํ•œ๋‹ค.** - ์ธ์ ‘ ์ฝ”๋“œยท์ฃผ์„ยทํฌ๋งท ์ž„์˜ "๊ฐœ์„ " ๊ธˆ์ง€ - ์•ˆ ๋ง๊ฐ€์ง„ ๊ฒƒ ๋ฆฌํŒฉํ† ๋ง ๊ธˆ์ง€ - ๋‹ค๋ฅด๊ฒŒ ํ•˜๊ณ  ์‹ถ์–ด๋„ ๊ธฐ์กด ์Šคํƒ€์ผ ์œ ์ง€ - ๋ฌด๊ด€ํ•œ dead code ๋ฐœ๊ฒฌํ•˜๋ฉด ๋ณด๊ณ ๋งŒ โ€” ์‚ญ์ œ X - ๋ณ€๊ฒฝ ๋•Œ๋ฌธ์— ์ƒ๊ธด import/๋ณ€์ˆ˜/ํ•จ์ˆ˜ orphan์€ ๋ณธ์ธ์ด ์ •๋ฆฌ - ์‚ฌ์ „ ์กด์žฌํ•˜๋˜ dead code๋Š” ์š”์ฒญ ์—†์ด ์‚ญ์ œ X ํ…Œ์ŠคํŠธ: ๋ณ€๊ฒฝ๋œ ๋ชจ๋“  ๋ผ์ธ์€ ๊ด€๋ฆฌ์ž๋‹˜ ์š”์ฒญ์— ์ง๊ฒฐ๋˜์–ด์•ผ ํ•œ๋‹ค. ### 4. ๋ชฉํ‘œ ๊ธฐ๋ฐ˜ ์‹คํ–‰ (Goal-Driven Execution) **์„ฑ๊ณต ๊ธฐ์ค€์„ ์ •์˜ํ•˜๊ณ , ๊ฒ€์ฆ๋  ๋•Œ๊นŒ์ง€ ๋ฃจํ”„.** - "validation ์ถ”๊ฐ€" โ†’ "์ž˜๋ชป๋œ ์ž…๋ ฅ ํ…Œ์ŠคํŠธ ์ž‘์„ฑ โ†’ ํ†ต๊ณผ์‹œํ‚ค๊ธฐ" - "๋ฒ„๊ทธ ๊ณ ์ณ" โ†’ "์žฌํ˜„ ํ…Œ์ŠคํŠธ ์ž‘์„ฑ โ†’ ํ†ต๊ณผ์‹œํ‚ค๊ธฐ" - "X ๋ฆฌํŒฉํ† ๋ง" โ†’ "์ „ํ›„ ํ…Œ์ŠคํŠธ ํ†ต๊ณผ ํ™•์ธ" ๋‹ค๋‹จ๊ณ„ ์ž‘์—…์€ ์งง์€ plan์„ ๋จผ์ € ๋งํ•œ๋‹ค: ``` 1. [๋‹จ๊ณ„] โ†’ ๊ฒ€์ฆ: [ํ™•์ธ] 2. [๋‹จ๊ณ„] โ†’ ๊ฒ€์ฆ: [ํ™•์ธ] ``` ๊ฐ•ํ•œ ์„ฑ๊ณต ๊ธฐ์ค€์€ ๋…๋ฆฝ์  ๋ฃจํ”„๋ฅผ ๊ฐ€๋Šฅ์ผ€ ํ•˜๊ณ , ์•ฝํ•œ ๊ธฐ์ค€("๋™์ž‘ํ•˜๊ฒŒ")์€ ๋Š์ž„์—†๋Š” ๋ช…์„ธ ์š”์ฒญ์„ ๋ถ€๋ฅธ๋‹ค.