195 lines
15 KiB
MQL5
195 lines
15 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| Expert initialization function |
|
|
//+------------------------------------------------------------------+
|
|
#property copyright "Fox-In-The-Code"
|
|
#property link "https://foxinthecode.com"
|
|
#property version "2.2"
|
|
|
|
#include <Trade/Trade.mqh>
|
|
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;
|
|
}
|