1 (edited by quantbot Yesterday 12:31:51)

Topic: 8-Phase Automated Validation Pipeline

8-Phase Automated Validation Pipeline

Hi everyone,

I've been using EA Studio and Express Generator for years now, and after a long journey of trial and error — testing different robustness approaches, losing money to overfitted strategies, and slowly figuring out what actually works — I've finally built a fully automated validation pipeline that I'm genuinely happy with.

I wanted to share it with the community because this forum and Mr. Popov's continuous work on Express Generator have been instrumental in getting me here. The speed, the scriptability, the constant updates — Express Generator is truly a lovely system, and I owe a big thank you to Mr. Popov for making it all possible. Every new version brings something useful, and the tool just keeps getting better.

So here's my complete workflow. I hope it helps some of you avoid the mistakes I made along the way.

---

The Problem: Overfitting is the Silent Killer

We all know the story. You generate a beautiful strategy with a perfect equity curve, put it on a demo or live account, and within weeks, it's underwater. The strategy was curve-fitted to historical data and had no real edge.

I spent a long time trying simple IS/OOS splits and basic Monte Carlo tests, but strategies kept failing in live trading. The turning point was realizing that one robustness test is not enough. You need multiple independent tests that challenge the strategy from completely different angles. If a strategy survives all of them, the probability that it's genuinely capturing a market pattern goes up dramatically.

---

The 8-Phase Pipeline Overview

Here's the full pipeline. Each phase tests a different dimension of robustness:

+---+---------------------------------+----------+---------+----------------------------------------------+
| # | Test                            |Data Range| Server  | Purpose                                      |
+---+---------------------------------+----------+---------+----------------------------------------------+
| 1 | Generate In-Sample              |  0%– 50% | Premium | Strategy discovery                           |
| 2 | Out-of-Sample Validation        | 50%– 80% | Premium | Overfit filter                               |
| 3 | Monte Carlo — Execution Stress  |  0%– 80% | Premium | Survives real-world execution?               |
| 4 | Monte Carlo — Param Sensitivity |  0%– 80% | Premium | Overfit to specific indicator values?        |
| 5 | Multi-Timeframe Validation      |  0%–100% | Premium | Captures a real pattern, not timeframe noise?|
| 6 | Multi-Instrument Validation     |  0%–100% | Premium | Works on related markets?                    |
| 7 | Cross-Broker Validation         |  0%– 80% | Eightcap| Real pattern or data artifact?               |
| 8 | Forward Test                    | 80%–100% | Premium | Performs on completely unseen data?          |
+---+---------------------------------+----------+---------+----------------------------------------------+

The key insight: Phases 1–4 use 80% of the data maximum, reserving 20% that the strategy has NEVER seen for the final forward test. Phases 5 and 6 use 100% data because they test on different timeframes/instruments entirely — the strategy has never been optimized on those markets.

---

Phase 1: Generate In-Sample (0%–50%)

Generation uses only the first half of the available data. This is deliberate — it gives us three more independent data segments to validate against.

I typically run this for 24 hours per instrument using `max_working_minutes = 1440`. The more strategies generated, the better the chances of finding genuinely robust ones.

---

Phase 2: Out-of-Sample Validation (50%–80%)

Feed the Phase 1 collection into Express Generator with data_start_percent = 50 and data_end_percent = 80. No generation, pure validation.

This 30% data window is completely unseen during generation. Strategies that were curve-fitted to the first 50% will typically fail here. This is your first major filter.

Settings are slightly relaxed compared to Phase 1 because the data window is smaller.

---

Phase 3: Monte Carlo — Execution Stress (0%–80%)

This is where I learned an important lesson. I used to combine all Monte Carlo tests into one phase, and it was eliminating 99.8% of strategies. Separating execution stress from parameter sensitivity into distinct phases was a game-changer — it gives you much better diagnostics about WHY a strategy failed.

Phase 3 tests execution robustness only — what happens when real-world conditions degrade?

---

Phase 4: Monte Carlo — Parameter Sensitivity (0%–80%)

Now test the opposite dimension: are the indicator parameters fragile?

Criteria are more lenient here than in Phase 3:

Why more lenient? Because parameter changes can legitimately shift a strategy's behavior more than execution noise does. A strategy using RSI(14) that still works at RSI(12) or RSI(16) is robust. It doesn't need to be equally profitable — just not broken.

Important lesson: I initially used 5% parameter variation, and it was too small to be meaningful. Use 15–20% for real stress testing. If a strategy breaks with 15% parameter variation, it's dangerously overfit.

---

Phase 5: Multi-Timeframe Validation (0%–100%)

This is where it gets interesting. A strategy generated on H1 should show some viability on adjacent timeframes (M30 and H4). If it completely falls apart, it's likely exploiting timeframe-specific noise rather than a real market pattern.

The workflow automatically maps adjacent timeframes:

- M5 → M1, M15
- M15 → M5, M30
- M30 → M15, H1
- H1 → M30, H4
- H4 → H1, D1
- D1 → H4

Criteria are very lenient — we're not expecting profitability, just "not catastrophic":

- Must pass at least 1 of 2 adjacent timeframes (50% pass rate)

The workflow automatically fetches data for adjacent timeframes before testing. This uses 100% of data since it's a completely different timeframe — there's no "seen/unseen" concern.

---

Phase 6: Multi-Instrument Validation (0%–100%)

Same idea but across related currency pairs. A EURUSD strategy should show some viability on structurally related pairs that share market dynamics.

The workflow has a hardcoded mapping of related instruments:

- EURUSD → GBPUSD, USDCHF, EURGBP, EURJPY, EURCAD
- USDJPY → EURJPY, GBPJPY, AUDJPY, CHFJPY, CADJPY
- GBPUSD → EURUSD, EURGBP, GBPJPY, GBPAUD, GBPCAD
- AUDUSD → NZDUSD, AUDJPY, AUDCAD, AUDCHF, AUDNZD

Pass requirement is percentage-based: min_pass = max(1, floor(count / 3)) — roughly 33%:
- 3 related instruments → minimum 1 must pass
- 6 related instruments → minimum 2 must pass

Tagging system: The results get tracked as tags like MI4of5 (passed 4 out of 5 instruments). These tags flow through to the final output filename, so at the end you can see at a glance:
- P8_EURUSD_H1_TF2of2_MI5of5.json = fully validated, strong
- P8_EURUSD_H1_TF1of2_MI2of6.json = passed minimums, borderline

---

Phase 7: Cross-Broker Validation (0%–80%)

Test the strategy against a different broker's data feed. I use Eightcap as the cross-broker (ECN with tight spreads, which makes it a slightly tougher test).

This answers: is the strategy capturing a real market pattern, or is it an artifact of Premium's specific price feed?

---

Phase 8: Forward Test (80%–100%)

The final boss. The last 20% of data that the strategy has never seen in any form. No generation, no optimization, no Monte Carlo — just pure validation on unseen data.

This is the closest simulation to what will happen when you go live. If a strategy survives all 7 previous phases and still performs well on completely unseen forward data, you can have much higher confidence it has a genuine edge.

Settings are moderate (the 20% data window is smaller, so absolute metrics will be lower)

---

Real Results: USDJPY H1 Through All 8 Phases

Here's an actual strategy that made it through the entire pipeline:

+---------------+-----------------------+------------------------+-----------------------+
| Metric        | Phase 3 (80% Premium) | Phase 7 (80% Eightcap) | Phase 8 (20% Forward) |
+---------------+-----------------------+------------------------+-----------------------+
| Profit        | $3,939                | $4,528                 | $3,763                |
| Profit/day    |  $0.84                |  $0.96                 |  $3.22                |
| Profit Factor |   1.43                |   1.13                 |   1.33                |
| R-squared     |  86.21                |  37.61                 |  72.22                |
| Return/DD     |   4.87                |   2.41                 |   3.66                |
| Max Drawdown  |   6.6%                |  18.5%                 |  8.31%                |
| Stagnation    |  19.3%                |  42.6%                 | 16.15%                |
| Trades        |    517                |    907                 |    346                |
+---------------+-----------------------+------------------------+-----------------------+

The strategy actually improved on forward data — profit per day jumped from $0.84 to $3.22 and drawdown stayed low at 8.3%. It also passed all adjacent timeframes (M30, H4) and all 5 related JPY instruments (EURJPY, GBPJPY, AUDJPY, CADJPY, CHFJPY).

Final output: P8_USDJPY_H1_TF2of2_MI5of5.json

---

How It All Runs: Automation

The entire pipeline is a single Windows batch script.

The script:
1. Fetches data for the main instrument
2. Runs all 8 phases sequentially
3. Automatically fetches data for adjacent timeframes before Phase 5
4. Automatically fetches data for related instruments before Phase 6
5. Prints statistics after each phase
6. Tags the final output with TF and MI results

---

Lessons Learned the Hard Way

  1. Separate your Monte Carlo tests. Combined MC (execution + parameters) was killing 99.8% of strategies. Separated, I get much better survival rates AND know exactly why a strategy failed.

  2. Don't be too strict too early. I spent months with overly tight criteria and getting zero strategies through. Better to have moderate filters across many phases than one impossibly strict filter.

  3. 5% parameter variation is useless. Use 15–20% to actually stress test. If your strategy breaks at 15% variation, it WILL break in live trading.

  4.valid_tests_percent = 80 is too strict for initial discovery. Start with 65–75% and only tighten later if needed.

  5. Reserve 20% of data for forward testing. Never touch it during any other phase. This is your reality check.

  6. Multi-instrument testing reveals a lot. A strategy that works on 5+ related pairs is much more likely to capture a real pattern than one that only works on a single instrument.

---

Final Thoughts

This pipeline isn't magic — no system can guarantee profitable strategies. But it dramatically reduces the probability of deploying an overfitted strategy. The philosophy is simple: test from every angle, and only trust what survives everything.

A huge thank you again to Mr. Popov for Express Generator. The speed, the command-line interface, the INI configuration system, and the data percentage splits — all of these features made this kind of automated pipeline possible. And the continuous updates keep making it better. This community and this tool have been invaluable.

Let's build robust strategies together!

Cheers,

Hani

Post's attachments

phase1-generate.ini 1.77 kb, 2 downloads since 2026-02-16 

phase2-oos.ini 1.56 kb, 1 downloads since 2026-02-16 

phase3-mc-execution.ini 2.25 kb, 1 downloads since 2026-02-16 

phase4-mc-params.ini 2.33 kb, 1 downloads since 2026-02-16 

phase5-multi-tf.ini 1.7 kb, 1 downloads since 2026-02-16 

You don't have the permssions to download the attachments of this post.

Re: 8-Phase Automated Validation Pipeline

Great post, thank you for sharing and especially detailing your steps, Hani!

I have a question: you have your workflow sorted, it is fully automated and reaching the goals you have set so to speak, but why do you still need to know "exactly" why a strat has failed? Does this provide you with further data to refine the process?

Another one: this is about multimarket. You say that you're using structurally related pairs that share market dynamics, but the first example for EURUSD shows correlation to EURUSD that is all across the board! Average daily correlation for GBPUSD is high, for USDCHF it is high (oppositely moving), for EURGBP there's no correlation, for EURJPY it is very low, for EURCAD it is low. Have you taken actual correlation into account by choosing the pairings?

Re: 8-Phase Automated Validation Pipeline

# Utility Scripts — Managing the Pipeline

After running the 8-phase pipeline for a while, I found myself repeating two tedious tasks: clearing old collections before a fresh run, and updating settings like stop loss ranges across all 8 INI files. So I built a few small scripts to make life easier.

==========================================================

## The Problem with 8 INI Files

There are 24 settings that must stay identical across all 8 phase files — account settings, strategy structure (stop loss, take profit, entry/exit slots), session times, and indicator options. If you change `stop_loss_range_max` in Phase 1 but forget Phase 7, you'll get unexpected behavior or silent failures.

The solution: one shared file, one sync script.

==========================================================

## shared-settings.ini

This file contains every setting that should be the same across all phases. Edit this one file instead of touching 8 files manually:

ini
; +=========================================================+
; |                      QUANT-BOT.COM                      |
; |       Shared Settings Across All Pipeline Phases        |
; |          8 Phases. Multiple Markets. One Goal.          |
; |                                                         |
; |          by Hani | Powered by Express Generator         |
; +=========================================================+
;
; Edit values here, then run sync-settings.cmd to push
; changes to all 8 phase INI files automatically.
;
; Only settings that MUST be identical across phases belong here.
; Phase-specific settings (acceptance criteria, Monte Carlo
; parameters, server, etc.) stay in their own phase files.

; Account
account_currency = USD
initial_account = 10000
leverage = 100
entry_lots = 0.1

; Strategy structure
trade_direction_mode = LongAndShort
opposite_entry_signal = IgnoreOrReverse
stop_loss_usage = AlwaysUse
stop_loss_type = FixedOrTrailing
stop_loss_range_min = 10
stop_loss_range_max = 200
take_profit_usage = MayUse
take_profit_range_min = 10
take_profit_range_max = 350
max_entry_slots = 4
max_exit_slots = 2

; Backtester
exit_trade_at = Open
close_at_backtest_end = true

; Trading session
session_open = 00:00
session_close = 24:00
friday_close = 20:40
trade_on_sunday = false
close_at_session_close = false
close_at_friday_close = true

; Indicator options
max_indicator_period = 200

==========================================================

## sync-settings.cmd

Run this after editing shared-settings.ini. It reads each `key = value` pair and updates the matching key in all 8 phase files. Phase-specific settings (like `min_profit`, `enable_monte_carlo`, `server`, etc.) are never touched — only keys that exist in both the shared file and the phase file get updated.

cmd
@echo off
REM +=========================================================+
REM |                      QUANT-BOT.COM                      |
REM |         Sync Shared Settings to All Phases              |
REM |          8 Phases. Multiple Markets. One Goal.          |
REM |                                                         |
REM |          by Hani | Powered by Express Generator         |
REM +=========================================================+

cd /d %~dp0

if not exist "shared-settings.ini" (
    echo ERROR: shared-settings.ini not found
    pause
    exit /b 1
)

echo Syncing shared-settings.ini to all phase files...
echo.

powershell -Command ^
    "$shared = @{}; " ^
    "Get-Content 'shared-settings.ini' | ForEach-Object { " ^
    "  if ($_ -match '^\s*([a-z_]+)\s*=\s*(.+)$') { " ^
    "    $shared[$Matches[1].Trim()] = $Matches[2].Trim() " ^
    "  } " ^
    "}; " ^
    "Write-Host ('Loaded ' + $shared.Count + ' settings from shared-settings.ini'); " ^
    "Write-Host ''; " ^
    "foreach ($f in (Get-ChildItem 'phase*.ini')) { " ^
    "  $lines = Get-Content $f.FullName; " ^
    "  $updated = 0; " ^
    "  $newLines = $lines | ForEach-Object { " ^
    "    if ($_ -match '^\s*([a-z_]+)\s*=') { " ^
    "      $key = $Matches[1].Trim(); " ^
    "      if ($shared.ContainsKey($key)) { " ^
    "        $updated++; " ^
    "        $key + ' = ' + $shared[$key] " ^
    "      } else { $_ } " ^
    "    } else { $_ } " ^
    "  }; " ^
    "  $newLines | Set-Content $f.FullName; " ^
    "  Write-Host ('  ' + $f.Name + ': ' + $updated + ' settings updated') " ^
    "}"

echo.
echo Done.
pause

Example output:

Loaded 24 settings from shared-settings.ini

  phase1-generate.ini: 24 settings updated
  phase2-oos.ini: 23 settings updated
  phase3-mc-execution.ini: 23 settings updated
  phase4-mc-params.ini: 23 settings updated
  phase5-multi-tf.ini: 23 settings updated
  phase6-multi-instr.ini: 23 settings updated
  phase7-crossbroker.ini: 23 settings updated
  phase8-forward.ini: 23 settings updated

Done.

==========================================================

## clear-collections.cmd

Before starting a fresh pipeline run, you want to clear old JSON files from all collection folders. This script does it with one click and a confirmation:

cmd
@echo off
REM +=========================================================+
REM |                      QUANT-BOT.COM                      |
REM |            Clear All Pipeline Collections               |
REM |          8 Phases. Multiple Markets. One Goal.          |
REM |                                                         |
REM |          by Hani | Powered by Express Generator         |
REM +=========================================================+

echo WARNING: This will delete ALL .json files from collection folders:
echo.
echo   collections\phase1\
echo   collections\phase2\
echo   collections\phase3\
echo   collections\phase4\
echo   collections\phase5\
echo   collections\phase6\
echo   collections\phase7\
echo   collections\phase8\
echo.

set /p CONFIRM=Are you sure? (Y/N): 
if /i not "%CONFIRM%"=="Y" (
    echo Cancelled.
    pause
    exit /b
)

cd /d %~dp0\..

for /L %%P in (1,1,8) do (
    if exist "collections\phase%%P\*.json" (
        del /q "collections\phase%%P\*.json"
        echo Cleared phase%%P
    ) else (
        echo phase%%P already empty
    )
)

echo.
echo Done - all collections cleared.
pause

==========================================================

## Summary

The full pipeline folder structure looks like this:

multi_stage_processing\
  shared-settings.ini        <-- edit this for structure changes
  sync-settings.cmd          <-- pushes shared settings to all phases
  clear-collections.cmd      <-- clears all JSON collections
  workflow.cmd               <-- main 8-phase pipeline
  runner.cmd                 <-- launches multiple instruments
  phase1-generate.ini
  phase2-oos.ini
  phase3-mc-execution.ini
  phase4-mc-params.ini
  phase5-multi-tf.ini
  phase6-multi-instr.ini
  phase7-crossbroker.ini
  phase8-forward.ini

Typical workflow:
1. Edit `shared-settings.ini` if you need to change structure/account settings
2. Run `sync-settings.cmd` to push changes to all phases
3. Run `clear-collections.cmd` to start fresh
4. Run `runner.cmd` to launch the pipeline

Hope this saves you some time!

Cheers,
Hani

Re: 8-Phase Automated Validation Pipeline

footon wrote:

Great post, thank you for sharing and especially detailing your steps, Hani!

I have a question: you have your workflow sorted, it is fully automated and reaching the goals you have set so to speak, but why do you still need to know "exactly" why a strat has failed? Does this provide you with further data to refine the process?

All workflows may work and generate some good strategies, but I care about the higher percentages, so yes I need to modify, or sometimes drop most of the phases based on what I am building. I don't generate strategies blindly. 

footon wrote:

=Another one: this is about multimarket. You say that you're using structurally related pairs that share market dynamics, but the first example for EURUSD shows correlation to EURUSD that is all across the board! Average daily correlation for GBPUSD is high, for USDCHF it is high (oppositely moving), for EURGBP there's no correlation, for EURJPY it is very low, for EURCAD it is low. Have you taken actual correlation into account by choosing the pairings?

This step is very basic to my actual operating workflow, and my aim was to show the capabilities of automation specialy in express-generator because I had tough times in the beginning to create this, and wanted to shortcut the road somehow on the new comers, and a direct answer to your question, "NO" I didn't take the actual correlation, I do this somewhere else wink

5 (edited by quantbot Yesterday 13:02:25)

Re: 8-Phase Automated Validation Pipeline

The remaining files are attached here.

Post's attachments

phase6-multi-instr.ini 1.67 kb, file has never been downloaded. 

phase7-crossbroker.ini 1.6 kb, 2 downloads since 2026-02-16 

phase8-forward.ini 1.56 kb, 1 downloads since 2026-02-16 

runner.cmd 2.36 kb, 1 downloads since 2026-02-16 

workflow.cmd 22.11 kb, 1 downloads since 2026-02-16 

You don't have the permssions to download the attachments of this post.

Re: 8-Phase Automated Validation Pipeline

# Live Pipeline Dashboard for Express Generator

After building the [8-phase validation pipeline], I wanted a way to monitor what's happening across all instruments without digging through JSON files. So I built a browser-based dashboard that reads the collection folders in real-time and shows everything in one view.

===============================================

## What It Does

The dashboard is a single Node.js file (`dashboard.js`) that runs a local web server on port 3000. It scans your `collections/phase1` through `collections/phase8` folders every 60 seconds and displays:

- **Pipeline Funnel** — strategy counts per instrument across all 8 phases, with survival rates
- **Phase Drop-off** — visual bars showing where strategies get eliminated and the drop percentage at each phase
- **Summary Cards** — total generated, total survivors, in-pipeline count, and best Return/Drawdown
- **Phase 8 Survivors** — detailed cards for each instrument that made it through all 8 phases, showing average Profit, PF, R², R/DD, Win Rate, Drawdown, Trades, and validation tags (TF2/2, MI5/5)

It auto-refreshes every 60 seconds with a countdown timer, so you can leave it open in a browser tab while the pipeline runs.

===============================================

## Setup

### File Structure

Place both files in your `multi_stage_processing` folder (same folder as your pipeline scripts):

-----------------------
express-generator/
  multi_stage_processing/
    dashboard.js          <-- the dashboard
    dashboard.cmd         <-- launcher
    workflow.cmd           
    runner.cmd             
    phase1-generate.ini   
    ...
    phase8-forward.ini   
  collections/
    phase1/
    phase2/
    ...
    phase8/
-----------------------

### dashboard.cmd

cmd
@echo off
TITLE Quant-Bot Pipeline Dashboard
cd /d %~dp0
echo Starting dashboard server...
node dashboard.js
PAUSE

### Running It

1. Double-click `dashboard.cmd`
2. Open `http://localhost:3000` in your browser
3. Leave it open — it auto-refreshes every 60 seconds

The console will show:

  +=========================================================+
  |                  QUANT-BOT.COM                           |
  |           Pipeline Dashboard Running                     |
  +=========================================================+

  Open:  http://localhost:3000
  Auto-refreshes every 60s | Press Ctrl+C to stop

===============================================

## How It Works

The dashboard reads collection JSON files from each phase folder and counts the strategies inside. It handles both raw EA Studio format (`backtestStats`) and internal format (`stat`). For Phase 8 survivors, it also parses the validation tags from the filename (e.g., `P8_USDJPY_H1_TF2of2_MI5of5.json`) to show how many timeframes and instruments each strategy passed.

===============================================

## dashboard.js — Full Code

The file is about 500 lines (inline HTML/CSS/JS + Node.js server).

The full `dashboard.js` file is available for download in this thread. Just save it to your `multi_stage_processing` folder and run with `node dashboard.js`.

===============================================

## Features

- **Funnel table** with per-instrument breakdown across all 8 phases
- **Survival rate bars** with percentage per instrument
- **Drop-off chart** showing exactly where strategies fail
- **Phase 8 survivor cards** with full stats and validation tags (TF/MI)
- **Summary cards** — total generated, survivors, in-pipeline, best R/DD
- **Auto-refresh** every 60 seconds with countdown timer
- **Responsive** — works on any screen size
- **Zero dependencies** — runs on plain Node.js, no npm install needed

===============================================

## Combining with the Pipeline

The typical workflow is:

1. Run `runner.cmd` to launch the pipeline across multiple instruments
2. Open `dashboard.cmd` in a separate window
3. Browse to `http://localhost:3000` and watch strategies flow through the phases
4. When the pipeline finishes, the dashboard shows your final survivors with full stats

It's been very useful for spotting patterns — for example, I noticed that MC Parameter Sensitivity (Phase 4) was my biggest bottleneck, eliminating 85%+ of strategies. That told me my initial generation criteria might need tightening, or that many strategies were overfitting to specific indicator values.

===============================================

Hope this is useful for anyone running multi-phase pipelines. If you're only using 3-4 phases, you can easily modify the `PHASES` array at the top of the file to match your setup.

Cheers,
Hani

Post's attachments

dashboard.cmd 875 b, file has never been downloaded. 

dashboard.js 26.26 kb, file has never been downloaded. 

You don't have the permssions to download the attachments of this post.

Re: 8-Phase Automated Validation Pipeline

Hani,

Thank you very much for sharing your experience and code, and for the excellent explanation of your workflow!