◆ kanex-ai
Loading…
Interactive Brokers Client Services Jun 17 12:40 AM
Message Center Notification
Interactive Brokers ticket response regarding Kanex account messaging.
financial
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.
vendor
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
employee high
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.
phishing urgent
Microsoft Outlook Jun 16 9:38 PM
Undeliverable: FW: $QCOM (June 17, 2026-daily)
Microsoft Outlook: Undeliverable: FW: $QCOM (June 17, 2026-daily)
employee high
TDhruv Sharma Jun 16 9:05 PM
[Teams oneOnOne] (Teams DM)
Dhruv Sharma: [Teams oneOnOne] (Teams DM)
personal
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.
family
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.
vendor
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
employee high
Sydnee Agent (AI) Jun 16 5:40 PM
[Calibration Daily] 2026-06-17
Sydnee Agent (AI): [Calibration Daily] 2026-06-17
employee high
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
employee high
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.
vendor
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
phishing urgent
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
vendor
[email protected] Jun 16 2:34 PM
New Funding Program
Funding broker offering working capital solutions and consolidation services.
vendor
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
phishing urgent
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
employee high
[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
phishing urgent
TAnthony Patino Jun 16 1:30 PM
[Teams oneOnOne] (Teams DM)
LK account overdrawn; bank fee applied, needs replenishment before QB charge.
employee high
TAnthony Patino Jun 16 1:27 PM
[Teams oneOnOne] (Teams DM)
Anthony Patino sent a brief Teams DM referencing 'LK'.
employee
TAnthony Patino Jun 16 1:27 PM
[Teams oneOnOne] (Teams DM)
Anthony Patino reports insufficient funds issue.
employee high
Amazon Payments Jun 16 12:44 PM
Action requise sur le compte Amazon Payments
Fake Amazon Payments suspension notice in French requesting account verification.
phishing urgent
Nick Daniel Jun 16 11:04 AM
Quick question
TriNet HR solution sales inquiry.
vendor low
Aarti Gupta Jun 16 10:04 AM
Re: Order help #1227
Aarti Gupta: Re: Order help #1227
employee high
Aarti Gupta Jun 16 10:03 AM
Re: Order help #1227
Aarti Gupta: Re: Order help #1227
employee high
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
employee high
Sean McGinley Jun 16 9:58 AM
Order help #1227
Customer inquiry about HDMI extender transmitter compatibility for order #1227.
vendor
IBKR FYI Jun 16 9:51 AM
FYI: Upcoming Exchange Holidays
Exchange holiday notice: MIAX, NASDAQ, NYSE closed June 19.
financial low
IBKR FYI Jun 16 9:27 AM
FYI: Upcoming Exchange Holidays
NASDAQ/MIAX exchange holiday June 19, 2026 — no trading.
financial low
Hims Jun 16 9:02 AM
Kelvin - action required on your account
⚠ PHISHING: phishing subject pattern: 'action required' from external sender icloud.com
phishing urgent
[email protected] Jun 16 9:02 AM
You have a new estimate
Suspicious medical estimate link from Providence—verify legitimacy before clicking.
phishing urgent
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.
financial
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.
vendor
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.
financial
TDhruv Sharma Jun 16 8:16 AM
[Teams oneOnOne] (Teams DM)
Dhruv Sharma: [Teams oneOnOne] (Teams DM)
personal
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.
employee
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.
vendor
KanexPro Jun 16 7:51 AM
NEW USB-C + USB-BDual-Host Extender · 100m
KanexPro: NEW USB-C + USB-BDual-Host Extender · 100m
employee high
KanexPro Jun 16 7:50 AM
NEW USB-C + USB-BDual-Host Extender · 100m
KanexPro: NEW USB-C + USB-BDual-Host Extender · 100m
employee high
KanexPro Jun 16 7:50 AM
NEW USB-C + USB-BDual-Host Extender · 100m
KanexPro: NEW USB-C + USB-BDual-Host Extender · 100m
employee high
KanexPro Jun 16 7:49 AM
NEW USB-C + USB-BDual-Host Extender · 100m
KanexPro: NEW USB-C + USB-BDual-Host Extender · 100m
employee high
TDhruv Sharma Jun 16 7:33 AM
[Teams oneOnOne] (Teams DM)
Dhruv Sharma: [Teams oneOnOne] (Teams DM)
personal
TDhruv Sharma Jun 16 7:32 AM
[Teams oneOnOne] (Teams DM)
Dhruv Sharma: [Teams oneOnOne] (Teams DM)
personal
Bank of America Jun 16 6:16 AM
Your available account balance is low
Bank of America: Your available account balance is low
financial
Let's Talk Supply Chain Jun 16 6:01 AM
Are you ready?
Suspicious meeting confirmation from unknown sender with obfuscation.
phishing urgent
Interactive Brokers Client Services Jun 16 5:18 AM
Message Center Notification
Interactive Brokers ticket response regarding Kanex account notification.
financial
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.
phishing urgent
IBKR FYI Jun 16 5:01 AM
FYI: Option Expiration Notification
Oracle options expiring 18JUN2026 — immediate action required.
financial high
IBKR FYI Jun 16 5:00 AM
FYI: Option Expiration Notification
MSTR call option expiring 18JUN2026; action needed if extending position.
financial
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
employee high

Sydnee nightly — exit_flow audit 2026-06-16 — 0P0 8P1 6R

Sydnee Agent (AI) <[email protected]>
To: Kelvin Yan <[email protected]>
Tuesday Jun 16, 2026 · 4:25 AM PT · in [email protected]
AI verdict  employee high · confidence: high · by internal-exempt
“Sydnee Agent (AI): Sydnee nightly — exit_flow audit 2026-06-16 — 0P0 8P1 6R”
Reasoning: @sydnee.ai is a protected domain — hard exemption
Sydnee nightly — exit_flow audit — 2026-06-16 P0 findings: 0 P1 findings: 8 Risks: 6 - Area: Exit Flow (Tuesday theme) - Branch: `dev` (a808030) - Files scanned: `bot.py` (~20 285 lines), `docs/strategy_decisions.md`, prior exit-flow audits (2026-06-09, 2026-06-10), `git log --oneline -30` - Bugs found (P0 / P1): 0 / 8 (1 new, 7 carried) - Risks noted: 6 (1 new, 5 carried) Cross-check: `git log --oneline -30` shows all commits since the 2026-06-10 exit-flow audit are tape entry/sizing/UI changes (TAPE_RTH_DELAY_MIN, RSI exhaustion guard, TAPE_PCT_NLV, OBV-5m gate tighten, tape_metadata JSONB merge). No commit touches `_evaluate_symbol` or the core exit-flow path. All 7 P1s from 2026-06-10 are confirmed unfixed. Line numbers shifted ~+110 from tape additions. 1 new P1 found: tape `_tape_entry_ms` not persisted to DB. --- Full report (dev branch): https://github.com/kanex1/sydnee.signals/blob/dev/docs/audit_2026-06-16_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-16 — EXIT FLOW ## Summary - Area: Exit Flow (Tuesday theme) - Branch: `dev` (a808030) - Files scanned: `bot.py` (~20 285 lines), `docs/strategy_decisions.md`, prior exit-flow audits (2026-06-09, 2026-06-10), `git log --oneline -30` - Bugs found (P0 / P1): 0 / 8 (1 new, 7 carried) - Risks noted: 6 (1 new, 5 carried) Cross-check: `git log --oneline -30` shows all commits since the 2026-06-10 exit-flow audit are tape entry/sizing/UI changes (TAPE_RTH_DELAY_MIN, RSI exhaustion guard, TAPE_PCT_NLV, OBV-5m gate tighten, tape_metadata JSONB merge). No commit touches `_evaluate_symbol` or the core exit-flow path. All 7 P1s from 2026-06-10 are confirmed unfixed. Line numbers shifted ~+110 from tape additions. 1 new P1 found: tape `_tape_entry_ms` not persisted to DB. --- ## Findings ### BUG [P1] (new): Tape `_tape_entry_ms` not persisted — 60min hard cap resets on restart **File:** `bot.py:18705` **Evidence:** ```python # bot.py:18705 — entry_ms default falls back to now_ms: entry_ms = int(getattr(my_pos, "_tape_entry_ms", now_ms)) # ↑ _tape_entry_ms is never written to DB; on restart it is always None # → entry_ms = now_ms → 60min cap counted from restart, not from original entry # bot.py:18706 — hard cap check: if now_ms - entry_ms > 60 * 60 * 1000: _tape_close_with_snapshot(my_pos, "Tape-4of4 60min cap") return # bot.py:18904 — written at entry time (in-memory only): t._tape_entry_ms = now_ms # Not in DB restore block (bot.py:1119–1175) — survives no restarts. ``` After any container restart, all Tape-4of4 positions have `_tape_entry_ms = None`. The default `now_ms` resets the clock to restart time. A tape position open for 55 min before restart gets a fresh 60min window — it can run 55 + 60 = 115 min total, well past the scalping cap. The RTH-close flat at 15:50 ET provides an absolute ceiling but the 60min intent is violated. **Impact:** TAPE trades run past their 60min hard cap after container restarts (which occur on most deploys). Adversely-positioned scalps can stay open 90–120 min with only the -1% catastrophic stop as protection. **Fix:** Lazy-restore `_tape_entry_ms` from the persisted `entry_time` field (already in DB) when the in-memory attribute is missing: ```python # bot.py:18705 — replace the one-liner with: if getattr(my_pos, "_tape_entry_ms", None) is None: try: _et = datetime.fromisoformat(str(my_pos.entry_time).replace("Z", "+00:00")) my_pos._tape_entry_ms = int(_et.timestamp() * 1000) except Exception: my_pos._tape_entry_ms = now_ms entry_ms = int(my_pos._tape_entry_ms) ``` --- ### BUG [P1] (carried from 2026-06-09): TRIM1 — `_trimmed` / `_rsi_force_trim` flags never set for 1-share parents **File:** `bot.py:5510–5571` (EXIT 4 TRIM1 block) **Evidence:** ```python # bot.py:5510-5522: 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 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 self._update_trade_field(t.trade_id, trimmed_1=True, force_trim_pending=False, ...) # no else branch ``` For 1-share non-FLAT_EXIT: `trim_shares = 0`, `_trimmed` never set, `_rsi_force_trim` never cleared. `trim = True` fires every bar → EXIT 5 (BE) and FIX 1 (trailing stop) both blocked by `not trim` guard. `force_trim_pending=True` persists in DB through restarts. **Fix:** Add after `if trim_shares > 0:` block: ```python else: t._trimmed = True t._rsi_force_trim = False self._update_trade_field(t.trade_id, trimmed_1=True, force_trim_pending=False, force_trim_reason=None, extreme_since_trim=live_price) t._extreme_since_trim = live_price ``` --- ### BUG [P1] (carried from 2026-05-26): TRIM2 — `_trimmed_2` / `_rsi_force_trim2` flags never set for 1-share runners **File:** `bot.py:5452–5486` (EXIT 3b SECOND TRIM block) **Evidence:** ```python # bot.py:5452-5460: if not hit and is_trimmed and not is_trimmed_2 and (_trim2_hit or _force_trim2): trim = True trim2_shares = t.shares // 2 # 0 for 1-share runner if trim2_shares > 0: t._trimmed_2 = True # ← inside guard — never set for 1-share t._rsi_force_trim2 = False # ← inside guard — never cleared for 1-share # no else branch ``` `_rsi_force_trim2 = True` and `force_trim2_pending=True` in DB stay set. TRIM2 re-fires every bar, `trim = True`, silencing the hold log and suppressing trailing stop. **Fix:** Add `else: 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)`. --- ### BUG [P1] (carried from 2026-06-10): TRIM3 — `_trimmed_3` flag never set for 1-share runners **File:** `bot.py:5407–5437` (EXIT 3 TRIM3 block) **Evidence:** ```python # bot.py:5409-5416: if not hit and is_trimmed_2 and not is_trimmed_3 and t.target_price: if _tgt_hit: trim = True trim3_shares = t.shares // 2 # 0 for 1-share (common: 3sh entry → 2sh → 1sh) 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) new_stop3 = ... # ← stop advance never happens # no else branch ``` 1-share runner at target: `_trimmed_3` stays False, TRIM3 fires every bar while `live_price >= target`. Stop stuck at TRIM2 level (entry + 0.25×ATR) instead of advancing to TRIM3 level (entry + 0.5×ATR). FIX 1 trailing stop suppressed by `trim = True`. **Fix:** Add after `if trim3_shares > 0:` block: ```python else: t._trimmed_3 = True self._update_trade_field(t.trade_id, trimmed_3=True) 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-02): OBV Rule F permanently disabled after in-loss profit-guard skip **File:** `bot.py:5036–5058` (EXIT 0, inner profit-guard block) **Evidence:** ```python # bot.py:5036-5058 — profit-guard / loss path: if _profit_guard and profit_per_share < 0: _dir_lbl_ex = "LONG" if t.direction == 1 else "SHORT" if _loss_exit: hit = True # OBV_LOSS_EXIT spot-exit ... elif not getattr(t, '_obv_be_applied', False): self._log_activity(sym, f"BE-STOP (OBV rule F) skipped ...", "info") t._obv_be_applied = True # ← always set, even on profit-guard skip t._obv_be_applied_at = ... self._update_trade_field(t.trade_id, obv_be_applied=True, ...) ``` When `OBV_BE_STOP=true`, `RSI_TRIM_PROFIT_GUARD=true`, `OBV_LOSS_EXIT=false` (or unset): the skip path sets `_obv_be_applied = True` without moving the stop. The outer guard `not getattr(t, "_obv_be_applied", False)` (line 4990) then permanently blocks Rule F for this trade — even after it recovers to profit and OBV turns adverse again. Stop stays at the wide original level instead of tightening to BE. **Impact:** Applicable to prod if `OBV_LOSS_EXIT` is not set there. A trade that was underwater when OBV first turned against it keeps its full −1R risk after recovery; the BE-stop protection that Rule F would have provided never fires. **Fix:** Remove `t._obv_be_applied = True` from the in-loss / non-loss-exit branch. To prevent log spam, add a rate-limit check instead: ```python elif not getattr(t, '_obv_be_applied', False): _last_skip = getattr(t, '_obv_skip_log_at', 0) if time.time() - _last_skip > 300: # log at most once per 5 min self._log_activity(sym, f"BE-STOP (OBV rule F) skipped ...", "info") t._obv_skip_log_at = time.time() # Do NOT set t._obv_be_applied here — rule stays live for recovery path ``` --- ### BUG [P1] (carried from 2026-06-02): `profit_per_share` uses stale 5m bar close — `_in_profit` gate misroutes RSI/BXt exits intrabar **File:** `bot.py:4970` (`profit_per_share`); `bot.py:5237` (`_in_profit`) **Evidence:** ```python # bot.py:4969-4970: live_price = float(ss.last_price) if ss.last_price else close_price profit_per_share = (close_price - t.entry_price) * t.direction # ← stale 5m close, not live # bot.py:5237: _in_profit = profit_per_share > 0 # ← gates trim-ladder vs full-close routing ``` When RSI/BXt reversal fires and intrabar price moved below entry since the last 5m close, `_in_profit = True` (stale) routes to trim ladder. Trim child fills at live (lower) price; BE stop is then placed above current price → immediate stop-out on the runner. **Fix:** `_in_profit = (live_price - float(t.entry_price)) * t.direction > 0` at lines 5237 and 5386 (BXt reversal uses the same variable in scope). --- ### BUG [P1] (carried from 2026-06-02): `_check_stops` defined but never called — intrabar wick through stop missed **File:** `bot.py:6723` (definition); zero callers **Evidence:** ```python # bot.py:6723 — defined, never wired: def _check_stops(self, trade: Trade, bar) -> None: if trade.stop_price: if trade.direction == 1 and bar.low <= trade.stop_price: # correct bar-low check ... # bot.py:5107-5110 — live exit only checks close_price: if t.direction == 1 and close_price <= t.stop_price: _stop_hit_pending = True ``` An intrabar wick trading through the stop but closing above it is never caught. `_check_stops` was written to fix this using bar high/low but was never called. Mitigated only when `WS_TICK_EXITS=true` (default off on dev/prod). **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, before the `_stop_hit_pending` deferred evaluation. --- ### BUG [P1] (carried from 2026-05-31): `TV_BXT_TRAIL_AGAINST` default mismatch — live `1.0` vs history replay `1.5` **File:** `bot.py:3838` (live); `bot.py:14949` (history replay) **Evidence:** ```python # bot.py:3838 — _obv_trail_stop_hit (live): agnst = float(os.environ.get("TV_BXT_TRAIL_AGAINST", "1.0")) # bot.py:14949 — /api/trade_obv_trail dashboard endpoint: agnst = float(os.environ.get("TV_BXT_TRAIL_AGAINST", "1.5")) ``` When `TV_BXT_TRAIL_AGAINST` env var is unset: live trail = 1.0×ATR, dashboard shows 1.5×ATR. Stop-analysis reports are wrong by 50% on unset-env sessions. **Fix:** Change `bot.py:14949` default `"1.5"` → `"1.0"`. One-line fix. --- ## Risks ### RISK: `_stop_hit_pending` deferred evaluation overwrites earlier `hit=True` exit reason **File:** `bot.py:5223–5225` ```python if _stop_hit_pending: # ← no `not hit` guard hit, reason = True, f"Stop-loss ${t.stop_price:.2f} · ..." # ← overwrites OBV/HOLD_CAP reason ``` If `OBV_LOSS_EXIT` or `HOLD_CAP_MIN` already set `hit=True`, and the same bar's 5m close also hits the stop, the reason is overwritten to "Stop-loss" in the DB. Trade closes correctly; P&L attribution is wrong. **Fix:** `if _stop_hit_pending and not hit:` at line 5223. --- ### RISK (carried): Tick exit path (`_tick_exit_step`) has no TRIM2 level check **File:** `bot.py:_tick_exit_step` (~line 19402) When `WS_TICK_EXITS=true`: after tick T1 (50% trim), the remaining 50% can be closed by tick TARGET before bar close — compressing the 4-level ladder into 2 levels. Behavioral divergence vs default `WS_TICK_EXITS=false`. `WS_TICK_EXITS` is off by default; low live impact. --- ### RISK (carried): 5m-naked OBV trail stop unavailable for first 75 min after pre-market open **File:** `bot.py:379