//+------------------------------------------------------------------+ //| OrdersEA_Smart_Grid.mq4 | //| Copyright 2024, Garfield Heron | //| https://fetcherpay.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2024, Garfield Heron" #property link "https://fetcherpay.com" #property version "3.0" #property strict #include #define VERSION "Version 3.0 Smart Grid" #define MAX_TRADES 600 #define MAX_LOG_TRADES 1200 //--- Input Parameters extern string Email= "garfield@fetcherpay.com"; extern int MagicNum= 333; //--- Smart Grid Settings extern string GridSettings = "=== Smart Grid Settings ==="; extern bool UseAutoPivots = true; // Auto-calculate pivot points extern double HIGH= 0; // Manual HIGH (if UseAutoPivots=false) extern double LOW= 0; // Manual LOW (if UseAutoPivots=false) extern double Entry= 10; // Grid spacing in pips extern double TP= 15; // Take profit per level extern double Lots=0.01; // Lot size per trade extern int MaxLevels = 10; // Max grid levels per side //--- Range Filter Settings extern string FilterSettings = "=== Range Filters ==="; extern bool UseRSIFilter = true; // Enable RSI filter extern int RSIPeriod = 14; // RSI period extern int RSILower = 35; // RSI lower bound (buy zone) extern int RSIUpper = 65; // RSI upper bound (sell zone) extern bool UseADXFilter = true; // Enable ADX filter extern int ADXPeriod = 14; // ADX period extern double ADXMax = 25; // Max ADX for ranging (below=trending) extern bool UseATRFilter = true; // Enable ATR filter extern int ATRPeriod = 14; // ATR period extern double ATRMultiplier = 1.5; // ATR multiplier for range width //--- Risk Management extern string RiskSettings = "=== Risk Management ==="; extern int StopLoss=0; extern int TRADE_RANGE= 50; extern double LongLimit= 0; extern double ShortLimit= 0; extern string GetOut= "N"; extern string OpenNewTrades="Y"; extern bool Opposite= false; extern int TakeProfitLevelPercent= 50; extern int TakeProfitLevelDollarAmount= 2000; extern bool Restart= true; extern int EquityFactorPercent= 0; extern int LotsFactorPercent= 0; extern int BaseEquity= 10000; extern bool Master= false; extern bool DiagnosticModeOn= false; //--- Indicator Handles int RSICurrent = 0; int ADXHandle = 0; int ATRHandle = 0; //--- Pivot Point Variables double PivotP = 0; double PivotR1 = 0; double PivotR2 = 0; double PivotS1 = 0; double PivotS2 = 0; //--- Original OrdersEA Variables int initialCycleEquity= 0; int longs, shorts; int longsTicket[MAX_TRADES]; int shortsTicket[MAX_TRADES]; int logTickets[MAX_LOG_TRADES]; int logTicketsTime[MAX_LOG_TRADES]; int logTicketsCounter; int Levels; double price[MAX_TRADES]; int stoplevel; bool bFirstTick= false; int logId; bool bEnableLongs; bool bEnableShorts; double tickValue; int MaximalLoss; int lastTicketSentOpen= 0, lastTicketSentClose= 0; double longAvgPrice= 0, longAvgLots= 0; double shortAvgPrice= 0, shortAvgLots= 0; double longProfit= 0; double shortProfit= 0; bool bConfirmed; bool bOpposite; bool bInit= false; int TakeProfit=0; bool AboveHigh; bool BelowLow; int tradeLogId; double closeOnProfit; bool bGetOutOK, bOpenNewTradesOK; int initEquity; int lotDigits; bool bWithdrawMailSent= false; bool bGetOutHandled; int PingTimeMinutes= 240; bool bAccess; bool bValidSettings; string errMsg; datetime PivotCalculationTime = 0; bool TradeExecutedToday = false; bool R1HitToday = false; bool S1HitToday = false; double P, R1, R2, S1, S2; bool PivotsCalculated = false; //+------------------------------------------------------------------+ //| Calculate Pivot Points | //+------------------------------------------------------------------+ void CalculatePivotPoints() { // Get yesterday's data datetime yesterday = Time[0] - PeriodSeconds(PERIOD_D1); int shift = iBarShift(NULL, PERIOD_D1, yesterday); double prevHigh = iHigh(NULL, PERIOD_D1, shift); double prevLow = iLow(NULL, PERIOD_D1, shift); double prevClose = iClose(NULL, PERIOD_D1, shift); // Standard Pivot Formula PivotP = (prevHigh + prevLow + prevClose) / 3.0; PivotR1 = (2.0 * PivotP) - prevLow; PivotS1 = (2.0 * PivotP) - prevHigh; PivotR2 = PivotP + (prevHigh - prevLow); PivotS2 = PivotP - (prevHigh - prevLow); // Set HIGH/LOW if auto-pivots enabled if(UseAutoPivots) { // Use R1/S1 for narrow range, R2/S2 for wider double atr = iATR(NULL, 0, ATRPeriod, 0); if(UseATRFilter && atr > 0) { // ATR-based adaptive range HIGH = NormalizeDouble(PivotP + (atr * ATRMultiplier), Digits); LOW = NormalizeDouble(PivotP - (atr * ATRMultiplier), Digits); } else { // Standard pivot-based range HIGH = PivotR1; LOW = PivotS1; } } Print("Pivot Calculated: P=", PivotP, " R1=", PivotR1, " S1=", PivotS1); Print("Grid Range: HIGH=", HIGH, " LOW=", LOW); } //+------------------------------------------------------------------+ //| Check if Market is Ranging (Good for Grid) | //+------------------------------------------------------------------+ bool IsRangingMarket() { bool isRanging = true; //--- RSI Filter if(UseRSIFilter) { double rsi = iRSI(NULL, 0, RSIPeriod, PRICE_CLOSE, 0); if(rsi < RSILower || rsi > RSIUpper) { Print("RSI Filter: Market at extremes (RSI=", rsi, "), skipping grid"); isRanging = false; } } //--- ADX Filter if(UseADXFilter && isRanging) { double adx = iADX(NULL, 0, ADXPeriod, PRICE_CLOSE, MODE_MAIN, 0); if(adx > ADXMax) { Print("ADX Filter: Market trending (ADX=", adx, "), skipping grid"); isRanging = false; } } //--- Price Position Filter double currentPrice = Bid; if(currentPrice > HIGH || currentPrice < LOW) { Print("Price outside grid range, waiting for re-entry"); isRanging = false; } return isRanging; } //+------------------------------------------------------------------+ //| Get Grid Lot Size (Original CalcLots) | //+------------------------------------------------------------------+ double CalcLots() { double tmp= (AccountEquity()-initEquity); double a= EquityFactorPercent; double b= LotsFactorPercent; double lots; if(0==EquityFactorPercent || 0==LotsFactorPercent) lots= Lots; else { a=initEquity*a/100; b=b/100; if(tmp>0) tmp= MathPow(1+b,(tmp/a)); else if(tmp<0) tmp= MathPow(1-b,MathAbs(tmp/a)); else tmp= 1; lots= NormalizeDouble(Lots*tmp,lotDigits); if(lots=0) { FileWrite(logId, TimeToStr(TimeCurrent(),TIME_DATE|TIME_SECONDS) + ": " + st); } } //+------------------------------------------------------------------+ //| Expert initialization | //+------------------------------------------------------------------+ int OnInit() { // Initialize indicators if(UseRSIFilter) RSICurrent = iRSI(NULL, 0, RSIPeriod, PRICE_CLOSE); if(UseADXFilter) ADXHandle = iADX(NULL, 0, ADXPeriod); if(UseATRFilter) ATRHandle = iATR(NULL, 0, ATRPeriod); // Calculate initial pivot points CalculatePivotPoints(); // Rest of original init PivotsCalculated = false; stoplevel = MarketInfo(Symbol(), MODE_STOPLEVEL) * Point; if(stoplevel <= 0) stoplevel = 0; Print("Smart Grid EA Initialized"); Print("AutoPivots: ", UseAutoPivots); Print("RSI Filter: ", UseRSIFilter, " (", RSILower, "-", RSIUpper, ")"); Print("ADX Filter: ", UseADXFilter, " (<", ADXMax, ")"); return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { // Cleanup indicators if(RSICurrent != 0) IndicatorRelease(RSICurrent); if(ADXHandle != 0) IndicatorRelease(ADXHandle); if(ATRHandle != 0) IndicatorRelease(ATRHandle); if(logId>=0) FileClose(logId); Print("Smart Grid EA Deinitialized"); } //+------------------------------------------------------------------+ //| Expert tick function - Smart Grid Logic | //+------------------------------------------------------------------+ void OnTick() { // Recalculate pivots at new day datetime TimeNow = TimeCurrent(); if(TimeHour(TimeNow) == 0 && TimeMinute(TimeNow) < 5) { CalculatePivotPoints(); } // Check if we should trade (ranging market?) if(!IsRangingMarket()) { // Close existing grid if market starts trending if(GetOut == "Y" || GetOut == "y") { // CloseAllTrades logic here } return; } // Original OrdersEA grid logic would go here // (Simplified for this template) static datetime lastBarTime = 0; datetime currentBarTime = iTime(NULL, 0, 0); if(currentBarTime != lastBarTime) { lastBarTime = currentBarTime; // Place grid orders logic // This is where you'd integrate the full OrdersEA order placement Print("Smart Grid: RSI=", iRSI(NULL,0,RSIPeriod,PRICE_CLOSE,0), " ADX=", iADX(NULL,0,ADXPeriod,PRICE_CLOSE,MODE_MAIN,0), " Range: ", LOW, " - ", HIGH); } } //+------------------------------------------------------------------+ //| Place Buy Order at Level | //+------------------------------------------------------------------+ bool PlaceBuyLevel(double priceLevel, int level) { if(level >= MaxLevels) return false; double lots = CalcLots(); double sl = (StopLoss > 0) ? priceLevel - (StopLoss * Point) : 0; double tp = priceLevel + (TP * Point); int ticket = OrderSend(Symbol(), OP_BUYSTOP, lots, priceLevel, 3, sl, tp, "Smart Grid Buy " + IntegerToString(level), MagicNum, 0, clrBlue); if(ticket > 0) { Print("Buy Level ", level, " placed at ", priceLevel); return true; } else { Print("Error placing buy level: ", GetLastError()); return false; } } //+------------------------------------------------------------------+ //| Place Sell Order at Level | //+------------------------------------------------------------------+ bool PlaceSellLevel(double priceLevel, int level) { if(level >= MaxLevels) return false; double lots = CalcLots(); double sl = (StopLoss > 0) ? priceLevel + (StopLoss * Point) : 0; double tp = priceLevel - (TP * Point); int ticket = OrderSend(Symbol(), OP_SELLSTOP, lots, priceLevel, 3, sl, tp, "Smart Grid Sell " + IntegerToString(level), MagicNum, 0, clrRed); if(ticket > 0) { Print("Sell Level ", level, " placed at ", priceLevel); return true; } else { Print("Error placing sell level: ", GetLastError()); return false; } }