How a hypothesis is scored

The method, published in full before any verdict — so a stranger can check every number, not take it on trust. The standard every published number must clear is set out in our validity principles. House rules and rules you register in Compete → Test run through the same evaluator, applied evenhandedly.

⬇ picks.csv ⬇ outcomes.csv Validation dashboard ↗ Test-mode leaderboard ↗ Live Gate-1 status ↗

1The pick log is the only judge

Every screened name is written to picks.csv before the outcome is known, with a timestamp. The log is append-only — rows are never edited or deleted, and every write is sealed into a tamper-evident hash chain. Grading writes to a separate outcomes.csv keyed by pick_id. If a claim isn't reproducible from these two public files, it isn't evidence. Backtests are used only to choose what to test — never as a performance claim.

Why we never re-download a historical price. Price history is restated whenever a company splits, so a price downloaded today is not the price that was on the screen at the time. Mixing the two invents returns that never happened. We store every price forward-only at grade time and reconcile it before use — a discipline we adopted the hard way, after finding this bug in our own code. The full write-up →

Record integrity — how you'd catch me editing history

The forward log (picks.csv, outcomes.csv, paths.csv) is append-only: rows are written before the outcome is known and never edited. But "append-only" is a promise, so it's backed by something a stranger can check.

Every scan, grade, and weekly report seals a row into integrity_ledger.csv: the SHA-256 of each log file plus a running chain hash that folds in the previous row. Editing any historical file — or any past ledger row — breaks the chain from that point forward, and the break is provable, not merely suspicious. The genesis row was sealed 2026-07-06.

file_sha            = sha256(raw bytes of the file)
prev_chain(genesis) = "0" * 64
chain               = sha256( prev_chain | picks_sha | outcomes_sha | paths_sha | ts | event )

Verify the entire history yourself, in one command:

python log_integrity.py --verify        # recompute the chain; exits 1 on any break
python log_integrity.py --verify-head   # also confirm current files match the last seal

The logs and the ledger are also uploaded as GitHub Actions artifacts on every run — a store independent of git history, so they survive a force-push or a bad rebase. You can spot-check the live seal against the public integrity_ledger.csv.

What this does and doesn't prove. It proves the published record has not been quietly rewritten since the genesis seal. It does not make the files physically unchangeable — I control the repository. The honest word is tamper-evident, not immutable: you don't have to trust me, you have to be able to catch me. The one remaining gap — the chain head lives in the same repo — is now closed by snapshotting the ledger to the Internet Archive on every run — a copy I don't control, so you can check the seal against one I can't rewrite: archive.org/web/*/thepicklog.vercel.app/integrity_ledger.csv.

2The return we measure is one you could actually get

Five trading days after a pick is logged, it's graded on the regular-session open → close return — enter at the day's open (not the pre-market print nobody can be filled at), exit at that day's close — net of a 2% round-trip cost haircut for wide low-float spreads. That net figure is the headline.

3Exit rules

A hypothesis is scored under one exit:

ExitReturn recorded per pick
same_day_closeThe open→close net return above (the default baseline exit).
target_T (+5/10/15/20%)If the 5-day MFE reached +T%, take +(T−2)% net (the target minus the 2% haircut); otherwise fall back to the 5-day close return.
target_T_stop_SSame target, plus a stop: if the 5-day MAE fell to −S%, take −(S+2)% net. When both the target and the stop are reached in the window, the stop is assumed to fire first (see caveat) — otherwise the 5-day close.

Slippage is real. Target exits assume the +T% limit fills exactly. On thin floats limits gap through, so live results run worse than the proxy. And because outcomes.csv records only the best (MFE) and worst (MAE) excursions — not their order — a stop-loss rule that hits both levels is scored as if the stop triggered first (conservative, so a stop can never over-credit itself). Both caveats appear on every affected readout.

4Pre-registration & the out-of-sample window

A rule is frozen with a registration date. Only picks whose trading_date is after that date count toward its score — that's the out-of-sample (OOS) test. A pattern spotted in data already seen overfits by construction; the date stamp is what turns it into a genuine test. Registered rules can't be edited, deleted, or backdated — only retired. Because the log is append-only, a rule frozen today has nothing pre-existing to fit against: it starts at zero picks and earns its record as new picks accumulate.

5The number on the board: expectancy delta vs baseline

Each rule is compared to a shared same-day-close baseline over the post-registration window. The headline Δ vs baseline is the difference in mean net return per trade (in percentage points). For a filter it's the kept picks' mean minus all picks' mean; for an exit it's the paired per-pick difference (same picks, its exit vs the close). We report the full distribution — mean, median, % positive, and MAE — never a lone win rate, which is the easiest number to game.

A third kind, a question, is scored exactly like a filter but makes no directional claim — it asks "does this trait help or hurt?" and lets the confidence interval be the answer. Questions are shown on the board but never ranked as if higher were better, because there's no claim to rank.

6Honesty about noise is the whole point

7What you can register (pick-time fields only)

A rule may only reference fields that are known at the moment the pick is loggedprice_at_screen, float_shares, gap_pct, rvol, short_interest_pct, tier — plus an exit from the fixed set above. Multiple conditions can be combined to match all of them (and) or any of them (or). Outcome columns are rejected, so no rule can reference the future. This whitelist is enforced both in the browser and again on the server at registration.

8Reproducible by anyone

One evaluator (hypo_eval.py, standard-library only, deterministic) scores house and user rules identically, and a self-test aborts the build if its numbers ever drift from the weekly report's hand-computed figures. Every value on the leaderboard re-derives from the public picks.csv × outcomes.csv. The Validation dashboard recomputes the house hypotheses live in your browser from those same files.

9The validity argument — including where it fails

The full construct-validity case behind this method is published too, mapped to Messick's six aspects (content, substantive, structural, generalizability, external, consequential) with an open gap register and a Uniform Guidelines cross-check — and it does not hide the parts that currently fall short. The headline finding is a structural one: the momentum tiers rank intensity (and drawdown), not forward return — the top tier historically has the worst mean net and the deepest drawdowns — which is exactly why tiers are labelled as a heat scale, not a quality grade. Read it in full: Validity framework & gap analysis, with its domain / coverage spec and structural monotonicity check (reproducible from the two CSVs above). Four empirical studies extend it — substantive, structural & discriminant tests (incl. the near-inert rvol weight and the screen being indistinguishable from the broad pool), a generalizability & consequential write-up (regime-dependence, intended-use/misuse, reflexivity), and a §15 validity dossier that indexes the whole record. Findings feed pre-registered forward tests (H-SUB1, H-STR1/2, H-REG, H-CTRL, H-REFLEX) — never fit in-sample. The method specs are public too: the validation plan & pick-log spec, the Quality-Lens downside test plan, and an independent code-fidelity QA report.

Educational / informational only — not investment advice. ThePickLog is a personal research instrument. The model is unvalidated until the sample and out-of-sample bars above are cleared. Low-float, low-priced stocks are highly volatile and carry substantial risk of loss. Past performance does not predict future results. (Prototype — sample copy pending legal review.)
Disclaimer · Privacy