//+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ #property copyright "Fox-In-The-Code" #property link "https://foxinthecode.com" #property version "2.2" #include CTrade Trade; //--- Input parameters input double RR_SL_Kerroin = 0.4; // Risk coefficient for Stop Loss input double RR_TP_Kerroin = 1.0; // Risk coefficient for Take Profit input double AtrMin = 3.0; // Minimum ATR input double AtrMax = 10.0; // Maximum ATR input double Lot_Size = 0.02; // Fixed lot size input double Ylipip = 1; // Pip threshold for entry input int ATR_Period = 14; // ATR period //--- Global variables int MagicNumber; double atrValue; bool bosDetected = false; bool isBuySignal = false; bool isSellSignal = false; double bosHigh = 0; double bosLow = 0; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { Print("Fox-In-The-Code Bot initialized."); MagicNumber = 123456; // Assign a unique magic number return INIT_SUCCEEDED; } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { Print("Fox-In-The-Code Bot deinitialized."); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { // Check for a new bar if (!IsNewBar()) return; // Update indicators if (!UpdateIndicators()) return; // Detect BOS on M30 timeframe if (!DetectBOS()) return; // Check for trade conditions based on ATR and M5 Salama if (CheckBuyConditions()) ExecuteTrade(ORDER_TYPE_BUY, bosHigh); if (CheckSellConditions()) ExecuteTrade(ORDER_TYPE_SELL, bosLow); } //+------------------------------------------------------------------+ //| Update ATR and other indicators | //+------------------------------------------------------------------+ bool UpdateIndicators() { atrValue = iATR(_Symbol, _Period, ATR_Period); // Correct ATR usage if (atrValue < AtrMin || atrValue > AtrMax) { Print("ATR out of range: ", atrValue); return false; } return true; } //+------------------------------------------------------------------+ //| Detect Break of Structure (BOS) | //+------------------------------------------------------------------+ bool DetectBOS() { // Ensure we are working on M30 timeframe if (_Period != PERIOD_M30) return false; if (iClose(_Symbol, PERIOD_M30, 1) > iHigh(_Symbol, PERIOD_M30, 2)) { bosHigh = iHigh(_Symbol, PERIOD_M30, 1); bosDetected = true; isBuySignal = true; isSellSignal = false; Print("BOS High detected: ", bosHigh); DrawArrow(bosHigh, true); } else if (iClose(_Symbol, PERIOD_M30, 1) < iLow(_Symbol, PERIOD_M30, 2)) { bosLow = iLow(_Symbol, PERIOD_M30, 1); bosDetected = true; isBuySignal = false; isSellSignal = true; Print("BOS Low detected: ", bosLow); DrawArrow(bosLow, false); } else { bosDetected = false; return false; } return true; } //+------------------------------------------------------------------+ //| Draw Arrow for BOS Visualization | //+------------------------------------------------------------------+ void DrawArrow(double price, bool isBuy) { string arrowName = "BOS_" + (isBuy ? "High" : "Low") + "_" + TimeToString(TimeCurrent(), TIME_DATE | TIME_MINUTES); if (!ObjectCreate(0, arrowName, OBJ_ARROW, 0, TimeCurrent(), price)) { Print("Failed to create arrow: ", GetLastError()); return; } ObjectSetInteger(0, arrowName, OBJPROP_ARROWCODE, isBuy ? 233 : 234); // Up for buy, down for sell ObjectSetInteger(0, arrowName, OBJPROP_COLOR, isBuy ? clrGreen : clrRed); } //+------------------------------------------------------------------+ //| Check Buy Conditions | //+------------------------------------------------------------------+ bool CheckBuyConditions() { if (!bosDetected || !isBuySignal) return false; // Switch to M5 and confirm Salama pattern double m5Close = iClose(_Symbol, PERIOD_M5, 0); double m5Open = iOpen(_Symbol, PERIOD_M5, 0); if (m5Close > m5Open + Ylipip * _Point && atrValue >= AtrMin && atrValue <= AtrMax) { return true; } return false; } //+------------------------------------------------------------------+ //| Check Sell Conditions | //+------------------------------------------------------------------+ bool CheckSellConditions() { if (!bosDetected || !isSellSignal) return false; // Switch to M5 and confirm Salama pattern double m5Close = iClose(_Symbol, PERIOD_M5, 0); double m5Open = iOpen(_Symbol, PERIOD_M5, 0); if (m5Close < m5Open - Ylipip * _Point && atrValue >= AtrMin && atrValue <= AtrMax) { return true; } return false; } //+------------------------------------------------------------------+ //| Execute Trade | //+------------------------------------------------------------------+ bool ExecuteTrade(ENUM_ORDER_TYPE orderType, double bosPrice) { MqlTradeRequest request; MqlTradeResult result; ZeroMemory(request); ZeroMemory(result); double price = (orderType == ORDER_TYPE_BUY) ? SymbolInfoDouble(_Symbol, SYMBOL_ASK) : SymbolInfoDouble(_Symbol, SYMBOL_BID); double sl = (orderType == ORDER_TYPE_BUY) ? price - atrValue * RR_SL_Kerroin : price + atrValue * RR_SL_Kerroin; double tp = (orderType == ORDER_TYPE_BUY) ? price + atrValue * RR_TP_Kerroin : price - atrValue * RR_TP_Kerroin; request.action = TRADE_ACTION_DEAL; request.symbol = _Symbol; request.volume = Lot_Size; request.price = NormalizeDouble(price, _Digits); request.sl = NormalizeDouble(sl, _Digits); request.tp = NormalizeDouble(tp, _Digits); request.type = orderType; request.magic = MagicNumber; request.type_filling = ORDER_FILLING_IOC; if (!OrderSend(request, result)) { Print("Trade failed. Error: ", GetLastError()); return false; } Print("Trade executed. Ticket: ", result.order, " Lot: ", Lot_Size, " SL: ", request.sl, " TP: ", request.tp); return true; } //+------------------------------------------------------------------+ //| Is New Bar | //+------------------------------------------------------------------+ bool IsNewBar() { static datetime lastBarTime = 0; datetime currentBarTime = iTime(_Symbol, _Period, 0); if (currentBarTime != lastBarTime) { lastBarTime = currentBarTime; return true; } return false; }