MQL5 traps
Index direction
In MQL5 a series array is often read newest first, so index 0 is the current bar. A port that keeps close[1] for "the previous bar" reads the wrong bar.
import forge as fg
FORGE_API = 1
def last_two_closes(close):
# Oldest first: [-1] is the latest closed bar, [-2] the one before it.
return close[-2], close[-1]Point, Digits and pips
_Point is the smallest price step and _Digits its number of decimals. A pip is 10 points on symbols with 5 or 3 digits and 1 point elsewhere. Forge prices are raw prices such as 1.08543, never points or pips. A pip or point amount appears only where a price amount is typed, and is resolved through the broker facts.
EMPTY_VALUE
An indicator buffer holds EMPTY_VALUE for "no value", which is a very large number. Forge uses NaN, and a comparison with NaN is false.
import forge as fg
from forge import ta
FORGE_API = 1
def ready(value):
# A missing value is NaN, never a sentinel number.
return ~ta.isna(value)Hedging and netting
An MQL5 account is either hedging, which allows several positions on one symbol, or netting, which keeps one. Forge reads the account's margin mode from the broker facts. A strategy that opens an opposite order on a netting account reduces or reverses the position, and an order the account does not allow is rejected with a named reason.
Ticks and bars
An expert advisor reacts in OnTick, on every price update. A Forge strategy decides on closed bars and fills at the next real price. A port that depended on the tick it was called on needs another design, or a bar type built from ticks.
Magic numbers
A magic number tags the orders of one expert advisor. Forge orders carry a tag, and a strategy lists its own positions by tag.
prev_calculated
OnCalculate receives prev_calculated, the number of bars already done. Forge passes start, the first bar to fill, to calculate. Fill every output from start on and do not keep your own count.