This is the development community for the indicator that was discussed in great detail at:
http://www.forexfactory.com/showthread.php?t=464948
Please upload documents such as notes from this thread that you think are important and code samples that you have.
GitHub: https://github.com/PenguinTraders/FractalArrowPrediction
Instructions: http://penguintraders.com/groups/fractal-arrow-prediction/forum/topic/installation-getting-started-guide/
Documents List
-
A MQL5 implementation (37.3k) # Fractal DNA — a faithful, standalone MQL5 implementation (and an honest test of it)
Attached is a complete MQL5 implementation of the Fractals / ZigZag / "Pissing Dog"
method, built strictly to the specification, plus the validation harness used to
prove it correct — and the results of testing it out-of-sample.
I'll give you the good news and the bad news up front, because both matter.
**The good news:** the build is verified faithful. It reproduces the §5.4
validation targets, and it agrees bar-for-bar with an independent second
implementation written from the same spec.
**The bad news:** on the data I tested, the method shows no predictive edge. Raw
pattern lookup scores 50.1% against a 50.2% baseline, and the fractal
self-similarity filter — the method's central claim — performs identically to no
filter at all.
That combination is the reason I'm posting rather than quietly dropping it.
---
## Why another implementation
The reference build (`FractalArrowPrediction`) is the only implementation anyone
publicly reported results from, and its own author was blunt about it:
> "this indicator is no way trading ready … It's not accurate at all"
> — Saver0, INSTALL#325
But that tells us about *that code*, not about the method, because the reference
deviates from the specification in four specific, independently verifiable ways:
1. **SET3 filtered against bar substrings instead of fractal substrings** — this
destroys the cross-scale self-similarity filter that is the method's entire
premise; SET3 collapses toward SET1.
2. **Fractal encoding inverted** relative to bar encoding — breaks the shared
`1 = up` semantic that makes cross-scale matching mean anything.
3. **C1's projected-length criterion commented out** — removes the test that
crodzilla's third worked example shows is decisive.
4. **C3 consensus relaxed from 100% to 61%/33%** — admits signals the spec rejects.
There is also no §3.4 ZigZag/fractal synchronisation in it at all.
So "the reference performed badly" was always weak evidence about the method and
strong evidence about the implementation. A faithful build had never been
publicly tested. That gap is what this fills.
---
## What's included
| File | Goes in | Purpose |
|---|---|---|
| `FractalDNAStandalone.mq5` | `Indicators\FractalDNA\` | The indicator. Self-contained. |
| `FractalDNASelfTest.mq5` | `Scripts\FractalDNA\` | Validation harness — **please run this** |
| `FractalDNA.mqh` | `Include\FractalDNA\` | §3.1–3.3 encoders, key packing, set storage |
| `FractalDNAZigZag.mqh` | `Include\FractalDNA\` | ZigZag + §3.4 fractal synchronisation |
| `FractalDNASetBuilder.mqh` | `Include\FractalDNA\` | §4 SET1/SET2/SET3 construction |
| `FractalDNAModel.mqh` | `Include\FractalDNA\` | §5 state machine, C1–C3 |
### Installation
Open MetaTrader 5 and go to **File → Open Data Folder**, then into `MQL5`. Copy
the files as follows — the four `.mqh` headers go in `Include`, **one copy only**:
```
MQL5\
├── Include\FractalDNA\ <-- create this folder │ FractalDNA.mqh │ FractalDNAZigZag.mqh │ FractalDNASetBuilder.mqh │ FractalDNAModel.mqh ├── Indicators\FractalDNA\ <-- create this folder │ FractalDNAStandalone.mq5 └── Scripts\FractalDNA\ <-- create this folder FractalDNASelfTest.mq5 ``` The folder names matter: the sources use `#include `, which
resolves from `MQL5\Include`, so the headers must sit in a folder called exactly
`FractalDNA` there.
Then in MetaEditor (F4), open `FractalDNAStandalone.mq5` and press **F7**, and do
the same for `FractalDNASelfTest.mq5`. Both should report `0 errors`. Back in the
terminal, press **Ctrl+M** to refresh the Navigator; the indicator appears under
*Indicators → FractalDNA* and the script under *Scripts → FractalDNA*.
Drag the indicator onto a **EURUSD M5** chart. First load builds the sets, which
takes a few seconds — watch the *Experts* tab for the build report.
> **If you edit any `.mqh`, recompile both programs and re-run the self-test.**
> The indicator and the validation harness share these headers deliberately, so
> that what you validate is what you run.
**Fully standalone.** No database, no set file, no Node.js, no Python, no DLL, no
network. Drop it on a chart and it builds its own sets from the chart's bars.
This deliberately avoids the MT4→SQL bridge the spec calls out as the documented
performance killer (§10.1) — everything is in-memory hash maps keyed on packed
`ulong` patterns.
### What is implemented
§3.1 bar bit-string including the 3-way doji rule · §3.2 fractals, lengths 5–9,
replicating MT4 `iFractals`' equal-high variants · §3.3 twin unfolding · **§3.4
ZigZag endpoints delayed to the next fractal** · §3.5 broken-chain (gap)
invalidation · §4 SET1/2/3 with SET3 filtered on **fractal** substrings · §5
state machine S0–S3 with C1's length criterion and C3's 100% consensus across
k ∈ [4,13] · §5.6 alternation and restart-from-signal.
### What is not
§6 Three Doors and §7 Adaptability. The spec's own build order (§10.4) puts them
after §5 is verified, and neither is specified precisely enough to implement
without guessing. Given the §5 results below, adding them would be decorating a
foundation that doesn't hold.
### Provenance of each step
Because two of the source documents have different terms, here is exactly which
one each part of the code follows.
| Step | Followed from | Terms |
|---|---|---|
| §3.1–3.5 encoders, ZigZag sync | `FractalDNA.pdf` §3–§4 (flx23) | no restriction |
| §4 SET1/2/3 | `FractalDNA.pdf` §5.1–5.3 | no restriction |
| §5.2 projected length | `FractalDNA.pdf` §6.2 | no restriction |
| §5.3 C1 | `FractalDNA.pdf` §6.3.2 | no restriction |
| §5.4 C2 | gg53, FF#203 — `MAX(p7…p13) > p14` | forum post |
| §5.5 C3 | `FractalDNA.pdf` §6.3.4 | no restriction |
`Probabilities.pdf` ( 2014 Carl Rodriguez, Inc.) contributes the **worked
numeric examples** and implementation guidance — the `(1010)` length walkthrough,
the three C1 verdicts, the 100%-consensus recommendation and the log format.
Those were invaluable for checking the implementation was right, and crodzilla
deserves the credit for them, but none of that material is reproduced in this
code. The algorithms themselves are the ones set out in `FractalDNA.pdf`, which
carries no restriction.
The projected-length step is switchable between the two published formulations:
`ProjectLenMethod = CRODZILLA` (clustering ratio, threshold 0.50) and `GG53`
(max over ±3 versus +4 — the same comparison shape gg53 gives for C2 in FF#203).
Both are described in `FractalDNA.pdf` §6.2.
### Non-repainting
Fractals are used only once their two right-hand bars exist, and the ZigZag
anchor at any bar is what ZigZag would have shown *at that bar* using bars 0..i
only. Arrows are drawn on closed bars and do not move afterwards. The forming bar
is never encoded.
---
## Validation — please reproduce this
Run `FractalDNASelfTest` on a EURUSD M5 chart. It uses `CopyRates` over an
explicit date range, so it validates the 2011–2012 window regardless of what your
chart is showing. It prints the §5.4 figures and writes three CSVs: its signals,
plus complete key-by-key dumps of SET2 and SET3.
I built a second, independent implementation in Python from the same spec and
cross-checked everything.
**Set construction, EURUSD M5, 2011-01-01 → 2012-12-31:**
| Set | Target (§5.4) | Dukascopy feed | Broker feed |
|---|---|---|---|
| SET1 keys | 16,368 | **16,368** | 16,366 |
| SET2 keys | ~990 | 988 | 996 |
| SET2 legs | ~8,000 | 7,951 | 7,811 |
| SET3 keys | ~2,000 | 2,012 | 1,926 |
The targets reproduce on two independent data sources. The small differences are
data-source artefacts (session boundaries, weekend handling), not logic.
**Cross-implementation agreement:** on identical bars, MQL5 and Python produce
**bit-identical SET2 and SET3** — every key, every occurrence count, and every
per-leg bar-count list across all 996 SET2 keys. Out-of-sample over 2013 Q1 both
produce **121 signals, 27 UP / 94 DOWN, agreeing bar-for-bar**.
Getting there took three rounds of debugging, and every bug was caught by these
dumps rather than by eyeballing arrows. At one point the two builds agreed on
97.5% of signals — close enough to look finished, and wrong. The causes were a
pattern-key truncation, a date-boundary off-by-one-day, and a leg-anchor guard
that let an old pivot drag the leg start backwards past a §5.6 restart. **If you
modify this code, re-run the self-test.** Arrows appearing on the chart tells you
almost nothing.
---
## Results — the part that matters
Everything above establishes the build is *faithful*. It says nothing about
whether the method *works*. So I tested it, out-of-sample, with sets built
strictly on bars older than every bar evaluated.
### Test 1 — does the database predict the next bar at all?
Strip away C1/C2/C3, the state machine, ZigZag and leg tracking. Ask SET3 the one
question the whole method rests on: given the last k−1 bars, is the next bar more
often 1 or 0? Sets built on 2024-04 → 2026-04; tested on 14,581 bars after that.
Baseline (majority class) is 50.2%.
| Level k | SET3 accuracy | SET1 accuracy (control) |
|---|---|---|
| 4 | 49.8% | 49.8% |
| 6 | 49.8% | 49.9% |
| 8 | 50.2% | 49.5% |
| 10 | 50.1% | 50.0% |
| 12 | 49.3% | 50.6% |
| unanimous across all levels | **50.1%** | 50.1% |
Every cell is within about a point of zero edge; binomial noise at these sample
sizes is ±0.5 points. The unanimous-consensus row — the actual §5.5 shape — scores
50.1% on 5,674 opportunities. Requiring every level to agree buys nothing.
**And SET3 scores the same as unfiltered SET1.** This is the part I'd most like
someone to check independently, because it goes at the thesis rather than the
tuning. §4's filter is *correctly implemented* here — verified against the targets
above — and it reduces 16,368 keys to 1,926. It changes which bars you have an
opinion about. It does not change how often that opinion is right.
### Test 2 — the full state machine
Sets built 2024-04 → 2026-04, tested on two disjoint out-of-sample windows split
before looking at results. "Edge" is hit rate minus what a coin flip with the same
up/down mix scores given each window's drift — so a permanently-bearish signal in
a falling market gets no free credit.
| C3 configuration | Window A | Window B |
|---|---|---|
| **Faithful §5.5** | −14.9% | −13.7% |
| Drop the current-bar check | −5.4% | −6.4% |
| next OR curr | −4.6% | −4.5% |
All negative, on both windows. Mean move per signal was −1.8 to 0.0 pips before
spread.
The ordering is the informative part: **the more aggressively C3 filters, the
worse the result**, and the faithful configuration is the worst of the lot by a
factor of three. If the database carried signal, tightening the filter should
concentrate it.
### An oddity worth reporting
Under the literal §5.5 reading, the two consensus checks are near mutually
exclusive in one direction. Over three months the model produced **65 signals, all
UP, zero DOWN**. ZigZag anchors were balanced (445 highs / 446 lows) and the state
machine reached the final gate evenly, but of 102 bars where the bearish next-bar
consensus held, *not one* also satisfied the current-bar consensus.
The cause is that the current-bar probe silently encodes the current bar's own
direction, so demanding it alongside an opposite next-bar call makes that branch
unreachable. That also means §5.6's alternation requirement cannot hold. Whether
this is what crodzilla intended is a fair question — the prose note ("it does not
matter whether the consensus actually matches the current bar") reads against the
pseudocode. I implemented the pseudocode. Fixing it restores DOWN signals but
does not produce an edge.
---
## Honest limits
One symbol, one timeframe, one two-year build window, one three-month test. This
does not prove the method fails everywhere. The obvious extensions, all cheap with
the attached code: other majors, M15/H1, and — most interesting — build on
2011–2012 and test on 2013, to see whether an edge existed in the era gg53 worked
in and has since decayed.
Also worth remembering: gg53 was updating his database with corrections
continuously from early 2013 (FF#285), so anyone starting from the same base data
will diverge from his published results. That alone explains much of the thread's
"why don't my results match?" traffic.
And the epilogue is hard to ignore. By December 2014 gg53 had moved on — a neural
net over three years of data ranked tick volume, currency strength, regression and
weekly channels, weekly pivots, momentum and volatility as the predictive features.
No fractals. No ZigZag. He never published working fractal-DNA results and never
returned to the method.
That isn't proof it fails. But the strongest advocate stopped using it, and now a
verified-faithful build measures no edge on modern data.
---
## Use it for what it's good for
This is a correct implementation of a specified method, with the tooling to prove
it correct. Use it to test the method properly, on data and instruments I haven't
touched. If you find an edge I missed, the self-test means you can demonstrate
your build is the specified thing rather than a new set of bugs — which is more
than anyone in this thread has been able to say until now.
Please don't trade it on the strength of the arrows appearing.
Full specification attached (`Fractals_ZZ_PissingDog_MQL5_Spec_v4_FINAL.md`) with
sources cited to individual forum posts, so every design decision here can be
traced back to something gg53, flx23, or crodzilla actually wrote.
Nothing here is investment advice. -
ZZ closed modified (9k)
modification of ZZ closed by Emonts. Do not know this is the right way to get ZZ by closed price or not, not tested yet
-
Fractal_Close_Mod (4.8k)
Modification of Fractal_Close indicator by Emonts. Adding weekend time filter, using only 5 bars to check the fractals.
-
CSV to create Database (1.7m) I uploaded the CSV file for filling the database. I created this file with Smallcats Indi, modified to use only valid close Fractals and ZigZag.
Note that i haven’t filtered ZigZags that don’t end on a Fractal.
You have to handle the situation where two Fractals appear at one bar.
You have to handle the situation with Doji Bars. -
ZigZag Close Modified (11.4k)
This is a modification of ZigZag_Close by Emonts. This file needs Fractals_close indicator (by Emonts too). Thanks Emonts.
ZZ close Mod will try to find the end of swing based on CLOSE price, and at the end of ZZ point, it must be fractal exists (based on CLOSE price too). -
fractals close (6.1k)
Hi,
Adapted fractal indicator based on bar close values.
The arrows are a little small. I put them 1 pip above or below the bars in the chart.
Just give it a try.
This indi does not show only the "good" fractals of GG's last chart.
But maybe it gives us a better idea in what direction we have to search/look.
So some research has to be done.BR
Huub -
ZigZag_Close.mq4 (8.3k)
Adapted zigzag indicator
-
Comprehensive notes from FF (1.6m) Thank you so much Madmoney for sharing this great document. I'm making a copy of it in the documents section so all the important stuff is here in one place.
-
Blank EA (1.3k)
This is just an empty EA to be used for back testing the indicator.