01
Look-ahead bias
If an event's threshold is chosen by looking at how much it returns, the threshold already "knows" the future. Every backtest that follows is circular, not predictive.
Quantitative research · Python
FORGE is an open-source engine for the systematic discovery of algorithmic trading rules from historical market data. It takes a KPI table, extracts events with stable temporal structure, measures their predictive power, and puts them through a realistic backtest — strictly separating every stage so the signal never "learns" the future ahead of time.
>>> from forgedge import forge >>> kpi = pd.read_parquet("kpi_table.parquet") >>> # full pipeline: from KPI table to validated rules >>> result = forge(kpi, ticker="BTCUSDC", timeframe="1H") >>> # EDGE / PARTIAL-EDGE only, with reasoning attached >>> for contract, response in result.edges(): ... print(contract.alpha_id, response.verdict) rsi14_spread_ema9_25 EDGE bb_width_p20_break PARTIAL-EDGE
The problem
Given enough time, any pattern can be made to look like an edge: just pick the right thresholds after seeing the returns. FORGE exists to close three recurring gaps, one by one.
01
If an event's threshold is chosen by looking at how much it returns, the threshold already "knows" the future. Every backtest that follows is circular, not predictive.
02
Searching for the best horizon, take-profit and filter on the same data used to measure the Profit Factor produces a PF that reflects sample noise, not real structure.
03
A statistically predictive event is not automatically profitable: fees, unfilled limit orders and horizons that must close regardless change everything.
5-module pipeline
No module accesses the next module's data. No threshold is recalibrated after discovery. The flow runs in one direction only: from the KPI table to the final report.
Classifies every bar of the KPI table by market regime across 5 levels, so the discovered edge can later be read for context dependency too.
regime, regime_stableDiscovers boolean conditions purely from the temporal structure of indicators — frequency, dispersion, monthly stability. The forward return never enters this module.
list[EventCandidate]First exposure to the forward return. Horizon, direction and take-profit are never assumed: they are measured per event and confirmed on an out-of-sample tail never touched before.
list[AlphaContract]Order mechanics, per-side fees, market or limit entry, walk-forward validation on rolling windows. This is where the operational verdict is born.
EDGE / PARTIAL-EDGE / NON-EDGE + operational parametersDeduplicates discovered rules, re-backtests them on other assets, and classifies them by genericity. Produces a flat table and a self-contained HTML report.
report.html (inline SVG, no CDN)Three concepts, three boundaries
A trading signal is born only at the intersection of all three assessments — never from just one of them.
"Is this market configuration stable and repeatable?"
A boolean condition on distributional thresholds — percentiles computed on the specific asset, not absolute values — fixed before a single forward return is ever computed.
"Does this event statistically predict an oriented return?"
Horizon, direction and take-profit derived from the data by scanning a grid and standardising against a circular rotation null — never imposed by the user.
"Is this alpha profitable under real order mechanics?"
A backtest with fees, realistic fills and walk-forward validation on rolling train/test windows — the final verdict, not an estimate.
The final output
Rule Discovery integrates hard and soft gates — Profit Factor, win rate, deflated Sharpe, regime dependency, walk-forward consistency — into one of the four outcomes below.
PF ≥ 2.0, win rate ≥ 55%, walk-forward consistency ≥ 50%, beats the session-level rotation null.
Clears the hard gates but not every EDGE gate: real evidence, not yet operationally solid.
PF < 1.5, every month negative, or no configuration with an adequate fill rate.
OOS evidence too thin for a confident judgement — not tradeable, but not discarded: re-assessed as more data arrives.
What it prevents, not what it promises
| Invariant | What it prevents |
|---|---|
| Module 1 never sees the forward return | Look-ahead bias in event selection |
| Thresholds are immutable after discovery | Threshold optimisation on the evaluation sample |
| Horizon, direction and take-profit are derived from data per event | Economic assumptions pre-baking the result |
| The tradeable verdict is gated by walk-forward OOS (Module 3) | Post-hoc confirmation of a foregone conclusion |
Quick start
FORGE depends solely on numpy and pandas. All statistical primitives — Spearman, t-test, OU regression, Benjamini-Hochberg FDR, incomplete beta — are implemented in pure numpy: no dependency on scipy, statsmodels or ML libraries.
from forgedge import forge kpi = pd.read_parquet("kpi_table.parquet") result = forge(kpi, ticker="BTCUSDC", timeframe="1H") print(result.summary()) # one row per candidate + rule_verdict print(result.registry.summary()) # Module 4 — catalogued rules
from forgedge import forge_multi frames = {"BTCUSDC": btc, "ETHUSDC": eth} results, registry = forge_multi(frames, timeframe="1H") # GENERIC: rule holds on ≥ 2/3 of tickers df = registry.flat_table() html = registry.html_report(timeframe="1H") open("report.html", "w").write(html) # inline SVG, self-contained, no CDN