Sydnee Agent (AI)
Apr 20 4:20 AM
Sydnee nightly — entry_flow audit 2026-04-20 — 0P0 3P1 2R
Sydnee Agent (AI): Sydnee nightly — entry_flow audit 2026-04-20 — 0P0 3P1 2R
Sydnee Agent (AI)
Apr 19 10:31 PM
Sydnee algo — time-gate backtest: +$20K/wk expected on prod
Sydnee Agent (AI): Sydnee algo — time-gate backtest: +$20K/wk expected on prod
Sydnee Agent (AI)
Apr 19 7:50 PM
RE: Can you put a pause toggle in footer?
Sydnee Agent (AI): RE: Can you put a pause toggle in footer?
Sydnee Agent (AI)
Apr 19 7:45 PM
RE: Can you put a pause toggle in footer?
Sydnee Agent (AI): RE: Can you put a pause toggle in footer?
Sydnee Agent (AI)
Apr 19 7:44 PM
RE: Can you put a pause toggle in footer?
Sydnee Agent (AI): RE: Can you put a pause toggle in footer?
Sydnee Agent (AI)
Apr 19 7:41 PM
RE: Can you put a pause toggle in footer?
Sydnee Agent (AI): RE: Can you put a pause toggle in footer?
Sydnee Agent (AI)
Apr 19 7:40 PM
RE: Can you put a pause toggle in footer?
Sydnee Agent (AI): RE: Can you put a pause toggle in footer?
Sydnee Agent (AI)
Apr 19 7:33 PM
RE: Pause trading
Sydnee Agent (AI): RE: Pause trading
Sydnee Agent (AI)
Apr 19 7:24 PM
RE: Pause trading
Sydnee Agent (AI): RE: Pause trading
Sydnee Agent (AI)
Apr 19 5:40 PM
RE: Pause trading
Sydnee Agent (AI): RE: Pause trading
Sydnee Agent (AI)
Apr 19 5:38 PM
RE: Pause trading
Sydnee Agent (AI): RE: Pause trading
Sydnee Agent (AI)
Apr 19 5:32 PM
RE: Pause trading
Sydnee Agent (AI): RE: Pause trading
Sydnee Agent (AI)
Apr 19 5:21 PM
RE: Dev down?
Sydnee Agent (AI): RE: Dev down?
Sydnee Agent (AI)
Apr 19 5:21 PM
RE: Dev down?
Sydnee Agent (AI): RE: Dev down?
Sydnee Agent (AI)
Apr 19 11:54 AM
Sydnee WEEKLY (cross-cutting) audit 2026-04-19 — 2P0 11P1 0R
Sydnee Agent (AI): Sydnee WEEKLY (cross-cutting) audit 2026-04-19 — 2P0 11P1 0R
Sydnee Agent (AI)
Apr 19 11:54 AM
Sydnee nightly — persistence audit 2026-04-16 — 0P0 2P1 3R
Sydnee Agent (AI): Sydnee nightly — persistence audit 2026-04-16 — 0P0 2P1 3R
Sydnee Agent (AI)
Apr 19 11:54 AM
Sydnee nightly — config_drift audit 2026-04-19 — 0P0 3P1 2R
Sydnee Agent (AI): Sydnee nightly — config_drift audit 2026-04-19 — 0P0 3P1 2R
Sydnee Agent (AI)
Apr 19 11:54 AM
Sydnee nightly — execution audit 2026-04-17 — 1P0 2P1 2R
Sydnee Agent (AI): Sydnee nightly — execution audit 2026-04-17 — 1P0 2P1 2R
Sydnee Agent (AI)
Apr 19 1:35 AM
RE: Test
Sydnee Agent (AI): RE: Test
Sydnee Agent (AI)
Apr 19 1:30 AM
Sydnee algo — 12mo signal-replay: baseline $+83,320 · full-flag sim unreliable (read caveats)
Sydnee Agent (AI): Sydnee algo — 12mo signal-replay: baseline $+83,320 · full-f
Sydnee Agent (AI)
Apr 19 1:16 AM
Sydnee algo daily — dev $-35,649 · prod $+0 · 6d window
Sydnee algo daily report: dev environment -$35,649 loss, 6-day window.
Sydnee Agent (AI)
Apr 19 1:15 AM
Sydnee algo daily — dev $-35,649 · prod $+0 · 6d window
Daily Sydnee algo performance report: dev down $35.6k, prod flat.
Sydnee Agent (AI)
Apr 19 1:09 AM
Sydnee algo — 3-week market-data replay findings
Sydnee algo market-data replay results for 3-week period ending Apr 17.
Sydnee Agent (AI)
Apr 19 1:09 AM
Sydnee agent test — Graph send from [email protected]
Sydnee agent test confirmation — Graph email delivery working.
Sydnee nightly — entry_flow audit 2026-04-20 — 0P0 3P1 2R
AI verdict
personal
normal
· confidence: high
· by self-identity
“Sydnee Agent (AI): Sydnee nightly — entry_flow audit 2026-04-20 — 0P0 3P1 2R”
Reasoning: sender is one of Kelvin's own addresses (me_identities), phishing check passed
Sydnee nightly — entry_flow audit — 2026-04-20
P0 findings: 0 P1 findings: 3 Risks: 2
- Area: Entry Flow (Monday theme — signal detection, time gates, RV gate, sizing, pullback path)
- Files scanned: `bot.py` (13 211 lines), `docs/strategy_decisions.md`, `CLAUDE.md`
- Branch: `dev` (ccf1e9c)
- Bugs found (P0 / P1): 0 / 3
- Risks noted: 2
---
Full report (dev branch): https://github.com/kanex1/sydnee.signals/blob/dev/docs/audit_2026-04-20_entry_flow.md
Reply FROM [email protected] to [email protected] to request fixes, e.g.:
"code_task on sydnee-signals-dev: apply fix for the P0 about RVOL threshold in bot.py"
Sydnee Agent will propose + you APPROVE (or plain 'approve') + auto-push to dev.
--- Full audit below (first 12 KB) ---
# Nightly Audit 2026-04-20 — ENTRY FLOW
## Summary
- Area: Entry Flow (Monday theme — signal detection, time gates, RV gate, sizing, pullback path)
- Files scanned: `bot.py` (13 211 lines), `docs/strategy_decisions.md`, `CLAUDE.md`
- Branch: `dev` (ccf1e9c)
- Bugs found (P0 / P1): 0 / 3
- Risks noted: 2
---
## Findings
### BUG [P1]: Overnight gap gate bypassed by pending pullback
**File:** `bot.py:4034–4091` (`_check_pullback`), vs gate at `bot.py:3589–3595`
**Evidence:**
The overnight-gap gate (00:50–01:00 PT / 3:50–4:00 AM ET) lives exclusively in
`_evaluate_symbol` and blocks signal creation:
```python
# bot.py:3589-3595
in_overnight_gap = 3 * 60 + 50 <= t_min < 4 * 60
if in_overnight_gap:
self._log_activity(sym, "CUTOFF: ... blocked 3:50-4:00 AM ET ...")
return
```
`_check_pullback` (called every 1m bar from the bar handler, line 2195–2196) has
**no time-gate check**. It fires unconditionally when `ss.pending_pullback` is set.
Attack path:
1. `rsi_extreme` signal fires at 00:48 PT — `_evaluate_symbol` gate passes (gap
not yet started), `ss.pending_pullback` is set.
2. At 00:50 PT the gap opens. `_evaluate_symbol` now blocks new signals.
3. 1m bar ticks at 00:51 PT → `_check_pullback` fires → RSI / VWAP condition
met **or** 3-min `PULLBACK_TIMEOUT_SEC` triggers → deferred to
`_deferred_trades` → `_open_trade` (no time gate) → trade opens during the
gap.
The same bypass applies to the RTH-open 30-min gate (`in_open_30`, 9:30–10:00
AM ET / 06:30–07:00 PT) for any signal that straddles the boundary, though BXt
and divergence are already blocked off-hours so only `rsi_extreme` is at risk.
**Impact:** `rsi_extreme` entries can open during the IBKR overnight-session
closing window — a deliberately thin tape with wide spreads and increased
slippage risk. One realistic scenario per night.
**Fix:** Add a time-gate at the top of `_check_pullback`:
```python
now_et = datetime.now(ET)
t_min_pb = now_et.hour * 60 + now_et.minute
in_gap = 3 * 60 + 50 <= t_min_pb < 4 * 60
if in_gap:
# Don't cancel the pending — let it survive to fire right after gap closes
return
```
---
### BUG [P1]: Stale `midday_bxt` monitor counter — gate never implemented, counter always 0
**File:** `bot.py:9893` and `bot.py:10194` (monitor SQL / regex map)
**Evidence:**
The monitor API tracks a `midday_bxt` bucket that counts activity-log messages
matching `MIDDAY FILTER|MIDDAY BLOCK`:
```python
# bot.py:9893 (SQL)
WHEN message ~ 'MIDDAY FILTER|MIDDAY BLOCK' THEN 'midday_bxt'
# bot.py:10194 (regex fallback)
"midday_bxt": r'MIDDAY FILTER|MIDDAY BLOCK',
```
A grep of the entire file for those strings shows **zero matching
`_log_activity` calls** — no code path emits `MIDDAY FILTER` or `MIDDAY BLOCK`.
`CLAUDE.md` documents a BXt block from 08:30–10:30 PT ("midday low-conviction
window"), but `strategy_decisions.md` (the single source of truth) says
"BXt/div restricted to 07:00–12:00 PT" — no midday sub-block. The actual time
gate in code (bot.py:3589–3604) likewise has no 08:30–10:30 BXt window.
The counter was added in anticipation of a gate that was never built.
**Impact:** `/api/monitor` `midday_bxt` is permanently 0. Any ops or backtesting
tooling that checks this field to confirm BXt midday filtering is working will
silently see a false-zero. If the gate is ever needed and added, the SQL pattern
is ready — but right now it's dead weight with misleading semantics.
**Fix (two options — pick one):**
- *Delete* the `midday_bxt` counter entirely (SQL + regex) until the gate is
actually implemented.
- *Implement* the 08:30–10:30 PT BXt block in the time-gate section
(bot.py:3589–3604) and emit the expected log message, resolving the
CLAUDE.md/code discrepancy at the same time.
---
### BUG [P1]: RV gate `fail-open` comment contradicts actual fail-closed behavior
**File:** `bot.py:3864` (comment) vs `bot.py:3888–3890` and `bot.py:3914–3916`
**Evidence:**
```python
# bot.py:3864 — comment claims fail-open
# POLYGON_API_KEY presence only; fail-open if unavailable.
# bot.py:3888-3890 — actual behavior: fail-CLOSED on None rv
if rv is None:
self._log_activity(sym, f"… RV unavailable …")
continue # ← skips entry
# bot.py:3914-3916 — fail-CLOSED on exception
except Exception as e:
logger.warning("RV check failed … — blocking entry (fail-closed)", ...)
continue # ← skips entry
```
`strategy_decisions.md` (2026-04-14 RV gate overhaul) explicitly says "fail-closed on `rv is None` for all triggers" — confirming the code behaviour is intentional. The `logger.warning` text even says `fail-closed`. The module-level comment at 3864 was never updated from the original fail-open design.
**Impact:** Low probability today — POLYGON_API_KEY is set on dev. Risk is on
future maintenance: a developer reading the comment could "fix" the `continue`
to a pass (restoring fail-open), allowing zero-RV blowoff trades to leak
through and recreating the AVGO/NET post-market losses from 2026-04-14.
**Fix:** Change bot.py:3864 comment:
```python
# fail-closed when POLYGON_API_KEY is set: rv is None or exception → block entry.
# fail-open when key is absent (no Polygon subscription configured).
```
---
### RISK: CLAUDE.md entry-gate table contradicts strategy_decisions.md on BXt windows
**File:** `CLAUDE.md` (Entry Time Blockers table) vs `docs/strategy_decisions.md`
(2026-04-14 time gates entry)
**Evidence:**
`CLAUDE.md` states:
```
| 08:30 – 10:30 | BXt blocked (midday low-conviction window) | BXt only |
Net effect: BXt effectively runs 06:30–08:30 and 10:30–12:00 PT.
```
`strategy_decisions.md` states:
```
07:00-12:00 PT: all triggers allowed
BXt/div restricted to 07:00-12:00 PT
```
The code (bot.py:3589–3604) matches `strategy_decisions.md` — BXt is allowed
the full 07:00–12:00 PT window; there is no 08:30–10:30 sub-block.
**Risk:** Kelvin or a future dev reads CLAUDE.md and expects BXt to be filtered
midday. Discrepancy could cause confusion during real-money go-live review
(2026-04-29) or when debugging unexpected midday BXt trades. The stale
`midday_bxt` counter (P1 above) amplifies this risk — it looks like the gate
was wired but just isn't firing.
---
### RISK: `_rsi_ext_pending_dir` and peak-confirm state not persisted across restarts
**File:** `bot.py:3468` (`_rsi_ext_pending_dir`), `bot.py:2384–2511` (peak-confirm machine)
**Evidence:**
Both the 1m BXt bias pending direction and the peak-confirm tracking state
(`_peak_tracking_dir`, `_peak_rsi`, `_peak_obv`, `_peak_bar_ts`, etc.) live
only in `SymbolState` in-memory attributes. A container restart mid-RTH
silently drops all in-flight state:
- An armed peak-confirm (RSI reached 75+, tracking for OBV reversal) is lost
→ next signal requires a fresh cycle, missing the fire window.
- A pending RSI extreme direction (`_rsi_ext_pending_dir = 1`) is lost →
next signal bar enters at full size instead of the intended 50% micro_scale.
**Risk:** The `OBV_BE_STOP` datetime.fromisoformat bug (fixed commit `782e3b6`,
noted in strategy_decisions.md) showed that silent no-ops can run undetected for
hours. A restart during a live peak-confirm tracking session would leave no trace
in logs — no error, no "state reset" message.
With real-money go-live on 2026-05-01, container restarts during RTH carry
higher consequence.
---
### OK (checked, working or recently fixed):
- **`total_scale` applied in `_open_trade`** (bot.py:4517–4519): fix from
commit `a6be962` confirmed. All multipliers (sentiment, bias, regime, div,
signal-weight, late-session, micro) flow through `total_scale` and are
applied via `shares = int(shares * total_scale)`.
- **RV gate fail-closed on `rv is None`**: behavior is correct (entry blocked);
only the comment is wrong (see P1 above).
- **RV blowoff ceiling**: `rv_10m > 5.0` for rsi_extreme at bot.py:3909. Config
drift audit (2026-04-19) noted CLAUDE.md still shows 2.0x — not re-filed.
- **Off-hours gate** (outside 06:30–13:00 PT): bot.py:3602 correctly blocks
BXt/div, allows rsi_extreme.
- **RTH opening-30 gate** (06:30–07:00 PT): bot.py:3596 blocks non-rsi_extreme.
- **Close-hour gate** (12:00–13:00 PT): bot.py:3599 blocks non-rsi_extreme.
- **Overnight gap gate** (00:50–01:00 PT): bot.py:3593 — works for new signals;
pullback bypass is the P1 bug above.
- **Session-aware RSI thresholds** (`_rsi_os`: 20 RTH / 15 off-hours; `_rsi_ob`:
85): bot.py:3465–3467 ✓.
- **1m BXt bias gate** (pending + 50% size on second consecutive adverse bar):
bot.py:3531–3552 ✓.
- **Size caps**: 0.10× close-hour, 0.25× off-hours: bot.py:3735–3741 ✓.
- **Pullback dedup** (skip if pullback already pending): bot.py:3843–3845 ✓.
- **OBV_BE_STOP `entry_time` datetime parse fix** (commit `782e3b6`): no
recurrence of `'str' object has no attribute 'tzinfo'` expected.
- **RSI_TRIM_PROFIT_GUARD**: prevents stop from moving above current price on a
losing position: bot.py:2927 ✓.
- **`_pending_entries` dedup / enter-strongest-only**: bot.py:3829–3837 ✓.
- **FLAT_EXIT, HOLD_CAP_MIN, OBV_LOSS_EXIT**: feature-flagged, checked for env
var presence — no issues with flag wiring.
- **RV gate exception path logs correctly**: bot.py:3915 emits `fail-closed`
in warning — monitoring can grep for it.