mql5/Experts/Downloads/FetchNews.mq5
Princeec13 ecd22e8ddd
2025-08-10 17:43:21 -04:00

169 lines
14 KiB
MQL5

//+------------------------------------------------------------------+
//| NewsEA.mq5 |
//| Copyright 2023, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Müller Peter"
#property link "https://www.mql5.com/en/users/mullerp04/seller"
#property version "1.00"
#include <Trade\Trade.mqh> // Include the standard trade library for trading operations
// Define an enum to specify what the expert advisor (EA) should do
enum e_Type {
Trading = 0, // Place trades based on news events
Alerting = 1 // Only alert about important news events
};
// Input parameters for the EA
input e_Type Type = Alerting; // The mode of operation (Trading or Alerting)
input int Magic = 1125021; // Magic number to identify EA orders (relevant in trading mode)
input int TPPoints = 150; // Take profit in points (relevant in trading mode)
input int SLPoints = 150; // Stop loss in points (relevant in trading mode)
input double Volume = 0.1; // Volume of orders (relevant in trading mode)
//+------------------------------------------------------------------+
//| Initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
// Declare necessary variables
MqlCalendarValue CalendarValues[]; // Array to hold calendar events
MqlCalendarEvent CalendarEvent; // Struct to hold specific event details
MqlCalendarCountry CalendarCountry; // Struct to hold country details
// Static variables to maintain state between ticks
static datetime LastRequest = TimeTradeServer(); // Last time news was fetched
static CTrade trade; // Trade object for trading operations
trade.SetExpertMagicNumber(Magic); // Set the magic number for the EA's trades
static datetime Expiry = 0; // Expiry time for pending orders
// Retrieve calendar events from the last 50 seconds to the next 50 seconds
CalendarValueHistory(CalendarValues, LastRequest, TimeTradeServer() + 50);
// If new events are found, update the last request time
if(ArraySize(CalendarValues) != 0)
LastRequest = TimeTradeServer() + 50;
// Loop through all retrieved events
for(int i = 0; i < ArraySize(CalendarValues); i++)
{
// Fetch detailed information about the event and the country
CalendarEventById(CalendarValues[i].event_id, CalendarEvent);
CalendarCountryById(CalendarEvent.country_id, CalendarCountry);
// Get the currency related to the event
string currency = CalendarCountry.currency;
// Check if the event is relevant to the current symbol
if(currency == SymbolInfoString(_Symbol, SYMBOL_CURRENCY_BASE) ||
currency == SymbolInfoString(_Symbol, SYMBOL_CURRENCY_PROFIT))
{
// If the event is high importance and the mode is Alerting, send an alert
if(CalendarEvent.importance == CALENDAR_IMPORTANCE_MODERATE && Type == Alerting)
{
Alert("Upcoming important news event: " + CalendarEvent.name +
" at " + TimeToString(CalendarValues[i].time));
}
// If the event relates to inflation or interest rate changes, place pending orders
if((StringContains(CalendarEvent.name, "cpi") ||
StringContains(CalendarEvent.name, "ppi") ||
StringContains(CalendarEvent.name, "interest rate decision")) && Type == Trading)
{
// Skip if there are already active pending orders
if(Expiry != 0)
continue;
// Retrieve current market prices
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
// Set expiry time for pending orders
Expiry = TimeTradeServer() + 500;
// Place buy stop and sell stop orders around the current price
trade.BuyStop(Volume, ask + TPPoints * _Point, NULL,
ask + TPPoints * _Point - SLPoints * _Point,
ask + 2 * TPPoints * _Point);
trade.SellStop(Volume, bid - TPPoints * _Point, NULL,
bid - TPPoints * _Point + SLPoints * _Point,
bid - 2 * TPPoints * _Point);
}
}
}
// Delete pending orders if they have expired
if(TimeTradeServer() > Expiry && Expiry != 0)
{
Expiry = 0;
DeletePending();
}
}
//+------------------------------------------------------------------+
//| Function to delete pending orders |
//+------------------------------------------------------------------+
void DeletePending()
{
COrderInfo ordinfo; // Order information object
CTrade trade; // Trade object
// Loop through all orders and delete those with the EA's magic number
for(int i = OrdersTotal() - 1; i >= 0; i--)
{
ordinfo.SelectByIndex(i);
if(ordinfo.Magic() == Magic)
trade.OrderDelete(ordinfo.Ticket());
}
}
//+------------------------------------------------------------------+
//| Helper function to check if a string contains another string |
//+------------------------------------------------------------------+
bool StringContains(string base, string containing, bool Cased = false)
{
// If case-insensitive, convert both strings to lowercase
if(!Cased)
{
StringToLower(base);
StringToLower(containing);
}
int ct = 0; // Counter to track matching characters
// Loop through the base string
for(unsigned i = 0; i < base.Length(); i++)
{
if(base.GetChar(i) == containing.GetChar(ct))
ct++; // Increment counter if characters match
else
ct = 0; // Reset counter if characters don't match
// If the entire containing string matches, return true
if(ct == containing.Length() - 1)
return true;
// If remaining base string is shorter than containing string, return false
if(base.Length() - i < containing.Length() && !ct)
return false;
}
return false; // Return false if no match is found
}