Files
MQL5Data/Documents/BKP/Indicators/bos-choch.mq5
T
2025-04-04 08:36:41 +03:30

128 lines
4.4 KiB
Plaintext

#property copyright "Your Name"
#property link "https://www.example.com"
#property version "1.00"
#property indicator_chart_window
#property indicator_buffers 0
#property indicator_plots 0
// Input parameters
input int SwingPeriod = 5; // Lookback period for swing detection
// Global variables
double LastSwingHigh = 0, LastSwingLow = 0;
bool IsBullish = false;
//+------------------------------------------------------------------+
int OnInit()
{
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
const int prev_calculated,
const datetime &time[],
const double &open[],
const double &high[],
const double &low[],
const double &close[],
const long &tick_volume[],
const long &volume[],
const int &spread[])
{
// Start from the latest bar
for(int i = rates_total - prev_calculated - 1; i >= 0; i--)
{
// Detect swing high and low
if(IsSwingHigh(high, low, i, SwingPeriod))
{
LastSwingHigh = high[i];
CheckStructure(i, high[i], low[i], time[i]);
}
if(IsSwingLow(high, low, i, SwingPeriod))
{
LastSwingLow = low[i];
CheckStructure(i, high[i], low[i], time[i]);
}
}
return(rates_total);
}
//+------------------------------------------------------------------+
bool IsSwingHigh(const double &high[], const double &low[], int index, int period)
{
if(index < period || index >= ArraySize(high) - period) return false;
for(int i = 1; i <= period; i++)
{
if(high[index] <= high[index - i] || high[index] <= high[index + i])
return false;
}
return true;
}
//+------------------------------------------------------------------+
bool IsSwingLow(const double &high[], const double &low[], int index, int period)
{
if(index < period || index >= ArraySize(low) - period) return false;
for(int i = 1; i <= period; i++)
{
if(low[index] >= low[index - i] || low[index] >= low[index + i])
return false;
}
return true;
}
//+------------------------------------------------------------------+
void CheckStructure(int index, double high, double low, datetime time)
{
// Determine trend direction
if(LastSwingHigh > 0 && LastSwingLow > 0)
{
IsBullish = (LastSwingHigh > LastSwingLow);
// Check for BOS
if(IsBullish && high > LastSwingHigh)
{
LastSwingHigh = high;
ObjectCreate(0, "BOS_" + TimeToString(time), OBJ_TEXT, 0, time, high);
ObjectSetString(0, "BOS_" + TimeToString(time), OBJPROP_TEXT, "BOS");
ObjectSetInteger(0, "BOS_" + TimeToString(time), OBJPROP_COLOR, clrGreen);
Alert("Break of Structure (BOS) detected at " + DoubleToString(high, 5));
}
else if(!IsBullish && low < LastSwingLow)
{
LastSwingLow = low;
ObjectCreate(0, "BOS_" + TimeToString(time), OBJ_TEXT, 0, time, low);
ObjectSetString(0, "BOS_" + TimeToString(time), OBJPROP_TEXT, "BOS");
ObjectSetInteger(0, "BOS_" + TimeToString(time), OBJPROP_COLOR, clrRed);
Alert("Break of Structure (BOS) detected at " + DoubleToString(low, 5));
}
// Check for CHoCH
if(IsBullish && low < LastSwingLow)
{
LastSwingLow = low;
ObjectCreate(0, "CHoCH_" + TimeToString(time), OBJ_TEXT, 0, time, low);
ObjectSetString(0, "CHoCH_" + TimeToString(time), OBJPROP_TEXT, "CHoCH");
ObjectSetInteger(0, "CHoCH_" + TimeToString(time), OBJPROP_COLOR, clrRed);
Alert("Change of Character (CHoCH) detected at " + DoubleToString(low, 5));
IsBullish = false; // Trend may reverse
}
else if(!IsBullish && high > LastSwingHigh)
{
LastSwingHigh = high;
ObjectCreate(0, "CHoCH_" + TimeToString(time), OBJ_TEXT, 0, time, high);
ObjectSetString(0, "CHoCH_" + TimeToString(time), OBJPROP_TEXT, "CHoCH");
ObjectSetInteger(0, "CHoCH_" + TimeToString(time), OBJPROP_COLOR, clrGreen);
Alert("Change of Character (CHoCH) detected at " + DoubleToString(high, 5));
IsBullish = true; // Trend may reverse
}
}
}
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
ObjectsDeleteAll(0, "BOS_");
ObjectsDeleteAll(0, "CHoCH_");
}