MQL5 language basics & the three event handlers
Types, functions, #property directives and input parameters, then the lifecycle every EA is built on: OnInit, OnTick and OnDeinit — with a minimal EA you can compile and run.
MQL5 reads like C++ with the sharp edges filed off: statically typed, compiled, curly-brace blocks, every statement ending in a semicolon. If you have written Python, the ideas transfer — you just have to *declare your types* and get used to the compiler refusing to run until everything lines up.
Types you will actually use
int— whole numbers (a period, a bar count). 32-bit signed. There is alsolongfor 64-bit.double— floating-point numbers. All prices, lot sizes and indicator values aredouble. This is the workhorse type.bool—true/false.string— text, in double quotes:"EURUSD". Used for symbols, comments and logging.datetime— a point in time (seconds since 1970). The open time of a bar is adatetime; comparing them is how you detect a new bar.color,enum,struct— you will meet these later; enums in particular name your dropdown options in the inputs panel.
Functions and the shape of a program
A function declares its return type, a name, and typed parameters. void means it returns nothing. Here is an ordinary helper — nothing special, just to fix the syntax in your mind:
class="c">// Returns the pip value distance as a price offset.
class="c">// _Point and _Digits are built-in variables for the current symbol.
double PipsToPrice(int pips)
{
class="c">// On class="n">5-digit and class="n">3-digit brokers, one class="s">"pip" is class="n">10 points.
double factor = (_Digits == class="n">3 || _Digits == class="n">5) ? class="n">10.0 : class="n">1.0;
return(pips * _Point * factor);
}Note the details: the type before the name, the semicolons, the // comments, and the ternary ?: operator. return wraps its value in parentheses by convention. _Point and _Digits are built-in globals the terminal fills in for the chart's symbol — you will use dozens of these.
#property: metadata for the compiler
Every EA starts with #property directives — preprocessor lines that tell MetaEditor and the terminal about your program. They are not code that runs; they are labels baked into the compiled file.
class="c">#property copyright class="s">"AlgoPro University"
class="c">#property link class="s">"https:class="c">//algopro-university.netlify.app"
class="c">#property version class="s">"class="n">1.00"
class="c">#property description class="s">"Teaching EA — demo accounts only, not financial advice."input: the parameters the user can change
The single most useful keyword in MQL5 is input. An input variable becomes a field in the EA's settings dialog — the box that pops up when you attach the EA to a chart or launch the Strategy Tester. This is how you expose a strategy's knobs (periods, lot size, stop distance) without editing code, and — crucially — it is what the optimiser sweeps in the final lesson.
input int FastPeriod = class="n">12; class="c">// Fast MA period
input int SlowPeriod = class="n">26; class="c">// Slow MA period
input double Lots = class="n">0.10; class="c">// Trade size in lots
input double StopLossPips = class="n">40; class="c">// Stop-loss distance (pips)
input double TakeProfitPips = class="n">80; class="c">// Take-profit distance (pips)
input ulong MagicNumber = class="n">8080; class="c">// Unique EA id for its own ordersThe three handlers: an EA's whole life
An EA has a lifecycle, and MQL5 gives you exactly three functions to hook into it. The terminal calls them for you at the right moments — you never call them yourself.
OnInit()— called once, when the EA is attached to the chart (or a test run starts, or inputs change). Set things up here: create indicator handles, validate inputs, allocate state. ReturnsINIT_SUCCEEDEDif all is well, or an error code to abort.OnTick()— called on every incoming tick. This is where the strategy lives: read data, decide, trade. It runs constantly, so it must be fast and defensive.OnDeinit()— called once, when the EA is removed, the chart closes, the timeframe changes, or the terminal shuts down. Clean up here: release indicator handles, tidy state. It receives areasoncode telling you *why* it is stopping.
A minimal EA you can compile right now
Here is the smallest complete Expert Advisor. It does not trade — it just prints, so you can watch the lifecycle in the terminal's Experts log tab and *feel* how ticks arrive.
class="c">#property copyright class="s">"AlgoPro University"
class="c">#property version class="s">"class="n">1.00"
input string Greeting = class="s">"Hello from MQL5"; class="c">// Message to print on start
int tickCount = class="n">0; class="c">// Global state persists across OnTick calls
class="c">// Called once when the EA starts.
int OnInit()
{
Print(Greeting, class="s">" — attached to ", _Symbol, class="s">" ", EnumToString(_Period));
tickCount = class="n">0;
return(INIT_SUCCEEDED);
}
class="c">// Called on every incoming tick.
void OnTick()
{
tickCount++;
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
class="c">// Print only every 50th tick so the log stays readable.
if(tickCount % class="n">50 == class="n">0)
Print(class="s">"Tick class="c">#", tickCount, class="s">" bid=", DoubleToString(bid, _Digits));
}
class="c">// Called once when the EA is removed.
void OnDeinit(const int reason)
{
Print(class="s">"EA stopped after ", tickCount, class="s">" ticks. Reason code: ", reason);
}Compile it (F7), drag it onto a demo EURUSD chart, and watch the Experts tab. You now understand the skeleton every EA in the world is built on. Next we make it *read the market*.