//+------------------------------------------------------------------+ //| NewsTrader.mq5| //| Generated by ChatGPT | //+------------------------------------------------------------------+ #include CTrade trade; // Input parameters input string NewsCurrency = "USD"; // Relevant currency for the news event input ENUM_ORDER_TYPE EntryType = ORDER_TYPE_BUY_STOP; // Order type input bool TrailStopOrder = true; // Enable or disable trailing stop orders input int MinutesBeforeNews = 30; // Minutes before news to identify signal candle input double PendingDistancePips = 10.0; // Distance in pips to place pending orders input double LimitStopTrailDistancePips = 2.0;// Trailing stop distance in pips input bool PendingOco = true; // Enable or disable OCO pending orders input int PendingExpiryMinutes = 10; // Expiry time for pending orders in minutes input double MaxSpreadMarketOrders = 0.0; // Maximum allowable spread for market orders input int LotSizeMethod = 1; // Method for calculating lot size input double LotSizeFixed = 0.1; // Fixed lot size input double RiskPercent = 1.0; // Risk percentage of account balance per trade input double StopLossPips = 15.0; // Stop loss in pips input double TakeProfitPips = 30.0; // Take profit in pips input double RiskReward = 3.0; // Risk to reward ratio input double WhenXPercentInProfit = 0; // Percentage of profit to trigger an action input double ThenLockInXPercent = 0; // Percentage of profit to lock in input int ADRPeriod = 14; // ADR calculation period struct NewsEvent { string Id; datetime Start; string Name; string Impact; string Currency; bool Alerted; // Field to mark if the event has been alerted }; // Example array of news events NewsEvent news_events[] = { {"e28b0560-06f6-47b3-b36b-7a7e24a88a13", D'2024.05.15 12:41', "Employment Change (QoQ)", "MEDIUM", "EUR", false}, {"e4d89748-0bea-46e0-8f91-893aad1f9094", D'2024.05.15 12:42', "Employment Change (YoY)", "LOW", "EUR", false}, {"0c0d5b42-6543-4f60-b56d-438f3407d3e9", D'2024.05.15 12:43', "Gross Domestic Product s.a. (QoQ)", "HIGH", "EUR", false}, {"6ae481f5-9e2f-47d7-8383-cf446583c401", D'2024.05.15 12:44', "Gross Domestic Product s.a. (YoY)", "HIGH", "EUR", false}, {"9f4602cb-4f5d-4d05-8ef7-a788408b0342", D'2024.05.15 12:45', "Industrial Production s.a. (MoM)", "MEDIUM", "EUR", false}, // Add more events as needed }; // Function to filter news by currency and time period void FilterNews(string currency, datetime time, NewsEvent &result) { for (int i = 0; i < ArraySize(news_events); i++) { if (news_events[i].Currency == currency && news_events[i].Start > time) { result = news_events[i]; break; } } } // Function prototypes double CalculateLotSize(); void PlacePendingOrders(double price, datetime newsTime); void ManageTrailingStop(); double CalculateADR(int period); bool IsBelowADRThreshold(double threshold); //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { // Initialization code EventSetTimer(60); // Set timer to check every minute return (INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { // Deinitialization code EventKillTimer(); } //+------------------------------------------------------------------+ //| Expert timer function | //+------------------------------------------------------------------+ void OnTimer() { // Filter news events NewsEvent nextNewsEvent; FilterNews(NewsCurrency, TimeCurrent(), nextNewsEvent); // Check for news events and place pending orders if conditions are met if (nextNewsEvent.Start > 0 && !nextNewsEvent.Alerted) { datetime signalCandleTime = nextNewsEvent.Start - MinutesBeforeNews * 60; if (TimeCurrent() >= signalCandleTime && TimeCurrent() < nextNewsEvent.Start) { if (IsBelowADRThreshold(0.3)) { double signalPrice = iClose(Symbol(), PERIOD_M1, iBarShift(Symbol(), PERIOD_M1, signalCandleTime)); PlacePendingOrders(signalPrice, nextNewsEvent.Start); nextNewsEvent.Alerted = true; // Mark as alerted } } } } //+------------------------------------------------------------------+ //| Calculate lot size | //+------------------------------------------------------------------+ double CalculateLotSize() { double lotSize = LotSizeFixed; if (LotSizeMethod == 1) { double riskAmount = AccountBalance() * (RiskPercent / 100.0); double pipValue = SymbolInfoDouble(Symbol(), SYMBOL_TRADE_TICK_VALUE); lotSize = riskAmount / (StopLossPips * pipValue / SymbolInfoDouble(Symbol(), SYMBOL_POINT)); } return (lotSize); } //+------------------------------------------------------------------+ //| Place pending orders | //+------------------------------------------------------------------+ void PlacePendingOrders(double price, datetime newsTime) { double lotSize = CalculateLotSize(); double buyStopPrice = price + PendingDistancePips * SymbolInfoDouble(Symbol(), SYMBOL_POINT); double sellStopPrice = price - PendingDistancePips * SymbolInfoDouble(Symbol(), SYMBOL_POINT); double sl = StopLossPips * SymbolInfoDouble(Symbol(), SYMBOL_POINT); double tp = TakeProfitPips * SymbolInfoDouble(Symbol(), SYMBOL_POINT); datetime expiryTime = newsTime + PendingExpiryMinutes * 60; trade.SetExpertMagicNumber(123456); // Place Buy Stop Order if (EntryType == ORDER_TYPE_BUY_STOP || EntryType == ORDER_TYPE_SELL_STOP) { if (EntryType == ORDER_TYPE_BUY_STOP) { trade.BuyStop(lotSize, buyStopPrice, Symbol(), sl, tp, 0, "Buy Stop Order", expiryTime); } else if (EntryType == ORDER_TYPE_SELL_STOP) { trade.SellStop(lotSize, sellStopPrice, Symbol(), sl, tp, 0, "Sell Stop Order", expiryTime); } } if (PendingOco) { trade.SellLimit(lotSize, sellStopPrice, Symbol(), sl, tp, 0, "Sell Limit Order", expiryTime); trade.BuyLimit(lotSize, buyStopPrice, Symbol(), sl, tp, 0, "Buy Limit Order", expiryTime); } } //+------------------------------------------------------------------+ //| Manage trailing stop | //+------------------------------------------------------------------+ void ManageTrailingStop() { if (TrailStopOrder) { // Manage trailing stop for open positions for (int i = PositionsTotal() - 1; i >= 0; i--) { ulong ticket = PositionGetTicket(i); if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) { double newSl = PositionGetDouble(POSITION_PRICE_OPEN) + LimitStopTrailDistancePips * SymbolInfoDouble(Symbol(), SYMBOL_POINT); if (PositionGetDouble(POSITION_SL) < newSl) { trade.PositionModify(ticket, newSl, PositionGetDouble(POSITION_TP)); } } if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL) { double newSl = PositionGetDouble(POSITION_PRICE_OPEN) - LimitStopTrailDistancePips * SymbolInfoDouble(Symbol(), SYMBOL_POINT); if (PositionGetDouble(POSITION_SL) > newSl) { trade.PositionModify(ticket, newSl, PositionGetDouble(POSITION_TP)); } } } } } //+------------------------------------------------------------------+ //| Calculate ADR | //+------------------------------------------------------------------+ double CalculateADR(int period) { double adr = 0.0; for (int i = 1; i <= period; i++) { adr += iHigh(NULL, PERIOD_D1, i) - iLow(NULL, PERIOD_D1, i); } return (adr / period); } //+------------------------------------------------------------------+ //| Check if the current day's movement is below ADR threshold | //+------------------------------------------------------------------+ bool IsBelowADRThreshold(double threshold) { double adr = CalculateADR(ADRPeriod); double currentRange = iHigh(NULL, PERIOD_D1, 0) - iLow(NULL, PERIOD_D1, 0); return (currentRange < adr * threshold); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { ManageTrailingStop(); }