Skip to content

Releases: CryptoGnome/dlmmbot

v0.26.2 — re-entry sizing goes under measurement

Choose a tag to compare

@CryptoGnome CryptoGnome released this 28 Aug 12:38
75effa1
  • Telemetry only — nothing about how the bot trades changes. Every same-token re-entry (2nd/3rd within 24h) now logs a reentry_ladder_deferred decision recording the 0.75×-ladder size actually used next to what full size would have been.
  • Why: on the live book, 2nd entries are the best cohort — 59 closes, 66% win rate, +0.79 SOL, against 51% / +0.72 across 117 first entries — so the ladder shrinks exactly the strongest trades. The 3rd-entry cutoff itself measures correct (3rd entries: 40% win rate, net negative) and is untouched.
  • Rows are retention-exempt, so the experiment accumulates instead of being pruned. A few weeks of live data decides whether the shrink should start at the 3rd entry instead of the 2nd — same instrumented-off process that promoted the give-back stop.
  • No new config keys, no operator action needed.

v0.26.1 — the daily-loss circuit breaker can now be switched off

Choose a tag to compare

@CryptoGnome CryptoGnome released this 28 Aug 12:15
c950d41
  • circuit_daily_loss_pct = 0 now disables the daily-loss circuit breaker (new entries no longer pause on a 24h realized-loss threshold). Previously 0 meant a zero threshold — any loss paused entries forever.
  • Shipped default is unchanged (3). Disabling is a per-operator choice in data/config.toml, hot-reloaded, no restart needed.
  • The cluster brake (lossy hard-exit bursts) and HALT are unaffected.

v0.26.0 — give-back stop goes live

Choose a tag to compare

@CryptoGnome CryptoGnome released this 28 Aug 11:46
5c214f0
  • New exit rule, on by default (meme sleeves only): the give-back stop. Once a position has been up past min(0.02 SOL, 5% of entry) counting banked fees, it closes the moment PnL falls back to 75% of that peak — leave before the round-trip completes. The token is benched 15 min like an escape; exits show as "Give-back stop" in the dashboard feed. Knobs: give_back_enabled, give_back_keep_frac (hot-reloaded). Promoted after a month of watch-only telemetry: replay +2.657 SOL over 120 closes, and the 20 live triggers since 08-22 net +0.857 SOL — including both BANDOS stops of 08-28.
  • stop_loss_count_claimed_fees decided: stays off. Its pre-registered live-telemetry week found zero wick-rescues; the stops it would have deferred kept falling (median trough ~-70%). Verdict recorded in STRATEGY.md.
  • Live closes now log a same-instant Jupiter quote next to the exit swap (exitSwap in the close event), so swap cost is measurable separately from market drift. Observation only — never delays or blocks a close.
  • New npm run sim:skips: backfills the price path after each scanner rejection so gates can be judged on what they actually blocked; backfilled rows are exempt from DB pruning.
  • No operator action needed: missing config keys back-fill from the template on deploy.

v0.25.0 — the bot now refuses pools it cannot build a proper range on

Choose a tag to compare

@CryptoGnome CryptoGnome released this 26 Aug 11:29
460e5ac

Nothing about how the bot trades changes today. Both changes are verified no-ops on the current book.

  • New entry gate. Some pools use very fine price steps, so a 40%-deep range would need 256 or 512 bins when the bot can only place 138. It used to quietly enter with a third of the range it meant to — that is how positions ended up 11–15% deep against a floor of 40, with nothing in the logs saying so. Now it skips the pool, logged as range_too_shallow. Checked against history: 0 of 142 meme positions would have been blocked.
  • Majors untouched. The fine-step pools are ANSEM / PUMP / MET / ORE. They trade those legitimately and plan their ranges through a separate path, so the sleeve is unaffected — a gate applied there would have blocked 29 of 34 of its positions.
  • No new setting to manage. The gate reads min_down_pct and max_position_accounts, so it always matches the depth floor you configured.
  • stop_loss_sustain_polls_in_range added and proven to do nothing. The stop had no wick tolerance while in range. Tested 1→4 over 138 replayed positions: no effect at any value, because every stop on the book fires below range, where the existing 4-poll wait already applies. Kept as instrumentation; default 1 is exactly today's behaviour.

Caveat: the measurement behind the gate is driven by the majors cohort, not the meme sleeve. It is a guard against silently entering a partial range, not a proven profit improvement.

v0.24.0 — the escape hatch's width bug is now measured in production, and the build pill tells the truth

Choose a tag to compare

@CryptoGnome CryptoGnome released this 26 Aug 09:49
72b813c

Nothing about how the bot trades changes in this release. The escape hatch still fires on exactly the rule it always has.

  • The escape hatch has a real width bug, and it is now being measured. It arms on a fraction of range depth, so the trigger price moves with how wide the range is — −26.4% on a 40%-deep range, −19.3% on a 30%-deep one, −8.8% on a shallow one. The fix (absolute drawdown from entry) is built but switched off: replayed against the book it changes 14 of the 96 positions the current rule reproduces faithfully — four carried by a single row, and ten are real escapes where no recorded data can say what holding would have done. The bot now logs an escape_absolute_deferred decision whenever the two rules disagree, so a week of live data decides instead of a backtest.
  • New config keys, all inert by default — back-filled into your existing data/config.toml automatically, no action needed: escape_hatch_absolute = false, escape_hatch_drawdown_pct = 26.4, escape_hatch_recovery_drawdown_pct = 12.0.
  • The dashboard build pill and Changes tab were showing the wrong release. The deploy watcher fetched branch refs but never tags, so git describe stayed frozen at clone time — staging reported v0.22.0 while main was two releases ahead. Fixed. Action: existing checkouts need one git fetch --tags to catch up; the watcher keeps them current after that.
  • npm run sim can overlay escape_hatch_absolute to replay either form of the hatch.
  • New: RANGE-WIDTH-DECISION.md — a pre-registered rule for testing a narrower range, written before the data exists. The widely-shared −75% argument does not survive this book: 0 of 176 closed positions ever traded that deep, and 12 of the 13 that passed −50% had already been closed by P0/P1.

v0.23.2 — no transaction depends on the RPC websocket any more

Choose a tag to compare

@CryptoGnome CryptoGnome released this 25 Aug 00:06
bab9562
  • Finishes what v0.23.1 started. sendAndConfirmTransaction confirms through an onSignature websocket subscription, so it was only as available as the ws endpoint. With Helius answering that endpoint 429 once a second, every confirm was guaranteed to fail while the transactions landed perfectly over HTTP — that is how a rent reclaim reported has expired: block height exceeded for a tx that had already succeeded.
  • send() now broadcasts with sendTransaction and resolves every outcome through signatureFate(), which polls getSignatureStatuses and distinguishes expired from unknown via isBlockhashValid. That distinction is what the no-double-execute rule depends on, and a bare confirm cannot make it.
  • Behaviour preserved, checked against the web3.js source: sendTransaction always overwrites recentBlockhash/lastValidBlockHeight, signs, and forces a new blockhash when the derived signature repeats — so retries still produce a different signature and tx.recentBlockhash is exactly what was signed. skipPreflight: false is kept, so program failures still abort rather than retry. Nothing is resent before the previous attempt's fate is known.
  • Verified on live money before release: a real rent reclaim confirmed on the server (+0.00207 SOL) with zero tx attempt … failed lines since deploy. The identical operation two hours earlier logged has expired: block height exceeded and had to be recovered.
  • ws error: 429 may still appear in stderr; nothing on the critical path reads that transport any more.

v0.23.1 — swap confirms no longer depend on the RPC websocket

Choose a tag to compare

@CryptoGnome CryptoGnome released this 24 Aug 23:45
88fd4cc
  • The 429 storm was the cause, not background noise. web3.js implements confirmTransaction with an onSignature websocket subscription, so a confirm is only as available as the RPC's ws endpoint. Helius has been answering ours with 429 once a second for hours, making every swap confirm guaranteed to time out at 30s while the transactions landed fine over HTTP. That is where pos#104's not confirmed in 30.00 seconds came from — v0.23.0 made the fallout recoverable, this removes the cause.
  • swapToSol / swapFromSol now confirm by polling getSignatureStatuses on the same HTTP endpoint everything else already uses. Both still attach the signature on timeout, so v0.23.0's recovery keeps working if a confirm fails for another reason.
  • Effect: closes stop taking an extra 30 seconds per swap and stop emitting spurious "swap failed" errors while the ws is refused.
  • The executor's own send() is unchanged — it already resolves timed-out attempts by polling via signatureFate(). Converting it away from the initial ws stall is the next step.
  • The ws 429 itself remains a Helius quota matter; the bot simply no longer depends on that transport for swaps.

v0.23.0 — exit swaps that timed out no longer book as total losses

Choose a tag to compare

@CryptoGnome CryptoGnome released this 24 Aug 23:36
8ecf5a4
  • A close whose Jupiter swap timed out was booking the whole token side as a loss. On a below-range exit the swap is the exit value — the remove-liquidity tx returns little more than rent. When the confirm timed out, the slippage ladder correctly detected the swap had landed, logged landed after all (wallet now 0) — and then returned null, the caller's "no swap happened" value, so the signature never reached the close's wealth delta.
  • What it cost: Railway pos#104 PUMP booked −0.719 SOL / −88.8% on a position that came back roughly flat (0.070 SOL from the remove + 0.695 SOL from a swap 44 seconds later, against a 0.750 deposit). The phantom loss tripped the daily circuit breaker one second later and the bot stopped entering.
  • Fix: swapToSol attaches the signature to the confirm error instead of losing it with the throw, and the ladder hands it back whenever the wallet proves the tier landed — between tiers and after the last tier, which had no re-read and lost the same money on the final rung. It never invents one: no signature recovered still returns null, and now says so in the log.
  • New: npm run repair-close -- <id…> [--apply] (dry-run by default) for rows the bug already wrote. Reads the chain, not the ledger: a transaction counts only if the wallet sold that position's token for SOL near the close and the close did not already book it. Credits recovered_sol, leaving close_return_sol as the honest record of what the close could measure. Records a per-signature receipt, so re-running is a no-op.
  • New: REPAIR_CLOSES env var — Railway has no shell; set it to a comma-separated list of ids and redeploy to repair before the bot opens the DB. Safe to leave set, and it never blocks startup.
  • Seven rows were affected (Railway pos#104/#122/#123/#124, server pos#186/#187/#188), all inside a window of RPC 429s that made confirms expire. Nothing would have restated them — stranded_sol and the residual sweep only recover tokens left in the wallet, and these were sold. Server rows already repaired: +0.0539 SOL restored, all three flipping from negative to positive.

v0.22.0 — Helius spend cut ~6x: marks read positions by key, polls every 20s

Choose a tag to compare

@CryptoGnome CryptoGnome released this 24 Aug 18:02
fd017a7
  • RPC credits per open position: 2.59M/month → 0.39M. Marking was essentially the whole Helius bill. Each mark ran a getProgramAccounts — 10 credits on Helius, vs 1 for everything else we call — asking the program for every position the wallet holds in the pool, then threw away all but the accounts already recorded in position_accounts. Marks now read those accounts by key, and take the active bin from the lbPair that refetchStates() just refreshed instead of paying getActiveBin() for a value already in hand. Measured on mainnet against SDK 1.9.14: 15 credits → 3 per mark.
  • manage.poll_s default 15 → 20, taking the remainder from 0.52M to 0.39M per position/month. A three-to-four position book was exhausting the 10M/month Developer plan; it now runs at roughly a fifth of it.
  • Action required to get the poll change: existing installs read their own data/config.toml, not the repo template. Set poll_s = 20 in dashboard Settings (hot-reloaded, no restart) on each bot. The mark change needs nothing — it ships with the deploy.
  • Poll-counted windows are a third longer now, deliberately: stop_loss_sustain_polls 60s → 80s, meme rotation_polls 45s → 60s, majors rotation_polls 30min → 40min, follow.cold_polls_end 45s → 60s. The counts were left unrescaled on purpose — changing them would change how many independent samples back each decision, which is what a "sustain" knob is for. Watch the P1 stop confirming 20s later. interval_s stays an exact multiple (60 = 3 × 20), so scans still snap to a tick.
  • Safety moved the right way. trackedButMissingOnChain existed because a lagging node answers getProgramAccounts with [] and no error, which became valueSol 0 → pool_dead → a fabricated -open_cost_sol on a position still sitting on chain. A keyed read cannot fail that way silently, and a miss on any tracked account now fails the mark — where the old all-or-nothing guard would still have marked a two-account position at half value if one account went blind.
  • Verified, not just reasoned: a live mainnet position returns identical positionData (amounts, feeX/feeY, bin bounds, version) through the new path, and a bit-identical active-bin price. Typecheck clean, 418 tests green.

v0.21.0 — Parallel position marking + a working RPC fallback

Choose a tag to compare

@CryptoGnome CryptoGnome released this 21 Aug 16:27
954579f
  • Manage ticks are no longer serial. Every open position used to be marked one at a time, so a tick cost the sum of their RPC latencies (4–5 round trips each, including a getProgramAccounts). Marks now run concurrently across pools — never twice within the same pool, so tranche pairs and re-entries are unaffected. Same API calls, same rate-limit budget; they just stop queueing behind each other.
  • New knob: manage.mark_concurrency (default 4), hot-reloaded like the rest of [manage]. Set it to 1 to restore the old strictly-serial behaviour if your RPC provider starts throwing 429s. Optional — an install whose config.toml predates the key keeps working.
  • RPC_URL_FALLBACK finally fails over. It has been offered in the dashboard as "used if the primary RPC fails", but nothing read it: every call site built its own connection on the primary, so an outage took the bot down with a backup node sitting idle. Failover is now per-request with a 20s per-attempt timeout, and a recovered primary is used again immediately.
  • Errors keep their cause chain, so a boot-reconcile fetch failed now names the endpoint that failed instead of dead-ending.

Watch the first few ticks after deploy: if 429 backoff ladders get worse in the logs, drop mark_concurrency to 2.