// ★★★ EA_SingleLogic_LongOnly ★★★ //--------------------------------------------- // (1) Input parameters //--------------------------------------------- // --- Parameters for Magic_A input double SARStep = 0.001; // SAR acceleration factor increment input double SARMaxStep = 0.2; // Maximum SAR acceleration factor input double TPPips = 90; // Take Profit in pips input double SLPips = 70; // Stop Loss in pips // --- Other settings input double MaxSpreadPips = 3.0; // Maximum allowed spread (pips) input int SlippagePips = 3; // Allowed slippage (pips) input double LotSize = 0.1; // Fixed lot size input int MaxOpenBuyPositions = 1; // Maximum number of open BUY positions //--------------------------------------------- // (2) Magic number //--------------------------------------------- input int Magic_A = 12345; //--------------------------------------------- // (3) Internal state variables //--------------------------------------------- datetime prevTime_A = 0; //--------------------------------------------- // (4) ENUM: Exit / Entry signals //--------------------------------------------- enum SignalType { NO_SIGNAL = 0, BUY_ENTRY, BUY_EXIT }; //--------------------------------------------- // (6) New bar detection //--------------------------------------------- bool IsNewBar(int timeframe, datetime &lastBarTime) { datetime currentBar = iTime(Symbol(), timeframe, 0); if (currentBar != lastBarTime) { lastBarTime = currentBar; return true; } return false; } //--------------------------------------------- // (7) Pip size calculation //--------------------------------------------- double Pip() { return (Digits == 5 || Digits == 3) ? Point * 10 : Point; } //--------------------------------------------- // Convert pips to points (for slippage) int PipToPoint(double pips) { return (int)MathRound(pips * Pip() / Point); } //--------------------------------------------- // (11) Count open BUY orders for this EA //--------------------------------------------- int CountOrdersByTypeThisEA(int type) { int count = 0; for (int i = OrdersTotal() - 1; i >= 0; i--) { if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) { if (OrderSymbol() == Symbol() && OrderMagicNumber() == Magic_A && OrderType() == type) { count++; } } } return count; } //--------------------------------------------- // (12) Check if a new BUY order can be placed //--------------------------------------------- bool CanPlaceNewBuy() { return CountOrdersByTypeThisEA(OP_BUY) < MaxOpenBuyPositions; } //--------------------------------------------- // (14) Exit signal logic //--------------------------------------------- SignalType ExitSignalA() { double SAR0 = iSAR(_Symbol, 0, SARStep, SARMaxStep, 0); double SAR1 = iSAR(_Symbol, 0, SARStep, SARMaxStep, 1); double SAR2 = iSAR(_Symbol, 0, SARStep, SARMaxStep, 2); if ((Low[1] > SAR1 && Close[0] <= SAR0) || (High[2] < SAR2 && High[1] < SAR1 && High[0] < SAR0)) return BUY_EXIT; return NO_SIGNAL; } //--------------------------------------------- // (15) Entry signal logic //--------------------------------------------- SignalType EntrySignalA() { double SAR1 = iSAR(_Symbol, 0, SARStep, SARMaxStep, 1); double SAR2 = iSAR(_Symbol, 0, SARStep, SARMaxStep, 2); double SAR3 = iSAR(_Symbol, 0, SARStep, SARMaxStep, 3); if ((High[2] < SAR2 && Close[1] >= SAR1) || (Low[3] > SAR3 && Low[2] > SAR2 && Low[1] > SAR1)) return BUY_ENTRY; return NO_SIGNAL; } //--------------------------------------------- // (21) Exit processing (BUY only) //--------------------------------------------- void HandleExitA(SignalType sig) { if (sig != BUY_EXIT) return; double closePrice = Bid; for (int i = OrdersTotal() - 1; i >= 0; i--) { if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) { if (OrderMagicNumber() == Magic_A && OrderSymbol() == _Symbol && OrderType() == OP_BUY) { int ticket = OrderTicket(); double lots = OrderLots(); bool result = OrderClose( ticket, lots, closePrice, PipToPoint(SlippagePips), clrOrange ); if (!result) PrintFormat("❌ OrderClose failed. Ticket=%d Error=%d", ticket, GetLastError()); else PrintFormat("✅ Order closed successfully. Ticket=%d", ticket); } } } } //--------------------------------------------- // (22) Entry processing (BUY only) //--------------------------------------------- void HandleEntryA(SignalType sig) { if (sig != BUY_ENTRY) return; // Spread check double spreadPips = (Ask - Bid) / Pip(); if (spreadPips > MaxSpreadPips) { PrintFormat("❌ Spread too high (%.1f pips). Entry skipped.", spreadPips); return; } if (!CanPlaceNewBuy()) return; double price = Ask; double sl = NormalizeDouble(price - SLPips * Pip(), Digits); double tp = NormalizeDouble(price + TPPips * Pip(), Digits); int slippagePoints = PipToPoint(SlippagePips); int ticket = OrderSend( _Symbol, OP_BUY, LotSize, price, slippagePoints, sl, tp, "Magic_A Entry", Magic_A, 0, clrOrange ); if (ticket > 0) PrintFormat("✅ Magic_A BUY order placed. Ticket=%d", ticket); else PrintFormat("❌ Magic_A OrderSend failed. Error=%d", GetLastError()); } //--------------------------------------------- // (27) Main OnTick processing //--------------------------------------------- void OnTick() { // EXIT: evaluated on every tick and executed immediately if conditions are met SignalType exitSig = ExitSignalA(); HandleExitA(exitSig); // ENTRY: evaluated only on a new bar if (IsNewBar(PERIOD_CURRENT, prevTime_A)) { SignalType entrySig = EntrySignalA(); HandleEntryA(entrySig); } } // --- END ---