# Trading bot: week summary, Mon 9/21 – Fri 9/25 2026

Everything added, changed and fixed this week, what is live now, what is built but switched off, and what's still open. Paper-trading account. All times are ET. Daily detail is in `reports/2026-09-23_session_summary.pdf` and `reports/2026-09-24_session_summary.pdf`; Friday's report comes after tonight's backtest.

## 1. The week's live results
| Day | Trades | Winners | P/L | What was running |
|---|---|---|---|---|
| Mon 9/21 | 25 | 7 | −$344.39 | Old rules; 1/4 giveback not yet built; a wash-trade bug left UUUU untracked overnight |
| Tue 9/22 | 11 | 3 | −$132.00 | Bot crashed at 10:49 (bug, fixed that evening) |
| Wed 9/23 | 68 | 20 | −$379.57 | 3× ATR stop + 1/4 giveback; slope rule on from 11:10; 6→5 slots |
| Thu 9/24 | 8 | 2 | −$80.52 | **Trade plan** live; context rules switched on at 11:52 |
| Fri 9/25 | 2 | 1 | **−$26.99** | Plan + context rules + real-level targets + early rescan; restarted at 10:05 for the data-bug fix |
| **Week** | **114** | **33** | **−$963.47** | Equity **$8,807.72** |

**Trend over the week:** far fewer, more selective trades. Daily losses went from **−$380 on 36–68 trades a day** to **−$27 to −$81 on 2–8 trades a day** once the trade plan and context rules were live (Thu/Fri).

## 2. Timeline: what changed each day
### Tuesday 9/22 (evening review)
- **Bugs fixed:** the bot crash at 10:49 (`deque mutated during iteration`), fixed with a per-symbol lock in `stream.py` plus a loop that logs errors and keeps running instead of stopping; the UUUU orphan (a wash-trade rejection was mistaken for a close) in `position_manager.py`; and the **hard stop, which could never fire** because it was recalculated from the current price every check. It now uses the stop set at entry.
- **Exit:** the 1/4 giveback from the peak became live (`giveback_room.giveback_ratio` 2/3 → 0.25, active after a +15¢ peak).
- **Entry:** the entry-quality score went live (minimum 55), and the entry stop was widened from 1.2× to **3× the 1-minute ATR**.

### Wednesday 9/23
- **5-bar slope rule** built, backtested and **switched on** at 11:10. It was later switched off on 9/24, because it conflicts with pullback buys.
- **`max_positions` 6 → 5**, and the **per-position cap 20% → 19%**, so all positions fit in buying power.
- **30-minute rescan** of the top-30 list, plus two stream bugs fixed (symbols added mid-session were never subscribed; a reconnect resubscribed the morning list only).
- **Built:** the resistance-stall exit, the per-tick **trade plan** (`setup_analyzer.py`), the volatility-based minimum stop, the re-entry-after-loss rule, and the context-dependent entry rules.
- **Testing method changed at your direction:** exits and entries are now tested **separately**. Exit tests replay the same entries with each exit rule (`--fixed-entries`). Entry tests take every signal with the same exit (no slot limit).
- **Findings:** the exit isn't the main leak (tighter profit protection cut big winners more than it saved); entry selection is. R:R ≥ 1.5 protects the plan: every loosening lost money.

### Thursday 9/24
- **Trade plan live** (it replaces the imbalance and entry-score final checks), with the **re-entry rule (`above_entry`)**, the **stall exit at 45 min**, and a **stop floor of 0.25× daily ATR**. The slope rule was off.
- **Mid-day switch** to the context rules (morning without them: −$100; afternoon with them: +$19).
- **Missed-opportunity review** of all 87 stocks watched (DNA, GRML and others).
- **Bug found:** midday rescans saved "high so far today" as the **premarket high**.
- **Built:** real-level targets (never the high of day), reclaim breakouts (no effect, left off), and an optional early rescan.

### Friday 9/25
- **Switched on before the open:** **real-level targets**, **true premarket high**, and an **extra rescan at 9:40**.
- **Big data bug fixed and live since 10:05:** every **9:28 opening scan** used price data from **two sessions back** (previous-day high, close and volume), so the gap, RVOL and volume filter were wrong every morning since the bot started. JAGX showed a 1% gap that was really 44%. Also fixed: stocks with no premarket trades now get **no** premarket high.
- **Built (off):** your **3–5% above-open entry limit**, your **low-ceiling rule** for the stall exit, **dead-money** detection, and **recent-trend deterioration**.
- **Position charts page** built for the report app (live, every 5 seconds, iPhone and desktop).
- **Opening-window dataset:** 20 days of 9:25–10:00 one-minute bars for every stock that met the universe rules.

## 3. What is live now (for Monday's 9:25 start)
| Area | Setting |
|---|---|
| Watchlist | Top 30 at 9:28 (**correct previous-day data now**), **rescan at 9:40**, then every 30 min until 15:15; true premarket highs |
| Stage 1 | Above VWAP, VWAP not falling, spread ≤ 1%, trend not negative, no 4-bar lower highs/lows, volume pace ≥ 0.4× (slope rule **off**) |
| Hold | 18 seconds of continuous Stage 1 passes |
| Final entry check | **Trade plan**: breakout (first close through a real level on ≥ 1.5× volume) or pullback (rising lows, buy zone, green bar), **R:R ≥ 1.5**, target reachable in the time left, **real-level targets**, **context rules on** (breakout slope; pullback reclaim, fading selling, support, imbalance) |
| Re-entry | After a losing trade, only above that trade's entry |
| Stop | Under the last pivot low, at least **0.25× daily ATR** and 2× the spread |
| Size | 1% risk, capped at **19%** of equity per position, **5 slots** |
| Exits (first to fire) | **1/4 giveback** after a +15¢ peak; **stall exit** at 45 min (+10 if building); hard stop; imbalance exit; deterioration (2 of 4 signs, 3 checks); sell everything at 15:55 |

## 4. Built this week, switched OFF
| Feature | Setting | Status |
|---|---|---|
| 3–5% above-open entry limit (your rule) | `smart_engine.max_extension_from_open` | Tonight's backtest (variants C, D) |
| Low-ceiling sell once the stall exit is armed (your rule) | `resistance_stall.low_ceiling_enabled` | Tonight's backtest (B, D, F) |
| Dead money (90 min, ≤ 1% range) | `resistance_stall.dead_money_minutes` | Tonight's backtest (F) |
| Recent-trend deterioration (30 bars) | `exit.deterioration_trend_bars` | Tonight's backtest (E) |
| 5-bar slope rule | `smart_engine.entry_slope_rule` | Off: conflicts with pullbacks |
| Reclaim breakouts | `setup_plan.reclaim_breakouts` | Off: no effect in tests |
| Breakout stop under the broken level | `setup_plan.breakout_stop: level` | Off: tested worse |
| Faster first-hour rescans | `scanner.rescan_interval_first_hour_minutes` | Off (only the 9:40 rescan is on) |
| Breakeven lock / giveback without slope | `giveback_room.breakeven_lock_cents`, `require_slope` | Off: tested worse |
| Tiered stop floor | `smart_engine.min_stop.style: tiers` | Off (k = 0.25 is live) |

## 5. Bugs found and fixed this week
| Bug | Effect | Fixed |
|---|---|---|
| Stream/monitor race (`deque mutated`) | Bot crashed at 10:49 on 9/22 | 9/22 |
| Wash-trade rejection read as a close | UUUU left untracked overnight | 9/22 |
| Hard stop recalculated from the current price | The stop could never fire | 9/22 |
| Symbols added mid-session never subscribed; reconnect used the morning list | Rescan couldn't work | 9/23 |
| Simulator reset the stop to 1.2× when `--min-entry-score` was passed | Misleading backtests | 9/23 |
| Rescans saved the high so far today as the premarket high | Fake resistance levels | 9/24 (fix on 9/25) |
| **Opening scan used data from two sessions back** | Wrong gap, RVOL, volume filter and previous-day high **every morning** | **9/25, live** |
| No-premarket stocks got the high so far today as their premarket high | Fake levels (WNC, MAAS, RES) | 9/25, live |

## 6. Tools and reports built
- **Simulator (`simulate.py`):** exit isolation (`--fixed-entries`), entry isolation (`--max-positions 99`), **rescan replay** (`--watch-windows`), peak and giveback metrics per trade, plus a flag for every new rule.
- **Position charts page:** `http://68.183.154.175/trade/report/positions.php`.
- **Opening-window dataset:** `reports/open_window/`, with 166,716 bars. Only 34 of 107 early 5%+ runners were in the (buggy) 9:28 top-30 list.
- **Daily reports:** 9/23 and 9/24 summaries (PDF); Friday's comes tonight.

## 7. Key findings this week
- **Entry selection matters more than the exit.** Holding every trade longer helps on some days (9/24) and hurts on others (9/18–9/23). The current giveback plus the stall exit is the best exit tested so far.
- **Buying back a stock after it just gave a loss** was the biggest single leak. The re-entry rule fixed most of it.
- **R:R ≥ 1.5** keeps the plan out of bad trades; every loosening lost money.
- **Targets must be real levels.** The high of day as a target blocked good morning runs (DNA).
- **The 9:28 scan was ranking on stale data** until Friday. From Monday the opening list should be better.

## 8. Open items
1. **Tonight's backtest (4:12 PM):** decide on the above-open limit, low-ceiling, dead-money and recent-trend options.
2. **Security, deferred by you until go-live:** the web server exposes the bots' `.env` files (outside IPs downloaded them on 9/11–9/18 and 9/25), data and logs; no dashboard password. **Before go-live:** block those paths, **rotate the Alpaca keys**, set `REPORT_PASSWORD`.
3. The stock's volatility class uses its daily ATR, which understates stocks whose price doubled overnight (INLF).
4. Very fast runners (JAGX +19% in 10 minutes) are hard for the current rules to catch; worth a study with the opening-window dataset.
5. More live days are needed. Most tuning so far is on 5–6 days, much of it in-sample.
