In this lesson, you will learn:
OnTick() is really meant to doOnTick() causes problems
OnTick() runs every time a new price tick arrives.
That can be many times per second.
Because of this, OnTick() should:
OnTick() should NOT:
Think of OnTick() as a traffic controller,
not a worker.
Most beginners start with something like this:
void OnTick()
{
// Spread check
double spread = MarketInfo(Symbol(), MODE_SPREAD);
if(spread > 20) return;
// Time filter
if(Hour() < 8 || Hour() > 16) return;
// Entry logic
if(OrdersTotal() == 0)
{
// OrderSend logic
}
// Trade management
if(OrdersTotal() > 0)
{
// trailing stop, exits, etc.
}
}
This code works, but it quickly becomes:
A well-structured OnTick() should be short and readable.
You should be able to understand it without scrolling.
void OnTick()
{
UpdateTradingRules();
if(!TradingAllowed) return;
ManageOpenTrades();
LookForEntries();
}
If you can read OnTick() like a checklist,
you are doing it right.
Rule checks include:
Instead of checking these directly in OnTick(),
move them into a single function.
// Global state
bool TradingAllowed = true;
void UpdateTradingRules()
{
TradingAllowed = true;
if(MarketInfo(Symbol(), MODE_SPREAD) > 20)
TradingAllowed = false;
if(Hour() < 8 || Hour() > 16)
TradingAllowed = false;
}
Now OnTick() simply asks:
if(!TradingAllowed) return;
//Meaning if TradingAllowed==False go back to the start and try again... YOU SHALL NOT PASS!
Managing open trades and opening new trades are two very different jobs.
They should NEVER be mixed in the same block of code.
void ManageOpenTrades()
{
// trailing stops, exits, breakeven logic
}
void LookForEntries()
{
if(OrdersTotal() > 0) return;
// entry logic here
}
This prevents:
Many EA calculations do not need to run on every tick.
A common professional technique is to run logic once per candle.
datetime LastBarTime = 0;
bool IsNewBar()
{
if(Time[0] != LastBarTime)
{
LastBarTime = Time[0];
return(true);
}
return(false);
}
Now OnTick() becomes even cleaner:
void OnTick()
{
UpdateTradingRules();
if(!TradingAllowed) return;
if(IsNewBar())
{
ManageOpenTrades();
LookForEntries();
}
}
This shows the recommended structure for a beginner-friendly, professional-quality EA.
//==============================
// GLOBAL VARIABLES
//==============================
bool TradingAllowed = true;
datetime LastBarTime = 0;
//==============================
// ONTICK (traffic controller)
//==============================
void OnTick()
{
UpdateTradingRules();
if(!TradingAllowed) return;
if(IsNewBar())
{
ManageOpenTrades();
LookForEntries();
}
}
//==============================
// LOGIC FUNCTIONS
//==============================
void UpdateTradingRules()
{
TradingAllowed = true;
if(MarketInfo(Symbol(), MODE_SPREAD) > 20)
TradingAllowed = false;
if(Hour() < 8 || Hour() > 16)
TradingAllowed = false;
}
void ManageOpenTrades()
{
// trade management logic
}
void LookForEntries()
{
if(OrdersTotal() > 0) return;
// entry logic
}
//==============================
// HELPER FUNCTIONS
//==============================
bool IsNewBar()
{
if(Time[0] != LastBarTime)
{
LastBarTime = Time[0];
return(true);
}
return(false);
}
OnTick() should be short and readableWriting Clean, Readable EA Code
We will focus on naming, spacing, comments, and structure so your EA is easy to understand months later.