Skip to content

docs(config): correct the "unvalidated skip set" claim on the live allowlist - #185

Merged
eaitbrahim merged 3 commits into
mainfrom
docs/reassess-unvalidated-skip-set
Aug 8, 2026
Merged

docs(config): correct the "unvalidated skip set" claim on the live allowlist#185
eaitbrahim merged 3 commits into
mainfrom
docs/reassess-unvalidated-skip-set

Conversation

@eaitbrahim

@eaitbrahim eaitbrahim commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

What

Re-assessment of a judgment carried in a live-money config, config.live-sandbox.yaml, directly above the real-money allowlist:

# The 5-trend Turtle set (same as the paper-forward + the walk-forward/PBO analysis).
# SOL/LTC/LINK are deliberately excluded -- they're the unvalidated skip set.
allowlist: [BTC, ETH, PAXG, ADA, XLM]

Verdict: the decision is right; the stated reasons were mostly wrong. The comment is rewritten to say what's actually true, and the working is recorded in a new experiment doc. The allowlist is unchanged.

What the old comment got right

"Same as the paper-forward" is accurate at the rule levelkeel.db's paper-status rules are exactly 10/11/12 (BTC/ETH/PAXG) + 22 (XLM) + 24 (ADA), i.e. the live 5. That's a coherent origin story for the exclusion and the PR now credits it.

What it got wrong

  • "The walk-forward/PBO analysis" describes work that does not exist for these assets. Every walk-forward/PBO/ablation run in docs/experiments/ stops at BTC/ETH/PAXG. trials-ledger.jsonl symbol census over 69 rows: BTC 32, ETH 33, PAXG 32, and 0 each for ADA, XLM, SOL, LTC, LINK. The walk-forward that exists tuned a parameter (turtle_breakout.py:113, entry_lookback 20 → 40).
  • "Unvalidated" doesn't distinguish anything. None of the five live assets was validated either. keel-live.db rules 1–5 carry promoted_at IS NULL — seeded straight to live through the bypass rules seed warns about, and left in place 14 days.
  • No compliance asymmetry. SOL/XLM/LTC/ADA were attested in the same second (2026-07-23 12:15:12); LINK 160s later under the same governing source. All three excluded assets ADMIT keel assets screen and carry more daily history (1827 bars) than PAXG (456, on the list only via a documented waiver).
  • Wrong gate. The comment attaches a rule-level reason to an asset-level control; rail 1 (guards.py:369) is a flat membership test consulting neither attestations nor rule status.

The measurement nobody had run

The old comment guessed. Running keel rules backtest against a copy of keel.db settles the direction:

rule asset n_trades win rate expectancy pf
21 SOL 13 23.08% −12.41 0.259
23 LTC 5 0.00% −13.09 0.000
25 LINK 15 20.00% −0.665 0.630
22 XLM 8 37.50% +0.056 11.44
24 ADA 6 50.00% +0.121 5.52

All three excluded assets are negative-expectancy; LTC won none of five. The exclusion is correct — now for a reproducible reason instead of an invented one.

Stated honestly: n = 5–15 against min_trades = 100, in-sample, one window, candles 6 days stale for the excluded three. A directional check, not validation. None of the five clears the gate — which is why the allowlist is unchanged, and why the new comment explicitly warns against reading a positive expectancy as licence to add an asset.

What this PR does NOT do

The allowlist is unchanged. No asset attested, no rule promoted, no production database written — backtests ran against a scratchpad copy; ~/keel/keel.db's mtime is untouched.

Verification

  • load_config yields an identical allowlist, caps and weights; a comment-stripped diff against main shows no non-comment differences.
  • python -m pytest tests/ -q2078 passed. (uv run pytest fails to import keel_core on a clean tree too — pre-existing, unrelated; this diff touches zero Python.)

Review corrections (second commit)

An independent adversarial review caught three false/unsupported claims in the first commit, two of them in the live config:

  1. "Nothing has traded" was FALSEkeel-live.db holds signals=1, a filled live order (BTC-USD BUY 0.000778 @ 64267.30) and an open position from the properly-promoted dca rule 6. The deployment is not inert and carries exposure. Removed.
  2. The min_trades argument used the wrong mechanismrules promote gates on a candle backtest (commands/rules.py:180), not trade_outcomes. Conclusion unchanged, now resting on ADA n=6 / XLM n=8.
  3. "Never been backtested" was unprovable and self-contradicted the doc's own point that the backtests table is dead schema (db.py:140, zero writers). Dropped.

Plus: credited the true paper-forward half, softened "same source" for LINK (its attestation deliberately classifies it a utility token), and made the entry_lookback quote verbatim.

Open operator items

Recorded in the doc, not actioned here:

  1. Deployment drift~/keel/config.live-sandbox.yaml still has the old comment; sync it.
  2. keel-live.db carries almost no compliance state — screening the live allowlist against a copy, 0 of 5 admit; SOL is ironically the only asset it admits. Harmless (rail 1 reads config, not the DB) but inverts the comment's picture.
  3. Live-seeded rules left in place 14 days, against rules seed's own instruction.
  4. Stale candles — re-run the backtests after keel fetch before relying on them.
  5. Two open attestation questions — LINK's staking floor is emissions-funded; LTC has carried MWEB (opt-in confidential transactions) since May 2022.

🤖 Generated with Claude Code

eaitbrahim and others added 3 commits August 7, 2026 21:13
…lowlist

`config.live-sandbox.yaml` carried, directly above the real-money allowlist:

    # The 5-trend Turtle set (same as the paper-forward + the walk-forward/PBO analysis).
    # SOL/LTC/LINK are deliberately excluded -- they're the unvalidated skip set.

Every part of that is false, and it entered git as an inherited assertion: the file was
tracked in 183dcdb as a backup, and no commit, PR or design doc ever introduced or justified
the exclusion. The phrase appears nowhere else in the repo.

- No walk-forward/PBO run has ever covered ADA or XLM. Every such run in docs/experiments/
  stops at BTC/ETH/PAXG. The walk-forward that exists tuned a PARAMETER (entry_lookback
  20 -> 40); it never validated a set of assets.
- SOL/LTC/LINK are not excluded on compliance grounds and failed nothing. All three were
  attested 2026-07-23 in the same batch as ADA/XLM -- same attestor, same source -- and
  ADMIT `keel assets screen`, carrying MORE daily history (1827 bars) than PAXG (456, on
  the allowlist only via a documented screen_exceptions waiver).
- The comment attaches a rule-level reason to an asset-level control. Rail 1 is a flat
  membership test that consults neither attestations nor rule status; what actually makes
  SOL/LTC/LINK inert is the absence of a live-status `rules` row.
- The live set didn't pass the promotion gate either: keel-live.db rules 1-5 have
  promoted_at IS NULL, seeded straight to `live` through the bypass `rules seed` warns
  about. trade_outcomes and signals are empty for every product against min_trades=100,
  so ADA/XLM's paper promotion cannot have been earned on evidence either.

The one true reading -- SOL/LTC/LINK have never been backtested -- is equally true of the
five assets that are live, which is what makes "the unvalidated skip set" the wrong name.

The allowlist itself is UNCHANGED. Correcting a false rationale is not grounds to act on
the decision it described; admission stays the operator's call through the deterministic
gate. Comment-only: load_config yields an identical allowlist and caps.

Also fixes the header's stale "(gitignored)" -- the file has been tracked since 183dcdb.

Full re-assessment, including open operator items (deployment drift, keel-live.db carrying
almost no compliance state, live-seeded rules left in place 14 days, stale SOL/LTC/LINK
candles), in docs/experiments/2026-08-07-unvalidated-skip-set-reassessment.md.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
… claims

Independent review of #185 found three false or unsupported claims, two of them in the
live-money config comment, and one omission that changes the conclusion's basis.

Corrections:

- "Nothing has traded: trade_outcomes and signals are empty for every product" was FALSE.
  trade_outcomes is empty, but keel-live.db holds signals=1, a FILLED live order (BTC-USD
  BUY 0.000778 @ 64267.30, rule_id=6) and an OPEN position, both 2026-08-07 01:12:50, from
  the dca rule 6 -- which IS properly promoted. The deployment is not inert and carries
  exposure. Saying otherwise above a live allowlist is the worst defect here.
- The min_trades argument used the wrong mechanism. `rules promote` gates on a candle-driven
  backtest (commands/rules.py:180), not trade_outcomes. Conclusion unchanged but now rests on
  the real numbers: XLM n_trades=8, ADA n_trades=6, against min_trades=100.
- "Every stated reason is false" was OVERSTATED. The parenthetical's paper-forward half is
  TRUE: keel.db `paper`-status rules are exactly 10/11/12 BTC/ETH/PAXG + 22 XLM + 24 ADA,
  i.e. the live 5. That is a coherent origin story, and it is now credited rather than
  dismissed. Only the walk-forward/PBO half was invented.
- "Have never been backtested" was UNPROVABLE and self-contradicted -- this same doc argues
  the backtests table is dead schema, so absence of a record proves nothing. Claim dropped.
- "Same source" flattened LINK's attestation, which deliberately classifies it a UTILITY
  token (ERC-20; 'native' chosen only because the enum lacks a 'utility' slot). Softened.
- entry_lookback annotation now quoted verbatim from turtle_breakout.py:113.

And the omission that mattered: the previous comment said "revisit once `keel rules backtest
21/23/25` has been run" without running it. Run now, against a COPY of keel.db:

    21 SOL   n=13  win 23.1%  expectancy -12.41   pf 0.26
    23 LTC   n= 5  win  0.0%  expectancy -13.09   pf 0.00
    25 LINK  n=15  win 20.0%  expectancy  -0.66   pf 0.63
    22 XLM   n= 8  win 37.5%  expectancy  +0.06   pf 11.44
    24 ADA   n= 6  win 50.0%  expectancy  +0.12   pf 5.52

All three excluded assets are negative-expectancy; LTC won none of five. So "there is no
negative result anywhere for SOL/LTC/LINK" was wrong -- there is one, and it was ten seconds
away in data already in keel.db. The exclusion is the right call, now for a reproducible
reason rather than an invented one.

Stated with the sample sizes in view: n=5..15 against min_trades=100, in-sample, one window,
candles 6 days stale for the excluded three. A directional check, not validation. NONE of the
five clears the gate, which is why the allowlist is still unchanged and why the comment now
explicitly warns against reading a positive expectancy as licence to add an asset.

No production database was written: backtests ran against a scratchpad copy; ~/keel/keel.db
mtime is unchanged.

Verification: load_config yields an identical allowlist/caps/weights; a comment-stripped diff
against main shows no non-comment differences; 2078 tests pass.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…station

Second review pass. All findings were non-blocking wording; two mattered enough to fix.

- **Compare on profit factor, not expectancy.** Expectancy is quote-currency per trade, so it
  tracks the asset's price -- BTC's +1353.99 and XLM's +0.056 are not commensurable, and the
  column read as a ranking would put BTC four orders of magnitude "ahead" of ADA purely because
  a bitcoin costs more. On the scale-free metric the split is clean and states itself: every
  excluded asset is pf < 1, every included asset is pf > 1. Added BTC/ETH/PAXG rows (10/11/12:
  n=13/13/4, pf 1.61/1.21/3.25) so the included cohort is shown rather than asserted.
- **"NONE of the five" was ambiguous** in a config whose own opening line says "The 5 assets
  this sandbox trades" -- the table's five were SOL/LTC/LINK/XLM/ADA. Now "not one of the eight
  rules above", with the live five explicitly included, and it is shown for all eight rather
  than left unshown. ETH's 30.77% win rate also sits under the canonical min_win_rate 0.55.
- **"The real reason SOL/LTC/LINK stay off" overstated it.** The measurement is dated
  2026-08-07, ~2 weeks after the 2026-07-24 exclusion, so it cannot have been the reason it was
  made. Reframed as a post-hoc vindication; the actual reason remains unrecorded.
- Staleness qualifier now applies only to SOL/LTC/LINK (the allowlisted rows are current).
- Epoch timestamps labelled UTC/EDT rather than bare local.

New item the review surfaced, now open item 3 rather than an aside: keel-live.db's sole
attestation is SOL, written 2026-08-08 00:29:43 UTC -- same-evening, ~44 min before this
branch's first commit -- and its `source` is a STAKING page, which sits awkwardly against its
own pays_yield=0 and against every keel.db attestation's "bare unstaked spot only" framing.
Not written by this work (scratchpad copies only; ~/keel/keel.db mtime unchanged, all queries
mode=ro), and keel-live.db is the live agent's own DB, so it is written continuously -- but
provenance should be confirmed, not assumed, and the staking source is a compliance question
for the operator independent of this document.

Verification unchanged: load_config identical, comment-stripped diff against main empty,
2078 tests pass.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@eaitbrahim
eaitbrahim merged commit d12d3ce into main Aug 8, 2026
1 check passed
@eaitbrahim
eaitbrahim deleted the docs/reassess-unvalidated-skip-set branch August 8, 2026 04:25
eaitbrahim added a commit that referenced this pull request Aug 8, 2026
…ays_yield=0 (#186)

Follow-up to #185, correcting a claim I made there.

Open item 3 said the live-DB SOL attestation's `source` (solana.com/staking) "sits awkwardly
against pays_yield=0". Fetching the page shows the opposite. It states: "In order to earn
staking rewards ... the tokens in a stake account must be delegated to a validator," with no
rebasing and no automatic distribution to holders. Bare holding earns nothing -- which is
precisely what pays_yield=0 asserts. The citation is direct evidence FOR the field, not
against it.

The real gap is narrower and different: it is the wrong KIND of source. AssetAttestation.source
is documented as "where this was established -- a URL, a standard, a scholar's ruling." A vendor
product page establishes the mechanical fact but not the RULING that a native L1 coin is Mal
Hukmi, lawful to own and trade. Every keel.db attestation carries both (KB source-86 + the
three-layer screen reasoning + "Attests bare unstaked spot only"); this row carries only the
mechanical half, implicitly. screen.py:249 cannot tell the difference -- it checks
source.strip() is non-empty and nothing more.

Provenance also resolved, and it was an open question worth closing rather than leaving as
"should be confirmed": ~/.zsh_history records the exact command at epoch 1786148982, one second
before the row's attested_at, preceded by a placeholder attempt and two `keel fetch --products
SOL-USD` runs. Hand-typed at the terminal -- not an agent, not the daemon.

Added: SOL now carries two attestations with different evidentiary bases, so which governs
depends on which --db a command runs against; and the page's ~8% initial inflation decaying to
1.5% means a bare holder is diluted rather than paid, which is a scholarly question rather than
one this file can answer. None of it is live-reachable -- SOL is not in the live allowlist and
has no rule in keel-live.db, so rail 1 blocks any SOL intent regardless.

Docs-only; no code, no config, no database touched.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant