Generate code in 3 minutes
Enter your idea and AI generates runnable code.
Here is a complete, fully commented MQL4 Expert Advisor (bot) that implements a Straddle Strategy.
Ask + Distance.Bid - Distance.//+------------------------------------------------------------------+
//| NewsStraddleBot.mq4 |
//| Copyright 2023, Quantitative Trading AI |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, Quantitative Trading AI"
#property link "https://www.mql5.com"
#property version "1.00"
#property strict
//--- Input Parameters
input string TimeSettings = "=== Time Settings ===";
input int TargetHour = 14; // Target Hour (Server Time, e.g., 14 for 14:30)
input int TargetMinute = 30; // Target Minute (e.g., 30 for 14:30)
input int MinutesBefore= 5; // How many minutes before target to place orders
input string TradeSettings = "=== Trade Settings ===";
input double DistancePips = 20; // Distance from current price in Pips
input double LotSize = 0.1; // Volume in Lots
input double StopLoss = 30; // Stop Loss in Pips (0 = No SL)
input double TakeProfit = 60; // Take Profit in Pips (0 = No TP)
input int ExpirationMin= 60; // Order expiration in minutes (0 = No expiration)
input int MagicNumber = 123456; // Unique ID for this EA's orders
input int Slippage = 3; // Max slippage allowed
//--- Global Variables
bool ordersPlacedToday = false;
int lastDayChecked = 0;
double pPoint; // Adjusted point value for 3/5 digit brokers
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
// Adjust point value for 5-digit and 3-digit brokers
if(Digits == 5 || Digits == 3) pPoint = Point * 10;
else pPoint = Point;
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
// 1. Reset the flag if it is a new day
if(Day() != lastDayChecked)
{
ordersPlacedToday = false;
lastDayChecked = Day();
}
// 2. If orders are already placed today, stop processing
if(ordersPlacedToday) return;
// 3. Calculate Target Time and Trigger Time for TODAY
datetime now = TimeCurrent();
// Construct the string for the target time (YYYY.MM.DD HH:MI)
string dateStr = StringFormat("%d.%02d.%02d", Year(), Month(), Day());
string timeStr = StringFormat("%02d:%02d", TargetHour, TargetMinute);
datetime targetTime = StrToTime(dateStr + " " + timeStr);
// Calculate the trigger time (Target - MinutesBefore)
datetime triggerTime = targetTime - (MinutesBefore * 60);
// 4. Check if current time is within the execution window
// We check if 'now' is past the trigger time AND 'now' is not too late (e.g., passed the news event)
if(now >= triggerTime && now < targetTime)
{
PlaceStraddleOrders();
ordersPlacedToday = true; // Mark as done for the day
}
}
//+------------------------------------------------------------------+
//| Helper function to place the orders |
//+------------------------------------------------------------------+
void PlaceStraddleOrders()
{
double buyStopPrice = Ask + (DistancePips * pPoint);
double sellStopPrice = Bid - (DistancePips * pPoint);
// Normalize prices to prevent errors
buyStopPrice = NormalizeDouble(buyStopPrice, Digits);
sellStopPrice = NormalizeDouble(sellStopPrice, Digits);
// Calculate SL and TP for Buy Stop
double buySL = (StopLoss > 0) ? buyStopPrice - (StopLoss * pPoint) : 0;
double buyTP = (TakeProfit > 0) ? buyStopPrice + (TakeProfit * pPoint) : 0;
// Calculate SL and TP for Sell Stop
double sellSL = (StopLoss > 0) ? sellStopPrice + (StopLoss * pPoint) : 0;
double sellTP = (TakeProfit > 0) ? sellStopPrice - (TakeProfit * pPoint) : 0;
// Normalize SL/TP
buySL = NormalizeDouble(buySL, Digits);
buyTP = NormalizeDouble(buyTP, Digits);
sellSL = NormalizeDouble(sellSL, Digits);
sellTP = NormalizeDouble(sellTP, Digits);
// Calculate Expiration Time
datetime expireTime = 0;
if(ExpirationMin > 0) expireTime = TimeCurrent() + (ExpirationMin * 60);
// --- Send Buy Stop ---
int ticketBuy = OrderSend(Symbol(), OP_BUYSTOP, LotSize, buyStopPrice, Slippage, buySL, buyTP, "Straddle Buy", MagicNumber, expireTime, clrGreen);
if(ticketBuy < 0)
{
Print("Error placing Buy Stop: ", GetLastError());
}
else
{
Print("Buy Stop placed at: ", buyStopPrice);
}
// --- Send Sell Stop ---
int ticketSell = OrderSend(Symbol(), OP_SELLSTOP, LotSize, sellStopPrice, Slippage, sellSL, sellTP, "Straddle Sell", MagicNumber, expireTime, clrRed);
if(ticketSell < 0)
{
Print("Error placing Sell Stop: ", GetLastError());
}
else
{
Print("Sell Stop placed at: ", sellStopPrice);
}
}
//+------------------------------------------------------------------+
F4.F7 or click the "Compile" button. Ensure there are no errors in the "Errors" tab at the bottom.5.TimeCurrent() (Broker Server Time), not your local computer time. This is crucial for accurate trading. Note: You must check your broker's time zone offset.pPoint automatically adjusts calculations so that "20 pips" works correctly on both 4-digit and 5-digit brokers.ordersPlacedToday flag ensures that once the orders are placed, the bot won't try to place them again until the next day.ExpirationMin input allows the pending orders to automatically delete themselves if the price doesn't move enough to trigger them within the specified time (e.g., 60 minutes).Q: Why does the bot use TimeCurrent() instead of TimeLocal()?
A: TimeCurrent() returns the time of the last known quote from the broker's server. This is the time displayed in the Market Watch window. Using local computer time (TimeLocal()) is dangerous because it may not match the broker's candle closing times or news event schedules.
Q: What happens if I restart the terminal after the orders are placed?
A: The global variable ordersPlacedToday is stored in memory. If you restart the terminal, this variable resets to false. However, the logic checks if(now >= triggerTime && now < targetTime). If you restart the terminal after the target time has passed, the bot will not place duplicate orders because the time condition will fail.
Q: Can I use this on multiple currency pairs simultaneously?
A: Yes, but you must change the MagicNumber input for each chart. The Magic Number allows the EA to identify which orders belong to which instance of the strategy. If they share the same number, they might interfere with each other's management logic (though this specific code only places orders and doesn't manage them after placement).
Q: Why did I get "Error 130" in the Journal?
A: Error 130 is ERR_INVALID_STOPS. This usually happens if your DistancePips is too small (inside the broker's "Freeze Level") or if the Stop Loss calculation places the SL on the wrong side of the price. The provided code calculates SL correctly relative to the pending order price, so ensure your DistancePips is at least 5-10 pips.