# From MQL5

Forge code is Python, but the ideas map across. An MQL5 indicator becomes an `fg.Indicator` with outputs in place of buffers. An MQL5 expert advisor becomes an `fg.Strategy` whose `compute` returns signals.

## What is different

- **Arrays run oldest first.** Index 0 is the oldest bar and `-1` is the latest closed bar. There is no series mode to switch on.
- **Missing values are NaN,** not `EMPTY_VALUE`.
- **Decisions are made on closed bars** and filled at the next real price. A strategy does not run on every tick.
- **Time is UTC.** The broker's clock is available, and converted for you.
- **The data is arrays.** `calculate` fills whole arrays instead of looping over `rates_total`.

The [traps page](https://oathra.dev/docs/porting/mql5/traps) lists the mistakes that cost the most when porting.

## Start from your file

The [Indicators](https://oathra.app/forge/indicators) screen in Oathra can convert an MQL5 indicator you already own. It turns the file into Python and says what translated exactly, what was approximated and what could not be converted. It converts indicators, not expert advisors: a file that places orders is refused.

Functions that only draw, notify or write files are dropped, because they change no number. Functions that read the wall clock, such as `TimeCurrent`, cannot be reproduced in a backtest and are reported as not translatable.

## Then read

Start with [repainting and look-ahead](https://oathra.dev/docs/concepts/repainting-and-look-ahead) and [warm-up](https://oathra.dev/docs/concepts/warm-up). Most ported indicators fail on one of the two.

## Name by name

[Every MQL5 name beside what you write in Forge](https://oathra.dev/docs/porting/mql5/to-forge). A test of the same rules can give different numbers in MetaTrader and in Forge: see [why a MetaTrader report and a Forge test differ](https://oathra.dev/docs/porting/why-results-differ).
