α σ Alpha Capital
Equity Research Infrastructure · Built Solo

Alpha Capital

A production-style market-data and machine-learning platform for testing U.S. equity signals under point-in-time, survivorship-correct, cost-aware conditions.

Six live data integrations feed a lineage-tracked PostgreSQL evidence spine; models train only on features knowable at the decision timestamp and are judged with purged walk-forward validation.

PythonPostgreSQLscikit-learnGoogle CloudSQLAlchemypytest
6 APIs
market data · filings · news · brokerage
2M+
lineage-tracked PostgreSQL rows
13K+
securities reconstructed · incl. delisted
72K+
signal observations · 30-month replay
At a Glance

Built a research platform rigorous enough to reject its own leading strategy.

The Problem

Most backtests are fiction.

A strategy that looks brilliant on historical data is usually measuring a mistake, not an edge.

The common failures all share one root: the test quietly uses information that wasn't available at the time. It scores against today's surviving companies and silently drops the ones that delisted or went to zero. It lets full-day or future values leak into features. It assumes perfect, costless fills.

Alpha Capital was built to answer a single, strict question for every signal:

"Could this have actually been known, traded, and validated at the time — net of cost?"
Research Scope

A research factory, not one strategy

Each research direction starts from a literature-backed market mechanism, then runs through Alpha Capital's own point-in-time, survivorship-corrected, cost-aware pipeline. The papers motivate hypotheses; they do not substitute for validation. Most are supposed to die in that pipeline; the value is a system honest enough to tell which few don't.

Post-earnings-announcement drift
Prices keep drifting after a large standardized earnings surprise as information is slowly incorporated.
SUE-ranked · market-cap sensitive · drift front-loaded d1–3
Academic anchors: Bernard & Thomas (1989, 1990) · Martineau (2021) · Vamossy (2025)
52-week-high breakout momentum
New 52-week highs on volume expansion tend to continue rather than mean-revert.
Price-derived · survivorship-backfillable
Academic anchors: Jegadeesh & Titman (1993, 2001) · Daniel, Hirshleifer & Subrahmanyam (1998) · Daniel & Moskowitz (2016)
Insider-cluster accumulation
Multiple insiders buying within a short window signals informed conviction ahead of the market.
SEC Form-4 sourced · survivor-bias sensitive
Academic anchors: Cohen, Malloy & Pomorski (2012) · Das (2025)
Day-0 gap & volume events
Large overnight gaps on volume spikes, where the move may continue or reverse intraday.
Intraday · information-arrival lens
Academic anchors: MacKinlay (1997) · Brown & Warner (1985) · Christie, Corwin & Harris (2002) · Heston, Korajczyk & Sadka (2010)
Capitulation-volume bounce
Deeply distressed names that print a capitulation volume spike bounce over the short term.
Cost-dominated; see the worked example below
Academic anchors: Hong & Stein (1999) · Amihud (2002) · Frazzini, Israel & Moskowitz (2018) · Sullivan, Timmermann & White (1999)
One spine, many bets
Every pattern is just a hypothesis: scored by the same leakage-clean features, labeled by the same cost-aware returns, judged by the same out-of-sample gauntlet.
Reusable research infrastructure
Academic anchors: Sullivan, Timmermann & White (1999) · MacKinlay (1997) · Brown & Warner (1985) · López de Prado, Advances in Financial Machine Learning

Literature-backed, not literature-proven: the citations define mechanisms and known failure modes; Alpha Capital re-tests every hypothesis against its own leakage-guarded, cost-aware validation stack.

Architecture

How it works

An automated, end-to-end pipeline — from six provider integrations to validated, leakage-controlled research artifacts.

Sources
Polygon · FMP · Nasdaq · SEC EDGAR · Benzinga · Alpaca
Market data, reference data, listings, filings, news, and quote/execution evidence.
Ingest
Automated nightly pipeline
A dedicated GCP VM runs idempotent collectors with provider-specific rate limits, retries, and run-status logging.
Fail-closed run guards
Store
PostgreSQL evidence spine
Normalized provider payloads, source attempts, row hashes, and run metadata in one lineage-tracked store.
2M+ rows · hash provenance
Reconstruct
Point-in-time universe engine
Rebuilds the tradable universe as it existed on each historical date, including delisted and dead companies.
Survivorship-correct
Model
Feature contracts + ML rankers
Versioned manifests and allowlists ensure the model sees only decision-time features.
Leakage-audited predictors
Validate
Cost-aware walk-forward verdicts
Purged splits, quote/slippage labels, cash handling, and JSON/Markdown artifacts before any promotion.
Promote only if it survives

Architecture controls

Provider evidence
Every provider call records status, source, payload hash, and attempt count, so missing data is never confused with no signal.
Scratch isolation
Heavy rebuilds run in scratch schemas; canonical tables are protected from experimental writes.
Point-in-time clocks
Evidence date, decision timestamp, execution timestamp, and label window are modeled as separate clocks.
Feature contracts
Versioned manifests pin allowed predictors and reject banned forward / full-day / outcome fields.
Reproducible artifacts
Each experiment emits hash-stamped JSON and Markdown reports, plus the event tapes it ran on.
Fail-closed gates
Checksum, row-count, manifest, and lineage mismatches halt the run instead of producing partial results.
The output of the architecture is not a backtest curve; it is an auditable research record.
The Data

Six providers, one point-in-time evidence spine

Alpha Capital normalizes market data, listings, filings, news, and quote evidence into a lineage-tracked PostgreSQL store. Each row is tied back to the provider attempt that produced it, so the system can distinguish a real no signal from missing data, a provider failure, a parser failure, or an intentional exclusion.

Polygon
Used for: daily and intraday OHLCV bars for historical replay, decision-time features, and forward path diagnostics.
Why it matters: intraday timestamps enforce what was knowable before the decision minute.
Financial Modeling Prep
Used for: reference data, fundamentals, split-adjusted daily context, and historical company metadata.
Why it matters: prior-day context and universe reconstruction that don't rely only on today's survivors.
Nasdaq
Used for: listing / archive evidence and tradability / universe support.
Why it matters: reconstructs which securities existed historically, including names that later disappeared.
SEC EDGAR
Used for: official filings and company-event evidence.
Why it matters: issuer and catalyst context, and a basis for poison-news / dilution risk filters.
Benzinga
Used for: news and catalyst feed.
Why it matters: separates price/volume events with real information behind them from pure mechanical churn.
Alpaca
Used for: quote and brokerage evidence.
Why it matters: spread, stale-quote, tradeability, and cost-realistic entry/exit assumptions.

Scale

6 provider APIs 2M+ lineage-tracked rows 13K+ securities reconstructed 30-month replay window 72K+ signal observations delisted / dead companies included quote / cost evidence before verdicts

Parameterizable U.S. equity universe; the Capitulation-Volume Bounce worked example focused on $30M–$5B small caps.

Five accepted corpora

Bar chart of accepted candidate rows per snapshot, falling from 12,883 at 09:35 to 1,060 at 10:30, against the same 2,001,017-row denominator with zero provider errors.
Five point-in-time corpora, each reconciled against the same 2,001,017-row denominator with zero active provider errors. Supply thins by the minute as the open passes.

Data-integrity states

These states are kept separate so bad data cannot silently become a clean negative example.
StateMeaning
Valid observationFetched, parsed, and normalized successfully.
Provider fetch errorThe API call failed or returned an error; the attempt is recorded, not a silent absence.
Parser / normalization errorPayload arrived but could not be cleanly mapped to the schema.
Missing-but-expectedA source attempt was expected but produced no row.
Intentional exclusionFiltered out by rule (non-common, ETF, ineligible security type).
No signal / did not qualifyClean data that simply did not meet the pattern's conditions.

Why this is hard

Most retail backtests use today's ticker list and clean historical bars. Alpha Capital instead reconstructs what the market looked like on each historical date, including delisted names, provider gaps, split adjustments, stale quotes, and failed fetches. That is the difference between a chart and an auditable dataset.

The evidence spine, in SQL

The point-in-time and fail-closed guarantees are enforced in the queries and the schema, not just described. Two representative examples from the repository:

i12_pit_ is the internal table prefix for the point-in-time worked-example corpus (the Capitulation-Volume Bounce); the scratch-schema qualifier is omitted below for readability.

engine/scripts/build_i12_pit_event_tape.py · point-in-time evidence reconciliation
WITH scoped AS (
  SELECT i12_pit_candidate_id
  FROM i12_pit_candidates
  WHERE is_active IS TRUE
    AND candidate_status = 'passed'
    AND decision_date BETWEEN :start_date AND :end_date
    AND decision_time_label = :decision_time
    AND path_mode = :path_mode
), counts AS (
  SELECT scoped.i12_pit_candidate_id,
         COUNT(child.i12_pit_quote_replay_id) AS row_count
  FROM scoped
  LEFT JOIN i12_pit_quote_replays child
    ON child.i12_pit_candidate_id = scoped.i12_pit_candidate_id
   AND child.quote_role = :role
   AND child.is_active IS TRUE
  GROUP BY scoped.i12_pit_candidate_id
)
SELECT
  SUM(CASE WHEN row_count = 0 THEN 1 ELSE 0 END) AS missing_count,
  SUM(CASE WHEN row_count > 1 THEN 1 ELSE 0 END) AS duplicate_count
FROM counts;

Scopes to active, passed candidates inside the decision window, then verifies each required quote role has exactly one active evidence row. Any missing or duplicate count halts the tape build instead of silently producing an ML artifact.

engine/migrations/ · survivorship reconstruction table (condensed from Alembic DDL)
CREATE TABLE historical_universe_reconstructions (
  replay_date        DATE    NOT NULL,
  normalized_symbol  TEXT    NOT NULL,
  inclusion_status   TEXT    NOT NULL,
  delisted_date      DATE,
  reconstructed      BOOLEAN NOT NULL DEFAULT true,
  input_hash         TEXT    NOT NULL,
  output_hash        TEXT    NOT NULL,
  -- ... lineage, provenance, and job-run columns ...
  CONSTRAINT ux_historical_universe_recon_date_symbol
    UNIQUE (replay_date, normalized_symbol)
);

One reconstructed row per (historical date, symbol) — the structural guarantee behind survivorship-correct point-in-time universes, delisted names included. Condensed from the Alembic migration; the production table also carries provenance, lineage, job-run, foreign-key, and index fields.

The public page and GitHub repository show derived / aggregate artifacts only; raw licensed market data and credentials are excluded.

Engineering & Operations

Built like a small production data platform

Alpha Capital is not a notebook backtest. It is an automated research system: provider adapters, PostgreSQL schemas, lineage tables, nightly jobs, fail-closed integrity gates, reproducible artifacts, and a test suite around the parts most likely to lie.

e2-standard-8
dedicated GCP VM · 8 vCPU / 32 GB / 50 GB SSD
2M+
lineage-tracked Postgres rows · Supabase Pro / Medium (2-core, 4 GB)
6
provider integrations
2,000+
automated tests
JSON + MD
hash-stamped artifact per run
Automated nightly pipeline
Runs unattended on a dedicated Google Cloud VM. Jobs are idempotent and resumable; the VM fast-forwards code only, logs failures, and does not silently skip failed captures.
Provider adapter layer
Polygon, FMP, Nasdaq, SEC EDGAR, Benzinga, and Alpaca adapters normalize heterogeneous schemas behind a consistent evidence model. Provider statuses, retries, rate limits, parser failures, and payload hashes are preserved.
PostgreSQL evidence spine
SQLAlchemy models store source attempts, normalized rows, strategy candidates, feature snapshots, labels, quotes, costs, and validation artifacts. Every derived result can be traced back to provider evidence.
Fail-closed integrity gates
Row-count mismatches, missing source attempts, provider errors, manifest hash mismatches, stale artifacts, incomplete quote/cost rows, and feature-schema violations block promotion instead of becoming warnings.
Reproducible research artifacts
Each major run emits hash-stamped JSON and Markdown artifacts. Scratch experiments are separated from canonical corpora so exploratory work cannot overwrite accepted data.
Test and migration discipline
SQLAlchemy ORM, Alembic migrations, and pytest coverage around loaders, feature contracts, leakage guards, event-tape builders, report generation, and ML manifests. Statement timeouts guard long jobs; rate-limited concurrency protects providers.

Failure modes handled

provider timeoutstale quotemissing barparser failureduplicate active rowinactive parent with child evidencestale report artifactfeature leakagethreshold miningrandom row split

Why the plumbing matters

In market research, bad plumbing creates fake alpha. The engineering work is what prevents missing data, stale artifacts, or future information from becoming a polished but false result.

In the repository

Engineering surface

Built with

Python PostgreSQL SQLAlchemy scikit-learn pandas / NumPy pytest Google Cloud Market-data APIs
Methodology · Rigor

The discipline is the product

Every control below exists to make sure the data cannot quietly lie.

Point-in-time reconstruction
Features use only data knowable at the decision timestamp — never full-day or future values.
Survivorship correction
The historical universe includes companies that later delisted, merged, or went to zero.
Leakage controls
Full-day and forward values exist only as labels and diagnostics — never as predictors.
Purged / walk-forward validation
Overlapping samples are purged so information cannot leak between train and test.
Cost-aware backtesting
Bid–ask spread, slippage, tradeability, and skipped-to-cash handling are applied before any result is trusted.
Fail-closed philosophy
If lineage hashes, checksums, or row counts don't match, the pipeline refuses to proceed rather than write bad data.
Reproducible research artifacts
Every experiment emits a hash-stamped JSON + Markdown record; any result can be re-derived and independently audited.
Integrity · Adversarial Research Controls

Every result is treated as suspect until it survives the audit.

Alpha Capital does not trust a backtest because it looks good. Each result is forced through leakage checks, source-row reconciliation, cost realism, walk-forward validation, threshold-mining tests, and independent reruns. A strategy can advance only if the data, the model, and the accounting all agree.

Predictor firewall
Feature manifests allow only decision-time fields. Forward bars, full-day volume, same-day close, exits, labels, MFE/MAE, and outcome fields are rejected before training.
Label separation
Future data is allowed only to define outcomes. It can create labels, diagnostics, and exit studies, but it cannot enter the predictor vector.
Source-row reconciliation
Candidate counts, source attempts, child quote/cost rows, active/inactive parents, and stale artifacts are reconciled before a corpus is accepted.
Adversarial audit workflow
Promising results are attacked on purpose: rerun reports, inspect artifacts, hunt for stale files, verify row counts, mutate assumptions, and try to refute the conclusion before accepting it.
sklearn / ML reproducibility
Diagnostics use explicit Python and scikit-learn experiments against frozen feature sets and held-out windows, not intuition or chart-fitting.
Threshold-mining defense
Threshold ladders and top-K books are split into separate selection and evaluation windows; post-hoc out-of-sample maxima are marked diagnostic, not tradeable.
Cost realism
Bid–ask spread, quote age, stale quotes, volume participation, slippage, and skipped-to-cash handling are applied before any verdict.
Fail-closed gates
Manifest hashes, row counts, artifact checksums, source-provider errors, and missing-source counts block promotion instead of becoming warnings.

Multiple-testing discipline

Raw backtest returns are not enough. A strategy can look profitable simply because enough variants, thresholds, snapshots, and filters were tried. Alpha Capital treats research as a multiple-testing problem: validation emphasizes walk-forward splits, bootstrap refutation, and deflated-Sharpe-style controls before any result is considered credible.

Academic anchors: Sharpe (risk-adjusted performance) · Lo (2002), "The Statistics of Sharpe Ratios" · Bailey & López de Prado (2014), "The Deflated Sharpe Ratio" · Sullivan, Timmermann & White (1999), data-snooping Reality Check.

What the audit caught: the worked example originally looked attractive because full-day volume had leaked into candidate selection. The integrity layer caught that the edge was inflated by information unknowable at the entry minute; after point-in-time reconstruction, quote/cost labels, and walk-forward validation, the strategy was marked no-go. The system is valuable precisely because it can kill false alpha before any capital is at risk.

Audit trail

Five point-in-time corpora accepted only after active-denominator, source, provider, and child-row checks.
Five-snapshot event tape verified row-by-row against the frozen predictor allowlist.
Evaluate-only ML run permitted; promotion blocked at the gate.
Threshold ladder corrected once out-of-sample threshold mining was identified.
Walk-forward gate returned no-go, and that verdict was preserved as the result.
Machine Learning

The ML layer: score candidates, then let validation decide

Alpha Capital uses scikit-learn models as selection engines, not as proof of an edge. A model scores each candidate using only point-in-time features; the book is then judged out-of-sample after spread, slippage, tradeability, and cash handling.

Event tape
five-snapshot, point-in-time
Feature manifest
frozen, decision-time only
Train / embargo / test
purged walk-forward split
Gradient-boosted score
sklearn HistGBR
Top-K / thresholded book
K is a cap; cash allowed
Promotion gate
positive OOS economics after cost, tail, bootstrap & walk-forward

Model card

Task
Score and rank candidate stock/date events by expected forward return; construct top-K or thresholded books from model scores.
Model
scikit-learn HistGradientBoostingRegressor; regularized with min leaf size, L2, and early stopping.
Inputs
19 frozen point-in-time predictors, known at the decision timestamp.
Labels
Quote- and cost-aware modeled forward returns. Future / full-day data defines outcomes only; it is never a predictor.
Split
Train Jan 2024 – Jun 2025 · embargo Jul 2025 · OOS Aug 2025 – Jun 2026.
Rows
16,853 train · 883 embargo · 8,751 OOS candidates.
Book construction
Rank by model score, take the top-K or thresholded candidates; skipped / untradeable names become cash, not dropped rows.
Promotion
BlockedMeasurable separation versus naive baselines, but the cost-aware OOS book did not clear zero.

OOS readout

OOS candidates8,751
Predictor fields19
Model familyHistGradientBoosting (HGBR)
Validationpurged / embargoed walk-forward
Resultmeasurable statistical separation; economic promotion blocked
Economic verdictno-go after spread / slippage
Promotionblocked
Grouped bars: for labels >0, >=5%, and >=20%, the model's top-10% slice beats the base rate while the bottom 10% is near zero.
The model found rank separation, but rank separation did not translate into a promoted strategy after costs.

Research-shadow prototypes: the signal was real enough to pursue

Research-shadow onlyNot promoted

Before the final point-in-time, cost-aware gate, I ran several research-shadow ML tests to check whether the model could rank candidate events better than hand rules. These were not production claims: some were PIT-deferred or prototype runs, and later validation was stricter. But they showed meaningful rank separation and justified building the full leakage-controlled pipeline.

2026-06-15 · Stage-1 ranker
sklearn HistGradientBoostingRegressor · 10,012 confirmed events · purged walk-forward CV (PIT-deferred corpus)
  • Fold 1  2.15× top-decile lift · +4.85% top decile vs +2.26% baseline · 55.4% win
  • Fold 2  1.94× lift · +4.33% vs +2.24% · 59.3% win
  • 2026 subset  2.2× lift · 64% win · rank IC +0.065
2026-06-12 · classifier prototype
logistic / GBM / shallow random forest · 688 out-of-time rows · OOT AUC 0.60–0.63
  • RF top-25%  +8.81% mean · +6.69% median · 68.0% win
  • RF top-10%  +8.64% mean · +7.07% median · 73.5% win
  • Bottom-25%  −2.45% mean (the avoid-side is real)
Pooled day-0 patterns · ML-rank thesis
two small-cap day-0 patterns (breakout momentum + capitulation bounce) · 3,744 pooled fires · out-of-fold 5-fold logistic
  • OOF AUC  0.601 · ML top-67% +4.25% mean vs +2.74% take-all
  • Deciles  top +7.35% · bottom −2.90%
  • ML-rank K=10  +5.75% vs firing-order K=10 +2.36%

These were research-shadow evidence, not promotion evidence. The later point-in-time, survivorship, spread, slippage, and walk-forward gates reduced or blocked the strategy. That is the point of the platform: promising models are not allowed to graduate unless the full evidence chain survives.

Oracle diagnostic: predicting the forbidden full-day-volume signal

The original Capitulation-Volume Bounce rule used full-day volume, which is not knowable at entry and is therefore banned as a live predictor. I turned that leaked rule into an oracle label and asked a stricter question: can point-in-time morning features predict which names will later satisfy the full-day-volume condition? This was a read-only scikit-learn diagnostic, fit in memory only, with no registry, model, or scoring writes.

8,025
pooled OOS rows
3,307
positives
0.751
AUC (pooled)
0.700
avg. precision
RF
random forest

Morning structure is partially predictive of the future condition: per-snapshot AUC runs 0.59 to 0.67, and 0.751 pooled across the five snapshots. Some of the forbidden full-day-volume behavior is genuinely inferable from what was knowable at the open. But predictive separation is not a tradeable edge: the point-in-time student book still printed a negative cost-aware daily mean and failed the loser/tail and walk-forward checks, so promotion stayed blocked.

Three bars: oracle teacher K=8 mean positive (uses leaked label), PIT student K=8 mean negative, raw baseline negative.
Full-day volume was useful as an oracle label, but not live-knowable at entry. The PIT student could partly predict oracle membership, but not enough to clear the economic gate.

Predictors vs. labels: the firewall

Predictors · go in · as-of decision
  • Prior daily context (off-high / off-low, momentum, σ20)
  • Opening gap & opening-range structure
  • Early intraday return / path
  • Pre-decision volume participation
  • Spread & liquidity fields
Labels · outcomes only · never features
  • Same-day & next-open returns
  • Full-day price-path diagnostics
  • Maximum favorable / adverse excursion (MFE / MAE)
  • Modeled entry/exit outcomes and quote/cost returns

The rule: future and full-day data can define an outcome to predict, but can never enter the feature vector. Any predictor that crosses the line is rejected before training (the leakage audit below enforces it).

Implementation proof

These snippets aren't decorative; they're the enforcement points in the repository's real scikit-learn pipeline, not an AI simulation or notebook toy:

I12 is the codebase's internal name for the Capitulation-Volume Bounce, so it appears in the constant names and file paths below.

alpha/jobs/train_model.py
def _new_gbrt_model(*, max_iter, random_state, model_params=None):
    from sklearn.ensemble import HistGradientBoostingRegressor

    params = dict(model_params or {})
    return HistGradientBoostingRegressor(
        max_iter=max_iter,
        min_samples_leaf=int(params.get("min_samples_leaf", DEFAULT_MIN_SAMPLES_LEAF)),
        l2_regularization=float(params.get("l2_regularization", DEFAULT_L2_REGULARIZATION)),
        early_stopping=_bool_model_param(params.get("early_stopping"), DEFAULT_EARLY_STOPPING),
        random_state=random_state,
    )

The estimator: a histogram-based gradient-boosted regressor, regularized (leaf-size + L2) and early-stopped to resist overfitting.

alpha/ml/model_features.py · leakage audit
FORBIDDEN_ZONE_TOKENS = (
    "forward", "post_signal", "post-signal",
    "outcome", "label", "future", "exit",
)
# A predictor is rejected before training if it names a banned
# (projected / full-day / outcome) path, or isn't on the frozen allowlist.
if locator in I12_PIT_BANNED_FEATURE_PATHS:
    raise FeatureSelectionError(
        "I12 PIT-clean feature schema requested a banned projected, "
        f"full-day, or outcome field: {field!r}"
    )
if locator not in I12_PIT_0940_ALLOWED_FEATURE_PATHS:
    raise FeatureSelectionError(
        "I12 PIT candidate feature is not in the frozen inclusion "
        f"allowlist: {field!r}"
    )

Look-ahead made structurally impossible: any feature touching a forward/outcome zone, or absent from the frozen allowlist, raises and halts training, rather than silently inflating a result.

alpha/ml/cv.py · purged, embargoed walk-forward
embargo = max(horizon_sessions, embargo_sessions)
train_cutoff = min(test_positions) - embargo
test_identities = {
    _security_identity_key(row)
    for row in examples if row.signal_date in set(block)
}
# Train rows must be strictly earlier than the test block (date purge)
# AND share no security with it (cluster purge), so nothing overlaps.
train_indices = [
    idx
    for idx, row in enumerate(examples)
    if date_to_position[row.signal_date] < train_cutoff
    and _security_identity_key(row) not in test_identities
]

The CV split is both date-purged (train strictly precedes test by the full horizon) and cluster-purged (no security appears on both sides), closing the two ways a time-series backtest usually leaks.

Reproducibility trace

Where this lives in the repository

The honest read: the model found measurable rank separation versus naive baselines, but the book still failed the economic bar after spread, slippage, and walk-forward validation. A model that scores better than chance yet loses to cost is not a tradeable edge; the platform is built to report that, not bury it.

Worked Example · Falsification Case Study

A promising signal that the platform refused to promote

The strongest proof of the system was not a winning chart. It was a clean no-go decision on my own leading strategy after the data controls caught what the naive backtest missed.

Case file

Pattern
Capitulation-Volume Bounce
Universe
U.S. small caps, roughly $30M–$5B market cap.
Hypothesis
Distressed names down 50%+ from 52-week highs can bounce after capitulation volume.
Data window
Jan 2024 – Jun 2026 (30 months).
Signals
13,839 unique ticker/date events · 26,487 five-snapshot rows.
Entry snapshots
09:35 · 09:40 · 09:45 · 10:00 · 10:30.
Final decision
No-goNot promoted; a fail-closed research decision.

What changed from naive to real

Naive version · flattering, but leaked
  • Used full-day volume as a selector
  • Assumed cleaner fills than thin names actually offer
  • Looked economically attractive
Production-grade version · point-in-time, cost-real
  • Replaced full-day knowledge with point-in-time morning snapshots
  • Reconstructed a survivorship-correct universe including dead / delisted names
  • Applied bid–ask spread, slippage, tradeability, and cash handling
  • Used purged / walk-forward out-of-sample validation
  • Blocked promotion when the economics failed
The critical leak was full-day volume: the original screen knew at 4 p.m. which names had sustained volume, but a live system at 9:40 does not. In the rebuilt tape, full-day volume is allowed only as an oracle label and diagnostic, never as a predictor. Closing that single leak turned a flattering backtest into a cost-aware no-go: a false positive caught before deployment.
Modeled out-of-sample equity curves after cost controls; both the ML-ranked book and the naive baseline end below $1.
Modeled OOS equity curves after cost controls; this was never live capital.
Monthly count of signals fired across the full sample; 13,839 total.
Signal coverage across the full sample.
Mean book return per day falling from a gross-looking positive to a cost-aware negative as each correction is applied.
Correction waterfall: gross-looking edge to cost-aware no-go.

Why this matters

Most backtests fail because they accidentally let future information or impossible execution into the result. This case study shows the opposite workflow: start with a plausible signal, rebuild it point-in-time, charge realistic costs, test it out-of-sample, and accept the verdict. The platform preserved integrity over a flattering backtest.

Validation · Gate System

A result advances only if every gate agrees

The platform separates validation into two decisions: whether the data is trustworthy, and whether the strategy is tradeable. For the worked example, the data passed; the strategy did not. That distinction is the point.

Data corpus
Go
Event tape
Go
Feature contract
Go
Model evaluation
Evaluated
Economic gate
No-go
Promotion
Blocked

Group A · Data & corpus gatesPassed

Five point-in-time corpora accepted
09:35, 09:40, 09:45, 10:00, and 10:30 all reconciled to the expected active denominator; active provider errors cleared.
Survivorship reconstruction
Universe rebuilt as-of each historical date, including dead and delisted names.
Source-row reconciliation
Candidate rows, source attempts, quote/cost child rows, active/inactive parents, and stale artifacts reconciled before use.
Quote/cost completeness
Passed candidates required complete quote and cost evidence before report acceptance.

Group B · Feature & leakage gatesPassed

Frozen predictor allowlist
The event-tape predictor vector held exactly the allowed fields; extra or missing fields block training.
Predictor / label firewall
Full-day volume, next-open returns, MFE/MAE, exits, and future data live only as labels and diagnostics.
Purged / embargoed split
Train Jan 2024 – Jun 2025; embargo Jul 2025; OOS Aug 2025 – Jun 2026. Random row split forbidden.
Multi-snapshot timing
Five entry snapshots were tested point-in-time; no convenient fill was assumed.

Group C · Economic & promotion gatesFailed

Cost-aware OOS book
The same-day K=8 book stayed negative after spread and slippage.
Bootstrap significance
The same-day mean CI was fully below zero, so the result did not clear statistical or economic zero.
Threshold-mining defense
A post-hoc positive threshold pocket was found, then rejected by a forward-valid walk-forward threshold gate.
Demand-quality rescue
Additional pre-decision demand-quality features improved some diagnostics but did not flip the strict walk-forward verdict.

Forward-valid gate evidence

Three bars: validation-selected q0.60 negative, OOT-best mined q0.75 positive but post-hoc, forward-valid gate negative.
A tempting positive pocket was found by mining the test set (q0.75), then rejected: the honest validation-selected threshold and the forward-valid gate are both negative.
Monthly same-day account mean bars, Aug 2025 to Jun 2026; only two months positive, aggregate negative.
Forward-valid threshold selection failed: 2 of 11 months positive, aggregate mean negative.

Final validation decision

Data, tape, and model evaluation: GO. Strategy promotion: NO-GO. The pipeline did not fail; it did its job by blocking a flattering but non-tradeable result.

Representative artifacts: i12_pit_stage1_analysis_5snap_3f5ed25.json · i12_pit_0940_walk_forward_threshold_gate_3f5ed25.json · i12_pit_oracle_full_day_volume_labels_5snap_3f5ed25.json.

Results · Cost-Aware Verdict

The model helped, but the book still failed the economic gate

The ranker improved on every naive baseline, yet the same-day book still lost money after spread and slippage. Same-day (flat by close) is the primary verdict; next-open appears only as a comparison. Every figure is modeled, cost-aware, and out-of-sample; not live P&L.

−0.337%
same-day K=8 book, mean per day
[−0.607, −0.071]
block-bootstrap 90% CI (% per day); fully below zero
41.9%
positive sessions (of 222)
Blocked
promotion decision

Sample & split

Full corpus
Jan 2024 – Jun 2026 · 13,839 unique ticker/date identities · 26,487 five-snapshot event rows.
Train
Jan 2024 – Jun 2025 · 16,853 rows.
Embargo
Jul 2025 · 883 rows.
Held-out OOS
Aug 2025 – Jun 2026 · 8,751 rows · 222 sessions.
Basis
Modeled, cost-aware, out-of-sample; never live capital.

Primary policy: same-day K=8 book

The live policy ranks each session's candidates by model score and takes up to K=8. K is a cap, not a forced-deployment mandate: skipped or untradeable names become cash, not dropped rows. "Same-day" means flat by the close (a same-day modeled exit), the strictest and most live-like basis, so it is the primary verdict.

Same-day, cost-aware, out-of-sample (222 sessions). The model book posts the least-negative mean of the four; every policy still stays below zero after cost.
PolicyMean / dayMedian / dayPositiveMax DDVerdict
ML-ranked K=8 book−0.337%−0.514%41.9%−69.6%No-go
Raw detector baseline−0.362%−0.592%42.3%−66.1%No-go
Persistence-only baseline−0.567%−0.468%43.2%−75.5%No-go
Liquidity / spread-only baseline−0.683%−0.966%38.7%−81.7%No-go

Held-out candidate rows (8,751 OOS rows): mean −0.249% per event · median 0.00% · 36.1% win rate. The typical event went nowhere net of cost; the return that exists sits in a thin right tail the ranker cannot reliably pre-select.

The takeaway is precise: the ML-ranked book beats all three baselines on mean (−0.337% vs −0.362% / −0.567% / −0.683%), so the model did reduce bad selection. But beating weak baselines is not the bar; same-day economics stay negative after cost, the bootstrap CI is fully below zero, and promotion is blocked.

Next-open comparison

Holding to the next open did not rescue the signal. It softened the mean loss to −0.252%/day (median −0.413%, 43.2% positive sessions, max drawdown −66.9%), but the block-bootstrap 90% CI was [−0.619%, +0.100%]; it still crossed zero, so promotion remained blocked.

Monthly mean daily return, next-open book (comparison), cost-aware, out-of-sample. Strong out of the gate, then gave it back through the winter.
MonthMean / dayMonthMean / day
Aug ’25+1.02%Feb ’26−1.73%
Sep ’25+0.29%Mar ’26−0.59%
Oct ’25−0.63%Apr ’26+0.08%
Nov ’25−0.03%May ’26+0.05%
Dec ’25−1.00%Jun ’26−0.81%
Jan ’26+0.40%

Source artifact: engine/artifacts/stage0/i12_pit_stage1_analysis_5snap_3f5ed25.json (local; derived data, not committed).

Point-in-Time · Entry Timing

Five decision timestamps, not one convenient fill

Every candidate was evaluated at five point-in-time decision timestamps: 09:35, 09:40, 09:45, 10:00, and 10:30. The point is not to cherry-pick the best timestamp after the fact; it is to test whether a signal survives realistic entry timing rather than one convenient, assumed fill.

Cost-aware same-day outcomes by decision snapshot. OOS rows drive the performance columns; full accepted rows show total corpus supply.
SnapshotFull acceptedOOS rowsSame-day meanMedianWin rate
09:3512,8834,223−0.246%0.00%33.4%
09:406,2302,026−0.235%0.00%37.5%
09:454,1481,386−0.138%0.00%38.5%
10:002,166752−0.498%−0.381%39.2%
10:301,060364−0.281%−0.299%44.0%
Two-panel chart: accepted rows declining across the five snapshots, and same-day mean return below zero at every snapshot.
Later entries have less supply and still lose money: the same-day mean stays below zero at every snapshot.
Supply decays sharply after the open. 12,883 accepted rows at 09:35 fall to 1,060 by 10:30.
Later snapshots are sparse, so any apparent pocket there is less reliable.
Same-day performance does not clear zero at any robust timing view.
The conclusion is operational: entry timing must be modeled explicitly; it cannot be assumed away.

For each row, predictors were computed only from bars available before that decision timestamp. Later snapshots and full-day outcomes were used as labels and diagnostics only, never as features.

Legacy next-open diagnostic

Next-open evaluate-only ranker selection distribution (not the same-day primary verdict). Given the choice of when to enter, the earlier next-open ranker concentrated its picks at the open: 09:35: 1,062 (59.9%) · 09:40: 308 (17.4%) · 09:45: 181 (10.2%) · 10:00: 142 (8.0%) · 10:30: 80 (4.5%). This was a separate, superseded evaluation; the same-day table above is the verdict.
Lessons

What this project demonstrates

The final output was a reusable research platform and the discipline to reject its own leading strategy on the evidence. That is the skill: build the system, run the evidence, and accept the result.

Data discipline beats model complexity
The hardest part was not fitting scikit-learn models. It was building a point-in-time data path the model could not cheat through: historical universes, provider lineage, feature contracts, and label separation.
Gross alpha is not deployable alpha
The microcap bounce looked real before costs, but thin spreads and tradeability turned the apparent edge into a no-go. The lesson is to judge a strategy after execution, not before it.
Statistically useful, economically insufficient
The ML layer found measurable rank separation and could predict the forbidden full-day-volume oracle signal at roughly AUC 0.751, yet the cost-aware book still failed. Better-than-random is not the same as tradeable.
Validation has to be adversarial
Threshold ladders, walk-forward gates, bootstrap intervals, stale-artifact checks, leakage guards, and independent audits exist because the easiest person to fool in research is yourself.
The platform survives the strategy
The Capitulation-Volume Bounce was archived as a falsified branch, but the infrastructure remains reusable: provider ingestion, point-in-time reconstruction, feature manifests, ML evaluation, and cost-aware validation can now be applied to liquid all-cap patterns with cleaner spreads and capacity.

Next research direction: liquid all-cap strategy discovery, where spreads are tighter, execution is cleaner, and a lower raw edge may be more deployable.