Skip to content

Peng-Protocol/EverWinter

Repository files navigation

❄️ EVERWINTER

EverWinter is a browser-based trading suite for Bybit USDT Perpetuals executing the Winter-Chaser strategy. See the Strategy Guide for trading logic and rationale.


Files

File Purpose
PseudoWinter.html Shorts-only simulation bot
PseudoChaser.html Longs-only simulation bot
PsychoWinter1.0.html Reactive approach standalone bot
ChartWinter.html Chart and market scan tool
plugins/modes/EverWinter.html Live trading plugin for PseudoWinter
plugins/modes/SunChaser.html Live trading plugin for PseudoChaser
plugins/modes/EDa-Winter.html EDa (Effective Debt Adjusted) plugin for PseudoWinter
plugins/modes/EDa-Chaser.html EDa plugin for PseudoChaser
plugins/strategies/MultiIndicator-Winter.html Entry filter plugin for PseudoWinter
plugins/strategies/MultiIndicator-Chaser.html Entry filter plugin for PseudoChaser
plugins/analytics/Permafrost-Winter.html Market climate plugin for PseudoWinter
plugins/analytics/Ashfall-Chaser.html Market climate plugin for PseudoChaser

Setup

Open any .html file directly in a browser. No build step, no server, no installation. Alpine.js and Bootstrap 5 are loaded from CDN — an internet connection is required on first load (cached after that).

Running both bots: open PseudoWinter and PseudoChaser in separate tabs from the same origin. When both are open simultaneously they automatically share bulk ticker fetches, kline caches, and liquidation results to halve API load. Either bot works normally on its own when the other tab isn't open.

In addition to the shared data pool, the Permafrost and Ashfall plugins maintain a separate cross-bot sample state (__ew_sample_state_v1) written after each structure cycle and read every 15 seconds. This state carries wave score, funding skew, OI skew, kline bar data, and liquidation cycle history. When one bot is in a drawdown halt or gains lock, its plugin reads the partner's sample to keep the Status Block bars, liq chart, and WAVE score line current — the halted bot's displays stay populated from the running partner's latest readings without opening any new entries.


Plugins

To load a plugin, open the Plugin Manager panel, click Load Plugin, and select the .html file. A page reload is required after loading or removing any plugin — the plugin pipeline runs once at page boot, so changes don't take effect until the next load.

Load order matters: live trading plugins (EverWinter, SunChaser) must load before strategy plugins (MultiIndicator, Permafrost/Ashfall). The Plugin Manager shows the current load order and warns about conflicts.


Main Config

Changes take effect immediately and are persisted to localStorage automatically.

Setting What it does
Scan Interval (scanMins) How often (minutes) the bot runs a full market scan. Controls both entry frequency and the scan bar in the UI.
Max Positions (maxPos) Maximum simultaneously open positions. No new entries open once this is reached.
Leverage (leverage) Position leverage. Affects order size, TP/SL prices, and EDa thresholds.
Min Notional (minNotional) Base margin per position in USDT. Actual order size = minNotional × leverage.
TP % (tpPct) Take-profit target. When EDa is active this is the buffered target — the debt-free close happens at a lower percentage.
SL % (slPct) Stop-loss. Position closes immediately when mark price hits this level.
Drawdown Throttle (drawdownThrottleEnabled) Halts new entries for 12 hours when rolling 6h realized PnL drops below a loss threshold.
Drawdown Factor (drawdownThrottleFactor) Loss threshold as a multiple of entry margin. At 0.5× with $1 margin, $0.50 of rolling losses triggers the halt.
Gains Lock (gainsLockEnabled) Halts new entries for 12 hours once rolling 6h profit hits a target. Banks a winning streak before it reverses.
Gains Factor (gainsLockFactor) Profit target as a multiple of entry margin. Same scale as Drawdown Factor.
Manual Halt Button (Halt tab) that blocks all new position entry indefinitely until manually lifted. Independent of Drawdown Throttle and Gains Lock — overrides both and doesn't stack with either.
EDa / Laggard Check (laggardCheckEnabled) Enables the Effective Debt Adjusted system. Realized losses are passed forward to surviving positions, which take higher TP targets to recover the debt. Requires the EDa-Winter / EDa-Chaser plugin (plugins/modes/).
TP Buffer (laggardProfitOffset) Extra TP headroom reserved above the functional target (%). The debt-free close happens at tpPct ÷ (1 + buffer/100) — at 50% buffer with an 18% TP slider, trades close at 12% without debt. Requires the EDa plugin.
Ticker Cooldown (bulkTickerCooldownHours) How long the bot reuses a cached bulk ticker fetch before hitting the API again. Higher = fewer API calls per day.
Whiplash Audit (whiplashEnabled) When on, the position watcher fetches 1-minute klines near TP to confirm whether price spiked through TP between watcher cycles.
Whiplash Proximity (whiplashProximityPct) How close (%) to TP price triggers the kline audit.
Runtime Limit (runtimeHours) Maximum position age. Forces a close at the deadline if TP hasn't been hit.
Symbol Banlist (banlistEnabled) When on, symbols on the ban list are excluded from all scans. Entries expire after 7 days.
Position Price Feed (restPollEnabled) When on, replaces the WebSocket price stream for open positions with periodic REST API calls. Use if the WS feed returns stale or incorrect prices.
Price Poll Interval (restPollBaseSec) Base polling interval in seconds for REST mode. The interval doubles automatically when price moves less than 0.1% between ticks and resets to base on any meaningful move.
Config Lock (cfgLocked) Locks all config controls to prevent accidental changes while the bot is running.

Stats Menu

The stats panel shows session-level metrics since the page was last loaded or state was cleared.

Stat Meaning
Session PnL Cumulative realized PnL from all closed trades this session.
Win / Loss Count of profitable vs. losing closed trades.
Win Skew Share of total PnL magnitude (all closed trades, cumulative) that came from wins — sum of winning PnL ÷ (sum of winning PnL + sum of losing PnL). Weighted by trade size, not just a count of wins vs. losses.
Avg PnL Mean realized PnL per closed trade.
Open uPnL Unrealized PnL across all currently open positions.
Positions Count of open positions.
Last Scan Timestamp of the most recent scan cycle.
Laggard The oldest open position — the EDa debt holder. Shows its current debt load when EDa is active.
Persistence "Active" (live in-memory position count) vs. "Stored" (confirmed saved to localStorage). These should always match.

Persistence mismatch: shown in red with a warning banner. It means a save failed or was overwritten, and usually clears on its own within a few seconds as the bot retries automatically. If it doesn't:

  • Check the activity log for [PST]/[PERSIST] entries.
  • Close any duplicate tabs of the same bot — a second tab can overwrite the first tab's saves with its own stale position count.

Storage usage (dropdown below Persistence): breaks localStorage down to one row per data type — e.g. Permafrost's structure wave, liquidation samples, and OC samples each get their own row instead of one lumped "Permafrost" figure, so a bloated data type is visible on its own. Oversized rows are shown in red. An Export link appears once expanded, downloading the same breakdown as a plain-text file.

Power usage (dropdown below Storage usage): a rolling average and peak of how many milliseconds the app spends reacting each second. A rising figure usually means a plugin panel left open somewhere is doing more work than it needs to — closing analytics panels you're not actively watching brings it back down.

Ticker Graylist: when MultiIndicator is enabled, the Stats menu shows a Ticker Graylist section listing symbols currently blocked from re-entry. It's empty when nothing is blocked. Each listed symbol clears itself automatically once the bulk ticker cooldown window elapses — no manual action needed.

Actions Dropdown

  • Export — Downloads current bot state (config, positions, closed trades, ban list, EDa state) as a .json file. Plugins with their own data (Permafrost/Ashfall profile, scorecard) have separate Export buttons inside their own accordions — the Stats menu Export covers the base bot state only.
  • Import — Restores state from a previously exported .json file. Config fields merge field-by-field; positions replace wholesale. A 5s debounce prevents accidental double-imports. Any config key that no longer belongs to a currently-loaded feature (the bot itself or an installed plugin) is dropped automatically on import and on every save — retired settings from an old config file don't linger indefinitely.
  • Clear Closed Trades — Wipes the closed trades list and resets session stats. Open positions are unaffected.
  • Clear All — Full reset. All positions, trades, stats, and config are wiped (config reverts to defaults).

Activity Log

Timestamped entries for every significant bot event. Color coding:

  • White — informational (scan results, entries, closes)
  • Yellow — warnings (halts engaged, API retries)
  • Red — errors (API failures, plugin conflicts)

Common prefixes: [MHL] manual halt · [DWN] drawdown throttle · [GLK] gains lock · [PST] (PseudoWinter) / [PERSIST] (PseudoChaser) save failures or recovered positions · [PFR]/[ASH] climate plugin events · [MIW]/[MIC] multi-indicator events.

The log is capped at 300 entries in memory and in localStorage. Oldest entries are dropped when the cap is exceeded.


Trades Menu

The trades panel shows a card for each closed trade, newest first. Each card carries a close-reason badge — TP, SL, FORCE (runtime limit), BAIL (drawdown throttle bail, Winter only), EDa (laggard debt-free close), or Sub (closed to free a slot for a higher-ranked candidate via MIW/MIC Substitution). Reasons introduced by other plugins show their own registered label, or the raw reason name if a plugin hasn't registered one.

Roll-up card: when the closed trades list exceeds 50 entries, the oldest are compacted into a single roll-up card showing their net PnL, trade count, and the date range they cover. The roll-up is not a trade — it is a historical summary. In the PnL chart, the roll-up's net value acts as a baseline offset applied to every plotted point.

PnL chart: click the PNL CHART bar below the header to expand a cumulative PnL line chart. The X-axis spans from the first to the last individual closed trade at fixed spacing. The chart is green when the net result is positive, red when negative. The chart only appears once at least 2 individual trades are closed.

CLEAR button: removes all closed trades and resets session stats. Clicking CLEAR reveals an inline confirmation ("Sure? Yes / No") before anything is deleted. Yes confirms; No cancels with no change.


MultiIndicator Plugin (MIW / MIC)

The Multi-Indicator plugin filters entries using configurable criteria combinations called slots. Each slot is an AND-gate: all criteria in the slot must be true for a ticker to qualify. Any single matching slot opens the ticker for entry.

Liquidation presence is mandatory, but it's a choice of three paths, not one fixed criterion — controlled by the Liquidation Presence setting (miwLiqPresenceModes/micLiqPresenceModes, below), a multi-select that can run any combination of:

  • Live — the slot anchors on exactly one of sliq/bliq/msliq/mbliq, fired the instant a liquidation message crosses the depth threshold mid-cycle, rather than waiting for the next scan.
  • 0-Liq — the slot anchors on 0liq. A ticker can only be confirmed liquidation-free once its surveillance cycle closes, so this stays on the regular scan cadence.
  • Past-1not a criterion. A Past-1 slot has no liquidation criterion in it at all; it's built entirely from secondary criteria. What makes it a Past-1 slot is that it's only ever matched against tickers with real recent liquidation activity that never qualified for Live (didn't cross the live threshold) or 0-Liq (wasn't clean) — see _miwPast1FreshSymbols/_micPast1FreshSymbols. The ticker-pool restriction is the anchor; there's nothing to tag in the slot or the scorecard.

A manual slot with no liquidation criterion is only valid while Past-1 is an active mode — otherwise (as before) it simply never matches, and the plugin logs a one-time warning on load listing how many.

Criteria

See Strategy_book.md's Market Reading section for what each criterion (fund, PEC, va, lsa/lba/rasl/rabl, ioa, sliq/bliq/msliq/mbliq, 0liq, Buy/Sell Skew, Order Count Deviation) means and when to use it. The mechanical notes below cover tiering, recording, and the depth gate — operational detail Strategy_book intentionally leaves out.

Tier gate: all tiered criteria (fund, va, lsa, lba, rasl, rabl, ioa, ocs, ocx) compute an integer tier as floor(value / step) and compare it against N. Current step sizes are shown as read-only chips under Tier Step Sizes on the Fetch tab. The same tier is recorded on the position and used as the scorecard key — lsa>25 and lsa+37 are different tiers and scored separately. PEC criteria (below) are matched differently — fixed thresholds, not a tier comparison — but still record a depth-based tier for scorecard purposes.

PEC (Price Effect Coefficient)

PEC replaces the old raw +24h/-24h ticker-field boolean with a graded read of where price has actually been across three timeframes — 6h, 12h, and 24h — each scored 0–100 (50 = neutral) from a composite candle built out of cached klines. Six criteria, all derived from the resulting 6h/12h/24h triple:

Criterion Fires when
pecob (PEC Overbought) 6h, 12h, and 24h all above PEC Threshold High (default 70)
pecos (PEC Oversold) 6h, 12h, and 24h all below PEC Threshold Low (default 30)
pecalpha (Red Mountain) 12h higher than both 6h and 24h — a peak on the middle timeframe
pecdelta (Green Delta) 12h lower than both 6h and 24h — a trough on the middle timeframe
pecmomup (Bullish Momentum) 6h > 12h > 24h — a pure, unbroken upward tilt across the whole day
pecmomdn (Bearish Momentum) 6h < 12h < 24h — the pure downward equivalent

pecalpha/pecdelta/momentum only compare the three readings to each other — none of the six pivot on a fixed midpoint the way the old removed pecbull/pecbear reversion pair did. Only pecob/pecos gate on Threshold High/Low.

Tie-break fallback: for any three distinct readings, exactly one of pecalpha/pecdelta/pecmomup/pecmomdn is true by construction. A tie between two of the three — most commonly a flat-range window, which the PEC calculation returns as exactly 50 rather than dividing by zero — fails all four strict checks, which would otherwise leave the ticker with no PEC criterion despite having valid data. _miwPecShapeMatch/_micPecShapeMatch then falls back to nearest-equivalent-by-magnitude: each archetype is scored by how close the triple comes to satisfying it, and whichever comes closest wins, even if that margin is ≤0. This doesn't apply to pecob/pecos, which are a separate fixed-threshold check.

Ticker scope: PEC is only ever computed for tickers whose liq surveillance batch just closed (tracked via registerLiqCloseHook, into the shared closed-batch pool _miwPecPool/_micPecPool) and are still within PEC Fresh Cycles of that close, capped per cycle at PEC Scan Cap. This is the same pool the Past-1 path draws from — every PEC-bearing slot already requires a liquidation anchor or the Past-1 path, so this adds no new fetch scope.

Wick dampening: when on, the range denominator used in the PEC calculation is the average of the individual sub-candle ranges within the window rather than the window's raw high-to-low, so one outsized liquidation-wick candle can't dominate the reading.

Funding emoji direction: the position/trade badge shows 🤑 or 💸 for a fund tier, and the two bots deliberately show opposite emoji for the same raw funding sign. It's not encoding the raw sign — it's encoding whether that funding condition favors the bot's own direction: longs paying shorts favors Winter's shorts (🤑) and costs Chaser's longs (💸); shorts paying longs is the reverse. Since Winter and Chaser trade opposite directions, the same funding reading is good news for one and bad news for the other.

OCS/OCX recording: on entry —

  • ocs records signed deviation-from-parity tiers, e.g. ocs+12 = 62% buy-dominant, ocs-8 = 42% buy / 58% sell.
  • ocx no longer records an absolute interval. It records signed tiered percentage deviation from a full-window population average — ocx+12 = this ticker's average inter-fill gap is running faster than the population average by 12 tiers (12 × step%; default 1%), ocx-8 = slower by 8 tiers.
  • The population average: _pfOcWindowAvgMs/_afOcWindowAvgMs (Permafrost/Ashfall) flattens every retained OC cycle (up to 25 — the same rolling history the OC chart already draws from), keeps only the latest reading per symbol across all of them, and averages the result. This is a stateless read over already-retained data — no new fetch, no new persistence. Both the scan-time pool and the live liq-trigger path read this exact same window, so a ticker's fast/slow classification means the same thing regardless of which path resolved it — the live path's single-ticker _ocFetchSingle reads the history but never writes to it, so it can't skew the population it's being compared against. There's no minimum-ticker floor: a thin or cold-start window (e.g. right after a fresh boot, or a long OC-disabled stretch) produces a noisy or unstable average — expected, not guarded against.
  • Unlike every other criterion, Order Count Surveillance data exists for essentially every ticker at all times — there are always orders flowing — so ocs/ocx are near-universally available rather than conditional on a data source being fresh or a pattern being present.
  • The OC sample (only fetched when a slot uses ocs/ocx) always includes whatever tickers this same scan just picked for liquidation surveillance, filling any remaining headroom with a random draw from the rest of the candidate pool — so OC data exists for exactly the tickers a liquidation event might be about to hit. The sample is sized to Permafrost/Ashfall's Liq Batch Size, not a separate cap. This same liq-surveillance bias carries into the OCX population average, since the window is built from these samples over time — by design, not an oversight; both entry paths sharing it is what matters, not debiasing it.

V/A / IO/A recording: replaces the old vm/iot/iom own-ratio criteria (ticker vs. its own market cap or turnover). Both are now population-relative, following the same design as OCX:

  • va records signed tiered percentage deviation of this ticker's 24h turnover from the population average — va+12 = running 12 tiers hotter than the sampled population (12 × step%; default 1%), va-8 = 8 tiers colder.
  • ioa records the same deviation for open interest value — ioa+12 = OI running 12 tiers above the population average, ioa-8 = below.
  • Both read the ticker's own live turnover24h/openInterestValue directly off the ticker payload — no fetch of any kind needed for the per-ticker side, live or scan path.
  • The population average: _pfVolIoWindowAvg/_afVolIoWindowAvg (Permafrost/Ashfall) — a sibling to _pfOcWindowAvgMs/_afOcWindowAvgMs above, same dedup-to-latest-per-symbol flatten over the same retained 25-cycle history. Volume and OI are sampled into that same tethered history alongside OC (Option A — one rolling window, one persistence store, guaranteed identical timing/ticker-set to OC by construction): the sampler seeds vol/oi straight from the ticker payload for every symbol in that cycle's list, and skips the recent-trade network fetch entirely on any cycle where no slot needs ocs/ocx — vol/oi sampling never costs a request of its own.
  • No mcap fetch, no supply cache, no CoinGecko/CoinPaprika/DexScreener waterfall, no sanity-cap guard against a wrong-coin match — the entire market-cap dependency this used to carry is gone. A ticker's own market cap (external, sometimes thin or mismatched) is no longer part of either criterion at all.
  • Same no-minimum-ticker-floor caveat as OCX: a thin or cold-start window produces a noisy or unstable average — expected, not guarded against.

Depth gate (sliq/bliq/msliq/mbliq): a live reading, checked the instant a liquidation message arrives.

  • sliq>N requires live sDepth ≥ N; sliq<N requires live sDepth ≤ N.
  • sDepth/bDepth are trunc(((sideTurnover / historicalAvg) − 1) × 100) — the liquidated side's turnover so far this message, compared to the average liquidation size recorded across all history (every ticker, every closed cycle; zero-turnover entries excluded so it isn't diluted by the majority of ticker/cycle combos with no liquidation that side).
  • +10 means this liquidation is running 10% above the historical average; -10 means 10% below. There's no upper ceiling; the practical floor is -100 (zero liquidation that side).
  • msliq/mbliq use the same depth value as sliq/bliq respectively.
  • On a manual slot, a depth suffix in the criteria picker overrides the general Live Depth Threshold (Config, below) for that slot only; leaving it bare falls back to the general threshold. Auto Slots always uses the general threshold, since there's no per-combo picker to set one.
  • The historical average is recomputed once per closed cycle (not per liquidation message), so a live reading mid-cycle is always judged against the average as it stood before the current cycle — same as the closed-cycle 0-Liq reading.

Config

Setting What it does
Enabled (miwEnabled/micEnabled) Master on/off. When off, the plugin opens no entries and runs no exits.
Picks (miwPicks/micPicks) Max new entries per scan cycle (1–10).
Share Cap (miwShareCapEnabled/micShareCapEnabled) Limits plugin entries to a percentage of maxPos. Prevents MIW/MIC from filling all position slots.
Share Cap % (miwShareCapPct/micShareCapPct) The cap percentage. At 50% with maxPos=6, MIW/MIC can hold at most 3 positions.
Kline Scan Cap (miwKlineScanCap/micKlineScanCap) Max tickers sampled per cycle for kline-based criteria (lsa/lba/rasl/rabl) fetches. Higher = broader coverage, more API calls.
PEC Granularity (miwPecGranularity/micPecGranularity) Sub-candle size for PEC's 6h/12h/24h composite windows: 15m×96, 1h×24 (default), or 3h×8. Finer = more precise, heavier fetch.
PEC Threshold High/Low (miwPecThresholdHigh/micPecThresholdHigh, miwPecThresholdLow/micPecThresholdLow) Gates pecob/pecos only (default 70/30) — the reversion, mountain/delta, and momentum criteria compare the three readings to each other or to the fixed 50 midpoint instead, and ignore these thresholds.
PEC Depth Step (miwPecDepthStep/micPecDepthStep) Index-point size of one depth tier for the collapsed-rank scorecard score (default 5). Strongest signal for pecob/pecos/momentum; noisier for reversion/mountain/delta since those don't scale linearly with distance from a threshold.
Wick Dampening (miwPecWickDampen/micPecWickDampen) When on, PEC's range denominator is the average of the individual sub-candle ranges within the window instead of the window's raw high-to-low, so one liquidation wick can't dominate the reading.
PEC Fresh Cycles (miwPecFreshCycles/micPecFreshCycles) How many scan cycles a closed liq batch's tickers stay eligible for PEC (and for the Past-1 path) before going stale. Default 4.
PEC Scan Cap (miwPecScanCap/micPecScanCap) Max freshly-surveilled tickers to fetch PEC candles for per cycle. Default 20. Doesn't limit Past-1 — that path checks the full pool, since it's a lookup against already-fetched liquidation data rather than a new fetch.
Tier Step Sizes (miwFundStep/miwVaStep/miwSpikeStep/miwIoaStep/miwOcsStep/miwOcxStep and mic equivalents) Read-only chip group on the Fetch tab showing the current tier step size for fund, va, lsa/lba/rasl/rabl (spike), ioa, ocs, and ocx. va/ioa/ocx steps are percentage-deviation-from-population-average steps (default 1% each), not raw units — see V/A / IO/A recording and OCS/OCX recording above. Not editable from the UI — change via config import if a different step is needed.
Cascade (miwCascadeEnabled/micCascadeEnabled) Closes every open position — any strategy's, not only MIW/MIC's own — when their collective unrealized profit hits a threshold. Banks a group move before it reverses. Checked continuously by the position watcher (every 5s while the bot is running), not just once per scan, so a threshold crossed and reversed between scans is still caught.
Cascade % (miwCascadePct/micCascadePct) Collective uPnL trigger as a % of base margin (minNotional ÷ leverage).
Sacrifice (miwSacrificeEnabled/micSacrificeEnabled) Closes every open position — any strategy's, not only MIW/MIC's own — when their collective unrealized loss hits a threshold. Caps group drawdown. Same continuous position-watcher check as Cascade.
Sacrifice % (miwSacrificePct/micSacrificePct) Collective uLoss trigger as a % of base margin (minNotional ÷ leverage).
Rolling Sacrifice (miwRollingSacrificeEnabled/micRollingSacrificeEnabled) When on, Sacrifice closes only the oldest open position at a time instead of all at once.
Target Halving (miwHalvingEnabled/micHalvingEnabled) Shrinks the Cascade/Sacrifice trigger threshold the longer the oldest open position (any strategy's) has been held, based on Halving Interval. This is continuous exponential decay, not a one-time halving — the multiplier keeps halving again every full interval that elapses (×0.5 after 1 interval, ×0.25 after 2, ×0.125 after 3, and so on with no floor), so a group left open for several intervals can trigger on a very small collective profit or loss.
Halving Interval (miwHalvingHours/micHalvingHours) Hours per halving step for Target Halving. The live hint below this control shows the oldest position's age and the multiplier it would apply on trigger right now.
Liquidation Presence (miwLiqPresenceModes/micLiqPresenceModes) Multi-select: Live, 0-Liq, Past-1 — any combination, each running its own anchor-matched slots side by side. At least one must stay selected. Requires Liquidation Surveillance in Permafrost/Ashfall — without it there's no liq data at all and no slot can ever match. Replaces the old exclusive Only-1/Only-0/Both toggle, migrated automatically on first load after update.
Slot Blocking (miwSlotBlockEnabled/micSlotBlockEnabled, miwSlotBlockPct/micSlotBlockPct) A per-criterion loss circuit breaker, independent of Liquidation Presence. If a triggering liquidation type's (sliq/bliq/msliq/mbliq/0liq) collapsed scorecard score — own trades plus the partner bot's inverted PnL plus Historical Scoring — drops beyond the configured % of base margin (minNotional ÷ leverage) in loss, new entries carrying that type stop opening. No manual clear needed: the block lifts the moment the score recovers, whether from a later win, Historical Scoring, or the partner bot losing on the same type. Past-1 has no anchor to block on — it's not a criterion, so there's nothing for this check to target; a Past-1 slot can still be blocked via Include Sign Tags below, on its secondary criteria. Pair with multiple active presence modes to let losing ones self-block instead of hand-picking which path to run.
Include Sign Tags (miwSlotBlockTags/micSlotBlockTags) Sub-toggle under Slot Blocking. When on, a losing score from any criterion selected in the Blockable Criteria picker directly below it also blocks entries carrying that tag, on top of the liq-type check above.
Blockable Criteria (miwSlotBlockCriteria/micSlotBlockCriteria) Chip picker, same interaction as Exclude from Auto, listing every secondary criterion as toggleable. Only shown when Include Sign Tags is on. Defaults to lsa/lba/rasl/rabl/all six PEC criteria/va/ioa. va/ioa are on by default — being population-relative rather than an own-ratio, a consistently losing deviation from the crowd is a meaningful signal worth pausing on. fund and ocs/ocx remain off by default: they're more generalized, since most entries across every slot share a similar fund tier or order-flow band regardless of outcome, so blocking on them risks pausing nearly the entire book off one bad stretch that had little to do with that specific reading. Enable with care.
Live Depth Threshold (miwLiveDepthThreshold/micLiveDepthThreshold) General live depth threshold (% vs. historical average liquidation size) applied to every Auto-Slot live liq anchor. Only shown when Auto Slots is on and the Live presence mode is active — manual slots set depth per-slot instead, via the criteria picker's depth suffix. This is also the threshold Past-1 checks retrospectively against each closed batch's dominant side, to tell "would have fired live" apart from "didn't beat the threshold."
Substitution (miwSubstitutionEnabled/micSubstitutionEnabled) When no entry slot is free (maxPos or Share Cap reached), closes the worst-scoring held position — any strategy's, not only MIW/MIC's own — and opens the best fresh candidate instead, but only if the candidate's collapsed score exceeds the held position's entry-time score by the configured Margin. Requires Co-Qualifying Penalty (Permafrost/Ashfall) — without it, every score is 0 and Substitution never fires.
Substitution Margin (miwSubstitutionMarginPct/micSubstitutionMarginPct) How much better the new candidate must score than the worst held position, as a % of base margin (minNotional ÷ leverage), before a swap happens. Prevents swapping on marginal score differences.
Substitution Min Age (miwSubstitutionMinAgeMins/micSubstitutionMinAgeMins) Minimum minutes a position must be held before it becomes eligible to be substituted out.
Protect Winners (miwSubstitutionProtectWinners/micSubstitutionProtectWinners) When on, a position currently in profit is never substituted out, regardless of how it ranks. Turn on if temporary winners in your markets tend to hold rather than reverse quickly, and should be shielded just for being ahead right now.
Protect Path-A (miwSubstitutionProtectPathA/micSubstitutionProtectPathA) When on, a live liq candidate (sliq/bliq/msliq/mbliq) can never substitute out a 0-Liq position — 0-Liq is the closed-cycle, higher-conviction read. A 0-Liq candidate can still substitute anything, live or closed-cycle. Turn off to rank purely by score regardless of which path opened a position.
Re-entry Block Mode (miwReentryBlockMode/micReentryBlockMode) Winners + Losers blocks a symbol from re-triggering for one bulk-ticker cooldown window after any close, win or loss. Losers Only lets a symbol that just closed in profit re-trigger immediately, blocking only a symbol that closed at a loss.
Self-Liq Graylist (miwSelfLiqGraylistEnabled/micSelfLiqGraylistEnabled) When on, any liquidation this bot's own surveillance records for a ticker — even one that never crossed the qualifying % threshold — graylists that ticker from the 0-Liq path for the last 25 liq batches. Redundant with 0-Liq Lookback above (which already checks the same retained window directly) but left on as a backstop. Only has an effect while '0' is an active Liquidation Presence mode — with only Live/Past-1 active, there's no 0-Liq path to guard.
Direction Lock (miwDirLockEnabled/micDirLockEnabled) When on, closing a live liq trade (sliq/bliq/msliq/mbliq) locks that exact type to that exact ticker for the last 25 liq batches: a win allows only that type to re-fire there, a loss excludes it. The Invert sub-toggle (miwDirLockInvert/micDirLockInvert) flips both — a win excludes the type instead, a loss locks it instead. Watch it working in the Ticker Locks stats section below the Hist Scoring panel. Only has an effect while Live is an active Liquidation Presence mode — with only 0-Liq/Past-1 active, no live liq entry is ever taken to lock.
0-Liq Lookback (miwLiqLookbackCycles/micLiqLookbackCycles) How many of Permafrost/Ashfall's retained closed liq cycles (up to 25) the 0-Liq slot criterion checks. A ticker only reads 0-Liq if it appeared at least once in that window and every appearance came back clean — not just its most recently closed cycle. Live sliq/bliq/msliq/mbliq entries aren't affected — there's nothing to go stale on a message that just arrived.
Auto Slots (miwAutoSlots/micAutoSlots) Replaces the manual slot list with a minimum-gate qualifier: a ticker qualifies once it satisfies a liquidation reading (or the Past-1 pool restriction) plus at least Minimum Criteria per Slot non-excluded secondary criteria — not a fixed-size combination. Every secondary criterion the ticker actually satisfies is captured and scored, not just enough to clear the floor. See _miwAutoQualify/_micAutoQualify.
Minimum Criteria per Slot (miwAutoSlotSize/micAutoSlotSize) The floor (1–5). For Live/0-Liq qualification this counts the mandatory liq anchor as one of them — at 1, the floor requires no secondary confirmation at all, though any secondary criteria the ticker happens to also satisfy are still captured and scored. Past-1 qualification uses the full value in secondary criteria instead, since there's no anchor to reserve room for.
Exclude from Auto (miwAutoSlotExclude/micAutoSlotExclude) Criteria omitted from Auto's qualifying set entirely — never checked, never counted toward the minimum, never scored. Excluding all liq types allowed under the current Liquidation Presence mode leaves nothing for Live/0-Liq to anchor on; Past-1 still qualifies normally as long as Past-1 is an active mode, since it doesn't need one.
Force-Evaluate General Criteria (miwForceGeneralCriteria/micForceGeneralCriteria) Auto mode only. fund, PEC, ocs/ocx, and ioa are expected to resolve for virtually any ticker once real data exists, but a match can end up missing several of them purely because that cycle's capped bulk fetch hadn't covered the ticker yet — not because they're actually false. When on: the live entry path force-fetches PEC on-demand for the entering symbol (kline/OC already did this unconditionally; PEC previously didn't); the scan-time open path (_miwOpen/_micOpen, via _miwTopUpGeneralCriteria/_micTopUpGeneralCriteria) re-checks fund/PEC/ocs/ocx/ioa with a forced, uncapped, per-symbol fetch — only for the handful of tickers actually about to open, never the whole pool — and appends any newly-true criteria, then recomputes compositeScore over the expanded set. Never drops a criterion the original match already found. ioa needs no fetch at all and is unaffected by this toggle either way — it's derived directly from the ticker snapshot plus the population window, so it was never missing for a data-availability reason. Costs a few extra requests per entry.
Historical Scoring (miwHistScoringEnabled/micHistScoringEnabled) When on, tickers that match a slot during a scan are tracked past that cycle. The bot waits for the next full 1h candle to close, then simulates whether that entry would have hit TP or SL — and writes the result to the shared scorecard as a historical record tagged separately from live trades. Builds slot history without requiring an actual open position. See Historical Scoring detail below.
Hist Tolerance (miwHistToleranceMins/micHistToleranceMins) Minimum minutes before the next hour boundary for a slot match to target that candle. If the boundary is within this window the match targets the following hour instead, ensuring the candle has enough time to fully form before observation.
Hist Sequester % (miwHistSequestrPct/micHistSequestrPct) Share of the kline scan cap reserved each cycle for confirming pending hist targets — e.g. a 50% share with a scan cap of 50 sends 25 slots to confirmation and 25 to discovery. Unused sequester slots roll over to discovery automatically.

Historical Scoring detail:

  • Data collection continues regardless of any block or halt mechanism active at the time — with one exception: with only Live active (0-Liq and Past-1 both off), new logging only runs during Drawdown Halt or Gains Lock, since real trades already cover the scorecard for every live match outside those windows. Any combination that includes 0-Liq or Past-1 is unaffected, since those resolve at scan time regardless of halt state.
  • Live-anchored slots (sliq/bliq/msliq/mbliq) can't be resolved by the scan-time checker at all, so they're logged from the same live liq-message feed that would otherwise open a real entry — during a halt, a message that matches a live-anchored slot is logged as a hist target instead of opening a position, using the exact same checks (banlist, Direction Lock, React to Partner 0-Liq Win, criteria match) a real entry would have used. This is what makes hist scoring possible at all with only Live active, since every one of its slots is live-anchored.
  • Duplicate prevention: the same symbol + slot + target candle combination can only be logged once, so repeated scans during the same candle window do not inflate records.
  • When a batch resolves, the activity log emits a numbered begin message and completion message — e.g. 📊 Hist-score batch #3 begun — 12 entries across 8 symbols. Batch numbers cycle 1–99.

Slots UI

Manual mode: click a slot to select it, then toggle criteria on/off in the picker row below. ✕ deletes the slot; + adds a new empty one. A slot needs a liquidation criterion to ever match — clicking sliq/bliq/msliq/mbliq opens the same depth picker described above, now setting that slot's live trigger threshold (or 0-Liq for the closed-cycle path, no depth to set) — unless Past-1 is an active Liquidation Presence mode, in which case leaving a slot with no liquidation criterion at all is valid: it's matched only against tickers on the Past-1 path.

Auto mode: replaces the manual builder with a minimum-slider and an exclusion chip row. A ticker qualifies on the liquidation reading (or Past-1 pool restriction) plus at least the chosen minimum of non-excluded secondary criteria — every criterion actually true is scored, not just enough to clear the floor. The hint under the slider states the current floor as "anchor + at least N of M secondary criteria."

  • Some criteria can never both be true for the same ticker at the same time: the three PEC opposite pairs (pecob/pecos, pecalpha/pecdelta, pecmomup/pecmomdn) and any two from the candle group (lsa, lba, rasl, rabl) — a candle only closes in one direction with one volume character at once. This doesn't need excluding anything to avoid dead combinations the way the old fixed-size generator did; a ticker simply can't ever contribute both sides toward its qualifying count.
  • lsa/lba/rasl/rabl and va can co-qualify freely for the same ticker now that va reads directly off the ticker payload instead of a capped market-cap subset — there's no longer a scan-cap-driven overlap gap between the two like there was with the old vm.

Permafrost / Ashfall Plugin

Permafrost targets PseudoWinter; Ashfall targets PseudoChaser. These plugins replace the fixed 12h drawdown/gains-lock timers with an adaptive halt system that learns from historical market conditions and trade outcomes.

They pair realized PnL from each close with a snapshot of market structure — breadth, momentum, and funding sentiment — building a recency-weighted profile over time. That profile drives a climate score that controls halt duration and signals downstream systems (the bots themselves) to adjust their entry and hold behavior accordingly. In practice, market regime (broadly bullish or bearish) is a significant driver of the learned profile, so the score reflects prevailing conditions rather than precise structural predictions.

During the first days of operation the plugin behaves almost identically to the stock timers. It withholds climate governance until enough evidence has accumulated near the current market reading.

Config

Setting What it does
Enabled Master toggle. When off, the bot uses the stock 12h halt timers.
Thaw/Settle Score Climate score the market must reach for an early halt lift. Higher = harder to thaw; bot stays halted longer in ambiguous conditions.
FIO Sentiment (permafrostFioEnabled/ashfallFioEnabled) Includes funding rate sentiment (which side is paying) in the climate score. Labeled FIO — funding-derived — to avoid confusion with the unrelated ioa (Open Interest) criterion.
Slot Scorecard (permafrostScorecardEnabled/ashfallScorecardEnabled) Records realized PnL per MIW/MIC criteria combination. Shows which slot types have been profitable or losing over time.
Sponge Quota (pfSpongeQuota/afSpongeQuota) How many recent closes per criterion are used to compute scores. Older records beyond this count are ignored. Lower = faster adaptation to recent performance; higher = more stable scores that smooth out short streaks.
Include Historical Scores (pfHistScoringEnabled/afHistScoringEnabled) When on, historical scoring records (written by the MIW/MIC Historical Scoring feature, tagged hist: true) are included in slot score calculations. When off, only live closed-trade records count. Independent of the MIW/MIC Historical Scoring toggle — turning that off in MIW/MIC only stops new historical entries from being generated; existing ones remain in the scorecard until this toggle is turned off or the sponge quota pushes them out. Turning this off while records exist immediately reduces slot scores to the real-trade-only baseline; slots with no real-trade records disappear from the scorecard entirely until live trades accumulate.
Cross Broadcast (permafrostCrossEnabled/ashfallCrossEnabled) Writes cascade/sacrifice closes, drawdown halt/gains-lock transitions, live liquidation events, and 0-Liq wins to a shared log that the partner bot can read. Required for Mutual DDH Lift and both React toggles below.
Mutual DDH Lift (permafrostMutualDdLiftEnabled/ashfallMutualDdLiftEnabled) When both bots are simultaneously in drawdown halt, lifts this bot's halt. Checked every 15 s. Requires Cross Broadcast to be on.
Gains Continuation (permafrostGainsContinuationEnabled/ashfallGainsContinuationEnabled) When the partner bot reaches its gains threshold and broadcasts a Gains Continuation signal, arms this bot's own drawdown halt for a full configured duration — same as if this bot's own drawdown throttle had just triggered, including bailing open positions if Drawdown Bail is on. Checked every 15 s. Requires Cross Broadcast to be on. Independent of this bot's own Gains Lock setting — only Drawdown Throttle needs to be on for this to apply.
React to Partner Live-Liq (pfCrossLiqGraylistEnabled/afCrossLiqGraylistEnabled) When the partner bot logs a live liquidation on a ticker, graylists that ticker from this bot's own 0-Liq path for 6 hours. Only has an effect while '0' is an active Liquidation Presence mode on this bot — with only Live/Past-1 active, there's no 0-Liq path to protect.
React to Partner 0-Liq Win (pfCrossWinGraylistEnabled/afCrossWinGraylistEnabled) When the partner bot wins a 0-Liq trade on a ticker, graylists that ticker from this bot's own live liq entries for 6 hours. Only has an effect while Live is an active Liquidation Presence mode on this bot — with only 0-Liq/Past-1 active, there's no live path to protect.
Stale Slot Purge (pfStaleSlotDays/afStaleSlotDays) Slots with no new close in this many days are fully removed from the scorecard on the next trim. Keeps the scorecard clean when criteria combinations fall out of use. Configurable 1–90 days.
Co-Qualifying Penalty (pfCoQualPenaltyEnabled/afCoQualPenaltyEnabled) When on, the composite score for each ticker is adjusted downward for every additional slot (beyond the best match) that the ticker qualifies for and that carries a negative collapsed score. A ticker matching one good slot and two losing slots is ranked lower than one that only matches the good slot. Only negative co-qualifying scores penalise — positive co-qualifying slots do not boost.
Depth Multiplier (pfCoQualDepthPct/afCoQualDepthPct) Scales every criterion's collapsed score by how far past that slot's own gate threshold the ticker qualifies, both for the best-match slot and any co-qualifying penalty slots — not by the raw tier value. E.g. a criterion scoring +$0.50 historically is applied as +$0.70 for a ticker qualifying 4 tiers past its slot's threshold at 10%/tier. Works the same in reverse — a losing criterion is penalised harder the deeper past threshold the ticker qualifies. Depth is direction-aware: for a < gate (va<N, ioa<N, ocx<N) a lower measured value is the deeper match, since those criteria consider low readings the extreme case. Range 0–50%.
Liquidation Surveillance (pfLiqEnabled/ashLiqEnabled) Opens WebSocket connections to track live liquidation flow across a rolling sample of volatile tickers. Required for sliq/bliq criteria in MIW/MIC.
Liq Batch Size (pfLiqBatchSize/ashLiqBatchSize) Tickers per liquidation batch (5–50). More tickers = broader market coverage per cycle. Also sizes MIW/MIC's OC ticker sample — see OCS/OCX recording in the MultiIndicator section.
0-Liq Sequester (pfLiqSequesterEnabled/ashLiqSequesterEnabled) When on, a ticker whose most recently closed batch read clean gets priority for resurveillance ahead of the random mover pool, bypassing the ≥6%/≤-6% 24h move requirement (other filters — USDT pair, price floor, not already active — still apply). Keeps a calm ticker's 0-Liq read from going stale just because it stopped moving. Evicted the moment it liquidates.
Sequester Draw Cap (pfLiqSequesterCap/ashLiqSequesterCap) Max sequestered tickers pulled into any one batch (default 12). Not a hard cap on how many tickers can be sequestered at once — if more qualify, the most recently reconfirmed clean are drawn first each cycle and the rest rotate in later.
Liq Threshold % (pfLiqThresholdPct/ashLiqThresholdPct) Minimum share of a cycle's total liquidation turnover one side must hold to qualify (10–90%). At 50%, one side must account for at least half.
Presence Regime Threshold (pfPresenceSkewThreshold/ashPresenceSkewThreshold) Aggregate B-Liq or S-Liq turnover share (50–95%) needed to call the market "dominant" one way or the other. Not scored or traded here directly, and currently has no active consumer since MIW/MIC's Auto Liquidation Presence and Speeder's Auto Speed Mode were both replaced by Slot Blocking.
Presence Regime Window (pfPresenceSkewWindow/ashPresenceSkewWindow) How many of the most recently closed liq cycles to aggregate for the regime read (0–25). 0 uses the entire retained history. Same currently-unconsumed status as Presence Regime Threshold above.
When Regime Is Mixed (pfPresenceMixedMode/ashPresenceMixedMode) Previously governed what Auto-mode consumers (MIW/MIC, Speeder) did when neither side crossed the Presence Regime Threshold. No active consumer now that both have been replaced by Slot Blocking.
Order Count Surveillance (pfOcEnabled/afOcEnabled) Fetches a fixed number of recent trades for the tickers in MIW/MIC's scan candidate pool. Required for ocs/ocx criteria in MIW/MIC. Each fetch is a fresh, independent snapshot — no accumulation or deduplication across cycles.
OC Order Limit (pfOcOrderLimit/afOcOrderLimit) Recent trades fetched per ticker per scan cycle (10–500). Buy/sell skew and average order interval are both computed from this single sample.

WAVE Tab

The WAVE tab holds display and analysis config controls: which sampling bars and charts to show (Structure / Funding / Liq / Vol toggles), Slope Window, Collective FIO toggle, and Liquidation Surveillance setup and config. The Danger Zone (Export / Import / Clear Profile / Clear Plugin State) is also accessed from this tab.

The wave chart, sampling bar displays (kline direction, funding skew, liq flow, volume), scorecard chip row, and liquidation results chart all appear directly in the accordion body — no tab needs to be clicked to see them.

The wave chart has three overlay toggles: Structure (the market lean path), FIO (funding sentiment line — named for its funding-rate derivation, distinct from the ioa Open Interest criterion), and Score (a gray line derived from the slot scorecard). When Score is on, a percentage readout appears below the chart showing the net scorecard balance as a share of total recorded weight — green when positive, red when negative.

Score line during halt: a drawdown halt or gains lock only pauses new position entry — scans keep running in full, so structure sampling, liquidation/OC surveillance, and the scorecard all keep collecting data. If this bot's own wave score is still unavailable for some other reason, the score line falls back to the partner bot's most recently published wave score. When the scorecard is thin, the wave score falls back to raw kline momentum from the last completed hour candles across the sampled ticker set.

Gaps in chart history: the wave chart's Structure/FIO/Score lines break the line across a real data gap (the bot off, or unable to sample) instead of drawing a straight connector across the missing period. A resumed session starts a fresh line segment rather than dragging the old one forward to the latest point. The gap threshold is padded above Scan Interval so ordinary scan-timing jitter is never mistaken for a real gap, while a genuine multi-cycle miss still breaks the line.

Status Block

Shows the current climate reading (magnitude, breadth, slope, FIO score, effective score, evidence mass), and active halt state (profile-governed or fallback timer). The wave graph plots recent market structure — direction label (rising/falling/steady) reflects the recent path of the market.

Two directional bar charts below the climate reading show relative dominance at a glance. Red extends left (adverse for this bot's direction), green extends right (favorable), with current values as a label. A drawdown halt or gains lock only pauses new position entry — this bot's own scans, and with them these bars, keep updating normally. Both bars also read from the partner bot's sample state every 15 seconds as a backup, so the display stays populated even if this bot's own sampling is thin or the bot is off.

Bar What it shows
1h Kline Bear vs. bull aggregate from the last completed 1h candle sample.
Funding Rate Neg vs. pos funding skew across the kline + liq ticker union.
Volume Sample Below-average vs. above-average volume share of the current kline sample, weighted by deviation magnitude. Gray extends left (below average) and thematic color extends right (above average). Only appears when the Volume fade signal is enabled.
Order Interval Sample Per-ticker bar chart, scrollable through history, with an OC / Vol / IO mode toggle in its header. OC (default) shows average seconds between orders (orderbook velocity) — a slower/quieter ticker draws a taller bar, busier/faster draws shorter. Vol and IO switch the same chart to the tethered 24h-turnover and open-interest samples instead — see Sample Chart detail below. Only appears when Order Count Surveillance is on and at least one sample has been taken. Not the same data as the Volume Sample bar above, which is kline-derived and unrelated.

Sample Chart detail:

  • The OC / Vol / IO toggle switches which of the three tethered samples the chart, its avg-value line, and its chip list below all display — they're read from the same underlying cycle history (see V/A / IO/A recording in the MultiIndicator section), just a different field per mode. Selection isn't persisted across reloads; it resets to OC.
  • OC mode: an Avg order interval line below the chart shows the mean seconds/order across every ticker in the displayed cycle. Tickers averaging over 12s/order are left off the chart so a handful of illiquid outliers don't stretch the axis and shrink every other bar to a sliver — they're still fully eligible for ocx/ocs entry criteria and still appear in the chip list below.
  • Vol/IO mode: an Avg volume/Avg open interest line shows the mean across the displayed cycle, formatted compactly (e.g. $1.2M). No outlier cap — these are the same population-relative values va/ioa compare against, so nothing is hidden from the chart that the criteria themselves can see.
  • Each cycle group is stamped with its sample time (HH:MM) and clickable, same as the Liq Sample chart — clicking one pins the summary and chip list to that cycle's per-ticker data. Clicking anywhere outside returns to the latest cycle, which is also what shows with nothing pinned.
  • Records left over from the pre-redesign OC system (a single raw order number instead of the buy/sell split) are purged from stored history automatically on load and on profile import.

Requires MultiIndicator: the Funding Rate Sample, Volume Sample, Order Count Surveillance, and the Slot Scorecard are all computed by MIW/MIC's own sampling pass and disappear entirely if MultiIndicator isn't loaded — they are not shown empty, they don't render at all.

Slot Scorecard

Slot Scorecard (Chaser/Winter View) — one chip per base MIW/MIC criterion (e.g. fund>, va>, pecob) with PnL pooled across all slots that contained it. Only shown when MIW/MIC is both loaded and enabled. Purple highlighting marks a criterion currently contributing to a Slot Blocking pause — hover a chip for the exact reason.

CLEAR wipes the record store. Each close writes one record; the Sponge Quota controls how many recent records per criterion are factored in, so scores always reflect the most recent N closes and adapt quickly to shifts in market behavior. MIW/MIC uses its own chart's per-criterion scores to order its entry queue — slots are ranked by the sum of their individual criteria scores. A slot with one losing criterion and one winning criterion ranks by their combined total.

A live position close isn't the only thing that updates the scorecard. Each completed Historical Scoring batch writes its own records and refreshes the scorecard the same way, so scores can shift between trades whenever Historical Scoring is enabled — see the Hist Scoring panel below.

Win/loss counts can appear high — this is normal. A criterion shared across many slots accumulates records from all of them. The Sponge Quota caps contributions per criterion, not per slot, which is what makes the scorecard responsive.

MIW/MIC builds a composite score for each candidate ticker before sorting the entry pool. The composite starts with the ticker's best-matching slot score. If Co-Qualifying Penalty is on, any additional slots the ticker qualifies for are inspected: those with negative criterion scores subtract from the composite. A ticker that satisfies one strong slot but also satisfies two consistently losing slots ranks lower than a ticker that only satisfies the strong slot. Slots with positive scores do not boost — only negative co-qualifying scores penalise.

The Both / Hist / Traded source filter (pfScorecardSource/afScorecardSource) cycles through which score records are included in the displayed chips. Both shows all records. Hist shows only records written by the MIW/MIC Historical Scoring feature. Traded shows only records from actual live closed trades. This is a display-only filter — it does not affect which records count toward collapsed scoring. Selection is persisted.

The Combined / Own toggle (pfScorecardView/afScorecardView) switches between: Combined (includes partner bot trades, PnL inverted) sorted by blended total; and Own (this bot's trades only). Selection is persisted.

Clicking a chip in Combined mode shows the raw partner win total; in Own mode it shows the raw own loss total. Clicking again or switching sort mode returns to the normal view.

CLEAR wipes all records in the shared store.

Hist Scoring panel: when Historical Scoring is enabled, the Stats menu also shows a Hist Scoring section with the current count of pending simulation targets, a countdown to the next expected batch (shows "next scan" once the window has elapsed), and a list of completed scoring batches (newest first). Each batch entry shows the batch number, wrote/total counts, win count (W), loss count (L), net simulated PnL, and the clock time the batch completed (same-day batches show HH:MM; older ones show month, day, and time). With only Live active, this section only appears during Drawdown Halt or Gains Lock — see the Historical Scoring row above.

Ticker Locks panel: when any of Self-Liq Graylist, React to Partner Live-Liq, React to Partner 0-Liq Win, or Direction Lock is enabled, the Stats menu shows a Ticker Locks section — one line per currently-affected ticker, listing every reason that currently applies to it (Self-Liq / Partner Live-Liq / Partner 0-Liq Win / the liq type for Direction Lock), each tagged LOCK (green) or EXCLUDE (red), plus the clock time the last of those reasons expires. Only shows a reason if it's actually relevant to the bot's current Liquidation Presence modes — Self-Liq/Partner Live-Liq only matter while '0' is active, Partner 0-Liq Win/Direction Lock only matter while Live is active, so a reason with no current effect doesn't clutter the panel. Empty when nothing is currently locked.

Liquidation Feed

The Liquidation Flow bar (B-Liq vs. S-Liq share of the full retained liq turnover window) sits directly above the Feed Watcher panel below. Toggled by the Liq sampling-bar switch; only appears when Liquidation Surveillance is on and there's turnover to show.

When surveillance is on: the Feed Watcher panel shows active batches (batch ID, ticker count, running S-Liq / B-Liq USDT totals, dominant side, countdown). The Liq Sample chart shows up to the last 25 closed cycles as stacked bars (S-Liq green / B-Liq red, qualifying segments at full opacity). Each cycle's bar group is clickable — clicking one pins the Highlighted Cycle chip grid below to that cycle's per-ticker qualification, with a label showing that cycle's time when it isn't the actual latest one. Clicking anywhere outside the chart or the chip grid returns Highlighted Cycle to the actual latest cycle, which is also what it shows by default with nothing pinned. Below the chart, a summary line ("Highlighted B-Liq % / S-Liq %") totals turnover for whichever cycle is currently pinned (or the latest one, if none is), alongside a second line totalling every ticker's latest known reading regardless of cycle ("All").

Each ticker's chip badge reflects the same 70%/30% classification MI's live criteria checker uses, not a flat pass/fail: 🥵 S-Liq or 🥶 B-Liq at ≥70% dominance, dimmer 💦/🌨️ (mixed) badges for a 30–70% majority. A near-even split (e.g. 55%/44%) shows as a dim mixed badge rather than looking identical to a decisively one-sided cycle.

Danger Zone

Export downloads one combined .json file with everything the plugin tracks — structure wave (events/closes/wave trajectory), scorecard records, liquidation cycle history, and OC cycle history (which now also carries the tethered volume/OI samples used by va/ioa — see V/A / IO/A recording in the MultiIndicator section). Import restores all of it from a previously exported file in one step; any field missing from the file is left untouched. Clear Plugin State removes all profile data and halt state from localStorage and memory. Use before uninstalling the plugin to avoid orphaned data, or to guarantee a fully clean slate. Irreversible.

Automatic storage pruning: structure wave, liquidation samples, OC samples, and the shared scorecard are each capped independently at 200KB. If one alone grows past that on a save, its own oldest records are dropped until it's back under budget — other data types aren't touched. This is deliberately per-data-type rather than one shared budget, so a spike in one (e.g. a burst of liquidation activity) can't force pruning of unrelated history (e.g. structure wave) that's still well within its own budget. The Stats menu's Storage usage dropdown shows each of these individually, so a bloated data type is easy to spot before it hits the cap.

The cross-bot shared registry is also capped, at 200KB — dropping its oldest per-symbol entries across all its internal caches (klines, watch tickers, liquidation results, ...) until back under budget, same as the history types above.


Randomized Outcomes

Multiple instances of the bot running simultaneously will naturally diverge in behavior:

  • Scan timing drifts independently per tab, so two instances launched minutes apart will hit different market states even with identical config.
  • Several data inputs are drawn randomly each cycle: the sample of tickers used to compute market breadth (red/green candle tally), the batch of tickers watched for live liquidation flow, and the kline lookups used for spike criteria all pull from different random subsets each time.

The practical effect is that no two instances share the same entry triggers, exit timing, or structural reading at any given moment — even when configured identically. This is intentional. Instances that move in lockstep are easier to front-run and more likely to cluster losses at the same market event. Divergence distributes risk across slightly different entry points and market reads without requiring any coordination between instances.


Multiplex Plugins

To maximize efficiency within single-file browser execution, the system architecture supports Multiplex Plugins. Unlike standard plugins that independently isolate their telemetry, a multiplex variant hooks directly into the flattened component created when all plugins are loaded, using the structural pipelines—core data arrays—API batched payloads, and state tracking structures without wrapping or reassigning parent methods. This cross-dependencies model dramatically reduces resource consumption and mitigates multi-plugin race conditions by treating the master surveillance/execution engine as a shared database/resource.

The Speeder Module (Tentative Multiplex)

Located in /plugins/multiplex/, Speeder leverages existing functions in MultiIndicator and data provenience in Ashfall/Permafrost. This direct-read capability allows it to tap directly into the rolling Order Count (OC) Surveillance histories and entry criteria builder.

  • What it does: Rather than assessing order flow via arbitrary millisecond barriers, Speeder dynamically splits the entire deduplicated pool of recent per-ticker trade intervals at the median during each scan.

  • How it does what it does: To filter out noise, Speeder does not qualify a ticker simply for landing in the fast or slow half; the ticker's specific trade interval must exceed that collective half’s independent mean—ensuring an extreme, mathematical divergence from the baseline market velocity.

  • When it does what it does: Adhering strictly to MultiIndicator's precedent, Speeder uses an automatic selection method for determining entry criteria (fast or slow), employing a base configuration dependent on the liquidation regime. Speeder can enter fast/slow tickers in hot or cold regimes.

  • When it doesn't: If the foundational surveillance plugins are completely absent from the flattened component, Speeder logs a clean failure warning and remains safely inactive.

Note: The Speeder strategy is tentative and lacks long-term historical validation; it remains isolated within the multiplex directory for demonstration purposes and architectural testing.


Trivia

Developer-level detail with no operational consequence. Included for reference.

localStorage Keys

Key Contents
pw_v1 PseudoWinter: cfg, positions, sess, closedTrades, bot timestamps, symbolBanlist, lostValue, laggardId
pw_v1_log PseudoWinter activity log (capped at 300 entries)
__pw_plugins_v1 PseudoWinter serialized plugin list
pc_v1 PseudoChaser: same structure as pw_v1
pc_v1_log PseudoChaser activity log
__pc_plugins_v1 PseudoChaser serialized plugin list
__ew_shared_v1 Cross-tab shared data registry (bulkTickers, watchTickers, klines_1h, klines_1h_last, pec_{granularity}_last, liqResults)
__ew_sample_state_v1 Cross-bot sample state written by Permafrost/Ashfall after each structure cycle. Contains state.winter and state.chaser — each carrying waveScore, fundSkew, oiSkew, klineBar, and liqHistory. Read every 15 s by the partner bot to keep displays current during halts.
__pf_liq_batches Permafrost active liq batch snapshots (for reconnect on reload)
__ash_liq_batches Ashfall active liq batch snapshots
__pf_liq_sequester Permafrost 0-Liq sequester membership (symbol → last-qualified timestamp)
__ash_liq_sequester Ashfall 0-Liq sequester membership
__permafrost_winter_v1 Permafrost profile: events, samples, wave history
__ashfall_chaser_v1 Ashfall profile
__everwinter_scorecard_v1 Shared slot scorecard written by both plugins. Each close is one record; each slot retains up to the Sponge Quota most recent records.
__miw_hist_batches MIW Historical Scoring batch history. Object containing batches (up to 25 completed records — each with batch ID, timestamp, entries written, total candidates, win count, loss count, and net simulated PnL) and fundSkew (last funding sample bar state).
__mic_hist_batches MIC Historical Scoring batch history. Same structure as __miw_hist_batches.
__ew_creds EverWinter live plugin API credentials
__sc_creds SunChaser live plugin API credentials

Cross-Tab Data Pool

Both bots share market data via localStorage.__ew_shared_v1 and BroadcastChannel('ew_shared'). Writes are last-write-wins per data type. Either bot operates normally solo — the registry is simply absent and all ladder checks fall through to normal fetches.

Plugin Transform Pipeline

pw()  →  plugin[0].transform(def)  →  plugin[1].transform(def)  →  ...  →  Alpine

Each plugin's transform(def) receives and returns the component definition. Load order matters for method wrapping — strategy plugins must declare after: ['everwinter'] / after: ['sunchaser'] so live-trading plugin wraps are innermost.

Bybit API Endpoints Used

Public: GET /v5/market/tickers, GET /v5/market/kline, GET /v5/market/instruments-info. WebSocket: wss://stream.bybit.com/v5/public/linear (liquidation feed). Signed (live plugins only): GET /v5/account/wallet-balance, GET /v5/position/list, POST /v5/order/create, POST /v5/position/trading-stop, POST /v5/order/cancel. Signing: HMAC-SHA-256 via crypto.subtle.sign; 250ms minimum gap between signed requests.

About

A browser-based crypto trading bot.

Topics

Resources

License

Stars

3 stars

Watchers

1 watching

Forks

Packages

 
 
 

Contributors