mql5/Experts/Previous/Forecast_trading_strategy.mq5

588 lines
22 KiB
MQL5
Raw Permalink Normal View History

2025-07-20 16:41:20 +01:00
//+------------------------------------------------------------------+
//| Universal_Trading_EA.mq5 |
//| Copyright 2025, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2025, MetaQuotes Ltd."
#property link "https://www.mql5.com"
#property version "1.00"
#include <Trade\Trade.mqh>
//=== TRADING LEVELS ===
input group "=== TRADING LEVELS ==="
input double EntryBuyLevel = 1.3600; // Buy entry level
input double TargetLevel = 1.3641; // Target level for buys
input double SupportLevel = 1.3566; // Support/resistance level
input double SellTarget = 1.3521; // Target level for sells
//=== SCENARIO CONTROLS ===
input group "=== SCENARIO CONTROLS ==="
input bool EnableBuyScenario1 = true; // Enable Buy Scenario 1
input bool EnableBuyScenario2 = true; // Enable Buy Scenario 2
input bool EnableSellScenario1 = true; // Enable Sell Scenario 1
input bool EnableSellScenario2 = true; // Enable Sell Scenario 2
//=== REVERSAL TRADING ===
input group "=== REVERSAL TRADING ==="
input bool EnableAutoReversals = true; // Enable automatic reversals
input double BuyReversalPips = 35; // Expected pullback pips after buy target
input double SellReversalPips = 25; // Expected rebound pips after sell target
//=== MACD SETTINGS ===
input group "=== MACD SETTINGS ==="
input int MACD_Fast = 12; // MACD Fast EMA period
input int MACD_Slow = 26; // MACD Slow EMA period
input int MACD_Signal = 9; // MACD Signal period
input double MACD_OversoldThreshold = -0.0005; // MACD oversold threshold
input double MACD_OverboughtThreshold = 0.0005; // MACD overbought threshold
//=== ENTRY CONDITIONS ===
input group "=== ENTRY CONDITIONS ==="
input double EntryTolerancePips = 5; // Price tolerance for entry (pips)
input double LevelTestTolerancePips = 3; // Price tolerance for level tests (pips)
input double BreakoutTolerancePips = 2; // Price tolerance for breakouts (pips)
input int TestTimeoutHours = 4; // Hours between level tests
input int LevelResetPips = 20; // Pips away to reset test counters
//=== RISK MANAGEMENT ===
input group "=== RISK MANAGEMENT ==="
input double LotSize = 0.1; // Fixed lot size (0 = auto calculation)
input double RiskPercent = 2.0; // Risk per trade as % of account
input double MaxDailyLoss = 5.0; // Maximum daily loss %
input double MaxSpread = 3.0; // Maximum allowed spread in points
input double StopLossPips = 30; // Stop loss in pips (0 = based on levels)
//=== GENERAL SETTINGS ===
input group "=== GENERAL SETTINGS ==="
input int MagicNumber = 123456; // Magic number for orders
input string TradeComment = "Universal EA"; // Trade comment prefix
// Global variables
CTrade trade;
int macdHandle;
double macdMain[], macdSignal[];
int testCount_Support = 0;
int testCount_Entry = 0;
datetime lastTestTime_Support = 0;
datetime lastTestTime_Entry = 0;
bool inLongPosition = false;
bool inShortPosition = false;
double dailyStartBalance;
datetime dailyStartTime;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
// Validate inputs
if(!ValidateInputs())
return INIT_PARAMETERS_INCORRECT;
// Initialize MACD indicator
macdHandle = iMACD(_Symbol, PERIOD_CURRENT, MACD_Fast, MACD_Slow, MACD_Signal, PRICE_CLOSE);
if(macdHandle == INVALID_HANDLE)
{
Print("Error creating MACD indicator for ", _Symbol);
return INIT_FAILED;
}
// Set array properties
ArraySetAsSeries(macdMain, true);
ArraySetAsSeries(macdSignal, true);
// Set trade parameters
trade.SetExpertMagicNumber(MagicNumber);
trade.SetDeviationInPoints(10);
// Initialize daily tracking
dailyStartBalance = AccountInfoDouble(ACCOUNT_BALANCE);
dailyStartTime = TimeCurrent();
// Print configuration
PrintConfiguration();
Print("Universal Trading EA initialized successfully for ", _Symbol);
return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
//| Validate input parameters |
//+------------------------------------------------------------------+
bool ValidateInputs()
{
if(EntryBuyLevel <= 0 || TargetLevel <= 0 || SupportLevel <= 0 || SellTarget <= 0)
{
Print("Error: All price levels must be positive");
return false;
}
if(TargetLevel <= EntryBuyLevel)
{
Print("Error: Target level must be above entry buy level");
return false;
}
if(SupportLevel >= EntryBuyLevel)
{
Print("Error: Support level must be below entry buy level");
return false;
}
if(SellTarget >= SupportLevel)
{
Print("Error: Sell target must be below support level");
return false;
}
if(RiskPercent <= 0 || RiskPercent > 10)
{
Print("Error: Risk percent must be between 0 and 10");
return false;
}
return true;
}
//+------------------------------------------------------------------+
//| Print EA configuration |
//+------------------------------------------------------------------+
void PrintConfiguration()
{
Print("=== UNIVERSAL TRADING EA CONFIGURATION ===");
Print("Instrument: ", _Symbol);
Print("Entry Buy Level: ", EntryBuyLevel);
Print("Target Level: ", TargetLevel);
Print("Support Level: ", SupportLevel);
Print("Sell Target: ", SellTarget);
Print("Buy Reversal Pips: ", BuyReversalPips);
Print("Sell Reversal Pips: ", SellReversalPips);
Print("MACD Oversold: ", MACD_OversoldThreshold);
Print("MACD Overbought: ", MACD_OverboughtThreshold);
Print("Risk per Trade: ", RiskPercent, "%");
Print("=========================================");
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
IndicatorRelease(macdHandle);
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
// Check daily risk management
if(!CheckDailyRiskManagement())
return;
// Check spread
if(!CheckSpread())
return;
// Update MACD values
if(!UpdateMACDValues())
return;
// Update position status
UpdatePositionStatus();
// Check trading scenarios
if(EnableBuyScenario1)
CheckBuyScenario1();
if(EnableBuyScenario2)
CheckBuyScenario2();
if(EnableSellScenario1)
CheckSellScenario1();
if(EnableSellScenario2)
CheckSellScenario2();
// Check exit conditions
CheckExitConditions();
}
//+------------------------------------------------------------------+
//| Check daily risk management |
//+------------------------------------------------------------------+
bool CheckDailyRiskManagement()
{
// Reset daily tracking at new day
MqlDateTime timeStruct;
TimeToStruct(TimeCurrent(), timeStruct);
MqlDateTime startStruct;
TimeToStruct(dailyStartTime, startStruct);
if(timeStruct.day != startStruct.day)
{
dailyStartBalance = AccountInfoDouble(ACCOUNT_BALANCE);
dailyStartTime = TimeCurrent();
Print("New trading day started. Daily balance reset for ", _Symbol);
}
// Check if daily loss limit exceeded
double currentBalance = AccountInfoDouble(ACCOUNT_BALANCE);
double dailyLoss = (dailyStartBalance - currentBalance) / dailyStartBalance * 100;
if(dailyLoss >= MaxDailyLoss)
{
Print("Daily loss limit exceeded: ", dailyLoss, "%. Trading stopped for ", _Symbol);
return false;
}
return true;
}
//+------------------------------------------------------------------+
//| Check spread |
//+------------------------------------------------------------------+
bool CheckSpread()
{
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
double spread = (ask - bid) / point;
return spread <= MaxSpread;
}
//+------------------------------------------------------------------+
//| Calculate lot size based on risk management |
//+------------------------------------------------------------------+
double CalculateLotSize(double entryPrice, double stopLoss)
{
// Use fixed lot size if specified
if(LotSize > 0)
return LotSize;
double balance = AccountInfoDouble(ACCOUNT_BALANCE);
double riskAmount = balance * RiskPercent / 100;
double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
double tickValue = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE);
double minLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
double maxLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);
double lotStep = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);
double stopLossPoints = MathAbs(entryPrice - stopLoss) / point;
if(stopLossPoints == 0) return minLot;
double lotSize = riskAmount / (stopLossPoints * tickValue);
// Round to nearest lot step
lotSize = MathFloor(lotSize / lotStep) * lotStep;
// Apply limits
if(lotSize < minLot) lotSize = minLot;
if(lotSize > maxLot) lotSize = maxLot;
return lotSize;
}
//+------------------------------------------------------------------+
//| Calculate stop loss level |
//+------------------------------------------------------------------+
double CalculateStopLoss(bool isBuy, double entryPrice)
{
double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
if(StopLossPips > 0)
{
// Use fixed stop loss pips
if(isBuy)
return entryPrice - StopLossPips * point;
else
return entryPrice + StopLossPips * point;
}
else
{
// Use level-based stop loss
if(isBuy)
return SupportLevel - 5 * point;
else
return EntryBuyLevel + 5 * point;
}
}
//+------------------------------------------------------------------+
//| Update MACD indicator values |
//+------------------------------------------------------------------+
bool UpdateMACDValues()
{
if(CopyBuffer(macdHandle, 0, 0, 3, macdMain) < 0 ||
CopyBuffer(macdHandle, 1, 0, 3, macdSignal) < 0)
{
Print("Error copying MACD buffers for ", _Symbol);
return false;
}
return true;
}
//+------------------------------------------------------------------+
//| Update position status |
//+------------------------------------------------------------------+
void UpdatePositionStatus()
{
inLongPosition = false;
inShortPosition = false;
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
if(PositionGetSymbol(i) == _Symbol && PositionGetInteger(POSITION_MAGIC) == MagicNumber)
{
if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
inLongPosition = true;
else if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL)
inShortPosition = true;
}
}
}
//+------------------------------------------------------------------+
//| Check Buy Scenario 1: Buy at entry level with MACD above zero |
//+------------------------------------------------------------------+
void CheckBuyScenario1()
{
if(inLongPosition)
return;
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
// Check if price is near entry level
if(MathAbs(ask - EntryBuyLevel) <= EntryTolerancePips * point)
{
// Check MACD conditions: above zero and rising (starting to rise)
if(macdMain[0] > 0 && macdMain[0] > macdMain[1])
{
double stopLoss = CalculateStopLoss(true, ask);
double lotSize = CalculateLotSize(ask, stopLoss);
// Execute buy order
if(trade.Buy(lotSize, _Symbol, ask, stopLoss, TargetLevel,
TradeComment + " - Buy Scenario 1"))
{
Print("Buy Scenario 1 executed for ", _Symbol, " at ", ask, " Lot: ", lotSize,
" MACD: ", macdMain[0], " (rising from ", macdMain[1], ")");
}
}
}
}
//+------------------------------------------------------------------+
//| Check Buy Scenario 2: Two tests of support with MACD oversold |
//+------------------------------------------------------------------+
void CheckBuyScenario2()
{
if(inLongPosition)
return;
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
// Check if price is testing support level
if(MathAbs(bid - SupportLevel) <= LevelTestTolerancePips * point)
{
// Check if this is a new test
if(TimeCurrent() - lastTestTime_Support > TestTimeoutHours * 3600)
{
testCount_Support++;
lastTestTime_Support = TimeCurrent();
Print("Test #", testCount_Support, " of support level detected for ", _Symbol);
// If second test and MACD is oversold
if(testCount_Support >= 2 && macdMain[0] < MACD_OversoldThreshold)
{
double stopLoss = CalculateStopLoss(true, ask);
double lotSize = CalculateLotSize(ask, stopLoss);
// Execute buy order
if(trade.Buy(lotSize, _Symbol, ask, stopLoss, TargetLevel,
TradeComment + " - Buy Scenario 2"))
{
Print("Buy Scenario 2 executed for ", _Symbol, " at ", ask, " Lot: ", lotSize,
" MACD oversold: ", macdMain[0], " (threshold: ", MACD_OversoldThreshold, ")");
testCount_Support = 0; // Reset counter
}
}
}
}
// Reset counter if price moves away from level
if(MathAbs(bid - SupportLevel) > LevelResetPips * point)
{
testCount_Support = 0;
}
}
//+------------------------------------------------------------------+
//| Check Sell Scenario 1: Sell below support with MACD below zero |
//+------------------------------------------------------------------+
void CheckSellScenario1()
{
if(inShortPosition)
return;
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
// Check if price breaks below support level
if(bid < SupportLevel - BreakoutTolerancePips * point)
{
// Check MACD conditions: below zero and declining (starting to decline)
if(macdMain[0] < 0 && macdMain[0] < macdMain[1])
{
double stopLoss = CalculateStopLoss(false, bid);
double lotSize = CalculateLotSize(bid, stopLoss);
// Execute sell order
if(trade.Sell(lotSize, _Symbol, bid, stopLoss, SellTarget,
TradeComment + " - Sell Scenario 1"))
{
Print("Sell Scenario 1 executed for ", _Symbol, " at ", bid, " Lot: ", lotSize,
" MACD: ", macdMain[0], " (declining from ", macdMain[1], ")");
}
}
}
}
//+------------------------------------------------------------------+
//| Check Sell Scenario 2: Two tests of entry with MACD overbought |
//+------------------------------------------------------------------+
void CheckSellScenario2()
{
if(inShortPosition)
return;
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
// Check if price is testing entry level
if(MathAbs(ask - EntryBuyLevel) <= LevelTestTolerancePips * point)
{
// Check if this is a new test
if(TimeCurrent() - lastTestTime_Entry > TestTimeoutHours * 3600)
{
testCount_Entry++;
lastTestTime_Entry = TimeCurrent();
Print("Test #", testCount_Entry, " of entry level detected for ", _Symbol);
// If second test and MACD is overbought
if(testCount_Entry >= 2 && macdMain[0] > MACD_OverboughtThreshold)
{
double stopLoss = CalculateStopLoss(false, bid);
double lotSize = CalculateLotSize(bid, stopLoss);
// Execute sell order
if(trade.Sell(lotSize, _Symbol, bid, stopLoss, SellTarget,
TradeComment + " - Sell Scenario 2"))
{
Print("Sell Scenario 2 executed for ", _Symbol, " at ", bid, " Lot: ", lotSize,
" MACD overbought: ", macdMain[0], " (threshold: ", MACD_OverboughtThreshold, ")");
testCount_Entry = 0; // Reset counter
}
}
}
}
// Reset counter if price moves away from level
if(MathAbs(ask - EntryBuyLevel) > LevelResetPips * point)
{
testCount_Entry = 0;
}
}
//+------------------------------------------------------------------+
//| Check exit conditions and automatic reversals |
//+------------------------------------------------------------------+
void CheckExitConditions()
{
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
if(PositionGetSymbol(i) == _Symbol && PositionGetInteger(POSITION_MAGIC) == MagicNumber)
{
ulong ticket = PositionGetInteger(POSITION_TICKET);
double currentPrice = (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) ? bid : ask;
// Check long position exit at target
if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
{
if(currentPrice >= TargetLevel)
{
if(trade.PositionClose(ticket))
{
Print("Long position closed at target for ", _Symbol, ": ", currentPrice);
// Open automatic reversal if enabled
if(EnableAutoReversals && BuyReversalPips > 0)
{
double reversalTarget = TargetLevel - BuyReversalPips * point;
double stopLoss = TargetLevel + 15 * point;
double lotSize = CalculateLotSize(bid, stopLoss);
if(trade.Sell(lotSize, _Symbol, bid, stopLoss, reversalTarget,
TradeComment + " - Auto Reversal Short"))
{
Print("Auto reversal short opened for ", _Symbol,
" expecting ", BuyReversalPips, " pip pullback");
}
}
}
}
}
// Check short position exit at target
else if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL)
{
if(currentPrice <= SellTarget)
{
if(trade.PositionClose(ticket))
{
Print("Short position closed at target for ", _Symbol, ": ", currentPrice);
// Open automatic reversal if enabled
if(EnableAutoReversals && SellReversalPips > 0)
{
double reversalTarget = SellTarget + SellReversalPips * point;
double stopLoss = SellTarget - 15 * point;
double lotSize = CalculateLotSize(ask, stopLoss);
if(trade.Buy(lotSize, _Symbol, ask, stopLoss, reversalTarget,
TradeComment + " - Auto Reversal Long"))
{
Print("Auto reversal long opened for ", _Symbol,
" expecting ", SellReversalPips, " pip rebound");
}
}
}
}
}
}
}
}
//+------------------------------------------------------------------+
//| Trade transaction function |
//+------------------------------------------------------------------+
void OnTradeTransaction(const MqlTradeTransaction& trans,
const MqlTradeRequest& request,
const MqlTradeResult& result)
{
if(trans.type == TRADE_TRANSACTION_DEAL_ADD)
{
Print("Trade executed: ", trans.symbol, " Volume: ", trans.volume,
" Price: ", trans.price, " Type: ",
(trans.deal_type == DEAL_TYPE_BUY ? "BUY" : "SELL"));
}
}