| //+------------------------------------------------------------------+
|
| //| Tick_Forge.mq5 |
|
| //| Copyright (c) 2026 Joshua Dunnink. MIT License (see LICENSE). |
|
| //| |
|
| //| Build custom backtesting symbols from your broker's own history: |
|
| //| - shift the raw timestamps by hours or days |
|
| //| - rescale / reshape prices with a typed function |
|
| //| - write real (transformed) ticks or M1 bars |
|
| //| The result is an ordinary custom symbol the Strategy Tester can |
|
| //| use (Every tick / Every tick based on real ticks / 1 minute OHLC).|
|
| //| |
|
| //| A utility: attach it to any chart to open its window. It never |
|
| //| trades. The source is open and it uses no DLL. It writes only the |
|
| //| custom symbol (its bars and ticks) - nothing else. |
|
| //+------------------------------------------------------------------+
|
| #property copyright "Copyright (c) 2026 Joshua Dunnink - MIT License"
|
| #property link "https://forge.mql5.io/joshuadunnink/Tick_Forge"
|
| #property version "1.04"
|
| #property description "Tick Forge builds custom symbols for the Strategy Tester from your broker's own history."
|
| #property description "Shift the timestamps, rescale or reshape the prices with a typed function, test your EA on the result."
|
| #property description "Utility: it never trades. Free and open source (MIT). No DLL, no internet access."
|
| #property strict
|
|
|
| #include "TF_Gui.mqh"
|
|
|
| int OnInit()
|
| {
|
| PrintFormat("Tick Forge v1.04 | chart %s", _Symbol);
|
| if(MQLInfoInteger(MQL_TESTER) || MQLInfoInteger(MQL_OPTIMIZATION))
|
| {
|
| Print("Tick Forge is a utility for a live chart (it creates symbols); it does nothing in the Strategy Tester.");
|
| return INIT_SUCCEEDED;
|
| }
|
| g_dlg = new CTickForgeDlg();
|
| if(!g_dlg.Create(0, "Tick Forge 1.04", 0, 20, 20, 20 + TF_W, 20 + TF_H))
|
| {
|
| const string need = StringFormat("Tick Forge needs a chart of at least %d x %d pixels (enlarge the window or maximise the chart).", TF_W + 40, TF_H + 40);
|
| Print(need);
|
| Comment(need);
|
| delete g_dlg; g_dlg = NULL;
|
| return INIT_SUCCEEDED;
|
| }
|
| g_dlg.Run();
|
| EventSetMillisecondTimer(30);
|
| return INIT_SUCCEEDED;
|
| }
|
|
|
| void OnDeinit(const int reason)
|
| {
|
| EventKillTimer();
|
| if(g_dlg != NULL) { g_dlg.Destroy(reason); delete g_dlg; g_dlg = NULL; }
|
| Comment("");
|
| }
|
|
|
| void OnTick() {}
|
|
|
| void OnTimer()
|
| {
|
| if(g_dlg == NULL) return;
|
| g_dlg.Tick(); // one day / one month of work per call, so the window stays responsive
|
| if(g_dlg.Closed()) ExpertRemove();
|
| }
|
|
|
| void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam)
|
| {
|
| if(g_dlg != NULL) g_dlg.ChartEvent(id, lparam, dparam, sparam);
|
| }
|
| //+------------------------------------------------------------------+
|