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-06-10 — 0P0 7P1 5R
AI verdict
employee
high
· confidence: high
· by internal-exempt
“Sydnee Agent (AI): Sydnee nightly — exit_flow audit 2026-06-10 — 0P0 7P1 5R”
Reasoning: @sydnee.ai is a protected domain — hard exemption
Sydnee nightly — exit_flow audit — 2026-06-10
P0 findings: 0 P1 findings: 7 Risks: 5
- Area: Exit flow (how and when open positions are closed)
- Branch: `dev` (afddfff — peak-monitor log, no strategy code changed overnight)
- Files scanned: `bot.py` (~18 497 lines), `docs/strategy_decisions.md`, yesterday's exit-flow audit (`audit_2026-06-09_exit_flow.md`), `git log --oneline -30`
- Bugs found (P0 / P1): 0 / 7 (1 new, 6 carried)
- Risks noted: 5 (0 new, 5 carried)
Cross-check: `git log --oneline -30` shows no strategy or exit-path commits since the 2026-06-09 audit. All 6 carried P1s are confirmed unfixed. 1 new P1 found: TRIM3 has the same `_trimmed_3` / 1-share flag-clearing gap as the already-carried TRIM1 and TRIM2 bugs.
---
Full report (dev branch): https://github.com/kanex1/sydnee.signals/blob/dev/docs/audit_2026-06-10_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-06-10 — EXIT FLOW
## Summary
- Area: Exit flow (how and when open positions are closed)
- Branch: `dev` (afddfff — peak-monitor log, no strategy code changed overnight)
- Files scanned: `bot.py` (~18 497 lines), `docs/strategy_decisions.md`, yesterday's exit-flow audit (`audit_2026-06-09_exit_flow.md`), `git log --oneline -30`
- Bugs found (P0 / P1): 0 / 7 (1 new, 6 carried)
- Risks noted: 5 (0 new, 5 carried)
Cross-check: `git log --oneline -30` shows no strategy or exit-path commits since the 2026-06-09 audit. All 6 carried P1s are confirmed unfixed. 1 new P1 found: TRIM3 has the same `_trimmed_3` / 1-share flag-clearing gap as the already-carried TRIM1 and TRIM2 bugs.
---
## Findings
### BUG [P1] (new): TRIM3 `_trimmed_3` flag never set for 1-share runners — target fires every bar, trailing stop permanently suppressed
**File:** `bot.py:5297–5325` (EXIT 3 TRIM3 block)
**Evidence:**
```python
# bot.py:5296-5325 — TRIM3 block:
if not hit and is_trimmed_2 and not is_trimmed_3 and t.target_price:
_tgt_hit = (t.direction == 1 and live_price >= float(t.target_price)) or ...
if _tgt_hit:
trim = True # ← unconditional
trim3_shares = t.shares // 2 # = 0 for 1-share runner
if trim3_shares > 0:
t._trimmed_3 = True # ← inside guard — never set for 1-share
self._update_trade_field(t.trade_id, trimmed_3=True) # never runs
new_stop3 = t.entry_price + 0.5 * _daily_atr * t.direction # never runs
...
# no else branch
```
A runner that reaches the target price with exactly 1 share remaining (the common case after TRIM1 on a 3-share entry → 2 shares, then TRIM2 → 1 share) produces:
- `trim3_shares = 1 // 2 = 0`
- `t._trimmed_3` stays `False` → `not is_trimmed_3 = True` → TRIM3 condition fires again every subsequent bar while `live_price >= target_price`
- `trim = True` unconditionally each bar
- FIX 1 (trailing stop, line 5473) checks `not trim` → blocked every bar
- Stop is never advanced to `entry_price + 0.5 × ATR` (that code is inside the guard)
**Concrete cascade for a 3-share LONG entry:**
1. Entry 3sh → TRIM1: 1sh child out, 2sh runner, `t._trimmed = True`
2. TRIM2: 1sh child out, 1sh runner, `t._trimmed_2 = True`
3. Target reached → TRIM3: `trim3_shares = 0`, `t._trimmed_3 = False` unchanged
4. Every subsequent bar with `live_price >= target`: `trim = True` → FIX 1 blocked
5. Stop remains at the TRIM2 level (`entry + 0.25×ATR`) — never tightened to `entry + 0.5×ATR`
6. Hold log line (`elif not trim:`) never written — activity log is silent for the runner
7. Loop ends only when the original stale stop fires or a full-close exit (RSI/BXt) triggers
**Impact:** All 1-share runners reaching TRIM3 target silently lose their stop-advance and trailing stop. Stop is stuck at the TRIM2 level, leaving ~0.25×ATR of additional buffer on the table. Activity log goes dark for the runner. Frequency: any 3-share or odd-lot entry where both prior trims succeed before target is reached.
**Fix:** Add an `else` after `if trim3_shares > 0:` at `bot.py:5308`:
```python
else:
t._trimmed_3 = True
self._update_trade_field(t.trade_id, trimmed_3=True)
# 1-share runner: advance stop to entry+0.5×ATR (same as the normal path)
new_stop3 = t.entry_price + 0.5 * _daily_atr * t.direction if _daily_atr > 0 else t.stop_price
cur_stop3 = float(t.stop_price or 0)
if t.direction == 1:
new_stop3 = max(new_stop3, cur_stop3)
elif cur_stop3 > 0:
new_stop3 = min(new_stop3, cur_stop3)
self._update_trade_field(t.trade_id, stop_price=new_stop3)
self._log_activity(sym, f"TRIM3 1-share runner @${live_price:.2f} — lock stop → ${new_stop3:.2f}", "trade")
```
---
### BUG [P1] (carried from 2026-06-09): TRIM1 `_rsi_force_trim` and `_trimmed` flags never set/cleared for 1-share parents
**File:** `bot.py:5395–5456` (EXIT 4 TRIM1 block)
**Evidence:**
```python
# bot.py:5397-5412 — inside EXIT 4:
if not hit and not is_trimmed and _trim_hit:
if True:
trim = True
trim_shares = t.shares if _flat_full_close else t.shares // 2 # = 0 for 1-share, non-FLAT
if trim_shares > 0:
t._trimmed = True # ← inside guard — never set for 1-share
t._rsi_force_trim = False # ← inside guard — never cleared for 1-share
...
# no else branch
```
For a 1-share parent: `trim = True` every bar, neither flag cleared, BE stop (EXIT 5) and trailing stop (FIX 1) permanently blocked.
**Fix:** Add `else: t._trimmed = True; t._rsi_force_trim = False; self._update_trade_field(...)` after `if trim_shares > 0:`.
---
### BUG [P1] (carried from 2026-06-02): `profit_per_share` uses stale bar close — `_in_profit` gate misroutes RSI/BXt exits when intrabar price is at a loss
**File:** `bot.py:4855` (`profit_per_share` assignment); `bot.py:5122` (`_in_profit` gate)
**Evidence:**
```python
# bot.py:4854-4855:
live_price = float(ss.last_price) if ss.last_price else close_price
profit_per_share = (close_price - t.entry_price) * t.direction # ← stale close
# bot.py:5122:
_in_profit = profit_per_share > 0
```
When intrabar price drops below entry after the last 5m close, `_in_profit = True` (stale) routes to trim ladder; BE stop then placed above current price → immediate stop-out on the runner.
**Fix:** `_in_profit = (live_price - float(t.entry_price)) * t.direction > 0` at line 5122 and 5271.
---
### BUG [P1] (carried from 2026-06-02): `_check_stops` defined but never called — intrabar bar-high/low stop check is dead code
**File:** `bot.py:6583` (definition); zero callers in all `.py` files
**Evidence:**
```python
# bot.py:6583:
def _check_stops(self, trade: Trade, bar) -> None:
if trade.stop_price:
if trade.direction == 1 and bar.low <= trade.stop_price: # bar-low check
...
```
The 5m exit loop only checks `close_price` against `stop_price`. An intrabar wick through the stop but closing above it is never caught. `_check_stops` was intended to fix this but was never wired in.
**Fix:** Wire `_check_stops` into `_evaluate_symbol` near the `_stop_hit_pending` block using `signal_df["low"].iloc[-1]` / `signal_df["high"].iloc[-1]` already in scope.
---
### BUG [P1] (carried from 2026-05-26): OBV Rule F permanently disabled after in-loss skip
**File:** `bot.py:4936–4943`
**Evidence:**
```python
# bot.py:4941 — in-loss / non-loss-exit path:
t._obv_be_applied = True # ← consumed WITHOUT moving stop
```
When `OBV_BE_STOP=true`, `RSI_TRIM_PROFIT_GUARD=true`, `OBV_LOSS_EXIT=false` and trade is at a loss: skip sets `_obv_be_applied = True` permanently without moving the stop. Rule F never fires again even after trade recovers to profit.
**Fix:** Remove `t._obv_be_applied = True` from the in-loss / non-loss-exit branch; keep only in the profit and OBV_LOSS_EXIT paths.
---
### BUG [P1] (carried from 2026-05-26): TRIM2 `_rsi_force_trim2` flag never cleared for 1-share parents
**File:** `bot.py:5337–5371`
**Evidence:**
```python
# bot.py:5341:
trim2_shares = t.shares // 2 # = 0 for 1-share
if trim2_shares > 0:
t._trimmed_2 = True
t._rsi_force_trim2 = False # ← inside guard — never clears when shares=1
...
# no else branch
```
1-share position: `_rsi_force_trim2 = True` and `force_trim2_pending=True` in DB stay set. TRIM2 re-fires every bar, `trim = True`, suppressing hold log and trailing stop.
**Fix:** Add `else: t._trimmed_2 = True; t._rsi_force_trim2 = False; self._update_trade_field(...)`.
---
### BUG [P1] (carried from 2026-05-31): `TV_BXT_TRAIL_AGAINST` default mismatch — live `1.0` vs history endpoint `1.5`
**File:** `bot.py:3774` (live OBV trail); `bot.py:14352` (history replay / stop-analysis endpoint)
**Evidence:**
```python
# bot.py:3774 — live _obv_trail_stop_hit:
agnst = float(os.environ.get("TV_BXT_TRAIL_AGAINST", "1.0"))
# bot.py:14352 — /api/trade_obv_trail dashboard:
agnst = float(os.environ.get("TV_BXT_TRAIL_AGAINST", "1.5"))
```
When env var is unset, live trail uses `1.0×ATR`; dashboard stop-analysis shows `1.5×ATR`. Operator sees a 50% wider trail in the dashboard than what actually ran.
**Fix:** Change `bot.py:14352` default `"1.5"` → `"1.0"`.
---
### RISK: `_stop_hit_pending` overwrites earlier `hit=True` reason with no `not hit` guard
**File:** `bot.py:5109`
**Evidence:**
```python
if _stop_hit_pending: # ← no `not hit` check
hit, reason = True, f"Stop-loss ${t.stop_price:.2f} · ..." # ← overwrites OBV/HOLD_CAP
```
If HOLD_CAP or OBV_LOSS_EXIT already set `hit=True`, and the same bar's close also hits the stop, `_stop_hit_pending=True` overwrites the prior exit reason. No incorrect close; P&L attribution in DB is wrong.
**Fix:** `if _stop_hit_pending and not hit:` at line 5109.
---
### RISK (carried): Tick exit path (`_tick_exit_step`) has no TRIM2 check — `WS_TICK_EXITS=true` skips the trim2 level
**File:** `bot.py` (`_tick_exit_step` ~line 16750)
After tick T1 fires (50% trim), the remaining 50% can be closed by TICK TARGET before bar close, compressing the 4-level trim ladder into 2 levels. Behavioral divergence from `WS_TICK_EXITS=false` runs. `WS_TICK_EXITS` is default off so live impact is low.
---
### RISK (carried): 5m-naked OBV trail stop unavailable first 75 min of pre-market
**File:** `bot.py:3769` (`_tv_atr_obv`); `bot.py:4123` (`_eval_bxt_1m_naked`)
OBV trail requires `n >= 15` 5m bars. Entries at/after 04:15 ET have no OBV trail until ~05:30 ET. TV-BXt's `TV_BXT_RTH_ONLY` flag mitigates for TV mode; 5m-naked entries remain unguarded.
---
### RISK (carried): FLAT_EXIT parent closed with empty `exit_reason` in DB
**File:** `bot.py:1319` (`_close_trade_in_store`)
```python
self.db.close_trade(
trade_id=trade_id, ..., exit_reason="", # ← always empty
```
`_close_trade_in_store` hard-codes `exit_reason=""`. FLAT_EXIT parent rows are unclassifiable in SQL exit-type queries. Trim child holds the real reason; parent does not.
---
### RISK (carried): `trim3` parent-DB comment stale
**File:** `bot.py:8272`
```python
elif trade.trade_id.endswith("_trim3"):
pass # no DB column for trim3 yet — state tracked in-memory
```
`trimmed_3` column was added in commit `a6be962` (2026-04-15). The `pass` is correct (parent updated at line 5302 when trim3 is set up), but the stale comment risks a developer adding a redundant update to this handler.
---
## OK (checked, working or recently fixed):
- **No overnight code commits:** `git log --oneline -30` shows only peak-monitor hourly logs since 2026-06-09 audit. All carry decisions from yesterday hold. ✓
- **TRIM3 monotonicity guard:** `new_stop3 = max(new_stop3, cur_stop3)` for longs prevents loosening. (This runs only when `trim3_shares > 0`; the 1-share gap is the new P1 above.) ✓
- **Scale-in first-fill fix (4517516):** `st["slots_done"] = slot_n` and `st["start_ms"] = now_ms` preserve slot count and pin the 10-min window to first fill. ✓
- **TRIM1 `if True:` wrapper:** cosmetic inert wrapper; trim logic runs unconditionally when the outer `not is_trimmed and _trim_hit` guard passes. ✓
- **BXt reversal `_pending_reversal` drain:** `t._pending_reversal = False` + `self._update_trade_field(pending_reversal=False)` at line 5268 correctly consumes the flag in-memory and DB on confirmation-bar fire. ✓
- **BXt reversal correct trim routing:** `_do_reversal` path routes through `is_trimmed` / `_is_trimmed_2_now` correctly (arming force-trim flags, not direct `hit=True`) for positions with partial trim history. ✓
- **Deferred-close dedup:** `seen_close_ids` set in `_process_deferred_orders` (line 6542) prevents duplicate close orders from stacked tick callbacks. ✓
- **HOLD_CAP `not hit` guard:** `if _hold_cap > 0 and not hit and ...` at line 4970 prevents HOLD_CAP from overwriting a prior `hit=True`. ✓
- **EXIT 5 (BE) `not trim` guard:** `if not hit and not trim and _daily_atr > 0 and not is_trimmed:` at line 5459 — co