Interactive Brokers Client Services
Jun 17 12:40 AM
Message Center Notification
Interactive Brokers ticket response regarding Kanex account messaging.
Joaquín Medina
Jun 17 12:34 AM
RE: Re:[## 708 ##] RE: RMA for EXT-4KHD70M
AVIT Vision requests credit memo for destroyed equipment per RMA 708.
Microsoft Outlook
Jun 16 10:36 PM
Undeliverable: FW: TIER 3 Trending Stocks Part 2 (1 New Red Candle): $DELL, $OSCR, $ONDS, $ZETA, $LMND and $TMC (June 17, 2026-daily)
Microsoft Outlook: Undeliverable: FW: TIER 3 Trending Stocks Part 2 (1 New Red
Interactive Brokers Client Services
Jun 16 9:59 PM
Security Notice for User k******8: Verify Log In
Fake Interactive Brokers security alert requesting account verification.
Microsoft Outlook
Jun 16 9:38 PM
Undeliverable: FW: $QCOM (June 17, 2026-daily)
Microsoft Outlook: Undeliverable: FW: $QCOM (June 17, 2026-daily)
TDhruv Sharma
Jun 16 9:05 PM
[Teams oneOnOne] (Teams DM)
Dhruv Sharma: [Teams oneOnOne] (Teams DM)
Fabiola Hernandez
Jun 16 6:55 PM
Tomorrow is Spirit Day – Souvenir T-Shirt Day
Spirit Day reminder: kids invited to wear souvenir t-shirt tomorrow at camp.
Derrick
Jun 16 6:19 PM
Request for More Info: EXT-USBC2XI-100M - Dual-Host USB 3.2 Gen 1 Extender over CAT6a — USB-C & USB-B Inputs, 100m/328ft
Product inquiry for USB extender; requesting pricing, specs, availability.
Sydnee Agent (AI)
Jun 16 6:00 PM
[Spread Cal] 2026-06-17 — per-stock max_spread_bps results
Sydnee Agent (AI): [Spread Cal] 2026-06-17 — per-stock max_spread_bps results
Sydnee Agent (AI)
Jun 16 5:40 PM
[Calibration Daily] 2026-06-17
Sydnee Agent (AI): [Calibration Daily] 2026-06-17
Sydnee Agent (AI)
Jun 16 5:30 PM
Sydnee algo daily — dev $-2,699 · prod $+0 · 6d window
Sydnee Agent (AI): Sydnee algo daily — dev $-2,699 · prod $+0 · 6d window
Find My
Jun 16 5:24 PM
A sound was played on Kelvin’s iPad mini.
Find My: A sound was played on Kelvin’s iPad mini.
Sammy Cemo, Matt Pourcho and Anthony DeLorenzo
Jun 16 4:04 PM
New Pricing | Fortune 40 Credit | STNL Industrial | 11 Yr. WALT | SoCal
⚠ PHISHING: employee impersonation: display name matches 'anthony' but sender is cbre.com
Microsoft Store
Jun 16 3:23 PM
Meet the new Surface lineup—with limited-time offers
Microsoft Store: Meet the new Surface lineup—with limited-time offers
[email protected]
Jun 16 2:34 PM
New Funding Program
Funding broker offering working capital solutions and consolidation services.
Sammy Cemo and Anthony DeLorenzo
Jun 16 2:03 PM
Single-Story Owner-User Offering in Newport Beach
⚠ PHISHING: employee impersonation: display name matches 'anthony' but sender is cbre.com
Aarti Gupta
Jun 16 1:53 PM
Re: CR-TOUCH6R 6" Widescreen Touch Panel with Knob, RS232/RS485 & PoE
Aarti Gupta: Re: CR-TOUCH6R 6" Widescreen Touch Panel with Knob, RS232/RS
[email protected]
Jun 16 1:43 PM
Action required: Your June booking bonuses expire soon
⚠ PHISHING: phishing subject pattern: 'Action required' from external sender vacationoffer.com
TAnthony Patino
Jun 16 1:30 PM
[Teams oneOnOne] (Teams DM)
LK account overdrawn; bank fee applied, needs replenishment before QB charge.
TAnthony Patino
Jun 16 1:27 PM
[Teams oneOnOne] (Teams DM)
Anthony Patino sent a brief Teams DM referencing 'LK'.
TAnthony Patino
Jun 16 1:27 PM
[Teams oneOnOne] (Teams DM)
Anthony Patino reports insufficient funds issue.
Amazon Payments
Jun 16 12:44 PM
Action requise sur le compte Amazon Payments
Fake Amazon Payments suspension notice in French requesting account verification.
Nick Daniel
Jun 16 11:04 AM
Quick question
TriNet HR solution sales inquiry.
Aarti Gupta
Jun 16 10:04 AM
Re: Order help #1227
Aarti Gupta: Re: Order help #1227
Aarti Gupta
Jun 16 10:03 AM
Re: Order help #1227
Aarti Gupta: Re: Order help #1227
Aarti Gupta
Jun 16 9:59 AM
EXT-USBCPD4K-70M 18Gbps USB-C 4K60 HDBaseT 3.0 Extender with 100W PD (70m)
Aarti Gupta: EXT-USBCPD4K-70M 18Gbps USB-C 4K60 HDBaseT 3.0 Extender with
Sean McGinley
Jun 16 9:58 AM
Order help #1227
Customer inquiry about HDMI extender transmitter compatibility for order #1227.
IBKR FYI
Jun 16 9:51 AM
FYI: Upcoming Exchange Holidays
Exchange holiday notice: MIAX, NASDAQ, NYSE closed June 19.
IBKR FYI
Jun 16 9:27 AM
FYI: Upcoming Exchange Holidays
NASDAQ/MIAX exchange holiday June 19, 2026 — no trading.
Hims
Jun 16 9:02 AM
Kelvin - action required on your account
⚠ PHISHING: phishing subject pattern: 'action required' from external sender icloud.com
[email protected]
Jun 16 9:02 AM
You have a new estimate
Suspicious medical estimate link from Providence—verify legitimacy before clicking.
Mail Delivery System
Jun 16 8:20 AM
Mail delivery failed [Invoice #36077 PO: SH260526762J]
Mail delivery failed for invoice #36077 to Mike Vanderkamp; recipient address rejected.
Mail Delivery System
Jun 16 8:19 AM
Mail delivery failed [Invoice #36078 PO: SH260430677J]
Mail delivery failed: [email protected] → [email protected] for invoice #36078.
Mail Delivery System
Jun 16 8:19 AM
Mail delivery failed [Invoice #36079 PO: SH2606101007J]
Mail delivery failure: invoice to [email protected] rejected by recipient server.
TDhruv Sharma
Jun 16 8:16 AM
[Teams oneOnOne] (Teams DM)
Dhruv Sharma: [Teams oneOnOne] (Teams DM)
Zoho Campaigns
Jun 16 7:55 AM
Campaign "NEW USB-C + USB-B Dual-Host Extender · 100m" has been successfully Sent - Zoho Campaigns
Zoho Campaigns notification: USB-C/USB-B extender product campaign sent successfully.
Ali Pacheco
Jun 16 7:53 AM
Request for More Info: EXT-USBC2XI-100M - Dual-Host USB 3.2 Gen 1 Extender over CAT6a — USB-C & USB-B Inputs, 100m/328ft
Product inquiry for USB 3.2 extender from external vendor.
KanexPro
Jun 16 7:51 AM
NEW USB-C + USB-BDual-Host Extender · 100m
KanexPro: NEW USB-C + USB-BDual-Host Extender · 100m
KanexPro
Jun 16 7:50 AM
NEW USB-C + USB-BDual-Host Extender · 100m
KanexPro: NEW USB-C + USB-BDual-Host Extender · 100m
KanexPro
Jun 16 7:50 AM
NEW USB-C + USB-BDual-Host Extender · 100m
KanexPro: NEW USB-C + USB-BDual-Host Extender · 100m
KanexPro
Jun 16 7:49 AM
NEW USB-C + USB-BDual-Host Extender · 100m
KanexPro: NEW USB-C + USB-BDual-Host Extender · 100m
TDhruv Sharma
Jun 16 7:33 AM
[Teams oneOnOne] (Teams DM)
Dhruv Sharma: [Teams oneOnOne] (Teams DM)
TDhruv Sharma
Jun 16 7:32 AM
[Teams oneOnOne] (Teams DM)
Dhruv Sharma: [Teams oneOnOne] (Teams DM)
Bank of America
Jun 16 6:16 AM
Your available account balance is low
Bank of America: Your available account balance is low
Let's Talk Supply Chain
Jun 16 6:01 AM
Are you ready?
Suspicious meeting confirmation from unknown sender with obfuscation.
Interactive Brokers Client Services
Jun 16 5:18 AM
Message Center Notification
Interactive Brokers ticket response regarding Kanex account notification.
Benjamin & Williams
Jun 16 5:03 AM
Commercial Claim Discovery Documents Our file:D-8222 Debtor: VICTORIA ROPA ELEGANTE
Fake debt collector demanding payment on unknown commercial claim within 24h.
IBKR FYI
Jun 16 5:01 AM
FYI: Option Expiration Notification
Oracle options expiring 18JUN2026 — immediate action required.
IBKR FYI
Jun 16 5:00 AM
FYI: Option Expiration Notification
MSTR call option expiring 18JUN2026; action needed if extending position.
Sydnee Agent (AI)
Jun 16 4:25 AM
Sydnee nightly — exit_flow audit 2026-06-16 — 0P0 8P1 6R
Sydnee Agent (AI): Sydnee nightly — exit_flow audit 2026-06-16 — 0P0 8P1 6R
Sydnee nightly — exit_flow audit 2026-05-26 — 0P0 2P1 4R
AI verdict
employee
high
· confidence: high
· by internal-exempt
“Sydnee Agent (AI): Sydnee nightly — exit_flow audit 2026-05-26 — 0P0 2P1 4R”
Reasoning: @sydnee.ai is a protected domain — hard exemption
Sydnee nightly — exit_flow audit — 2026-05-26
P0 findings: 0 P1 findings: 2 Risks: 4
- Area: Exit flow (how and when open positions are closed)
- Bugs found (P0 / P1): 0 / 2
- Risks noted: 4
Branch: `dev` (dc2d9b4). Cross-checked against `git log --oneline -30` and `docs/strategy_decisions.md`.
---
Full report (dev branch): https://github.com/kanex1/sydnee.signals/blob/dev/docs/audit_2026-05-26_exit_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-05-26 — EXIT FLOW
## Summary
- Area: Exit flow (how and when open positions are closed)
- Bugs found (P0 / P1): 0 / 2
- Risks noted: 4
Branch: `dev` (dc2d9b4). Cross-checked against `git log --oneline -30` and `docs/strategy_decisions.md`.
---
## Findings
### BUG [P1]: OBV Rule F permanently disabled after in-loss skip
**File:** `bot.py:4295–4334`
**Evidence:**
```python
if _obv_against:
...
if _new_stop != _cur_stop:
if _profit_guard and profit_per_share < 0:
# In-loss path — skip BE-tighten
if _loss_exit:
hit = True
elif not getattr(t, '_obv_be_applied', False):
self._log_activity(...)
t._obv_be_applied = True # ← set regardless (line 4332)
self._update_trade_field(..., obv_be_applied=True)
else:
# In-profit path — tighten stop
...
t._obv_be_applied = True
```
The outer guard at line 4265–4266 is `not getattr(t, "_obv_be_applied", False)`. Once `_obv_be_applied = True` is set, Rule F is permanently skipped for that trade's lifetime. The in-loss path (profit guard) sets this flag WITHOUT tightening the stop — consuming the one-shot protection.
**Scenario that breaks:** Trade enters, goes underwater, OBV turns adverse → profit guard fires, flag is set, stop unchanged. Trade recovers to profit later. OBV remains adverse or turns adverse again. Rule F never fires. The wide entry stop defends until it's hit or another exit fires.
**Impact:** Missing OBV-based stop tighten for trades that temporarily go in-loss before recovering. The Rule F protection intended to cut `bxt_reversal` damage (−$774 → −$217 avg in the original backtest) is silently disabled for these trades.
**Fix:** Move `t._obv_be_applied = True` inside the `else:` branch (in-profit, tighten fired). In the in-loss case, log and skip without consuming the flag:
```python
if _profit_guard and profit_per_share < 0:
if _loss_exit:
hit = True
...
else:
self._log_activity(...) # no-op for this bar only
# Do NOT set _obv_be_applied — let Rule F retry next bar when profitable
else:
...
t._obv_be_applied = True # only mark applied when stop actually moved
```
Note: OBV_LOSS_EXIT (spot-exit) path still sets the flag because the trade is being closed — that's correct.
---
### BUG [P1]: TRIM2 `_rsi_force_trim2` flag never cleared for 1-share parents
**File:** `bot.py:4728–4762`
**Evidence:**
```python
if not hit and is_trimmed and not is_trimmed_2 and (_trim2_hit or _force_trim2):
trim = True # ← set unconditionally
trim2_shares = t.shares // 2
if trim2_shares > 0: # ← guard
...
t._trimmed_2 = True # ← inside guard
t._rsi_force_trim2 = False # ← inside guard (never clears if shares=1)
self._update_trade_field(t.trade_id, trimmed_2=True, force_trim2_pending=False, ...)
```
When TRIM1 reduces a position to 1 share, `trim2_shares = 1 // 2 = 0`. The `if trim2_shares > 0:` guard prevents the trim from executing. However `t._trimmed_2` and `t._rsi_force_trim2` are inside that guard — they are NOT updated when `trim2_shares == 0`.
**Impact:** On every subsequent bar:
1. `_force_trim2 = getattr(t, '_rsi_force_trim2', False)` returns `True` (never cleared)
2. TRIM2 condition fires: `trim = True` but no close is queued
3. Fruitless re-evaluation until the stop or EOD exits the position
The `force_trim2_pending` column in DB also stays `True`, surviving restarts and re-triggering the same no-op indefinitely. No crash or incorrect close — but CPU wasted every bar and the activity log cannot distinguish "TRIM2 executing" from "TRIM2 stuck at zero-share no-op."
**Fix:** Add an `else` branch to set `_trimmed_2 = True` and clear the force-trim flag when `trim2_shares == 0`:
```python
if trim2_shares > 0:
... # existing logic
else:
# Can't trim (0 shares) — mark done so we don't retry every bar
t._trimmed_2 = True
t._rsi_force_trim2 = False
self._update_trade_field(t.trade_id, trimmed_2=True,
force_trim2_pending=False, force_trim_reason=None)
```
---
### RISK: OBV trail stop unavailable for early pre-market 5m-naked positions
**File:** `bot.py:3517–3556`
**Evidence:**
```python
def _tv_atr_obv(self, ss):
df5 = ss.bars.get(5, pd.DataFrame())
n = len(df5)
if n < 15:
return 0.0, 0 # ← no ATR, no OBV slope
def _obv_trail_stop_hit(self, my_pos, ss, price):
...
atr5, obv_slope = self._tv_atr_obv(ss)
if atr5 <= 0:
return None # ← stop silently disabled
```
15 bars = 75 minutes of 5m data. The 5m-naked BXT engine runs from pre-market open (04:15 ET). For the first 75 minutes, both the catastrophic stop (`catx × ATR`) and the OBV-trail stop are disabled. A position opened at 04:15 ET has no mechanical stop until ~05:30 ET.
**Impact:** Pre-market 5m-naked positions opened in the 04:15–05:30 ET window carry unlimited intra-session loss risk if a gap or fast move occurs. The engine's only protection during this window is the session-boundary force-flat (which only fires at 09:15 ET or the next session gap). This risk increases with the current 3% NLV risk / 15% cap (ca4b173 + b3fedce).
**Mitigation:** Could add a `min_bars_for_entry` guard in `_eval_bxt_1m_naked` that skips new entries (but not exits) when `len(ss.bars.get(5, [])) < 15`. Or gate the `_eval_bxt_1m_all` call to only the RTH + post-market windows where 5m history is sufficient.
---
### RISK: Friday EOD progressive-trim exemption comment is stale/misleading
**File:** `bot.py:3935–3950`
**Evidence:**
```python
# Skip RSI extreme entries from after 12:00 PM PT — keep those intact. # ← stale comment
_is_rsi_trig = _reason_chk.startswith('RSI extreme')
if _is_rsi_trig:
if _et_et2.hour * 60 + _et_et2.minute >= 15 * 60:
continue # skip — late RSI extreme, keep overnight # ← "keep overnight" is removed behavior
```
The comment "keep those intact" and inline `# skip — late RSI extreme, keep overnight` reflect the pre-2026-04-17 behavior (RSI extreme held through the weekend). That exemption was removed in commit 52f1bb1: the 3:50 PM final sweep (bot.py:4003–4020) now closes ALL positions with no exemption.
The current exemption only skips the *progressive 25% trimming* (3:00–3:50 PM window) for late RSI extreme entries. The position still closes at 3:50 PM. This may be intentional (fresh entries shouldn't be trimmed immediately), but the comments are wrong — they still say "keep overnight."
**Impact:** No runtime bug — positions don't actually get held overnight. But the misleading comments create audit ambiguity and could confuse a future developer into thinking the overnight hold is still present.
**Mitigation:** Update comments at bot.py:3935, 3940, 3948 to reflect current behavior: late RSI extreme entries are exempt from progressive trimming but are fully closed at 3:50 PM like all other positions.
---
### RISK: FLAT_EXIT parent closed with empty `exit_reason` in DB
**File:** `bot.py:4845`, `bot.py:1264–1268`
**Evidence:**
```python
# FLAT_EXIT 100% close: parent closed DB-only after IBKR order via child
self._close_trade_in_store(t.trade_id, live_price)
```
```python
def _close_trade_in_store(self, trade_id, exit_price):
...
self.db.close_trade(trade_id=trade_id, ..., exit_reason="") # ← always empty
```
For FLAT_EXIT setups (FLAT_EXIT=true, non-trend), TRIM1 closes 100% of shares via a child trade record (which gets the proper exit reason), and then `_close_trade_in_store` is called on the parent with `exit_reason=""`. The parent's DB row shows a closed trade with no exit reason.
**Impact:** Post-trade analytics (trade review, P&L attribution by exit type) cannot classify FLAT_EXIT parent rows. The SQL regex in `bot.py:12356–12368` uses `exit_reason` matching — these rows fall through to `'other'`. Only the `_trim` child row has the correct reason.
**Mitigation:** Pass the reason into `_close_trade_in_store` as an optional parameter, or update the parent via `db.update_trade(parent_id, exit_reason="FLAT_EXIT parent — see _trim child")` after the child is confirmed.
---
### RISK: `trim3` parent-DB update comment says "no DB column" — now incorrect
**File:** `bot.py:7622–7623`
**Evidence:**
```python
elif trade.trade_id.endswith("_trim3"):
pass # no DB column for trim3 yet — state tracked in-memory
```
The `trimmed_3` column WAS added in the 2026-04-15 persistence fixes (commit `a6be962`, strategy_decisions.md line 344). The column is populated at EXIT 3 (bot.py:4692–4693) before the trim child is queued. The `pass` here is correct (parent already updated), but the comment "no DB column for trim3 yet" is false and could cause confusion.
**Impact:** No runtime impact. But a developer reading this comment might conclude the DB schema is incomplete and try to "fix" it by adding the update here, causing a benign duplicate write.
**Mitigation:** Update comment to: `# trimmed_3 already set via _update_trade_field in EXIT 3 (bot.py:4692) — no second update needed`.
---
## OK (checked, working or recently fixed):
- **FLAT_EXIT trim1 DB-vs-memory discrepancy** — fixed in ff4ac0d (bot.py:6615–6625): monotonicity guard's collapsed trim1 level is restored to `trim_target_price` for FLAT_EXIT setups before persisting. Verified in code.
- **Friday pullback cutoff in `_check_pullback`** — fixed in the 2026-05-19 audit chain (bot.py:6025–6035): ALL pending pullbacks including rsi_extreme are cancelled Friday ≥ 15:00 ET.
- **RSI in-loss exit flow gate + MIN_FLOW_BLOCK floor** — shipping correctly (bot.py:4519–4552): gate blocks in-loss RSI exit only when flow magnitude > 10K (default). Quiet-bar noise band is filtered.
- **TRIM2 stop tighten direction (SHORT)** — verified correct: `new_stop2 = entry + 0.25×ATR×direction` gives `entry − 0.25×ATR` for shorts; stop fires at `close_price >= stop_price`, locking $0.25×ATR profit for shorts as intended.
- **Friday final flat sweep** — no exemptions (bot.py:4003–4020): closes ALL positions at 3:50 PM ET on Fridays regardless of trigger type. The progressive trim exemption (3:00–3:50 PM) for late RSI extreme is scoped only to trimming, not the final flat.
- **`pending_reversal` persistence on restart** — confirmed via `_load_trades_from_db` (bot.py:1100–1101): `t._pending_reversal = True` restored from DB on bot restart.
- **`force_trim_pending` / `force_trim2_pending` persistence on restart** — confirmed (bot.py:1104–1109): both flags and `_force_trim_reason` are restored from DB.
- **OBV-trail ratchet persistence (Redis)** — confirmed (bot.py:3573–3580): ratchet is written to Redis with 7-day TTL on each move; restored in `_load_trades_from_db` (bot.py:1129–1140).
- **`_obv_trail_stop_hit` shared between TV and 5m-naked** — correct: called in `_eval_tv_bxt_sym` (bot.py:3730) and `_eval_bxt_1m_naked` (bot.py:3774).
- **BXt1m/TV-BXt exemption from `_evaluate_symbol`** — confirmed (bot.py:3912–3915): exempt positions bypass all normal stop/trim/EOD logic. Identification via `strategy_reason.startswith("BXT1m")` / `startswith("TV-BXt")` is reliable.
- **Deferred-close dedup** — confirmed (bot.py:5932–5946): `seen_close_ids` prevents duplicate closes in the same drain; `if not trade.is_open: continue` catches already-closed trades.
- **HOLD_CAP_MIN trend exemption** — correct: applied only when `"MEAN_REVERT"` or `"EXT_FADE"` or `"EXTENSION_FADE"` in `strategy_reason.upper()`. Trend setups (BXT, pullback, RSI) don't match.
- **`consec_losses` rebuilt on restart** — confirmed from 2026-05-22 persistence audit fixes.
- **OBV Rule F `entry_time` parse fix** — confirmed (bot.py:4279–4281): `datetime.fromisoformat` used to convert string `entry_time` before timezone operations. The silent no-op bug (commit 782e3b6) is fixed.