# 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 ๋ฏธ์ฒด๊ฒฐ ์กฐํšŒ๋กœ ์ •์ •/์ทจ์†Œ ๋Œ€์ƒ ์ž๋™ ์ถ”์ถœ. kt00016 ๊ธฐ๊ฐ„ ๊ณ„์ขŒ์ˆ˜์ต๋ฅ (`get_period_return`)๋กœ ๊ธฐ๊ฐ„๋‚ด ์ด์ž…๊ธˆยท์ด์ถœ๊ธˆ ์กฐํšŒ โ†’ ํˆฌ์ž์›๊ธˆ ์‚ฐ์ถœ(`investment_principal.py`) - **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` ํ˜ธ์ถœ). **์˜ค์ „ ๋ธŒ๋ฆฌํ•‘์€ `youtube_briefing_digest`๋ฅผ importํ•ด ์ƒ๋‹จ์— ๐ŸŒŽ ํ•ด์™ธ ์ฆ์‹œยท์ด์Šˆ + ๐Ÿ‡ฐ๐Ÿ‡ท ๊ตญ๋‚ด ์ฆ์‹œยท์ด์Šˆ ์นด๋“œ 2๊ฐœ ์‚ฝ์ž…**. `prepare morning [--final]`์ด `us_market`(@futuresnow)ยท`behive_market`(๋น„ํ•˜์ด๋ธŒ ์ฃผ์‹์‹œํ™ฉ) ๋ธ”๋ก(available_todayยทrecap_expected_todayยทvideoยทtranscript)์„ ์‚ฐ์ถœ. โš ๏ธ **๋น„ํ•˜์ด๋ธŒ ์ฃผ์‹์‹œํ™ฉ์ด ๋ฏธ๊ตญ์ฆ์‹œ๋„ ๋‹ค๋ค„ @futuresnow์™€ ํ•ด์™ธ๋ถ€๋ถ„ ๊ฒน์นจ** โ†’ LLM์ด ๋‘ ์ž๋ง‰์„ ํ•ฉ์ณ ์ค‘๋ณต์ œ๊ฑฐ ํ›„ **ํ•ด์™ธ(`overseas_summary`)/๊ตญ๋‚ด(`domestic_summary`)๋กœ ์žฌ์ •๋ฆฌ**(ํ•ด์™ธ=๋‘ ์†Œ์Šค ๋ณ‘ํ•ฉ, ๋ฏธ๊ตญ์ˆ˜์น˜๋Š” @futuresnow ์šฐ์„  / ๊ตญ๋‚ด=๋น„ํ•˜์ด๋ธŒ ๊ตญ๋‚ด๋ถ€๋ถ„๋งŒ). ๋ฐœ์†ก ๊ฒŒ์ดํŠธ `us_send_directive`(proceed/wait): **๋‘˜ ์ค‘ ํ•˜๋‚˜๋ผ๋„ available์ด๋ฉด proceed**, ํ‰์ผ(๋‘˜ ์ค‘ ํ•˜๋‚˜๋ผ๋„ ๊ฒŒ์‹œ์˜ˆ์ •)์ธ๋ฐ ๋‘˜ ๋‹ค ๋ฏธ๊ฒŒ์‹œ๋ฉด wait(๋‹ค์Œ ํด๋ฐฑ ์žฌ์‹œ๋„), ์ฃผ๋ง/`--final`์€ proceed. cron์ด directive==wait๋ฉด ๋ฐœ์†ก ๋ณด๋ฅ˜. ์นด๋“œ ์š”์•ฝ์€ LLM์ด ์นดํ…Œ๊ณ ๋ฆฌ ๊ทธ๋ฃน ๋ฐฐ์—ด(`[{label,items[]}]`)๋กœ ์ž‘์„ฑ, compose์˜ `_video_summary_card`๊ฐ€ `overseas_summary`/`domestic_summary` ์žˆ์„ ๋•Œ๋งŒ ๋ Œ๋”(ํ•ด์™ธ=ํŒŒ๋ž‘ยท๊ตญ๋‚ด=์ดˆ๋ก ํŒ”๋ ˆํŠธ, ๊ทธ๋ฃน ๋ผ๋ฒจ์— ์•ˆ ๋งž๋Š” ๋‚ด์šฉ์€ '๊ธฐํƒ€' ๊ทธ๋ฃน). **์˜คํ›„ ๋ธŒ๋ฆฌํ•‘์€ `behive_close`(๋น„ํ•˜์ด๋ธŒ '๋งˆ๊ฐ์‹œํ™ฉ')๋กœ ๐Ÿ“• ๋งˆ๊ฐ์‹œํ™ฉ ์นด๋“œ**(๊ฐˆ์ƒ‰ ํŒ”๋ ˆํŠธ, `close_summary` ๊ทธ๋ฃน๋ฐฐ์—ด, best-effort) โ€” ์‹œ์žฅ ์ฒดํฌ ๋‹ค์Œยท๋‰ด์Šค ์•ž์— ๋ Œ๋”. **์š”์•ฝยท๋‰ด์Šค ๋ณธ๋ฌธ์˜ `**๊ฐ•์กฐ**` ๋งˆํฌ๋‹ค์šด์€ `_emphasize`๊ฐ€ ๊ตต๊ฒŒ+์ง„ํ•œ ๊ฐ•์กฐ์ƒ‰(๊ธ€์ž์ƒ‰ #c62828, ๋ฐฐ๊ฒฝ ์•ˆ ๊ฑด๋“œ๋ฆผ)์œผ๋กœ ๋ณ€ํ™˜** โ€” LLM์ด ํ•ต์‹ฌ ์ˆ˜์น˜ยทํ‚ค์›Œ๋“œ๋งŒ ์ ˆ์ œํ•ด์„œ ํ‘œ์‹œ(์‹œํ™ฉ ์นด๋“œยท๋‰ด์Šค ์š”์•ฝ ๊ณตํ†ต). **๊ตญ๋‚ด ์ฆ์‹œ์— ํฐ ์˜ํ–ฅ ์ค„ ๋‰ด์Šค๋Š” LLM์ด article์— `kr_impact:true` โ†’ `_article_card`๊ฐ€ ๐Ÿ”ฅ'๊ตญ๋‚ด์ฆ์‹œ ์˜ํ–ฅ' ๋ฐฐ์ง€+๋นจ๊ฐ• ๊ฐ•์กฐ ํ…Œ๋‘๋ฆฌ**๋กœ ๋ถ€๊ฐ(๋ฐ˜๋„์ฒดยทํ™˜์œจยท๋ฏธ ๊ธˆ๋ฆฌยท์™ธ๊ตญ์ธ ์ˆ˜๊ธ‰ยท์ •์ฑ… ๋“ฑ, ๋‚จ๋ฐœ ๊ธˆ์ง€). **ํ•ด์™ธ/๊ตญ๋‚ด/๋งˆ๊ฐ์‹œํ™ฉ ์นด๋“œ ๋ถˆ๋ฆฟ๋„ ๊ตญ๋‚ด ์˜ํ–ฅ ํฐ ํ•ญ๋ชฉ์€ LLM์ด ๋งจ ์•ž์— `๐Ÿ”ฅ ` ์ ‘๋‘ โ†’ `_us_items_html`์ด ๊ฐ•์กฐ ๋ฐฐ๊ฒฝ ๋ฐด๋“œ(#fff7f6)๋กœ ํ‘œ์‹œ**. **์‹œ์žฅ ์ฒดํฌ์˜ ์ฝ”์Šคํ”ผ ์•ผ๊ฐ„์„ ๋ฌผยทMSCI๋Š” ๋น„ํ•˜์ด๋ธŒ ์ž๋ง‰ ์–ธ๊ธ‰๊ฐ’์œผ๋กœ ์˜ค๋ฒ„๋ผ์ด๋“œ** โ€” LLM์ด `kospi_futures_override`/`msci_override`(๋ผ์ธ ๋ฌธ์ž์—ด) ์ž‘์„ฑ ์‹œ build_html_body๊ฐ€ ์Šคํฌ๋žฉ๊ฐ’(investing.com, ์ „๋‚  ๊ฒƒ์ผ ์ˆ˜ ์žˆ์Œ) ๋Œ€์‹  ์‚ฌ์šฉ, ๋ฏธ์ž‘์„ฑยท๋ถˆ๋ช…ํ™•์ด๋ฉด ์Šคํฌ๋žฉ ์œ ์ง€. โš ๏ธ @futuresnow '์˜ค๋Š˜์˜ ์š”์•ฝ'์—” ์ฝ”์Šคํ”ผ/MSCI ์–ธ๊ธ‰ ์—†์Œ(๋ฏธ๊ตญ ์ „์šฉ) โ€” ์ด ๊ฐ’ ์ถœ์ฒ˜๋Š” ๋น„ํ•˜์ด๋ธŒ๋ฟ - `gmail_label_classify.py` โ€” Gmail ๋ผ๋ฒจ ์ž๋™ ๋ถ„๋ฅ˜ (์กฐํšŒ ์ „์šฉ Gmail API, ๊ณ„์ • `mini.snowoyh@gmail.com`). self-sent ๋ฉ”์ผ์„ ์ œ๋ชฉ ๋ฃฐ๋กœ ๋ผ๋ฒจ๋ง: `[์˜ค์ „/์˜คํ›„ ๋ธŒ๋ฆฌํ•‘]`โ†’`๋ธŒ๋ฆฌํ•‘`, `[๋น„ํ•˜์ด๋ธŒ ์ข…๋ชฉ๋ถ„์„]`โ†’`์ข…๋ชฉ๋ถ„์„`(`์ฃผ์‹` ๋ผ๋ฒจ ์ œ๊ฑฐ), `[์ฃผ์‹ ๋ฆฌํฌํŠธ]`โ†’`์ฃผ์‹๋ธŒ๋ฆฌํ•‘`(`์ฃผ์‹` ์ œ๊ฑฐ) + 24h ์ง€๋‚œ ํ…Œ์ŠคํŠธ๋ฉ”์ผ ํœด์ง€ํ†ต ์ด๋™. ๋กœ๊ทธ `state/gmail_label_classify.log`. launchd `ai.openclaw.gmail-label-classify` ๋งค์ผ 01:00(LLM ๋ฏธ๊ฒฝ์œ , 2026-06-26 cron์—์„œ ์ด๊ด€). CLI: `python3 gmail_label_classify.py [--dry-run]` - `youtube_briefing_digest.py` โ€” ์˜ค์ „ ๋ธŒ๋ฆฌํ•‘์šฉ ์œ ํŠœ๋ธŒ ์‹œํ™ฉ ์˜์ƒ ๊ฐ์ง€+์ž๋ง‰ (๋‘ ์ฑ„๋„ ๊ณต์šฉ). `get_us_summary()`=์˜ค์„ ์˜ ๋ฏธ๊ตญ ์ฆ์‹œ ๋ผ์ด๋ธŒ(@futuresnow, `UC_JJ_NhRqPKcIOj5Ko3W_3w`) '์˜ค๋Š˜์˜ ์š”์•ฝ'(๋ฏธ๊ตญ์žฅ ๋งˆ๊ฐ ํ›„ 07:20~08:30 KST, ์˜ˆ์ •=ํ™”~ํ† ) / `get_behive_market_summary()`=๋น„ํ•˜์ด๋ธŒ ํˆฌ์ž์ž๋ฌธ(`UCHTRF5r154igU2gXjudUMzg`) '์ฃผ์‹์‹œํ™ฉ'(์žฅ์ „ ์‹œํ™ฉ, 05:40~06:50 KST, ์˜ˆ์ •=์›”~๊ธˆ) / `get_behive_close_summary()`=๊ฐ™์€ ์ฑ„๋„ '๋งˆ๊ฐ์‹œํ™ฉ'(์žฅ ๋งˆ๊ฐ ํ•ด์„ค, 16:45~18:10 KST, ์˜ˆ์ •=์›”~๊ธˆ, ์˜คํ›„ ๋ธŒ๋ฆฌํ•‘์šฉ). ๊ณตํ†ต: ์ฑ„๋„ ์˜์ƒ ํŽ˜์ด์ง€ `lockupViewModel` ์Šคํฌ๋žฉ(RSS ํ”ผ๋“œ IP 404 ์žฆ์•„ ๋ฏธ์‚ฌ์šฉ)โ†’์ œ๋ชฉํ•„ํ„ฐโ†’์ตœ์‹ ์˜์ƒโ†’watch `publishDate`(PTโ†’KST)๋กœ ์˜ค๋Š˜๊ฒŒ์‹œ ํŒ์ •(์ œ๋ชฉ ๋‚ ์งœ๋Š” ์‹ ๋ขฐX)โ†’์ž๋ง‰. CLI: `python3 youtube_briefing_digest.py {latest|transcript} [us|behive]`. โš ๏ธ ๋ ˆ์ด์˜ `behive_youtube_digest.py`(์ข…๋ชฉ๋ถ„์„โ†’์›Œ์น˜๋ฆฌ์ŠคํŠธ)์™€ ๋ณ„๊ฐœ โ€” ๊ฐ™์€ ์ฑ„๋„์ด์ง€๋งŒ ๋ชฉ์ ยท์†Œ์œ ์ž ๋‹ค๋ฆ„ 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` - `investment_principal.py` โ€” **ํˆฌ์ž์›๊ธˆ(๋ˆ„์  ์ž…๊ธˆโˆ’์ถœ๊ธˆ) ์ง‘๊ณ„**. ์กฐํšŒ ์ „์šฉ. `์ˆœ์ž์‚ฐ โˆ’ ํˆฌ์ž์›๊ธˆ = ์ง„์งœ ์ด์ˆ˜์ต`(์‹คํ˜„+๋ฏธ์‹คํ˜„+๋ฐฐ๋‹น) โ€” kt00018 ํ‰๊ฐ€์†์ต์€ ํ˜„์žฌ ๋ณด์œ ๋ถ„ ๋ฏธ์‹คํ˜„๋งŒ์ด๋ผ ๋ˆ„์  ์‹คํ˜„์†์ตยท๋ฐฐ๋‹น์„ ๋†“์นœ๋‹ค(์‹ค์ธก ๋ณธ์ธ 619๋งŒยท๊ฐ€ํฌ 232๋งŒ ๋ˆ„๋ฝ). ๋ฐ์ดํ„ฐ์›์€ kt00016 ๊ธฐ๊ฐ„๋‚ด์ด์ž…๊ธˆยท์ด์ถœ๊ธˆ(ํ•ฉ๊ณ„) + kt00015 tp='1'(์ž…์ถœ๊ธˆ ํ–‰ ๋‹จ์œ„). โš ๏ธ **๋‘˜ ๋‹ค ์กฐํšŒ๊ธฐ๊ฐ„ 1๋…„ ์ œํ•œ**(kt00016 `505221` / kt00015 `501058`)์ด๋ผ ์—ฐ๋„๋ณ„ ์ฐฝ์œผ๋กœ ์ชผ๊ฐœ ๋ˆ„์  โ€” `_fetch_year`๊ฐ€ ์ฐฝ๋‹น 2์ฝœ. โš ๏ธ **kt00015 tp='1' ์ž…๊ธˆ์—” ๋ฐฐ๋‹น๊ธˆยท์˜ˆํƒ๊ธˆ์ด์šฉ๋ฃŒ(์ด์ž)ยท์ˆ˜์ต๋ถ„๋ฐฐ๊ธˆยท๊ณต๋ชจ์ฃผํ™˜๋ถˆ๊ธˆยท๋‹จ์ฃผ๋งค๊ฐ๋Œ€๊ธˆยท์ฟ ํฐํ˜„๊ธˆ์ง€๊ธ‰์ด ์„ž์—ฌ ์žˆ๋‹ค** โ€” ๊ทธ๋Œ€๋กœ ํ•ฉ์น˜๋ฉด ์›๊ธˆ ๊ณผ๋Œ€๊ณ„์ƒ. **kt00016์˜ ์ด์ž…๊ธˆ/์ด์ถœ๊ธˆ์€ ์ด๊ฑธ ์ด๋ฏธ ์ œ์™ธํ•œ ์ˆœ์ˆ˜ ์™ธ๋ถ€ ์ด์ฒด์•ก**์ด๋‹ค(์ „ ๊ณ„์ขŒยท์—ฐ๋„ ์‹ค์ฆ). ํ–‰ ๋‹จ์œ„ ๋ถ„๋ฅ˜๋Š” `is_principal_flow` = ์ ์š”์— **์ด์ฒด/๋Œ€์ฒด/์ธ์ฆ** ํฌํ•จ ์—ฌ๋ถ€ โ†’ ์ด ๋ถ„๋ฅ˜ ํ•ฉ์ด kt00016 ํ•ฉ๊ณ„์™€ **18๊ฐœ (๊ณ„์ขŒ,์—ฐ๋„) ๊ตฌ๊ฐ„ ์ „๋ถ€ ์˜ค์ฐจ 0**์œผ๋กœ ์ผ์น˜ ํ™•์ธ(์ถ”์ธก ์•„๋‹˜). ์ƒˆ ์ ์š”๊ฐ€ ๋“ฑ์žฅํ•˜๋ฉด ์ฐฝ๋ณ„ `rec=False`๋กœ ๋“œ๋Ÿฌ๋‚˜ ๋ชจ๋‹ฌ์— ๊ฒฝ๊ณ ๊ฐ€ ๋œฌ๋‹ค. โš ๏ธ ์‘๋‹ต์˜ `invt_bsamt`๋Š” "ํˆฌ์ž์›๊ธˆ**ํ‰์ž”**"(๊ธฐ๊ฐ„ ํ‰๊ท ์ž”๊ณ )์ด๋ผ ๋ˆ„์  ์›๊ธˆ์ด ์•„๋‹˜ โ€” ์ด๋ฆ„์ด ๋น„์Šทํ•ด ์˜ค์šฉ ์ฃผ์˜. ํ•ญ๋“ฑ์‹ `์ˆœ์ž์‚ฐ์ดˆ + ์ž…๊ธˆ โˆ’ ์ถœ๊ธˆ + ํ‰๊ฐ€์†์ต = ์ˆœ์ž์‚ฐ๋ง`์ด ์ „ ์—ฐ๋„ยท๊ณ„์ขŒ์—์„œ ์˜ค์ฐจ 0์œผ๋กœ ์„ฑ๋ฆฝ(์ž์ฒด ๊ฒ€์ฆ์šฉ, `show`๊ฐ€ ์ถœ๋ ฅ). ์บ์‹œ `state/investment_principal.json` = `frozen`(์ง€๋‚œ ์—ฐ๋„=ํ™•์ •๊ฐ’, ์žฌ์กฐํšŒ X) + `current`(์˜ฌํ•ด ์ฐฝ, ๊ฐฑ์‹  ๋Œ€์ƒ) + `seen`(๋งˆ์ง€๋ง‰ ๊ฐฑ์‹  ์‹œ์  ๋‹น์ผ ์ž…์ถœ๊ธˆ โ€” ์ด๋ฒคํŠธ ๊ฐ์ง€ ๊ธฐ์ค€). **๋ณ„๋„ ํŠธ๋ฆฌ๊ฑฐ ์—†์Œ** โ€” behive_web ๋ Œ๋” ๊ฒฝ๋กœ๊ฐ€ ์ด๋ฏธ ์กฐํšŒ ์ค‘์ธ kt00015 ๋‹น์ผ ์ž…์ถœ๊ธˆ์ด `seen`๊ณผ ๋‹ค๋ฅผ ๋•Œ๋งŒ ์˜ฌํ•ด ์ฐฝ ์žฌ์กฐํšŒ(๊ณ„์ขŒ๋‹น 1์ฝœ), ์ž…์ถœ๊ธˆ ์—†๋Š” ํ‰์‹œ์—” kt00016 ์ฝœ 0. ์•ˆ์ „๋ง์œผ๋กœ 7์ผ ์ดˆ๊ณผ ์‹œ ๊ฐ•์ œ ๊ฐฑ์‹ . ์บ์‹œ ์—†์œผ๋ฉด `needs_refresh`๊ฐ€ Falseยท`get_principal`์ด None โ†’ ํŽ˜์ด์ง€๋ฅผ 68์ฝœ๋กœ ๋ง‰์ง€ ์•Š๊ณ  KPI 2ํ–‰๋งŒ ์กฐ์šฉํžˆ ์ƒ๋žต. `bootstrap`์€ FLOOR_YEAR(2010)~์˜ฌํ•ด ์ „์ˆ˜ ์กฐํšŒ(4๊ณ„์ขŒร—17๋…„=68์ฝœ โ‰ˆ25์ดˆ, ์กฐ๊ธฐ์ข…๋ฃŒ ์—†์Œ โ€” ํœด๋ฉด ์—ฐ๋„๊ฐ€ ๋ผ์–ด๋„ ์•ž ์—ฐ๋„ ์•ˆ ๋†“์นจ) **1ํšŒ์„ฑ CLI ์ „์šฉ, ๋ Œ๋” ๊ฒฝ๋กœ ํ˜ธ์ถœ ๊ธˆ์ง€**. ์ฃผ์‹ ์ž…์ถœ๊ณ (ํƒ€์‚ฌ๋Œ€์ฒด `termin_tot_inq/outq`)๊ฐ€ ์žˆ์œผ๋ฉด ํ˜„๊ธˆ ๊ธฐ์ค€ ์›๊ธˆ์ด ๊ณผ์†Œ๊ณ„์ƒ โ†’ `qty_flow` ํ”Œ๋ž˜๊ทธ๋กœ KPI์— โš ๏ธ ํ‘œ์‹œ(ํ˜„์žฌ ์ „ ๊ณ„์ขŒ 0). CLI: `python3 scripts/investment_principal.py {bootstrap|refresh|show}` - `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 - `fomc_calendar_sync.py` โ€” ๋ฏธ ์—ฐ์ค€ FOMC ํšŒ์˜ ์ผ์ • โ†’ Google Calendar (`ipo_calendar_sync.py` ๊ตฌ์กฐ ๋ณต์ œ, ์กฐํšŒ+๋“ฑ๋ก ์ „์šฉ). ์ถœ์ฒ˜ `federalreserve.gov/monetarypolicy/fomccalendars.htm`(์ธ์ฆ ๋ถˆํ•„์š”) โ€” `fomc-meeting__month`/`fomc-meeting__date` div ํŒŒ์‹ฑ, ๋‚ ์งœ ๋ `*`=SEP(๊ฒฝ์ œ์ „๋งยท์ ๋„ํ‘œ) ํšŒ์˜. ์ œ๋ชฉ `[FOMC] YYYY-MM ํšŒ์˜`(+` (SEP)`)๋Š” **2026-03-23 ๊ด€๋ฆฌ์ž๋‹˜์ด ์ผ๊ด„ ๋“ฑ๋กํ•œ ๊ธฐ์กด ํ‘œ๊ธฐ๋ฅผ ๊ทธ๋Œ€๋กœ ์Šน๊ณ„** โ€” ๋•๋ถ„์— ๊ธฐ์กด ํ•ญ๋ชฉ์ด ์ค‘๋ณต ์—†์ด ํก์ˆ˜๋จ. `state_key`=์‹œ์ž‘์›” `YYYY-MM`(FOMC๋Š” ํ•œ ๋‹ฌ์— ๋‘ ๋ฒˆ ์•ˆ ์—ด๋ ค ๊ณ ์œ ). **์ด๋ฒคํŠธ ๊ธฐ๊ฐ„ = ํšŒ์˜ ์‹œ์ž‘์ผ(ET) ~ ๋ฐœํ‘œ์ผ(KST)**๋กœ 3์ผ์งœ๋ฆฌ ์ข…์ผ ์ด๋ฒคํŠธ(`cal_start`/`cal_end`). ์„ฑ๋ช… ๋ฐœํ‘œ๋Š” ํšŒ์˜ ๋งˆ์ง€๋ง‰๋‚  `America/New_York` 14:00 = KST ์ต์ผ 03:00(EDT)ยท04:00(EST)์ด๋ผ, ET ํšŒ์˜๋‚ ์งœ๋งŒ ๋„ฃ์œผ๋ฉด **์ •์ž‘ ํ•œ๊ตญ ์žฅ์ด ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜์˜ํ•˜๋Š” ๋‚ ์— ์บ˜๋ฆฐ๋”๊ฐ€ ๋น„์–ด ๋ธŒ๋ฆฌํ•‘ '์˜ค๋Š˜ ์ผ์ •'์—๋„ ์•ˆ ๋œฌ๋‹ค** โ€” ๊ทธ๋ž˜์„œ ๋ฐœํ‘œ์ผ๊นŒ์ง€ ๋ฎ๋Š”๋‹ค(2026-07-29 ๊ด€๋ฆฌ์ž๋‹˜ ์ง€์ ์œผ๋กœ ์ˆ˜์ •, ๊ทธ์ „์—” 2์ผ์งœ๋ฆฌ์˜€์Œ). ์ œ๋ชฉยทdescription์€ ET ํšŒ์˜๋‚ ์งœ ๊ธฐ์ค€ ์œ ์ง€(๋‰ด์Šคยท์‹œํ™ฉ ํ‘œ๊ธฐ์™€ ์ผ์น˜). โš ๏ธ `parse_meetings`์˜ ๋ฏธ๋ž˜ ํŒ์ • ๊ธฐ์ค€๋„ `start_date`๊ฐ€ ์•„๋‹ˆ๋ผ **`cal_end > today`** โ€” ET ํšŒ์˜๊ฐ€ ๋๋‚ฌ์–ด๋„ ํ•œ๊ตญ ๋ฐœํ‘œ์ผ์ด ๋‚จ์•˜์œผ๋ฉด ๊ฐฑ์‹  ๋Œ€์ƒ์ด๋‹ค. โš ๏ธ `--event-color` **๋ฏธ์ง€์ •** โ€” ๊ธฐ์กด colorId 9(๋ธ”๋ฃจ๋ฒ ๋ฆฌ) ๋ณด์กด. ์•ˆ์ „์žฅ์น˜: ์Šคํฌ๋ž˜ํ•‘ ์‹คํŒจ๋กœ ๋ชฉ๋ก์ด ๋น„๋ฉด cleanup ์ „์ฒด ์Šคํ‚ต / ์กฐํšŒยท์‚ญ์ œ ๋ฒ”์œ„๋Š” `์˜ค๋Š˜ ์ดํ›„`๋กœ ํ•œ์ • + **์‚ญ์ œ ๋ฃจํ”„๊ฐ€ `old_start <= today`๋ฅผ ๊ฑด๋„ˆ๋œ€**(์ง„ํ–‰ ์ค‘์ด๊ฑฐ๋‚˜ ์ง€๋‚œ ํšŒ์˜๋Š” ํŒŒ์‹ฑ ๋Œ€์ƒ์—์„œ ๋น ์งˆ ๋ฟ์ธ๋ฐ stale๋กœ ์˜ค์ธ๋ผ ์ง€์›Œ์ง€๋Š” ๊ฑธ ๋ง‰์Œ). CLI: `--list`(ํŒŒ์‹ฑ ๊ฒฐ๊ณผ๋งŒ, gog ๋ฏธํ˜ธ์ถœ โ€” ์ธ์ฆ ์—†๋Š” ํ™˜๊ฒฝ์—์„œ ํŒŒ์„œ ๊ฒ€์ฆ์šฉ) / `--dry-run` / ๋ฌด์ธ์ž=์‹ค๋ฐ˜์˜. ์บ์‹œ `state/fomc_calendar_sync.json` - `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 ์žฌํ™œ์šฉ - `trailing_monitor.py` โ€” **ํŠธ๋ ˆ์ผ๋ง ์Šคํ†ฑ ๊ฐ์‹œ** (2026-07-30). ํ‚ค์›€ REST์— ํŠธ๋ ˆ์ผ๋ง ์ฃผ๋ฌธ TR์ด ์—†์–ด์„œ, ์Šคํ†ฑ์ง€์ •๊ฐ€(`trde_tp=28`) ์ฃผ๋ฌธ์„ ์‹ค์ œ๋กœ ๊ฑธ์–ด๋‘๊ณ  ๊ณ ์  ๊ฐฑ์‹  ์‹œ `kt10002` ์ •์ •(`mdfy_cond_uv`)์œผ๋กœ ์กฐ๊ฑด๋‹จ๊ฐ€๋ฅผ ์˜ฌ๋ ค ๊ตฌํ˜„. **์ฃผ๋ฌธ์ด ํ‚ค์›€ ์„œ๋ฒ„์— ์žˆ์–ด ๊ฐ์‹œ ๋ฃจํ”„๊ฐ€ ์ฃฝ์–ด๋„ ๋งˆ์ง€๋ง‰ ์†์ ˆ์„ ์€ ์‚ด์•„์žˆ๋‹ค** (์ž์ฒด ํด๋ง ๋ฐœ์ฃผ ๋ฐฉ์‹์€ ๋ฃจํ”„๊ฐ€ ์ฃฝ์œผ๋ฉด ์†์ ˆ์ด ํ†ต์งธ๋กœ ์‚ฌ๋ผ์ง โ€” ์ด ์ฐจ์ด๊ฐ€ ์„ค๊ณ„ ์„ ํƒ ์ด์œ ). ์‚ฌ์ดํด๋‹น ํ•˜๋Š” ์ผ: โ‘ `ka10075` ๋ฏธ์ฒด๊ฒฐ ์กฐํšŒ๋กœ ์˜ˆ์•ฝ ์ƒ์กด ํ™•์ธ(๊ณ„์ขŒ๋‹น 1์ฝœ). ์‚ฌ๋ผ์ง€๋ฉด ์ •๋ฆฌ + **์‚ฌ์œ  ๊ตฌ๋ถ„ ์•Œ๋ฆผ** โ€” ๋ฏธ์ฒด๊ฒฐ ์กฐํšŒ๋งŒ์œผ๋กœ๋Š” ์ฒด๊ฒฐยท์ทจ์†Œยท์†Œ๋ฉธ์ด ๊ตฌ๋ถ„๋˜์ง€ ์•Š์•„(์…‹ ๋‹ค ๋ชฉ๋ก์—์„œ ๋น ์ง) ๊ทธ๋•Œ๋งŒ `ka10170` 1์ฝœ ์ถ”๊ฐ€๋กœ ํŒ์ •: โœ…์ฒด๊ฒฐ(๋‹น์ผ ๋งค๋„๊ธฐ๋ก ์žˆ์Œ) / โš ๏ธ์†Œ๋ฉธ(๊ธฐ๋ก ์—†์Œ = ์ฒด๊ฒฐ ์•ˆ ๋จ ํ™•์ •, ์žฌ๋“ฑ๋ก ์•ˆ๋‚ด) / ๐ŸŽฏํŒ์ •๋ถˆ๊ฐ€(์ผ์ง€ ์กฐํšŒ ์‹คํŒจ). โš ๏ธ **์กฐํšŒ ์‹คํŒจ๋ฅผ '์ฒด๊ฒฐ ์•ˆ ๋จ'์œผ๋กœ ๋‹จ์ • ๊ธˆ์ง€** โ€” `_fill_check` ๊ฐ€ (๊ธฐ๋ก, ์„ฑ๊ณต์—ฌ๋ถ€) ํŠœํ”Œ์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ์ด์œ  โ‘ก`ka10095` ์‹œ์„ธ 1์ฝœ โ†’ ๊ณ ์  ๊ฐฑ์‹ ๋ถ„๋งŒ ์ •์ •. ์ฃผ๊ฐ€๊ฐ€ ๊ทธ๋Œ€๋กœยทํ•˜๋ฝ์ด๋ฉด API ์ฝœ 0. โš ๏ธ **`kt10002` ์‘๋‹ต `ord_no`๋Š” ์‹ ๊ทœ ์ฃผ๋ฌธ๋ฒˆํ˜ธ** โ€” `trailing.commit_modify`๊ฐ€ ์ƒํƒœํŒŒ์ผ `ord_no`๋ฅผ ๊ฐฑ์‹ ํ•˜์ง€ ์•Š์œผ๋ฉด ๋‘ ๋ฒˆ์งธ ์ •์ •๋ถ€ํ„ฐ `orig_ord_no`๊ฐ€ ํ‹€๋ ค ์ „๋ถ€ ์‹คํŒจ(์ตœ๋Œ€ ํ•จ์ •). โš ๏ธ **๊ณ ์ ์€ ๋“ฑ๋ก ์‹œ์  ํ˜„์žฌ๊ฐ€์—์„œ ์‹œ์ž‘ํ•ด ํ˜„์žฌ๊ฐ€๋กœ๋งŒ ๊ฐฑ์‹ **ํ•œ๋‹ค โ€” `ka10095`๊ฐ€ ๋‹น์ผ๊ณ ๊ฐ€(`high`)๋„ ์ฃผ์ง€๋งŒ ๋“ฑ๋ก ์ „์— ์ฐํžŒ ๊ณ ๊ฐ€๊นŒ์ง€ ๋ฐ˜์˜๋˜๋ฉด ์†์ ˆ์„ ์ด ํ˜„์žฌ๊ฐ€ ์œ„๋กœ ์˜ฌ๋ผ๊ฐ€ ์ฆ‰์‹œ ๋ฐœ๋™(์˜ˆ: ์˜ค์ „ 15,000โ†’14,000์ผ ๋•Œ 3% ๋“ฑ๋ก ์‹œ ๋‹น์ผ๊ณ ๊ฐ€ ๊ธฐ์ค€ ์กฐ๊ฑด 14,550 > ํ˜„์žฌ๊ฐ€). ๊ฐ™์€ ์ด์œ ๋กœ ์ดˆ๊ธฐ ๊ณ ์  ์„ ํƒ ์˜ต์…˜(52์ฃผ ์ „๊ณ ์ ยท๋งค์ˆ˜ํ›„ ๊ณ ์ )๋„ ์ œ๊ฑฐ๋จ. 1๋ถ„ ๊ฐ„๊ฒฉ์ด๋ผ ๊ทธ ์‚ฌ์ด ์ŠคํŒŒ์ดํฌ๋Š” ๋†“์นœ๋‹ค(์†์ ˆ์„ ์ด ๋œ ์˜ฌ๋ผ๊ฐ€ ์ด์ต ํ™•์ • ํญ์ด ์กฐ๊ธˆ ์ค„์–ด๋“œ๋Š” ๋ฐฉํ–ฅ โ€” ์†์‹ค ์œ„ํ—˜์€ ์•„๋‹˜). โš ๏ธ **์ •๋ฐ€๋„ ๋ณด์™„์€ ํ•˜์ง€ ์•Š๊ธฐ๋กœ ๊ฒฐ๋ก **(2026-07-30 ๊ด€๋ฆฌ์ž๋‹˜ ํŒ๋‹จ): ์ตœ์ € ๋งค๋„๊ฐ€๋กœ ํ•˜ํ•œ์ด ํ†ต์ œ๋˜๋ฏ€๋กœ 1๋ถ„ ํ•ด์ƒ๋„์˜ ๊ณ ์  ๋ˆ„๋ฝ์€ ๊ฐ๋‹น ๋ฒ”์œ„. ๊ฒ€ํ† ํ–ˆ๋˜ ๋‘ ์•ˆ โ€” `entry_day_high`(๋“ฑ๋ก ์‹œ์  ๋‹น์ผ๊ณ ๊ฐ€๋ฅผ ๊ธฐ์ค€์„ ์œผ๋กœ ์ €์žฅํ•ด ๊ทธ๋ณด๋‹ค ํฐ `high`๋งŒ ๋“ฑ๋ก ์ดํ›„ ์‹ ๊ณ ๊ฐ€๋กœ ์ธ์ •. ์ถ”๊ฐ€ ์ฝœ 0์ด์ง€๋งŒ ๊ธฐ์ค€์„  ์•„๋ž˜ ์ŠคํŒŒ์ดํฌ๋Š” ์—ฌ์ „ํžˆ ๋ˆ„๋ฝ) / `realtime_hub` WS ํ‹ฑ ๊ณ ์  ์ถ”์ (์ •ํ™•ํ•˜์ง€๋งŒ ๊ตฌ๋…ยท์žฌ์—ฐ๊ฒฐ ํด๋ฐฑ ํ•„์š”) โ€” **๋‘˜ ๋‹ค ์ฑ„ํƒ ์•ˆ ํ•จ. ๋‹ค์‹œ ์ œ์•ˆํ•˜์ง€ ๋ง ๊ฒƒ.** โš ๏ธ **`fill_watcher`๋ฅผ ๊ฑธ์ง€ ์•Š๋Š”๋‹ค** โ€” ์Šคํ†ฑ ์˜ˆ์•ฝ์€ ์žฅ์ค‘ ๋‚ด๋‚ด ๋ฏธ์ฒด๊ฒฐ์ด ์ •์ƒ์ด๋ผ 30๋ถ„ ๋ฏธ์ฒด๊ฒฐ ์•Œ๋ฆผ์ด ์˜คํƒ. ์ƒ์กดยท์ฒด๊ฒฐ ๊ฐ์‹œ๋Š” ์ด ์Šคํฌ๋ฆฝํŠธ๊ฐ€ ์ง์ ‘. โš ๏ธ **์Šคํ†ฑ์ฃผ๋ฌธ์€ ์žฅ ๋งˆ๊ฐ ํ›„ ์†Œ๋ฉธํ•œ๋‹ค(2026-07-30 ์‹ค์ฆ)** โ€” ์ฒซ ์‹ค์ฃผ๋ฌธ์ด ์ฒด๊ฒฐ ์—†์ด ์‚ฌ๋ผ์ง(๋‹น์ผ ๋งค๋„๊ธฐ๋ก 0ยท๋ณด์œ  ๋ถˆ๋ณ€), ๊ฐ์ง€ 18:21๋กœ 15:30 ์ฆ‰์‹œ๊ฐ€ ์•„๋‹ˆ๋ผ ๋ช‡ ์‹œ๊ฐ„ ๋’ค. **์ž๋™ ์žฌ๋“ฑ๋ก์€ ํ•˜์ง€ ์•Š๋Š”๋‹ค**(๊ด€๋ฆฌ์ž๋‹˜ ๊ฒฐ์ •) โ€” ์•Œ๋ฆผ๋งŒ ๋ณด๋‚ด๊ณ  ์žฌ๋“ฑ๋ก์€ ์ž์‚ฐ์›น์—์„œ ์ˆ˜๋™. ์ •์ • ์ˆ˜๋Ÿ‰์€ ์ €์žฅ qty๊ฐ€ ์•„๋‹Œ **๋ฏธ์ฒด๊ฒฐ ์ž”๋Ÿ‰**(๋ถ€๋ถ„์ฒด๊ฒฐ ๋Œ€์‘). ๋ฏธ์ฒด๊ฒฐ ์กฐํšŒ ์‹คํŒจ ๊ณ„์ขŒ๋Š” ๊ทธ ์‚ฌ์ดํด ํŒ๋‹จ ๋ณด๋ฅ˜(์—†๋‹ค๊ณ  ๋‹จ์ •ํ•˜๋ฉด ์‚ด์•„์žˆ๋Š” ์˜ˆ์•ฝ์„ ์ง€์›€). CLI: `check [--repeat N --gap S] [--force] [--dry-run]` / `list` - `orders/trailing.py` โ€” ํŠธ๋ ˆ์ผ๋ง ์˜ˆ์•ฝ ์ƒํƒœ(`state/trailing_stops.json`) + ์†์ ˆ์„  ๊ณ„์‚ฐ. `compute_levels(peak, pct, min_sell_price=None)` = `cond_uv` = **max(peakร—(1โˆ’pct/100), min_sell_price)** ํ˜ธ๊ฐ€๋‹จ์œ„ ๋‚ด๋ฆผ + `ord_uv`(์กฐ๊ฑด๋‹จ๊ฐ€ โˆ’`ORD_UV_GAP_TICKS` 2ํ‹ฑ โ€” ์กฐ๊ฑด๋‹จ๊ฐ€์™€ ๊ฐ™๊ฒŒ ๋‘๋ฉด ๋ฐœ๋™ ํ›„ ๊ทธ ๊ฐ€๊ฒฉ ์•„๋ž˜๋กœ ์•ˆ ํŒ”๋ ค ๋ฏธ์ฒด๊ฒฐ๋กœ ๋‚จ๊ณ , ๋„ˆ๋ฌด ๋ฒŒ๋ฆฌ๋ฉด ๊ธ‰๋ฝ ์‹œ ํ—๊ฐ’ ๋งค๋„). ๋ฐ˜ํ™˜์— `floor_applied`(์ตœ์ €๊ฐ€๊ฐ€ ํŠธ๋ ˆ์ผ์„ ์ด๊ฒผ๋Š”์ง€)๋ฅผ ์‹ค์–ด ์นด๋“œยท๋ฏธ๋ฆฌ๋ณด๊ธฐ๊ฐ€ ์–ด๋А ์ชฝ์ด ์ง€๋ฐฐ ์ค‘์ธ์ง€ ํ‘œ์‹œํ•œ๋‹ค. **์ตœ์ € ๋งค๋„๊ฐ€**๋Š” ์†์ ˆ์„ ์˜ ํ•˜ํ•œ โ€” ํŠธ๋ ˆ์ผ ํญ์„ ๋„“๊ฒŒ ์žก์•„๋„ ์ด ๊ฐ€๊ฒฉ ์•„๋ž˜๋กœ ์•ˆ ๋‚ด๋ ค๊ฐ„๋‹ค(์ดˆ๊ธฐ ๊ตฌ๊ฐ„ ์†์‹ค ์ œํ•œ). ๊ณ ์ ์ด ์˜ฌ๋ผ ํŠธ๋ ˆ์ผ์ด ์ตœ์ €๊ฐ€๋ฅผ ์ถ”์›”ํ•˜๋ฉด ๊ทธ ๋’ค๋ก  ํŠธ๋ ˆ์ผ์ด ์ง€๋ฐฐ(์ „ํ™˜์  = `min_sell_price รท (1โˆ’pct/100)`, ์˜ˆ: ์ตœ์ € 4,500ยท20% โ†’ 5,625์›). ์ตœ์ €๊ฐ€ ์ง€๋ฐฐ ๊ตฌ๊ฐ„์—์„  ๊ณ ์ ์ด ์˜ฌ๋ผ๋„ ์กฐ๊ฑด๋‹จ๊ฐ€๊ฐ€ ์•ˆ ๋ณ€ํ•ด `next_levels`๊ฐ€ None โ†’ ๋ถˆํ•„์š”ํ•œ ์ •์ • API ์ฝœ 0. `next_levels(res, cur)`๋Š” **์ƒํ–ฅ ์ „์šฉ ์ˆœ์ˆ˜ํ•จ์ˆ˜**(ํ˜„์žฌ๊ฐ€>๊ณ ์  AND ์ƒˆ ์กฐ๊ฑด๋‹จ๊ฐ€>๊ธฐ์กด ์กฐ๊ฑด๋‹จ๊ฐ€์ผ ๋•Œ๋งŒ ๊ฐ’ ๋ฐ˜ํ™˜) โ€” ๋‹จ์œ„ํ…Œ์ŠคํŠธ ๋Œ€์ƒ. ํŠธ๋ ˆ์ผ ํญ ํ—ˆ์šฉ 0.5~30%. ๊ฐ™์€ ๊ณ„์ขŒยท์ข…๋ชฉ ์ค‘๋ณต ์˜ˆ์•ฝ์€ `find_by_symbol`๋กœ propose ๋‹จ๊ณ„์—์„œ ์ฐจ๋‹จ. fcntl lock + atomic write (`pin.py` ํŒจํ„ด) - `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 ๋‚ด๋ถ€๋ง ํ•œ์ • ์šด์˜. **๋นŒ๋“œ ๋ฒ„์ „ ์ž๋™ ๋ฆฌ๋กœ๋“œ**(2026-07-03): ์ด ์•ฑ์€ `location.reload` ์—†์ด fetch๋กœ๋งŒ ๊ฐฑ์‹ ํ•ด ์ฝ”๋“œ ์ˆ˜์ •+์žฌ์‹œ์ž‘ ํ›„์—๋„ ์—ด๋ ค์žˆ๋˜ ํŽ˜์ด์ง€๋Š” ์˜› ์ธ๋ผ์ธ JS/CSS๋ฅผ ๊ณ„์† ์”€. `BUILD`(ํŒŒ์ผ mtime, import ์‹œ 1ํšŒ) ์ƒ์ˆ˜๋ฅผ shell `window.__build`์™€ `/api/panels` ์‘๋‹ต `build`์— ์‹ค์–ด, `apply()`๊ฐ€ ๋ถˆ์ผ์น˜(์˜› ํŽ˜์ด์ง€=`__build` ์—†์Œ ํฌํ•จ) ๊ฐ์ง€ ์‹œ `sessionStorage` ๊ฐ€๋“œ๋กœ build๋‹น 1ํšŒ ์ž๋™ ๋ฆฌ๋กœ๋“œ โ†’ ์ตœ์‹  JS/CSS ๋ฐ˜์˜(๋ฆฌ๋กœ๋“œ๋กœ๋„ ์•ˆ ๋งž์œผ๋ฉด ๋ฃจํ”„ ์—†์ด ํฌ๊ธฐ). ๋ณด์œ ์ข…๋ชฉ day_change ๋ณด์ •์€ brifing ๊ณผ ๋™์ผ A-4 ์ •์ฑ…. **KPI ๋ผ๋ฒจ ๊ทœ์น™**(2026-07-29): **'์ด'์€ ๊ณ„์ขŒ ์ „์ฒด(ํ˜„๊ธˆ ํฌํ•จ) ๊ธฐ์ค€์ผ ๋•Œ๋งŒ ์“ด๋‹ค** โ€” `์ด์ž์‚ฐ`(=ํ‰๊ฐ€๊ธˆ์•ก+์˜ˆ์ˆ˜๊ธˆ)ยท`์ด์ˆ˜์ต`(=์ด์ž์‚ฐโˆ’ํˆฌ์ž์›๊ธˆ)๋งŒ '์ด'์„ ๊ฐ–๊ณ , ๋ณด์œ ์ข…๋ชฉ ํ•œ์ •์ธ `ํ‰๊ฐ€๊ธˆ์•ก`ยท`๋งค์ž…๊ธˆ์•ก`ยท`ํ‰๊ฐ€์†์ต`์€ ์•ˆ ๋ถ™์ธ๋‹ค. ์ด๋ฆ„๋งŒ์œผ๋กœ ๊ด€๊ณ„์‹์ด ์ฝํžˆ๊ฒŒ ํ•œ ์ •๋ฆฌ(๊ตฌ ๋ผ๋ฒจ: ์ด ํ‰๊ฐ€๊ธˆ์•กโ†’ํ‰๊ฐ€๊ธˆ์•ก, ์ˆœ์ž์‚ฐโ†’**์ด์ž์‚ฐ**, ์ด ๋งค์ž…๊ธˆ์•กโ†’๋งค์ž…๊ธˆ์•ก, ์ด ํ‰๊ฐ€์†์ตโ†’ํ‰๊ฐ€์†์ต, `์ด์ˆ˜์ต (์›๊ธˆ ๋Œ€๋น„)`โ†’์ด์ˆ˜์ต). ํ—ท๊ฐˆ๋ฆฌ๋˜ ์„ธ ์Œ์„ ๋ถ„๋ฆฌํ•œ ๊ฒฐ๊ณผ โ€” โ‘ ํ‰๊ฐ€๊ธˆ์•ก vs ์ด์ž์‚ฐ(์ฐจ์ด=์˜ˆ์ˆ˜๊ธˆ) โ‘ก๋งค์ž…๊ธˆ์•ก vs ํˆฌ์ž์›๊ธˆ(์ „์ž๋Š” ํ˜„ ๋ณด์œ ๋ถ„ ๋งค์ž…์›๊ฐ€, ํ›„์ž๋Š” ์‹ค์ œ ์ž…๊ธˆ์•ก) โ‘ขํ‰๊ฐ€์†์ต vs ์ด์ˆ˜์ต(์ „์ž๋Š” ๋ณด์œ ๋ถ„ ๋ฏธ์‹คํ˜„๋งŒ, ํ›„์ž๋Š” ์‹คํ˜„ยท๋ฐฐ๋‹น ํฌํ•จ). `_render_owner_kpi`ยท`_render_account_kpi`ยท**`stock_portfolio_report`(HTMLยทํ‰๋ฌธยทํ…”๋ ˆ๊ทธ๋žจ)**ยท์ˆœ์ž์‚ฐ ์ฐจํŠธ ํ‘œ์‹œ๋ฌธ(`NET_WORTH_MODE_PRESETS`ยท์ฐจํŠธ ์ œ๋ชฉยทariaยทํˆดํŒ ํ–‰) ์ „๋ถ€ ํ†ต์ผ. โš ๏ธ ํ‰๋ฌธ ๋ฆฌํฌํŠธ ๋ผ๋ฒจ์€ **ํ‘œ์‹œํญ 17์นธ ์ •๋ ฌ**(ํ•œ๊ธ€ 2์นธ) โ€” ๋ผ๋ฒจ ๋ฐ”๊ฟ€ ๋•Œ ๊ณต๋ฐฑ ์ˆ˜ ์žฌ๊ณ„์‚ฐ ํ•„์š”. โš ๏ธ `_rtk` ์‹ค์‹œ๊ฐ„ ๋งคํ•‘ ํ‚ค๊ฐ€ ๋ผ๋ฒจ ๋ฌธ์ž์—ด์ด๋ผ ๋ผ๋ฒจ ๋ณ€๊ฒฝ ์‹œ ํ•จ๊ป˜ ๊ณ ์ณ์•ผ ํ•œ๋‹ค. โš ๏ธ PBR ์„ค๋ช…๋ฌธ์˜ 'ํšŒ์‚ฌ ์ˆœ์ž์‚ฐ'์€ ๋œป์ด ๋‹ค๋ฅด๋‹ˆ ๊ฑด๋“œ๋ฆฌ์ง€ ์•Š๋Š”๋‹ค. โš ๏ธ `render`๋Š” **์…ธ HTML๋งŒ** ์ƒ์„ฑ(๋ฐ์ดํ„ฐ fetch ์—†์Œ) โ€” ํŒจ๋„ ๋‚ด์šฉ ๊ฒ€์ฆ์€ `_build_panels_payload()` ์ง์ ‘ ํ˜ธ์ถœ์ด๋‚˜ `/api/panels` curl๋กœ ํ•ด์•ผ ํ•œ๋‹ค. **KPI ํ–‰ ์ˆœ์„œ**(2026-07-29, ๊ด€๋ฆฌ์ž๋‹˜ ์ง€์ •): ํ•ฉ์‚ฐ owner ์นด๋“œ(`_render_owner_kpi`)๋Š” **๊ตฌ๋ถ„์„ ยท๊ทธ๋ฃน ์—†๋Š” ๋‹จ์ผ ๋ชฉ๋ก** โ€” `์ด์ž์‚ฐ ยท **ํˆฌ์ž์›๊ธˆ** ยท ๋งค์ž…๊ธˆ์•ก ยท ํ‰๊ฐ€๊ธˆ์•ก ยท ํ‰๊ฐ€์†์ต ยท ์˜ˆ์ˆ˜๊ธˆ ยท [๋‹น์ผ ์ž…์ถœ๊ธˆ] ยท ๋ณด์œ ์ข…๋ชฉ/๋‹น์ผ๋งค๋งค ยท ๋‹น์ผ ํ‰๊ฐ€์†์ต` + ์กฐ๊ฑด๋ถ€ `๋‹น์ผ ์‹คํ˜„์†์ต`(non-compact) + ๋งจ ์•„๋ž˜ `์ด์ˆ˜์ต`. `๋‹น์ผ ์ž…์ถœ๊ธˆ`์€ ์˜ˆ์ˆ˜๊ธˆ ๋ฐ”๋กœ ์•„๋ž˜(ํ˜„๊ธˆ ์ž”์•กโ†”๊ทธ๋‚  ํ˜„๊ธˆ ์ด๋™)์ด๊ณ  ์ž…์ถœ๊ธˆ ์—†๋Š” ๋‚ ์€ ํ–‰ ์ž์ฒด๊ฐ€ ์—†๋‹ค. ํˆฌ์ž์›๊ธˆ์€ ์ด์ž์‚ฐ ๋ฐ”๋กœ ์•„๋ž˜(์ „์ฒด ์ž์‚ฐโ†”๋„ฃ์€ ๋ˆ ๋Œ€๋น„), ์ด์ˆ˜์ต์€ ๋งจ ์•„๋ž˜ ๊ฒฐ๋ก . ์›๊ธˆ ๋ฏธ์ง‘๊ณ„(๋ถ€ํŠธ์ŠคํŠธ๋žฉ ์ „)๋ฉด **๋‘ ํ–‰ ๋ชจ๋‘** ์‚ฌ๋ผ์ง„๋‹ค. ๋ณด์œ ์ข…๋ชฉยท๋‹น์ผ๋งค๋งค๋Š” **ํ•œ ํ–‰ ๊ฒฐํ•ฉ**(`3๊ฐœ / 2๊ฐœ`) โ€” compact์—๋„ ๋‹น์ผ๋งค๋งค๊ฐ€ ํ•จ๊ป˜ ๋ณด์ธ๋‹ค. ํ‰๋ฌธ ๋ฆฌํฌํŠธ์—์„œ `๋ณด์œ ์ข…๋ชฉ/๋‹น์ผ๋งค๋งค`๋Š” ํ‘œ์‹œํญ์ด ์ •ํ™•ํžˆ 17์นธ์ด๋ผ ํŒจ๋”ฉ ์—†์ด ์ฝœ๋ก ์ด ๋งž๋Š”๋‹ค. ๊ฐ™์€ ์ˆœ์„œยท๋ผ๋ฒจ์„ `_render_account_kpi`์™€ `stock_portfolio_report`(HTML ์†Œ์œ ์ž๋ณ„ยท์ „์ฒดํ•ฉ๊ณ„, ํ‰๋ฌธ)์—๋„ ์ ์šฉ. โš ๏ธ 2026-07-29 ์ค‘ 4๊ทธ๋ฃน(์ž์‚ฐ/๋ณด์œ /๋ˆ„์ /๋‹น์ผ) ๊ตฌ๋ถ„์„  ๋ฐฉ์‹์„ ๊ฑฐ์ณค๋‹ค๊ฐ€ ๋‹จ์ผ ๋ชฉ๋ก์œผ๋กœ ๋˜๋Œ๋ฆผ โ€” `.kpi-gtop` CSS๋Š” ์ œ๊ฑฐ๋จ. `_rtk` ์‹ค์‹œ๊ฐ„ ๋งคํ•‘(value/profit/net/daypl/totret)์€ ๋ผ๋ฒจ ๊ธฐ์ค€์ด๋ผ ๊ทธ๋ฃนํ™”์™€ ๋ฌด๊ด€ํ•˜๊ฒŒ ๋™์ž‘. ๊ณ„์ขŒ๋ณ„ pane(`_render_account_kpi`)์€ ํ‰๋ฉด ์œ ์ง€(๊ด€๋ฆฌ์ž๋‹˜ ์„ ํƒ). โš ๏ธ ๊ทธ๋ฃนํ™”๋กœ stock_portfolio_report ๋ฉ”์ผ์˜ ํ‰๋ฉด ์ˆœ์„œ์™€๋Š” ๋ฐฐ์น˜๊ฐ€ ๊ฐˆ๋ ธ๋‹ค(๋ผ๋ฒจ์€ ๋™์ผ). **ํˆฌ์ž์›๊ธˆยท์ด์ˆ˜์ต KPI**(2026-07-29): `๋ˆ„์  ์„ฑ๊ณผ` ๊ทธ๋ฃน 2ํ–‰ โ€” `ํˆฌ์ž์›๊ธˆ`(๊ฐ’์€ ๊ธˆ์•ก๋งŒ, **๋ผ๋ฒจ ์˜† ์ž‘์€ ์›ํ˜• `[!]` ๋ฒ„ํŠผ**) / `์ด์ˆ˜์ต`. ๋ฒ„ํŠผ์„ ๊ฐ’(td)์ด ์•„๋‹ˆ๋ผ ๋ผ๋ฒจ(th)์— ๋‘๋Š” ์ด์œ  โ€” ๊ธˆ์•ก ๋’ค์— ๋ถ™์ด๋ฉด ์ˆซ์ž ์šฐ์ธก์ •๋ ฌ์ด ํํŠธ๋Ÿฌ์ง„๋‹ค. `kpis` ํŠœํ”Œ์˜ **3๋ฒˆ์งธ ์›์†Œ**๊ฐ€ ๋ผ๋ฒจ ๋’ค HTML(escape ๋Œ€์ƒ ์•„๋‹˜)๋กœ ๋ Œ๋”๋œ๋‹ค. **KPI ์ƒ์„ธ ํŒ์—…์€ ๊ณต์šฉ 1๊ฐœ**(`kpi-modal` + `openKpiModal(src,title)`): ๋ผ๋ฒจ ์˜† `.kpi-more-btn`์ด `data-kpi-src`(์—”๋“œํฌ์ธํŠธ)ยท`data-kpi-title`์„ ๋“ค๊ณ  ์žˆ๊ณ , ์œ„์ž„ ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ๊ทธ๊ฑธ ์ฝ์–ด fetch โ†’ ๋ณธ๋ฌธ innerHTML. ๋ฒ„ํŠผ ์ƒ์„ฑ์€ `_kpi_more_button(src, title)`. ๋ณธ๋ฌธ์€ **์„œ๋ฒ„๊ฐ€ HTML๋กœ ์กฐ๋ฆฝ**ํ•˜๋ฏ€๋กœ ์ƒˆ [!] ๋ฒ„ํŠผ์„ ๋Š˜๋ฆด ๋•Œ JSยท๋ชจ๋‹ฌ ์ถ”๊ฐ€๊ฐ€ ํ•„์š” ์—†๋‹ค โ€” ๋ Œ๋” ํ•จ์ˆ˜ + ์—”๋“œํฌ์ธํŠธ ๋ถ„๊ธฐ๋งŒ ๋”ํ•˜๋ฉด ๋œ๋‹ค. ํ˜„์žฌ 2๊ฐœ: `/api/principal?owner=`(`_render_principal_body` โ€” ํˆฌ์ž์›๊ธˆยท๋ˆ„์  ์ž…๊ธˆ/์ถœ๊ธˆยท๊ณ„์ขŒ๋ณ„ + ์ž…์ถœ๊ธˆ ๋‚ด์—ญ 233ํ–‰) / `/api/cashflow?owner=`(`_render_cashflow_body` โ€” ๋‹น์ผ ์ž…๊ธˆ/์ถœ๊ธˆ ํ•ฉ๊ณ„ + ๊ฑด๋ณ„ ๋‚ด์—ญ, kt00015 ๊ณ„์ขŒ๋‹น 1์ฝœ ์žฌ์กฐํšŒ). ๋‘ ํŒ์—… ๋ชจ๋‘ `.pm-*` CSS ๊ณต์œ . โš ๏ธ ์ˆœ์•ก๊ณผ ํ•ฉ๊ณ„๊ฐ€ ๊ฐ™์•„์ง€๋Š” ์ค‘๋ณต ํ‘œ์‹œ ๊ธˆ์ง€ โ€” ๋‹น์ผ ์ž…์ถœ๊ธˆ์€ **ํ•œ์ชฝ ๋ฐฉํ–ฅ๋ฟ์ด๋ฉด `์ˆœ ์ž…์ถœ๊ธˆ` ํ–‰์„ ์ƒ๋žต**ํ•œ๋‹ค(`+3,000,000์› ยท ์ž…๊ธˆ 3,000,000์›` ๊ฐ™์€ ๊ตฐ๋”๋”๊ธฐ๊ฐ€ KPI ํ–‰ยท๋ฉ”์ผยทํ…”๋ ˆ๊ทธ๋žจ 4๊ณณ์— ์žˆ์—ˆ์Œ, 2026-07-29 ์ œ๊ฑฐ). ๋ชจ๋‹ฌ ์…ธ์€ shell HTML ์ง์†์ด๋ผ panels swap ์˜ํ–ฅ ์—†์Œ. ๋‚ด์—ญ์€ `ip.get_flows` ์บ์‹œ ์ฝ๊ธฐ๋ผ **ํ‚ค์›€ ์ฝœ 0**. ๋‚ด์—ญ 233ํ–‰ ์ค‘ ๋Œ€๋ถ€๋ถ„์ด ๋ฐฐ๋‹นยท์ด์ž๋ผ ์‹ค์ œ ์ž…๊ธˆ์ด ๋ฌปํžˆ๋ฏ€๋กœ **๊ธฐ๋ณธ์€ ์›๊ธˆ ๋ฐ˜์˜๋ถ„๋งŒ ๋ณด์ด๊ณ **(๋ณธ์ธ 49/140ยท๊ฐ€ํฌ 15/93) ์ฒดํฌ๋ฐ•์Šค๋กœ ๋‚˜๋จธ์ง€๋ฅผ ํŽผ์นœ๋‹ค โ€” `.pm-all-cb:not(:checked) ~ .pm-list .pm-row.other{display:none}` **CSS-only, JS ์—†์Œ**. ๊ฐœ๋… ์„ค๋ช…๋ฌธ์€ ๋„ฃ์ง€ ์•Š๋Š”๋‹ค(๊ด€๋ฆฌ์ž๋‹˜ ์ง€์‹œ). โš ๏ธ ๊ณ„์ขŒ ๊ฐ„ ๋Œ€์ฒด(๋‚ด ์ผ๋ฐ˜โ†”ISA)๊ฐ€ ์žˆ์œผ๋ฉด owner ํ•ฉ๊ณ„๋Š” ์ƒ์‡„๋˜์ง€๋งŒ **๊ณ„์ขŒ๋ณ„ ๊ธˆ์•ก์€ ์™œ๊ณก**๋˜๋ฏ€๋กœ ์•ˆ๋‚ด๋ฌธ(`.pm-note-in`)์„ ๋„์šด๋‹ค(์‹ค์ธก ๋ณธ์ธ 6,000,000ยท๊ฐ€ํฌ 1,000,000 ๊ฐ๊ฐ ์ƒ์‡„). `์ˆœ์ž์‚ฐ โˆ’ ์›๊ธˆ` ๊ด€๊ณ„๊ฐ€ ๋ˆˆ์œผ๋กœ ์ฝํžˆ๊ฒŒ ๋ถ™์—ฌ ๋†“๊ณ , ์œ„์ชฝ `์ด ํ‰๊ฐ€์†์ต`(๋ณด์œ ๋ถ„ ๋ฏธ์‹คํ˜„)๊ณผ ํ˜ผ๋™๋˜์ง€ ์•Š๊ฒŒ ๋ผ๋ฒจ์— "์›๊ธˆ ๋Œ€๋น„"๋ฅผ ๋ช…์‹œ. ๋ฐ์ดํ„ฐ๋Š” `investment_principal.get_principal(lbls)`(์บ์‹œ ์ฝ๊ธฐ, ์ฝœ 0) โ†’ `_build_owner_data`๊ฐ€ `principal`ยท`principal_cash_in/out`ยท`principal_qty_flow`๋กœ ์ฃผ์ž…, None์ด๋ฉด 2ํ–‰ ์ƒ๋žต. ์ˆœ์ž์‚ฐ์ด WS ํ‹ฑ๋งˆ๋‹ค ์›€์ง์ด๋ฏ€๋กœ ์ด์ˆ˜์ต๋„ ๊ฐ™์ด ๊ฐฑ์‹  โ€” ์นด๋“œ `data-rt-principal` + td `data-rt-kpi="totret"`๋ฅผ `setOwnerKpis`๊ฐ€ ์ฝ์–ด `T.net โˆ’ principal` ์žฌ๊ณ„์‚ฐ(`updateScopes`/`T` ๊ตฌ์กฐ ๋ฌด๋ณ€๊ฒฝ). ๊ณ„์ขŒ๋ณ„ pane(`_render_account_kpi`)์€ ๋ฏธ์ ์šฉ. ๋ณด์œ ์ข…๋ชฉ ํ–‰๋งˆ๋‹ค `๐Ÿ“‹ ๊ฑฐ๋ž˜๋‚ด์—ญ` + `๐Ÿ’ฐ ๊ฑฐ๋ž˜` + `๐Ÿ“ ๋ฉ”๋ชจ` ๋ฒ„ํŠผ. ์ž์‚ฐ์ •๋ณด ํƒญ 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=ํ•˜๋‚˜๋ผ๋„ ์ ‘์ˆ˜). **๋งค๋„ ์ฃผ๋ฌธ์œ ํ˜• 4์ข…** โ€” ์ง€์ •๊ฐ€(LIMIT) / ์‹œ์žฅ๊ฐ€(MARKET) / ์Šคํ†ฑ์ง€์ •๊ฐ€(STOP_LIMIT, ํ•˜๋ฝ ์‹œ ๋งค๋„ยท์กฐ๊ฑด๋‹จ๊ฐ€ ๊ณ ์ •) / **ํŠธ๋ ˆ์ผ๋ง ์Šคํ†ฑ(TRAILING_STOP, 2026-07-30 ์ถ”๊ฐ€)**. ๋’ค 2๊ฐœ๋Š” ๋งค๋„ ์ „์šฉ(๋งค์ˆ˜ ์„ ํƒ ์‹œ ์˜ต์…˜ disabled + LIMIT๋กœ ๋˜๋Œ๋ฆผ, `refreshStopUI`). **ํŠธ๋ ˆ์ผ๋ง ์ž…๋ ฅ 2๊ฐœ**(๋‹จ๊ฐ€ ์ž…๋ ฅํ–‰์€ ์ˆจ๊น€ โ€” ์กฐ๊ฑด๋‹จ๊ฐ€ยท์ง€์ •๊ฐ€๋Š” ์„œ๋ฒ„ ๊ณ„์‚ฐ): โ‘ **ํŠธ๋ ˆ์ผ ํญ %**(0.5~30, ๊ธฐ๋ณธ 10) โ‘ก**์ตœ์ € ๋งค๋„๊ฐ€**(์„ ํƒ, ๋น„์šฐ๋ฉด ์ œํ•œ ์—†์Œ). ๋‹จ์œ„(`(%)`ยท`(์›)`)๋Š” **๋ผ๋ฒจ์— ๋ฐ•๋Š”๋‹ค** โ€” ์ž…๋ ฅ์นธ ์˜†์— ๋ถ™์ด๋ฉด ๊ฐ€๋กœ๋กœ ๋ฒŒ์–ด์ ธ ์Šคํฌ๋กค์ด ์ƒ๊ธฐ๊ณ  number input ์•ˆ์ชฝ absolute ์ ‘๋ฏธ์‚ฌ๋Š” ๋ฐ์Šคํฌํ†ฑ ์Šคํ”ผ๋„ˆ์™€ ๊ฒน์นœ๋‹ค. `handler.propose_trade(trail_pct, min_sell_price)`๊ฐ€ ์ดˆ๊ธฐ ๊ณ ์ ์„ `md['current_price']`๋กœ ์ •ํ•˜๊ณ  `trailing.compute_levels`๋กœ ๊ณ„์‚ฐ. โš ๏ธ **๊ณ ์  ๊ธฐ์ค€ ์„ ํƒ ์˜ต์…˜์€ 2026-07-30 ์ œ๊ฑฐ๋จ**(`peak_basis` / `52์ฃผ ์ „๊ณ ์ ` / `๋งค์ˆ˜ํ›„ ๊ณ ์ `) โ€” ๊ณผ๊ฑฐ ๊ณ ์ ์„ ๊ธฐ์ค€์œผ๋กœ ์žก์œผ๋ฉด ์†์ ˆ์„ ์ด ํ˜„์žฌ๊ฐ€ ์œ„๋กœ ์˜ฌ๋ผ๊ฐ€ ๋“ฑ๋ก ์ฆ‰์‹œ ๋ฐœ๋™ํ•œ๋‹ค. **์†์‹ค ์ข…๋ชฉ์€ ๋“ฑ๋ก ์ž์ฒด๊ฐ€ ๋ถˆ๊ฐ€**(์‹ค์ธก ์ œ๋‹‰์Šค๋กœ๋ณดํ‹ฑ์Šค ํ˜„์žฌ๊ฐ€ 4,805 ยท ๋งค์ˆ˜ํ›„ ๊ณ ์  6,890 โ†’ ํ•„์š” ํญ 30.3% / 52์ฃผ 19,940 โ†’ 75.9%, ๋‘˜ ๋‹ค ์ƒํ•œ 30% ์ดˆ๊ณผ), **์ด์ต ์ข…๋ชฉ์€ ๊ณผ๊ฑฐ ๊ณ ์  โ‰ˆ ํ˜„์žฌ๊ฐ€๋ผ ๊ฒฐ๊ณผ๊ฐ€ ๊ฐ™๋‹ค**. ์ฆ‰ ์ฐจ์ด๊ฐ€ ๋‚  ๋•Œ๋Š” ๋ชป ์“ฐ๊ณ  ์“ธ ์ˆ˜ ์žˆ์„ ๋•Œ๋Š” ์ฐจ์ด๊ฐ€ ์—†์–ด ์˜ต์…˜์„ ์—†์•ด๋‹ค. **๋‹ค์‹œ ๋„ฃ์ง€ ๋ง ๊ฒƒ.** โš ๏ธ **์†์ ˆ์„  โ‰ฅ ํ˜„์žฌ๊ฐ€๋ฉด `TRAIL_IMMEDIATE`๋กœ ๊ฑฐ๋ถ€** โ€” ๊ณ ์ =ํ˜„์žฌ๊ฐ€ ๊ณ ์ •์ด๋ผ ์ด์ œ ์ตœ์ € ๋งค๋„๊ฐ€๊ฐ€ ํ˜„์žฌ๊ฐ€๋ณด๋‹ค ๋†’์€ ๊ฒฝ์šฐ๋งŒ ๋‚จ๋Š”๋‹ค. **๊ฑฐ๋ถ€ ์‹œ์ ์€ ์ž…๋ ฅ ์‹œ์ **(2026-07-30 ๊ด€๋ฆฌ์ž๋‹˜ ์ง€์‹œ๋กœ propose ์‹œ์ ์—์„œ ์ด๋™) โ€” `trailBlockReason()`์ด ์ž…๋ ฅ๊ฐ’์„ ๋ณด๊ณ  ์‚ฌ์œ  ๋ฌธ์ž์—ด์„ ๋‚ด๋†“๊ณ , ๊ฑธ๋ฆฌ๋ฉด ๋งค๋„ ๋ฒ„ํŠผ์ด disable + title ์— ์‚ฌ์œ . ์„œ๋ฒ„ `TRAIL_IMMEDIATE`๋Š” ์ตœํ›„ ๋ฐฉ์–ด์„ ์œผ๋กœ ์œ ์ง€. โš ๏ธ **๋ฒ„ํŠผ `disabled`๋Š” `refreshSubmitGate()` ํ•œ ๊ณณ์—์„œ๋งŒ ๊ฒฐ์ •ํ•œ๋‹ค** โ€” ์‹œ์žฅ phase ๊ฒŒ์ดํŠธ(`updateMarketPhaseDisplay`, `/api/market_state` ์ฃผ๊ธฐ ํด๋ง)์™€ ํŠธ๋ ˆ์ผ ๊ฒŒ์ดํŠธ๊ฐ€ ๊ฐ™์€ ๋ฒ„ํŠผ์„ ๊ฑด๋“œ๋ ค์„œ, ์˜ˆ์ „์ฒ˜๋Ÿผ ๊ฐ์ž ๋Œ€์ž…ํ•˜๋ฉด ์ฃผ๊ธฐ ํ˜ธ์ถœ์ด ํŠธ๋ ˆ์ผ ๊ฒŒ์ดํŠธ๋ฅผ ๋ฎ์–ด์จ ์ฆ‰์‹œ๋ฐœ๋™ ์ž…๋ ฅ์ด ํ†ต๊ณผ๋œ๋‹ค. phase ์ชฝ์€ `state.phaseCanTrade`/`phaseLabel`๋งŒ ์“ฐ๊ณ  ํŒ๋‹จ์„ ์œ„์ž„. propose ์ง„ํ–‰ ์ค‘์—๋Š” `btn.dataset.busy='1'`๋กœ ์ž ๊ฐ€ ์ฃผ๊ธฐ ํ˜ธ์ถœ์ด ๋ฒ„ํŠผ์„ ๋˜์‚ด๋ฆฌ์ง€ ๋ชปํ•˜๊ฒŒ ํ•˜๊ณ , ์‘๋‹ตยท์—๋Ÿฌ ํ›„ busy ํ•ด์ œ + ์žฌ๊ณ„์‚ฐ. `renderTrailPreview`๋Š” ์กฐ๊ธฐ ๋ฐ˜ํ™˜ ๊ฒฝ๋กœ(ํญ ๋ฏธ์ž…๋ ฅยท์‹œ์„ธ ๋กœ๋”ฉ)์—์„œ๋„ ๊ฒŒ์ดํŠธ๊ฐ€ ๊ฑธ๋ ค์•ผ ํ•˜๋ฏ€๋กœ **ํ•จ์ˆ˜ ๋งจ ์•ž์—์„œ** `refreshSubmitGate()`๋ฅผ ๋ถ€๋ฅธ๋‹ค. ํด๋ผ์ด์–ธํŠธ ๋ฏธ๋ฆฌ๋ณด๊ธฐ(`renderTrailPreview`/`trailCondPrice`/`floorTick`)๋Š” ์„œ๋ฒ„์™€ **๊ฐ™์€ ์‹**์ด์ง€๋งŒ ์‹ค์ œ ๋ฐœ์ฃผ๊ฐ’์€ ์„œ๋ฒ„ ๊ณ„์‚ฐ๋ถ„์ด ์Šน์ž โ€” ํ•œ์ชฝ๋งŒ ๋ฐ”๊พธ๋ฉด ํ‘œ์‹œ์™€ ๋ฐœ์ฃผ๊ฐ€ ์–ด๊ธ‹๋‚˜๋‹ˆ `orders/trailing.compute_levels` ์ˆ˜์ • ์‹œ JS๋„ ํ•จ๊ป˜ ๊ณ ์น  ๊ฒƒ(112๊ฐœ ์กฐํ•ฉ node ๋Œ€์กฐ๋กœ ๊ฒ€์ฆํ•˜๋Š” ๋ฐฉ์‹). ํ‚ค์›€์—” ์Šคํ†ฑ์ง€์ •๊ฐ€๋กœ ๋‚˜๊ฐ€๊ณ (`submit_with_pin`์ด `TRAILING_STOP`โ†’`STOP_LIMIT` ๋ณ€ํ™˜) ํŠธ๋ ˆ์ผ๋ง์€ ์šฐ๋ฆฌ ์ชฝ ๊ฐœ๋…. ์Šน์ธ ํ›„ `trailing.register(ord_no, ...)`๋กœ ์˜ˆ์•ฝ ๋“ฑ๋ก, ์ดํ›„ `trailing_monitor`๊ฐ€ ์กฐ๊ฑด๋‹จ๊ฐ€ ์ƒํ–ฅ. **๋“ฑ๋ก ์‹คํŒจ ์‹œ ์ฃผ๋ฌธ์€ ์ด๋ฏธ ์ ‘์ˆ˜๋œ ์ƒํƒœ**๋ผ ์นด๋“œ ๋ฉ”์‹œ์ง€์— โš ๏ธ ๊ฒฝ๊ณ ๋ฅผ ๋ถ™์ด๊ณ  ledger `trailing_register_failed` ๊ธฐ๋ก(์ˆจ๊ธฐ๋ฉด ํŠธ๋ ˆ์ผ๋ง์ด ์•ˆ ๋„๋Š” ๊ฑธ ๋ชจ๋ฅธ๋‹ค). ํŠธ๋ ˆ์ผ๋งยท์Šคํ†ฑ์ง€์ •๊ฐ€๋Š” ๋‹จ์ผ ๊ณ„์ขŒ ์˜ˆ์•ฝ์ด๋ผ **2๊ณ„์ขŒ ๋™์‹œ ๋งค๋„ ๋ถ„๊ธฐ์—์„œ ์ œ์™ธ**. ์ทจ์†Œ๋Š” `[๐Ÿ“‹ ์ง„ํ–‰์ค‘]`์—์„œ ํ•ด๋‹น ๋ฏธ์ฒด๊ฒฐ ์ฃผ๋ฌธ ์ทจ์†Œ โ†’ ๋‹ค์Œ ๊ฐ์‹œ ์‚ฌ์ดํด์ด ์‚ฌ๋ผ์ง„ ์˜ˆ์•ฝ์„ ์ž๋™ ์ •๋ฆฌ. โš ๏ธ ํŠธ๋ ˆ์ผ๋ง ์˜ˆ์•ฝ์ด ๋ฏธ์ฒด๊ฒฐ ๋งค๋„๋กœ ์žกํ˜€ ์žˆ์œผ๋ฉด `/api/order/check`์˜ `_pending_sell_qty` ์ฐจ๊ฐ ๋•์— **์ผ๋ฐ˜ ๋งค๋„ max_qty๊ฐ€ ์ž๋™์œผ๋กœ ์ค„์–ด๋“ ๋‹ค**(์ด์ค‘ ๋งค๋„ ๊ตฌ์กฐ์  ์ฐจ๋‹จ). **ํ…”๋ ˆ๊ทธ๋žจ ๋ฐœ์†ก ์ •์ฑ… (์›น ๋งค๋งค)** โ€” ๊ฑฐ๋ถ€ยท๊ฒ€์ฆ ์—๋Ÿฌ๋Š” ํ† ์ŠคํŠธ๋งŒ, **๋งค๋งค๋“ฑ๋ก(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). **๊ทœ์น™(๋‚˜โ†’๋‚˜ iMessage)**: ๊ด€๋ฆฌ์ž ๋ณธ์ธ handle๋กœ ๋ณด๋‚ด๋Š” iMessage๋Š” ํ•ญ์ƒ `--service imessage`(ํŒŒ๋ž€) ๊ฐ•์ œ โ€” SMS ์…€ํ”„๋ฐœ์†ก ๊ธˆ์ง€. ์ด์œ : iMessage ์…€ํ”„๋ฐœ์†ก์€ Note-to-Self๋ผ ๋ณด๋‚ธ ๋ฒ„๋ธ”๋งŒ ๋œจ๊ณ  OTP ๋„๋ฉ”์ธ ์ž๋™์ž…๋ ฅ์ด ์ •์ƒ ๋™์ž‘ํ•˜์ง€๋งŒ, SMS ์…€ํ”„๋ฐœ์†ก์€ ํ†ต์‹ ์‚ฌ loopback์œผ๋กœ ์ดˆ๋กยท์ˆ˜์‹ ๋ฒ„๋ธ”์ด ์ƒ๊ธฐ๊ณ  ์ž๋™์ž…๋ ฅ์ด ๊นจ์งˆ ์ˆ˜ ์žˆ์Œ. ํƒ€์ธ ๋Œ€์ƒ(์˜ˆ: ๊ฐ€ํฌ ๋ฆฌ๋งˆ์ธ๋” `gahee_reminder._send_imessage`๋Š” `--service sms`)์€ ์˜ˆ์™ธ. **์‹ ๊ทœ 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 ๋“ฑ ๋ฐ์ดํ„ฐ ์—†์œผ๋ฉด ํ•ด๋‹น ํƒญ "๋ฐ์ดํ„ฐ ์—†์–ด์š”". **๋ฉ”๋ชจ ๋ชจ๋‹ฌ (`note-modal`)**(2026-06-26) โ€” ๋ณด์œ ยท๊ด€์‹ฌยท๊ฐ์‹œ์ข…๋ชฉ ํ–‰ ๋ชจ๋‘์— `๐Ÿ“ ๋ฉ”๋ชจ` ๋ฒ„ํŠผ. ํด๋ฆญ โ†’ ํŒ์—… textarea(์ตœ๋Œ€ 1000์ž, ์—ฌ๋Ÿฌ ์ค„)์— ๊ธฐ์กด ๋ฉ”๋ชจ prefill โ†’ [์ €์žฅ]์€ `/notes/set` POST(submit ํ•ธ๋“ค๋Ÿฌ๊ฐ€ `note-form`์„ fetch๋กœ ๊ฐ€๋กœ์ฑ„ **ํ˜„์žฌ ํƒญ ์œ ์ง€** โ€” ๋„ค์ดํ‹ฐ๋ธŒ ํผ์ด๋ฉด 303โ†’`/` ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ๋กœ ์ž์‚ฐ์ •๋ณด ํƒญ์œผ๋กœ ํА) ํ›„ ํŒจ๋„ ์ƒˆ๋กœ๊ณ ์นจ, [์‚ญ์ œ]๋Š” ๋ฒ„ํŠผ ์™ผ์ชฝ ์œ„ ์ž‘์€ **ํ™•์ธ ํŒ์—…(์˜ˆ/์•„๋‹ˆ์˜ค)** ํ›„ ๋นˆ ํ…์ŠคํŠธ submit์œผ๋กœ ํ•ญ๋ชฉ ์ œ๊ฑฐ(์˜ค์‚ญ์ œ ๋ฐฉ์ง€, `note-confirm`). ๋ฉ”๋ชจ ์žˆ์œผ๋ฉด ๋ฒ„ํŠผ์ด `๐Ÿ“ ๋ฉ”๋ชจ โ—` ๋…ธ๋ž€ ๊ฐ•์กฐ(`has-note`)+hover ํˆดํŒ. ์ €์žฅ์†Œ `state/behive_stock_notes.json`(`{by_code, by_name}`, code ์šฐ์„ โ†’name fallback, `stock_tags`์™€ ๋™์ผํ•œ fcntl lockยทatomic write). **์ข…๋ชฉ ๋‹จ์œ„ ๊ณต์šฉ**(๊ณ„์ขŒ ๋ถ„๋ฆฌ X). ๋ฐฑ์—”๋“œ `_load/_get/_set_stock_note`ยท`_note_button_html`ยท`_render_note_modal`, ํƒœ๊ทธ ๋ชจ๋‹ฌ ํŒจํ„ด ๋ณต์ œ. **๊ด€์‹ฌ์ข…๋ชฉ ๊ทธ๋ฃน (`group-assign-modal` + `group-manage-modal`)**(2026-07-03) โ€” ๊ด€์‹ฌ์ข…๋ชฉ์ด 39๊ฐœ๊นŒ์ง€ ์Œ“์—ฌ ๊ทธ๋ฃน ๋ถ„๋ฅ˜ ๋„์ž…. **๊ด€์‹ฌ์ข…๋ชฉ ํƒญ ์ „์šฉ**(๊ฐ์‹œ์ข…๋ชฉ ์ œ์™ธ), `stock_tags`์™€ **๋…๋ฆฝ**. ์ €์žฅ์†Œ `state/behive_interest_groups.json` = `{"groups":[์ˆœ์„œ์žˆ๋Š” ์ด๋ฆ„], "members":{์ข…๋ชฉ๋ช…:[๊ทธ๋ฃน๋ช…]}}` โ€” ๋ฉค๋ฒ„์‹ญ ํ‚ค๋Š” **์ข…๋ชฉ๋ช…**(interests๊ฐ€ ์ข…๋ชฉ๋ช… dict ํ‚ค๋ผ ์•ˆ์ •์ , rename ์—†์Œ). **๋‹ค์ค‘ ๊ทธ๋ฃน ์†Œ์†**ยท๋นˆ ๊ทธ๋ฃน ์œ ์ง€ยทํ‘œ์‹œ์ˆœ์„œยทrename/delete ์—ฐ์‡„๋ฅผ ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ ํ•œ ํŒŒ์ผ์—์„œ ํ‘œํ˜„. `stock_tags`/`stock_notes`์™€ ๋™์ผํ•œ fcntl lockยทatomic write. ๊ด€์‹ฌ ์‚ญ์ œ ์‹œ `_apply_interests_action('delete')`๊ฐ€ `_interests_lock` **๋ฐ–์—์„œ** `_set_interest_groups(stock,[])`๋กœ ๋ฉค๋ฒ„์‹ญ ์ž๋™ ์ •๋ฆฌ(๋ณ„๋„ ํŒŒ์ผ ๋ฝ, ๋ฐ๋“œ๋ฝ ํšŒํ”ผ). **ํŒจ๋„**(`_render_interests_panel`): **๊ทธ๋ฃน ํ’€๋‹ค์šด**(`.igrp-select`/`.igrp-panel`, `์ „์ฒด`+`๋ณด์œ ์ค‘`+๋ฉค๋ฒ„ ์žˆ๋Š” ๊ทธ๋ฃน+`๋ฏธ๋ถ„๋ฅ˜` ์˜ต์…˜, ๋‹ค์ค‘์†Œ์†์€ ๊ฐ ํŒจ๋„ ์ค‘๋ณต ๋…ธ์ถœ). **๋ณด์œ ์ค‘์€ `mode=='held'`๋กœ ์ž๋™ ์ฑ„์›Œ์ง**(๋ ˆ์ง€์ŠคํŠธ๋ฆฌ ๋ฏธ๋“ฑ๋ก, ๋ณด์œ ์ข…๋ชฉ๋„ ๊ทธ๋ฃน ๋ฐฐ์ • ์‹œ ํ•ด๋‹น ๊ทธ๋ฃน์— ํ•จ๊ป˜ ๋…ธ์ถœ). ์ „์ฒด=๋ณด์œ +๊ด€์‹ฌ(๋ณด์œ  ๋จผ์ €), ๋ฏธ๋ถ„๋ฅ˜=๋ฏธ๋ณด์œ &๋ฏธ๋ฐฐ์ •๋งŒ. ๋ณด์œ ยท๊ทธ๋ฃน ๋‘˜ ๋‹ค ์—†์œผ๋ฉด ๋‹จ์ผ ๋ชฉ๋ก์œผ๋กœ ํด๋ฐฑ. ์„ ํƒ ์ƒํƒœ๋Š” ์ž์‚ฐํƒญ `.sub-tab`๊ณผ ๊ฒฉ๋ฆฌ(`igrpState`+`restoreIgrp`, 3s swap ํ›„ ๋ณต์›, ์‚ฌ๋ผ์ง„ ํ‚ค๋Š” ์ „์ฒด๋กœ ํด๋ฐฑ). ๊ฐ™์€ ์ข…๋ชฉ์ด ์—ฌ๋Ÿฌ ํŒจ๋„์— ์ค‘๋ณต โ†’ `details_mutex`๋Š” ๊ฐ™์€ `data-row-key`๋ผ๋ฆฌ ์•ˆ ๋‹ซ์Œ(ํŽผ์นจ ์œ ์ง€), `apply()`๋Š” `querySelectorAll`๋กœ ์ „ ์ธ์Šคํ„ด์Šค open ๋ณต์›. ๊ด€์‹ฌ์ข…๋ชฉ ํ–‰ **`+ ๊ทธ๋ฃน` ๋ฒ„ํŠผ์€ `+ํƒœ๊ทธ` ๋ฒ„ํŠผ๊ณผ ๊ฐ™์€ ๋””์ž์ธ(`btn-add-tag`)์œผ๋กœ ๊ทธ ์˜†(detail-name ์ค„)** โ†’ ์ฒดํฌ๋ฐ•์Šค ๋ฐฐ์ • ๋ชจ๋‹ฌ(+์ƒˆ ๊ทธ๋ฃน ์ธ๋ผ์ธ, `new_group`). **ํ’€๋‹ค์šด ์˜ค๋ฅธ์ชฝ `+` ๋ฒ„ํŠผ**(`.igrp-add-btn`, flatยทempty ์ผ€์ด์Šค์—๋„ ํ•ญ์ƒ ๋…ธ์ถœ)โ†’ ์ž‘์€ ๋“œ๋กญ๋‹ค์šด ๋ฉ”๋‰ด(`.igrp-menu`: `์ข…๋ชฉ ์ถ”๊ฐ€`=interest-modal / `๊ทธ๋ฃน ๊ด€๋ฆฌ`=group-manage-modal). ํ•˜๋‹จ ํŠธ๋ฆฌ๊ฑฐ(๊ด€์‹ฌ์ถ”๊ฐ€ยท๊ทธ๋ฃน๊ด€๋ฆฌ ๋ฒ„ํŠผ)๋Š” ์ด ๋ฉ”๋‰ด๋กœ ๋Œ€์ฒดยท์ œ๊ฑฐ. ๊ทธ๋ฃน ๊ด€๋ฆฌ ๋ชจ๋‹ฌ(๊ทธ๋ฃน๋‹น 2์ค„ ์นด๋“œ: ์ด๋ฆ„ ์ธํ’‹+์ˆ˜ / โ–ฒโ–ผยท์ด๋ฆ„๋ณ€๊ฒฝยท์‚ญ์ œ, ํ•˜๋‹จ ์ƒˆ ๊ทธ๋ฃน ํ–‰). **๊ด€๋ฆฌ ๋ชจ๋‹ฌ open์€ ํŠธ๋ฆฌ๊ฑฐ `data-group-all`+`data-group-counts`(JSON)๋กœ ์„œ๋ฒ„ ์™•๋ณต ์—†์ด ์ฆ‰์‹œ ๋ Œ๋”**, ์ดํ›„ op๋Š” keepOpen fetch ์‘๋‹ต `{groups,counts}`๋กœ ์žฌ๋ Œ๋”. ์—”๋“œํฌ์ธํŠธ `POST /interests/groups/set`(stock+groups ๋ฐ˜๋ณตํ•„๋“œ+new_group)ยท`POST /interests/groups`(op=create|rename|delete|reorder|listใ€”list๋Š” ์กฐํšŒ ํด๋ฐฑ์šฉ ์œ ์ง€ใ€•, `in_actions` ๊ฒ€์‚ฌ๋ณด๋‹ค ๋จผ์ € ์ •ํ™•๋งค์นญ). ๋ฐฑ์—”๋“œ `_load/_save/_get_interest_group(s)`ยทCRUD(`_create/_rename/_delete/_reorder_interest_groups`)ยท`_set_interest_groups`ยท`_interest_group_button_html`ยท`_render_group_assign_modal`ยท`_render_group_manage_modal`, ํƒœ๊ทธ/๋ฉ”๋ชจ ๋ชจ๋‹ฌ ํŒจํ„ด ๋ณต์ œ. ๊ธฐ์กด 39๊ฐœ๋Š” ๋ฏธ๋ถ„๋ฅ˜๋กœ ์ž๋™ ํŽธ์ž…(์“ฐ๊ธฐ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ์—†์Œ). ๋ ˆ๊ฑฐ์‹œ `์—์ดํ”ผ์•Œ.tag:"๋ทฐํ‹ฐ"` ์ธ๋ผ์ธ ํ•„๋“œ๋Š” ๋ฏธ์‚ฌ์šฉ ๋ฐฉ์น˜. - `send_balance_to_budget.py` โ€” ๋งค์›” 1์ผ 04:30 launchd. ๋ณธ์ธ+๊ฐ€ํฌ ๊ณ„์ขŒ๋ฅผ ์†Œ์œ ์ž๋ณ„(self/gahee)๋กœ ์ž”์•กยท์˜ˆ์ˆ˜๊ธˆยทํ‰๊ฐ€์•ก ์ง‘๊ณ„ํ•ด `agents/budget/inbox/incoming/`์— envelope(`topic: securities_balance`, schema v2 `by_owner`)๋กœ ๋–จ์–ด๋œจ๋ฆฐ๋‹ค. ๊ณจ๋””๊ฐ€ selfโ†’`์ฆ๊ถŒ(ํšจ์›)`ยทgaheeโ†’`์ฆ๊ถŒ(๊ฐ€ํฌ)`๋กœ reconcile ๋ถ„๊ฐœ. ๊ณจ๋”” ์›”๊ฐ„ ๊ฒฐ์‚ฐ(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/fomc_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:30 โ€” ๋‰ด์Šค ๋ธŒ๋ฆฌํ•‘ ๋ฉ”์ผ + ๐Ÿ‡บ๐Ÿ‡ธ ๋ฏธ๊ตญ์ฆ์‹œ ์š”์•ฝ(@futuresnow). ์˜์ƒ์ด ์•„์ง ๋ฏธ๊ฒŒ์‹œ๋ฉด(KST ํ™”~ํ†  ๊ฒŒ์‹œ์˜ˆ์ •์ผ) ๋ฐœ์†ก ๋ณด๋ฅ˜ - **์˜ค์ „ ๋ธŒ๋ฆฌํ•‘ (fallback 0755)** (main) โ€” Daily 07:55 โ€” 1์ฐจ ํด๋ฐฑ. 07:30์— ๋ฏธ๊ตญ์ฆ์‹œ ์š”์•ฝ ๋ฏธ๊ฒŒ์‹œ๋กœ ๋ณด๋ฅ˜๋œ ๊ฒฝ์šฐ ์žฌ์‹œ๋„(์—ฌ์ „ํžˆ ๋ฏธ๊ฒŒ์‹œ๋ฉด ๋˜ ๋ณด๋ฅ˜). `already_sent`๋กœ idempotent - **์˜ค์ „ ๋ธŒ๋ฆฌํ•‘ (fallback 0830)** (main) โ€” Daily 08:30 โ€” 2์ฐจ ํด๋ฐฑยท์ตœ์ข…. `prepare morning --final`๋กœ US ๋ฏธ๊ฒŒ์‹œ์—ฌ๋„ ๋ฌด์กฐ๊ฑด ๋ฐœ์†ก. 07:30ยท07:55์— ์ •์ƒ ๋ฐœ์†ก๋์œผ๋ฉด `already_sent`๋กœ ์Šคํ‚ต - **์˜คํ›„ ๋ธŒ๋ฆฌํ•‘** (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.trailing-monitor** โ€” ํ‰์ผ 09:00โ€“15:30 **๋งค 1๋ถ„** (`StartCalendarInterval` 391์—”ํŠธ๋ฆฌ, ์Šคํฌ๋ฆฝํŠธ self-skip) โ€” `trailing_monitor.py check`: **ํŠธ๋ ˆ์ผ๋ง ์Šคํ†ฑ ๊ฐ์‹œ**. โš ๏ธ **๋งค๋งค API๋ฅผ ์ž๋™ ํ˜ธ์ถœํ•˜๋Š” ์œ ์ผํ•œ ํŠธ๋ฆฌ๊ฑฐ** โ€” ๋งค๋งค ์ž๋™ ํŠธ๋ฆฌ๊ฑฐ ๊ธˆ์ง€ ๊ทœ์น™์˜ ์˜ˆ์™ธ๋กœ 2026-07-30 ๊ด€๋ฆฌ์ž๋‹˜ ๋ช…์‹œ ์Šน์ธ. ํ˜ธ์ถœํ•˜๋Š” ๊ฑด `kiwoom_order.modify_order` ํ•˜๋‚˜๋ฟ์ด๊ณ  ์‹ ๊ทœ ๋ฐœ์ฃผยท์ˆ˜๋Ÿ‰ยท๋ฐฉํ–ฅ ๋ณ€๊ฒฝ ๊ฒฝ๋กœ๊ฐ€ ์—†์Œ(PIN ์Šน์ธ ์‹œ ๊ณ„์ขŒยท์ข…๋ชฉยท์ˆ˜๋Ÿ‰ยทํŠธ๋ ˆ์ผ ํญ ํ™•์ •, ๊ฐ์‹œ๋Š” ์กฐ๊ฑด๋‹จ๊ฐ€ **์ƒํ–ฅ๋งŒ**). ์˜ˆ์•ฝ 0๊ฑด์ด๋ฉด ์ฆ‰์‹œ ์ข…๋ฃŒ(API ์ฝœ 0). ๋กœ๊ทธ `logs/stock-trailing-monitor.{log,err.log}`. โš ๏ธ **cadence ์ด๋ ฅ 2๋ถ„โ†’30์ดˆโ†’1๋ถ„**(์ „๋ถ€ 2026-07-30) โ€” launchd ์ตœ์†Œ ๋‹จ์œ„๊ฐ€ 1๋ถ„์ด๋ผ 30์ดˆ๋Š” ํ”„๋กœ์„ธ์Šค ๋‚ด๋ถ€ `--repeat 2 --gap 30`์œผ๋กœ ๊ตฌํ˜„ํ–ˆ๊ณ  CLI ์˜ต์…˜์€ ์‚ด์•„์žˆ์Œ(๋‹ค์‹œ ์“ธ ๋• plist ์ธ์ž๋งŒ ์ถ”๊ฐ€). `StartInterval=30`์€ GUI idle ์‹œ ๋ฐœํ™” ๋ณด๋ฅ˜๋ผ ์‚ฌ์šฉ ๊ธˆ์ง€ - **stock.ipo-calendar-sync** โ€” ๋งค์ฃผ ๊ธˆ์š”์ผ 17:00 โ€” IPO ์ฒญ์•ฝยท์ƒ์žฅ ์ผ์ • ์บ˜๋ฆฐ๋” ๋“ฑ๋ก - **stock.fomc-calendar-sync** โ€” ๋งค์›” 1์ผ 09:10 โ€” `fomc_calendar_sync.py`: ์—ฐ์ค€ FOMC ํšŒ์˜ ์ผ์ • ์บ˜๋ฆฐ๋” ๋“ฑ๋กยท๊ฐฑ์‹ . ์—ฐ์ค€์ด 1๋…„ ์ด์ƒ ์•ž์„œ ๊ณตํ‘œํ•˜๊ณ  ๋ณ€๊ฒฝ์ด ๊ฑฐ์˜ ์—†์–ด ์›” 1ํšŒ๋กœ ์ถฉ๋ถ„(ํด๋ฐฑ ํŠธ๋ฆฌ๊ฑฐ ์—†์Œ). LLM ๋ฏธ๊ฒฝ์œ . ๋กœ๊ทธ `logs/fomc-calendar-sync.{log,err.log}` - **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 **๋งค 2๋ถ„** (`StartCalendarInterval` 196์—”ํŠธ๋ฆฌ, ์—”์ง„์ด ์žฅ์™ธ/ํœด์žฅ self-skip) โ€” **์ž๋™๋งค๋งค ์‹œ๋ฎฌ(ํŽ˜์ดํผ)** 1ํšŒ ์Šค์บ”. (2026-06-09 15๋ถ„โ†’5๋ถ„, 2026-06-17 5๋ถ„โ†’2๋ถ„ ๋‹จ์ถ• โ€” ์Šค์บ” 1ํšŒ ์‹ค์ธก ~3.6์ดˆ๋ผ 2๋ถ„ cadence์— ์˜ค๋ฒ„๋žฉยทrate limit ์—ฌ์œ . 1๋ถ„์ด ์บ˜๋ฆฐ๋” ํŠธ๋ฆฌ๊ฑฐ ํ•œ๊ณ„์ง€๋งŒ ์ผ๋ด‰ ๊ธฐ๋ฐ˜ ์‹ ํ˜ธ๋ผ 2๋ถ„์œผ๋กœ ์ถฉ๋ถ„ ํŒ๋‹จ) โš ๏ธ 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 ์‚ฌ์šฉ - **gmail-label-classify** (main/ํด๋กœ) โ€” ๋งค์ผ 01:00 โ€” `workspace/scripts/gmail_label_classify.py`: self-sent ๋ธŒ๋ฆฌํ•‘ยท์ข…๋ชฉ๋ถ„์„ยท์ฃผ์‹ ๋ฆฌํฌํŠธ ๋ฉ”์ผ์„ Gmail ๋ผ๋ฒจ๋กœ ์ž๋™ ๋ถ„๋ฅ˜ + 24h ์ง€๋‚œ ํ…Œ์ŠคํŠธ๋ฉ”์ผ ํœด์ง€ํ†ต ์ด๋™. LLM ๋ฏธ๊ฒฝ์œ (`gog` CLI ์ง์ ‘ ํ˜ธ์ถœ). ๋กœ๊ทธ `logs/gmail-label-classify.{log,err.log}` + ์ƒํƒœ `state/gmail_label_classify.log`. โš ๏ธ 2026-06-26 OpenClaw cron(main 01:00)์—์„œ ์ด๊ด€ โ€” ๋ณธ๋ฌธ ์ƒ์„ฑ ์—†๋Š” ๋‹จ์ˆœ ์Šคํฌ๋ฆฝํŠธ๋ผ ๋ชจ๋ธ ์„ธ์…˜ ๋ถˆํ•„์š”(TASKS.md ยง3-3 ์›์น™) - **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 ์ œ์™ธ๋ผ ๋ณ„๋„ ๋ฐฑ์—… ํ•„์š”) - **codex-fallback-monitor** โ€” ํ‰์ผยท์ฃผ๋ง ๋งค 5๋ถ„(`StartCalendarInterval` Minute 0/5/โ€ฆ/55) โ€” `workspace/scripts/codex_fallback_monitor.py`: codex ์ฃผ ๋ชจ๋ธ(openai/gpt-5.5)์ด ์ฃฝ์–ด ๊ฒŒ์ดํŠธ์›จ์ด๊ฐ€ ์กฐ์šฉํžˆ **์œ ๋ฃŒ OpenRouter๋กœ ํด๋ฐฑ**ํ•˜๋ฉด ํ† ํฐ๋น„๊ฐ€ ์ƒˆ๋Š” ๊ฑธ ๊ฐ์ง€โ†’ํด๋กœ(main) ํ…”๋ ˆ๊ทธ๋žจ ์ฆ‰์‹œ ์•Œ๋ฆผ. ์‹ ํ˜ธ์›=`agents/*/sessions/*.trajectory.jsonl`์˜ `model.completed` ์ด๋ฒคํŠธ(์Šน์ž ๋ชจ๋ธ). ์Šน์ž `provider==openrouter`๋ฉด ํด๋ฐฑ์œผ๋กœ ํŒ์ •(์ •์ƒ=`openai/gpt-5.5` codex ํ•˜๋„ค์Šค). ๋ฌด๋น„์šฉยท์˜จ๋””์ŠคํฌยทLLM ๋ฏธ๊ฒฝ์œ . dedupe=`state/codex_fallback_monitor.json` ์›Œํ„ฐ๋งˆํฌ(`last_ts`)+30๋ถ„ ์ฟจ๋‹ค์šด(์žฅ๊ธฐ ๋‹ค์šด ์ŠคํŒธ ๋ฐฉ์ง€). ์ฒซ ์‹คํ–‰์€ ๊ณผ๊ฑฐ ๋ฌด์‹œํ•˜๊ณ  ์›Œํ„ฐ๋งˆํฌ๋งŒ ์„ธํŒ…. ๋ฐœ์†ก์€ ํ…”๋ ˆ๊ทธ๋žจ Bot API ์ง์ ‘ HTTP POST(`openclaw.json` `channels.telegram.accounts.default` ํ† ํฐยทallowFrom, ๋ ˆ์ด `send_telegram` ์Šคํฌ๋ฆฝํŠธ์™€ ๋™์ผ ํŒจํ„ด, urllib stdlib). ๋กœ๊ทธ `logs/codex-fallback-monitor.{log,err.log}`. โš ๏ธ codex ์—๋Ÿฌ ์ž์ฒด๋Š” ๋กœ๊ทธยทaudit(metadata-only)์— ์•ˆ ๋‚จ๊ณ  ํด๋ฐฑ ์‹œ OpenRouter๋Š” codex ํ•˜๋„ค์Šค ๋กœ๊ทธ๋ฅผ ์•ˆ ๋‚จ๊ฒจ, trajectory `model.completed`๊ฐ€ ์œ ์ผํ•˜๊ฒŒ ์‹ ๋ขฐ ๊ฐ€๋Šฅํ•œ ์Šน์ž ์‹ ํ˜ธ - **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. [๋‹จ๊ณ„] โ†’ ๊ฒ€์ฆ: [ํ™•์ธ] ``` ๊ฐ•ํ•œ ์„ฑ๊ณต ๊ธฐ์ค€์€ ๋…๋ฆฝ์  ๋ฃจํ”„๋ฅผ ๊ฐ€๋Šฅ์ผ€ ํ•˜๊ณ , ์•ฝํ•œ ๊ธฐ์ค€("๋™์ž‘ํ•˜๊ฒŒ")์€ ๋Š์ž„์—†๋Š” ๋ช…์„ธ ์š”์ฒญ์„ ๋ถ€๋ฅธ๋‹ค.