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 — execution_quality audit 2026-06-12 — 0P0 3P1 4R
AI verdict
employee
high
· confidence: high
· by internal-exempt
“Sydnee Agent (AI): Sydnee nightly — execution_quality audit 2026-06-12 — 0P0 3P”
Reasoning: @sydnee.ai is a protected domain — hard exemption
Sydnee nightly — execution_quality audit — 2026-06-12
P0 findings: 0 P1 findings: 3 Risks: 4
- Area: Execution Quality (Friday theme)
- Branch: `dev` (210f257 — tape-tab UI; no execution-path code changed overnight)
- Files scanned: `bot.py` (~19 359 lines), `core/executor.py`, `config.json`,
`docs/strategy_decisions.md`, `git log --oneline -30`, prior execution audit 2026-05-29
- **Bugs found (P0 / P1): 0 / 3 (2 new, 1 carryover)**
- **Risks noted: 4 (2 new, 2 carryovers)**
Cross-check: `max_shares` raised to 50 000 in `config.json` → the TV-BXt partial-close P1
from 2026-05-29 is resolved (confirmed below).
---
Full report (dev branch): https://github.com/kanex1/sydnee.signals/blob/dev/docs/audit_2026-06-12_execution_quality.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-12 — EXECUTION QUALITY
## Summary
- Area: Execution Quality (Friday theme)
- Branch: `dev` (210f257 — tape-tab UI; no execution-path code changed overnight)
- Files scanned: `bot.py` (~19 359 lines), `core/executor.py`, `config.json`,
`docs/strategy_decisions.md`, `git log --oneline -30`, prior execution audit 2026-05-29
- **Bugs found (P0 / P1): 0 / 3 (2 new, 1 carryover)**
- **Risks noted: 4 (2 new, 2 carryovers)**
Cross-check: `max_shares` raised to 50 000 in `config.json` → the TV-BXt partial-close P1
from 2026-05-29 is resolved (confirmed below).
---
## Findings
### BUG [P1] (new): `config_syms` undefined in `_exec_qa_patrol` — position mismatch check silently never runs
**File:** `bot.py:7921`
**Evidence:**
```python
# bot.py:7911-7924 — check 5 of _exec_qa_patrol
try:
ibkr_pos = {p.contract.symbol: int(p.position) for p in self.ib.positions()}
bot_pos = {}
for t in self.open_trades():
bot_pos.setdefault(t.symbol, 0)
bot_pos[t.symbol] += t.shares * t.direction
for sym in set(list(ibkr_pos.keys()) + list(bot_pos.keys())):
ib_qty = ibkr_pos.get(sym, 0)
bot_qty = bot_pos.get(sym, 0)
if ib_qty != bot_qty and sym in config_syms: # ← NameError: config_syms
issues.append(f"{sym} mismatch: IBKR={ib_qty} vs bot={bot_qty}")
except Exception:
pass # ← NameError swallowed here
```
`config_syms` is never defined anywhere in `_exec_qa_patrol` (or in the class scope).
The surrounding `try/except Exception: pass` swallows the `NameError` on every call,
so check 5 (IBKR vs bot position sync) has never run since it was written.
`watchlist_syms` is the correct variable — it is defined two blocks above at `bot.py:7860`:
```python
watchlist_syms = set(self.symbols)
```
`_exec_qa_patrol` is called after every entry (`bot.py:7496`) and every exit
(`bot.py:8379`), so this check fires frequently but contributes nothing.
**Impact:** Any IBKR vs bot position discrepancy (orphaned shares after a partial
max_shares-capped close, a reconcile-import gone stale, a manual position opened outside
the bot) goes undetected intraday. The startup reconciler still catches these on restart,
but the intraday patrol path is dead. Ghost positions accumulate unreported P&L and bypass
the per-trade risk gates until the next container restart.
**Fix:**
```python
# bot.py:7921 — replace config_syms with watchlist_syms
if ib_qty != bot_qty and sym in watchlist_syms:
```
---
### BUG [P1] (new): `_execution_qa` 30s MKT fallback fires unconditionally outside RTH — cancels valid resting LMT, places rejected MKT, silently drops entry
**File:** `bot.py:7625–7638`
**Evidence:**
The docstring for `_execution_qa` says `30s: cancel and retry as aggressive limit`
(`bot.py:7511`), but the actual 30s retry sends `MarketOrder` unconditionally:
```python
# bot.py:7625-7638
if elapsed > RETRY_AT and not retried and not is_manual:
retried = True
self.ib.cancelOrder(exec_trade.order) # ← cancels the resting LMT
self.ib.sleep(1)
order2 = MarketOrder(action, shares) # ← naked market order
_ct2, order2 = self._route_for_session(ss.contract, order2)
exec_trade = self._place_order_with_overnight_fallback(_ct2, order2, ss.contract)
...
start_time = time.time()
```
Outside RTH, bot entry orders are placed as `LimitOrder` with `tif="DAY"` and
`outsideRth=True` (bot.py:7384–7395). When the LMT rests in the pre/post-market book
for >30s without filling (the stock hasn't come down to our bid, or market data was stale
on limit-price computation), the generic 30s retry fires because:
- The PreSubmitted guard at `bot.py:7593` is bypassed: `_existing_is_lmt=True` (our
entry IS a LMT), so that branch explicitly skips.
- The status transitions from `PreSubmitted` → `Submitted` (resting); `retried` is
still `False`; elapsed reaches 30s at roughly the 11th 3-second polling iteration.
The `_route_for_session` wrapper sets `outsideRth=True` and `tif="GTC"` on the new
`MarketOrder`. IBKR rejects MKT outside RTH (confirmed by the existing comment at
`bot.py:7587–7588`: *"IBKR rejects MKT outside RTH"*). The rejection → status
`Inactive/Cancelled`; since `retried=True`, the handler at `bot.py:7574` returns
`(None, None)`. The resting LMT was already cancelled at line 7628.
**Concrete scenario:** `rsi_extreme` pre-market entry (4:00–6:30 AM PT) where the
aggressive limit (ask + 1¢) is below the spread. Order rests 30s → bot cancels it
and sends MKT → IBKR rejects → entry silently dropped after ~33s.
**Impact:** Pre/post-market `rsi_extreme` entries that don't fill on first liquidity
touch are abandoned rather than resting legitimately. The 24×5 edge of the rsi_extreme
strategy is silently truncated for any off-hours entry in thin-spread conditions.
**Fix:** Add an RTH check before falling back to `MarketOrder`; outside RTH, refresh
the limit price instead:
```python
# bot.py:7625 — replace the generic MKT fallback block
if elapsed > RETRY_AT and not retried and not is_manual:
retried = True
now_et_retry = datetime.now(ET)
t_min_retry = now_et_retry.hour * 60 + now_et_retry.minute
in_rth_retry = 9 * 60 + 30 <= t_min_retry < 16 * 60
self.ib.cancelOrder(exec_trade.order)
self.ib.sleep(1)
if in_rth_retry:
order2 = MarketOrder(action, shares)
else:
lmt2 = self._get_aggressive_limit(sym, ss, action)
if lmt2:
order2 = LimitOrder(action, shares, lmt2)
order2.tif = "GTC"
else:
order2 = MarketOrder(action, shares) # no quote — MKT as last resort
_ct2, order2 = self._route_for_session(ss.contract, order2)
exec_trade = self._place_order_with_overnight_fallback(_ct2, order2, ss.contract)
...
```
---
### BUG [P1] (carryover 2026-05-29): `RSI_TICK_FIRE` window ends at 780 (13:00 ET), not 960 (16:00 ET) — three RTH hours lost
**File:** `bot.py:17412`
**Evidence:**
```python
# bot.py:17412 — confirmed unchanged since 2026-05-29 filing
if not (570 <= t_min < 780) or now_et.weekday() >= 5:
# Not RTH — reset state and skip
if ss._tick_state != 0:
ss._tick_state = 0
return
```
`780 = 13:00 ET`. RTH closes at `960 = 16:00 ET`. When `RSI_TICK_FIRE=true`, this gate
suppresses the 5m peak-confirm AND plain RSI fallback paths
(`bot.py:5631-5634`), yielding zero `rsi_extreme` entries 13:00–16:00 ET.
Flag defaults off — dormant unless explicitly enabled. Backtest (2026-05-19) showed
13:00 ET is the single highest-edge slot for afternoon rsi_extreme longs (+0.534% avg).
**Fix:** `bot.py:17412` — change `780 → 960`.
---
### RISK (new): `_execution_qa` original order ID leaked into `_active_order_ids` on retry
**File:** `bot.py:7528–7529`, `bot.py:7570–7572`, `bot.py:7632–7634`, `bot.py:7664–7670`
**Evidence:**
```python
oid = exec_trade.order.orderId
self._active_order_ids.add(oid) # ← original oid added
try:
while ...:
...
# On Cancelled → retry:
exec_trade = ...new order...
oid = exec_trade.order.orderId # ← oid variable reassigned to new order
self._active_order_ids.add(oid)
...
finally:
self._active_order_ids.discard(oid) # ← removes only the LAST oid
# original oid is never removed
```
Each retry path (`bot.py:7570`, `7611`, `7634`) reassigns `oid` and adds the new ID,
but the `finally` block only `discard`s the final `oid`. The original order's ID
stays in `_active_order_ids` indefinitely. Over a trading day with multiple retried
orders, the set grows by one dead ID per retry.
**Impact:** Minor memory leak. The dead IDs correspond to cancelled/rejected orders
that IBKR will never show in `openTrades()`, so they cannot cause `_exec_qa_patrol`
to falsely protect a working order from cancellation. No safety consequence.
**Fix:** Save the original oid and discard it explicitly when replacing the order:
```python
# In each retry branch, before: exec_trade = new order
self._active_order_ids.discard(oid) # drop the cancelled order's id
exec_trade = ...
oid = exec_trade.order.orderId
self._active_order_ids.add(oid)
```
---
### RISK (new): `_tape_eval_sym` calls `_open_trade` directly from daemon thread — cross-thread `ib.sleep()` may conflict with main asyncio loop
**File:** `bot.py:17158–17161`
**Evidence:**
```python
# bot.py:17158 — _tape_eval_sym, running in threading.Thread "tape-mode" (bot.py:18501)
try:
self._open_trade(sym, res["dir"], atr_val, price, ss,
entry_reason="Tape-4of4",
scale_slot_shares=shares)
```
`_open_trade` calls `_execution_qa` which calls `self.ib.sleep(3)` in a polling loop.
In ib_insync 0.9.86, `IB.sleep()` calls `loop.run_until_complete()` (or
`run_coroutine_threadsafe` in some builds); if the asyncio event loop is running in
the main thread, calling `run_until_complete` from the tape daemon thread raises
`RuntimeError: This event loop is already running`. The outer `except Exception` in
`_tape_eval_sym` silently swallows it → all tape entries fail without any indication
beyond a debug log line.
Compare with `_force_close_symbol` (`bot.py:8383–8394`) which explicitly defers via
`_deferred_closes` to the main loop to avoid exactly this conflict.
**Risk level:** Low — `TAPE_MODE_ENABLED=false` by default; the thread runs but entries
are gated. No impact on the 5m/BXt1m/TV-BXt paths.
**Fix (before enabling for production):** Route tape entries through `_deferred_entries`
(the same queue used by the 5m signal path), so order placement runs on the main loop
thread:
```python
# Replace direct _open_trade call with deferred entry:
self._deferred_entries.append((sym, res["dir"], atr_val, price, ss,
"Tape-4of4", 1.0, 1.0, None, None, shares))
```
---
### RISK (carryover 2026-05-29): `_reconcile_bracket_fills` records `ss.last_price` as exit price instead of actual IBKR fill
**File:** `bot.py:8425`, `bot.py:8444`
**Evidence:**
```python
exit_price = ss.last_price if ss else t.entry_price # ← polled price, not fill
pnl = self._close_trade_in_store(t.trade_id, exit_price)
```
No change since 2026-05-29 filing. Distorts P&L on bracket-closed trades, corrupts
`consec_losses` and the daily P&L report. Low blast radius; `_reconcile_bracket_fills`
only fires when the bot uses bracket orders (not the default path).
---
### RISK (carryover 2026-05-29): `_on_portfolio_update` two-step `in`+`[]` not atomic under watchlist shrink
**File:** `bot.py:18712–18720` (line numbers approximate — function body unchanged)
No change since 2026-05-29 filing. GIL-atomic float write; `KeyError` only if a symbol
is removed from `sym_states` between the `in` check and the `[]` assignment (rare; caught
by `except Exception`). No execution consequence in practice.
---
## OK (checked, working or recently fixed)
- **TV-BXt partial-close P1 RESOLVED** — `config.json` now has `max_shares: 50000`
(was `500`). TV-BXt positions sized at 50% NLV on typical names (~900–1 800sh)
are well below the new ceiling; close orders no longer get capped to 500sh. ✓
- **`_execution_qa` fill-price path** (`bot.py:7543`): `avgFillPrice` (IBKR-weighted
average across venue splits) is the primary source; `fills[0].execution.price` is
the fallback used only when `avgFillPrice == 0`. The 3s polling interval means IBKR
has populated `avgFillPrice` by the time we check. ✓
- **`_close_trade` exit VWAP override** (`bot.py:8195–8198`): when the per-execution
fill list VWAP diverges from `exec_trade.orderStatus.avgFillPrice` by > 0.5¢
(MKT→LMT conversion mid-flight), the function overrides `exit_price` with the true
fill-list VWAP. ✓
- **IOC entry inside RTH** (`bot.py:7385–7388`): aggressive LMT + IOC TIF in RTH; no
market-order exposure at entry for the standard 5m/BXt1m paths. ✓
- **Duplicate close guard** (`bot.py:8068–8082`): `trade.is_open` flag checked at
`_close_trade` entry; duplicate queued clos