Generic State Machine Framework
Order and position lifecycles in a real expert advisor grow conditionals fast: "if pending and not already filled and connection is up, fill it; if open and stop hit and not already closing, close it; if rejected, cancel regardless of where we were." Written as nested if/else across OnTick, OnTradeTransaction and a handful of flags, this logic becomes exactly the kind of code nobody wants to touch six months later, because the actual set of valid transitions is nowhere written down - it only exists as the union of every condition scattered through the file. This header makes the transition table explicit. You register rules once, each one a plain (fromState, event, toState) triple with an optional name, and then the entire lifecycle collapses to one call: sm.Fire(eventId). The machine looks up the matching rule, checks an optional guard, runs optional enter/exit hooks, updates the state, and logs exactly what happened. If no rule matches the current state, Fire() returns false and changes nothing - the machine never silently accepts an event it has no rule for. States and events are plain integers you define yourself with #define or an enum - the framework has no opinion on what they mean, so it applies equally to an order lifecycle, a connection state machine, or a multi-leg strategy's own phase tracking. NameState is optional and purely cosmetic, used only to make the log readable. A wildcard "from" state (STATEMACHINE_ANY_STATE) lets one rule apply regardless of the current state - the natural way to model something like a broker rejection, which can happen whether the order was pending or already open, without duplicating the same rule for every state it should cover. Guards and lifecycle hooks go through one optional listener interface with non-pure virtual methods, so a simple machine that only needs a guard is not forced to also implement three empty hook methods it does not use. Notes and limitations - Exactly one rule fires per Fire() call, chosen by exact (state, event) match first, falling back to a wildcard rule for that event if no exact match exists. If you register both an exact and a wildcard rule for the same event, the exact one always wins - this is deliberate, not a bug. - The state machine is not itself thread-safe or re-entrancy-safe: calling Fire() from inside a listener hook works, but the log and state changes interleave in call order, so keep hook logic simple if you do this. - Guards run before OnExit/OnEnter/OnTransition. A guard that returns false leaves the machine completely unchanged - no hooks fire, no log entry is added beyond the "BLOCKED" line. - This header does not persist state across terminal restarts. If your lifecycle must survive a restart, save CurrentState() yourself (a global variable or a file) and reconstruct the machine with that state on OnInit - see StateSerializer.mqh elsewhere in this catalogue for a ready-made way to save mixed-type state like this to a file.
Script · MT4 · v1.0 · Free
About Generic State Machine Framework
Generic State Machine Framework is a script for MetaTrader 4. MQL source code included.
Files in the download: StateMachineFramework.mqh, StateMachineFramework.txt, StateMachineFrameworkDemo.mq4.
How to install
- Download the ZIP from your PolyMaria library and unzip it.
- In MetaTrader 4 open File → Open Data Folder, then go to MQL4 → Scripts.
- Copy the .mq4 file(s) there. Put any .mqh files in MQL4 → Include.
- Open the .mq4 file in MetaEditor and press Compile (F7) if MetaTrader does not show it.
- Drag the script onto a chart to run it once.
Tags: MT4 Script · MQL4 Source Code