# 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/AGENTS). โš ๏ธ 2026-09-10 OpenClaw 2026.9.3 ์—…๊ทธ๋ ˆ์ด๋“œ ์‹œ doctor ๊ฐ€ ๊ฐ ์›Œํฌ์ŠคํŽ˜์ด์Šค์˜ `TOOLS.md` ๋ฅผ `AGENTS.md` ๋กœ ๋ณ‘ํ•ฉํ•˜๊ณ  ์›๋ณธ์„ ์‚ญ์ œํ–ˆ๋‹ค(๋‚ด์šฉ ์†์‹ค ์—†์Œ ํ™•์ธ). ๋„๊ตฌ ๋ชฉ๋ก์€ ์ด์ œ `AGENTS.md` ์•ˆ์— ์žˆ๋‹ค - **Cron ์ €์žฅ์†Œ** โ€” 2026-07-20๋ถ€ํ„ฐ `state/openclaw.sqlite`์˜ `cron_jobs` ํ…Œ์ด๋ธ”. `cron/jobs.json`์€ ์—†๋‹ค(`.migrated` ์ž”์žฌ๋งŒ). ์กฐํšŒยท์ˆ˜์ •์€ `openclaw cron {list|show|edit}` (์˜ˆ: `openclaw cron edit --cron "30 7 * * 1-6"` / `--message "<ํ”„๋กฌํ”„ํŠธ>"`). ์‹คํ–‰ ์ด๋ ฅ์€ `cron_run_logs` - `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`. ํ•˜์œ„ ํด๋” ๋งŒ๋“ค์ง€ ์•Š๊ณ  ์ง์†์— ๋‘”๋‹ค. - `MAINTENANCE.md` โ€” **์ฝ”๋”” ์›”๊ฐ„ ์ ๊ฒ€ ์ฒดํฌ๋ฆฌ์ŠคํŠธ**. ๋งค์›” 1์ผ health-check ๊ฐ€ ํ…”๋ ˆ๊ทธ๋žจ์œผ๋กœ ์•Œ๋ฆฐ๋‹ค. ์ฃผ๊ธฐ ์žก ์ƒ์กด์€ health-check ๊ฐ€ ๋งค์ผ ๋ณด๋ฏ€๋กœ, ์—ฌ๊ธฐ์—” **๋ฐ”๊นฅ์ด ๋ณ€ํ•ด์„œ ์šฐ๋ฆฌ๊ฐ€ ์กฐ์šฉํžˆ ์–ด๊ธ‹๋‚˜๋Š”** ๊ฒƒ๋งŒ ๋‹ด์•˜๋‹ค(๋ชจ๋ธ ์นดํƒˆ๋กœ๊ทธยท๋ณธ์ฒด ๋ฒ„์ „ยท์™ธ๋ถ€ ๋ฐ์ดํ„ฐ์†Œ์Šค 403ยท๋ฌธ์„œ ๋“œ๋ฆฌํ”„ํŠธยท์ž๊ฒฉ์ฆ๋ช… ๋งŒ๋ฃŒ) - `identity/` โ€” Device identity and auth - `completions/` โ€” Shell completion scripts (bash/zsh/fish/ps1) ## Runtime (๋ณธ์ฒดยทNode) - **OpenClaw 2026.9.3** (2026-09-10 `2026.7.1-2` ์—์„œ ์—…๊ทธ๋ ˆ์ด๋“œ). npm global ์„ค์น˜, `npm root -g` = `/opt/homebrew/lib/node_modules` - โš ๏ธ **Node 24 ํ•„์ˆ˜** โ€” 2026.9.3 ์˜ `engines` ๋Š” `>=24.16.0 <25 || >=26.1.0` ์ด๋ผ **node@22 ๋กœ๋Š” ์•ˆ ๋œฌ๋‹ค**. keg-only `node@24`(24.20.0) ๋ฅผ ์„ค์น˜ํ•ด ์“ฐ๊ณ , ์‹œ์Šคํ…œ ์ „์—ญ `node`(`/opt/homebrew/bin/node`)๋Š” **node@22 ๋กœ ๊ทธ๋Œ€๋กœ ๋’€๋‹ค**(๋‹ค๋ฅธ ๋„๊ตฌ ์˜ํ–ฅ ์ตœ์†Œํ™”). ๊ทธ๋ž˜์„œ openclaw ์‹คํ–‰ ๊ฒฝ๋กœ ๋‘ ๊ณณ์— node@24 ์ ˆ๋Œ€๊ฒฝ๋กœ๊ฐ€ ๋ฐ•ํ˜€ ์žˆ๋‹ค โ€” CLI ๋ž˜ํผ `~/.local/bin/openclaw`, ๊ฒŒ์ดํŠธ์›จ์ด `~/Library/LaunchAgents/ai.openclaw.gateway.plist`(+ `service-env/ai.openclaw.gateway.env` ์˜ `PATH`). ์„œ๋น„์Šค ์ชฝ ์…‹์€ `openclaw gateway install --force` ๊ฐ€ **ํ˜„์žฌ ์‹คํ–‰ ์ค‘์ธ node ๊ธฐ์ค€์œผ๋กœ ์žฌ์ƒ์„ฑ**ํ•˜๋ฏ€๋กœ ์†์œผ๋กœ ๊ณ ์น˜์ง€ ๋ง๊ณ  ์ด ๋ช…๋ น์„ ์“ด๋‹ค - โš ๏ธ **npm 11 ์€ install script ๋ฅผ ๊ธฐ๋ณธ ์ฐจ๋‹จ**ํ•œ๋‹ค โ€” ๊ทธ๋ƒฅ `npm install -g openclaw` ํ•˜๋ฉด `postinstall-bundled-plugins` ๊ฐ€ ์•ˆ ๋Œ์•„ ๋ฒˆ๋“ค ํ”Œ๋Ÿฌ๊ทธ์ธ์ด ๋น ์ง„๋‹ค. `--allow-scripts=openclaw,@google/genai,koffi,tree-sitter-bash,protobufjs` ๋ฅผ ๋ถ™์ผ ๊ฒƒ - โš ๏ธ **FDA ๋Š” node ๊ฒฝ๋กœ์™€ ๋ฌด๊ด€** โ€” `imsg` ๊ฐ€ ์ž์ฒด responsible process ๋ผ ๊ณจ๋”” whooing-sync(๋ณ„๋„ launchd ์žก)๋Š” node ๋ฅผ ๋ฐ”๊ฟ”๋„ chat.db ๋ฅผ ๊ณ„์† ์ฝ๋Š”๋‹ค(2026-09-10 ์‹ค์ธก). ์›๋ž˜๋ถ€ํ„ฐ ์•ˆ ๋˜๋˜ ๊ฑด **๊ฒŒ์ดํŠธ์›จ์ด ํ•˜์œ„**์—์„œ ๋ถ€๋ฅด๋Š” `imsg` ๋ฟ์ด๊ณ  ๊ทธ๊ฑด ์ด ์—…๊ทธ๋ ˆ์ด๋“œ๋กœ ๋‹ฌ๋ผ์ง€์ง€ ์•Š์•˜๋‹ค ## 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/gpt-5.6-sol` (์„ธ ์—์ด์ „ํŠธ ๊ณตํ†ต, codex ํ•˜๋„ค์Šค=ChatGPT oauth ๊ฒฝ๋กœ) with fallbacks to `openai/gpt-5.6-terra` โ†’ `openai/gpt-5.6-luna` โ†’ `openrouter/free`. โš ๏ธ **์ฒด์ธ ์ „์ฒด๊ฐ€ ๊ณผ๊ธˆ 0 ์ด๋‹ค**(2026-09-10 ๊ด€๋ฆฌ์ž๋‹˜ ์š”๊ตฌ โ€” ์œ ๋ฃŒ ๋ชจ๋ธ์€ ์“ฐ์ง€ ์•Š๋Š”๋‹ค). terraยทluna ๋Š” sol ๊ณผ **๊ฐ™์€ ChatGPT oauth(codex) ๊ฒฝ๋กœ**๋กœ ๋Œ๊ณ (`openai-chatgpt-responses` ์‹ค์ธก), `openrouter/free` ๋Š” OpenRouter ๋ฌด๋ฃŒ ํ‹ฐ์–ด๋‹ค. ์•ž์˜ ์…‹์ด ๊ฐ™์€ codex ๊ฒฝ๋กœ๋ผ **codex ๊ฐ€ ํ†ต์งธ๋กœ ์ฃฝ์œผ๋ฉด ์…‹ ๋‹ค ์ฃฝ์œผ๋ฏ€๋กœ**, ๊ทธ๋•Œ๋ฅผ ์œ„ํ•ด provider ๊ฐ€ ๋‹ค๋ฅธ ๋ฌด๋ฃŒ ๋ชจ๋ธ์„ ๋งจ ๋’ค์— ๋’€๋‹ค. โš ๏ธ **`modelPolicy.allow` ๋„ ์ด 4์ข…์œผ๋กœ ์ขํ˜”๋‹ค** โ€” ํด๋ฐฑ ์ˆœ์„œ๋งŒ ๋ฐ”๊พธ๋ฉด ์œ ๋ฃŒ ๋ชจ๋ธ์ด allow ์— ๋‚จ์•„ ์ˆ˜๋™ ์ง€์ • ์‹œ ๊ณผ๊ธˆ๋˜๋ฏ€๋กœ, ํ—ˆ์šฉ ๋ชฉ๋ก ์ž์ฒด์—์„œ ๋นผ๋Š” ๊ฒŒ ์œ ์ผํ•œ ๊ตฌ์กฐ์  ์ฐจ๋‹จ์ด๋‹ค. ์œ ๋ฃŒ๋ฅผ ๋‹ค์‹œ ์“ฐ๋ ค๋ฉด allow ์— ๋จผ์ € ์ถ”๊ฐ€ํ•ด์•ผ ํ•œ๋‹ค. โš ๏ธ `gpt-5.4` ๋Š” **Codex ๊ฒฝ๋กœ์—์„œ ์€ํ‡ด**ํ•ด ์“ธ ์ˆ˜ ์—†๋‹ค(๋ณธ์ฒด๊ฐ€ `gpt-5.6-terra` ๋กœ ๋Œ€์ฒด ์•ˆ๋‚ด). ์ •์  ์นดํƒˆ๋กœ๊ทธ์˜ ์ œ์™ธ ๊ทœ์น™๋งŒ ๋ณด๋ฉด terraยทluna ๊ฐ€ ์•ˆ ๋  ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ด์ง€๋งŒ **์‹ค์ œ๋กœ๋Š” ๋œ๋‹ค** โ€” ์‹ค์ธก์ด ๋‹ต์ด๋‹ค. โš ๏ธ ์ด์ „ ๊ตฌ์„ฑ(`gpt-5.5` primary, ํด๋ฐฑ haikuยทsonnetยท`gpt-5.5-pro`)์—์„œ ์˜จ ์ด์œ : 5.5ยท5.5-pro ๋Š” ์นดํƒˆ๋กœ๊ทธ์ƒ **deprecated**(`replacedBy: gpt-5.6-sol`)์˜€๊ณ  sol ์€ 5.5 ์™€ ๋™์ผ ๋‹จ๊ฐ€๋ผ ๋น„์šฉ ์ฆ๊ฐ€ 0 ์ด์—ˆ๋‹ค. โš ๏ธ **`gpt-6-astra` ๋Š” ์˜๋„์ ์œผ๋กœ ์•ˆ ์“ด๋‹ค**(2026-09-10 ๊ฒ€ํ† ยท์ œ์™ธ): โ‘ ๋‹จ๊ฐ€ $10/$50, 272k ์ดˆ๊ณผ ๊ตฌ๊ฐ„ $20/$75 ๋กœ sol ์˜ 2~2.5๋ฐฐ์ธ๋ฐ ์„ธ ์—์ด์ „ํŠธ ์—…๋ฌด(๋‰ด์Šคยท์ž๋ง‰ ์š”์•ฝ, ๋ถ„๋ฅ˜)์—” ๊ทธ ์ถ”๋ก ์ด ๋ถˆํ•„์š” โ‘กopenclaw ์˜ codex **์ •์  ์นดํƒˆ๋กœ๊ทธ์—์„œ ๋ช…์‹œ์ ์œผ๋กœ ์ œ์™ธ**๋ผ(`buildOpenAICodexStaticProviderConfig` ์˜ `modelId === "gpt-6-astra"` ๋ถ„๊ธฐ) `resolveCodexForwardCompatModel` ์˜ forward-compat ๊ฒฝ๋กœ๋กœ๋งŒ ํ†ต๊ณผํ•˜๋Š” ๋ฏธ๊ฒ€์ฆ ๋ฃจํŠธ โ‘ขprovider ๊ฐ€ `openai` ๋ผ **`codex_fallback_monitor` ๊ฐ€ ๊ฐ์ง€ํ•˜์ง€ ๋ชปํ•œ๋‹ค**(`FALLBACK_PROVIDERS={"openrouter"}`) โ€” 2๋ฐฐ ๋‹จ๊ฐ€๋กœ ์กฐ์šฉํžˆ ๋„๋Š” ์‚ฌ๊ฐ์ง€๋Œ€๊ฐ€ ์ƒ๊ธด๋‹ค. ๋‹ค์‹œ ๋„ฃ์ž๋Š” ์ œ์•ˆ์ด ์˜ค๋ฉด ์ด ์„ธ ๊ฐ€์ง€๋ฅผ ๋จผ์ € ํ™•์ธํ•  ๊ฒƒ - **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`. **์ฆ๊ถŒ ์ด์ฒด ๋งค์นญ**(2026-09-10, `scripts/securities_match.py`): ์€ํ–‰โ†’์ฆ๊ถŒ ์ด์ฒด๋Š” ์€ํ–‰ SMS ์— **์ž…๊ธˆ์ž๋ช…๋งŒ** ์ฐํ˜€ ๋ชฉ์ ์ง€๋ฅผ ์•Œ ์ˆ˜ ์—†์–ด `๋ฐฉํšจ์›` ์ž์ฒด์ด์ฒด ๋ฃฐ โ†’ ์ž๋ณธ ๋ถ„๊ฐœ ๊ฐ€๋“œ์— ๋ง‰ํ˜€ **๋ฏธ๋ฐ˜์˜**๋๊ณ , ๋ฐ˜๋Œ€ํŽธ ์ฆ๊ถŒ ์ž…๊ธˆ์€ SMS ๊ฐ€ ์—†์–ด ์›” 1ํšŒ reconcile ์ฐจ์•ก์ด ์ „๋ถ€ `์ฃผ์‹ํ‰๊ฐ€์ˆ˜์ต` ์œผ๋กœ ๋ถ„๊ฐœ๋ผ **์ด์ฒด๊ฐ€ ์†์ต์œผ๋กœ ๋‘”๊ฐ‘**ํ–ˆ๋‹ค(์–‘์ชฝ ๋™์‹œ ๋ˆ„๋ฝ). ์ด์ œ capital-block ์ง์ „์— ํ‚ค์›€ kt00015 ์—์„œ ์ง(๊ฐ™์€ ๋‚ ยท๊ฐ™์€ ๊ธˆ์•กยท๋ฐ˜๋Œ€ ๋ฐฉํ–ฅยท`is_principal_flow` ์ ์š”)์„ ์ฐพ์•„ `์ฆ๊ถŒ(ํšจ์›) โ† ํ•˜๋‚˜์€ํ–‰(ํšจ์›)` ์ด์ฒด๋กœ ๋ถ„๊ฐœํ•œ๋‹ค. โš ๏ธ **ํ˜ธ์ถœ์€ capital-block ์ง์ „๋ฟ์ด๋ผ ํ‰์‹œ ํ‚ค์›€ ์ฝœ 0**(์ด์ฒด ์žˆ๋Š” ์‚ฌ์ดํด๋งŒ 4์ฝœ). โš ๏ธ **์• ๋งคํ•˜๋ฉด ๋งค์นญ ์•ˆ ํ•œ๋‹ค** โ€” ํ›„๋ณด ์—ฌ๋Ÿฟ์ด๋ฉด ์‹œ๊ฐ ๊ทผ์ ‘(600์ดˆ)์œผ๋กœ ์ขํžˆ๊ณ  ๊ทธ๋ž˜๋„ ์•ˆ ์ค„๋ฉด ํฌ๊ธฐ, ํ•œ ๊ณ„์ขŒ๋ผ๋„ ์กฐํšŒ ์‹คํŒจ๋ฉด ์ „์ฒด ํฌ๊ธฐ. โš ๏ธ **์ฆ๊ถŒ ๊ณ„์ขŒ ๊ฐ„ ๋Œ€์ฒด๋Š” ์ œ์™ธ**(`_drop_internal_transfers` โ€” ํ›„์ž‰์—” ๊ฐ™์€ ์ž์‚ฐ์ด๋ผ ๋ถ„๊ฐœ ๋Œ€์ƒ์ด ์•„๋‹Œ๋ฐ ๊ธˆ์•ก์ด ๊ฐ™์œผ๋ฉด ์˜ค๋งค์นญ). โš ๏ธ **kt00015 ํ–‰์— ๊ณ ์œ  ID ๊ฐ€ ์—†์–ด** ์ค‘๋ณต๋ฐฉ์ง€ ํ‚ค๋Š” `๋‚ ์งœ|๊ณ„์ขŒ|IO|๊ธˆ์•ก|์‹œ๊ฐ` ํ•ฉ์„ฑ(`state/whooing_securities_matched.json`, POST ์„ฑ๊ณต ํ›„์—๋งŒ ๊ธฐ๋ก). ๋ถ€์ˆ˜ํšจ๊ณผ๋กœ **reconcile ์ฐจ์•ก์— ์ˆœ์ˆ˜ ํ‰๊ฐ€์†์ต๋งŒ ๋‚จ๋Š”๋‹ค** - **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_portfolio_report`์™€ ๋™์ผ ๋ฐ์ดํ„ฐ. ๋ฉ”์ผ์€ 2026-08-12๋ถ€ํ„ฐ ๋ฐœ์†ก ์•ˆ ํ•˜๋ฏ€๋กœ **์ด ์›น์ด ๋ฆฌํฌํŠธ๋ฅผ ๋ณด๋Š” ์œ ์ผํ•œ ์ฐฝ๊ตฌ**๋‹ค). 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 ์–ธ๊ธ‰ ์—†์Œ(๋ฏธ๊ตญ ์ „์šฉ) โ€” ์ด ๊ฐ’ ์ถœ์ฒ˜๋Š” ๋น„ํ•˜์ด๋ธŒ๋ฟ. **ํ† ์š”์ผ = ํ•ด์™ธ ์ „์šฉ ๋ธŒ๋ฆฌํ•‘**(2026-08-12): `build_prepare_payload`๊ฐ€ `now.weekday()==5`๋ฉด `overseas_only=True` โ†’ ๋‰ด์Šค๋Š” `OVERSEAS_NEWS_FEEDS`('๊ตญ์ œ' 2๊ฐœ, ๊ตญ๋‚ด๊ฒฝ์ œยท์ฆ์‹œ ์ œ์™ธ)๋งŒ ์“ฐ๊ณ  **์ผ์ •ยทIPOยท๋‚ด์ผ์ƒ์žฅ์€ ์ˆ˜์ง‘ ์ž์ฒด๋ฅผ ์ƒ๋žต**ํ•œ๋‹ค. ๋ถ€์ˆ˜ํšจ๊ณผ ๋‘˜: `gog` 3์ฝœ์ด ์‚ฌ๋ผ์ ธ ์œ ์ผํ•œ ๋‹จ์ผ ์‹คํŒจ์ (`get_today_events`๋Š” try/except๊ฐ€ ์—†์–ด ์‹คํŒจ ์‹œ prepare ์ „์ฒด ์ค‘๋‹จ)์„ ํ† ์š”์ผ์—” ํšŒํ”ผํ•˜๊ณ , IPO๋ฅผ ์•ˆ ์ฝ์œผ๋‹ˆ `mark_ipo_changes_seen`์ด seen์„ ์„ ์ ํ•˜์ง€ ์•Š์•„ **๊ธˆ์š”์ผ sync ๊ฒฐ๊ณผ๊ฐ€ ์›”์š”์ผ ์•„์นจ์— ์ •์ƒ ๋…ธ์ถœ**๋œ๋‹ค. โš ๏ธ `build_html_body`์—์„œ ์ผ์ • ์นด๋“œ๋ฅผ **๋ช…์‹œ์ ์œผ๋กœ ์Šคํ‚ต**ํ•ด์•ผ ํ•œ๋‹ค โ€” `events`๊ฐ€ ๋นˆ ๋ฐฐ์—ด์ด์–ด๋„ `_list_card`๋Š” '์ผ์ • ์—†์Šต๋‹ˆ๋‹ค' ์นด๋“œ๋ฅผ ๋ Œ๋”ํ•œ๋‹ค. ๊ตญ๋‚ด ์นด๋“œ๋Š” `domestic_summary` ์กฐ๊ฑด๋ถ€๋ผ ์ž๋™ ์ œ์™ธ๋˜๊ณ , `_morning_missing_summary_notes`์˜ '๋น„ํ•˜์ด๋ธŒ ์š”์•ฝ ์—†์Œ' ๊ฐ์ฃผ๋„ `overseas_only`๋ฉด ์–ต์ œ(์˜๋„๋œ ๋ถ€์žฌ๋ผ ๋…ธ์ด์ฆˆ). **๋‰ด์Šค ์ค‘๋ณต์ œ๊ฑฐ 3๋‹จ**: โ‘ ์‹คํ–‰ ๋‚ด ์ •๊ทœํ™” ์ œ๋ชฉ ์™„์ „์ผ์น˜ โ‘ก์‹คํ–‰ ๋‚ด ํ† ํฐ min-overlap โ‰ฅ`NEWS_DUP_THRESHOLD`(0.40) โ‘ข48h ๋ฐœ์†ก์ด๋ ฅ โ€” โ‘ข์€ ์˜ค๋ž˜ **์™„์ „์ผ์น˜๋ฟ**์ด๋ผ '๊ฐ™์€ ์‚ฌ์•ˆ ๋‹ค๋ฅธ ์ œ๋ชฉ'์ด ์˜คํ›„์— ์žฌ๋“ฑ์žฅํ–ˆ๊ณ , 2026-08-12 `recent_history_token_sets()`๋กœ ์ด๋ ฅ ์ œ๋ชฉ์˜ ํ† ํฐ ์ง‘ํ•ฉ์„ ๋งŒ๋“ค์–ด `collect_news_articles(exclude_token_sets=)`์— ๋„˜๊ฒจ โ‘ก์˜ fuzzy๋ฅผ ์ด๋ ฅ์—๋„ ์ ์šฉํ–ˆ๋‹ค(์‹ค์ธก: ์˜ค์ „ ๋ฐœ์†ก๋ถ„๊ณผ ๊ฐ™์€ ์‚ฌ์•ˆ 2๊ฑด์ด ์ €๋… ํ›„๋ณด์—์„œ ๊ฑธ๋Ÿฌ์ง€๊ณ  ๊ทธ ์ž๋ฆฌ์— ์ƒˆ ๊ธฐ์‚ฌ๊ฐ€ ์ฑ„์›Œ์ง). โš ๏ธ **ํ•œ๊ตญ์–ด ์กฐ์‚ฌยท๋ณตํ•ฉ๋ช…์‚ฌ ๋•Œ๋ฌธ์— ๊ฐ™์€ ์‚ฌ์•ˆ์ด 0.40 ์•„๋ž˜๋กœ ๋–จ์–ด์ง€๋Š” ์Œ์ด ๋‚จ์•„ ์žˆ๋‹ค**(์‹ค์ธก 'ํŠธ๋Ÿผํ”„ ๊ณจํ”„์žฅ์— ์ด๋™์‹ ๋ฐฉ๊ณต๋ฏธ์‚ฌ์ผ' vs '๊ณจํ”„์žฅ์— ๋ฐฉ๊ณต ๋ฏธ์‚ฌ์ผโ€ฆํŠธ๋Ÿผํ”„์˜ ์•”์‚ด ๋…ธ์ด๋กœ์ œ' = 0.29). ๋ฌธํ„ฑ์„ ๋‚ฎ์ถ”๋ฉด ์˜คํƒ์ด ๋Š˜์–ด ์†๋Œ€์ง€ ์•Š์•˜๋‹ค โ€” ๋” ์ค„์ด๋ ค๋ฉด ํ† ํฌ๋‚˜์ด์ €(์กฐ์‚ฌ ์ ˆ๋‹จยท๋ฌธ์ž n-gram)๋ฅผ ๊ณ ์น˜๋Š” ์ชฝ. โš ๏ธ `prepare`๋Š” `already_sent`๋ฉด `briefing_pending_selection.json`์„ **๋ฎ์–ด์“ฐ์ง€ ์•Š๋Š”๋‹ค**(2026-08-12) โ€” ๊ทธ์ „์—” 08:30 ํด๋ฐฑ์ด ์Šคํ‚ต ์ง์ „์— ๊ธฐ์‚ฌ๋ฅผ ์žฌ์„ ๋ณ„ํ•ด ๋ฐœ์†ก๋ณธ๊ณผ ๋ฌด๊ด€ํ•œ ๋ชฉ๋ก์„ ๋‚จ๊ฒผ๊ณ (์‹ค์ธก ๋ฐœ์†ก 7๊ฑด vs ํŒŒ์ผ 4๊ฑด, ๊ต์ง‘ํ•ฉ 0), ์ด ํŒŒ์ผ์ด '๊ฐ™์€ ๋‰ด์Šค๊ฐ€ ๋˜ ์™€?' ๋””๋ฒ„๊น… ์ง„์ž…์ ์ด๋ผ ํ‹€๋ฆฐ ์ฆ๊ฑฐ๋ฅผ ๋ณด๊ฒŒ ๋๋‹ค - `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]` - `chat_web.py` โ€” **์›น ์ฑ„ํŒ…**(2026-10-07). `chat.hyowons.net`์—์„œ ํด๋กœยท๋ ˆ์ดยท๊ณจ๋””์™€ ํ…”๋ ˆ๊ทธ๋žจ์ฒ˜๋Ÿผ ๋Œ€ํ™”ํ•˜๋Š” ์ž์ฒด ์›น(ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋‹จ์ผ ํŒŒ์ผ, ํฌํŠธ 18793, launchd `ai.openclaw.chat-web` ์ƒ์‹œ). **Tailscale ์—†์ด** NAS ๋ฆฌ๋ฒ„์Šค ํ”„๋ก์‹œ๋กœ ๊ณต๊ฐœ๋˜๋ฏ€๋กœ(์™€์ผ๋“œ์นด๋“œ DNS๋ผ ํ”„๋ก์‹œ ๊ทœ์น™๋งŒ ์ถ”๊ฐ€) ๋กœ๊ทธ์ธ์€ **๋ณธ์ธ iMessage OTP ๋‹จ๋…**(`[์ธ์ฆ ์ฝ”๋“œ ๋ฐ›๊ธฐ]` โ†’ `@chat.hyowons.net #์ฝ”๋“œ` iOS ์ž๋™์ž…๋ ฅ, 5๋ถ„) โ†’ 30์ผ ์„ธ์…˜ ์ฟ ํ‚ค(HttpOnlyยทSecureยทLax, ์„œ๋ฒ„์—” sha256๋งŒ `state/chat_web/auth.json`). โš ๏ธ **๋น„๋ฐ€๋ฒˆํ˜ธ๋Š” ์—†๋‹ค**(2026-10-07 ๊ด€๋ฆฌ์ž๋‹˜ ๊ฒฐ์ • โ€” ์ฒ˜์Œ์—” ๋น„๋ฐ€๋ฒˆํ˜ธ+OTP 2๋‹จ๊ณ„๋กœ ๋งŒ๋“ค์—ˆ๋‹ค๊ฐ€ ์ œ๊ฑฐ). ๊ทธ๋ž˜์„œ ๋ˆ„๊ตฌ๋‚˜ '์ฝ”๋“œ ๋ฐ›๊ธฐ'๋ฅผ ๋ˆ„๋ฅผ ์ˆ˜ ์žˆ์–ด **๋ฐœ์†ก ์ œํ•œ**์ด ํ•ต์‹ฌ ๋ฐฉ์–ด๋‹ค โ€” 1๋ถ„ 1ํšŒยท1์‹œ๊ฐ„ 5ํšŒ, ๋„˜์œผ๋ฉด 15๋ถ„ ์ž ๊ธˆ. ์ฝ”๋“œ๋ฅผ 15๋ถ„ ์•ˆ์— 5ํšŒ ํ‹€๋ ค๋„(**IP ๋ฌด๊ด€ ์ „์—ญ**) 15๋ถ„ ์ž ๊ธˆ. ๋‘˜ ๋‹ค ์ž ๊ธธ ๋•Œ + ํด๋กœ ํ…”๋ ˆ๊ทธ๋žจ ์•Œ๋ฆผ(`codex_fallback_monitor._send_telegram` ์žฌ์‚ฌ์šฉ). API POST๋Š” ์„ธ์…˜ + `X-CW: 1` ํ—ค๋” ํ•„์ˆ˜(๊ต์ฐจ ์ถœ์ฒ˜ ์š”์ฒญ ์ฐจ๋‹จ). ์—์ด์ „ํŠธ ํ˜ธ์ถœ์€ `openclaw agent --agent --session-key webโ€ฆ --message-file โ€ฆ --json`(๊ฒŒ์ดํŠธ์›จ์ด ๊ฒฝ์œ  โ€” ๊ฒŒ์ดํŠธ์›จ์ด ์ž์ฒด๋Š” ์™ธ๋ถ€์— ์•ˆ ์—ฐ๋‹ค). โš ๏ธ **์„ธ์…˜ ํ‚ค๊ฐ€ ํ…”๋ ˆ๊ทธ๋žจ๊ณผ ๋‹ฌ๋ผ ์›น ๋Œ€ํ™”๋Š” ๋ณ„๋„ ๋งฅ๋ฝ**์ด๊ณ , `--deliver` ๋ฏธ์ง€์ •์ด๋ผ ๋‹ต์ด ํ…”๋ ˆ๊ทธ๋žจ์œผ๋กœ ๋‚˜๊ฐ€์ง€ ์•Š๋Š”๋‹ค(๊ด€๋ฆฌ์ž๋‹˜ ์„ ํƒ). '์ƒˆ ๋Œ€ํ™” ์‹œ์ž‘'์€ ์„ธ์…˜ ํ‚ค๋ฅผ `web-<์‹œ๊ฐ>`์œผ๋กœ ๋ฐ”๊พผ๋‹ค(`state/chat_web/session_keys.json`). **๋ช…๋ น์–ด**: ์Šฌ๋ž˜์‹œ ๋ช…๋ น์€ ๊ทธ๋Œ€๋กœ ์—์ด์ „ํŠธ์— ์ „๋‹ฌ๋ผ OpenClaw ๋ณธ์ฒด๊ฐ€ ์ฒ˜๋ฆฌํ•œ๋‹ค(`/new`=๋ณธ์ฒด๊ฐ€ ์„ธ์…˜ ๋ฆฌ์…‹ `โœ… New session started.`, `/status`=LLM์ด session_status ๋„๊ตฌ๋กœ ๋‹ตํ•จ โ€” ์‹ค์ธก). **`/clear`๋งŒ ์›น ์ „์šฉ**์œผ๋กœ ์„œ๋ฒ„๊ฐ€ ๊ฐ€๋กœ์ฑ„ ํ™”๋ฉด ๊ธฐ๋ก์„ `history/archive/`๋กœ ์˜ฎ๊ธฐ๊ณ (์‚ญ์ œ X) ์„ธ์…˜ ํ‚ค๋ฅผ ์ƒˆ๋กœ ๋ฐ”๊พผ๋‹ค(์—์ด์ „ํŠธ ํ˜ธ์ถœ ์—†์Œ). ์—์ด์ „ํŠธ๋‹น ๋™์‹œ 1๊ฑด(๋‹ต ๊ธฐ๋‹ค๋ฆฌ๋Š” ์ค‘ ์ „์†ก์€ 409). ํ™”๋ฉด ๊ธฐ๋ก `state/chat_web/history/.jsonl`(์ตœ๊ทผ 300์ค„ ํ‘œ์‹œ). ํด๋ผ์ด์–ธํŠธ๋Š” ๋‹ต์„ ๊ธฐ๋‹ค๋ฆด ๋•Œ๋งŒ 2์ดˆ, ํ‰์†Œ์—” 20์ดˆ๋งˆ๋‹ค ํด๋ง โ€” ์—์ด์ „ํŠธ๊ฐ€ ๋จผ์ € ๋ง์„ ๊ฑฐ๋Š” ๊ฒฝ๋กœ๋Š” ์—†๋‹ค(ํฌ๋ก  ์•Œ๋ฆผ์€ ์—ฌ์ „ํžˆ ํ…”๋ ˆ๊ทธ๋žจ). โš ๏ธ OTPยท๋กœ๊ทธ์ธ ๋Œ€๊ธฐ ์ƒํƒœ๋Š” ๋ฉ”๋ชจ๋ฆฌ์—๋งŒ ์žˆ์–ด ์„œ๋ฒ„ ์žฌ์‹œ์ž‘ ์‹œ ๋กœ๊ทธ์ธ ์ค‘์ด๋˜ ์‚ฌ๋žŒ์€ ์ฒ˜์Œ๋ถ€ํ„ฐ ๋‹ค์‹œ ํ•œ๋‹ค. **์„ ํƒ์ง€ ๋ฒ„ํŠผ**(2026-10-07, ๋‘ ๋ฐฉ์‹ ๋ณ‘ํ–‰ โ€” ๊ด€๋ฆฌ์ž๋‹˜ ์„ ํƒ): โ‘ **์—์ด์ „ํŠธ ์ง€์ •** โ€” ์›น์—์„œ ๋ณด๋‚ด๋Š” ๋ฉ”์‹œ์ง€์—๋งŒ `WEB_HINT`("๊ณ ๋ฅผ ์งˆ๋ฌธ์ด๋ฉด ๋งˆ์ง€๋ง‰ ์ค„์— `[[๋ฒ„ํŠผ: A | B]]`")๋ฅผ ๋ง๋ถ™์—ฌ ์—์ด์ „ํŠธ์— ์ „๋‹ฌํ•˜๊ณ , ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋งˆ์ปค๋ฅผ ์ˆจ๊ธฐ๊ณ  ๋ฒ„ํŠผ์œผ๋กœ ๊ทธ๋ฆฐ๋‹ค. ํ™”๋ฉด ๊ธฐ๋ก์—” ์›๋ฌธ๋งŒ ์ €์žฅ(์•ˆ๋‚ด๋Š” ์•ˆ ๋ณด์ž„). โš ๏ธ **์Šฌ๋ž˜์‹œ ๋ช…๋ น์—” ์•ˆ๋‚ด๋ฅผ ๋ถ™์ด์ง€ ์•Š๋Š”๋‹ค**(`/new` ๋“ฑ ๋ณธ์ฒด ๋ช…๋ น์ด ๊นจ์ง„๋‹ค). โš ๏ธ **AGENTS.md ์— ๋„ฃ์ง€ ์•Š์€ ์ด์œ ** โ€” ํ…”๋ ˆ๊ทธ๋žจ์—” ๋ฒ„ํŠผ์ด ์—†์–ด ๋งˆ์ปค๊ฐ€ ๋‚ ๊ฒƒ์œผ๋กœ ๋ณด์ด๊ณ , ํ…”๋ ˆ๊ทธ๋žจ ๋ฉ”ํƒ€ ๊ทœ์น™์€ ๋ถ€์ž‘์šฉ ์ „๋ก€๊ฐ€ ์žˆ๋‹ค. ์‹ค์ธก ๊ณจ๋””ยทํด๋กœ ๋ชจ๋‘ ํ˜•์‹์„ ์ง€์ผฐ๊ณ  ๋งˆ์ปค ์œ„์น˜๋Š” `[๋‹ต๋ณ€์™„๋ฃŒ]` ์•ž๋’ค๊ฐ€ ์„ž์—ฌ ๋‚˜์™€ ์–ด๋””์— ์žˆ์–ด๋„ ํŒŒ์‹ฑํ•œ๋‹ค โ‘ก**๋ฌธ์žฅ ์ถ”์ถœ(ํด๋ฐฑ)** โ€” ๋งˆ์ปค๊ฐ€ ์—†์„ ๋•Œ๋งŒ, ๋‹ต๋ณ€ ์† `"์ˆ˜์ •ํ•ด์ค˜"๋ผ๊ณ `ยท`'์ทจ์†Œ'๋ผ๊ณ ` ๊ฐ™์€ **๋”ฐ์˜ดํ‘œ+(์ด)๋ผ๊ณ ** ํ‘œํ˜„์„ `choices()` ๊ฐ€ ๋ฝ‘๋Š”๋‹ค. ๋ˆ„๋ฅด๋ฉด ๊ทธ ๋ฌธ๊ตฌ๋ฅผ ๊ทธ๋Œ€๋กœ ๋ณด๋‚ธ๋‹ค(์ž…๋ ฅ์ฐฝ ์ดˆ์•ˆ์€ ์•ˆ ๊ฑด๋“œ๋ฆผ). โš ๏ธ **๋งˆ์ง€๋ง‰ ๋ฉ”์‹œ์ง€๊ฐ€ ์—์ด์ „ํŠธ ๋‹ต๋ณ€์ผ ๋•Œ๋งŒ** ๋„์šด๋‹ค โ€” ์ง€๋‚œ ๋‹ต๋ณ€์˜ ๋ฒ„ํŠผ์€ ์ด๋ฏธ ๋๋‚œ ์งˆ๋ฌธ์ด๋‹ค. ๋‹ต์„ ๊ธฐ๋‹ค๋ฆฌ๋Š” ๋™์•ˆ ๋ฒ„ํŠผ์€ ๋น„ํ™œ์„ฑ. **์—์ด์ „ํŠธ ์ „ํ™˜**์€ ํƒญ์ด ์•„๋‹ˆ๋ผ ์ž…๋ ฅ์ฐฝ ์™ผ์ชฝ ์›ํ˜• ๋ฒ„ํŠผ(ํ˜„์žฌ ์—์ด์ „ํŠธ ์ด๋ชจ์ง€) โ†’ ์œ„๋กœ ๋œจ๋Š” ๋ชฉ๋ก์—์„œ ๊ณ ๋ฅธ๋‹ค(2026-10-07 ๊ด€๋ฆฌ์ž๋‹˜ ์ง€์ • โ€” ์ƒ๋‹จยทํ•˜๋‹จ ํƒญ ๋ชจ๋‘ ๊ฑฐ์ณ์„œ ๋ฐ”๊ฟˆ). ๋‹ค๋ฅธ ์—์ด์ „ํŠธ์— ์•ˆ ์ฝ์€ ๋‹ต์ด ์žˆ์œผ๋ฉด ๋ฒ„ํŠผ๊ณผ ๋ชฉ๋ก ํ•ญ๋ชฉ์— ๋นจ๊ฐ„ ์ . **๋ชจ๋ฐ”์ผ(โ‰ค600px)์€ ์•ฝ 80% ํฌ๊ธฐ**(๋ณธ๋ฌธ 12px, ์ž…๋ ฅ์นธ 13px) โ€” ์ž…๋ ฅ์นธ์ด 16px ๋ฏธ๋งŒ์ด๋ฉด iOS ๊ฐ€ ํฌ์ปค์Šค ๋•Œ ํ™•๋Œ€ํ•˜๋ฏ€๋กœ viewport ์— `maximum-scale=1` ์„ ๋„ฃ์—ˆ๋‹ค. **๐Ÿ›  ์ฝ”๋”” ํ•ญ๋ชฉ**(2026-10-07): ๋ชฉ๋ก ๋งจ ์•„๋ž˜ ์ฝ”๋””๋Š” ์ด ์›น์˜ ๋Œ€ํ™” ์ƒ๋Œ€๊ฐ€ **์•„๋‹ˆ๋‹ค** โ€” ๋ˆ„๋ฅด๋ฉด `POST /api/cody` ๊ฐ€ `~/.openclaw` workdir ์˜ remote-control ์„ธ์…˜์„ ์ฐพ์•„ **๋–  ์žˆ์œผ๋ฉด ์žฌ์‚ฌ์šฉ, ์—†์œผ๋ฉด `session_tool.py session open openclaw` ๋กœ ๊ธฐ๋™**ํ•˜๊ณ , ์„ธ์…˜ ๋กœ๊ทธ(`logs/claude-session-.log`)์˜ **๋งˆ์ง€๋ง‰ ํ™”๋ฉด ํ”„๋ ˆ์ž„**์—์„œ ์ฃผ์†Œ๋ฅผ ๋ฝ‘์•„ `[Claude ์•ฑ์—์„œ ์—ด๊ธฐ]` ๋ฒ„ํŠผ์œผ๋กœ ์ค€๋‹ค(์—ฐ๊ฒฐ๋œ ์„ธ์…˜์ด ์žˆ์œผ๋ฉด `claude.ai/code/session_โ€ฆ` ์งํ†ต, ์—†์œผ๋ฉด `?environment=env_โ€ฆ` ์ง„์ž…). โš ๏ธ ์ž๋™ ์ด๋™์ด ์•„๋‹ˆ๋ผ ๋ฒ„ํŠผ์ธ ์ด์œ  โ€” iOS ๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ์ง์ ‘ ๋ˆ„๋ฅธ ๋งํฌ์—ฌ์•ผ ์œ ๋‹ˆ๋ฒ„์„ค ๋งํฌ๋กœ Claude ์•ฑ์„ ์—ฐ๋‹ค. โš ๏ธ ์›น์—์„œ ์ฝ”๋””์™€ ๋Œ€ํ™”ํ•˜์ง€ ์•Š๋Š” ์ด์œ  โ€” ์Šน์ธ ํ”„๋กฌํ”„ํŠธ๋ฅผ ๋ชป ๋„์›Œ ์ฝ๊ธฐ์ „์šฉ/๋ฌด์Šน์ธ ์ „๊ถŒ ๋‘˜ ์ค‘ ํ•˜๋‚˜๊ฐ€ ๋˜๊ณ , ๋ฌด์Šน์ธ ์ „๊ถŒ์ด๋ฉด OTP ํ•˜๋‚˜๋กœ ๋งฅ ์ „์ฒด๋ฅผ ์กฐ์ž‘ํ•˜๋Š” ์›น์ด ๋œ๋‹ค(๊ด€๋ฆฌ์ž๋‹˜๊ณผ ๊ฒ€ํ†  ํ›„ ์ด ๋ฐฉ์‹ ์„ ํƒ). ์‹ค์ œ ๋Œ€ํ™”๋Š” Claude ์•ฑ์—์„œ ํ•˜๋ฏ€๋กœ Anthropic ๋กœ๊ทธ์ธ์ด ๋ณดํ˜ธ๋ง‰์ด๋‹ค. ๋Œ€์ƒ์€ `CLAUDE_TARGETS`(session_tool ํ”„๋กœํ•„๋ช…ยทํ‘œ์‹œ๋ช…ยท์ด๋ชจ์ง€) โ€” ํ˜„์žฌ `openclaw`=๐Ÿ›  ์ฝ”๋””, `develop2025`=๐ŸŒ‹ Averno(2026-10-07 ์ถ”๊ฐ€). workdir ์€ ํ”„๋กœํ•„์—์„œ ์ฝ์–ด **๊ฐ™์€ workdir ์˜ running ์„ธ์…˜**์„ ์žฌ์‚ฌ์šฉํ•˜๊ณ , ๋ชฉ๋ก์— ์—†๋Š” ํ”„๋กœํ•„์€ ๊ฑฐ๋ถ€ํ•œ๋‹ค. ์ƒˆ ๋Œ€์ƒ์€ session_tool ์— ํ”„๋กœํ•„์„ ๋จผ์ € ๋“ฑ๋กํ•˜๊ณ  ์ด ์ƒ์ˆ˜์— ํ•œ ์ค„ ์ถ”๊ฐ€. ์‹ค์ธก ์ƒˆ ๊ธฐ๋™ 3.5์ดˆ. ์„ธ์…˜์€ ์ž๋™์œผ๋กœ ๋‹ซํžˆ์ง€ ์•Š๋Š”๋‹ค โ€” ๋‹ซ๊ธฐ๋Š” ๊ธฐ์กด๋Œ€๋กœ ํด๋กœ์—๊ฒŒ '์„ธ์…˜ ๋‹ซ์•„์ค˜'. **ํ™ˆ ํ™”๋ฉด ์•„์ด์ฝ˜**์€ `chat_web_icon.png`(180px, ๊ฐ™์€ ํด๋”)๋ฅผ `/apple-touch-icon.png` ๋กœ **์ธ์ฆ ์—†์ด** ์„œ๋น™ํ•œ๋‹ค(iOS ๋Š” ์ด๊ฒŒ ์—†์œผ๋ฉด ์ œ๋ชฉ ์ฒซ ๊ธ€์ž '์ฑ„'๋กœ ์•„์ด์ฝ˜์„ ๋งŒ๋“ ๋‹ค). ์•„์ด์ฝ˜์„ ๋ฐ”๊พธ๋ฉด iOS ๋Š” ์บ์‹œํ•˜๋ฏ€๋กœ ํ™ˆ ํ™”๋ฉด์—์„œ ์ง€์šฐ๊ณ  ๋‹ค์‹œ ์ถ”๊ฐ€ํ•ด์•ผ ๋ฐ˜์˜๋œ๋‹ค - `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}` - `net_worth_backfill.py` โ€” **์ž์‚ฐ์›น ์†์ต์ฐจํŠธ ๊ณผ๊ฑฐ ๊ตฌ๊ฐ„ ์ฑ„์šฐ๊ธฐ**(2026-10-02, 1ํšŒ์„ฑ CLI, ์กฐํšŒ ์ „์šฉ). ์Šค๋ƒ…์ƒท์ด ์ฐจํŠธ์— ์“ธ ์ˆ˜ ์žˆ๋Š” ํ˜•์‹(holdings+deposit)์œผ๋กœ ์‹œ์ž‘ํ•˜๋Š” 2026-05-01 **์ด์ „**์„ ํ‚ค์›€ `kt00002`(์ผ๋ณ„์ถ”์ •์˜ˆํƒ์ž์‚ฐํ˜„ํ™ฉ, ๊ณ„์ขŒ๋ณ„ ์ผ๋ณ„ ์ด์ž์‚ฐ)๋กœ ์ฑ„์›Œ `state/net_worth_history.json`(`days: {date: {owner: {net, cash_in?, cash_out?}}}`)์— ์ €์žฅ. behive_web ์˜ `_load_net_worth_series`ยท`_load_cash_flow_by_date`ยท`_available_chart_periods` ๊ฐ€ ๊ฒฝ๊ณ„์ผ ์ด์ „ ๊ตฌ๊ฐ„์— ์ด ํŒŒ์ผ์„ ์ด์–ด ๋ถ™์ธ๋‹ค(๊ทธ ๊ตฌ๊ฐ„์˜ ์˜› ํ˜•์‹ ์Šค๋ƒ…์ƒท์€ ๋ฒ„๋ฆผ). ํ˜„์žฌ ์ ์žฌ 2025-01-02~2026-04-30, 323๊ฑฐ๋ž˜์ผ. โš ๏ธ **์กฐํšŒ 1ํšŒ 6๊ฐœ์›” ๋ฏธ๋งŒ**(`501067`) โ†’ 170์ผ ์ฐฝ. โš ๏ธ kt00002 ๋Š” **์ฃผ๋งยทํœด์žฅ์ผ ํ–‰๋„ ์˜จ๋‹ค** โ†’ KOSPI ์ผ๋ณ„์ข…๊ฐ€๊ฐ€ ์žˆ๋Š” ๋‚ (`state/sim/index_history.json`, 2024-10~)๋งŒ ๋‚จ๊ธด๋‹ค(`market_holidays.json` ์€ 2026๋…„๋ถ€ํ„ฐ๋ผ ๋ชป ์“ด๋‹ค). โš ๏ธ **๊ฐ’ ๊ธฐ์ค€์ด ์Šค๋ƒ…์ƒท๊ณผ ๋‹ค๋ฅด๋‹ค** โ€” KRX ์ข…๊ฐ€ ํ‰๊ฐ€์—์„œ ์ถ”์ • ๋งค๋„๋น„์šฉ(์•ฝ 0.18%)์„ ๋บ€ ๊ฐ’์ด๊ณ , ์Šค๋ƒ…์ƒท์€ 20:10 NXT ๊ฐ€๊ฒฉ. ๊ทธ๋ž˜์„œ ๊ฒฝ๊ณ„์ผ ๋น„์œจ๋กœ owner ๋ณ„ ์Šค์ผ€์ผ(์•ฝ 1.002)์„ ๊ณฑํ•ด ๋‹จ์ฐจ๋ฅผ ์—†์•ค๋‹ค. 5~9์›” ๊ฒน์น˜๋Š” 103์ผ ๋น„๊ต ์‹œ ๊ฐ€ํฌ๋Š” 91์ผ์ด 0.3% ์ด๋‚ด๋กœ ๋งž์•˜์ง€๋งŒ **๋ณธ์ธ์€ ํŠน์ • ETF(์ฝ”์Šค๋‹ฅ150๋ ˆ๋ฒ„๋ฆฌ์ง€ ๋“ฑ) ๋ณด์œ  ๊ตฌ๊ฐ„์— 1~2.5% ๋‚ฎ๊ฒŒ** ๋‚˜์™”๋‹ค(์›์ธ ๋ฏธํ™•์ •) โ€” ๊ณผ๊ฑฐ ๊ตฌ๊ฐ„์—๋„ ๋น„์Šทํ•œ ์˜ค์ฐจ๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ๋‹ค. ์ž…์ถœ๊ธˆ์€ `investment_principal` ์บ์‹œ(kt00015, ํ‚ค์›€ ์ฝœ 0)์˜ **์ „์ฒด ์ž…์ถœ๊ธˆ**(๋ฐฐ๋‹นยท์ด์ž ํฌํ•จ โ€” ์Šค๋ƒ…์ƒท `cash_in` ๊ณผ ๊ฐ™์€ ์˜๋ฏธ). ๊ณ„์ขŒ๋ณ„ ๋ฐ์ดํ„ฐ ์‹œ์ž‘: ๊ฐ€ํฌ_์ผ๋ฐ˜ 2018-11, ์ผ๋ฐ˜ 2021-01, ISA 2025-11, ๊ฐ€ํฌ_ISA 2026-01. โš ๏ธ ๊ฒฐ๊ณผ ํŒŒ์ผ์€ `state/` ๋ผ git ์— ์•ˆ ๋“ค์–ด๊ฐ„๋‹ค(.gitignore) โ€” ์ง€์›Œ์ง€๋ฉด ์ด CLI ๋กœ ๋‹ค์‹œ ๋งŒ๋“ ๋‹ค. CLI: `python3 net_worth_backfill.py [--from YYYY-MM-DD] [--dry-run]` - `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ยทํ’€๋งค๋„)์€ ์ž”๊ณ ์— ์—†์–ด ๋ณ„๋„ [๋‹น์ผ์ •์‚ฐ] ์นด๋“œ๋กœ ํ‘œ์‹œ. โš ๏ธ **๋ฉ”์ผ ๋ฐœ์†ก ์ค‘์ง€ โ€” 2026-08-12 ๊ด€๋ฆฌ์ž๋‹˜ ๊ฒฐ์ •**(๋ฉ”์ผ ํ†ต์ˆ˜ ์ถ•์†Œ). launchd๋Š” `send --no-mail`๋กœ ๋Œ์•„ **์Šค๋ƒ…์ƒท๋งŒ** ๋‚จ๊ธด๋‹ค(`state/portfolio_daily_snapshot.json` = ์ž์‚ฐ์›น '๋‹น์ผ ํ‰๊ฐ€์†์ต'ยท`rebase_to_nxt_close` ์ „์ผ baseline์˜ ๊ทผ๊ฑฐ๋ผ ๊ณ„์† ํ•„์š”). `--no-mail`์€ `send` ๊ฒฝ๋กœ์˜ ํœด์žฅ์ผ self-skipยท์‹คํŒจ ์ž๊ฐ€์•Œ๋ฆผ์„ ์œ ์ง€ํ•˜๊ณ  `send_mail` ํ˜ธ์ถœ๋งŒ ๊ฑด๋„ˆ๋›ด๋‹ค(`MAIL_SKIPPED=no_mail_flag`) โ€” **`run`์œผ๋กœ ๋Œ€์ฒด ๊ธˆ์ง€**(ํœด์žฅ์ผ ๊ฐ€๋“œ๊ฐ€ `send` ๋ถ„๊ธฐ์—๋งŒ ์žˆ์–ด ํœด์žฅ์ผ ํ‚ค๊ฐ€ ์ด๋ ฅ์— ์„ž์ด๊ณ  ํ‰๋ฌธ 100์—ฌ ์ค„์ด ๋กœ๊ทธ๋กœ ์Ÿ์•„์ง„๋‹ค). ๋ฆฌํฌํŠธ ๋ณธ๋ฌธ์„ ๋ˆˆ์œผ๋กœ ๋ณผ ๋• ์ˆ˜๋™ `run`(`/tmp/stock_report_preview.html`). โš ๏ธ ํ…”๋ ˆ๊ทธ๋žจ ์š”์•ฝ ์ฝ”๋“œ(`tg_text`, ~104์ค„)๋Š” 2026-05-14 ๋น„ํ™œ์„ฑ ์ดํ›„ **์™„์ „ํ•œ ๋ฐ๋“œ์ฝ”๋“œ**๊ฐ€ ๋๋‹ค โ€” ๋˜์‚ด๋ฆด ๋• `main`์˜ ๋ฐœ์†ก ๋ถ„๊ธฐ๋งŒ ๊ณ ์น˜๋ฉด ๋˜๊ณ , ์ •๋ฆฌํ•  ๋• ๊ด€๋ฆฌ์ž๋‹˜ ํ™•์ธ ํ›„ - `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` โ€” ํ•œ๊ตญ(KRX) ํœด์žฅ์ผ โ†’ `state/market_holidays.json`. โš ๏ธ **์ด ํŒŒ์ผ์€ behive_web ๋งŒ ์“ฐ๋Š” ๊ฒŒ ์•„๋‹ˆ๋ผ ๋ ˆ์ด ์ž๋™ํ™” ๋Œ€๋ถ€๋ถ„์˜ ํœด์žฅ์ผ ํŒ์ • ๊ธฐ์ค€**์ด๋‹ค โ€” `trailing_monitor`ยท`surge_monitor`ยท`watchlist_monitor`(์žฅ์ค‘ ๊ฐ์‹œ self-skip), `stock_portfolio_report`ยท`trade_journal`ยท`market_indicators_sync`(EOD ์ ์žฌ self-skip), `behive_web`ยท`realtime_hub`ยท`sim`(์ž๋™๊ฐฑ์‹ ยท์Šค์บ” ํ™œ์„ฑ ํŒ์ •). ํ‹€๋ ค๋„ ์ž˜๋ชป๋œ ๋งค๋งค๋Š” ์—†๊ณ  ์ž๋™ํ™”๊ฐ€ ํ—›๋Œ๋ฉฐ ๋กœ๊ทธยทAPI ์ฝœ๋งŒ ์“ด๋‹ค. โš ๏ธ **2026-09-10 ๋ถ€ํ„ฐ investing.com ์ด 403(๋ด‡ ์ฐจ๋‹จ)์ด๋ผ ์‚ฌ์‹ค์ƒ nager ๋‹จ๋… ์šด์˜**(`source_used` ํ•„๋“œ๋กœ ๊ตฌ๋ถ„). KRX ๊ณต์‹(data.krx.co.kr)๋„ `LOGOUT` ๋งŒ ๋ฐ˜ํ™˜ํ•ด ๋Œ€์•ˆ์ด ๋ชป ๋œ๋‹ค. ์‹ค์ธก์ƒ nager ๋‹จ๋… ๊ฒฐ๊ณผ๊ฐ€ ์ง์ „ investing ๋ฐ์ดํ„ฐ 16์ผ๊ณผ **์™„์ „ํžˆ ์ผ์น˜**ํ•ด ์ •ํ™•๋„ ์†์‹ค์€ ํ™•์ธ๋˜์ง€ ์•Š์•˜๋‹ค(์ด๋ฆ„ ํ‘œ๊ธฐ๋งŒ ๋‹ค๋ฆ„: ๊ทผ๋กœ์ž์˜ ๋‚ โ†’๋…ธ๋™์ ˆ ๋“ฑ). โš ๏ธ nager ๋Š” '๊ณตํœด์ผ'์ด๋ผ **๊ฑฐ๋ž˜์†Œ ์ „์šฉ ํœด์žฅ์ธ ์—ฐ๋ง ํ์žฅ์ผ(12/31)์ด ์—†๋‹ค** โ†’ ํ‰์ผ์ผ ๋•Œ๋งŒ `์—ฐ๋ง ํœด์žฅ`์œผ๋กœ ๋ณด๊ฐ•ํ•œ๋‹ค(investing ๋ฐ์ดํ„ฐ์—๋„ ์—†์–ด์„œ ์›๋ž˜ ๋ˆ„๋ฝ๋ผ ์žˆ๋˜ ๋‚ ). โš ๏ธ **๋ฏธ๋ฐœํ‘œ ์—ฐ๋„ ์˜ค์—ผ ๋ฐฉ์ง€ ๊ฒŒ์ดํŠธ**: KRX ๋Š” ๋‹ค์Œ ํ•ด ํœด์žฅ ์บ˜๋ฆฐ๋”๋ฅผ 11~12์›”์— ๋ฐœํ‘œํ•œ๋‹ค. investing ์ด ์‚ด์•„ ์žˆ์œผ๋ฉด '๊ทธ ์—ฐ๋„๋ฅผ ์žก์•˜๋‹ค'๋Š” ๊ฒŒ ๋ฐœํ‘œ ์‹ ํ˜ธ๋ผ ๊ทธ ์—ฐ๋„๋งŒ ์ฑ„์› ๋Š”๋ฐ, investing ์ด ์ฃฝ์€ ์ง€๊ธˆ์€ **๋‹ฌ๋ ฅ์œผ๋กœ ๋Œ€์‹  ํŒ์ •**ํ•œ๋‹ค โ€” ์˜ฌํ•ด๋Š” ํ•ญ์ƒ, ๋‚ด๋…„์€ **11์›” ์ดํ›„์—๋งŒ**. ๊ทธ๋ž˜์„œ 9์›”์ธ ์ง€๊ธˆ 2027 ์ด ๋น„์–ด ์žˆ๋Š” ๊ฑด ์ •์ƒ์ด๊ณ , 12์›”โ†’1์›” ๊ฐญ๋„ ๋ง‰ํžŒ๋‹ค. 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 ์žฌํ™œ์šฉ - `surge_monitor.py` โ€” **๊ธ‰๋“ฑ๋ฝ ์•Œ๋ฆผ** (2026-08-04). ํ† ๊ธ€ ์ผœ์ง„ ์ข…๋ชฉ๋งŒ ๊ฐ์‹œ(`state/behive_surge_toggles.json`, behive_web ๐Ÿ”” ๋ฒ„ํŠผ์ด ์”€). **์„ธ ๊ธฐ์ค€ ๋ณ‘ํ–‰**: โ‘ ๊ฑฐ๋ž˜์†Œ **์ƒยทํ•˜ํ•œ๊ฐ€ ๋„๋‹ฌ**(2026-08-06 ์ถ”๊ฐ€) = ๊ทธ๋‚  ๊ฐˆ ์ˆ˜ ์žˆ๋Š” ๋๊นŒ์ง€ ๊ฐ„ ๊ฒƒ์ด๋ผ ๊ฐ€์žฅ ๊ฐ•ํ•œ ์‹ ํ˜ธ, ๋ฌด์—‡์—๋„ ๊ฐ€๋ฆฌ์ง€ ์•Š๋Š”๋‹ค โ‘ก๊ฑฐ๋ž˜์†Œ **VI ๋ฐœ๋™** = "์ด๊ฑด ๊ธ‰๋“ฑ๋ฝ์ด๋‹ค"๋ฅผ ๊ฑฐ๋ž˜์†Œ๊ฐ€ ๊ณต์‹ ํŒ์ •ํ•˜๋ฏ€๋กœ ๋ฌธํ„ฑ์„ ์šฐ๋ฆฌ๊ฐ€ ์•ˆ ์ •ํ•ด๋„ ๋œ๋‹ค โ‘ข**์ž๊ธฐ ์ด๋ ฅ ๋ถ„์œ„์ˆ˜** = ์žฅ์ค‘ ์ดํƒˆํญ(์ „์ผ์ข…๊ฐ€ ๋Œ€๋น„) โ‰ฅ ๊ทธ ์ข…๋ชฉ ๊ณผ๊ฑฐ ์ดํƒˆํญ์˜ `SURGE_PCTL`(p90) ๋ถ„์œ„์ˆ˜, ํ™•๋Œ€๋‹จ๊ณ„๋Š” `SURGE_PCTL_BIG`(p98). โš ๏ธ **๊ณ ์ • %๋Š” ๊ตฌ์กฐ์ ์œผ๋กœ ๋ถˆ๊ฐ€** โ€” ์‹ค์ธก(๊ด€์‹ฌยท๊ฐ์‹œ 65์ข…๋ชฉ ร— 280๊ฑฐ๋ž˜์ผ) ์žฅ์ค‘ ์ดํƒˆํญ ์ค‘๊ฐ„๊ฐ’์ด 3.8%๋ผ ยฑ3%๋Š” ํ‰๋ฒ”ํ•œ ๋‚ ์ด๊ณ , ์ข…๋ชฉ๋ณ„ ๋ณ€๋™์„ฑ์ด 22๋ฐฐ ์ฐจ(ATR14 1.0~22.3%)๋ผ ยฑ5% ๋ฌธํ„ฑ์ด๋ฉด KODEX ๋ฏธ๊ตญS&P500์€ ๋ฐœ์ƒ 0ํšŒยทSK์ดํ„ฐ๋‹‰์Šค๋Š” 75ํšŒ๋‹ค. โš ๏ธ **ATR ๋ฐฐ์ˆ˜(ATR%ร—K)๋„ ์“ฐ๋ฉด ์•ˆ ๋œ๋‹ค โ€” 2026-08-04 ๊ด€๋ฆฌ์ž๋‹˜ ์ง€์ ์œผ๋กœ ํ๊ธฐ**: ๊ตญ๋‚ด ํ•˜๋ฃจ ๊ฐ€๊ฒฉ์ œํ•œํญ์ด **ยฑ30%**์ธ๋ฐ ATR ๋ฐฐ์ˆ˜๋Š” ์ƒํ•œ์ด ์—†์–ด ๋ณ€๋™์„ฑ ํฐ ์ข…๋ชฉ์˜ ๋ฌธํ„ฑ์ด ์ œํ•œํญ ๋ฐ–์œผ๋กœ ๋ฐ€๋ ค๋‚œ๋‹ค. ์‹ค์ธก 1์ฐจ(ATRร—1.5) 5/65์ข…๋ชฉยทํ™•๋Œ€(ATRร—3.0) **31/65(48%)**๊ฐ€ 30% ์ดˆ๊ณผ = **์˜์›ํžˆ ๋ฐœ๋™ ๋ถˆ๊ฐ€**์˜€๋‹ค(ATR% ์ค‘๊ฐ„๊ฐ’ 10%๋ผ ํ™•๋Œ€๋Š” ์ ˆ๋ฐ˜์ด ์ฃฝ์Œ). ๋ถ„์œ„์ˆ˜๋Š” ์‹ค์ œ ๊ด€์ธก๋œ ์ดํƒˆํญ์ด๋ผ ๊ตฌ์กฐ์ ์œผ๋กœ ์ œํ•œํญ์„ ๋„˜์„ ์ˆ˜ ์—†๊ณ (p90~p99 ์ „๋ถ€ 30% ์ดˆ๊ณผ 0์ข…๋ชฉ), ์•Œ๋ฆผ๋Ÿ‰๋„ ์ •์˜์ƒ (1โˆ’p)๋กœ ํ™•์ •๋œ๋‹ค โ€” p90 = ์ข…๋ชฉ๋‹น ์—ฐ 25ํšŒ. **๋‹ค์‹œ ATR ๋ฐฐ์ˆ˜๋กœ ๋˜๋Œ๋ฆฌ์ง€ ๋ง ๊ฒƒ.** ๋ฐ์ดํ„ฐ์›์€ behive_web `/api/realtime/quotes` 1์ฝœ โ€” ํ˜„์žฌ๊ฐ€์™€ VI๋ฅผ ํ•œ ๋ฒˆ์— ์ฃผ๊ณ  **ํ‚ค์›€ ์ฝœ 0**. VI(1h)๋Š” ์‹œ์žฅ ์ „์—ญ broadcast๋ผ ๊ตฌ๋… ๋ถˆํ•„์š”, ํ˜„์žฌ๊ฐ€(0B)๋Š” ๊ตฌ๋… ํ•„์š”ํ•œ๋ฐ `_rt_gather_codes()`๊ฐ€ ์ด๋ฏธ ๋ณด์œ +๊ด€์‹ฌ+๊ฐ์‹œ๋ฅผ ๊ตฌ๋…ํ•˜๋ฏ€๋กœ ํ† ๊ธ€ ์ข…๋ชฉ์€ ๋ถ€๋ถ„์ง‘ํ•ฉ(์ƒํ•œ์— ๊ฑธ๋ ค ๋น ์ง„ ์ข…๋ชฉ๋งŒ ka10095 ๋ฐฐ์น˜ 1์ฝœ ํด๋ฐฑ). โš ๏ธ **๋ฌธํ„ฑ์€ ํ•˜๋ฃจ 1ํšŒ๋งŒ ๊ณ„์‚ฐ**(`state/surge_thresholds.json`, `pctl` ์„œ๋ช… ๋ถˆ์ผ์น˜ ์‹œ ์žฌ๊ณ„์‚ฐ) โ€” `daily_candles_cache.get_candles`๋Š” ์บ์‹œ ์ตœ์‹ ๋ด‰์ด ์–ด์ œ๋ณด๋‹ค ์˜ค๋ž˜๋˜๋ฉด ka10081์„ ๋•Œ๋ฆฌ๋ฏ€๋กœ ๋งค๋ถ„ ร— ์ข…๋ชฉ์ˆ˜๋กœ ๋ถ€๋ฅด๋ฉด ํญ์ฃผ. โš ๏ธ **ka10081 ์œ ๋Ÿ‰์ด ์ดˆ๋‹น 5๊ฑด**์ด๋ผ ํ•œ๊บผ๋ฒˆ์— ๋Œ๋ฆฌ๋ฉด 429๊ฐ€ ์Ÿ์•„์ง„๋‹ค(์‹ค์ธก 70์ข…๋ชฉ ์ผ๊ด„ ์‚ฐ์ถœ ์‹œ 26์ข…๋ชฉ ์‹คํŒจ) โ†’ ์‚ฌ์ดํด๋‹น `MAX_COMPUTE_PER_CYCLE`(12)๊ฐœ๊นŒ์ง€ `COMPUTE_PACE_SEC`(0.35s) ๊ฐ„๊ฒฉ์œผ๋กœ๋งŒ ๊ณ„์‚ฐ, ๋‚˜๋จธ์ง€๋Š” ๋‹ค์Œ ์‚ฌ์ดํด์ด ์ด์–ด๋ฐ›๋Š”๋‹ค(70์ข…๋ชฉ = 6์‚ฌ์ดํด โ‰ˆ 6๋ถ„, ์‚ฌ์ดํด๋‹น 4~5์ดˆ ์‹ค์ธก). โš ๏ธ **์กฐํšŒ ์‹คํŒจ๋Š” ์บ์‹œํ•˜์ง€ ์•Š๋Š”๋‹ค** โ€” ์ด๋ ฅ๋ถ€์กฑ(`{}`)๊ณผ ๊ฐ™์ด ์ทจ๊ธ‰ํ•˜๋ฉด 429 ํ•œ ๋ฒˆ์— ๊ทธ ์ข…๋ชฉ์ด ํ•˜๋ฃจ ๋‚ด๋‚ด ์กฐ์šฉํžˆ VI๋งŒ ๊ฐ์‹œํ•˜๊ฒŒ ๋œ๋‹ค. `_compute_thresholds`๊ฐ€ `(๊ฒฐ๊ณผ, ์žฌ์‹œ๋„์—ฌ๋ถ€)` ํŠœํ”Œ์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ์ด์œ . โš ๏ธ **ํŒ์ •์€ `prev_close`์™€ ๋ฌด๊ด€**ํ•˜๋‹ค(`pct` % vs ๋ฌธํ„ฑ % ๋น„๊ต) โ€” ์บ์‹œ๊ฐ€ ํ•˜๋ฃจ stale์ด๋ฉด `list`์˜ ๋ฐœ๋™๊ฐ€ ํ‘œ์‹œ๋งŒ ์–ด๊ธ‹๋‚˜๊ณ  ํŠธ๋ฆฌ๊ฑฐ๋Š” ์ •ํ™•ํ•˜๋‹ค. โš ๏ธ **์ƒยทํ•˜ํ•œ๊ฐ€ยทVI ๊ฐ€ ๊ฑธ๋ฆฐ ๋™์•ˆ ๋ถ„์œ„์ˆ˜ ํŠธ๋ฆฌ๊ฑฐ๋Š” ์ƒ๋žต์ด ์•„๋‹ˆ๋ผ ๋ณด๋ฅ˜**๋‹ค(2026-08-06 ๊ด€๋ฆฌ์ž๋‹˜ ์š”์ฒญ์œผ๋กœ ๋ณ€๊ฒฝ). ๊ฐ™์€ ์‚ฌ๊ฑด์„ ๋‘ ๋ฒˆ ์•Œ๋ฆฌ์ง€ ์•Š์œผ๋ฉด์„œ๋„, ๊ทธ ์‚ฌ์ด ๋ฌธํ„ฑ์„ ๋„˜์€ ์‚ฌ์‹ค์€ `surge_alerts.json`์˜ `__pending__`(์ข…๋ชฉโ†’ํ‚คโ†’`{pct,word,reason,via}`, pct๋Š” ์ดํƒˆํญ ์ตœ๋Œ€ ์‹œ์ )์— ์ ์–ด๋’€๋‹ค๊ฐ€ **๊ฐ€๋ฆผ์ด ํ’€๋ฆฐ ์‚ฌ์ดํด์— ๋ฐฉ์ถœ**ํ•œ๋‹ค. ๊ทธ์ „์—” ์กฐ์šฉํžˆ ๋ฒ„๋ ค์ ธ์„œ, **VI ์ค‘ ๋ฌธํ„ฑ ๋ŒํŒŒ ํ›„ ํ•ด์ œ ์‹œ์ ์— ๋˜๋ฐ€๋ฆฐ ์›€์ง์ž„์€ ์•Œ๋ฆผ์ด ์•„์˜ˆ ์—†์—ˆ๋‹ค**. โš ๏ธ **๊ฐ€๋ฆผ ์—ฌ๋ถ€๋ฅผ "๋ณด๋ฅ˜ํ•  ํŠธ๋ฆฌ๊ฑฐ๊ฐ€ ๋น„์—ˆ๋Š”์ง€"๋กœ ํŒ๋‹จํ•˜๋ฉด ์•ˆ ๋œ๋‹ค** โ€” VI ์ค‘ ์ฃผ๊ฐ€๊ฐ€ ๋ฌธํ„ฑ ์•„๋ž˜๋กœ ๋˜๋ฐ€๋ฆฌ๋ฉด ๊ทธ๊ฒƒ๋„ ๋น„์–ด์„œ, VI ๋„์ค‘์— ๋ณด๋ฅ˜๋ถ„์ด ์ƒˆ์–ด๋‚˜๊ฐ„๋‹ค. `evaluate`๊ฐ€ ์„ธ ๋ฒˆ์งธ ๋ฐ˜ํ™˜๊ฐ’์œผ๋กœ **๊ฐ€๋ฆผ์‚ฌ์œ  ๋ฌธ์ž์—ด**์„ ๋”ฐ๋กœ ์ฃผ๋Š” ์ด์œ . โš ๏ธ **๋ฐฉ์ถœ๋ถ„์€ ๋ฐœ์†ก ์„ฑ๊ณต ์‹œ์—๋งŒ ๋ณด๋ฅ˜์—์„œ ์ง€์šด๋‹ค**(ํ…”๋ ˆ๊ทธ๋žจ ์‹คํŒจ ์‹œ ์žฌ์‹œ๋„ ๋Œ€์ƒ). โš ๏ธ **์•Œ๋ฆผ ์•„์ด์ฝ˜์€ pct ๊ฐ€ ์•„๋‹ˆ๋ผ ๋ฐฉํ–ฅ์–ด์—์„œ ํŒŒ์ƒ**ํ•œ๋‹ค โ€” ๋ฐฉ์ถœ ๊ฑด์€ ๋ŒํŒŒ ์‹œ์  ๋ฐฉํ–ฅ(๊ธ‰๋ฝ)๊ณผ ๋ฐฉ์ถœ ์‹œ์  ํ˜„์žฌ๊ฐ€ ๋ถ€ํ˜ธ(+)๊ฐ€ ์–ด๊ธ‹๋‚  ์ˆ˜ ์žˆ์–ด pct ๋กœ ๊ณ ๋ฅด๋ฉด `๐Ÿš€ ๊ธ‰๋ฝ`์ด ์ฐํžŒ๋‹ค. โš ๏ธ **VI ๊ฐ€ ์žฅ ๋งˆ๊ฐ๊นŒ์ง€ ์•ˆ ํ’€๋ฆฌ๋ฉด ๊ทธ๋‚  ๋ณด๋ฅ˜๋ถ„์€ ๋ฐฉ์ถœ๋˜์ง€ ์•Š๋Š”๋‹ค**(๊ฐ•์ œ flush ์—†์Œ). โš ๏ธ **์ƒยทํ•˜ํ•œ๊ฐ€๋Š” ๊ฑฐ๋ž˜์†Œ ๊ณ„์‚ฐ๊ฐ’(ka10095 `upl_pric`/`lst_pric`)์„ ๊ทธ๋Œ€๋กœ ์“ด๋‹ค** โ€” ์ œํ•œํญ์€ ๊ธฐ์ค€๊ฐ€์˜ ํ˜ธ๊ฐ€๋‹จ์œ„๋กœ ์ ˆ์‚ฌํ•œ ๋’ค ยฑํ•˜๋Š” ๊ทœ์น™์ด๋ผ ์ง์ ‘ ๊ณ„์‚ฐํ•˜๋ฉด ETFยท๊ฐ€๊ฒฉ๋Œ€๋ณ„ ํ˜ธ๊ฐ€๋‹จ์œ„ ํ‘œ๋ฅผ ์žฌํ˜„ํ•ด์•ผ ํ•ด ํ‹€๋ฆด ์—ฌ์ง€๊ฐ€ ์žˆ๋‹ค(VI์™€ ๊ฐ™์€ ์ด์œ ). ๊ธฐ์ค€๊ฐ€๋กœ ์ •ํ•ด์ ธ ์žฅ์ค‘ ๋ถˆ๋ณ€์ด๋ผ `state/surge_limits.json`์— **ํ•˜๋ฃจ 1์ฝœ**๋งŒ ์บ์‹œํ•˜๊ณ , ์ผ๋ด‰ ์ด๋ ฅ์ด ํ•„์š” ์—†์–ด **์ด๋ ฅ ๋ถ€์กฑ ์ข…๋ชฉ๋„ ์ด ๊ธฐ์ค€์œผ๋ก  ๊ฐ์‹œ๋œ๋‹ค**. โš ๏ธ **VI ๋ ˆ๊ทธ๋Š” behive_web ํ”„๋กœ์„ธ์Šค์— ์˜์กด** โ€” ์ฃฝ์œผ๋ฉด VI ์•Œ๋ฆผ์ด ์กฐ์šฉํžˆ ์‚ฌ๋ผ์ง€๊ณ  stderr ๊ฒฝ๊ณ ๋งŒ ๋‚จ๋Š”๋‹ค(์ž๋™ ์žฌ์‹œ๋„ยท๋ฐฑ์—… ํŠธ๋ฆฌ๊ฑฐ๋Š” ์˜๋„์ ์œผ๋กœ ์—†์Œ). ์ด๋ ฅ `MIN_HISTORY`(60์ผ) ๋ฏธ๋‹ฌ ์ข…๋ชฉ์€ VIยท์ƒํ•˜ํ•œ๊ฐ€๋งŒ ๊ฐ์‹œ(์‹ ๊ทœ์ƒ์žฅยท์ •๋ฆฌ๋งค๋งค๋Š” ์ œํ•œํญ ์˜ˆ์™ธ์ง€๋งŒ ์• ์ดˆ์— ์ด๋ ฅ์ด ์—†์–ด ์—ฌ๊ธฐ ํ•ด๋‹น). dedup์€ `state/surge_alerts.json`์— ๋‚ ์งœยท์ข…๋ชฉ๋ณ„ ํŠธ๋ฆฌ๊ฑฐํ‚ค 1ํšŒ์”ฉ โ€” ๋ถ„์œ„์ˆ˜ ๋ฐฉํ–ฅ๋ณ„ 1ํšŒ + ํ™•๋Œ€๋‹จ๊ณ„ 1ํšŒ + `limit_up`/`limit_down` 1ํšŒ, VI ๋Š” `vi:<๋ฐœ๋™์‹œ๊ฐ>`์ด๋ผ **๋ฐœ๋™ ๊ฑด๋งˆ๋‹ค** 1ํšŒ(ํ•˜๋ฃจ ์ƒํ•œ ์—†์Œ). ๊ฐ์‹œ ๋Œ€์ƒ์€ **์ฝ”๋“œ ๊ธฐ์ค€**(๋ฉ”๋ชจ์™€ ๋‹ฌ๋ฆฌ ์ข…๋ชฉ๋ช… fallback ์—†์Œ โ€” ์‹œ์„ธ ์กฐํšŒ์— ์ฝ”๋“œ๊ฐ€ ํ•„์š”). CLI: `check [--force]` / `dry-run`(๋ณด๋ฅ˜ ํ˜„ํ™ฉ ํ‘œ์‹œ) / `list`(๋ฌธํ„ฑ%ยท๊ธ‰๋“ฑ๊ฐ€ยท๊ธ‰๋ฝ๊ฐ€ยท์ƒํ•˜ํ•œ๊ฐ€ ํ‘œ์‹œ) - `trailing_monitor.py` โ€” **ํŠธ๋ ˆ์ผ๋ง ์Šคํ†ฑ ๊ฐ์‹œ** (2026-07-30). ํ‚ค์›€ REST์— ํŠธ๋ ˆ์ผ๋ง ์ฃผ๋ฌธ TR์ด ์—†์–ด์„œ, ์Šคํ†ฑ์ง€์ •๊ฐ€(`trde_tp=28`) ์ฃผ๋ฌธ์„ ์‹ค์ œ๋กœ ๊ฑธ์–ด๋‘๊ณ  ๊ณ ์  ๊ฐฑ์‹  ์‹œ `kt10002` ์ •์ •(`mdfy_cond_uv`)์œผ๋กœ ์กฐ๊ฑด๋‹จ๊ฐ€๋ฅผ ์˜ฌ๋ ค ๊ตฌํ˜„. **์ฃผ๋ฌธ์ด ํ‚ค์›€ ์„œ๋ฒ„์— ์žˆ์–ด ๊ฐ์‹œ ๋ฃจํ”„๊ฐ€ ์ฃฝ์–ด๋„ ๋งˆ์ง€๋ง‰ ์†์ ˆ์„ ์€ ์‚ด์•„์žˆ๋‹ค** (์ž์ฒด ํด๋ง ๋ฐœ์ฃผ ๋ฐฉ์‹์€ ๋ฃจํ”„๊ฐ€ ์ฃฝ์œผ๋ฉด ์†์ ˆ์ด ํ†ต์งธ๋กœ ์‚ฌ๋ผ์ง โ€” ์ด ์ฐจ์ด๊ฐ€ ์„ค๊ณ„ ์„ ํƒ ์ด์œ ). **์˜ˆ์•ฝ 1๊ฑด = ๊ณ„๋‹จ(๋ ˆ๊ทธ) N๊ฐœ**๋ผ ์ƒ์กด ํ™•์ธยท์ •์ • ๋ชจ๋‘ ๋ ˆ๊ทธ ๋‹จ์œ„๋กœ ๋ˆ๋‹ค. ์‚ฌ์ดํด๋‹น ํ•˜๋Š” ์ผ: โ‘ `ka10075` ๋ฏธ์ฒด๊ฒฐ ์กฐํšŒ๋กœ **๋ ˆ๊ทธ๋ณ„** ์ƒ์กด ํ™•์ธ(๊ณ„์ขŒ๋‹น 1์ฝœ). ์‚ฌ๋ผ์ง„ ๋ ˆ๊ทธ๋งŒ ์ •๋ฆฌํ•˜๊ณ  ๋‚˜๋จธ์ง€ ๊ณ„๋‹จ์€ ๊ฐ์‹œ ์œ ์ง€ + **์‚ฌ์œ  ๊ตฌ๋ถ„ ์•Œ๋ฆผ** โ€” ๋ฏธ์ฒด๊ฒฐ ์กฐํšŒ๋งŒ์œผ๋กœ๋Š” ์ฒด๊ฒฐยท์ทจ์†Œยท์†Œ๋ฉธ์ด ๊ตฌ๋ถ„๋˜์ง€ ์•Š์•„(์…‹ ๋‹ค ๋ชฉ๋ก์—์„œ ๋น ์ง) ๊ทธ๋•Œ๋งŒ `kt00007` 1์ฝœ ์ถ”๊ฐ€๋กœ ํŒ์ •: โœ…์ฒด๊ฒฐ(๊ทธ `ord_no`์˜ `cntr_qty`>0) / โš ๏ธ์†Œ๋ฉธ(์ฒด๊ฒฐ์ˆ˜๋Ÿ‰ 0 = ์ฒด๊ฒฐ ์•ˆ ๋จ ํ™•์ •, ์žฌ๋“ฑ๋ก ์•ˆ๋‚ด) / ๐ŸŽฏํŒ์ •๋ถˆ๊ฐ€(์กฐํšŒ ์‹คํŒจ). โš ๏ธ **ํŒ์ •์€ ๋ฐ˜๋“œ์‹œ ์ฃผ๋ฌธ๋ฒˆํ˜ธ ๋‹จ์œ„ `kt00007`๋กœ** โ€” ์ข…๋ชฉ ๋‹จ์œ„ ์ง‘๊ณ„์ธ `ka10170`์„ ์“ฐ๋ฉด **ํ•œ ๊ณ„๋‹จ์ด ์ฒด๊ฒฐ๋œ ๋‚  ๋‚˜๋จธ์ง€ ๊ณ„๋‹จ์ด ์žฅ ๋งˆ๊ฐ์œผ๋กœ ์†Œ๋ฉธํ–ˆ์„ ๋•Œ ๊ทธ ์†Œ๋ฉธ๋ถ„๊นŒ์ง€ '์ฒด๊ฒฐ'๋กœ ์˜คํŒ**ํ•œ๋‹ค(๊ฐ™์€ ์ข…๋ชฉ ๋งค๋„๊ธฐ๋ก์ด ์ด๋ฏธ ๋‚จ์•„ ์žˆ์–ด์„œ). 2026-07-31 ๊ณ„๋‹จ์‹ ์ „ํ™˜ ๋•Œ ๊ต์ฒด. โš ๏ธ **์กฐํšŒ ์‹คํŒจ๋ฅผ '์ฒด๊ฒฐ ์•ˆ ๋จ'์œผ๋กœ ๋‹จ์ • ๊ธˆ์ง€** โ€” `_leg_fill_check` ๊ฐ€ (๊ธฐ๋ก, ์„ฑ๊ณต์—ฌ๋ถ€) ํŠœํ”Œ์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ์ด์œ . ์•Œ๋ฆผ์€ **์˜ˆ์•ฝ ๋‹จ์œ„๋กœ ๋ฌถ์–ด 1๊ฑด**(์žฅ ๋งˆ๊ฐ์ด๋ฉด ๊ณ„๋‹จ์ด ํ†ต์งธ๋กœ ์‚ฌ๋ผ์ ธ ๋ ˆ๊ทธ๋งˆ๋‹ค ๋ณด๋‚ด๋ฉด 3~5ํ†ต์ด ๋ชฐ์•„์นœ๋‹ค) โ‘ก`ka10095` ์‹œ์„ธ 1์ฝœ โ†’ ๊ณ ์  ๊ฐฑ์‹  ์‹œ ์‚ด์•„์žˆ๋Š” ๋ ˆ๊ทธ **์ „๋ถ€** ์ •์ •(์ •์ • ์ฝœ์ด ๊ณ„๋‹จ ์ˆ˜์— ๋น„๋ก€). ์ฃผ๊ฐ€๊ฐ€ ๊ทธ๋Œ€๋กœยทํ•˜๋ฝ์ด๋ฉด API ์ฝœ 0. โš ๏ธ **`kt10002` ์‘๋‹ต `ord_no`๋Š” ์‹ ๊ทœ ์ฃผ๋ฌธ๋ฒˆํ˜ธ** โ€” `trailing.commit_step_modify`๊ฐ€ ์ƒํƒœํŒŒ์ผ์˜ **๋ ˆ๊ทธ๋ณ„** `ord_no`๋ฅผ ๊ฐฑ์‹ ํ•˜์ง€ ์•Š์œผ๋ฉด ๊ทธ ๋ ˆ๊ทธ์˜ ๋‘ ๋ฒˆ์งธ ์ •์ •๋ถ€ํ„ฐ `orig_ord_no`๊ฐ€ ํ‹€๋ ค ์ „๋ถ€ ์‹คํŒจ(์ตœ๋Œ€ ํ•จ์ •). โš ๏ธ **ํ•œ ๊ณ„๋‹จ์ด ์ฒด๊ฒฐ๋ผ๋„ ๋‚จ์€ ๊ณ„๋‹จ์„ ์žฌ๋ฐฐ์น˜ํ•˜์ง€ ์•Š๋Š”๋‹ค**(2026-07-31 ๊ด€๋ฆฌ์ž๋‹˜ ๊ฒฐ์ •) โ€” ๋‚จ์€ ์ˆ˜๋Ÿ‰์„ ๊ณ„๋‹จ ๋น„์œจ๋Œ€๋กœ ๋‹ค์‹œ ์ชผ๊ฐœ๋ ค๋ฉด ๊ธฐ์กด ์ฃผ๋ฌธ ์ทจ์†Œ+์‹ ๊ทœ ๋ฐœ์ฃผ๊ฐ€ ํ•„์š”ํ•ด ๊ฐ์‹œ ๋ฃจํ”„์— ์ž๋™ ๋ฐœ์ฃผ ๊ฒฝ๋กœ๊ฐ€ ์ƒ๊ธด๋‹ค. ๋‚จ์€ ๊ณ„๋‹จ์€ ์ƒˆ ๊ณ ์  ๊ธฐ์ค€์œผ๋กœ ๋”ฐ๋ผ ์˜ฌ๋ผ๊ฐ€๊ธฐ๋งŒ ํ•œ๋‹ค. โš ๏ธ **๊ณ ์ ์€ ๋“ฑ๋ก ์‹œ์  ํ˜„์žฌ๊ฐ€์—์„œ ์‹œ์ž‘ํ•ด ํ˜„์žฌ๊ฐ€๋กœ๋งŒ ๊ฐฑ์‹ **ํ•œ๋‹ค โ€” `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 ์ฆ‰์‹œ๊ฐ€ ์•„๋‹ˆ๋ผ ๋ช‡ ์‹œ๊ฐ„ ๋’ค. **์ž๋™ ์žฌ๋“ฑ๋ก์€ ํ•˜์ง€ ์•Š๋Š”๋‹ค**(๊ด€๋ฆฌ์ž๋‹˜ ๊ฒฐ์ •) โ€” ์•Œ๋ฆผ๋งŒ ๋ณด๋‚ด๊ณ  ์žฌ๋“ฑ๋ก์€ ์ž์‚ฐ์›น์—์„œ ์ˆ˜๋™. **์žฌ๋“ฑ๋ก ๋ฒ„ํŠผ**(2026-08-27): ์ž์‚ฐ์›น `[๐Ÿ“‹ ์ง„ํ–‰์ค‘]` ๋ชจ๋‹ฌ ํ•˜๋‹จ **์ตœ๊ทผ ์ข…๋ฃŒ** ์„น์…˜์˜ `โ†บ ์žฌ๋“ฑ๋ก` ์ด **๊ฑฐ๋ž˜ ๋ชจ๋‹ฌ์„ ์–ด์ œ ์„ค์ •(๊ณ„๋‹จยท์ตœ์ € ๋งค๋„๊ฐ€ยท์ˆ˜๋Ÿ‰ยท๋ฐœ๋™๊ฐ€)์œผ๋กœ ์ฑ„์›Œ์„œ ์—ด์–ด์ค„ ๋ฟ**์ด๊ณ  ์นด๋“œยทํ™•์ธ ํŒ์—…ยทPIN ์€ ํ‰์†Œ์™€ ๋™์ผ โ€” **๊ฐ์‹œ ๋ฃจํ”„๊ฐ€ ์Šค์Šค๋กœ ๋˜์‚ด๋ฆฌ๋Š” ๊ฒฝ๋กœ๋Š” ์—ฌ์ „ํžˆ ์—†๋‹ค.** ๋ชฉ๋ก ๋Œ€์ƒ์€ **์žฅ ๋งˆ๊ฐ ์†Œ๋ฉธ + arm ๋งŒ๋ฃŒ 2์ข…๋ฟ**(์ฒด๊ฒฐยทํŒ์ •๋ถˆ๊ฐ€ยท์ˆ˜๋™์ทจ์†Œยท๋ฐœ๋™๋ถˆ๊ฐ€ยท`firing_at` ์ค‘๋‹จ๋ถ„ ์ œ์™ธ). โš ๏ธ **๊ณ ์ ์€ ์Šน๊ณ„ ์•ˆ ํ•จ**(์–ด์ œ ๊ณ ์ ์ด๋ฉด `TRAIL_IMMEDIATE` ๊ฑฐ๋ถ€). โš ๏ธ **์‚ฌ์ดํด ๊ฑธ์นœ ๋ถ€๋ถ„์ฒด๊ฒฐ**์€ ๊ทธ ๋ฐฐ์น˜์— ์ฒด๊ฒฐ์ด ์—†์–ด ์กฐ๊ฑด์„ ํ†ต๊ณผํ•˜๋ฏ€๋กœ `len(evs) == len(entry_steps)` ๋กœ ๋ง‰๋Š”๋‹ค. โš ๏ธ ์˜ˆ์•ฝ์˜ **`entry_steps`**(๋“ฑ๋ก ์‹œ์  ๊ณ„๋‹จ ์ •์˜)๊ฐ€ ํ•„์š”ํ•œ ์ด์œ  โ€” `remove_step` ์Šค๋ƒ…์ƒท์€ ๋ ˆ๊ทธ๋ฅผ ๋บ€ **๋’ค**๋ผ ๋งˆ์ง€๋ง‰ ๋ ˆ๊ทธ๊ฐ€ ๋น ์ง€๋ฉด `steps: []` ๋‹ค. โš ๏ธ ์†Œ๋ฉธ ์•Œ๋ฆผ ๋ฌธ๊ตฌ๋„ **๊ธฐ๋ก ์กฐ๊ฑด๊ณผ ๊ฐ™์ด ๋ถ„๊ธฐ**ํ•œ๋‹ค(์ฒด๊ฒฐยทํŒ์ •๋ถˆ๊ฐ€๋ฉด ์žฌ๋“ฑ๋ก ๋ฒ„ํŠผ์„ ์–ธ๊ธ‰ํ•˜์ง€ ์•Š๋Š”๋‹ค โ€” ์—†๋Š” ๋ชฉ๋ก์œผ๋กœ ์•ˆ๋‚ด ๊ธˆ์ง€). โš ๏ธ ์ตœ๊ทผ ์ข…๋ฃŒ๋Š” ๋ฐฐ์ง€ ์นด์šดํŠธ(`unique_count`)์— **๋„ฃ์ง€ ์•Š๋˜** `/api/order/active` ์˜ `recent_count` ๋กœ **ํŒ์—…์€ ์—ด๋ฆฌ๊ฒŒ** ํ•œ๋‹ค(๋ฏธ์ฒด๊ฒฐ 0๊ฑด์ด๋ฉด ํ† ์ŠคํŠธ๋กœ ๋๋‚˜ ๋ชฉ๋ก์— ๋‹ฟ์„ ๊ธธ์ด ์—†๋‹ค). ์ €์žฅ์€ `trailing_stops.json` ์„ธ ๋ฒˆ์งธ ํ‚ค **`recent`**(20๊ฑดยท7์ผ ๋ง๋ฒ„ํผ, UI ์ „์šฉ์ด์ง€ ๊ฐ์‚ฌ ์›์žฅ ์•„๋‹˜ โ€” `_read_doc`/`_write` ๋ฅผ ๋ฐ˜๋“œ์‹œ ๊ฐ™์ด ๊ณ ์น  ๊ฒƒ). ์ •์ • ์ˆ˜๋Ÿ‰์€ ์ €์žฅ qty๊ฐ€ ์•„๋‹Œ **๋ฏธ์ฒด๊ฒฐ ์ž”๋Ÿ‰**(๋ถ€๋ถ„์ฒด๊ฒฐ ๋Œ€์‘). ๋ฏธ์ฒด๊ฒฐ ์กฐํšŒ ์‹คํŒจ ๊ณ„์ขŒ๋Š” ๊ทธ ์‚ฌ์ดํด ํŒ๋‹จ ๋ณด๋ฅ˜(์—†๋‹ค๊ณ  ๋‹จ์ •ํ•˜๋ฉด ์‚ด์•„์žˆ๋Š” ์˜ˆ์•ฝ์„ ์ง€์›€). CLI: `check [--repeat N --gap S] [--force] [--dry-run]` / `list` - `orders/trailing.py` โ€” ํŠธ๋ ˆ์ผ๋ง ์˜ˆ์•ฝ ์ƒํƒœ(`state/trailing_stops.json`) + ์†์ ˆ์„  ๊ณ„์‚ฐ. **์˜ˆ์•ฝ 1๊ฑด = ๊ณ„๋‹จ(๋ ˆ๊ทธ) N๊ฐœ = ํ‚ค์›€ ์Šคํ†ฑ์ฃผ๋ฌธ N๊ฑด**(๊ณ„๋‹จ์‹ ๋ถ„ํ•  ๋งค๋„, 2026-07-31). ํ•˜๋ฝ๋ฅ ์ด ๊นŠ์–ด์งˆ์ˆ˜๋ก ๋” ๋งŽ์ด ํŒ๋‹ค โ€” ์˜ˆ โˆ’10% 20% / โˆ’20% 50% / โˆ’30% ์ „๋Ÿ‰. `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ํ‹ฑ โ€” ์กฐ๊ฑด๋‹จ๊ฐ€์™€ ๊ฐ™๊ฒŒ ๋‘๋ฉด ๋ฐœ๋™ ํ›„ ๊ทธ ๊ฐ€๊ฒฉ ์•„๋ž˜๋กœ ์•ˆ ํŒ”๋ ค ๋ฏธ์ฒด๊ฒฐ๋กœ ๋‚จ๊ณ , ๋„ˆ๋ฌด ๋ฒŒ๋ฆฌ๋ฉด ๊ธ‰๋ฝ ์‹œ ํ—๊ฐ’ ๋งค๋„). โš ๏ธ `int(round(peakร—(1โˆ’pct/100), 6))` ์˜ **round ๋Š” ๋ถ€๋™์†Œ์ˆ˜์  ์žก์Œ ์ œ๊ฑฐ์šฉ**(5500ร—0.7์ด 3849.9999999999995๋ผ int()๊ฐ€ 3849๋กœ ๊นŽ๊ณ  ํ˜ธ๊ฐ€๋‚ด๋ฆผ์ด 3845๊นŒ์ง€ ๋Œ์–ด๋‚ด๋ฆฌ๋˜ ๋ฒ„๊ทธ, 2026-07-31 ์ˆ˜์ •). ๊ณ„๋‹จ ํ•จ์ˆ˜ 4์ข…: `normalize_steps(raw)`=์ž…๋ ฅํ•œ **๋ˆ„์ ** ๋น„์ค‘(20/50/100)์„ **์ถ”๊ฐ€** ๋น„์ค‘(20/30/50)์œผ๋กœ ํ™˜์‚ฐ+๊ฒ€์ฆ(ํ•˜๋ฝ๋ฅ ยท๋ˆ„์  ๋‘˜ ๋‹ค ์ˆœ์ฆ๊ฐ€, ํ•˜๋ฝ๋ฅ  0.5~30%, ๋ˆ„์  โ‰ค100%ใ€”100 ๋ฏธ๋งŒ ํ—ˆ์šฉ=์ผ๋ถ€๋งŒ ๊ณ„๋‹จ ์ฒญ์‚ฐใ€•, ๊ณ„๋‹จ โ‰ค`MAX_STEPS` 5) / `allocate_step_qty(total, weights)`=**์ตœ๋Œ€์ž”์—ฌ๋ฒ•**(๋‚ด๋ฆผ ํ›„ ์†Œ์ˆ˜๋ถ€ ํฐ ๊ณ„๋‹จ๋ถ€ํ„ฐ 1์ฃผ์”ฉ โ€” "๋‚ด๋ฆผ ํ›„ ๋งˆ์ง€๋ง‰์— ๋ชฐ์•„์ฃผ๊ธฐ"๋ณด๋‹ค ์–•์€ ๊ณ„๋‹จ์ด 0์ฃผ๋กœ ์ฃฝ๋Š” ์ผ์ด ์ ๋‹ค: 2์ฃผยท20/30/50 โ†’ `[0,1,1]` vs `[0,0,2]`) / `compute_step_levels(peak, steps, floor)` / `next_step_levels(res, cur)`. **์ตœ์ € ๋งค๋„๊ฐ€**๋Š” ์†์ ˆ์„ ์˜ ํ•˜ํ•œ โ€” ํŠธ๋ ˆ์ผ ํญ์„ ๋„“๊ฒŒ ์žก์•„๋„ ์ด ๊ฐ€๊ฒฉ ์•„๋ž˜๋กœ ์•ˆ ๋‚ด๋ ค๊ฐ„๋‹ค(์ดˆ๊ธฐ ๊ตฌ๊ฐ„ ์†์‹ค ์ œํ•œ). โš ๏ธ **floor ๋Š” ๋ชจ๋“  ๊ณ„๋‹จ์— ๊ฐ™์€ ํ•˜ํ•œ์œผ๋กœ ๊ฑธ๋ ค** ์ดˆ๊ธฐ์—” ์—ฌ๋Ÿฌ ๊ณ„๋‹จ์ด ๊ฐ™์€ ๊ฐ€๊ฒฉ์œผ๋กœ ๋ญ‰์น  ์ˆ˜ ์žˆ๋‹ค. **๊ทธ๋ž˜๋„ ์ฃผ๋ฌธ์„ ๋ณ‘ํ•ฉํ•˜์ง€ ์•Š๋Š”๋‹ค** โ€” ๊ณ ์ ์ด ์˜ฌ๋ผ ํŠธ๋ ˆ์ผ์ด floor๋ฅผ ์ถ”์›”ํ•˜๋ฉด ๊ฐ ๊ณ„๋‹จ์ด ์ œ ํ•˜๋ฝ๋ฅ ๋Œ€๋กœ ๋‹ค์‹œ ๋ฒŒ์–ด์ง€๋Š”๋ฐ, ๋ณ‘ํ•ฉํ•˜๋ฉด ์ •์ •๋งŒ์œผ๋กœ๋Š” ๋ชป ์ชผ๊ฐ ๋‹ค(์‹ ๊ทœ ๋ฐœ์ฃผ๊ฐ€ ํ•„์š”ํ•ด์ง). ์ „ํ™˜์  = `min_sell_price รท (1โˆ’pct/100)`, ์˜ˆ: ์ตœ์ € 4,500ยท20% โ†’ 5,625์›. `next_step_levels(res, cur)`๋Š” **์ƒํ–ฅ ์ „์šฉ ์ˆœ์ˆ˜ํ•จ์ˆ˜** โ€” ๊ณ ์  ์•ˆ ์˜ฌ๋ž์œผ๋ฉด None, ์˜ฌ๋ž์œผ๋ฉด `{peak, steps:[์˜ฌ๋ฆด ๋ ˆ๊ทธ๋งŒ]}`. โš ๏ธ **steps ๊ฐ€ ๋นˆ ๋ฆฌ์ŠคํŠธ์ผ ์ˆ˜ ์žˆ๋‹ค**(ํ˜ธ๊ฐ€๋‚ด๋ฆผยทfloor ์ง€๋ฐฐ๋กœ ์˜ฌ๋ฆด ์กฐ๊ฑด๋‹จ๊ฐ€๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ) โ†’ ํ˜ธ์ถœ์ธก์€ ์ •์ • API ์—†์ด `commit_peak`๋กœ ๊ณ ์ ๋งŒ ๊ฐฑ์‹ (์ฝœ 0, ํ™”๋ฉด ๊ณ ์  ํ‘œ์‹œ๋Š” ์ •ํ™• ์œ ์ง€). ์ƒํƒœ ๊ฐฑ์‹ ์€ ๋ ˆ๊ทธ ๋‹จ์œ„: `register_steps`/`commit_step_modify`/`remove_step`(๋งˆ์ง€๋ง‰ ๋ ˆ๊ทธ ์ œ๊ฑฐ ์‹œ ์˜ˆ์•ฝ์งธ ์‚ญ์ œ)/`commit_peak`. ๊ฐ™์€ ๊ณ„์ขŒยท์ข…๋ชฉ ์ค‘๋ณต ์˜ˆ์•ฝ์€ `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 ์ •์ฑ…. **ka10095 ๋ฅผ KRX+AL 2์ข…์œผ๋กœ ํ†ต์ผ**(2026-09-10): โš ๏ธ ์˜ˆ์ „์—” ๋ณด์œ (KRX/NX/AL 3์ฝœ)์™€ ๊ฐ์‹œยท๊ด€์‹ฌ(AL + NX probe)์ด ์ œ๊ฐ๊ฐ์ด์—ˆ๊ณ  NXT ๋‹จ๋… ์กฐํšŒ๊ฐ€ ๊ณณ๊ณณ์— ์žˆ์—ˆ๋‹ค. ์ง€๊ธˆ์€ **NXT ๋‹จ๋… ์กฐํšŒ๊ฐ€ ์—†๋‹ค** โ€” โ‘ ํ˜„์žฌ๊ฐ€ ๋ณด์ •์€ AL ํ•˜๋‚˜๋กœ(AL ์ด ๊ณง '์ง€๊ธˆ ํ™œ์„ฑ ์‹œ์žฅ์˜ ์ตœ์‹  ์ฒด๊ฒฐ'์ด๋ผ ์˜ˆ์ „์˜ phase๋ณ„ ๋ถ„๊ธฐ regular=KRX/nxt=NXT ๊ฐ€ ํ†ต์งธ๋กœ ์‚ฌ๋ผ์ง) โ‘กRVOL ์˜ KRX ๊ฑฐ๋ž˜๋Ÿ‰์€ KRX ๋ฅผ ์ง์ ‘ ์กฐํšŒ(์˜ˆ์ „ `ALโˆ’NXT` ์—ญ์‚ฐ์€ ๋‘ ์กฐํšŒ์˜ ์‹œ์ ์ฐจ๋งŒํผ ์˜ค์ฐจ๊ฐ€ ๋‚ฌ๋‹ค โ€” ์‹ค์ธก ์‚ผ์„ฑ์ „์ž 14์ฃผ) โ‘ขNXT ๊ฑฐ๋ž˜ ์—ฌ๋ถ€๋Š” `_is_nxt_traded()` = `state/stock_codes.json` ์˜ `nxt_enable`(**ํ‚ค์›€ ์ฝœ 0**, ์ฝ”๋“œ ํ‚ค ์—ญ์ธ๋ฑ์Šค 5๋ถ„ ์บ์‹œ `_nxt_enable_map`). โš ๏ธ `kc.lookup_stock_meta` ๋ฅผ ํ–‰๋งˆ๋‹ค ๋ถ€๋ฅด๋ฉด ์•ˆ ๋œ๋‹ค โ€” ํ˜ธ์ถœ๋งˆ๋‹ค 954KB JSON ์„ ๋‹ค์‹œ ์ฝ๊ณ  3500์ข…๋ชฉ์„ ์ˆœํšŒํ•ด 100์ข…๋ชฉ์ด๋ฉด ๋ Œ๋”๊ฐ€ ๋ฉˆ์ถ˜๋‹ค. โš ๏ธ KRX ๋ณด์ • ์กฐํšŒ๋Š” **`nxt_enable=True` ์ข…๋ชฉ๋งŒ** ํ•œ๋‹ค โ€” NXT ๋ฏธ๊ฑฐ๋ž˜ ์ข…๋ชฉ์€ AL ์ด ๊ณง KRX ๊ฐ’์ด๋ผ ์กฐํšŒํ•ด๋„ ๊ฐ™์€ ๊ฐ’์ด ์˜จ๋‹ค(101์ข…๋ชฉ ์ „์ˆ˜ ์‹ค์ธก ์˜ˆ์™ธ 0๊ฑด). ์ข…๋ชฉ ์ˆ˜๊ฐ€ ๋Š˜์–ด๋„ ์„ฑ๋ฆฝํ•˜๋Š” ๊ทœ์น™์ด๋ผ '๋ช‡ ์ข…๋ชฉ์ด๋‹ˆ ๋ช‡ ์ฝœ'์‹ ๊ฐ€์ •์— ๊ธฐ๋Œ€์ง€ ์•Š๋Š”๋‹ค. **์‹ค์ธก ๋ Œ๋”๋‹น ka10095 10์ฝœ โ†’ 7์ฝœ**(๊ฐ์‹œยท๊ด€์‹ฌ 101์ข…๋ชฉ์ด 40๊ฐœ ๋ฐฐ์น˜ ํ•œ๋„๋กœ 3์ฝœ์”ฉ ์ชผ๊ฐœ์ง€๋Š” ๊ฒŒ ๋Œ€๋ถ€๋ถ„์ด๋‹ค โ€” ์ฝœ ์ˆ˜๋ฅผ ์…€ ๋•Œ ์ด ๋ถ„ํ• ์„ ๋น ๋œจ๋ฆฌ๊ธฐ ์‰ฝ๋‹ค). โš ๏ธ ์ดˆ๋ก์  ํŒ์ •์ด meta ๊ธฐ๋ฐ˜์ด ๋˜๋ฉด์„œ **๊ณ„์ขŒ๋ณ„ ํ–‰์—๋„ ์ดˆ๋ก์ ์ด ๋ถ™๋Š”๋‹ค**(์˜ˆ์ „์—” `ohlc_nxt` ๊ฐ€ consolidated ํ–‰์—๋งŒ ์ฃผ์ž…๋ผ ๊ณ„์ขŒ๋ณ„ ํ–‰์—์„œ ์กฐ์šฉํžˆ ๋น ์กŒ๋‹ค). **๋“€์–ผ OHLC ๋ฏธ๋‹ˆํ‘œ๋Š” `KRX | ํ†ตํ•ฉ`**(2026-09-10, ๊ด€๋ฆฌ์ž๋‹˜ ๊ฒฐ์ •): ์˜ˆ์ „ `KRX | NXT` ์—์„œ ๋‘ ๋ฒˆ์งธ ์—ด์„ ํ†ตํ•ฉ์œผ๋กœ ๊ต์ฒด. NXT ์‹œ๊ฐ„๋Œ€์—” ํ†ตํ•ฉ = NXT ์ตœ์‹  ์ฒด๊ฒฐ์ด๋ผ ๊ฐ€๊ฒฉ 4๊ฐ’์ด ๊ฐ™๊ณ  ๊ฑฐ๋ž˜๋Ÿ‰๋งŒ ํ•ฉ์‚ฐ์ด๋ฉฐ, ์ •๊ทœ์žฅ์—” ํ†ตํ•ฉ์ด ํ”„๋ฆฌ๋งˆ์ผ“์„ ํฌํ•จํ•ด KRX ์™€ ๊ฐˆ๋ฆฐ๋‹ค(์‹ค์ธก ์‚ผ์„ฑ์ „์ž ์‹œ๊ฐ€ 269,000 vs 268,000). โš ๏ธ ํ†ตํ•ฉ ์—ด ์‹œ๊ฐ€๋Š” **๋ฎ์–ด์“ฐ์ง€ ์•Š๋Š”๋‹ค** โ€” ์˜ˆ์ „ NXT ์—ด์€ ์‹œ๊ฐ€ ์นธ์— ์ „์ผ์ข…๊ฐ€๋ฅผ ๋„ฃ์—ˆ์ง€๋งŒ ํ†ตํ•ฉ ์‹œ๊ฐ€๋Š” NXT ํ”„๋ฆฌ๋งˆ์ผ“ ์ฒซ ์ฒด๊ฒฐ์ด๋ผ ๊ทธ ์ž์ฒด๊ฐ€ ์ •๋ณด๋‹ค. โš ๏ธ ํ†ตํ•ฉ ์—ด ์ „์ผ์ข…๊ฐ€๋Š” **`r['pred_close']` ๋ฅผ ์“ฐ๋ฉด ์•ˆ ๋œ๋‹ค** โ€” ๊ทธ ๊ฐ’์€ `rebase_to_nxt_close` ๊ฐ€ ๋งŒ๋“œ๋Š” '๋‹น์ผ ๋“ฑ๋ฝ baseline' ์ด๋ผ **์–ด์ œ ๋ณด์œ ๊ฐ€ ์—†๋˜ ์ข…๋ชฉ(์˜ค๋Š˜ ์‹ ๊ทœ ๋งค์ˆ˜)์—” ๋งค์ˆ˜ ํ‰๋‹จ์ด ๋“ค์–ด๊ฐ„๋‹ค**(์‹ค์ธก 2026-09-10 ์šฐ๋ฆฌ๊ธฐ์ˆ : ํ‰๋‹จ 13,780 ์ด ์ „์ผ์ข…๊ฐ€ ์ž๋ฆฌ์— ๋…ธ์ถœ, ์‹ค์ œ ์ „์ผ์ข…๊ฐ€๋Š” 14,320). ๊ทธ๋ž˜์„œ rebase **์ง์ „์—** ์–ด์ œ ์Šค๋ƒ…์ƒท ์ข…๊ฐ€๋ฅผ `pred_close_snap` ์œผ๋กœ ๋”ฐ๋กœ ๋ณด์กดํ•˜๊ณ , ๋ฏธ๋‹ˆํ‘œ๋Š” โ‘ `pred_close_snap`(์–ด์ œ ๋ณด์œ ๋ถ„ = ์–ด์ œ NXT ์ข…๊ฐ€) โ‘ก์—†์œผ๋ฉด ka10095 AL ์˜ `ํ˜„์žฌ๊ฐ€ โˆ’ ์ „์ผ๋Œ€๋น„` ์ˆœ์œผ๋กœ ์“ด๋‹ค. โš ๏ธ ๊ธฐ์กด NXT ์—ด์—๋„ ๊ฐ™์€ ์ฝ”๋“œ์˜€์ง€๋งŒ 'NXT ๋ฏธ๊ฑฐ๋ž˜ + ์˜ค๋Š˜ ์‹ ๊ทœ๋งค์ˆ˜' ๋‘ ์กฐ๊ฑด์ด ๊ฒน์ณ์•ผ ๋ณด์ด๋Š” ์ž๋ฆฌ(NXT ๋ฏธ๊ฑฐ๋ž˜๋ฉด ์—ด์ด ํ†ต์งธ๋กœ ๋น„์—ˆ๋‹ค)๋ผ ๋“œ๋Ÿฌ๋‚˜์ง€ ์•Š์•˜๋‹ค. โš ๏ธ ๋ณด์œ ํ–‰ '๋‹น์ผ ๋“ฑ๋ฝ'์€ ์—ฌ์ „ํžˆ ํ‰๋‹จ ๊ธฐ์ค€์ด๋‹ค โ€” ์˜ค๋Š˜ ์‚ฐ ์ข…๋ชฉ์„ ์–ด์ œ ์ข…๊ฐ€์™€ ๋น„๊ตํ•˜๋Š” ๊ฑด ์†์ต ๊ด€์ ์—์„œ ๋ฌด์˜๋ฏธํ•˜๋ฏ€๋กœ ์˜๋„๋œ ๋™์ž‘์ด๊ณ , ๋ฏธ๋‹ˆํ‘œ(์‹œ์žฅ ๋ฐ์ดํ„ฐ)์™€ ๋ชฉ์ ์ด ๋‹ค๋ฅด๋‹ค. **์ •๊ทœ์žฅ(09:00~15:30)์—” KRX ๊ธฐ์ค€**(2026-10-02 ๊ด€๋ฆฌ์ž๋‹˜ ์ง€์ ): ๋ฏธ๋‹ˆํ‘œ ๊ฐ•์กฐ ์—ดยทKRX ์—ด ํ˜„์žฌ๊ฐ€ยท์นด๋“œ ์š”์•ฝ ์บ”๋“ค์„ KRX ๋กœ ๋‘”๋‹ค(๊ทธ ์™ธ ๊ฑฐ๋ž˜์‹œ๊ฐ„์€ ํ†ตํ•ฉ). ์‹ค์‹œ๊ฐ„ ํ‹ฑ์€ `_AL` ๋ฟ์ด๋ผ ์ •๊ทœ์žฅ KRX ํ˜„์žฌ๊ฐ€ ์…€์—” `data-rt-ohlc-cur` ๋ฅผ ๋‹ฌ์ง€ ์•Š๋Š”๋‹ค โ€” ๋‹ฌ๋ฉด ํ†ตํ•ฉ ํ‹ฑ์ด ๋ฎ์–ด์“ด๋‹ค(๊ทธ๋ž˜์„œ ๊ทธ ์…€์€ ๋ Œ๋” ์‹œ์  ๊ฐ’). โš ๏ธ ๋ฏธ๋‹ˆํ‘œ ์ „ํ™˜์€ **์ฝœ ์ ˆ๊ฐ์ด ๋ชฉ์ ์ด ์•„๋‹ˆ๋‹ค**(๋ณด์œ  NX ์ฝœ์€ ์–ด์ฐจํ”ผ ๊ฐ์‹œยท๊ด€์‹ฌ NXT ์กฐํšŒ์— ์–น์œผ๋ฉด ๊ณต์งœ์˜€๋‹ค) โ€” ํ™”๋ฉด ์ผ๊ด€์„ฑ ๋•Œ๋ฌธ์— ์„ ํƒํ•œ ๊ฒƒ. **๊ฐ์‹œยท๊ด€์‹ฌ ์นด๋“œ ๋ฏธ๋‹ˆํ‘œ๋„ ๊ฐ™์€ ๋ผ๋ฒจ**(2026-09-11): `_render_ohlc_mini` ๋Š” ๊ตฌ์กฐ๊ฐ€ ๋‹ค๋ฅด๋‹ค โ€” ๊ฐ€๊ฒฉ์€ ํ†ตํ•ฉ(AL) ํ•˜๋‚˜์ด๊ณ  **๋“ฑ๋ฝ๋ฅ ๋งŒ ๋‘ ๊ธฐ์ค€**์œผ๋กœ ๋‚˜๋‰œ๋‹ค(โ‘ KRX ์ „์ผ์ข…๊ฐ€ โ‘ก์–ด์ œ ํ†ตํ•ฉ ๋งˆ์ง€๋ง‰ ์ฒด๊ฒฐ = `_watchlist_nxt` ์Šค๋ƒ…์ƒท์˜ NXT ์ข…๊ฐ€). ๋ณด์œ ํ–‰ `ํ†ตํ•ฉ` ์—ด๊ณผ ๊ฐ™์€ ๊ฐœ๋…์ด๋ผ ๊ฐ’ยท๋ฐ์ดํ„ฐ์›์€ ๊ทธ๋Œ€๋กœ ๋‘๊ณ  ํ—ค๋” ๋ผ๋ฒจ๋งŒ 'NXT'โ†’'ํ†ตํ•ฉ' ์œผ๋กœ ๋งž์ท„๋‹ค. โš ๏ธ ๋ณด์œ ํ–‰๊ณผ ๋‹ฌ๋ฆฌ **ํด๋ฐฑ(์—†์œผ๋ฉด KRX ์ „์ผ์ข…๊ฐ€)์„ ๋‘์ง€ ์•Š๋Š”๋‹ค** โ€” ๋‘ ์ปฌ๋Ÿผ์ด ๊ฐ™์€ ๊ฐ’์ด ๋˜์–ด ์ค‘๋ณต์ด๋‹ค(NXT ๋ฏธ์šด์˜ ์ข…๋ชฉ์€ ์–ด์ œ ์ข…๊ฐ€๊ฐ€ ๊ณง KRX ์ข…๊ฐ€๋ผ ์›๋ž˜ ๋‘ ๊ฐ’์ด ๊ฐ™๋‹ค). โš ๏ธ 320px ์—์„œ ๋ฏธ๋‹ˆํ‘œ๊ฐ€ 6px ๋„˜์น˜๋Š” ๊ฑด ๋ผ๋ฒจ๊ณผ ๋ฌด๊ด€ํ•œ ๊ธฐ์กด ๋™์ž‘์ด๋‹ค(๋ผ๋ฒจ์„ 'NXT' ๋กœ ๋˜๋Œ๋ ค๋„ ๋™์ผ, ์ปฌ๋Ÿผ ํญ 56px ๋ถˆ๋ณ€ โ€” 360px ์ด์ƒ์€ ๋„˜์นจ 0). **์‹œ์žฅ phase 4์ข…**(2026-09-21 `after` ์‹ ์„ค): `regular`(09:00~15:30) / `nxt`(08:00~09:00 ํ”„๋ฆฌ + 15:30~16:00) / **`after`(16:00~20:00 = KRX ์• ํ”„ํ„ฐ๋งˆ์ผ“ + NXT ์• ํ”„ํ„ฐ๋งˆ์ผ“)** / `closed`ยท`holiday`ยท`weekend`. โš ๏ธ **KRX ์• ํ”„ํ„ฐ๋งˆ์ผ“ ์‹œํ–‰(2026-09-14)์œผ๋กœ NXT ๋ฏธ์ƒ์žฅ ์ข…๋ชฉ๋„ 16:00 ์ดํ›„ ๊ฑฐ๋ž˜๋œ๋‹ค** โ€” ํ•œ ๊ฐ’์œผ๋กœ ๋ญ‰์ณ ๋‘๋ฉด `nxt_enable=False` ์ธ 2,600์—ฌ ์ข…๋ชฉ์ด ๋ถ€๋‹นํ•˜๊ฒŒ ์ž ๊ธด๋‹ค(์‹ค์ธก ๋ณด์œ  16ยท๊ด€์‹ฌ 26ยท๊ฐ์‹œ 46์ข…๋ชฉ์ด '๊ฐ’์€ ๊ฐฑ์‹ ๋˜๋Š”๋ฐ ๋ฒ„ํŠผ์€ ์ž ๊ธด' ์ƒํƒœ์˜€๋‹ค). โš ๏ธ **`after` ์ถ”๊ฐ€ ์‹œ `== 'nxt'` ๋น„๊ต ์†Œ๋น„์ฒ˜๋ฅผ ์ „๋ถ€ ๊ฐ™์ด ๊ณ ์ณ์•ผ ํ•œ๋‹ค** โ€” ์•ˆ ๊ณ ์น˜๋ฉด else ๋กœ ๋–จ์–ด์ ธ ์‹ค์‹œ๊ฐ„ ๊ฐ€๊ฒฉ ๋ณด์ •(`active_map`)ยท๊ฑฐ๋ž˜๊ฐ€๋Šฅ ์ดˆ๋ก์  2๊ณณยทOHLC ํ™œ์„ฑ์—ด์ด **์กฐ์šฉํžˆ ์ฃฝ๋Š”๋‹ค**. ๊ทธ๋ž˜์„œ ๊ฑฐ๋ž˜์‹œ๊ฐ„ ํŒ์ •์€ `_PHASE_TRADING` ์ƒ์ˆ˜๋กœ, ์ข…๋ชฉ๋ณ„ ๊ฑฐ๋ž˜๊ฐ€๋Šฅ์€ **`_phase_tradable(phase, code)` ํ•œ ํ•จ์ˆ˜๋กœ ๋ชจ์•˜๋‹ค**(์˜ˆ์ „์—” ๋ฏธ๋ฆฌ๋ณด๊ธฐ ํ–‰๊ณผ ๋ณด์œ ํ–‰์— ๊ฐ™์€ if/elif ๊ฐ€ ๋ณต์ œ๋ผ ์žˆ์–ด ํ•œ์ชฝ๋งŒ ๊ณ ์น˜๋ฉด ๊ฐ™์€ ์ข…๋ชฉ์ด ํ™”๋ฉด ๋‘ ๊ณณ์—์„œ ๋‹ค๋ฅด๊ฒŒ ๋ณด์˜€๋‹ค). โš ๏ธ **์• ํ”„ํ„ฐ๋งˆ์ผ“ ์ฐจ๋‹จ ๋Œ€์ƒ์€ ETF/ETN ๋ฟ**์ด๊ณ  ํŒ๋ณ„์€ `stock_codes.json` ์˜ `etf_etn` ํ”Œ๋ž˜๊ทธ๋‹ค(2026-09-21 ์‹ค์ธก: TIGER 200 ์€ 15:35 ์ดํ›„ ๊ฑฐ๋ž˜๋Ÿ‰ยทํ˜„์žฌ๊ฐ€ยทํ˜ธ๊ฐ€์ž”๋Ÿ‰์ด **์™„์ „ ๊ณ ์ •**). ์ œ์™ธ์ข…๋ชฉ 9์ข…(๊ฑฐ๋ž˜์ •์ง€ยทํˆฌ์ž๊ฒฝ๊ณ ยท์ด์ƒ๊ธ‰๋“ฑ ๋“ฑ)์€ ํŒ๋ณ„ ํ•„๋“œ๊ฐ€ ์—†์–ด ์™„์ „ ์ฐจ๋‹จ์ด ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค โ€” ๋ง‰์„ ์ˆ˜ ์žˆ๋Š” ๊ฒƒ๋งŒ ๋ง‰๊ณ  ๋‚˜๋จธ์ง€๋Š” ํ‚ค์›€ ๊ฑฐ๋ถ€ ๋ฉ”์‹œ์ง€๋กœ ๋“œ๋Ÿฌ๋‚ธ๋‹ค. โš ๏ธ 15:30~16:00 ์€ `nxt` ๋กœ ๋‚จ๊ธด๋‹ค(KRX ์ชฝ์€ ์‹œ๊ฐ„์™ธ ์ข…๊ฐ€๋งค๋งค๋ฟ์ด๊ณ  ์šฐ๋ฆฌ๋Š” `trde_tp=81` ์„ ์“ฐ์ง€ ์•Š๋Š”๋‹ค). โš ๏ธ ํ˜ธ๊ฐ€ยทํ˜„์žฌ๊ฐ€๋Š” ์• ํ”„ํ„ฐ๋งˆ์ผ“์—” **KRX(bare)** ๋ฅผ ์“ด๋‹ค โ€” KRX ์• ํ”„ํ„ฐ๋งˆ์ผ“ ํ˜ธ๊ฐ€๊ฐ€ bare ์กฐํšŒ๋กœ ๊ทธ๋Œ€๋กœ ์˜จ๋‹ค(์‹ค์ธก ์‚ผ์„ฑ์ „์ž์šฐ ๋งค๋„1/๋งค์ˆ˜1 ์ด 16:05ยท17:00ยท18:00 ๋ชจ๋‘ ๊ฐฑ์‹ ). โš ๏ธ **KRX OHLC ์—ด์˜ '์ข…๊ฐ€' ํ‘œ์‹œ๋Š” 15:30~16:00 ๊ณผ 20:00 ์ดํ›„๋งŒ**์ด๋‹ค โ€” ์• ํ”„ํ„ฐ๋งˆ์ผ“์—” KRX ๊ฐ€ ์ ‘์†๋งค๋งค๋กœ ๋‹ค์‹œ ๋Œ์•„ ๊ฐ€๊ฒฉ์ด ๋ณ€ํ•˜๋ฏ€๋กœ, ์˜ˆ์ „์ฒ˜๋Ÿผ 15:30 ์ดํ›„ ์ „๋ถ€ ์ข…๊ฐ€๋กœ ๋‘๋ฉด '์ข…๊ฐ€'๋ผ ์จ๋†“๊ณ  ๊ฐ’์ด ๊ณ„์† ๋ฐ”๋€๋‹ค. **์• ํ”„ํ„ฐ๋งˆ์ผ“ ์ข…๊ฐ€ โ‰  ๊ณต์‹ ์ „์ผ์ข…๊ฐ€**(2026-09-22 ์‹ค์ธก): ์˜ค๋Š˜์˜ ์ „์ผ์ข…๊ฐ€๋Š” **์–ด์ œ 15:30 ์ •๊ทœ์žฅ ์ข…๊ฐ€**๋‹ค(7์ข…๋ชฉ ์ „์ˆ˜ โ€” ์‚ผ์„ฑ์ „์ž์šฐ ์ •๊ทœ์žฅ 208,000 / ์• ํ”„ํ„ฐ ๋งˆ์ง€๋ง‰ 210,500 โ†’ ์˜ค๋Š˜ ์ „์ผ์ข…๊ฐ€ 208,000). ๊ทธ๋Ÿฐ๋ฐ `stock_portfolio_report` ๋Š” ์Šค๋ƒ…์ƒท์„ **20:10** ์— ์ฐ๊ณ  kt00018 ์„ **`exchange='NXT'`** ๋กœ ์กฐํšŒํ•ด์„œ, NXT **์ƒ์žฅ** ์ข…๋ชฉ์—” ์• ํ”„ํ„ฐ ์ข…๊ฐ€๊ฐ€ NXT **๋ฏธ๊ฑฐ๋ž˜** ์ข…๋ชฉ์—” **stale**(์ •๊ทœ์žฅ ์ข…๊ฐ€)์ด ๋“ค์–ด๊ฐ„๋‹ค โ€” **ํ•œ ์Šค๋ƒ…์ƒท์— ๋‘ ๊ธฐ์ค€์ด ์„ž์ธ๋‹ค**(์–ด์ œ ์‹ค์ธก: ์‚ผ์„ฑ์ „์ž 275,000 ์• ํ”„ํ„ฐ / ์ œ๋‹‰์Šค๋กœ๋ณดํ‹ฑ์Šค 6,150 stale). โš ๏ธ ์• ํ”„ํ„ฐ๋งˆ์ผ“ ์‹œํ–‰(2026-09-14) **์ „์—๋Š” ๋ฌธ์ œ๊ฐ€ ์—†์—ˆ๋‹ค** โ€” 20:10 ์Šค๋ƒ…์ƒท์ด ๊ณง ์ •๊ทœ์žฅ ์ข…๊ฐ€๋ผ KRX ์—ด๊ณผ ํ†ตํ•ฉ ์—ด baseline ์ด ์šฐ์—ฐํžˆ ์ผ์น˜ํ–ˆ๊ณ , ์• ํ”„ํ„ฐ๋งˆ์ผ“์ด ๊ทธ ์šฐ์—ฐ์„ ๊นผ๋‹ค. ๊ทธ๋ž˜์„œ `_fetch_all_data` ๊ฐ€ **`_nxt_inactive` ์ข…๋ชฉ์˜ `pred_close_snap`/`pred_close`/`day_change` ๋ฅผ KRX ๋ฐฐ์น˜์‹œ์„ธ์˜ ์ „์ผ์ข…๊ฐ€(`price โˆ’ change`)๋กœ ๋ฎ์–ด์“ด๋‹ค** โ€” ์‹ค์ธก ์•„๋‚œํ‹ฐ ๋ฏธ๋‹ˆํ‘œ ์ „์ผ์ข…๊ฐ€ `5,210 | 5,210` ๋‘ ์—ด ์ผ์น˜. NXT ์ƒ์žฅ ์ข…๋ชฉ์ด `274,000 | 275,000` ์œผ๋กœ ๊ฐˆ๋ฆฌ๋Š” ๊ฑด **์˜๋„๋œ ์„ค๊ณ„**๋‹ค. โš ๏ธ **๋‘ ์ง€ํ‘œ๊ฐ€ ์„œ๋กœ ๋‹ค๋ฅธ baseline ์„ ์“ฐ๋Š” ๊ฒƒ์ด ์ •๋‹ต์ด๋‹ค** โ€” ๋ฏธ๋‹ˆํ‘œ ๋“ฑ๋ฝ๋ฅ ์€ ์‹œ์žฅ ํ‘œ๊ธฐ์™€ ๋งž์•„์•ผ ํ•˜๋‹ˆ **๊ณต์‹ ์ „์ผ์ข…๊ฐ€(15:30)**, ๋‹น์ผ ํ‰๊ฐ€์†์ต(`prev_net`)์€ '์–ด์ œ ์žฅ ๋งˆ๊ฐ ๋Œ€๋น„ ๋‚ด ์ž์‚ฐ ๋ณ€๋™'์ด๋‹ˆ **์• ํ”„ํ„ฐ ์ข…๊ฐ€(20:00)**(`correct_nxt_inactive_rows` ๊ฐ€ ์Šค๋ƒ…์ƒท `price`/`eval_value` ๋ฅผ KRX ์ตœ์‹ ๊ฐ€๋กœ ๊ต์ฒดํ•ด ์ด์ชฝ์„ ํ†ต์ผ). **ํ•œ์ชฝ์œผ๋กœ ํ•ฉ์น˜๋ ค ํ•˜์ง€ ๋ง ๊ฒƒ.** โš ๏ธ `_nxt_inactive` ํŒ์ •์€ ์ „๋‚  ์Šค๋ƒ…์ƒท ๋ชฉ๋ก๋งŒ ๋ฏฟ์œผ๋ฉด ์•ˆ ๋œ๋‹ค โ€” ๋ชฉ๋ก์ด ๋‚ก๊ฑฐ๋‚˜ ์‹ ๊ทœ ์ข…๋ชฉ์ด๋ฉด ํ†ตํ•ฉ ์—ด์— ์—‰๋šฑํ•œ baseline ์ด ๋“ค์–ด๊ฐ€๋ฏ€๋กœ `not _is_nxt_traded(code)` ๋ฅผ ํ•จ๊ป˜ ๋ณธ๋‹ค(์บ์‹œ ๋ฏธ์Šค ์‹œ True ๋ผ ๋ฏธ์ง€ ์ข…๋ชฉ์„ ์ž ๊ทธ์ง€ ์•Š๋Š”๋‹ค). **์‹œ์žฅ phase ์ „ํ™˜ ์žฌ๋ Œ๋”**(2026-08-25): 2026-07-22 ์ด๋ฒคํŠธ ๊ธฐ๋ฐ˜ ์ „ํ™˜์œผ๋กœ ์ฃผ๊ธฐ์  ํŒจ๋„ swap ์ด ์‚ฌ๋ผ์ง„ ๋’ค, `auto_reload_script` ์˜ `/api/market_state` ํด๋ง์ด **์œ ์ผํ•œ ์‹œ๊ฐ ๊ธฐ๋ฐ˜ ์žฌ๋ Œ๋” ํŠธ๋ฆฌ๊ฑฐ**๋‹ค. โš ๏ธ ์ „ํ™˜ ํŒ์ •์„ `active` ๋ถˆ๋ฆฌ์–ธ์œผ๋กœ ํ•˜๋ฉด ์•ˆ ๋œ๋‹ค โ€” `regular`ยท`nxt` ๋‘˜ ๋‹ค `active:true` ๋ผ **09:00ยท15:30 ์ „ํ™˜์ด ์•„์˜ˆ ๊ฐ์ง€๋˜์ง€ ์•Š๊ณ **, ์ฒด๊ฒฐยทํƒญ์ „ํ™˜์ด ์—†์œผ๋ฉด ๊ฑฐ๋ž˜๊ฐ€๋Šฅ ์ดˆ๋ก์ (`.px-dot.tradable`)ยทOHLC ํ™œ์„ฑ ์ปฌ๋Ÿผ์ด ๋ฌด๊ธฐํ•œ stale ๋กœ ๊ตณ๋Š”๋‹ค. ๊ทธ๋ž˜์„œ `phase` ๋ฌธ์ž์—ด์„ ํ•จ๊ป˜ ๋น„๊ตํ•œ๋‹ค. โš ๏ธ ์ „ํ™˜ ์‹œ ์žฌ๋ Œ๋”๋Š” **`__behive_load(null,true)` fresh ํ•„์ˆ˜** โ€” ํŒจ๋„ ์บ์‹œ(10s)๊ฐ€ ์ „ํ™˜ ์ง์ „ HTML ์„ ๋Œ๋ ค์ฃผ๋ฉด ๊ทธ๊ฑธ ๊ณ ์น  ๋‹ค์Œ ํŠธ๋ฆฌ๊ฑฐ๊ฐ€ ์—†๋‹ค. โš ๏ธ ํด๋ง์€ `setInterval` ๊ณ ์ • 60์ดˆ๊ฐ€ ์•„๋‹ˆ๋ผ **`_secs_to_next_phase()`(์‘๋‹ต `next_in`)๋กœ ๋‹ค์Œ ๊ฒฝ๊ณ„ +2์ดˆ์— ๋งž์ถฐ ์žฌ์˜ˆ์•ฝํ•˜๋Š” `setTimeout` ์ฒด์ธ**์ด๋‹ค(๊ณ ์ • ์ฃผ๊ธฐ๋ฉด ๊ฒฝ๊ณ„์™€ ์ตœ๋Œ€ 60์ดˆ ์–ด๊ธ‹๋‚จ). `now.second` ์ ˆ์‚ฌ๋ผ ๊ฐ’์ด ํ•ญ์ƒ ์‹ค์ œ๋ณด๋‹ค ํฌ๊ฑฐ๋‚˜ ๊ฐ™์•„ ํƒ€์ด๋จธ๊ฐ€ ๊ฒฝ๊ณ„๋ณด๋‹ค ์ผ์ฐ ๊นจ์ง€ ์•Š๋Š”๋‹ค. ์ˆจ๊น€ ์ƒํƒœ์—์„  ํด๋ง์„ ๊ฑด๋„ˆ๋›ฐ๋ฏ€๋กœ `visibilitychange` ๋ณต๊ท€ ์‹œ 300ms ๋’ค 1ํšŒ ํ™•์ธ. **ํ—ˆ๋ธŒ ์ข…๋ฃŒ ์‹œ ์‹ค์‹œ๊ฐ„ ์Šค๋ƒ…์ƒท ํ๊ธฐ**(2026-09-10): โš ๏ธ `/api/realtime/quotes` ํด๋ง์ด `connected:false` ๋ฅผ ๋ฐ›๊ณ  **๊ทธ๋ƒฅ return ํ•˜๋ฉด ์•ˆ ๋œ๋‹ค** โ€” ๋งˆ์ง€๋ง‰ ์‘๋‹ต์ด `connected:true` ์ธ ์ฑ„ `window.__rtState` ์— ๋‚จ๊ณ , `behive:panels-loaded` ํ›…์˜ `applyState(__rtState)` ๊ฐ€ `d.connected`(์˜› true)๋งŒ ๋ณด๊ณ  ํ†ต๊ณผํ•ด **์„œ๋ฒ„๊ฐ€ ๋ฐฉ๊ธˆ ์กฐํšŒํ•œ ๊ฐ’์„ ์˜› ํ‹ฑ์œผ๋กœ ๋ฎ์–ด์“ด๋‹ค**. 20:00 NXT ๋งˆ๊ฐ โ†’ ํ—ˆ๋ธŒ ์ข…๋ฃŒ(์žฅ๋งˆ๊ฐ ํ™•์ธ์ด 30์ดˆ ์ฃผ๊ธฐ๋ผ 20:00:00~20:00:30) ๋’ค์—๋Š” ์ด ๊ฒฝ๋กœ ๋•Œ๋ฌธ์— **phase ์ „ํ™˜ ์žฌ๋ Œ๋”๋ฅผ ํ•ด๋„ ํ™”๋ฉด์ด 19:5x ๊ฐ’์— ๊ณ ์ฐฉ**๋๋‹ค(์‹ค์ธก: swap ํ›„ ์ข…๋ชฉ ํ–‰ยทowner KPI ๋Š” ์˜› rt, ๊ณ„์ขŒ๋ณ„ KPI ๋Š” ์„œ๋ฒ„ REST ๋ผ ํ•œ ํ™”๋ฉด์—์„œ 3,848,000์› ๊ฐˆ๋ฆผ). ๊ทธ๋ž˜์„œ ๋Š๊ธฐ๋ฉด `__rtState`ยท`__rtPx` ๋ฅผ **null ๋กœ ๋ฒ„๋ฆฐ๋‹ค** โ€” ํ—ˆ๋ธŒ๊ฐ€ ์—†์œผ๋ฉด REST ๊ฐ€ ์ง„์‹ค์ด๋‹ค. โš ๏ธ **20:00 ์ดํ›„์—” ์„œ๋ฒ„ ์žฌ๋ Œ๋” ํŠธ๋ฆฌ๊ฑฐ๊ฐ€ ์‚ฌ์‹ค์ƒ ์—†๋‹ค** โ€” `holdings_seq` ํด๋ง์€ ์žฅ์™ธ ์Šคํ‚ต, `fill_seq` ๊ฐ์ง€๋Š” `connected:false` ๋ฉด tick ์ด ๋จผ์ € return. ์ˆ˜๋™ ์ƒˆ๋กœ๊ณ ์นจยทPTRยทํŽ˜์ด์ง€ ์žฌ์ง„์ž…์ด ์ „๋ถ€๋‹ค. โš ๏ธ **๊ณ„์ขŒ๋ณ„ KPI(`_render_account_kpi`)๋Š” ์—ฌ์ „ํžˆ ์‹ค์‹œ๊ฐ„ ๊ฐฑ์‹  ๋Œ€์ƒ์ด ์•„๋‹ˆ๋‹ค**(`setOwnerKpis` ๊ฐ€ `[data-rt-owner]` ์นด๋“œ๋งŒ ๊ฐฑ์‹ ) โ€” ์žฅ์ค‘์—” owner ํ•ฉ๊ณ„(rt ๊ธฐ์ค€)์™€ ๊ณ„์ขŒ๋ณ„ ํ•ฉ(์„œ๋ฒ„ ๋ Œ๋” ์‹œ์ )์ด ์ƒ์‹œ ์–ด๊ธ‹๋‚œ๋‹ค. 2026-09-10 ๊ด€๋ฆฌ์ž๋‹˜ ํŒ๋‹จ์œผ๋กœ ์ด์ชฝ์€ ์†๋Œ€์ง€ ์•Š์•˜๋‹ค. **์ฐจํŠธ๋ณด๊ธฐ ์ปจํŠธ๋กค**(2026-10-02 ๊ด€๋ฆฌ์ž๋‹˜ ์ง€์ •): **ํ•ญ์ƒ ํ•œ ์ค„ 4์นธ**(๋†’์ด 28px) `[์—ฐ๋„๋ณ„โ–พ] [์›”๋ณ„โ–พ] [๊ธฐ๊ฐ„์„ค์ •] [์ž์‚ฐํ˜•ํƒœโ–พ]` ๋„ค ๊ฐœ๋ฟ โ€” โš ๏ธ ๋ณด์ด๋Š” ๊ฑด 11px ๋ผ๋ฒจ(`.cc-txt`)์ด๊ณ  ์‹ค์ œ select ๋Š” ์œ„์— `opacity:0` ์œผ๋กœ ๊ฒน์ณ ๋‘”๋‹ค(select ๋ฅผ 16px ๋ฏธ๋งŒ์œผ๋กœ ์ค„์ด๋ฉด iOS ๊ฐ€ ํƒญํ•  ๋•Œ ํ™”๋ฉด์„ ํ™•๋Œ€ํ•œ๋‹ค). ์›” ๋ผ๋ฒจ์€ `2026.10` ์œผ๋กœ ์ถ•์•ฝ, ๊ธฐ๊ฐ„์„ค์ • ์นธ๋งŒ 1.4๋ฐฐ ํญ(`08.14~09.03` ์ด 320px ์—์„œ ์•ˆ ์ž˜๋ฆฌ๊ฒŒ) โ€” ๊ธฐ์กด ํ”„๋ฆฌ์…‹(์ „์ฒด๋ณด๊ธฐ/์˜ฌํ•ด/์ด๋ฒˆ๋‹ฌ/์ด๋ฒˆ์ฃผ)ยท๋‹จ์œ„ selectยท์ง€์ •๊ธฐ๊ฐ„/์œ ํ˜• ์ค„์€ **์ œ๊ฑฐ**ํ–ˆ๋‹ค. ์—ฐ๋„๋ณ„=`2026๋…„โ€ฆ` ๊ณ ๋ฅด๋ฉด ๊ทธ ํ•ด๋ฅผ **์›” ๋‹จ์œ„** / ์›”๋ณ„=`2026๋…„ 10์›”โ€ฆ`(๋ฐ์ดํ„ฐ ์žˆ๋Š” ๋‹ฌ๋งŒ) ๊ณ ๋ฅด๋ฉด ๊ทธ ๋‹ฌ์„ ์ผ ๋‹จ์œ„ / ๊ธฐ๊ฐ„์„ค์ •=๋ฒ„ํŠผ โ†’ ์…ธ ์ง์† `range-modal` ํŒ์—…(๋‹จ์œ„ ์ผ๋ณ„ยท์›”๋ณ„ + ์‹œ์ž‘ยท์ข…๋ฃŒ, ๋‹จ์œ„ ๋ฐ”๊พธ๋ฉด ์ž…๋ ฅ์ด dateโ†”month ๋กœ ๋ณ€ํ™˜) โ†’ ์ ์šฉ. ์…‹ ์ค‘ ์ ์šฉ ์ค‘์ธ ๊ฒƒ๋งŒ ๊ฐ’์ด ๋ณด์ด๊ณ  `cc-active`(๋นจ๊ฐ„ ํ…Œ๋‘๋ฆฌ), ๋‚˜๋จธ์ง€๋Š” ์ด๋ฆ„๋งŒ ํ๋ฆฌ๊ฒŒ. ๋ฏธ์ง€์ •์ด๋ฉด **์ด๋ฒˆ ๋‹ฌ(์›”๋ณ„)์ด ๊ธฐ๋ณธ**. ์ƒํƒœ๋Š” `chart_ym` ํ•˜๋‚˜์— **ํ˜•์‹์œผ๋กœ ๋‹จ์œ„๊นŒ์ง€ ์ธ์ฝ”๋”ฉ**(`YYYY` / `YYYY-MM` / `D~D` / `YYYY-MM~YYYY-MM`) โ€” ํŒ์ •์€ `_parse_chart_ym` ํ•œ ๊ณณ. ์ฐจํŠธ ์ œ๋ชฉ์€ '์ตœ๊ทผ N์›”' ๋Œ€์‹  ๊ธฐ๊ฐ„ ์ž์ฒด(`2026๋…„`, `2026.04~2026.09`). โš ๏ธ ์„œ๋ฒ„์˜ `chart_days`/`chart_unit` ํŒŒ๋ผ๋ฏธํ„ฐ ์ฒ˜๋ฆฌ์™€ `_load_net_worth_series` ์˜ ํ”„๋ฆฌ์…‹ ๋ถ„๊ธฐ๋Š” ์•„์ง ๋‚จ์•„ ์žˆ๋‹ค(UI ์—์„œ๋งŒ ์•ˆ ์“ด๋‹ค โ€” ์ •๋ฆฌ๋Š” ๊ด€๋ฆฌ์ž๋‹˜ ํ™•์ธ ํ›„). โš ๏ธ ํŒ์—…์ด ์—ด๋ฆฌ๋ ค๋ฉด `window.__behiveOpenModal/__behiveCloseModal` export ๊ฐ€ ํ•„์š”ํ•˜๋‹ค(openModal ์ด ๋‹ค๋ฅธ IIFE ์•ˆ์— ์žˆ๋‹ค). โš ๏ธ `load()` ๋Š” **์š”์ฒญ ํ›„ ์ฐจํŠธ ์„ค์ •์ด ๋ฐ”๋€Œ๋ฉด ์‘๋‹ต์„ ๋ฒ„๋ฆฐ๋‹ค**(`chartSig`) โ€” fresh ์š”์ฒญ๋ผ๋ฆฌ๋Š” dedupe ๊ฐ€ ์—†์–ด, ๋Šฆ๊ฒŒ ์˜จ ์˜› ์„ค์ • ์‘๋‹ต์ด ์ƒˆ ์ฐจํŠธ๋ฅผ ๋ฎ์–ด์“ฐ๋˜ ๊ฒฝํ•ฉ์„ ์‹ค์ธก์œผ๋กœ ์žก์•˜๋‹ค. **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ยท๋ชจ๋‹ฌ ์ถ”๊ฐ€๊ฐ€ ํ•„์š” ์—†๋‹ค โ€” ๋ Œ๋” ํ•จ์ˆ˜ + ์—”๋“œํฌ์ธํŠธ ๋ถ„๊ธฐ๋งŒ ๋”ํ•˜๋ฉด ๋œ๋‹ค. ํ˜„์žฌ 4๊ฐœ: `/api/surge?code=&name=`(`_render_surge_body` โ€” ๊ธ‰๋“ฑ๋ฝ ์•Œ๋ฆผ ๊ตฌ๊ฐ„ยท์˜ค๋Š˜ ์†Œ์ง„ยทon/off ํ† ๊ธ€, ์•„๋ž˜ ์ฐธ์กฐ) / `/api/deposit?owner=` / `/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๊ณ„์ขŒ ํ†ตํ•ฉ + ํ–‰๋ณ„ ์ทจ์†Œยท๊ฐ€๊ฒฉ ์ •์ •). **๊ฐ€๊ฒฉ ์ •์ •**(2026-09-11): ํ–‰์˜ `์ •์ •` ๋ฒ„ํŠผ(โ†”`์ ‘๊ธฐ` ํ† ๊ธ€)์ด ํ–‰ ์•ˆ์— ์ธ๋ผ์ธ ์ž…๋ ฅ์ค„์„ ํŽผ์นœ๋‹ค โ€” ๊ธฐ์กด ์ฃผ๋ฌธ๊ฐ€ prefillยท`snapToTick` ํ˜ธ๊ฐ€ ์ž๋™ ๋ณด์ •(ํ‚ค์›€ ๊ฑฐ๋ถ€ ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๊ธฐ ์ „์— ๋งž์ถ˜๋‹ค)ยทEnter ์ œ์ถœยทํ™•์ธ ํŒ์—… 1ํšŒ โ†’ `POST /api/orders/modify`. **PIN ์—†์Œ**(์ทจ์†Œ์™€ ๊ฐ™์€ ์ •์ฑ… โ€” ์ด๋ฏธ ์Šน์ธ๋œ ์ฃผ๋ฌธ์˜ ๊ฐ€๊ฒฉ๋งŒ ๋ฐ”๋€Œ๊ณ  ์ˆ˜๋Ÿ‰ ์ฆ๊ฐ€ ๊ฒฝ๋กœ๊ฐ€ ์—†๋‹ค). **๊ฐ€๋“œ๋Š” ์‹ ๊ทœ ์ฃผ๋ฌธ๊ณผ ๊ฐ™์€ ๊ฒƒ์„ ํƒœ์šด๋‹ค**(2026-09-11) โ€” `guards.validate_price_band`(ยฑ30% ์ œํ•œํญ)์™€, ๋งค์ˆ˜๋ฉด `guards.validate_balance_for_buy`(์˜ˆ์ˆ˜๊ธˆ). propose ๋งŒ ๋ง‰์•„๋‘๋ฉด ์ •์ •์ด ๊ทธ ๊ฒ€์ฆ์„ ์šฐํšŒํ•˜๋Š” ๋’ท๋ฌธ์ด ๋˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. โš ๏ธ **์˜ˆ์ˆ˜๊ธˆ์€ ๋˜๋”ํ•ด์„œ ๋น„๊ตํ•œ๋‹ค** โ€” `datasource.collect_market_data` ์˜ `balance_d2` ๋Š” ๋ฏธ์ฒด๊ฒฐ ๋งค์ˆ˜๋กœ ๋ฌถ์ธ ๋ˆ์„ **์ •์ • ๋Œ€์ƒ ์ฃผ๋ฌธ๊นŒ์ง€ ํฌํ•จํ•ด** ๋บ€ ๊ฐ’์ด๋ผ, ๊ทธ ์ฃผ๋ฌธ ๋ชซ(`order_price ร— unfilled_qty`)์„ ๋˜๋Œ๋ ค ๋”ํ•˜์ง€ ์•Š์œผ๋ฉด **์ œ ์ฃผ๋ฌธ์— ์ œ๊ฐ€ ๋ง‰ํžŒ๋‹ค**(149,000ร—2 ๋กœ ๋ฌถ์ธ ์ƒํƒœ์—์„œ 149,100 ์œผ๋กœ ์˜ฌ๋ฆฌ๋Š” ๊ฒƒ์กฐ์ฐจ '์˜ˆ์ˆ˜๊ธˆ ๋ถ€์กฑ'). ๋˜๋”ํ•˜๋Š” ์‹์€ datasource ์˜ locked ๊ณ„์‚ฐ๊ณผ **๊ฐ™์•„์•ผ** ์ •ํ™•ํžˆ ์ƒ์‡„๋œ๋‹ค. โš ๏ธ ๋งค๋„ ๋ณด์œ ์ˆ˜๋Ÿ‰(`validate_position_for_sell`)์€ ํƒœ์šฐ์ง€ ์•Š๋Š”๋‹ค โ€” ์ด๋ฏธ ์ ‘์ˆ˜๋œ ์ฃผ๋ฌธ์˜ ์ˆ˜๋Ÿ‰์„ ๊ทธ๋Œ€๋กœ ๋‘๊ฑฐ๋‚˜ ์ค„์ด๋Š” ๊ฒฝ๋กœ๋ผ ์ƒˆ๋กœ ํ•„์š”ํ•œ ๋ณด์œ ๋ถ„์ด ์—†๋‹ค. โš ๏ธ **`collect_market_data` ๋ฅผ ํ†ต์งธ๋กœ ์žฌ์‚ฌ์šฉํ•ด ์ •์ • 1ํšŒ์— ํ‚ค์›€ 5~6์ฝœ**์ด ๋‚˜๊ฐ„๋‹ค(ํ˜ธ๊ฐ€ ka10004ยท์ฒด๊ฒฐ kt00007 ์€ ์ •์ •์—” ๋ถˆํ•„์š”ํ•˜์ง€๋งŒ ํ•จ์ˆ˜๋ฅผ ์ชผ๊ฐœ์ง€ ์•Š์•˜๋‹ค). ์ˆ˜๋™ยท์ €๋นˆ๋„ ์กฐ์ž‘์ด๋ผ ์ˆ˜์šฉํ•œ ํŠธ๋ ˆ์ด๋“œ์˜คํ”„. โš ๏ธ ์‹œ์„ธ ์กฐํšŒ๊ฐ€ ์‹คํŒจํ•˜๋ฉด `upper_limit=0` ์ด๋ผ **๋ชจ๋“  ์ •์ •์ด ๊ฑฐ๋ถ€**๋œ๋‹ค(propose ์™€ ๊ฐ™์€ ๋ณด์ˆ˜์  ์‹คํŒจ). โš ๏ธ **์ˆ˜๋Ÿ‰์€ ์›น์—์„œ ์—ด์ง€ ์•Š์•˜๋‹ค**(๊ฐ€๊ฒฉ๋งŒ ๋ณด๋‚ธ๋‹ค) โ€” ๋‹ค๋งŒ ๋ฐฑ์—”๋“œ๋Š” qty ๋ฅผ ๋ฐ›์œผ๋ฏ€๋กœ CLIยทํ…”๋ ˆ๊ทธ๋žจ์˜ ์ˆ˜๋Ÿ‰ ์ฆ๊ฐ€๋„ ์ด์ œ ๊ฐ™์€ ์˜ˆ์ˆ˜๊ธˆ ๊ฒ€์ฆ์„ ๋ฐ›๋Š”๋‹ค. โš ๏ธ **์Šคํ†ฑ์ง€์ •๊ฐ€ยทํŠธ๋ ˆ์ผ๋ง ๋ ˆ๊ทธ๋Š” ์ •์ • ๋ถˆ๊ฐ€** โ€” `handler.modify_open_order` ๊ฐ€ `row['stop_price']>0` ์ด๋ฉด **์ „ ๊ฒฝ๋กœ์—์„œ**(์›นยทํ…”๋ ˆ๊ทธ๋žจ ๊ณตํ†ต) ๊ฑฐ๋ถ€ํ•œ๋‹ค. ๋‘ ๊ฐ€์ง€๊ฐ€ ๋™์‹œ์— ๊นจ์ง€๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค: โ‘ `mdfy_cond_uv`(์กฐ๊ฑด๋‹จ๊ฐ€)๋ฅผ ์•ˆ ๋„˜๊ฒจ ์กฐ๊ฑด์ด ๋นˆ ๊ฐ’์œผ๋กœ ๋‚˜๊ฐ„๋‹ค โ‘ก์ •์ • ์‘๋‹ต์˜ `ord_no` ๋Š” **์‹ ๊ทœ ์ฃผ๋ฌธ๋ฒˆํ˜ธ**์ธ๋ฐ `trailing_stops.json` ์˜ ๋ ˆ๊ทธ๋Š” ๊ทธ๊ฑธ ๋ชจ๋ฅด๋ฏ€๋กœ ๊ทธ ๋ ˆ๊ทธ์˜ ์ž๋™ ์†์ ˆ์„  ์ƒํ–ฅ์ด ์ดํ›„ ์ „๋ถ€ ์‹คํŒจํ•œ๋‹ค. ๋ฐ”๊พธ๋ ค๋ฉด ์ทจ์†Œ ํ›„ ์žฌ๋“ฑ๋ก. ํ”„๋ŸฐํŠธ๋„ ๊ฐ™์€ ๊ธฐ์ค€(`!r.trailing && !r.stop_price && r.order_price > 0`)์œผ๋กœ ๋ฒ„ํŠผ ์ž์ฒด๋ฅผ ์•ˆ ๊ทธ๋ฆฐ๋‹ค โ€” ์‹œ์žฅ๊ฐ€๋Š” ๊ฐ€๊ฒฉ์ด 0์ด๋ผ ์• ์ดˆ์— ์ •์ • ๋ถˆ๊ฐ€. โš ๏ธ **์ •์ • ์„ฑ๊ณต ํ›„ `loadOpenOrders()` ์žฌ์กฐํšŒ๋Š” ํ•„์ˆ˜**(ord_no ๊ฐ€ ๋ฐ”๋€Œ์–ด ํ™”๋ฉด์˜ ์˜› ๋ฒˆํ˜ธ๋กœ๋Š” ๋‹ค์Œ ์ทจ์†Œยท์ •์ •์ด ์—‰๋šฑํ•œ ๊ณณ์— ๊ฐ„๋‹ค). โš ๏ธ ํŽธ์ง‘์ค„์— [์ทจ์†Œ] ๋ฒ„ํŠผ์„ ๋‘์ง€ ์•Š๋Š”๋‹ค โ€” ์˜ค๋ฅธ์ชฝ ์ฃผ๋ฌธ [์ทจ์†Œ]์™€ ๋ง์ด ๊ฒน์ณ ์˜ค์กฐ์ž‘์„ ๋ถ€๋ฅธ๋‹ค(์ ‘๊ธฐ๋Š” `์ •์ •`โ†”`์ ‘๊ธฐ` ํ† ๊ธ€๋กœ). ๋งค์ˆ˜ ์‹œ ๊ธˆ์•กโ†”์ˆ˜๋Ÿ‰ ์–‘๋ฐฉํ–ฅ ์ž๋™(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=ํ•˜๋‚˜๋ผ๋„ ์ ‘์ˆ˜). **๋งค๋„ ์ฃผ๋ฌธ์œ ํ˜• 5์ข…** โ€” ์ง€์ •๊ฐ€(LIMIT) / ์‹œ์žฅ๊ฐ€(MARKET) / ์Šคํ†ฑ์ง€์ •๊ฐ€(STOP_LIMIT, ํ•˜๋ฝ ์‹œ ๋งค๋„ยท์กฐ๊ฑด๋‹จ๊ฐ€ ๊ณ ์ •) / **ํŠธ๋ ˆ์ผ๋ง ์Šคํ†ฑ(TRAILING_STOP, 2026-07-30 ์ถ”๊ฐ€)** / **์˜ˆ์•ฝ ํŠธ๋ ˆ์ผ๋ง(TRAILING_ARM, 2026-08-25 ์ถ”๊ฐ€ โ€” ๋ฐœ๋™๊ฐ€์— ๋‹ฟ์œผ๋ฉด ๊ทธ๋•Œ ํŠธ๋ ˆ์ผ๋ง ์‹œ์ž‘. ์ƒ์„ธ๋Š” ์•„๋ž˜ ใ€Œ์˜ˆ์•ฝ ํŠธ๋ ˆ์ผ๋งใ€)**. ๋’ค 2๊ฐœ๋Š” ๋งค๋„ ์ „์šฉ(๋งค์ˆ˜ ์„ ํƒ ์‹œ ์˜ต์…˜ disabled + LIMIT๋กœ ๋˜๋Œ๋ฆผ, `refreshStopUI`). **ํŠธ๋ ˆ์ผ๋ง ์ž…๋ ฅ**(๋‹จ๊ฐ€ ์ž…๋ ฅํ–‰์€ ์ˆจ๊น€ โ€” ์กฐ๊ฑด๋‹จ๊ฐ€ยท์ง€์ •๊ฐ€ยท๊ณ„๋‹จ๋ณ„ ์ฃผ์ˆ˜๋Š” ์„œ๋ฒ„ ๊ณ„์‚ฐ): โ‘ **๊ณ„๋‹จ ํ”„๋ฆฌ์…‹ ๋“œ๋กญ๋‹ค์šด** โ€” ์ฝ”๋“œ ์ƒ์ˆ˜ `TRAIL_PRESETS` **๊ณ ์ • 4์ข…, ์ฝ๊ธฐ ์ „์šฉ**. ํ‘œ์‹œ ์ˆœ์„œ = **๋‹จ์ผ / ๋ณด์ˆ˜ / ํ‘œ์ค€ / ๋А์Šจ**(๊ธฐ๋ณธ๊ฐ’์€ ๋งจ ์•ž `๋‹จ์ผ`, ๊ทธ ๋’ค๋กœ ํŠธ๋ ˆ์ผ ํญ์ด ์ข์€ ๊ฒƒ๋ถ€ํ„ฐ). ์˜ต์…˜์€ **์ด๋ฆ„๋งŒ** โ€” ๊ณ„๋‹จ ์ˆ˜์น˜๋Š” ๋ฐ”๋กœ ์•„๋ž˜ ํŽธ์ง‘ ํ‘œ์— ๊ทธ๋Œ€๋กœ ๋ณด์—ฌ ์ค‘๋ณต์ด๋‹ค(2026-07-31 ๊ด€๋ฆฌ์ž๋‹˜ ์ง€์‹œ, ๋‹ค์‹œ ๋ถ™์ด์ง€ ๋ง ๊ฒƒ). ์…ธ HTML์— `window.__trailPresets`๋กœ ์‹ค๋ ค ๋ชจ๋‹ฌ ์—ด ๋•Œ fetch 0. โš ๏ธ **ํ”„๋ฆฌ์…‹ ์ €์žฅยท์‚ญ์ œ ๊ธฐ๋Šฅ์€ ๋‘์ง€ ์•Š๋Š”๋‹ค**(2026-07-31 ๊ด€๋ฆฌ์ž๋‹˜ ์ง€์‹œ๋กœ ์ œ๊ฑฐ โ€” ๊ณ ๋ฅธ ๋’ค ์•„๋ž˜ ํ‘œ์—์„œ ๊ทธ ์ž๋ฆฌ์— ๊ณ ์ณ ์“ฐ๋ฉด ๋˜๋ฏ€๋กœ ์ €์žฅ์†Œยท๋ฝยท์—”๋“œํฌ์ธํŠธ๊ฐ€ ๋ถˆํ•„์š”ํ–ˆ๋‹ค. `state/trailing_presets.json`๋„ ํ๊ธฐ). ํ”„๋ฆฌ์…‹์„ ๋Š˜๋ฆฌ๋ ค๋ฉด ์ƒ์ˆ˜๋ฅผ ๊ณ ์นœ๋‹ค โ‘ก๊ทธ ์•„๋ž˜ **๊ณ„๋‹จ ํŽธ์ง‘ ํ…Œ์ด๋ธ”**(`ํ•˜๋ฝ/๋ˆ„์ ` **ํ—ค๋” ํ•œ ์ค„** + ํ–‰๋งˆ๋‹ค `[__]% [__]%` + โœ•, ์•„๋ž˜ full-width `+ ๊ณ„๋‹จ ์ถ”๊ฐ€`, ์ตœ๋Œ€ 5) โ‘ข**์ตœ์ € ๋งค๋„๊ฐ€**(์„ ํƒ, ๋น„์šฐ๋ฉด ์ œํ•œ ์—†์Œ). โš ๏ธ **๋ผ๋ฒจ์„ ํ–‰๋งˆ๋‹ค ๋ฐ˜๋ณตํ•˜์ง€ ๋ง ๊ฒƒ**(2026-07-31 ์ •๋ฆฌ) โ€” `.order-inputs` ์‹คํญ์ด ๋ชจ๋ฐ”์ผ ~200px๋ผ ํ–‰๋งˆ๋‹ค 'ํ•˜๋ฝ'ยท'๋ˆ„์ ' ๊ธ€์ž์™€ ํ™”์‚ดํ‘œ๋ฅผ ๋„ฃ์œผ๋ฉด ์ž…๋ ฅ์นธ์ด 38px(์‹คํ…์ŠคํŠธ 26px)๊นŒ์ง€ ๋ˆŒ๋ฆฐ๋‹ค. ํ—ค๋”๋กœ ๋นผ๊ณ  ํ™”์‚ดํ‘œ๋ฅผ ์ง€์›Œ 78px๋กœ ํšŒ๋ณตํ–ˆ๊ณ , number ์Šคํ”ผ๋„ˆ๋„ `-webkit-appearance:none`์œผ๋กœ ์—†์•ด๋‹ค(๋ฐ์Šคํฌํ†ฑ์—์„œ ์ˆซ์ž๋ฅผ ๊ฐ€๋ฆผ). โš ๏ธ ํ—ค๋” ํ–‰๋„ `.trail-step` ํด๋ž˜์Šค๋ผ **`trailSteps()`๋Š” `:not(.trail-step-head)`๋กœ ๊ฑธ๋Ÿฌ์•ผ ํ•œ๋‹ค** โ€” ์•ˆ ๊ทธ๋Ÿฌ๋ฉด ์ž…๋ ฅ์นธ ์—†๋Š” ํ–‰์„ ์ฝ์–ด TypeError. โš ๏ธ ๊ณ„๋‹จ 0๊ฐœ๋ฉด ํ—ค๋”๋„ ๊ทธ๋ฆฌ์ง€ ์•Š๋Š”๋‹ค. ๋‹จ์œ„(`(%)`ยท`(์›)`)๋Š” **๋ผ๋ฒจ์— ๋ฐ•๋Š”๋‹ค** โ€” ์ž…๋ ฅ์นธ ์˜†์— ๋ถ™์ด๋ฉด ๊ฐ€๋กœ๋กœ ๋ฒŒ์–ด์ ธ ์Šคํฌ๋กค์ด ์ƒ๊ธฐ๊ณ  number input ์•ˆ์ชฝ absolute ์ ‘๋ฏธ์‚ฌ๋Š” ๋ฐ์Šคํฌํ†ฑ ์Šคํ”ผ๋„ˆ์™€ ๊ฒน์นœ๋‹ค. **๋ˆ„์  ๋น„์ค‘์œผ๋กœ ์ž…๋ ฅ๋ฐ›๋Š” ์ด์œ ** โ€” ๊ด€๋ฆฌ์ž๋‹˜์ด ๊ทธ๋ ‡๊ฒŒ ์ƒ๊ฐํ•œ๋‹ค("30% ๋น ์ง€๋ฉด ์ „๋Ÿ‰"). ์ฃผ๋ฌธ ์ˆ˜๋Ÿ‰์ธ ์ถ”๊ฐ€๋ถ„ ํ™˜์‚ฐ์€ `normalize_steps`๊ฐ€ ํ•œ๋‹ค. `handler.propose_trade(trail_steps, min_sell_price)`๊ฐ€ ์ดˆ๊ธฐ ๊ณ ์ ์„ `md['current_price']`๋กœ ์ •ํ•˜๊ณ  `compute_step_levels`+`allocate_step_qty`๋กœ ๊ณ„๋‹จ๋ณ„ ๊ฐ€๊ฒฉยท์ฃผ์ˆ˜๋ฅผ ๋งŒ๋“ ๋‹ค. **0์ฃผ๊ฐ€ ๋œ ๊ณ„๋‹จ์€ ๋–จ์–ด๋‚ด๋˜ ๋‹จ๊ณ„ ๋ฒˆํ˜ธ(n)๋Š” ์œ ์ง€**ํ•ด ์นด๋“œ์—์„œ ๋ช‡ ๋‹จ๊ณ„๊ฐ€ ๋น ์กŒ๋Š”์ง€ ๋ณด์ด๊ฒŒ ํ•œ๋‹ค. โš ๏ธ ํŠธ๋ ˆ์ผ๋ง์— `budget`(์˜ˆ์‚ฐ ํ™˜์‚ฐ) ๊ธˆ์ง€ โ€” ๊ณ„๋‹จ ์ฃผ์ˆ˜๋Š” ๋ณด์œ ์ˆ˜๋Ÿ‰์„ ๋‚˜๋ˆ  ๋งŒ๋“œ๋Š”๋ฐ ์˜ˆ์‚ฐ์ด ๋ผ๋ฉด ๊ธฐ์ค€์ด ๋‘˜์ด ๋œ๋‹ค(`TRAIL_BUDGET`์œผ๋กœ ๊ฑฐ๋ถ€). โš ๏ธ **๊ณ ์  ๊ธฐ์ค€ ์„ ํƒ ์˜ต์…˜์€ 2026-07-30 ์ œ๊ฑฐ๋จ**(`peak_basis` / `52์ฃผ ์ „๊ณ ์ ` / `๋งค์ˆ˜ํ›„ ๊ณ ์ `) โ€” ๊ณผ๊ฑฐ ๊ณ ์ ์„ ๊ธฐ์ค€์œผ๋กœ ์žก์œผ๋ฉด ์†์ ˆ์„ ์ด ํ˜„์žฌ๊ฐ€ ์œ„๋กœ ์˜ฌ๋ผ๊ฐ€ ๋“ฑ๋ก ์ฆ‰์‹œ ๋ฐœ๋™ํ•œ๋‹ค. **์†์‹ค ์ข…๋ชฉ์€ ๋“ฑ๋ก ์ž์ฒด๊ฐ€ ๋ถˆ๊ฐ€**(์‹ค์ธก ์ œ๋‹‰์Šค๋กœ๋ณดํ‹ฑ์Šค ํ˜„์žฌ๊ฐ€ 4,805 ยท ๋งค์ˆ˜ํ›„ ๊ณ ์  6,890 โ†’ ํ•„์š” ํญ 30.3% / 52์ฃผ 19,940 โ†’ 75.9%, ๋‘˜ ๋‹ค ์ƒํ•œ 30% ์ดˆ๊ณผ), **์ด์ต ์ข…๋ชฉ์€ ๊ณผ๊ฑฐ ๊ณ ์  โ‰ˆ ํ˜„์žฌ๊ฐ€๋ผ ๊ฒฐ๊ณผ๊ฐ€ ๊ฐ™๋‹ค**. ์ฆ‰ ์ฐจ์ด๊ฐ€ ๋‚  ๋•Œ๋Š” ๋ชป ์“ฐ๊ณ  ์“ธ ์ˆ˜ ์žˆ์„ ๋•Œ๋Š” ์ฐจ์ด๊ฐ€ ์—†์–ด ์˜ต์…˜์„ ์—†์•ด๋‹ค. **๋‹ค์‹œ ๋„ฃ์ง€ ๋ง ๊ฒƒ.** โš ๏ธ **1๋‹จ๊ณ„(๊ฐ€์žฅ ์–•์€ ๊ณ„๋‹จ) ์†์ ˆ์„  โ‰ฅ ํ˜„์žฌ๊ฐ€๋ฉด `TRAIL_IMMEDIATE`๋กœ ๊ฑฐ๋ถ€** โ€” ๊ณ ์ =ํ˜„์žฌ๊ฐ€ ๊ณ ์ •์ด๋ผ ์ด์ œ ์ตœ์ € ๋งค๋„๊ฐ€๊ฐ€ ํ˜„์žฌ๊ฐ€๋ณด๋‹ค ๋†’์€ ๊ฒฝ์šฐ๋งŒ ๋‚จ๋Š”๋‹ค. **๊ฑฐ๋ถ€ ์‹œ์ ์€ ์ž…๋ ฅ ์‹œ์ **(2026-07-30 ๊ด€๋ฆฌ์ž๋‹˜ ์ง€์‹œ๋กœ propose ์‹œ์ ์—์„œ ์ด๋™) โ€” `trailBlockReason()`์ด ์ž…๋ ฅ๊ฐ’์„ ๋ณด๊ณ  ์‚ฌ์œ  ๋ฌธ์ž์—ด์„ ๋‚ด๋†“๊ณ , ๊ฑธ๋ฆฌ๋ฉด ๋งค๋„ ๋ฒ„ํŠผ์ด disable + title ์— ์‚ฌ์œ . ๊ณ„๋‹จ ์ˆœ์„œยท๋ฒ”์œ„ ์œ„๋ฐ˜(`TRAIL_STEPS`)๊ณผ "์ด ์ˆ˜๋Ÿ‰์œผ๋ก  ๊ณ„๋‹จ์„ ๋ชป ๋‚˜๋ˆ”"(`TRAIL_QTY`)๋„ ๊ฐ™์€ ํ•จ์ˆ˜๊ฐ€ ๊ฐ™์€ ๋ฌธ๊ตฌ๋กœ ๋จผ์ € ๋ง‰๋Š”๋‹ค. ์„œ๋ฒ„๋Š” ์ตœํ›„ ๋ฐฉ์–ด์„ ์œผ๋กœ ์œ ์ง€. โš ๏ธ **๋ฒ„ํŠผ `disabled`๋Š” `refreshSubmitGate()` ํ•œ ๊ณณ์—์„œ๋งŒ ๊ฒฐ์ •ํ•œ๋‹ค** โ€” ์‹œ์žฅ phase ๊ฒŒ์ดํŠธ(`updateMarketPhaseDisplay`, `/api/market_state` ์ฃผ๊ธฐ ํด๋ง)์™€ ํŠธ๋ ˆ์ผ ๊ฒŒ์ดํŠธ๊ฐ€ ๊ฐ™์€ ๋ฒ„ํŠผ์„ ๊ฑด๋“œ๋ ค์„œ, ์˜ˆ์ „์ฒ˜๋Ÿผ ๊ฐ์ž ๋Œ€์ž…ํ•˜๋ฉด ์ฃผ๊ธฐ ํ˜ธ์ถœ์ด ํŠธ๋ ˆ์ผ ๊ฒŒ์ดํŠธ๋ฅผ ๋ฎ์–ด์จ ์ฆ‰์‹œ๋ฐœ๋™ ์ž…๋ ฅ์ด ํ†ต๊ณผ๋œ๋‹ค. phase ์ชฝ์€ `state.phaseCanTrade`/`phaseLabel`๋งŒ ์“ฐ๊ณ  ํŒ๋‹จ์„ ์œ„์ž„. propose ์ง„ํ–‰ ์ค‘์—๋Š” `btn.dataset.busy='1'`๋กœ ์ž ๊ฐ€ ์ฃผ๊ธฐ ํ˜ธ์ถœ์ด ๋ฒ„ํŠผ์„ ๋˜์‚ด๋ฆฌ์ง€ ๋ชปํ•˜๊ฒŒ ํ•˜๊ณ , ์‘๋‹ตยท์—๋Ÿฌ ํ›„ busy ํ•ด์ œ + ์žฌ๊ณ„์‚ฐ. `renderTrailPreview`๋Š” ์กฐ๊ธฐ ๋ฐ˜ํ™˜ ๊ฒฝ๋กœ(ํญ ๋ฏธ์ž…๋ ฅยท์‹œ์„ธ ๋กœ๋”ฉ)์—์„œ๋„ ๊ฒŒ์ดํŠธ๊ฐ€ ๊ฑธ๋ ค์•ผ ํ•˜๋ฏ€๋กœ **ํ•จ์ˆ˜ ๋งจ ์•ž์—์„œ** `refreshSubmitGate()`๋ฅผ ๋ถ€๋ฅธ๋‹ค. ํด๋ผ์ด์–ธํŠธ ๋ฏธ๋ฆฌ๋ณด๊ธฐ(`renderTrailPreview`/`trailCondPrice`/`allocStepQty`/`trailWeights`/`floorTick`)๋Š” ์„œ๋ฒ„์™€ **๊ฐ™์€ ์‹**์ด์ง€๋งŒ ์‹ค์ œ ๋ฐœ์ฃผ๊ฐ’์€ ์„œ๋ฒ„ ๊ณ„์‚ฐ๋ถ„์ด ์Šน์ž โ€” ํ•œ์ชฝ๋งŒ ๋ฐ”๊พธ๋ฉด ํ‘œ์‹œ์™€ ๋ฐœ์ฃผ๊ฐ€ ์–ด๊ธ‹๋‚˜๋‹ˆ `orders/trailing.py` ์ˆ˜์ • ์‹œ JS๋„ ํ•จ๊ป˜ ๊ณ ์น  ๊ฒƒ(**๋ Œ๋”๋œ ํŽ˜์ด์ง€์—์„œ ํ•จ์ˆ˜ ์†Œ์Šค๋ฅผ ๋ฝ‘์•„ node๋กœ ์‹คํ–‰ํ•ด Python๊ณผ ๋Œ€์กฐ**ํ•˜๋Š” ๋ฐฉ์‹, ํ˜„์žฌ 418์กฐํ•ฉ: ์†์ ˆ์„  360ยท์ˆ˜๋Ÿ‰๋ฐฐ๋ถ„ 54ยท๋น„์ค‘ํ™˜์‚ฐ 4). ํ‚ค์›€์—” ๊ณ„๋‹จ๋งˆ๋‹ค ์Šคํ†ฑ์ง€์ •๊ฐ€๋กœ ๋‚˜๊ฐ€๊ณ (`_submit_trailing_steps`๊ฐ€ ๋ ˆ๊ทธ๋ณ„ `STOP_LIMIT` ์ œ์ถœ) ํŠธ๋ ˆ์ผ๋ง์€ ์šฐ๋ฆฌ ์ชฝ ๊ฐœ๋…. **์นด๋“œ 1์žฅยทPIN 1๊ฐœ๋กœ ๊ณ„๋‹จ N๊ฑด์„ ์Šน์ธ**ํ•œ๋‹ค. **๋ ˆ๊ทธ ๋…๋ฆฝ ์ œ์ถœ** โ€” ์–•์€ ๊ณ„๋‹จ๋ถ€ํ„ฐ ์ ‘์ˆ˜ํ•ด ์ค‘๊ฐ„์— ๋ง‰ํ˜€๋„ ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ๋ฐฉ์–ด์„ ์ด ๋จผ์ € ๊ฑธ๋ฆฌ๊ณ , ํ•œ ๋ ˆ๊ทธ๊ฐ€ ์‹คํŒจํ•ด๋„ ๋‚˜๋จธ์ง€๋Š” ์‹œ๋„ํ•˜๋ฉฐ ์ ‘์ˆ˜๋œ ๊ฒƒ๋งŒ `trailing.register_steps`๋กœ ๋“ฑ๋กํ•œ๋‹ค(์ด๋ฏธ ๋‚˜๊ฐ„ ์ฃผ๋ฌธ์„ ๋˜๋Œ๋ฆฌ์ง€ ์•Š๋Š” ์ด์œ ๋Š” ์ทจ์†Œ๋„ ์‹คํŒจํ•  ์ˆ˜ ์žˆ์–ด ์ƒํƒœ๊ฐ€ ๋” ๋ถˆ๋ถ„๋ช…ํ•ด์ ธ์„œ โ€” ๋Œ€์‹  ๋ช‡ ๋‹จ์ด ๊ฑธ๋ฆฌ๊ณ  ๋ช‡ ๋‹จ์ด ์‹คํŒจํ–ˆ๋Š”์ง€ ๋ฉ”์‹œ์ง€์— ๊ทธ๋Œ€๋กœ ์ ๋Š”๋‹ค). **๋“ฑ๋ก ์‹คํŒจ ์‹œ ์ฃผ๋ฌธ์€ ์ด๋ฏธ ์ ‘์ˆ˜๋œ ์ƒํƒœ**๋ผ ๋ฉ”์‹œ์ง€์— โš ๏ธ ๊ฒฝ๊ณ ๋ฅผ ๋ถ™์ด๊ณ  ledger `trailing_register_failed` ๊ธฐ๋ก(์ˆจ๊ธฐ๋ฉด ํŠธ๋ ˆ์ผ๋ง์ด ์•ˆ ๋„๋Š” ๊ฑธ ๋ชจ๋ฅธ๋‹ค). ํŠธ๋ ˆ์ผ๋งยท์Šคํ†ฑ์ง€์ •๊ฐ€๋Š” ๋‹จ์ผ ๊ณ„์ขŒ ์˜ˆ์•ฝ์ด๋ผ **2๊ณ„์ขŒ ๋™์‹œ ๋งค๋„ ๋ถ„๊ธฐ์—์„œ ์ œ์™ธ**. ์ทจ์†Œ๋Š” `[๐Ÿ“‹ ์ง„ํ–‰์ค‘]`์—์„œ ํ•ด๋‹น ๋ฏธ์ฒด๊ฒฐ ์ฃผ๋ฌธ ์ทจ์†Œ โ†’ ๋‹ค์Œ ๊ฐ์‹œ ์‚ฌ์ดํด์ด ์‚ฌ๋ผ์ง„ ์˜ˆ์•ฝ์„ ์ž๋™ ์ •๋ฆฌ. โš ๏ธ **์Šคํ†ฑ ๊ณ„์—ด์€ SOR(`_AL`)๋กœ ๋ฐœ์ฃผํ•  ์ˆ˜ ์—†๋‹ค** โ€” ํ‚ค์›€์ด `407022: SOR์ฃผ๋ฌธ์ด ๋ถˆ๊ฐ€๋Šฅํ•œ ์ฃผ๋ฌธ์ข…๋ฅ˜์ž…๋‹ˆ๋‹ค`๋กœ ๊ฑฐ๋ถ€ํ•œ๋‹ค(2026-09-21 ์‚ผ์„ฑ์ „์ž ์‹ค์ธก). `guards.determine_routing`์ด `order_type`์„ ๋ฐ›์•„ ์Šคํ†ฑ ๊ณ„์—ด์ด๋ฉด `_AL`์„ **KRX(`''`)๋กœ ๊ฐ•๋“ฑ**ํ•œ๋‹ค. โš ๏ธ ์ด ๊ฒฐํ•จ์€ **NXT ๊ฑฐ๋ž˜ ์ข…๋ชฉ์—์„œ๋งŒ ๋“œ๋Ÿฌ๋‚œ๋‹ค** โ€” NXT ๋ฏธ๊ฑฐ๋ž˜ ์ข…๋ชฉ์€ ์ •๊ทœ์žฅ ๋ผ์šฐํŒ…์ด ์›๋ž˜ KRX๋ผ, 2026-07-30 ์ฒซ ์‹ค์ฃผ๋ฌธ(์ œ๋‹‰์Šค๋กœ๋ณดํ‹ฑ์Šค)์ด ์„ฑ๊ณตํ•œ ๋’ค๋กœ๋„ ๋Œ€ํ˜•์ฃผ ํŠธ๋ ˆ์ผ๋ง์€ **ํ•œ ๋ฒˆ๋„ ์ ‘์ˆ˜๋œ ์ ์ด ์—†์—ˆ๋‹ค**. โš ๏ธ **์˜ˆ์•ฝ ํŠธ๋ ˆ์ผ๋ง(ARM) ๋ฐœ๋™ ๊ฒฝ๋กœ๋„ ๊ฐ™์€ ํ•จ์ˆ˜๋ฅผ ์“ด๋‹ค**(`trailing_monitor._fire_arm`) โ€” ๋ฐœ๋™ ์‹œ์ ์— ๋ผ์šฐํŒ…์„ ๋‹ค์‹œ ๊ณ„์‚ฐํ•˜๋ฏ€๋กœ ์—ฌ๊ธฐ๋„ ๊ฐ™์ด ๋ง‰ํ˜€ ์žˆ์—ˆ๋‹ค. โš ๏ธ NXT ๋‹จ๋… ์‹œ๊ฐ„๋Œ€(`_NX`)๊ฐ€ ์Šคํ†ฑ์„ ๋ฐ›๋Š”์ง€๋Š” **์‹ค์ฆ ์•ˆ ๋จ** โ€” KRX๊ฐ€ ๋‹ซํžŒ ์‹œ๊ฐ„์ด๋ผ ๊ฐ•๋“ฑํ•  ๊ณณ์ด ์—†์–ด ์‹œ๋„๋Š” ๊ทธ๋Œ€๋กœ ๋‘๊ณ , ๊ฑฐ๋ถ€๋˜๋ฉด ๊ทธ ๋ฉ”์‹œ์ง€๋กœ ๋“œ๋Ÿฌ๋‚˜๊ฒŒ ํ•œ๋‹ค. **์˜ˆ์•ฝ ํŠธ๋ ˆ์ผ๋ง (TRAILING_ARM)**(2026-08-25) โ€” ๋ฐœ๋™๊ฐ€๋ฅผ ๋ฏธ๋ฆฌ ์ •ํ•ด๋‘๊ณ  **ํ˜„์žฌ๊ฐ€๊ฐ€ ๊ทธ ๊ฐ€๊ฒฉ์— ์˜ฌ๋ผ์™€ ๋‹ฟ๋Š” ์ˆœ๊ฐ„** ๊ทธ๋•Œ์˜ ํ˜„์žฌ๊ฐ€๋ฅผ ๊ณ ์ ์œผ๋กœ ํŠธ๋ ˆ์ผ๋ง์„ ๋“ฑ๋กํ•œ๋‹ค. ์•„์ง ์˜ค๋ฅด์ง€ ์•Š์€ ์ข…๋ชฉ์— ํŠธ๋ ˆ์ผ๋ง์„ ๊ฑธ๋ฉด ์†์ ˆ์„ ์ด ํ˜„์žฌ๊ฐ€ ๊ธฐ์ค€์œผ๋กœ ์žกํ˜€ ์ƒ์Šน ์—ฌ๋ ฅ์„ ๋ชป ๋‹ด๋Š”๋ฐ, ๊ทธ ํ‹ˆ์„ ๋ฉ”์šด๋‹ค. ์ž…๋ ฅ์€ ํŠธ๋ ˆ์ผ๋ง๊ณผ ๋™์ผ(๊ณ„๋‹จยท์ตœ์ € ๋งค๋„๊ฐ€)ํ•˜๊ณ  **๋ฐœ๋™๊ฐ€ ํ•˜๋‚˜๋งŒ ๋”** ๋ฐ›๋Š”๋‹ค(`data-order-arm-row`). โš ๏ธ **ํŒ์ •์€ ์ƒ์Šน ๋„๋‹ฌ๋งŒ**(`ํ˜„์žฌ๊ฐ€ >= ๋ฐœ๋™๊ฐ€`) โ€” ํ•˜๋ฝ ๋„๋‹ฌ์€ ์Šคํ†ฑ์ง€์ •๊ฐ€์™€ ๊ฒน์นœ๋‹ค. โš ๏ธ **๋Œ€๊ธฐ ์˜ˆ์•ฝ์€ ํ‚ค์›€์ด ์•„๋‹ˆ๋ผ `state/trailing_stops.json` ์˜ `arms` ํ‚ค์—๋งŒ ์žˆ๋‹ค** โ†’ ๊ฑฐ๋ž˜์†Œ๊ฐ€ ์ง€์›Œ์ฃผ์ง€ ์•Š์œผ๋ฏ€๋กœ **์šฐ๋ฆฌ๊ฐ€ ์Šคํ†ฑ์ฃผ๋ฌธ๊ณผ ๊ฐ™์€ ์ˆ˜๋ช…(๋“ฑ๋ก์ผ ๋‹น์ผ)์„ ๊ฐ•์ œ**ํ•œ๋‹ค(`trailing.is_arm_expired` + ๊ฐ์‹œ ๋ฃจํ”„์˜ `_expire_arms`, 2026-08-25 ๊ด€๋ฆฌ์ž๋‹˜ ์ง€์‹œ๋กœ ๋ฌด๊ธฐํ•œ โ†’ ๋‹น์ผ ๋ณ€๊ฒฝ). ๋ฐ˜๋Œ€๋กœ **๊ฐ์‹œ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์ฃฝ์œผ๋ฉด ๋ฐœ๋™ํ•˜์ง€ ์•Š๋Š”๋‹ค**(ํŠธ๋ ˆ์ผ๋ง ์Šคํ†ฑ๊ณผ ์ •๋ฐ˜๋Œ€ ์„ฑ์งˆ). โš ๏ธ **๋งŒ๋ฃŒ ๊ธฐ์ค€์€ `guards.after_trading_day`(NXT ์• ํ”„ํ„ฐ ๋งˆ๊ฐ 20:00)** โ€” `session_at(now)=='CLOSED'` ๋กœ ๋Œ€์‹ ํ•˜๋ฉด **09:00:00~09:00:30 ํ‹ˆ**๊ณผ ์ƒˆ๋ฒฝ์—๋„ CLOSED ๊ฐ€ ๋‚˜์™€ ์•„์นจ์— ๋ฉ€์ฉกํ•œ ์˜ˆ์•ฝ์ด ๋งŒ๋ฃŒ๋กœ ์žกํžŒ๋‹ค. โš ๏ธ **๊ฐ์‹œ๊ฐ€ 08:00~19:59 ์—๋งŒ ๋Œ์•„ 20:00 ์งํ›„์—” ํŒŒ์ผ์— ๋‚จ์•„ ์žˆ๋‹ค** โ†’ ์‹ค์ œ ์ •๋ฆฌ๋Š” ๋‹ค์Œ ๊ฑฐ๋ž˜์ผ ์ฒซ ์‚ฌ์ดํด์ด๊ณ , ๊ทธ ์‚ฌ์ด ์ž์‚ฐ์›น์€ `๋งŒ๋ฃŒ โ€” ์ •๋ฆฌ ๋Œ€๊ธฐ`๋กœ ํ‘œ์‹œํ•œ๋‹ค(์ˆจ๊ธฐ๋ฉด ํ™”๋ฉด์ด ๊ฑฐ์ง“๋ง์„ ํ•œ๋‹ค). โš ๏ธ **๋งŒ๋ฃŒ ์ •๋ฆฌ๋Š” ์‹œ์„ธ ์กฐํšŒ๋ณด๋‹ค ์•ž์— ๋‘”๋‹ค** โ€” ์‹œ์„ธ๊ฐ€ ์‹คํŒจํ•ด๋„ ์ •๋ฆฌ๋Š” ๋ผ์•ผ ํ•˜๊ณ , ์–ด์ œ ์˜ˆ์•ฝ์ด ์˜ค๋Š˜ ์‹œ์„ธ๋กœ ๋ฐœ๋™ํ•˜๋ฉด ์ ˆ๋Œ€ ์•ˆ ๋œ๋‹ค. ์•Œ๋ฆผ์€ ๊ฑด์ˆ˜ ์ƒ๊ด€์—†์ด **ํ•œ ํ†ต์œผ๋กœ ๋ฌถ๋Š”๋‹ค**. โš ๏ธ **PIN ์€ ๋“ฑ๋ก ์‹œ 1ํšŒ๋ฟ, ๋ฐœ๋™ ์‹œ์—” ์—†๋‹ค** โ€” ๊ด€๋ฆฌ์ž๋‹˜ ๋ช…์‹œ ์Šน์ธ(2026-08-25)์œผ๋กœ `trailing-monitor` ์— **์‹ ๊ทœ ๋ฐœ์ฃผ ๊ฒฝ๋กœ**๊ฐ€ ์ƒ๊ธด ๊ฒƒ์ด๊ณ , SOUL.md ์ž๋™ ํŠธ๋ฆฌ๊ฑฐ ๊ธˆ์ง€์˜ ๋‘ ๋ฒˆ์งธ ์˜ˆ์™ธ๋‹ค. ๊ทธ๋ž˜์„œ ์Šน์ธ ์นด๋“œยท์›น ๋ฏธ๋ฆฌ๋ณด๊ธฐยทํ™•์ธ ํŒ์—… **3๊ณณ์— "์ง€๊ธˆ์€ ์ฃผ๋ฌธ์ด ๋‚˜๊ฐ€์ง€ ์•Š์Šต๋‹ˆ๋‹ค / ๋ฐœ๋™ ์‹œ PIN ์žฌํ™•์ธ ์—†์Œ"์„ ๋ช…์‹œ**ํ•ด ๋’€๋‹ค(๋นผ์ง€ ๋ง ๊ฒƒ). โš ๏ธ **arms ์™€ reservations ๋ฅผ ํ•œ ํŒŒ์ผ์— ๋‘” ์ด์œ ๋Š” ๋ฐœ๋™์ด "arm ์ œ๊ฑฐ + ์˜ˆ์•ฝ ๋“ฑ๋ก"์ด๋ผ๋Š” ํ•˜๋‚˜์˜ ์›์ž์  ์ „์ด์—ฌ์•ผ ํ•ด์„œ๋‹ค** โ€” `promote_arm` ์ด ๋ฝ ํ•˜๋‚˜ ์•ˆ์—์„œ `os.replace` 1ํšŒ๋กœ ๋๋‚ธ๋‹ค. ํŒŒ์ผ์„ ์ชผ๊ฐœ๋ฉด ์ค‘๊ฐ„์— ์ฃฝ์—ˆ์„ ๋•Œ ๋‘˜ ๋‹ค ์กด์žฌํ•˜๊ฑฐ๋‚˜ ๋‘˜ ๋‹ค ์‚ฌ๋ผ์ง„๋‹ค. ๊ทธ๋ž˜์„œ `trailing._write(reservations=None, arms=None)` ๋Š” **None ์ธ ์ชฝ์„ ๋””์Šคํฌ์—์„œ ๋‹ค์‹œ ์ฝ์–ด ๋ณด์กด**ํ•œ๋‹ค(๊ธฐ์กด 6๊ฐœ ํ˜ธ์ถœ๋ถ€๊ฐ€ `_write(reservations)` ๊ทธ๋Œ€๋กœ์—ฌ๋„ arms ๊ฐ€ ์•ˆ ์ง€์›Œ์ง€๋Š” ์ด์œ ). โš ๏ธ **๊ณ„๋‹จ์€ ๊ฐ€๊ฒฉยท์ฃผ์ˆ˜ ์—†์ด ์ •์˜(n/pct/cum/weight)๋งŒ ์ €์žฅ**ํ•˜๊ณ  ๋ผ์šฐํŒ…๋„ ์ €์žฅํ•˜์ง€ ์•Š๋Š”๋‹ค โ€” ๊ฐญ ์ƒ์Šน์œผ๋กœ ๋ฐœ๋™๊ฐ€๋ฅผ ํ›Œ์ฉ ๋„˜๊ฒจ ์—ด๋ฆด ์ˆ˜ ์žˆ๊ณ , ๊ฐ™์€ ๋‚  ์•ˆ์—์„œ๋„ ๋“ฑ๋ก ์‹œ์  ์„ธ์…˜(์ •๊ทœ์žฅ)๊ณผ ๋ฐœ๋™ ์‹œ์  ์„ธ์…˜(NXT ์• ํ”„ํ„ฐ)์ด ๋‹ฌ๋ผ ์˜› suffix ๋กœ ๋ฐœ์ฃผํ•˜๋ฉด ๊ฑฐ๋ถ€๋œ๋‹ค. ๋ฐœ๋™ ์‹œ์ ์— `plan_arm_fire` + `guards.determine_routing` ์œผ๋กœ ์ƒˆ๋กœ ๊ณ„์‚ฐํ•œ๋‹ค. โš ๏ธ **ํฌ๋ž˜์‹œ ์•ˆ์ „์€ 2๋‹จ๊ณ„ ๋งˆํ‚น** โ€” ๋ฐœ์ฃผ ์ „์— `mark_arm_firing` ์œผ๋กœ `firing_at` ์„ ๋””์Šคํฌ์— ๋‚จ๊ธฐ๊ณ , ๋ ˆ๊ทธ๋งˆ๋‹ค `record_arm_leg` ๋กœ ์ฃผ๋ฌธ๋ฒˆํ˜ธ๋ฅผ ์ ๋Š”๋‹ค. **`firing_at` ์ด ๋‚จ์€ ์˜ˆ์•ฝ์€ ์ž๋™ ์žฌ๋ฐœ๋™ํ•˜์ง€ ์•Š๋Š”๋‹ค**(์ฃผ๋ฌธ์ด ๋‚˜๊ฐ”๋Š”์ง€ ๋ชจ๋ฅด๋Š” ์ƒํƒœ์˜ ์žฌ์‹œ๋„๊ฐ€ ๊ณง ์ด์ค‘ ๋งค๋„) โ€” ์•Œ๋ฆผ๋งŒ ๋ณด๋‚ด๊ณ  ๊ด€๋ฆฌ์ž๋‹˜์ด ๋ฏธ์ฒด๊ฒฐ ํ™•์ธ ํ›„ ์ž์‚ฐ์›น์—์„œ ์ทจ์†Œ. โš ๏ธ **๋Œ€๊ธฐ ์ˆ˜๋Ÿ‰์€ ์ผ๋ฐ˜ ๋งค๋„ ๊ฐ€๋Šฅ์ˆ˜๋Ÿ‰์—์„œ ์ฐจ๊ฐํ•˜์ง€ ์•Š๋Š”๋‹ค**(๋Œ€๊ธฐ๊ฐ€ ๋ณด์œ ๋ถ„์„ ๋ฌถ์œผ๋ฉด ์†์ด ๋ฌถ์ด๋ฏ€๋กœ) โ†’ ๊ทธ ์‚ฌ์ด ์ง์ ‘ ํŒ”์•˜์œผ๋ฉด ๋ฐœ๋™ ์‹œ `min(์˜ˆ์•ฝ, ๋งค๋„๊ฐ€๋Šฅ)`์œผ๋กœ **์ถ•์†Œ ์žฌ๋ฐฐ๋ถ„**ํ•˜๊ณ  ์•Œ๋ฆผ์— ๋ช…์‹œ, 0์ฃผ๋ฉด ์˜ˆ์•ฝ ์‚ญ์ œ+์•Œ๋ฆผ. โš ๏ธ **์‚ฌ์ด๋“œ์นด(`/orders_off`)๋Š” ๋งˆํ‚น *์ „์—* ํ™•์ธ**ํ•œ๋‹ค โ€” ๋งˆํ‚น ํ›„ ์ „ ๋ ˆ๊ทธ๊ฐ€ `SidecarBlocked` ๋กœ ์ฃฝ์œผ๋ฉด ์˜ˆ์•ฝ์ด ๋ฐœ๋™ ์ฒ˜๋ฆฌ ์ค‘๋‹จ ์ƒํƒœ๋กœ ๊ฐ‡ํžŒ๋‹ค. ์กฐํšŒ๋Š” `arms` ์‹ฌ๋ณผ์„ ๊ธฐ์กด ka10095 ๋ฐฐ์น˜์— ํ•ฉ์ณ **API ์ฝœ ์ถ”๊ฐ€ 0**, ๋ฏธ๋„๋‹ฌ ํ‰์‹œ์—” ํ‚ค์›€ ์ฝœ 0(๋ฐœ๋™ํ•œ ๊ณ„์ขŒ๋งŒ kt00018 1์ฝœ). arm ํ‰๊ฐ€๋Š” ์†์ ˆ์„  ์ƒํ–ฅ์ด **๋๋‚œ ๋’ค** ๋ณ„๋„ `try/except` ๋กœ ๋„๋Š”๋ฐ, ์ˆœ์„œ๊ฐ€ ์„ค๊ณ„๋‹ค โ€” ์‹ค์ฃผ๋ฌธ์„ ์ง€ํ‚ค๋Š” ์ƒํ–ฅ์„ arm ์ชฝ ์˜ˆ์™ธ๊ฐ€ ์„ ์ ํ•˜๋ฉด ์•ˆ ๋œ๋‹ค. ๋Œ€๊ธฐ ์˜ˆ์•ฝ์€ ka10075 ์— ์•ˆ ์žกํ˜€ **๋ฏธ์ฒด๊ฒฐ ๊ธฐ๋ฐ˜ ํ‘œ์‹œ(`pending_*`)์—์„œ ํ†ต์งธ๋กœ ๋น ์ง„๋‹ค** โ€” 2026-09-10 ์ด์ „์—” ๊ทธ๋ž˜์„œ ์ข…๋ชฉ ํ–‰์ด ์™„์ „ํžˆ ์กฐ์šฉํ–ˆ๊ณ  `[๐Ÿ“‹ ์ง„ํ–‰์ค‘]` ํŒ์—…์ด ์œ ์ผํ•œ ์ฐฝ๊ตฌ์˜€๋‹ค. ์ง€๊ธˆ์€ `_arms_by_code()`(์ƒํƒœํŒŒ์ผ ์ฝ๊ธฐ, ํ‚ค์›€ ์ฝœ 0)๊ฐ€ payload ๋‹จ๊ณ„์—์„œ ์ฝ”๋“œ๋ณ„๋กœ ์ฃผ์ž…ํ•ด **๋ณด์œ ยท๊ด€์‹ฌยท๊ฐ์‹œ ํ–‰์— โณ ๋ฐฐ์ง€(`badge pending-arm`) + ์ž์„ธํžˆ๋ณด๊ธฐ '์˜ˆ์•ฝ ํŠธ๋ ˆ์ผ๋ง' ์ƒ์„ธ**(๋ฐœ๋™๊ฐ€ยท๋ฐœ๋™๊ฐ€๊นŒ์ง€ %ยท๊ณ„๋‹จยท์ตœ์ € ๋งค๋„๊ฐ€ยท๊ณ„์ขŒ/๋“ฑ๋ก์‹œ๊ฐ/์˜ˆ์•ฝID)๋ฅผ ๊ทธ๋ฆฐ๋‹ค. โš ๏ธ **owner ํ•„ํ„ฐ๋Š” `derive_owner(account)`** โ€” ๊ฐ™์€ ์ข…๋ชฉ์„ ๋ณธ์ธยท๊ฐ€ํฌ๊ฐ€ ํ•จ๊ป˜ ๋ณด์œ ํ•˜๋ฉด ํ•„ํ„ฐ ์—†์ด๋Š” ๋‚จ์˜ ํƒญ์— ์˜ˆ์•ฝ์ด ๋œฌ๋‹ค(์‹ค์ธก ์ œ๋‹‰์Šค๋กœ๋ณดํ‹ฑ์Šค๊ฐ€ ์–‘์ชฝ ๋ณด์œ ). โš ๏ธ ์ฃผ์ž… ๋Œ€์ƒ์€ **consolidatedยทphantomยท์›Œ์น˜๋ฆฌ์ŠคํŠธ ์นด๋“œ**๋ฟ์ด๋ผ ๊ณ„์ขŒ๋ณ„ pane(raw rows)์—” ์•ˆ ๋œฌ๋‹ค โ€” ๊ธฐ์กด `pending_*` ์ฃผ์ž… ๋ฒ”์œ„์™€ ๊ฐ™๋‹ค. ์ƒํƒœ ๋ผ๋ฒจ์€ `firing_at` > `expired` ์ˆœ์œผ๋กœ ๊ฐˆ๋ฆฐ๋‹ค(๋ฐœ๋™ ์ค‘๋‹จ์ด ๋งŒ๋ฃŒ๋ณด๋‹ค ์ค‘์š”). **์ทจ์†Œ๋Š” ์—ฌ์ „ํžˆ `[๐Ÿ“‹ ์ง„ํ–‰์ค‘]` ํŒ์—…์ด ์œ ์ผํ•œ ์ฐฝ๊ตฌ**(`_arm_rows()` ํ•ฉ์„ฑ ํ–‰, `kind='arm'`ยท`ord_no` ๋นˆ ๋ฌธ์ž์—ด๋กœ ๋ฏธ์ฒด๊ฒฐ ์ทจ์†Œ๊ฐ€ ์‚ผํ‚ค์ง€ ๋ชปํ•˜๊ฒŒ ๋ถ„๋ฆฌ, ์ทจ์†Œ๋Š” `POST /api/orders/arm_cancel` โ†’ `handler.cancel_trailing_arm`, ํ…”๋ ˆ๊ทธ๋žจ ์—†์Œ). โš ๏ธ **์ข…๋ชฉ ๋ณ€๊ฒฝ ์‹œ ๋ฐœ๋™๊ฐ€ยท์ตœ์ € ๋งค๋„๊ฐ€๋ฅผ ๋น„์šฐ๊ณ  ์ฃผ๋ฌธ์œ ํ˜•์„ LIMIT ์œผ๋กœ ๋˜๋Œ๋ฆฐ๋‹ค** โ€” ์ ˆ๋Œ€๊ฐ€๊ฒฉ์ด๋ผ ์ด์ „ ์ข…๋ชฉ ๊ฐ’์ด ๋‚จ์œผ๋ฉด ์—‰๋šฑํ•œ ๊ฐ€๊ฒฉ์œผ๋กœ ์˜ˆ์•ฝ์ด ๋‚˜๊ฐ„๋‹ค(๊ณ„๋‹จ์€ %๋ผ ์œ ์ง€). โš ๏ธ **๋ฐœ๋™๊ฐ€๋Š” ๊ฐ€๊ฒฉ์ œํ•œํญ ๊ฒ€์ฆ์„ ๋ฐ›์ง€ ์•Š๋Š”๋‹ค** โ€” ์‹ค์ œ ๋ฐœ์ฃผ๋Š” ๋ฐœ๋™ ์‹œ์  ํ˜„์žฌ๊ฐ€๋กœ ๊ณ„์‚ฐ๋˜๋ฏ€๋กœ ๊ทธ๋•Œ ๊ฒ€์ฆ๋œ๋‹ค. ๋‹น์ผ ์œ ํšจ๊ฐ€ ๋œ ๋’ค๋กœ ์ƒํ•œ๊ฐ€ ์ดˆ๊ณผ๋Š” '์˜ค๋Š˜ ๋„๋‹ฌ ๋ถˆ๊ฐ€ = ๊ทธ๋ƒฅ ๋งŒ๋ฃŒ'๋ฅผ ๋œปํ•˜์ง€๋งŒ **๋ง‰์ง€ ์•Š๊ณ  ๊ฒฝ๊ณ ๋งŒ** ํ•œ๋‹ค(2026-08-25 ๊ด€๋ฆฌ์ž๋‹˜ ๊ฒฐ์ •). ๊ฒฝ๊ณ  ์œ„์น˜ 3๊ณณ โ€” ์Šน์ธ ์นด๋“œ(`card.format_card`)ยท์›น ๋ฏธ๋ฆฌ๋ณด๊ธฐ(`renderTrailPreview`)ยทํ™•์ธ ํŒ์—…(`openOrderConfirm`). `guards` ์—์„œ ๊ฑฐ๋ถ€๋กœ ๋ฐ”๊พธ์ง€ ๋ง ๊ฒƒ. โš ๏ธ ํŠธ๋ ˆ์ผ๋ง ์˜ˆ์•ฝ์ด ๋ฏธ์ฒด๊ฒฐ ๋งค๋„๋กœ ์žกํ˜€ ์žˆ์œผ๋ฉด `/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์œผ๋กœ ์ดˆ๋กยท์ˆ˜์‹ ๋ฒ„๋ธ”์ด ์ƒ๊ธฐ๊ณ  ์ž๋™์ž…๋ ฅ์ด ๊นจ์งˆ ์ˆ˜ ์žˆ์Œ. **ํƒ€์ธ ๋Œ€์ƒ๋„ `--service imessage`** โ€” ๊ฐ€ํฌ ๋ฆฌ๋งˆ์ธ๋”(`gahee_reminder._send_imessage`)๊ฐ€ `sms` ๊ฐ•์ œ์˜€๋‹ค๊ฐ€ 2026-08-03 ์ „ํ™˜. SMS ๊ฐ•์ œ๋Š” ๊ทธ ์ˆ˜์‹ ์ž์—๊ฒŒ 3์ „ 3ํŒจ์˜€๊ณ (์ „๋ถ€ `error=4` ๋ฏธ๋ฐœ์†ก, ์‚ด์•„๋‚จ์€ ๊ฑด์€ Messages๊ฐ€ ์ž„์˜๋กœ RCS๋กœ ๋ฐ”๊ฟ”์ค€ ์šด), 7/25 ๋ฏธ๋ฐœ์†ก์ด ์„ฑ๊ณต์œผ๋กœ ๊ธฐ๋ก๋ผ 7์›” ์ž”์•ก์ด ํ†ต์งธ๋กœ ๋ˆ„๋ฝ๋๋‹ค. โš ๏ธ **`imsg send`์˜ rc=0์€ ๋ฐœ์†ก ์„ฑ๊ณต์ด ์•„๋‹ˆ๋‹ค** โ€” Messages์— ๋„˜๊ฒผ๋‹ค๋Š” ๋œป์ผ ๋ฟ์ด๊ณ  ์‹ค์ œ ์‹คํŒจ๋Š” ๋น„๋™๊ธฐ๋กœ `chat.db`์˜ `error`์— ์ฐํžŒ๋‹ค. rc๋งŒ ๋ณด๋Š” ์ฝ”๋“œ๋Š” ๋ฏธ๋ฐœ์†ก์„ ์„ฑ๊ณต์œผ๋กœ ์˜ค์ธํ•œ๋‹ค. โš ๏ธ **์ž๋™ํ™” โ†’ ๋ฉ”์‹œ์ง€(AppleEvents) ๊ถŒํ•œ์ด `imsg`ยทiTerm2์—๋งŒ ํ—ˆ์šฉ, Claude Code์—๋Š” ๊ฑฐ๋ถ€**๋ผ ์ฝ”๋”” ์…ธ์—์„œ `imsg send`๋ฅผ ๋ถ€๋ฅด๋ฉด 20์ดˆ ํƒ€์ž„์•„์›ƒ. ๋ฐœ์†ก์€ launchd ๊ฒฝ์œ (์ž„์‹œ oneshot plist)๋กœ๋งŒ ๊ฐ€๋Šฅ. **์‹ ๊ทœ 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 + ํ…”๋ ˆ๊ทธ๋žจ), `POST /api/orders/modify?ord_no&account&price` (handler.modify_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`, ํƒœ๊ทธ ๋ชจ๋‹ฌ ํŒจํ„ด ๋ณต์ œ. **๊ณต๋ชจ์ฃผ sub-tab**(2026-10-02) โ€” ์ž์‚ฐ์ •๋ณด ํƒญ ํ•˜๋‹จ `[๊ณต๋ชจ์ฃผ]`(4๋ฒˆ์งธ). **ํƒ€์ดํ‹€ ๋ฐฐ์ง€**: ํ—ค๋” `์ž์‚ฐํ˜„ํ™ฉ` ์˜† `#ipo-flag` ํ…์ŠคํŠธ ๋ฐฐ์ง€ `[์ฒญ์•ฝ]` **ํ•˜๋‚˜๋กœ ํ†ต์ผ**(๊ด€๋ฆฌ์ž๋‹˜ ์ง€์ • โ€” ์‚ฌ์œ ๋ณ„๋กœ ๋‚˜๋ˆ„์ง€ ์•Š๋Š”๋‹ค, ์‚ฌ์œ ๋Š” ํˆดํŒ) โ€” โ‘ ์ฒญ์•ฝ๊ธฐ๊ฐ„ ์ค‘์ธ๋ฐ ์ฒญ์•ฝ์™„๋ฃŒ ์•ˆ ํ•œ ์ข…๋ชฉ โ‘ก์ฒญ์•ฝ์™„๋ฃŒํ•œ ์ข…๋ชฉ์˜ ์˜ค๋Š˜ ์ƒ์žฅ, ๋‘˜ ์ค‘ ํ•˜๋‚˜๋ผ๋„ ์žˆ์œผ๋ฉด ํ‘œ์‹œ(๊ด€๋ฆฌ์ž๋‹˜ ์ง€์ •, ํด๋ฆญ ๋™์ž‘ ์—†์Œ, ์‚ฌ์œ ๋Š” title ํˆดํŒ). `_ipo_flag()` ๊ฐ€ `/api/panels` ์‘๋‹ต `ipo_flag` ๋กœ ์‹ค์–ด `apply()` ๊ฐ€ ํ† ๊ธ€ โ€” ์…ธ์€ ๋ฐ์ดํ„ฐ fetch ์—†๋Š” ์›์น™์ด๋ผ ์ฒซ ํŒจ๋„ ๋กœ๋“œ ๋’ค์— ๋œฌ๋‹ค. ์ข…๋ชฉ ์นด๋“œ๋Š” `
` **๊ธฐ๋ณธ ์ ‘ํž˜**(์š”์•ฝ์ค„ = ์ข…๋ชฉ๋ช…ยท์‹œ์žฅยท์ฒญ์•ฝ๊ธฐ๊ฐ„ยท์ฆ๊ถŒ์‚ฌ ์ˆ˜ยท๋งˆ๊ฐ์ผ/์™„๋ฃŒ ๋ฐฐ์ง€), ํŽผ์นจ ์ƒํƒœ๋Š” `apply()` ์˜ ํŒจ๋„ swap ๋•Œ `data-ipo-key` ๋กœ ๋ณต์›(`details.row` ๋ณต์›๊ณผ ๋ณ„๋„ โ€” ๊ณต๋ชจ์ฃผ ์นด๋“œ๋Š” ์ข…๋ชฉ ํ–‰์ด ์•„๋‹ˆ๋ผ `row` ํด๋ž˜์Šค๋ฅผ ์“ฐ๋ฉด ์ข…๋ชฉ์ฝ”๋“œ ๊ธฐ๋ฐ˜ ์…€๋ ‰ํ„ฐ๋“ค๊ณผ ์—ฎ์ธ๋‹ค). โ‘ **์˜ค๋Š˜์ฒญ์•ฝ** = ์ฒญ์•ฝ๊ธฐ๊ฐ„(`poStartDate โ‰ค ์˜ค๋Š˜ โ‰ค poEndDate`) ์ค‘์ธ ์ข…๋ชฉ ์ „๋ถ€๋ฅผ **์ฆ๊ถŒ์‚ฌ๋ณ„ ์•„์ดํ…œ**(์ฒญ์•ฝ์ผยท์ฆ๊ฑฐ๊ธˆ(์ตœ์†Œ ์ˆ˜๋Ÿ‰)ยท์ˆ˜์ˆ˜๋ฃŒยท์ƒ์žฅ์ผ, ๋งˆ์ง€๋ง‰ ๋‚  `๋งˆ๊ฐ์ผ` ๋ฐฐ์ง€)์œผ๋กœ โ‘ก**์ฒญ์•ฝ์™„๋ฃŒ** = ๊ธฐ๋ก๋œ ์ข…๋ชฉ์„ **์ƒ์žฅ์ผ๊นŒ์ง€**(๋ฏธ์ •์ด๋ฉด ๊ณ„์†) ํ‘œ์‹œ. `[์ฒญ์•ฝ์™„๋ฃŒ]` โ†’ ์ž‘์€ ํ™•์ธ ํŒ์—…(`.note-confirm` ์žฌ์‚ฌ์šฉ) โ†’ ์˜ˆ โ†’ `POST /ipo/subscribe`(fetch, JSON) โ†’ `state/behive_ipo_subscribed.json`(`{ipoCode:{name,po_start,po_end,lcal_date,by:{self|gahee:{broker,at}},interest_added?}}`, fcntl lock+atomic). **์‚ฌ๋žŒ๋ณ„ ๋ฒ„ํŠผ 2๊ฐœ**(2026-10-02 ๊ด€๋ฆฌ์ž๋‹˜ ์ง€์‹œ๋กœ ์ข…๋ชฉ ๋‹จ์œ„ 1๊ฑด โ†’ ์‚ฌ๋žŒ๋ณ„๋กœ ๋ณ€๊ฒฝ): ์•„์ดํ…œ๋งˆ๋‹ค `[๊ด€๋ฆฌ์ž(์ฒญ์•ฝ)] [๊ฐ€ํฌ(์ฒญ์•ฝ)]`, ์ค‘๋ณต์ฒญ์•ฝ ๊ธˆ์ง€๊ฐ€ 1์ธ ๊ธฐ์ค€์ด๋ผ **์‚ฌ๋žŒ๋ณ„ ์ข…๋ชฉ๋‹น 1๊ฑด** โ€” ๋ˆ„๋ฅด๋ฉด ๊ทธ ์‚ฌ๋žŒ์˜ ๋ฒ„ํŠผ๋งŒ ๊ทธ ์ข…๋ชฉ ๋ชจ๋“  ์ฆ๊ถŒ์‚ฌ์—์„œ `โœ… ๊ด€๋ฆฌ์ž(์™„๋ฃŒ)` ๋กœ ๋ฐ”๋€๋‹ค(์ฒญ์•ฝํ•œ ์ฆ๊ถŒ์‚ฌ ์นด๋“œ๋งŒ ์ดˆ๋ก ๊ฐ•์กฐ, ์ฆ๊ถŒ์‚ฌ๋ช…์€ ์ฒญ์•ฝ์™„๋ฃŒ ์„น์…˜์— โ€” ๊ด€๋ฆฌ์ž๋‹˜ ์ง€์ • ๋ฌธ๊ตฌ). ์ด๋ฏธ ๊ธฐ๋ก๋œ ์‚ฌ๋žŒ์€ ๋ฎ์–ด์“ฐ์ง€ ์•Š๋Š”๋‹ค. ์˜› ํ˜•์‹(์ข…๋ชฉ ๋‹จ์œ„ `broker/at`)์€ `_load_ipo_subscribed` ๊ฐ€ ๊ด€๋ฆฌ์ž ๊ธฐ๋ก์œผ๋กœ ์ฝ๋Š”๋‹ค(๋ฉœ์ฝ˜ 1๊ฑด ๊ทธ๋ ‡๊ฒŒ ์ด๊ด€). ํƒ€์ดํ‹€ [์ฒญ์•ฝ] ๋ฐฐ์ง€์˜ ๋ฏธ์™„๋ฃŒ ํŒ์ •์€ **ํ•œ ๋ช…์ด๋ผ๋„ ํ–ˆ์œผ๋ฉด ์™„๋ฃŒ**(๊ด€๋ฆฌ์ž๋‹˜ ์ง€์ •). **๋˜๋Œ๋ฆฌ๊ธฐ ๋ฒ„ํŠผ ์—†์Œ**(์ž˜๋ชป ๋ˆŒ๋ €์œผ๋ฉด state ํŒŒ์ผ์—์„œ ์ œ๊ฑฐ). ๋ฐ์ดํ„ฐ์›์€ `ipo_alert.py` ์™€ ๊ฐ™์€ ๋„ค์ด๋ฒ„ IPO API โ€” ๋ชฉ๋ก(`ipo_calendar_sync._naver_api_rows`)ยท์ƒ์„ธ(`ipo_alert._detail`) ๊ฐ 30๋ถ„ ์บ์‹œ, **์ฆ๊ฑฐ๊ธˆยท์ˆ˜์ˆ˜๋ฃŒ๋Š” `ipo_alert._manager_blocks` ๋ฅผ ๊ทธ๋Œ€๋กœ import**ํ•ด ํ…”๋ ˆ๊ทธ๋žจ ์•Œ๋ฆผ๊ณผ ์ˆซ์ž๊ฐ€ ํ•ญ์ƒ ๊ฐ™๋‹ค(์ˆ˜์ˆ˜๋ฃŒ ํ‘œ `BROKER_ONLINE_FEES` ๋„ ๊ฑฐ๊ธฐ ํ•œ ๊ณณ). ์ƒ์„ธ ์กฐํšŒ๋Š” ์ฒญ์•ฝ๊ธฐ๊ฐ„ ์ค‘ยท์™„๋ฃŒ ์ข…๋ชฉ๋งŒ, **ํ‚ค์›€ ์ฝœ 0**. โš ๏ธ ์˜ˆ์ „ ๊ณต๋ชจ์ฃผ ์กฐํšŒ ์‹คํŒจ๋Š” `finance.naver.com/sise/ipo.naver` HTML ์Šคํฌ๋ž˜ํ•‘ ์‹œ์ ˆ ์–˜๊ธฐ๊ณ  2026-09-30 ๊ฒฝ JSON API ๋กœ ๊ต์ฒด๋œ ๋’ค์—” ์ •์ƒ(์‹ค์ธก). ๋ Œ๋” ์˜ˆ์™ธ๋Š” `_render_summary_panel` ์ด ์žก์•„ ๊ณต๋ชจ์ฃผ ํŒจ๋„๋งŒ ์—๋Ÿฌ ๋ฌธ๊ตฌ. **์ƒ์žฅ์ผ ๊ด€์‹ฌ์ข…๋ชฉ ์ž๋™๋“ฑ๋ก**: ์ฒญ์•ฝ์™„๋ฃŒํ•œ ์ข…๋ชฉ์€ ์ƒ์žฅ์ผ ์•„์นจ `ipo_alert.py listing`(launchd `stock.ipo-alert` 08:30, ๊ธฐ์กด ํŠธ๋ฆฌ๊ฑฐ ์žฌ์‚ฌ์šฉ โ€” ์ƒˆ ํŠธ๋ฆฌ๊ฑฐ ์—†์Œ)์ด `behive_web.register_listed_ipo_interests()` ๋ฅผ ๋ถˆ๋Ÿฌ ๊ด€์‹ฌ์ข…๋ชฉ์— ๋„ฃ๋Š”๋‹ค(์ฝ”๋“œ = ipoCode ์•ž `A` ์ œ๊ฑฐ, ๋ฉ”๋ชจ `๊ณต๋ชจ์ฃผ ์ฒญ์•ฝ (๊ด€๋ฆฌ์ž ๋Œ€์‹ ์ฆ๊ถŒ, ๊ฐ€ํฌ ํ•˜๋‚˜์ฆ๊ถŒ)`). ์ข…๋ชฉ๋‹น 1ํšŒ โ€” ๊ธฐ๋ก์— `interest_added` ๋ฅผ ๋‚จ๊ธฐ๊ณ , ์ด๋ฏธ ๊ด€์‹ฌ์ข…๋ชฉ์ด๋ฉด ์„ฑ๊ณต์œผ๋กœ ์นœ๋‹ค. ์ƒ์žฅ์ผ ํŒ์ •์€ API ์ƒ์žฅ ๋ชฉ๋ก โˆช ๊ธฐ๋ก์˜ `lcal_date` ๋ผ **๋„ค์ด๋ฒ„ ์กฐํšŒ๊ฐ€ ์‹คํŒจํ•ด๋„ ๊ธฐ๋ก์œผ๋กœ ์‹œ๋„**ํ•œ๋‹ค(๊ทธ๋ž˜์„œ `ipo_alert` ๊ฐ€ ์†Œ์Šค ์‹คํŒจ ์‹œ ๋ฐ”๋กœ return ํ•˜์ง€ ์•Š๋Š”๋‹ค). `--dry-run` ์ด๋ฉด ๊ฑด๋„ˆ๋œ€. ํ•˜๋‹จ ํƒญ ๋ฒ„ํŠผ์ด 4๊ฐœ๊ฐ€ ๋˜๋ฉด์„œ `.sub-tabs-bottom .sub-tab` ์„ `flex:1 1 0; max-width:110px; nowrap` ์œผ๋กœ ๋ฐ”๊ฟจ๋‹ค(360px ์—์„œ '์ž์‚ฐ๋ณด ๊ธฐ'๋กœ ๊บพ์ด๋˜ ๊ฒƒ โ€” 320px ๋„˜์นจ 0 ์‹ค์ธก). **๋น„ํ•˜์ด๋ธŒ ๊ณต๋ชจ์ฒญ์•ฝ ์˜์ƒ ์š”์•ฝ**(2026-10-07): ์นด๋“œ ํŽผ์นจ ์ƒ๋‹จ(์ฒญ์•ฝ์™„๋ฃŒ ์นด๋“œ๋Š” kv ์•„๋ž˜)์— `๐Ÿ ๋น„ํ•˜์ด๋ธŒ ์˜๊ฒฌ` ๋ธ”๋ก โ€” ๊ฒฐ๋ก  ํ•œ ๊ตฌ์ ˆ(๊ธ์ • ์ดˆ๋กยท์ค‘๋ฆฝ ํšŒ์ƒ‰ยท๋ถ€์ • ๋นจ๊ฐ• ์™ผ์ชฝ ๋ ) + ํ•ต์‹ฌ 3~4์ค„ + ์˜์ƒ ๋งํฌ. ์ƒ์‚ฐ์€ `ipo_youtube_digest.py` โ€” ์ฑ„๋„ ์˜์ƒ ๋ชฉ๋ก์—์„œ ์ œ๋ชฉ `๊ณต๋ชจ์ฒญ์•ฝ` ํ•„ํ„ฐ โ†’ ์ฒ˜๋ฆฌ ์•ˆ ํ•œ ์˜์ƒ๋งŒ ์ž๋ง‰ โ†’ LLM(`openai/gpt-5.6-sol`) โ†’ `state/ipo_youtube_summaries.json`(์˜์ƒ ๋‹จ์œ„, `done`ยท`attempts`). โš ๏ธ **์˜์ƒโ†”์ข…๋ชฉ ๋งค์นญ์€ ์ œ๋ชฉ ํ•ด์‹œํƒœ๊ทธ๋กœ ํ•˜์ง€ ์•Š๋Š”๋‹ค** โ€” ์›”๊ฐ„ ์ผ์ • ์˜์ƒ์ฒ˜๋Ÿผ ํ•œ ์˜์ƒ์ด ์—ฌ๋Ÿฌ ์ข…๋ชฉ์„ ๋‹ค๋ฃจ๋ฏ€๋กœ, ๋„ค์ด๋ฒ„ IPO ํ›„๋ณด ๋ชฉ๋ก(์ƒ์žฅ 2์ฃผ ์ด๋‚ด๊นŒ์ง€)์„ LLM ์— ์ฃผ๊ณ  **ipoCode ๋กœ ๋Œ๋ ค๋ฐ›์•„** ๋ชฉ๋ก ๋ฐ– ์ฝ”๋“œ๋Š” ๋ฒ„๋ฆฐ๋‹ค. ํ•œ ์ข…๋ชฉ์— ์˜์ƒ์ด ์—ฌ๋Ÿฟ์ด๋ฉด **์ œ๋ชฉ `#์ข…๋ชฉ๋ช…` ์ „์šฉ ์˜์ƒ ์šฐ์„  โ†’ ์ตœ์‹ ์ˆœ** 1๊ฑด๋งŒ ๋ณธ๋ฌธ, ๋‚˜๋จธ์ง€๋Š” ๋งํฌ. ํŠธ๋ฆฌ๊ฑฐ๋Š” **๊ธฐ์กด `stock.ipo-alert`(08:30ยท10:00)์— ์–น์—ˆ๋‹ค** โ€” `ipo_alert.main` ๋์—์„œ `run()`(dry-run ์ œ์™ธ, ์‹คํŒจ๋Š” stderr ๋งŒ). ์ƒˆ ์˜์ƒ ์—†์œผ๋ฉด ์ฑ„๋„ ํŽ˜์ด์ง€ 1์ฝœ๋กœ ๋๋‚˜๊ณ , ๋ Œ๋” ๊ฒฝ๋กœ๋Š” ํŒŒ์ผ ์ฝ๊ธฐ๋งŒ(LLMยท๋„คํŠธ์›Œํฌ 0). ์ž๋ง‰ ๋ฏธ์ƒ์„ฑยทLLM ์‹คํŒจ๋Š” `attempts` ์ฆ๊ฐ€ ํ›„ ๋‹ค์Œ ์‹คํ–‰์—์„œ ์žฌ์‹œ๋„, 6ํšŒ(โ‰ˆ3์ผ)๋ฉด ํฌ๊ธฐ. โš ๏ธ **LLM ์€ `~/.local/bin/openclaw` ์ ˆ๋Œ€๊ฒฝ๋กœ๋กœ ๋ถ€๋ฅธ๋‹ค** โ€” launchd PATH ์—์„  `openclaw` ๊ฐ€ `/opt/homebrew/bin`(node22)๋กœ ์žกํ˜€ ์•ˆ ๋œฌ๋‹ค. ํ•œ๊ณ„: ํ•˜๋ฃจ 2ํšŒ๋ผ 10:00 ์ดํ›„ ์˜ฌ๋ผ์˜จ ์˜์ƒ์€ ๋‹ค์Œ ๋‚  08:30 ์— ๋ถ™๋Š”๋‹ค. CLI: `python3 ipo_youtube_digest.py [run|show] [--dry-run]`. โš ๏ธ **์ž๋ง‰ ์ˆซ์ž๋Š” ๋ฐ›์•„์“ฐ๊ธฐ ์˜ค๋ฅ˜๊ฐ€ ์žฆ๋‹ค**(์‹ค์ธก ์—˜๋ฆฌ์Šค๊ทธ๋ฃน ํฌ๋ง๊ณต๋ชจ๊ฐ€ 74,000์›๋Œ€๊ฐ€ '7,400~9,500์›'์œผ๋กœ ์š”์•ฝ๋จ) โ†’ ํ›„๋ณด ๋ชฉ๋ก์— ๋„ค์ด๋ฒ„์˜ ํฌ๋งยทํ™•์ • ๊ณต๋ชจ๊ฐ€๋ฅผ ์‹ค์–ด LLM ์ด ๊ทธ ๊ฐ’์„ ์ •๋‹ต์œผ๋กœ ์“ฐ๊ฒŒ ํ•œ๋‹ค. โš ๏ธ `youtube_transcript_api` ๋Š” ์งง์€ ์‹œ๊ฐ„์— ๋ฐ˜๋ณต ํ˜ธ์ถœํ•˜๋ฉด **IP ๋‹จ์œ„ `IpBlocked`** ๊ฐ€ ๊ฑธ๋ฆฐ๋‹ค(2026-10-07 ํ…Œ์ŠคํŠธ ์ค‘ ๋ฐœ์ƒ, ๋ธŒ๋ฆฌํ•‘ ์ž๋ง‰๊ณผ ๊ฐ™์€ IP๋ผ ํ•จ๊ป˜ ๋ง‰ํžŒ๋‹ค) โ€” ์ˆ˜๋™ ํ…Œ์ŠคํŠธ ๋•Œ ์ž๋ง‰ ์žฌ์กฐํšŒ๋ฅผ ์•„๋‚„ ๊ฒƒ. **๊ฐ€ํฌ ์ƒ์žฅ์ผ ๋ฌธ์ž**(2026-10-07 ๊ด€๋ฆฌ์ž๋‹˜ ์š”์ฒญ): `ipo_alert.py listing`(08:30)์ด ์ฒญ์•ฝ๊ธฐ๋ก `by.gahee` ๊ฐ€ ์žˆ๋Š” ์ข…๋ชฉ์˜ ์ƒ์žฅ์ผ์— ๊ฐ€ํฌ๋‹˜๊ป˜ iMessage(`imsg --service imessage`, ๊ฐ€ํฌ ๋ฆฌ๋งˆ์ธ๋”์™€ ๊ฐ™์€ ๋ฐฉ์‹) โ€” ํ˜•์‹ `[๊ณต๋ชจ์ฃผ ์ƒ์žฅ] ์˜ค๋Š˜ {์ข…๋ชฉ} ์ƒ์žฅ์ผ์ด์—์š” / ยท ์ฒญ์•ฝ ์ฆ๊ถŒ์‚ฌ / ยท ํ™•์ • ๊ณต๋ชจ๊ฐ€ / ยท 09:00 ๊ฑฐ๋ž˜ ์‹œ์ž‘ โ€” ๋ฐฐ์ • ์ฃผ์‹์€ {์ฆ๊ถŒ์‚ฌ} ์•ฑ์—์„œ ํ™•์ธํ•˜์„ธ์š”`(๊ด€๋ฆฌ์ž๋‹˜ ์„ ํƒ). ๊ฐ™์€ ๋‚  ์—ฌ๋Ÿฌ ์ข…๋ชฉ์ด๋ฉด ํ•œ ํ†ต, dedup ์€ `ipo_alerts.json` ์˜ `gahee_listing|๋‚ ์งœ|์ฝ”๋“œ๋“ค`(rc=0 ์ผ ๋•Œ๋งŒ ๊ธฐ๋ก). ์ƒ์žฅ์ผ ํŒ์ •์€ ๊ด€์‹ฌ์ข…๋ชฉ ์ž๋™๋“ฑ๋ก๊ณผ ๊ฐ™์€ ๊ทœ์น™(API โˆช ๊ธฐ๋ก lcal_date). **๊ธ‰๋“ฑ๋ฝ ์•Œ๋ฆผ โ€” ํ‘œ์‹œ์ž ๐Ÿ”” + `[๐Ÿ”” ์•Œ๋ฆผ]` ๋ฒ„ํŠผ + ํŒ์—…**(2026-08-04 ๋„์ž… โ†’ **2026-08-06 ๊ฐœํŽธ**) โ€” ์ฒ˜์Œ์—” `detail-name` ์ค„์˜ **์•„์ด์ฝ˜ ์ „์šฉ ํ† ๊ธ€**์ด์—ˆ์œผ๋‚˜, ๊ด€๋ฆฌ์ž๋‹˜ ์ง€์‹œ๋กœ **์•„์ด์ฝ˜์€ on/off ํ‘œ์‹œ๋งŒ ํ•˜๊ณ  ์กฐ์ž‘์€ ํŒ์—… ์•ˆ์œผ๋กœ** ์˜ฎ๊ฒผ๋‹ค(์•„์ด์ฝ˜ ํ•˜๋‚˜๋ฟ์ด๋ผ `title` ํˆดํŒ์ด ์œ ์ผํ•œ ์„ค๋ช…์ด์—ˆ๊ณ  โ€” ๋ชจ๋ฐ”์ผ์—” hover๊ฐ€ ์—†๋‹ค โ€” ์˜ค์กฐ์ž‘ ์œ„ํ—˜๋„ ์žˆ์—ˆ๋‹ค). ๊ตฌ์„ฑ 3๊ฐœ: - **ํ‘œ์‹œ์ž**(`_surge_indicator_html`) โ€” `detail-name` ์ค„ ์ข…๋ชฉ๋ช… ์˜†์˜ **๋น„๋Œ€ํ™”ํ˜• ``**. ๊บผ์ง ๐Ÿ”•(opacity 0.45 + grayscale)ยท์ผœ์ง ๐Ÿ””(์ดˆ๋ก ๋ฐฐ๊ฒฝ). โš ๏ธ **`data-surge-toggle` ์„ ๋‹ฌ์ง€ ๋ง ๊ฒƒ** โ€” ๊ทธ ์†์„ฑ์ด ์žˆ์–ด์•ผ ์œ„์ž„ ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ์žก์œผ๋ฏ€๋กœ, ์—†์–ด์•ผ ํด๋ฆญ์ด ๋ฌด๋ฐ˜์‘์ด๋‹ค. CSS `.detail-name .surge-ind` ์— `cursor/hover/active` ๋ฅผ ์ฃผ์ง€ ์•Š๋Š” ๊ฒƒ๋„ ๊ฐ™์€ ์ด์œ (๋ˆ„๋ฅผ ์ˆ˜ ์žˆ์–ด ๋ณด์ด๋ฉด ์•ˆ ๋œ๋‹ค). - **๋ฒ„ํŠผ**(`_surge_info_button_html`) โ€” `.actions` ์ค„ `๐Ÿ“ ๋ฉ”๋ชจ` ์˜† `๐Ÿ”” ์•Œ๋ฆผ`. `class="kpi-more-btn btn-surge-info"` ๋ผ **๊ธฐ์กด kpi-modal ์œ„์ž„ ํ•ธ๋“ค๋Ÿฌ(`t.closest('.kpi-more-btn')`, document ์ „์—ญ)๊ฐ€ ๊ทธ๋Œ€๋กœ ์žก๋Š”๋‹ค โ†’ JSยท๋ชจ๋‹ฌ ๋งˆํฌ์—… ์ถ”๊ฐ€ 0**. ์ผœ์ง์ด๋ฉด `has-surge` ๊ฐ•์กฐ(๋ฉ”๋ชจ์˜ `has-note` ํŒจํ„ด). **๊บผ์ง„ ์ข…๋ชฉ์—๋„ ๋…ธ์ถœ**ํ•œ๋‹ค โ€” ์ผœ๋Š” ์ž…๊ตฌ๊ฐ€ ์ด ํŒ์—…๋ฟ์ด๋ผ์„œ. โš ๏ธ **`&name=` ์„ src ์— ์‹ค์–ด์•ผ ํ•œ๋‹ค** โ€” ๊บผ์ง„ ์ข…๋ชฉ์€ ํ† ๊ธ€ ์ €์žฅ์†Œ์— ์ด๋ฆ„์ด ์—†์–ด์„œ ํŒ์—…์—์„œ ์ผœ๋ฉด ๋นˆ ์ด๋ฆ„์œผ๋กœ ์ €์žฅ๋˜๊ณ  ์•Œ๋ฆผ์— ์ข…๋ชฉ์ฝ”๋“œ๊ฐ€ ์ฐํžŒ๋‹ค(2026-08-06 ์‹ค์ธก). - **ํŒ์—…**(`_render_surge_body`, `GET /api/surge?code=&name=`) โ€” ํ† ๊ธ€ + ๊ตฌ๊ฐ„ ์‚ฌ๋‹ค๋ฆฌ(โซ์ƒํ•œ๊ฐ€ยท๊ธ‰๋“ฑํ™•๋Œ€ยท๊ธ‰๋“ฑ1์ฐจยท์ „์ผ์ข…๊ฐ€ยท๊ธ‰๋ฝ1์ฐจยท๊ธ‰๋ฝํ™•๋Œ€ยทโฌํ•˜ํ•œ๊ฐ€, ํ˜ธ๊ฐ€์ฐฝ์ฒ˜๋Ÿผ ์œ„๊ฐ€ ๋น„์Œˆ) + ์˜ค๋Š˜ ์†Œ์ง„ ํ˜„ํ™ฉ(๋‚˜๊ฐ„/๋‚จ์€/๋ณด๋ฅ˜ ์นฉ) + ๊ทผ๊ฑฐ(`N์ผ ์ด๋ ฅ ๊ธฐ์ค€ ยท ์ƒ์œ„ 10%/2%`). โš ๏ธ **`sm.get_threshold_map()`/`sm.get_limit_map()` ์„ ์ ˆ๋Œ€ ๋ถ€๋ฅด์ง€ ์•Š๋Š”๋‹ค** โ€” ๊ฐ๊ฐ ka10081(์œ ๋Ÿ‰ ์ดˆ๋‹น 5๊ฑด)ยทka10095 ๋ฅผ ๋•Œ๋ ค์„œ ํŒ์—… ์—ด ๋•Œ๋งˆ๋‹ค ์กฐํšŒ๊ฐ€ ๋‚˜๊ฐ€๊ณ , ๋ฌธํ„ฑ ์‚ฐ์ถœ์˜ ์‚ฌ์ดํด๋‹น 12์ข…๋ชฉ ํŽ˜์ด์‹ฑ์ด ๋ฌด๋„ˆ์ง„๋‹ค. `surge_thresholds.json`ยท`surge_limits.json`ยท`surge_alerts.json` **์บ์‹œ ์ฝ๊ธฐ + `_RT_HUB.get_quote` ๋ฟ์ด๋ผ ํ‚ค์›€ ์ฝœ 0**(์‹ค์ธก 2.9ms). ์บ์‹œ์— ์—†์œผ๋ฉด ์ƒํƒœ๋ณ„ ์•ˆ๋‚ด๋กœ ๋Œ€์ฒด โ€” ๊บผ์ง/๊ณ„์‚ฐ๋Œ€๊ธฐ/์ด๋ ฅ๋ถ€์กฑ(์ œํ•œ๊ฐ€๋งŒ ํ‘œ์‹œ)/stale. โš ๏ธ **stale(์–ด์ œ ์บ์‹œ)์ด๋ฉด ๊ตฌ๊ฐ„์„ ์•„์˜ˆ ์•ˆ ๋ณด์—ฌ์ค€๋‹ค** โ€” ์ „์ผ์ข…๊ฐ€๊ฐ€ ๋ฐ”๋€Œ๋ฉด ๊ตฌ๊ฐ„์ด ํ†ต์งธ๋กœ ๋‹ฌ๋ผ์ ธ ์–ด์ œ ๊ฐ’์€ ํ‹€๋ฆฐ ๊ฐ€๊ฒฉ์ด๋‹ค. - **ํ† ๊ธ€ ๋™์ž‘** โ€” ํŒ์—… ์•ˆ ํ† ๊ธ€์ด `data-surge-toggle`+`data-surge-refresh` ๋ฅผ ๋“ค๊ณ  ์žˆ์–ด **๊ธฐ์กด ํ•ธ๋“ค๋Ÿฌยท`POST /surge/toggle` ์ด ๋ฌด๋ณ€๊ฒฝ์œผ๋กœ ์žฌ์‚ฌ์šฉ**๋œ๋‹ค(๋‚™๊ด€์  ๊ฐฑ์‹  โ†’ ์‹คํŒจ ๋กค๋ฐฑ โ†’ ํ† ์ŠคํŠธ). โš ๏ธ `paintSurge(code,on)` ๋Š” **code ๋กœ ์ „ ์ธ์Šคํ„ด์Šค**๋ฅผ ์น ํ•œ๋‹ค(๊ฐ™์€ ์ข…๋ชฉ์ด ์—ฌ๋Ÿฌ ํŒจ๋„์— ์ค‘๋ณต ๋…ธ์ถœ โ€” 005930์€ 9๊ณณ) โ€” ํ‘œ์‹œ์žยท`.actions` ๋ฒ„ํŠผยทํŒ์—… ํ† ๊ธ€ 3์ข…์„ ํ•จ๊ป˜. โš ๏ธ **`window.__behive_load`(ํŒจ๋„ ์ „์ฒด ์ƒˆ๋กœ๊ณ ์นจ)๋ฅผ ๋ถ€๋ฅด์ง€ ๋ง ๊ฒƒ** โ€” ํ‚ค์›€ ์กฐํšŒ๊นŒ์ง€ ๋‹ค์‹œ ๋Œ์•„ ๋ช‡ ์ดˆ ๋’ค์—์•ผ ๋ฐ”๋€๋‹ค. ์„œ๋ฒ„๊ฐ€ `_invalidate_panels_cache()` ๋ฅผ ์ด๋ฏธ ํ–ˆ์œผ๋‹ˆ ๋‹ค์Œ ์ž๋™ ์ƒˆ๋กœ๊ณ ์นจ์ด ์ผ์น˜์‹œํ‚จ๋‹ค. ํ† ๊ธ€ ์„ฑ๊ณต ์‹œ `data-surge-refresh` ๋กœ ํŒ์—… ๋ณธ๋ฌธ๋งŒ ์žฌ fetch(์•ˆ ํ•˜๋ฉด ์ผ  ์งํ›„์—๋„ '๊บผ์ง' ๋ฌธ๊ตฌ๊ฐ€ ๋‚จ๋Š”๋‹ค). โš ๏ธ **๋„ค์ดํ‹ฐ๋ธŒ ํผ์œผ๋กœ ๋งŒ๋“ค์ง€ ๋ง ๊ฒƒ** โ€” 303โ†’`/` ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ๋กœ hash ํƒญ์ด ๋‚ ์•„๊ฐ„๋‹ค(๋ฉ”๋ชจ ๋ชจ๋‹ฌ๊ณผ ๊ฐ™์€ ์ด์œ ). โš ๏ธ **ํ‚ค๋Š” ์ข…๋ชฉ์ฝ”๋“œ ์ „์šฉ**(๋ชจ๋‹ˆํ„ฐ๊ฐ€ ์‹œ์„ธ ์กฐํšŒ์— ์ฝ”๋“œ๋ฅผ ์“ด๋‹ค โ€” `_set_surge_toggle` ์ด ValueError). ์ €์žฅ์†Œ `state/behive_surge_toggles.json`(fcntl lock + atomic write)๋ฅผ `surge_monitor.py` ๊ฐ€ ์ฝ๋Š”๋‹ค. ๋ฐฑ์—”๋“œ `_load/_is/_set_surge_toggle`ยท`_surge_toggles_lock`ยท`_surge_indicator_html`ยท`_surge_info_button_html`ยท`_render_surge_body`ยท`_surge_key_label`, CSS `.detail-name .surge-ind`ยท`.actions .btn-surge-info`ยท`.sg-*`. **๊ด€์‹ฌ์ข…๋ชฉ ๊ทธ๋ฃน (`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 (`state/openclaw.sqlite` โ†’ `cron_jobs`, OpenClaw ์—์ด์ „ํŠธ ์„ธ์…˜ โ€” LLM ๊ฒฝ์œ ) - **์˜ค์ „ ๋ธŒ๋ฆฌํ•‘** (main) โ€” **์›”~ํ† ** 07:30 (`30 7 * * 1-6`) โ€” ๋‰ด์Šค ๋ธŒ๋ฆฌํ•‘ ๋ฉ”์ผ + ๐Ÿ‡บ๐Ÿ‡ธ ๋ฏธ๊ตญ์ฆ์‹œ ์š”์•ฝ(@futuresnow). ์˜์ƒ์ด ์•„์ง ๋ฏธ๊ฒŒ์‹œ๋ฉด(KST ํ™”~ํ†  ๊ฒŒ์‹œ์˜ˆ์ •์ผ) ๋ฐœ์†ก ๋ณด๋ฅ˜. **์ผ์š”์ผ ์—†์Œ** (2026-08-12 ์ฃผ๋ง ์ œ์™ธ). **ํ† ์š”์ผ์€ ํ•ด์™ธ ์ „์šฉ** โ€” ์•„๋ž˜ `briefing_mail.py` ์˜ `overseas_only` ์ฐธ์กฐ - **์˜ค์ „ ๋ธŒ๋ฆฌํ•‘ (fallback 0755)** (main) โ€” ์›”~ํ†  07:55 โ€” 1์ฐจ ํด๋ฐฑ. 07:30์— ๋ฏธ๊ตญ์ฆ์‹œ ์š”์•ฝ ๋ฏธ๊ฒŒ์‹œ๋กœ ๋ณด๋ฅ˜๋œ ๊ฒฝ์šฐ ์žฌ์‹œ๋„(์—ฌ์ „ํžˆ ๋ฏธ๊ฒŒ์‹œ๋ฉด ๋˜ ๋ณด๋ฅ˜). `already_sent`๋กœ idempotent - **์˜ค์ „ ๋ธŒ๋ฆฌํ•‘ (fallback 0830)** (main) โ€” ์›”~ํ†  08:30 โ€” 2์ฐจ ํด๋ฐฑยท์ตœ์ข…. `prepare morning --final`๋กœ US ๋ฏธ๊ฒŒ์‹œ์—ฌ๋„ ๋ฌด์กฐ๊ฑด ๋ฐœ์†ก. 07:30ยท07:55์— ์ •์ƒ ๋ฐœ์†ก๋์œผ๋ฉด `already_sent`๋กœ ์Šคํ‚ต - **์˜คํ›„ ๋ธŒ๋ฆฌํ•‘** (main) โ€” **ํ‰์ผ** 19:00 (`0 19 * * 1-5`) โ€” ๋‰ด์Šค ๋ธŒ๋ฆฌํ•‘ ๋ฉ”์ผ. ์ฃผ๋ง ์—†์Œ (2026-08-12 ์ฃผ๋ง ์ œ์™ธ) - **๋น„ํ•˜์ด๋ธŒ ์ข…๋ชฉ๋ถ„์„ ์š”์•ฝ** (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) - **chat-web** โ€” ์ƒ์‹œ daemon (์›น ์ฑ„ํŒ… `chat.hyowons.net`, ํฌํŠธ 18793, `workspace/scripts/chat_web.py serve`) - **stock.briefing** โ€” ํ‰์ผ 20:10 โ€” `stock_portfolio_report.py send --no-mail`: **ํฌํŠธํด๋ฆฌ์˜ค ์Šค๋ƒ…์ƒท ํ™•๋ณด ์ „์šฉ, ๋ฉ”์ผ ๋ฐœ์†ก ์—†์Œ**(2026-08-12 ๊ด€๋ฆฌ์ž๋‹˜ ๊ฒฐ์ • โ€” ๋ฉ”์ผ ํ†ต์ˆ˜ ์ถ•์†Œ). ์Šค๋ƒ…์ƒท์€ ์ž์‚ฐ์›น '๋‹น์ผ ํ‰๊ฐ€์†์ต'ยท`rebase_to_nxt_close` ์ „์ผ baseline์˜ ๊ทผ๊ฑฐ๋ผ ๊ณ„์† ์Œ“๋Š”๋‹ค. โš ๏ธ **`run` ๋ชจ๋“œ๋กœ ๋ฐ”๊พธ์ง€ ๋ง ๊ฒƒ** โ€” ํœด์žฅ์ผ self-skip์ด `send` ๋ถ„๊ธฐ์—๋งŒ ์žˆ์–ด ํœด์žฅ์ผ ํ‚ค๊ฐ€ ์ด๋ ฅ์— ์„ž์ด๊ณ  ํ‰๋ฌธ ๋ฆฌํฌํŠธ๊ฐ€ ๋กœ๊ทธ๋กœ ์Ÿ์•„์ง„๋‹ค. `--no-mail`์€ ํœด์žฅ์ผ ๊ฐ€๋“œยท์‹คํŒจ ์ž๊ฐ€์•Œ๋ฆผ์„ ์œ ์ง€ํ•˜๊ณ  `send_mail`๋งŒ ๊ฑด๋„ˆ๋œ€ - **stock.briefing-fallback-2030** โ€” ํ‰์ผ 20:30 โ€” ์˜ค๋Š˜ ์Šค๋ƒ…์ƒท ์—†์œผ๋ฉด `send --no-mail` ์žฌ์‹คํ–‰ (idempotent). ์ตœ๊ทผ 2์ฃผ ์‹ค์ธก ํ•œ ๋ฒˆ๋„ ์‹ค์ œ ์ž‘์—… ์•ˆ ํ•จ(20:10์ด ๋งค์ผ ์„ฑ๊ณต) - **stock.briefing-fallback-2100** โ€” ํ‰์ผ 21:00 โ€” **๋ฌด์กฐ๊ฑด fresh fetch๋กœ ์Šค๋ƒ…์ƒท ๊ฐฑ์‹ ** (`briefing_fallback.py force` โ†’ ์Šค๋ƒ…์ƒท ์žˆ์œผ๋ฉด `stock_portfolio_report.py run` ๋ฉ”์ผยทํ…”๋ ˆ๊ทธ๋žจ X, ์—†์œผ๋ฉด `send --no-mail` ํด๋ฐฑ + ์‹คํŒจ ์‹œ ์•Œ๋ฆผ). 20:10 ๋ฐ์ดํ„ฐ ๋ถ€์ •ํ™• ์ผ€์ด์Šค ๋ณด์™„์šฉ - **stock.watchlist-monitor** โ€” ํ‰์ผ 10:00 / 12:00 / 14:00 โ€” ์›Œ์น˜๋ฆฌ์ŠคํŠธ buy/target/stop ์•Œ๋ฆผ (2026-05-12: 15๋ถ„ ๊ฐ„๊ฒฉ โ†’ 3ํšŒ๋กœ ์ถ•์†Œ) - **stock.trailing-monitor** โ€” ํ‰์ผ 08:00โ€“19:59 **๋งค 1๋ถ„** (`StartCalendarInterval` 720์—”ํŠธ๋ฆฌ, ์Šคํฌ๋ฆฝํŠธ self-skip โ€” 2026-08-25 plist ์‹ค์ธก ์ •์ •. ๊ทธ์ „์—” "09:00โ€“15:30 391์—”ํŠธ๋ฆฌ"๋กœ ์ ํ˜€ ์žˆ์—ˆ๋‹ค) โ€” `trailing_monitor.py check`: **ํŠธ๋ ˆ์ผ๋ง ์Šคํ†ฑ ๊ฐ์‹œ**. โš ๏ธ **๋งค๋งค API๋ฅผ ์ž๋™ ํ˜ธ์ถœํ•˜๋Š” ์œ ์ผํ•œ ํŠธ๋ฆฌ๊ฑฐ** โ€” ๋งค๋งค ์ž๋™ ํŠธ๋ฆฌ๊ฑฐ ๊ธˆ์ง€ ๊ทœ์น™์˜ ์˜ˆ์™ธ๋กœ 2026-07-30 ๊ด€๋ฆฌ์ž๋‹˜ ๋ช…์‹œ ์Šน์ธ. ํ˜ธ์ถœ ๋Œ€์ƒ์€ โ‘ `kiwoom_order.modify_order`(์กฐ๊ฑด๋‹จ๊ฐ€ ์ƒํ–ฅ ์ •์ •) โ‘ก**์˜ˆ์•ฝ ํŠธ๋ ˆ์ผ๋ง ๋ฐœ๋™ ์‹œ `submit(STOP_LIMIT)` ์‹ ๊ทœ ๋ฐœ์ฃผ**(2026-08-25 ๊ด€๋ฆฌ์ž๋‹˜ ์Šน์ธ) 2์ข…. โš ๏ธ ๊ทธ์ „ ๊ทผ๊ฑฐ์˜€๋˜ "์‹ ๊ทœ ๋ฐœ์ฃผ ๊ฒฝ๋กœ๊ฐ€ ์—†์Œ"์€ ๋” ์ด์ƒ ์‚ฌ์‹ค์ด ์•„๋‹ˆ๋‹ค โ€” ๋ฐ”๋€ ๊ทผ๊ฑฐ๋Š” **๊ณ„์ขŒยท์ข…๋ชฉยท์ˆ˜๋Ÿ‰ยท๊ณ„๋‹จยท๋ฐœ๋™๊ฐ€๊ฐ€ PIN ์Šน์ธ ์‹œ์ ์— ํ™•์ •๋˜๊ณ  ๊ฐ์‹œ๋Š” ๋ฐœ๋™๊ฐ€ ๋„๋‹ฌ ํŒ์ •๋งŒ ํ•œ๋‹ค**(์ˆ˜๋Ÿ‰ ์ฆ๊ฐ€ยท๋ฐฉํ–ฅ ๋ณ€๊ฒฝ ๊ฒฝ๋กœ ์—†์Œ, ๋งค๋„๊ฐ€๋Šฅ ๋ถ€์กฑ ์‹œ ์ถ•์†Œ๋งŒ)(PIN ์Šน์ธ ์‹œ ๊ณ„์ขŒยท์ข…๋ชฉยท๊ณ„๋‹จ๋ณ„ ์ˆ˜๋Ÿ‰ยทํ•˜๋ฝ๋ฅ  ํ™•์ •, ๊ฐ์‹œ๋Š” ์กฐ๊ฑด๋‹จ๊ฐ€ **์ƒํ–ฅ๋งŒ**. ๊ณ„๋‹จ์ด ์ฒด๊ฒฐ๋ผ๋„ ์žฌ๋ฐฐ์น˜=์ทจ์†Œ+์‹ ๊ทœ๋ฐœ์ฃผ๋Š” ํ•˜์ง€ ์•Š๋Š”๋‹ค). ์˜ˆ์•ฝ 0๊ฑด์ด๋ฉด ์ฆ‰์‹œ ์ข…๋ฃŒ(API ์ฝœ 0). โš ๏ธ ๊ณ„๋‹จ์‹์ด๋ผ **์ •์ • ์ฝœ์ด ๊ณ„๋‹จ ์ˆ˜์— ๋น„๋ก€**(์˜ˆ์•ฝ 3๊ฑดร—5๊ณ„๋‹จ์ด๋ฉด ๋ถ„๋‹น ์ตœ๋Œ€ 15์ฝœ). ๋กœ๊ทธ `logs/stock-trailing-monitor.{log,err.log}` โ€” โš ๏ธ **์ด๋ฒคํŠธ๊ฐ€ ์žˆ์„ ๋•Œ๋งŒ ์ฐ๋Š”๋‹ค**(์˜ˆ์•ฝ 0๊ฑด์ด๋ฉด ํ•œ ์ค„๋„ ์•ˆ ๋‚จ์•„ 2026-08-28~09-10 13์ผ๊ฐ„ ๋กœ๊ทธ ๋ฌด๊ฐฑ์‹ ์ด ์ •์ƒ์ธ์ง€ ์žฅ์• ์ธ์ง€ ๊ตฌ๋ถ„ ๋ถˆ๊ฐ€์˜€๋‹ค). ๊ทธ๋ž˜์„œ ์‚ฌ์ดํด๋งˆ๋‹ค `state/trailing_monitor_heartbeat` ์˜ mtime ๋งŒ ๊ฐฑ์‹ ํ•˜๋Š” ์ƒ์กด ์‹ ํ˜ธ๋ฅผ ๋‘๊ณ  `health_check.py` ๊ฐ€ ๊ทธ ํŒŒ์ผ์„ ์ฝ๋Š”๋‹ค(๋กœ๊ทธ๋กœ ์ฐ์œผ๋ฉด ๋ถ„๋‹น 1์ค„ ร— 720ํšŒ/์ผ์ด ์‹ค์ œ ์ด๋ฒคํŠธ๋ฅผ ๋ฎ๋Š”๋‹ค). ์˜ˆ์•ฝ ํŠธ๋ ˆ์ผ๋ง์€ ๊ฐ์‹œ๊ฐ€ ์ฃฝ์œผ๋ฉด ์•„์˜ˆ ๋ฐœ๋™ํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ ์ด ์žก์€ ์ƒ์กด ํ™•์ธ์ด ํŠนํžˆ ์ค‘์š”ํ•˜๋‹ค. โš ๏ธ **cadence ์ด๋ ฅ 2๋ถ„โ†’30์ดˆโ†’1๋ถ„**(์ „๋ถ€ 2026-07-30) โ€” launchd ์ตœ์†Œ ๋‹จ์œ„๊ฐ€ 1๋ถ„์ด๋ผ 30์ดˆ๋Š” ํ”„๋กœ์„ธ์Šค ๋‚ด๋ถ€ `--repeat 2 --gap 30`์œผ๋กœ ๊ตฌํ˜„ํ–ˆ๊ณ  CLI ์˜ต์…˜์€ ์‚ด์•„์žˆ์Œ(๋‹ค์‹œ ์“ธ ๋• plist ์ธ์ž๋งŒ ์ถ”๊ฐ€). `StartInterval=30`์€ GUI idle ์‹œ ๋ฐœํ™” ๋ณด๋ฅ˜๋ผ ์‚ฌ์šฉ ๊ธˆ์ง€ - **stock.surge-monitor** โ€” ํ‰์ผ **09:00โ€“19:59** **๋งค 1๋ถ„** (`StartCalendarInterval` **660์—”ํŠธ๋ฆฌ**, ์Šคํฌ๋ฆฝํŠธ self-skip) โš ๏ธ **2026-09-22 15:35 โ†’ 20:00 ํ™•๋Œ€**(KRX ์• ํ”„ํ„ฐ๋งˆ์ผ“ ๋Œ€์‘). ํ™•๋Œ€๊ฐ€ ์„ฑ๋ฆฝํ•˜๋Š” ์ „์ œ๋Š” `realtime_hub` ๊ฐ€ โ‘ `_AL`(ํ†ตํ•ฉ) ๊ตฌ๋…์ด๋ผ KRX ์• ํ”„ํ„ฐ๋งˆ์ผ“ ์ฒด๊ฒฐ์ด ๊ทธ ๊ตฌ๋…์œผ๋กœ ๋“ค์–ด์˜ค๊ณ  โ‘ก`_market_open()` = `behive_web._market_phase_state()["active"]` ๋ผ 20:00 ๊นŒ์ง€ ์‚ด์•„ ์žˆ๋‹ค๋Š” ๊ฒƒ. โš ๏ธ **๋งˆ๊ฐ ํ›„ ๋ฒ„ํผ๋ฅผ ๋‘์ง€ ์•Š๋Š”๋‹ค** โ€” 20:00 ์— ํ—ˆ๋ธŒ๊ฐ€ ์ข…๋ฃŒ๋ผ ๊ทธ ๋’ค ์‚ฌ์ดํด์€ ์‹œ์„ธยทVI ๋ฅผ ๋ชป ๋ฐ›๊ณ  ํ—›๋ˆ๋‹ค(๊ธฐ์กด 15:35 ๋Š” "15:30 ๋งˆ๊ฐ + 5๋ถ„ ๋ฒ„ํผ"์˜€๋‹ค). โš ๏ธ ์•Œ๋ฆผ ์ฆ๊ฐ€๋ถ„์€ ๋ฏธ๋ฏธํ•˜๋‹ค โ€” ์‹ค์ธก ๋ฌธํ„ฑ์ด 8~14% ๋ผ ์• ํ”„ํ„ฐ๋งˆ์ผ“ ์›€์ง์ž„(์–ด์ œ +1.2%)์œผ๋กœ๋Š” ์•ˆ ๋„˜๊ณ , ๋‚ ์งœยท์ข…๋ชฉ๋ณ„ dedup ๋„ ์žˆ์–ด ์ •๊ทœ์žฅ์— ์ด๋ฏธ ๋ฐœ๋™ํ•œ ์ข…๋ชฉ์€ ์ถ”๊ฐ€ ์•Œ๋ฆผ์ด ์—†๋‹ค โ€” `surge_monitor.py check`: **๊ธ‰๋“ฑ๋ฝ ์•Œ๋ฆผ**(VI ๋ฐœ๋™ + ATR ๋ฐฐ์ˆ˜ ๋ŒํŒŒ โ†’ ๋ ˆ์ด ํ…”๋ ˆ๊ทธ๋žจ). ์กฐํšŒยท์•Œ๋ฆผ ์ „์šฉ์œผ๋กœ ์ฃผ๋ฌธ API ํ˜ธ์ถœ ๊ฒฝ๋กœ๊ฐ€ ์—†์–ด ๋งค๋งค ์ž๋™ ํŠธ๋ฆฌ๊ฑฐ ๊ธˆ์ง€ ๊ทœ์น™์— ์ €์ด‰๋˜์ง€ ์•Š์Œ. ํ† ๊ธ€ 0๊ฑด์ด๋ฉด ์ฆ‰์‹œ ์ข…๋ฃŒ(API ์ฝœ 0). ํ‰์‹œ ์‚ฌ์ดํด ๋น„์šฉ์€ behive_web localhost 1์ฝœ + ํ‚ค์›€ 0์ฝœ. ๋กœ๊ทธ `logs/stock-surge-monitor.{log,err.log}`. โš ๏ธ `StartInterval` ๊ธˆ์ง€(GUI idle ์‹œ ๋ฐœํ™” ๋ณด๋ฅ˜) - **stock.ipo-calendar-sync** โ€” **์›”ยท์ˆ˜ยท๊ธˆ 17:00** (plist ์‹ค์ธก `Weekday 1,3,5`; ๋ฌธ์„œ์— ์˜ค๋ž˜ '๋งค์ฃผ ๊ธˆ์š”์ผ'๋กœ ์ž˜๋ชป ์ ํ˜€ ์žˆ์—ˆ๋‹ค โ€” 2026-08-12 ์ˆ˜์ •) โ€” 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 โ€” KRX ํœด์žฅ์ผ โ†’ `state/market_holidays.json`. ๋ ˆ์ด ์ž๋™ํ™” ์ „๋ฐ˜์˜ ํœด์žฅ์ผ ํŒ์ • ๊ธฐ์ค€(์ƒ์„ธ๋Š” ์œ„ `holiday_sync.py`). โš ๏ธ investing 403 ์ฐจ๋‹จ ์ดํ›„ nager ๋‹จ๋…์œผ๋กœ ๋„๋Š” ์ค‘์ด๋ผ **stderr ์— `investing ... 403` ๋‘ ์ค„์ด ๋งค์ฃผ ๋‚จ๋Š” ๊ฒƒ์ด ์ •์ƒ**์ด๋‹ค(์–‘์ชฝ ๋‹ค ์‹คํŒจํ•ด์•ผ ์•Œ๋ฆผ). 2026-07-12~09-10 ์‚ฌ์ด์—” investing 0๊ฑด์ด๋ฉด ์ €์žฅ ์ž์ฒด๋ฅผ ๊ฑด๋„ˆ๋›ฐ๋Š” ๊ฐ€๋“œ ๋•Œ๋ฌธ์— **2๊ฐœ์›”๊ฐ„ ์กฐ์šฉํžˆ stale ์ด์—ˆ๋‹ค** - **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` ํ•„์ˆ˜) โ‘ค`kiwoom_client.py refresh-codes --if-stale 7` (2026-09-10 ์ถ”๊ฐ€ โ€” ์ข…๋ชฉ์ฝ”๋“œ ์บ์‹œ ์ฃผ 1ํšŒ ๊ฐฑ์‹ . `--if-stale N` ์€ ํŒŒ์ผ mtime ์ด N์ผ ๋ฏธ๋งŒ์ด๋ฉด ๊ฑด๋„ˆ๋›ฐ๋ฏ€๋กœ ๋งค์ผ ๋ฐœํ™”ํ•ด๋„ ์‹ค์ œ ์กฐํšŒ๋Š” ์ฃผ 1ํšŒ. โš ๏ธ ์ด ์บ์‹œ์—” `etf_etn` ํ”Œ๋ž˜๊ทธ๋„ ์žˆ๋‹ค(2026-09-21 ์ถ”๊ฐ€) โ€” ka10099 ๋ฅผ ETF/ETN ์ „์šฉ ์‹œ์žฅ(`mrkt_tp` 8ยท60ยท70ยท90)์œผ๋กœ 4์ฝœ ๋” ์กฐํšŒํ•ด ๊ธฐ์กด ํ•ญ๋ชฉ์— ํ‘œ์‹œ๋งŒ ์–น๋Š”๋‹ค(์ƒˆ ํ•ญ๋ชฉ ์ถ”๊ฐ€ X, 1,540์ข…๋ชฉ). **์• ํ”„ํ„ฐ๋งˆ์ผ“ ๊ฑฐ๋ž˜๋ถˆ๊ฐ€ ํŒ์ •์˜ ์œ ์ผํ•œ ๊ทผ๊ฑฐ**์ด๊ณ , ์ข…๋ชฉ๋ช… ํ”„๋ฆฌํ”ฝ์Šค(KODEX/TIGERโ€ฆ) ์ถ”์ธก์„ ์“ฐ์ง€ ์•Š๋Š” ์ด์œ ๋Š” ์‹ ๊ทœ ์šด์šฉ์‚ฌ ๋ธŒ๋žœ๋“œ๊ฐ€ ์ƒ๊ธฐ๋ฉด ์กฐ์šฉํžˆ ํ‹€๋ฆฌ๋Š”๋ฐ ์ด๊ฒŒ ๋งค๋งค ๊ฒŒ์ดํŠธ๋ผ์„œ๋‹ค. โš ๏ธ ka10099 ์œ ๋Ÿ‰์ด ์ดˆ๋‹น 5๊ฑด์ด๋ผ ํŽ˜์ด์ง€๋„ค์ด์…˜ ์งํ›„ 0.15s ๊ฐ„๊ฒฉ์œผ๋กœ ์ด์–ด ๋ถ™์ด๋ฉด ๋งˆ์ง€๋ง‰ ์‹œ์žฅ์ด 429 ๋กœ ํŠ•๊ธด๋‹ค(์‹ค์ธก mrkt_tp=90 8์ข…๋ชฉ ๋ˆ„๋ฝ) โ€” 0.5s ํŽ˜์ด์‹ฑ + 429 ์žฌ์‹œ๋„ 1ํšŒ๋ฅผ ๋‘” ์ด์œ . ํ”Œ๋ž˜๊ทธ ์กฐํšŒ๊ฐ€ ์‹คํŒจํ•ด๋„ **์บ์‹œ ์ €์žฅ์€ ๊ณ„์†ํ•œ๋‹ค**(ํ”Œ๋ž˜๊ทธ ํ•˜๋‚˜ ๋•Œ๋ฌธ์— 4300์ข…๋ชฉ ์บ์‹œ๋ฅผ ์žƒ์œผ๋ฉด ์ข…๋ชฉ๋ช… ๊ฒ€์ƒ‰ยทNXT ํŒ์ •์ด ๋‹ค ๋ฉˆ์ถ˜๋‹ค). โš ๏ธ ์ด ์บ์‹œ์˜ `nxt_enable` ์ด ์ž์‚ฐ์›น์˜ NXT ๊ฑฐ๋ž˜ ์ข…๋ชฉ ํŒ์ • ๊ทผ๊ฑฐ๋‹ค โ€” lazy ๊ฐฑ์‹ ์€ '๋ชจ๋ฅด๋Š” ์ข…๋ชฉ๋ช… ๊ฒ€์ƒ‰' ๋•Œ๋งŒ ๋Œ์•„ 3์ฃผ๊ฐ„ ๋ฐฉ์น˜๋ผ ์žˆ์—ˆ๊ณ , ๊ฐฑ์‹ ํ•˜๋‹ˆ 4300์ข…๋ชฉ ์ค‘ 3๊ฑด์ด ์‹ค์ œ๋กœ ๋ฐ”๋€Œ์—ˆ๋‹ค) โ‘ฃ`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.6-sol)์ด ์ฃฝ์–ด ๊ฒŒ์ดํŠธ์›จ์ด๊ฐ€ ์กฐ์šฉํžˆ **์œ ๋ฃŒ OpenRouter๋กœ ํด๋ฐฑ**ํ•˜๋ฉด ํ† ํฐ๋น„๊ฐ€ ์ƒˆ๋Š” ๊ฑธ ๊ฐ์ง€โ†’ํด๋กœ(main) ํ…”๋ ˆ๊ทธ๋žจ ์ฆ‰์‹œ ์•Œ๋ฆผ. ์‹ ํ˜ธ์›=`agents/*/agent/openclaw-agent.sqlite` ์˜ **`trajectory_runtime_events`** ํ…Œ์ด๋ธ”์— ์Œ“์ด๋Š” `model.completed` ์ด๋ฒคํŠธ(์Šน์ž ๋ชจ๋ธ). โš ๏ธ **2026-09-10 2026.9.3 ์—…๊ทธ๋ ˆ์ด๋“œ๋กœ ํŒŒ์ผ(`agents/*/sessions/*.trajectory.jsonl`)์—์„œ ์ด ํ…Œ์ด๋ธ”๋กœ ์ด๊ด€**๋๋‹ค โ€” ์˜› ํŒŒ์ผ glob ์€ ๋งค์น˜ 0๊ฑด์ด๋ผ ์˜ˆ์™ธ ์—†์ด 'ํด๋ฐฑ ์—†์Œ'๋งŒ ๋ฐ˜ํ™˜ํ•˜๋ฉฐ **์กฐ์šฉํžˆ ๋ฌด๋ ฅํ™”**๋œ๋‹ค(์›Œํ„ฐ๋งˆํฌ๊ฐ€ ๋ฉˆ์ถ˜ ๊ฒƒ์ด ์œ ์ผํ•œ ์ฆ์ƒ). ๊ฒŒ์ดํŠธ์›จ์ด๊ฐ€ ์“ฐ๋Š” ์ค‘์ด๋ฏ€๋กœ `mode=ro` + busy timeout ์œผ๋กœ ์ฝ๋Š”๋‹ค. โš ๏ธ **ํŒ์ • ๊ธฐ์ค€์€ provider ๊ฐ€ ์•„๋‹ˆ๋ผ `primary` ์™€ ๋‹ค๋ฅธ ๋ชจ๋ธ์ธ๊ฐ€**(2026-09-10 ๋ณ€๊ฒฝ) โ€” ํด๋ฐฑ ์ฒด์ธ์ด ์ „๋ถ€ ๋ฌด๊ณผ๊ธˆ์ด ๋˜๋ฉด์„œ `solโ†’terra` ๊ฐ™์€ **๊ตฌ๋… ๋‚ด ํด๋ฐฑ์„ provider ๋งŒ ๋ณด๋ฉด ํ†ต์งธ๋กœ ๋†“์นœ๋‹ค**. ๊ณผ๊ธˆ 0 ์ด์–ด๋„ '์ฃผ ๋ชจ๋ธ์ด ์ฃฝ์—ˆ๋‹ค'๋Š” ์‚ฌ์‹ค์€ ์•Œ์•„์•ผ ํ•œ๋‹ค. `_primary_models()` ๊ฐ€ `openclaw.json` ์—์„œ ์—์ด์ „ํŠธ๋ณ„ primary ๋ฅผ ์ฝ๊ณ , ๋ชป ์ฝ์„ ๋•Œ๋งŒ ์˜› ๊ทœ์น™(openrouter=ํด๋ฐฑ)์œผ๋กœ ํ›„ํ‡ดํ•œ๋‹ค. ์•Œ๋ฆผ ๋ฌธ๊ตฌ๋Š” `_is_billed` ๋กœ ๊ฐˆ๋ฆฐ๋‹ค โ€” ์œ ๋ฃŒ๋ฉด ๐Ÿšจ ์ฆ‰์‹œ ์ ๊ฒ€, ๋ฌด๊ณผ๊ธˆ์ด๋ฉด โš ๏ธ ๊ณผ๊ธˆ ์—†์Œ. โš ๏ธ **`_model_key` ์ •๊ทœํ™”๋ฅผ ๋ฐ˜๋“œ์‹œ ๊ฑฐ์นœ๋‹ค** โ€” openrouter ๋Š” modelId ์— provider ๊ฐ€ ์ด๋ฏธ ๋ถ™์–ด ์™€(`openrouter/free`) ๊ทธ๋ƒฅ ์ด์–ด๋ถ™์ด๋ฉด `openrouter/openrouter/free` ๊ฐ€ ๋˜๊ณ  **๋ฌด๋ฃŒ๊ฐ€ ์œ ๋ฃŒ๋กœ ์˜คํŒ๋œ๋‹ค**(2026-09-10 ์‹ค์ธก์œผ๋กœ ์žก์€ ๋ฒ„๊ทธ). ๋ฌด๋น„์šฉยท์˜จ๋””์Šคํฌยท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`๊ฐ€ ์œ ์ผํ•˜๊ฒŒ ์‹ ๋ขฐ ๊ฐ€๋Šฅํ•œ ์Šน์ž ์‹ ํ˜ธ - **log-rotate** โ€” ๋งค์ฃผ ์ผ์š”์ผ 04:00 โ€” `scripts/log_rotate.py`: `logs/` ํฌ๊ธฐ ์ƒํ•œ ์œ ์ง€. 30์ผ ์ดˆ๊ณผ ๋กœ๊ทธ๋Š” trash, 20MB ์ดˆ๊ณผ **ํ™œ์„ฑ** ๋กœ๊ทธ๋Š” ์ตœ๊ทผ 3000์ค„๋งŒ ๋‚จ๊ธฐ๊ณ  **in-place** ์ถ•์†Œ. โš ๏ธ **rename ๋ฐฉ์‹ ๊ธˆ์ง€** โ€” launchd ๋ฐ๋ชฌ์€ ์ด๋ฏธ ์—ฐ inode ์— ๊ณ„์† ์“ฐ๋ฏ€๋กœ ๋””์Šคํฌ๋Š” ์•ˆ ์ค„๊ณ  ์ƒˆ ํŒŒ์ผ๋งŒ ๋น„์–ด ์žˆ๊ฒŒ ๋œ๋‹ค. ๊ฐ™์€ fd ๋ฅผ ์œ ์ง€ํ•œ ์ฑ„ ์•ž์œผ๋กœ ๋‹น๊ฒจ์“ฐ๊ณ  truncate ํ•œ๋‹ค(๋ฐ๋ชฌ์ด O_APPEND ๋กœ ์—ด๊ธฐ ๋•Œ๋ฌธ์— ์•ˆ์ „ โ€” 2026-09-10 behive-web 112MB ๋ฅผ ์ถ•์†Œํ•œ ๋’ค ๋˜๋Œ์•„๊ฐ€์ง€ ์•Š์Œ์„ ์‹ค์ธก). ๋„์ž… ์‹œ์  ์‹ค์ธก **1033MB โ†’ 30MB**(๋Œ€๋ถ€๋ถ„ ์ข…๋ฃŒ๋œ claude-session ๋กœ๊ทธ, ๋‹จ์ผ ํŒŒ์ผ 422MB). โš ๏ธ ๊ฒŒ์ดํŠธ์›จ์ด ๋กœ๊ทธ๋Š” ๋Œ€์ƒ ์•„๋‹˜ โ€” 2026.9.3 ๋ถ€ํ„ฐ `~/Library/Logs/openclaw/` ๋กœ ์˜ฎ๊ฒจ๊ฐ€ ๋ณธ์ฒด๊ฐ€ ์ž์ฒด ๊ด€๋ฆฌํ•œ๋‹ค(`logs/gateway.*` 19MB ๋Š” ๊ทธ๋•Œ ๋‚จ์€ ๊ณ ์•„๋ผ STALE ๋กœ ์ •๋ฆฌ๋จ). ๋กœ๊ทธ `logs/log-rotate.{log,err.log}` - **health-check** โ€” **๋งค์ผ 09:00** โ€” `scripts/health_check.py`: **์กฐ์šฉํžˆ ์ฃฝ์€ ์ž๋™ํ™” ๊ฐ์ง€**. ๊ฐ์‹œ ๋Œ€์ƒ์€ **`TASKS.md` ยง4 ํ‘œ๋ฅผ ํŒŒ์‹ฑ**ํ•ด์„œ ์ •ํ•œ๋‹ค โ€” ํ‘œ๊ฐ€ ๊ณง ์„ค์ •์ด๋ผ, ํŠธ๋ฆฌ๊ฑฐ๋ฅผ ๋ฐ”๊พธ๊ณ  ํ‘œ๋ฅผ ์•ˆ ๊ณ ์น˜๋ฉด ์•Œ๋ฆผ์ด ๋– ์„œ ๋ฌธ์„œ ๋“œ๋ฆฌํ”„ํŠธ๊ฐ€ ์Šค์Šค๋กœ ๋“œ๋Ÿฌ๋‚œ๋‹ค. ํŒ์ •์€ exit code ๊ฐ€ ์•„๋‹ˆ๋ผ **๊ฒฐ๊ณผ๋ฌผ์˜ mtime**(2026-09-10 ์ ๊ฒ€์—์„œ ํ•˜๋“œ ์‹คํŒจ๋Š” 0๊ฑด์ธ๋ฐ `holiday_sync` 2๊ฐœ์›” staleยท`codex_fallback_monitor` ๋ฌด๋ ฅํ™”์ฒ˜๋Ÿผ **exit 0 ์ธ๋ฐ ๊ฒฐ๊ณผ๊ฐ€ ์˜›๊ฒƒ**์ธ ์‹คํŒจ๊ฐ€ ์‹ค์ œ ์œ„ํ—˜์œผ๋กœ ๋“œ๋Ÿฌ๋‚ฌ๋‹ค). โš ๏ธ **์ฆ๊ฑฐ๋Š” '๊ทธ ์žก์ด ๋Œ๋ฉด ๋ฐ˜๋“œ์‹œ ๊ฐฑ์‹ ๋˜๋Š”' ํŒŒ์ผ์ด์–ด์•ผ ํ•œ๋‹ค** โ€” `surge_alerts.json`ยท`trailing_stops.json`ยท`whooing_synced.json` ์ฒ˜๋Ÿผ ์ผ์ด ์žˆ์„ ๋•Œ๋งŒ ์“ฐ์ด๋Š” ํŒŒ์ผ์€ ์กฐ์šฉํ•œ ๋‚  stale ๋กœ ๋ณด์—ฌ ์˜คํƒ์ด ๋œ๋‹ค. โš ๏ธ KeepAlive ๋ฐ๋ชฌ์€ `daemon: