ThetaPrime v0.35.15
Download ThetaPrime-0.35.15-setup.exe
Fixed
Batches 3-9 of the 2026-08-25 systematic bug hunt (findings #6-44), plus the 2026-08-26 orphaned-fill incident. Full suite: 1220 passed.
- KiteAdapter now tracks dead-session state at the class level (mirrors the fix already shipped for Breeze/Dhan) — a fresh adapter per request previously meant it never armed.
- Dhan contract validation now clears the class-level dead-token flag between checks, not just the instance flag, avoiding a repeat of the 2026-07-19 incident.
convert_to_limit(Kite/Breeze/Dhan) no longer re-places a marketable LIMIT on top of an order whose cancel wasn't confirmed CANCELLED/REJECTED, which could double a leg.- Strategy engine now aborts cleanly when a structure builds zero legs, instead of leaving
status=ACTIVEwith no orders placed. - Fixed an unpadded-hour bug ("9:45" vs "09:45") that silently broke entry-time filters, EOD exits, and the fullday-sim/scheduler "latest exit time" calc; spec save-time validation now rejects unpadded hours.
- Fullday-sim orphaned-thread handling now waits for the orphaned thread to finish before restoring env / releasing its lock, so a second concurrent sim can't corrupt the first's date/hour/minute env vars; the lock is also released on exception instead of deadlocking.
- One strategy's malformed active-trade state no longer crashes reconciliation for every other strategy.
.secrets.jsonnow writes via temp-file +os.replaceinstead of truncating in place, so a crash mid-write can no longer wipe every stored credential.- Fixed a stuck
AWAITING_REENTRYstatus left over from a dayrun_eod()never ran, which had been silently skipping the next day's entry. - Fill verification no longer treats a genuine 0.0 average fill price as "no fill" and skips backfilling it.
- Orphaned-fill incident (2026-08-26): subprocess timeout raised to 240s (was shorter than Breeze's own worst-case fill-poll budget, guaranteeing a mid-poll kill); a killed run now gets a proper run-history row and crash notification instead of vanishing; entry legs are checkpointed to disk after each successful placement, not only on failure. Reconciliation now reads
_partial_entrylegs and a diagonal's held long legs on the ACTIVE branch; the periodic reconcile safety net now runs whenever real trading is configured, not only once a leg is already believed open; the UI modal no longer hides held long legs after a successful short re-entry. - Close orders get the same mid-poll checkpoint as entries, across all 7 close call sites (close, close-long, close-for-reentry, adjustment rolls, retry-unconfirmed, rollback).
lot_size()now raises for a genuinely unrecognized underlying instead of silently defaulting to NIFTY's lot size.- Long-leg monitor context (diagonal hedges) now carries
entry_vix, setsposition_dte(not justlong_dte), and fetches a fresh VIX reading when adelta_stop/iv_stopis in scope — these exits previously never fired on long legs. - Black-Scholes formulas no longer raise
ZeroDivisionErroronvix=0; return the correct zero-vol limit instead. - Margin estimate no longer treats a genuine 0.0
wing_pts(same-strike wing) as undefined risk. - Nine JSON-body routes switched from
request.json or {}(raises on missing/non-JSON Content-Type) torequest.get_json(silent=True) or {}. - Concurrent safety/broker/backup config saves are now lock-guarded against a lost-update race.
_settle_close_ordernow catches broker exceptions instead of letting one dead session abort the whole retry/roll loop for every other unconfirmed leg.- AI
ask()now raises a clean error on a tool-calls-only reply (content: null) instead of crashing callers withAttributeError. - Scheduled backup pruning now rejects
keep <= 0instead of deleting every backup including the one just made. - Strategy archiving now derives the state-file path the same way app.py does, fixing a false "no open position" check for legacy
.pystrategies. GammaTarget/DeltaOtmselectors now raise a clean error whenmin_otm_pct > max_otm_pctempties the scan range.- License revocation check now stamps "checked" even on a failed network call, so a sustained outage doesn't force the blocking 5s check on every page load.
- Cloning a strategy now also checks for an existing display/param sidecar file, not just the strategy file itself.
multi_sim.extend()no longer widens the session's date range before the corresponding batch of days has actually run.- Local-credential-store writes (
storage.py) are now lock-guarded against concurrent read-modify-write races, including the trial-start write-once guard. - Revocation state and pending-request storage now go through the OS keyring first, local file only as fallback.
- Fixed a SQLite connection leak in the app-events table helpers.
- The
X-MCP-Authheader now shares/login's brute-force lockout, instead of being uncapped. - MCP server error responses now surface app.py's actual error message instead of a generic HTTP status line.
- First-run data-encryption setup no longer raises unguarded on a keyring/disk failure.
sync_backup_job()no longer takes down the entire scheduler when a saved backup time is out of range.- Run IDs are now unique to sub-second resolution, preventing two same-second runs from overwriting each other's tracking entry.
_send_email()now validatesuser/passwordup front instead of a bareKeyErroron a partial config.- Sim logging handler cleanup now only removes handlers the sim itself added, instead of clearing whatever's present.
[0.35.14] — 2026-08-26
Fixed
- Loss-limit breach no longer force-downgrades an unrelated strategy's real exits to paper — the arm gate now exempts monitor-mode runs, and
long_exitwas added to the daily loss-limit check's event types (composer diagonal/covered-call terminal closes were never enforced against it). Reentry now also respectsSTRATEGY_ENTRIES_BLOCKED, closing a gap where a disarmed strategy's monitor tick could still place a brand-new real reentry order mid-breach. - Rejected-leg reconciliation tightened from
>= unitsto== unitsso a differently-sized unrelated position can no longer be mistaken for a rejected leg's fill. - Breeze weekly-option symbol parsing fixed for Oct/Nov/Dec expiries — the single-digit-month regex mis-parsed them as a different month/day; now tries both month widths and disambiguates by closest-to-today (mirrors an existing Dhan adapter fix for the same collision).
- Notifier: fixed a dedup-prune
KeyErrorrace (now locked), a LIB V1 entry alert silently dropping its Target/SL line, and icon selection crashing on non-numeric P&L values. - Dhan adapter hardening: session-dead state is now tracked per token at the class level (previously per-adapter-instance, so it never actually engaged since app.py builds a fresh adapter per request) —
ltp()/quote()now raise once a session is dead instead of returning an empty price dict; the scrip-master loader is now lock-guarded against concurrent double-downloads.