Generate code in 3 minutes
Enter your idea and AI generates runnable code.
To capture the price of every single tick in MQL4 for a fast scalping strategy, you must utilize the OnTick() event handler combined with the SymbolInfoTick() function.
In high-frequency or fast scalping strategies, using the standard Bid and Ask variables is acceptable, but SymbolInfoTick() is superior because it populates an MqlTick structure. This ensures that the Bid, Ask, and Time values are synchronized from the exact same snapshot, preventing data mismatch during highly volatile moments.
OnTick(). This function triggers every time the server sends a new price update.MqlTick to get Bid and Ask simultaneously.OnTick must execute faster than the arrival of the next tick. Avoid Sleep(), heavy loops, or complex graphical object creation inside the main trading logic.Here is a complete, optimized framework for a tick-based scalping strategy.
//+------------------------------------------------------------------+
//| FastTickScalper.mq4 |
//| Copyright 2023, Quantitative AI Assistant |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, Quantitative AI Assistant"
#property link "https://www.mql5.com"
#property version "1.00"
#property strict
//--- Input Parameters
input double InpLots = 0.1; // Lot size
input int InpStopLoss = 10; // Stop Loss in points
input int InpTakeProfit = 10; // Take Profit in points
input int InpMaxSpread = 15; // Max allowed spread in points
input int InpSlippage = 3; // Max slippage in points
input int InpMagicNum = 12345; // Magic Number
//--- Global Variables for Tick Analysis
MqlTick currentTick;
double lastTickBid = 0;
double lastTickAsk = 0;
double point;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
// Initialize point value for calculations
point = Point;
if(Digits == 3 || Digits == 5) point *= 10;
// Initial data population
if(!SymbolInfoTick(_Symbol, currentTick))
{
Print("Failed to get initial tick data");
return(INIT_FAILED);
}
lastTickBid = currentTick.bid;
lastTickAsk = currentTick.ask;
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
// 1. GET THE TICK DATA
// We use SymbolInfoTick for atomic data access (Bid/Ask/Time sync)
if(!SymbolInfoTick(_Symbol, currentTick))
{
// If we can't get the tick, we can't trade. Exit immediately.
return;
}
// 2. CHECK SPREAD (Crucial for Scalping)
// Calculate spread in points
int spread = (int)((currentTick.ask - currentTick.bid) / Point);
// If spread is too high, do not execute logic
if(spread > InpMaxSpread)
{
// Update history for next comparison and exit
lastTickBid = currentTick.bid;
lastTickAsk = currentTick.ask;
return;
}
// 3. FAST SCALPING LOGIC
// Example Logic: Detect a micro-momentum (Tick moves up/down)
// NOTE: Replace this block with your specific algo logic
bool signalBuy = false;
bool signalSell = false;
// Simple example: If Bid moved up significantly in one tick
if(currentTick.bid > lastTickBid + point)
{
signalBuy = true;
}
// Simple example: If Bid moved down significantly in one tick
else if(currentTick.bid < lastTickBid - point)
{
signalSell = true;
}
// 4. EXECUTION
// Only check orders if we have a signal to save CPU cycles
if(signalBuy || signalSell)
{
// Check if we already have open positions to avoid over-trading
if(OrdersTotal() == 0)
{
if(signalBuy)
{
OpenTrade(OP_BUY, currentTick.ask);
}
else if(signalSell)
{
OpenTrade(OP_SELL, currentTick.bid);
}
}
}
// 5. STORE HISTORY
// Store current tick as "last" for the next execution
lastTickBid = currentTick.bid;
lastTickAsk = currentTick.ask;
}
//+------------------------------------------------------------------+
//| Helper: Open Trade |
//+------------------------------------------------------------------+
void OpenTrade(int type, double price)
{
double sl = 0, tp = 0;
// Calculate SL/TP based on direction
if(type == OP_BUY)
{
if(InpStopLoss > 0) sl = price - InpStopLoss * point;
if(InpTakeProfit > 0) tp = price + InpTakeProfit * point;
}
else if(type == OP_SELL)
{
if(InpStopLoss > 0) sl = price + InpStopLoss * point;
if(InpTakeProfit > 0) tp = price - InpTakeProfit * point;
}
// Normalize prices
sl = NormalizeDouble(sl, Digits);
tp = NormalizeDouble(tp, Digits);
price = NormalizeDouble(price, Digits);
// Send Order
int ticket = OrderSend(_Symbol, type, InpLots, price, InpSlippage, sl, tp, "FastScalper", InpMagicNum, 0, clrNONE);
if(ticket < 0)
{
Print("OrderSend failed with error #", GetLastError());
}
}
MqlTick currentTick: This structure is the core of the strategy. It holds time, bid, ask, last, and volume. Using this structure is faster and cleaner than calling MarketInfo() multiple times.SymbolInfoTick(_Symbol, currentTick): This function fills the structure with the very latest data from the market watch. It returns true if successful.OnTick if the spread exceeds InpMaxSpread. This prevents the EA from calculating logic during expensive market conditions.currentTick against lastTickBid (stored from the previous execution). This allows you to analyze price velocity or direction tick-by-tick.OrdersTotal() only after a signal is generated. This saves processing time on ticks where no signal exists, which is the majority of the time.While the code above is optimized, you must be aware of the platform limitations:
OnTick() logic takes 100ms to execute, but 3 ticks arrive during that 100ms, you will miss 2 ticks. The EA will only process the latest tick available when it finishes the previous calculation.CopyTicks function to retrieve history. You can only see the current tick. If you miss a tick because the CPU was busy, that data is lost to the EA.Q: Can I backtest this tick strategy in MT4?
A: Yes, but with limitations. MT4 Strategy Tester generates ticks based on M1 OHLC data (interpolation), meaning the ticks are simulated, not real. For accurate tick scalping backtests, you must use "Tick Data Suite" or similar 3rd party tools to inject real tick history into MT4, or switch to MT5 which supports real tick data natively.
Q: How do I make the code run faster?
A: Remove any Print() or Comment() functions from the OnTick loop, as writing to the log/screen is slow. Ensure you are not calling heavy custom indicators (iCustom) on every tick; instead, code the indicator logic directly into the EA if possible.
Q: Why use SymbolInfoTick instead of Bid and Ask?
A: Bid and Ask are variables that are updated automatically, but SymbolInfoTick fills a structure that includes the time and volume of that specific tick update. It ensures that if you read the Bid and then the Ask, they belong to the exact same market snapshot.