# StockBot v3.0 - Claude Code Operating Guide > Last updated: 2026-06-04 > Runtime: local Windows now, planned Synology NAS Docker migration later > Current mode: paper trading / dry run (`KIS_MOCK=true`, `DRY_RUN=true`) This file is written for Claude Code. Keep it operational, explicit, and easy for an agent to follow. Human-facing project background belongs in `README.md`. ## Agent Role - When working alone: analyze, plan, implement, verify, and self-review. - When collaborating with Codex: implement only the approved scope and provide Codex with the approved plan, relevant files, diff, test results, and acceptance criteria for review. - Do not ask Codex for the entire conversation history during collaboration. - Do not edit files that Codex is actively editing. - Limit review loops: one pass for small work, at most two passes for medium work. Split large work into phase gates. ## Solo Workflow 1. Analyze the request and classify scope: small, medium, or large. 2. Write an explicit plan before implementation. 3. Implement one file at a time and keep the scope tight. 4. Run focused verification. 5. Perform the veteran self-review below. 6. If the score is below 90, fix the highest-leverage issues and review again. Use this exact self-review format: ```text Veteran role: Overall score: <0-100> Decision: PASS | FAIL Category scores: - Correctness and requirement fit: /30 - - Safety, security, and failure handling: /20 - - Maintainability and architecture fit: /20 - - Testability and verification: /15 - - Scope control and operational readiness: /10 - - Clarity of handoff and reviewer confidence: /5 - Blocking issues preventing 90+: - Highest-leverage fixes: - ``` ## Safety Policy - AI is for market review, context generation, and proposals only. - The code decides entries, exits, risk gates, and order behavior. - Runtime ML model scores are observation-only. They may be logged and stored, but must not block buys, resize positions, or override exits unless explicitly approved later. - Evening review must not directly edit `app/config.py`, `app/execution/`, `app/strategy/`, or `app/risk/`. Write proposal reports instead. - Strategy parameter changes must be written to `reports/proposals/YYYY-MM-DD_strategy_proposal.md` with evidence and manual approval requirements. - `FORCE_EXIT = "14:50"` is immutable. - Stop-loss checks must remain higher priority than profit-taking checks. - Real-cash trading is not approved yet. ## Current Implementation Status - Current mode is paper trading / dry-run focused. - Approved strategy values: - `ENTRY_START = "09:20"` - `MAX_HOLD_MIN = 90` - `FORCE_EXIT = "14:50"` unchanged - `avoid_sectors` filtering is active at runtime. `main.py` passes sector context into `check_entry()`. - Sector handling keeps a `ticker_sectors` cache and uses name-based hints for known avoid-sector cases. - Re-entry controls are active: - `TIME` and `FORCE` cooldown is based on final exit time, not entry time. - Final `TP1`/`TP2` exits block same-day re-entry for that ticker. - Re-entry control state is restored from today's DB rows after restart. - SL cascade halt is active: - `SL_CASCADE_HALT_THRESHOLD = 5` - `SL_CASCADE_WINDOW_MIN = 60` - New entries stop when the threshold is reached; existing positions keep normal exit handling. - Duplicate bot execution guards are active: - `app/main.py` uses `SingleInstanceLock` on `logs/stockbot.lock`. - `scripts/start_bot.py` stops the PID-file process and scans for existing `app/main.py` processes before starting one new bot. - `scripts/run_morning.ps1` is the only owner of post-morning bot startup. - `.claude/commands/morning.md` must not call `/start-bot` or `scripts/start_bot.py`. - KIS stability hardening is active: - Mode-specific request spacing in `KISClient`. - Price lookups retry transient KIS timeout/rate-limit errors. - DRY_RUN buy/sell paths can reuse the already-read quote as the simulated fill price to reduce extra API calls. - Daily summary has a duplicate guard; Discord settlement-send failures are logged without crashing settlement. - Data layer: - `entry_snapshots` are active. - `post_entry_snapshots` sample 60s, 180s, 300s, and 600s after entry. - Bot data export: `scripts/export_training_dataset.py`. - External data and ML: - Daily features: `scripts/collect_daily_features.py`, with KIS fallback when pykrx fails. - KIS minute bars: `scripts/collect_minute_data.py`, ETF/ETN excluded by default, multi-window collection from 09:30 to 14:00. - External dataset builder: `scripts/build_external_training_dataset.py`. - Training: `scripts/train_ai_model.py`. - Runtime loader: `app/ml/predictor.py`. - Latest successful training run: 2026-06-02 18:36. - Latest rows: 5,773 total (`external_training_dataset.csv` 5,720 + bot dataset 53). - Latest metrics: `label_stop_loss` ROC-AUC 0.896, `label_win` ROC-AUC 0.715. - Latest daily review/proposal files exist through 2026-06-02. - 2026-06-03 was skipped as a market holiday. ## Current Risks - The ML model is observation-only and still dominated by external pretraining rows; bot-trade labels are only 53 rows. - KIS minute data is verified for same-day windows, but historical depth and ticker coverage are limited. - External minute data is pretraining data, not actual bot-trade data. - pykrx daily feature collection can fail for same-day data; KIS fallback is active. - KIS rate limits can still happen if multiple scripts or processes call KIS at the same time. - The 2026-06-03 holiday training run logged a failure at the holiday-check step instead of a clean skip. Inspect this before relying on holiday automation noise level. - The 2026-06-04 morning duplicate execution happened before the `/morning` instruction fix. The next scheduled morning run should be checked for exactly one context generation and one `start_bot.py` startup. - Real-cash mode still needs stronger fill, partial-fill, unfilled-order, cancel/replace, and recovery logic. - Security cleanup is needed: keep webhooks, credentials, tokens, and remote credentials out of tracked files and remote URLs. - Older logs contain encoding damage. New operational notes should stay ASCII unless the target file intentionally uses another encoding. ## Automation Flow ```text 08:15 StockBot_Morning -> scripts/run_morning.ps1 -> /morning Build data/daily_context.json. After /morning exits, run_morning.ps1 calls python scripts/start_bot.py. 08:30 Bot loads daily_context.json and builds the watch universe. 08:50 Bot calculates volatility breakout targets. If restarted after 08:50, the bot recalculates targets immediately; open=0 is ignored. 09:00 Morning trading session starts. 09:00-15:05 StockBot_Watchdog checks bot liveness every 5 minutes. 11:00 New entries pause if midday_context.json has not loaded. 11:20 StockBot_Midday -> scripts/run_midday.ps1 -> /midday Build data/midday_context.json; bot detects it and starts lunch controls. 14:00 New entries stop; exits continue. 14:50 Force exit all positions. This time is immutable. 15:10 Daily settlement and Discord summary. Watchdog must not restart the bot at or after 15:10. 15:30 StockBot_Evening -> scripts/run_evening.ps1 -> /evening Write daily report and proposal report when needed. 16:00 StockBot_Training -> scripts/run_training_pipeline.ps1 ``` ## Slash Command Responsibilities ### `/morning` 1. Run `python app/ai/morning.py --print`. 2. Analyze collected news, KIS flow, sectors, and ticker-specific news. 3. Write `data/daily_context.json`. 4. Send the morning Discord summary. 5. Do not start the bot. Startup belongs only to `scripts/run_morning.ps1`. ### `/midday` 1. Run `python app/ai/midday.py --print`. 2. Compare morning context with actual morning trades and market snapshot. 3. Write `data/midday_context.json`. 4. Send the midday Discord summary. ### `/evening` 1. Run `python app/ai/evening.py --print`. 2. Review trades, win rate, PnL, fees, exit distribution, overtrading, AI filter quality, and execution quality. 3. Write `reports/daily/YYYY-MM-DD.md`. 4. If a strategy change is justified, write `reports/proposals/YYYY-MM-DD_strategy_proposal.md`. 5. Do not directly edit runtime strategy/config/risk/execution code during evening review. 6. Check live-readiness criteria. 7. Send a concise Discord summary. ### `/start-bot` 1. Run `python scripts/start_bot.py`. 2. The script stops existing PID-file and scanned `app/main.py` processes. 3. It starts exactly one detached `app/main.py` process. 4. It writes `logs/bot.pid` and sends the Discord start notification. ## Important Files ```text app/main.py Main trading loop and runtime orchestration app/config.py Strategy parameters app/strategy/volatility_breakout.py Entry/exit signal logic app/risk/manager.py L1-L5 risk controls and L3-B sizing app/execution/kis_client.py KIS REST/WebSocket wrapper app/execution/order_executor.py Order execution and trade persistence app/db/models.py SQLite schema app/db/repository.py DB access helpers app/ai/morning.py Morning data collection app/ai/midday.py Midday data collection app/ai/evening.py Evening data collection scripts/start_bot.py Deterministic single-bot startup scripts/run_morning.ps1 Scheduler morning job scripts/run_midday.ps1 Scheduler midday job scripts/run_evening.ps1 Scheduler evening job scripts/run_training_pipeline.ps1 Training pipeline ``` ## Edit Boundaries Freely editable when the task calls for it: - `app/config.py` - `app/strategy/volatility_breakout.py` - `app/risk/manager.py` - `reports/` - Documentation files Requires explicit user approval: - Structural changes to `app/main.py` - `app/execution/` - `app/db/` - Database schema changes - Real-cash trading behavior Never edit or commit: - `.env` - token files - runtime DB files - runtime logs - `logs/stockbot.lock` - files the user says they are currently editing Never change: - `FORCE_EXIT = "14:50"` - stop-loss priority over profit-taking ## Git Rules - Branch: `master`. - Remote: `origin` on the NAS Gitea server. - After file edits, commit and push to `origin master` without asking again, unless the user says not to. - Commit message format: `[YYYY-MM-DD] concise Korean or English summary`. - Stage only the intended files. Do not include `.env`, runtime logs, lock files, token files, DB files, or user-in-progress data files. ## Risk Controls | Level | Condition | Action | |---|---|---| | L1 | Single trade hits stop-loss | Exit immediately | | L2 | Daily loss reaches -3% | Stop new entries for the day | | L3-B | Consecutive stop-losses | Reduce position size, no full stop | | L4 | Weekly loss reaches -7% | Stop until weekend review | | L5 | Monthly loss reaches -15% | Retire strategy and review | L3-B sizing: | Consecutive stop-loss count | Position multiplier | |---|---| | 0 | 1.0x | | 1 | 0.7x | | 2 | 0.5x | | 3+ | 0.3x | ## Live-Cash Readiness All conditions must pass before real-cash mode: - At least 30 trading days of operation. - Recent 30-day win rate above 48%. - Recent 30-day MDD better than -10%. - Recent 30-day Sharpe above 1.0. - L3-B minimum multiplier events no more than twice per month. If all pass, create `reports/live_ready/YYYY-MM-DD_READY.md` and send Discord notification. Switching to real-cash mode requires manual `.env` changes: `KIS_MOCK=false`, `DRY_RUN=false`. ## Next Checks - Verify the next morning run has exactly one `/morning` context generation and one `scripts/start_bot.py` startup. - Fix the holiday training pipeline so market holidays end as clean skips. - Move tracked webhook/credential material into environment variables and rotate anything exposed. - Continue WebSocket migration planning. - Continue NAS Docker migration planning.