128 lines
4.4 KiB
Plaintext
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_");
|
|
} |