0% found this document useful (0 votes)
10 views35 pages

Rsi

Uploaded by

medofski2011
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
10 views35 pages

Rsi

Uploaded by

medofski2011
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 35

//+------------------------------------------------------------------+

//| ICT Enhanced Version.mq4 |


//| Based on Michael Huddleston Model |
//+------------------------------------------------------------------+
#property copyright ""
#property link ""
#property version "1.00"
#property strict
#property indicator_chart_window
#property indicator_buffers 18

// Indicator buffers for drawing


double LondonHighBuffer[];
double LondonLowBuffer[];
double NYHighBuffer[];
double NYLowBuffer[];
double FVGHighBuffer[];
double FVGLowBuffer[];
double DailyBiasBuffer[];
double AsianHighBuffer[];
double AsianLowBuffer[];
double BuySignalBuffer[];
double SellSignalBuffer[];
double BullishPatternBuffer[];
double BearishPatternBuffer[];
double BullishDivergenceBuffer[];
double BearishDivergenceBuffer[];
double adxBuffer[];

// Indicator buffers for market regime detection


double upperBBBuffer[];
double lowerBBBuffer[];

// New buffer for RSI values


double RSIValues[];

// Input parameters
input color RangeColor = clrYellow; // Range High/Low Color
input color AsianColor = clrPurple; // Asian Session High/Low Color
input color LondonColor = clrRed; // London Session High/Low Color
input color NYColor = clrBlue; // NY Session High/Low Color
input color FVGColor = clrLightGreen; // Fair Value Gap Color
input color BiasColor = clrMagenta; // Daily Bias Arrow Color
input bool ShowAsianFibo = true; // Show Asian Session Fibonacci
Retracement
input bool ShowLondonFibo = true; // Show London Session Fibonacci
Retracement
input bool ShowNYFibo = true; // Show NY Session Fibonacci Retracement
input bool ShowSessions = true; // Show Session Lines
input bool ShowFVG = true; // Show Fair Value Gaps
input bool ShowFibo = true; // Show Fibonacci Retracements
input bool ShowDailyBias = true; // Show Daily Bias Calculation
input int DailyBiasPeriod = 20; // Daily Bias Calculation Period
input bool AlertsOn = false; // Enable Alerts
input int GMT_Offset = 0; // Manual GMT Offset (used only if
AutoDetectGMT=false)
input bool UseLocalTime = false; // Use local PC time instead of server
time
input bool AutoDetectGMT = true; // Automatically detect GMT offset
input double BiasThresholdMultiplier = 1.0; // Bias threshold sensitivity (0.5-2.0)
input string GoldBiasParams = "--------- XAUUSD-Specific Bias Settings
---------"; // Separator
input bool UseGoldOptimizedSettings = false;// Use Gold-Optimized Bias Calculation
input double EMAAlignmentWeight = 2.0; // EMA Alignment Weight (2.5 recommended
for Gold)
input double MomentumWeight = 0.75; // Momentum Indicator Weight (1.25 for
Gold)
input double USDCorrelationWeight = 0.0; // USD Correlation Factor Weight (1.0
for Gold)
input int ATRPeriod = 14; // ATR Period (20 recommended for Gold)
input double VolatilityMultiplier = 1.5; // Volatility Threshold Multiplier (1.75
for Gold)
input bool IncludeAsianSession = false; // Include Asian Session High/Low
input double PivotPointWeight = 1.0; // Daily Pivot Point Weight (1.25 for
Gold)
input int EMA1Period = 20; // First EMA Period
input int EMA2Period = 50; // Second EMA Period (55 recommended for
Gold)
input int EMA3Period = 200; // Third EMA Period
input bool UseEMA89 = false; // Use Additional EMA 89 for Gold
input double EMA89Weight = 1.0; // EMA 89 Crossing Weight (1.5 for Gold)
input bool UseDXYCorrelation = false; // Use DXY Correlation for Bias
input bool UseRoundNumbers = false; // Consider Round Number
Support/Resistance
input double RoundNumberIncrement = 50.0; // Round Number Increment for Gold
input bool ConsiderPsychLevels = false; // Consider Psychological Price Levels
input int RSIPeriod = 14; // RSI Period (21 recommended for Gold)
input int RSIUpperThreshold = 60; // RSI Upper Threshold (65 for Gold)
input int RSILowerThreshold = 40; // RSI Lower Threshold (35 for Gold)
input double HighConfidenceMultiplier = 1.5;// High Confidence Threshold Multiplier
(1.8 for Gold)
input double MediumConfidenceMultiplier = 1.0;// Medium Confidence Threshold
Multiplier (1.2 for Gold)

// New multi-timeframe parameters


input bool UseTimeframeSpecificSettings = true; // Use different settings for
different timeframes
input int FastTimeframeEMA1 = 10; // EMA1 for 1-5min charts
input int FastTimeframeEMA2 = 20; // EMA2 for 1-5min charts
input int FastTimeframeRSI = 7; // RSI Period for 1-5min charts
input int MediumTimeframeEMA1 = 20; // EMA1 for 15min-1H charts
input int MediumTimeframeEMA2 = 50; // EMA2 for 15min-1H charts
input int MediumTimeframeRSI = 14; // RSI Period for 15min-1H charts
input int SlowTimeframeEMA1 = 50; // EMA1 for 4H-Daily charts
input int SlowTimeframeEMA2 = 200; // EMA2 for 4H-Daily charts
input int SlowTimeframeRSI = 21; // RSI Period for 4H-Daily charts

// Market Regime Detection Parameters


input double TrendStrengthThreshold = 25.0; // ADX threshold for trend strength
input int BBPeriod = 20; // Bollinger Bands period
input double BBDeviation = 2.0; // Bollinger Bands standard deviation

// Price Action Confirmation Parameters


input int PriceActionLookback = 5; // Number of bars to analyze for price action
patterns
input double PinBarMinSize = 0.0005; // Minimum size for pin bars
input double EngulfingMinSize = 0.001; // Minimum size for engulfing patterns
// Multi-Timeframe Alignment Parameters
input int HigherTFPeriod = PERIOD_H4; // Higher timeframe to check alignment
input int LowerTFPeriod = PERIOD_M15; // Lower timeframe to check alignment

// Candlestick Pattern Parameters


input bool ShowCandlestickPatterns = true; // Show candlestick patterns
input int PatternLookback = 5; // Number of recent bars to analyze for patterns
input color BullishPatternColor = clrGreen; // Bullish pattern color
input color BearishPatternColor = clrRed; // Bearish pattern color

// RSI Divergence Parameters


input bool ShowRSIDivergence = true; // Show RSI Divergence
input int RSIDivergencePeriod = 14; // RSI Period for divergence
input int RSIDivergenceLookback = 5; // Lookback period for divergence
input double RSIDivergenceThreshold = 5.0; // Minimum divergence threshold
input color BullishDivergenceColor = clrGreen; // Bullish divergence color
input color BearishDivergenceColor = clrRed; // Bearish divergence color

// Arrow parameters
input color BuyArrowColor = clrGreen;
input color SellArrowColor = clrRed;
input int ArrowSize = 2;

// Time variables
datetime londonOpen, nyOpen, newDayStart;
datetime prevLondonOpen, prevNYOpen, prevAsianOpen;
double londonHigh, londonLow;
double nyHigh, nyLow;
double asianHigh, asianLow;
bool newLondonSession = false;
bool newNYSession = false;
bool newAsianSession = false;
int dailyBias = 0; // 1 for bullish, -1 for bearish, 0 for neutral
int autoGMTOffset = 0; // Auto-detected GMT offset
datetime asianOpen, asianClose; // Add these declarations

// Array to store FVG levels


struct FairValueGap {
datetime time;
double high;
double low;
int direction; // 1 for bullish, -1 for bearish
};

FairValueGap fvgArray[100];
int fvgCount = 0;

// Market regime variables


int marketRegime = 0; // 0 = ranging, 1 = bullish trend, -1 = bearish trend
double adxValue = 0.0;
double upperBB = 0.0;
double lowerBB = 0.0;
double middleBB = 0.0;

double biasThresholdMultiplierValue; // New variable to hold the value

//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int OnInit() {
// Dynamically resize arrays based on available bars
int rates_total = Bars;
ArrayResize(LondonHighBuffer, rates_total);
ArrayResize(LondonLowBuffer, rates_total);
ArrayResize(NYHighBuffer, rates_total);
ArrayResize(NYLowBuffer, rates_total);
ArrayResize(FVGHighBuffer, rates_total);
ArrayResize(FVGLowBuffer, rates_total);
ArrayResize(DailyBiasBuffer, rates_total);
ArrayResize(AsianHighBuffer, rates_total);
ArrayResize(AsianLowBuffer, rates_total);
ArrayResize(BuySignalBuffer, rates_total);
ArrayResize(SellSignalBuffer, rates_total);
ArrayResize(BullishPatternBuffer, rates_total);
ArrayResize(BearishPatternBuffer, rates_total);
ArrayResize(BullishDivergenceBuffer, rates_total);
ArrayResize(BearishDivergenceBuffer, rates_total);
ArrayResize(adxBuffer, rates_total);
ArrayResize(upperBBBuffer, rates_total);
ArrayResize(lowerBBBuffer, rates_total);
ArrayResize(RSIValues, rates_total);

// Set empty value for proper indicator drawing


SetIndexEmptyValue(0, 0);
SetIndexEmptyValue(1, 0);
SetIndexEmptyValue(2, 0);
SetIndexEmptyValue(3, 0);
SetIndexEmptyValue(4, 0);
SetIndexEmptyValue(5, 0);
SetIndexEmptyValue(6, EMPTY_VALUE);
SetIndexEmptyValue(7, EMPTY_VALUE);
SetIndexEmptyValue(8, 0);
SetIndexEmptyValue(9, EMPTY_VALUE);
SetIndexEmptyValue(10, EMPTY_VALUE);
SetIndexEmptyValue(11, EMPTY_VALUE);
SetIndexEmptyValue(12, EMPTY_VALUE);
SetIndexEmptyValue(13, EMPTY_VALUE);
SetIndexEmptyValue(14, EMPTY_VALUE);
SetIndexEmptyValue(15, EMPTY_VALUE);
SetIndexEmptyValue(16, 0); // Added for upperBBBuffer
SetIndexEmptyValue(17, 0); // Added for lowerBBBuffer

// Initialize indicator buffers


SetIndexBuffer(0, LondonHighBuffer);
SetIndexBuffer(1, LondonLowBuffer);
SetIndexBuffer(2, NYHighBuffer);
SetIndexBuffer(3, NYLowBuffer);
SetIndexBuffer(4, FVGHighBuffer);
SetIndexBuffer(5, FVGLowBuffer);
SetIndexBuffer(6, DailyBiasBuffer);
SetIndexBuffer(7, AsianHighBuffer);
SetIndexBuffer(8, AsianLowBuffer);
SetIndexBuffer(9, BuySignalBuffer);
SetIndexBuffer(10, SellSignalBuffer);
SetIndexBuffer(11, BullishPatternBuffer);
SetIndexBuffer(12, BearishPatternBuffer);
SetIndexBuffer(13, BullishDivergenceBuffer);
SetIndexBuffer(14, BearishDivergenceBuffer);
SetIndexBuffer(15, adxBuffer);
SetIndexBuffer(16, upperBBBuffer);
SetIndexBuffer(17, lowerBBBuffer);

// Set indicator line styles


SetIndexStyle(0, DRAW_LINE, STYLE_DASH, 1, LondonColor);
SetIndexStyle(1, DRAW_LINE, STYLE_DASH, 1, LondonColor);
SetIndexStyle(2, DRAW_LINE, STYLE_DASH, 1, NYColor);
SetIndexStyle(3, DRAW_LINE, STYLE_DASH, 1, NYColor);
SetIndexStyle(4, DRAW_HISTOGRAM, STYLE_SOLID, 1, FVGColor);
SetIndexStyle(5, DRAW_HISTOGRAM, STYLE_SOLID, 1, FVGColor);
SetIndexStyle(6, DRAW_ARROW, STYLE_SOLID, 2, BiasColor);
SetIndexStyle(7, DRAW_LINE, STYLE_DASH, 1, AsianColor);
SetIndexStyle(8, DRAW_LINE, STYLE_DASH, 1, AsianColor);
SetIndexStyle(9, DRAW_ARROW, STYLE_SOLID, ArrowSize, BuyArrowColor);
SetIndexStyle(10, DRAW_ARROW, STYLE_SOLID, ArrowSize, SellArrowColor);
SetIndexStyle(11, DRAW_ARROW, STYLE_SOLID, ArrowSize, BullishPatternColor);
SetIndexStyle(12, DRAW_ARROW, STYLE_SOLID, ArrowSize, BearishPatternColor);
SetIndexStyle(13, DRAW_ARROW, STYLE_SOLID, ArrowSize, BullishDivergenceColor);
SetIndexStyle(14, DRAW_ARROW, STYLE_SOLID, ArrowSize, BearishDivergenceColor);
SetIndexStyle(15, DRAW_LINE, STYLE_SOLID, 1, clrGray);
SetIndexStyle(16, DRAW_LINE, STYLE_SOLID, 1, clrGray);
SetIndexStyle(17, DRAW_LINE, STYLE_SOLID, 1, clrGray);

// Set indicator labels


SetIndexLabel(0, "London High");
SetIndexLabel(1, "London Low");
SetIndexLabel(2, "NY High");
SetIndexLabel(3, "NY Low");
SetIndexLabel(4, "FVG High");
SetIndexLabel(5, "FVG Low");
SetIndexLabel(6, "Daily Bias");
SetIndexLabel(7, "Asian High");
SetIndexLabel(8, "Asian Low");
SetIndexLabel(9, "Buy Signal");
SetIndexLabel(10, "Sell Signal");
SetIndexLabel(11, "Bullish Pattern");
SetIndexLabel(12, "Bearish Pattern");
SetIndexLabel(13, "Bullish RSI Divergence");
SetIndexLabel(14, "Bearish RSI Divergence");
SetIndexLabel(15, "ADX");
SetIndexLabel(16, "Upper Bollinger Band");
SetIndexLabel(17, "Lower Bollinger Band");

// Parameter validation
biasThresholdMultiplierValue = BiasThresholdMultiplier;
if (biasThresholdMultiplierValue < 0.5 || biasThresholdMultiplierValue > 2.0) {
Alert("Error: BiasThresholdMultiplier out of range. Resetting to 1.0.");
biasThresholdMultiplierValue = 1.0;
}

// Precompute session times


static datetime lastSessionCalculation = 0;
datetime currentTime = TimeCurrent();
if (IsNewDay(currentTime, lastSessionCalculation)) {
CalculateSessionTimes();
lastSessionCalculation = currentTime;
}
// Auto-detect GMT offset if enabled
if (AutoDetectGMT) {
DetectGMTOffset();
} else {
autoGMTOffset = GMT_Offset;
}

// Initialize time variables


CalculateSessionTimes();

// Set up timer for optimal refreshing


EventSetTimer(60); // Refresh every 60 seconds

return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Auto-detect GMT offset based on broker server time |
//+------------------------------------------------------------------+
void DetectGMTOffset() {
// Get current UTC time
datetime utcTime = TimeGMT();

// Get current server time


datetime serverTime = TimeCurrent();

// Calculate the difference in hours


int diffSeconds = (int)(serverTime - utcTime);
autoGMTOffset = (int)MathRound(diffSeconds / 3600.0);

// Display detected GMT offset


Print("Auto-detected GMT offset: ", autoGMTOffset);
}

//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
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[]) {

static datetime lastCalculationTime = 0;


static int lastRatesTotal = 0;
datetime currentTime = time[0];

// Detect timeframe change or significant data change


if (rates_total != lastRatesTotal) {
// Resize all buffers to match the new number of bars
ArrayResize(LondonHighBuffer, rates_total);
ArrayResize(LondonLowBuffer, rates_total);
ArrayResize(NYHighBuffer, rates_total);
ArrayResize(NYLowBuffer, rates_total);
ArrayResize(FVGHighBuffer, rates_total);
ArrayResize(FVGLowBuffer, rates_total);
ArrayResize(DailyBiasBuffer, rates_total);
ArrayResize(AsianHighBuffer, rates_total);
ArrayResize(AsianLowBuffer, rates_total);
ArrayResize(BuySignalBuffer, rates_total);
ArrayResize(SellSignalBuffer, rates_total);
ArrayResize(BullishPatternBuffer, rates_total);
ArrayResize(BearishPatternBuffer, rates_total);
ArrayResize(BullishDivergenceBuffer, rates_total);
ArrayResize(BearishDivergenceBuffer, rates_total);
ArrayResize(adxBuffer, rates_total);
ArrayResize(upperBBBuffer, rates_total);
ArrayResize(lowerBBBuffer, rates_total);
ArrayResize(RSIValues, rates_total);

// Reset session variables


newLondonSession = true;
newNYSession = true;
newAsianSession = true;

lastRatesTotal = rates_total;
}

// Only recalculate session times when day changes or on first run


if(IsNewDay(currentTime, lastCalculationTime) || lastCalculationTime == 0) {
if(AutoDetectGMT) {
DetectGMTOffset();
}
CalculateSessionTimes();
lastCalculationTime = currentTime;
}

// Check if we have enough data


if(rates_total < DailyBiasPeriod + 10) return(0);

int limit;
if(prev_calculated > rates_total || prev_calculated <= 0) {
limit = MathMax(0, rates_total - 100); // Calculate only the most recent 100
bars on first load
} else {
limit = MathMax(0, rates_total - prev_calculated); // Calculate only new bars
}

// Calculate Daily Bias


if (ShowDailyBias) {
CalculateDailyBias(rates_total, time, high, low, open, close);
}

// Calculate session ranges and key levels


CalculateRanges(rates_total, time, high, low);

// Find Fair Value Gaps (if enabled)


if (ShowFVG) {
FindFairValueGaps(rates_total, time, high, low, open, close);
}

// Draw levels on the chart


DrawLevels(rates_total, time);
// Check for trading setups based on ICT model
CheckForTradingSetups(rates_total, time, high, low, open, close);

// Detect market regime


DetectMarketRegime(rates_total);

// Draw price action arrows


DrawPriceActionArrows(rates_total, time, open, high, low, close, tick_volume);

// Detect and visualize candlestick patterns


if (ShowCandlestickPatterns) {
DetectAndDrawPatterns(rates_total, time, open, high, low, close);
}

// Calculate and visualize RSI divergence


if (ShowRSIDivergence) {
CalculateRSI(rates_total, time, close);
DetectRSIDivergence(rates_total, time, high, low, close);
}

// Visualize market regime


VisualizeMarketRegime(rates_total, time);

return(rates_total);
}

//+------------------------------------------------------------------+
//| Calculate session times with GMT offset |
//+------------------------------------------------------------------+
void CalculateSessionTimes() {
// Store previous session times
prevLondonOpen = londonOpen;
prevNYOpen = nyOpen;
prevAsianOpen = asianOpen;

// Get current time based on setting


datetime currentTime;
int actualGMTOffset = AutoDetectGMT ? autoGMTOffset : GMT_Offset;

if (UseLocalTime) {
// Use local PC time
currentTime = TimeLocal();
} else {
// Use server time with GMT offset adjustment
currentTime = TimeCurrent() + (actualGMTOffset * 3600);
}

// Calculate midnight in specified time zone


int dayOfWeek = TimeDayOfWeek(currentTime);
datetime midnight = currentTime - TimeHour(currentTime) * 3600
- TimeMinute(currentTime) * 60
- TimeSeconds(currentTime);

// Calculate session times based on GMT offset


// London Open: Standard time is 08:00 AM GMT (03:00 AM EST)
londonOpen = midnight + 8 * 3600;

// NY Open: Standard time is 13:00 PM GMT (08:00 AM EST)


nyOpen = midnight + 13 * 3600;

// Asian Open: Standard time is 00:00 AM GMT (Tokyo session)


asianOpen = midnight;

// Asian Close: Standard time is 08:00 AM GMT (when London opens)


asianClose = londonOpen;

// Start of new day


newDayStart = midnight;

// Reset session flags


newLondonSession = (prevLondonOpen != londonOpen);
newNYSession = (prevNYOpen != nyOpen);
newAsianSession = (prevAsianOpen != asianOpen);

// Initialize session high/low levels


if (newLondonSession) {
londonHigh = 0;
londonLow = 999999;
}

if (newNYSession) {
nyHigh = 0;
nyLow = 999999;
}

if (newAsianSession) {
asianHigh = 0;
asianLow = 999999;
}

// Draw vertical lines for sessions if enabled


if (ShowSessions) {
ObjectDelete("LondonOpen");
ObjectDelete("NYOpen");
ObjectDelete("AsianOpen");

ObjectCreate("LondonOpen", OBJ_VLINE, 0, londonOpen, 0);


ObjectSetInteger(0, "LondonOpen", OBJPROP_COLOR, LondonColor);
ObjectSetInteger(0, "LondonOpen", OBJPROP_STYLE, STYLE_DASH);
ObjectSetInteger(0, "LondonOpen", OBJPROP_WIDTH, 1);
ObjectSetText("LondonOpen", "London Open", 8);

ObjectCreate("NYOpen", OBJ_VLINE, 0, nyOpen, 0);


ObjectSetInteger(0, "NYOpen", OBJPROP_COLOR, NYColor);
ObjectSetInteger(0, "NYOpen", OBJPROP_STYLE, STYLE_DASH);
ObjectSetInteger(0, "NYOpen", OBJPROP_WIDTH, 1);
ObjectSetText("NYOpen", "NY Open", 8);

ObjectCreate("AsianOpen", OBJ_VLINE, 0, asianOpen, 0);


ObjectSetInteger(0, "AsianOpen", OBJPROP_COLOR, AsianColor);
ObjectSetInteger(0, "AsianOpen", OBJPROP_STYLE, STYLE_DASH);
ObjectSetInteger(0, "AsianOpen", OBJPROP_WIDTH, 1);
ObjectSetText("AsianOpen", "Asian Open", 8);
}

// Display time zone information on chart


string timeZoneText = "Time Zone: GMT" + (actualGMTOffset > 0 ? "+" : "") +
IntegerToString(actualGMTOffset) +
(AutoDetectGMT ? " (Auto-detected)" : "") +
(UseLocalTime ? " (Local PC Time)" : " (Server Time)");

ObjectDelete("TimeZoneLabel");
ObjectCreate("TimeZoneLabel", OBJ_LABEL, 0, 0, 0);
ObjectSetText("TimeZoneLabel", timeZoneText, 8, "Arial", clrWhite);
ObjectSet("TimeZoneLabel", OBJPROP_CORNER, 1);
ObjectSet("TimeZoneLabel", OBJPROP_XDISTANCE, 10);
ObjectSet("TimeZoneLabel", OBJPROP_YDISTANCE, 40);
}

//+------------------------------------------------------------------+
//| Calculate Daily Bias with Gold-Optimized Settings |
//+------------------------------------------------------------------+
void CalculateDailyBias(const int rates_total, const datetime &time[],
const double &high[], const double &low[],
const double &open[], const double &close[]) {
double biasScore = 0.0; // Declare biasScore here

// Only recalculate daily bias once per new day


static datetime lastBiasCalc = 0;
static double cachedBiasScore = 0;

// Use cached value if within same day


if(time[0] > 0 && lastBiasCalc > 0 &&
TimeDay(time[0]) == TimeDay(lastBiasCalc) &&
TimeMonth(time[0]) == TimeMonth(lastBiasCalc) &&
TimeYear(time[0]) == TimeYear(lastBiasCalc)) {

// Only recalculate every 30 minutes during trading hours


if(TimeHour(time[0]) == TimeHour(lastBiasCalc) &&
MathAbs(TimeMinute(time[0]) - TimeMinute(lastBiasCalc)) < 30) {

biasScore = cachedBiasScore;
return; // Use cached value
}
}

// Core data points


double dailyOpen = iOpen(Symbol(), PERIOD_D1, 0);
double prevDayHigh = iHigh(Symbol(), PERIOD_D1, 1);
double prevDayLow = iLow(Symbol(), PERIOD_D1, 1);
double weeklyOpen = iOpen(Symbol(), PERIOD_W1, 0);
double monthlyOpen = iOpen(Symbol(), PERIOD_MN1, 0);

// === ASIAN SESSION ANALYSIS (GOLD-SPECIFIC) ===


// Use global variables directly
if (IncludeAsianSession || (UseGoldOptimizedSettings && Symbol() == "XAUUSD")) {
// Calculate Asian session times (approx. 00:00-08:00 GMT)
datetime asianStart = newDayStart;
datetime asianEnd = newDayStart + 8*3600;

// Find Asian session high/low


for (int i = rates_total - 1; i >= 0; i--) {
if (time[i] >= asianStart && time[i] < asianEnd) {
if (high[i] > asianHigh) asianHigh = high[i];
if (low[i] < asianLow) asianLow = low[i];
}
}
}

// === PIVOT POINT CALCULATION ===


double pivot = 0;
double r1 = 0, r2 = 0, s1 = 0, s2 = 0;

if (PivotPointWeight > 0 || (UseGoldOptimizedSettings && Symbol() == "XAUUSD"))


{
// Calculate standard pivot points
double prevHigh = iHigh(Symbol(), PERIOD_D1, 1);
double prevLow = iLow(Symbol(), PERIOD_D1, 1);
double prevClose = iClose(Symbol(), PERIOD_D1, 1);

pivot = (prevHigh + prevLow + prevClose) / 3;


r1 = (2 * pivot) - prevLow;
r2 = pivot + (prevHigh - prevLow);
s1 = (2 * pivot) - prevHigh;
s2 = pivot - (prevHigh - prevLow);
}

// === MULTI-TIMEFRAME ANALYSIS ===


double h4Close = iClose(Symbol(), PERIOD_H4, 0);
double h4MA20 = iMA(Symbol(), PERIOD_H4, EMA1Period, 0, MODE_EMA, PRICE_CLOSE,
0);

// Use appropriate EMA periods based on settings


int ema1Period = EMA1Period;
int ema2Period = EMA2Period;
int ema3Period = EMA3Period;

// For Gold, use optimized EMA settings if specified


if (UseGoldOptimizedSettings && Symbol() == "XAUUSD") {
ema2Period = 55; // Use EMA 55 instead of EMA 50 for gold
}

// Calculate EMAs
double ma20 = iMA(Symbol(), PERIOD_D1, ema1Period, 0, MODE_EMA, PRICE_CLOSE, 0);
double ma50 = iMA(Symbol(), PERIOD_D1, ema2Period, 0, MODE_EMA, PRICE_CLOSE, 0);
double ma200 = iMA(Symbol(), PERIOD_D1, ema3Period, 0, MODE_EMA, PRICE_CLOSE,
0);

// Add EMA 89 for Gold if enabled


double ma89 = 0;
bool aboveEMA89 = false;

if (UseEMA89 || (UseGoldOptimizedSettings && Symbol() == "XAUUSD")) {


ma89 = iMA(Symbol(), PERIOD_D1, 89, 0, MODE_EMA, PRICE_CLOSE, 0);
aboveEMA89 = Close[0] > ma89;
}

// === ENHANCED MARKET STRUCTURE ANALYSIS ===


bool bullishStructure = true;
bool bearishStructure = true;

// Check the last 5 swings for market structure


for (int i = 1; i < 5; i++) {
// Cannot confirm bullish structure if we have a lower low
if (Low[i] < Low[i+1]) bullishStructure = false;
// Cannot confirm bearish structure if we have a higher high
if (High[i] > High[i+1]) bearishStructure = false;
}

// === EMA ALIGNMENT ANALYSIS ===


bool emaAlignment = false;
int emaStrength = 0;

// Apply appropriate EMA alignment weight


double actualEMAWeight = UseGoldOptimizedSettings && Symbol() == "XAUUSD" ?
2.5 : EMAAlignmentWeight;

// Check if EMAs are aligned


if (ma20 > ma50 && ma50 > ma200) {
emaAlignment = true;
emaStrength = 3; // Strong bullish
}
else if (ma20 < ma50 && ma50 < ma200) {
emaAlignment = false;
emaStrength = -3; // Strong bearish
}
else if (ma20 > ma50) {
emaAlignment = true;
emaStrength = 1; // Weak bullish
}
else if (ma20 < ma50) {
emaAlignment = false;
emaStrength = -1; // Weak bearish
}

// === MOMENTUM CONFIRMATION WITH OPTIMIZED RSI SETTINGS ===


int actualRSIPeriod = UseGoldOptimizedSettings && Symbol() == "XAUUSD" ? 21 :
RSIPeriod;
int actualUpperThreshold = UseGoldOptimizedSettings && Symbol() == "XAUUSD" ? 65
: RSIUpperThreshold;
int actualLowerThreshold = UseGoldOptimizedSettings && Symbol() == "XAUUSD" ? 35
: RSILowerThreshold;

// Apply appropriate momentum weight


double actualMomentumWeight = UseGoldOptimizedSettings && Symbol() == "XAUUSD" ?
1.25 : MomentumWeight;

double rsiDaily = iRSI(Symbol(), PERIOD_D1, actualRSIPeriod, PRICE_CLOSE, 0);

// === USD CORRELATION FOR GOLD ===


double usdCorrelation = 0;

if ((UseDXYCorrelation || (UseGoldOptimizedSettings && Symbol() == "XAUUSD")) &&

(Symbol() == "XAUUSD" || Symbol() == "GOLD")) {

// Try to get DXY data - use multiple possible symbols for DXY index
double dxyClose = 0;
double dxyPrevClose = 0;
bool dxyDataFound = false;

string dxySymbols[6] = {"DXY.cash", "USDX", "DXY", "USDIndex", "DOLLAR",


"USD"};
for (int i = 0; i < 5; i++) {
dxyClose = iClose(dxySymbols[i], PERIOD_D1, 0);
dxyPrevClose = iClose(dxySymbols[i], PERIOD_D1, 1);

// If we found a valid DXY symbol


if (dxyClose > 0 && dxyPrevClose > 0) {
dxyDataFound = true;
Print("DXY symbol detected: " + dxySymbols[i]); // This line shows
which symbol was found
break;
}
}

// Calculate USD correlation (negative for gold typically)


if (dxyDataFound) {
double dxyChange = dxyClose - dxyPrevClose;
if (dxyChange > 0) usdCorrelation = -1.0; // Typically negative
correlation
else if (dxyChange < 0) usdCorrelation = 1.0; // Typically positive
correlation
} else {
usdCorrelation = 0.0;
Print("Error: DXY data not found. USD correlation set to neutral.");
}
}

// === ROUND NUMBER ANALYSIS FOR GOLD ===


double roundNumberEffect = 0;

if ((UseRoundNumbers || (UseGoldOptimizedSettings && Symbol() == "XAUUSD")) &&


(Symbol() == "XAUUSD" || Symbol() == "GOLD")) {

double actualIncrement = RoundNumberIncrement;


double currentPrice = Close[0];

// Check proximity to round numbers


double roundedPrice = MathRound(currentPrice / actualIncrement) *
actualIncrement;
double distanceToRound = MathAbs(currentPrice - roundedPrice);
double proximityThreshold = actualIncrement * 0.05; // Within 5% of increment

// Check psychological levels


bool nearPsychLevel = false;

if (ConsiderPsychLevels || (UseGoldOptimizedSettings && Symbol() ==


"XAUUSD")) {
int hundreds = (int)currentPrice / 100;
double psychLevel = hundreds * 100;
double distanceToPsych = MathAbs(currentPrice - psychLevel);

if (distanceToPsych < 5.0) {


nearPsychLevel = true;
}
}

// Adjust bias for round number proximity - can cause reversals


if (distanceToRound < proximityThreshold || nearPsychLevel) {
// Check if approaching from above or below
if (currentPrice > roundedPrice) {
roundNumberEffect = -0.5; // Slight bearish tendency at resistance
} else {
roundNumberEffect = 0.5; // Slight bullish tendency at support
}
}
}

// === CUSTOM ATR VOLATILITY SETTINGS ===


int actualATRPeriod = UseGoldOptimizedSettings && Symbol() == "XAUUSD" ? 20 :
ATRPeriod;
double actualVolMultiplier = UseGoldOptimizedSettings && Symbol() == "XAUUSD" ?
1.75 : VolatilityMultiplier;

double atr = iATR(Symbol(), PERIOD_D1, actualATRPeriod, 0);


double avgATR = 0;

// Calculate average ATR for volatility context


for (int i = 0; i < 5; i++) {
avgATR += iATR(Symbol(), PERIOD_D1, actualATRPeriod, i);
}
avgATR /= 5;

// === COMPREHENSIVE WEIGHTED SCORING SYSTEM ===

// Market structure (highest weight: 2.5)


if (bullishStructure) biasScore += 2.5;
if (bearishStructure) biasScore -= 2.5;

// EMA alignment with custom weight


biasScore += emaStrength * (actualEMAWeight / 3.0); // Scale to actual weight

// EMA89 for gold if enabled


if ((UseEMA89 || (UseGoldOptimizedSettings && Symbol() == "XAUUSD")) && ma89 >
0) {
if (Close[0] > ma89) biasScore += EMA89Weight;
if (Close[0] < ma89) biasScore -= EMA89Weight;
}

// H4 vs Daily EMA (weight: 1.5)


if (h4Close > h4MA20) biasScore += 1.5;
if (h4Close < h4MA20) biasScore -= 1.5;

// Current price vs key levels (weight: 1.0)


if (Close[0] > prevDayHigh) biasScore += 1.0;
if (Close[0] < prevDayLow) biasScore -= 1.0;

// Asian session levels for Gold


if ((IncludeAsianSession || (UseGoldOptimizedSettings && Symbol() == "XAUUSD"))
&&
asianHigh > 0 && asianLow < 999999) {
if (Close[0] > asianHigh) biasScore += 1.0;
if (Close[0] < asianLow) biasScore -= 1.0;
}

// Pivot points with custom weight


if ((PivotPointWeight > 0 || (UseGoldOptimizedSettings && Symbol() == "XAUUSD"))
&& pivot > 0) {
double actualPivotWeight = UseGoldOptimizedSettings && Symbol() == "XAUUSD" ?
1.25 : PivotPointWeight;

if (Close[0] > r1) biasScore += actualPivotWeight;


else if (Close[0] > pivot) biasScore += actualPivotWeight * 0.5;
else if (Close[0] < s1) biasScore -= actualPivotWeight;
else if (Close[0] < pivot) biasScore -= actualPivotWeight * 0.5;
}

// Daily close vs open (weight: 0.75)


if (Close[0] > dailyOpen) biasScore += 0.75;
if (Close[0] < dailyOpen) biasScore -= 0.75;

// Weekly open assessment (weight: 0.5)


if (Close[0] > weeklyOpen) biasScore += 0.5;
if (Close[0] < weeklyOpen) biasScore -= 0.5;

// Monthly open assessment (weight: 0.5)


if (Close[0] > monthlyOpen) biasScore += 0.5;
if (Close[0] < monthlyOpen) biasScore -= 0.5;

// RSI momentum with custom weight and thresholds


if (rsiDaily > actualUpperThreshold) biasScore += actualMomentumWeight;
else if (rsiDaily < actualLowerThreshold) biasScore -= actualMomentumWeight;

// USD correlation for Gold


if ((UseDXYCorrelation || (UseGoldOptimizedSettings && Symbol() == "XAUUSD")) &&

(Symbol() == "XAUUSD" || Symbol() == "GOLD")) {


double actualUSDWeight = UseGoldOptimizedSettings && Symbol() == "XAUUSD" ?
1.0 : USDCorrelationWeight;
biasScore += usdCorrelation * actualUSDWeight;
}

// Round number effect for Gold


biasScore += roundNumberEffect;

// === DYNAMIC THRESHOLD BASED ON VOLATILITY ===


double biasThreshold = 2.0 * biasThresholdMultiplierValue;

// Adjust threshold based on volatility


if (atr > avgATR * actualVolMultiplier) {
// Higher volatility requires stronger signal
biasThreshold *= 1.25;
}

// === OPTIMIZED BIAS CONFIDENCE LEVELS FOR GOLD ===


string confidenceLevel = "";
color biasDisplayColor;

// Use custom confidence multipliers - higher for Gold


double actualHighMultiplier = UseGoldOptimizedSettings && Symbol() == "XAUUSD" ?
1.8 : HighConfidenceMultiplier;
double actualMediumMultiplier = UseGoldOptimizedSettings && Symbol() == "XAUUSD"
? 1.2 : MediumConfidenceMultiplier;

if (biasScore >= biasThreshold * actualHighMultiplier) {


dailyBias = 1; // Strong bullish
confidenceLevel = "HIGH";
biasDisplayColor = clrLime;
}
else if (biasScore >= biasThreshold * actualMediumMultiplier) {
dailyBias = 1; // Bullish
confidenceLevel = "MEDIUM";
biasDisplayColor = clrGreen;
}
else if (biasScore <= -biasThreshold * actualHighMultiplier) {
dailyBias = -1; // Strong bearish
confidenceLevel = "HIGH";
biasDisplayColor = clrRed;
}
else if (biasScore <= -biasThreshold * actualMediumMultiplier) {
dailyBias = -1; // Bearish
confidenceLevel = "MEDIUM";
biasDisplayColor = clrCrimson;
}
else if (biasScore > 0) {
dailyBias = 1; // Weak bullish
confidenceLevel = "LOW";
biasDisplayColor = clrDarkGreen;
}
else if (biasScore < 0) {
dailyBias = -1; // Weak bearish
confidenceLevel = "LOW";
biasDisplayColor = clrMaroon;
}
else {
dailyBias = 0; // Neutral
confidenceLevel = "NEUTRAL";
biasDisplayColor = clrGray;
}

// === ENHANCED DISPLAY WITH GOLD-SPECIFIC INDICATORS ===


string biasDirection = "";
if (dailyBias == 1) biasDirection = "BULLISH";
else if (dailyBias == -1) biasDirection = "BEARISH";
else biasDirection = "NEUTRAL";

string instrumentSpecific = "";


if (UseGoldOptimizedSettings && (Symbol() == "XAUUSD" || Symbol() == "GOLD")) {
instrumentSpecific = " [GOLD-OPTIMIZED]";
}

string biasText = "ICT Daily Bias: " + biasDirection + " (" + confidenceLevel +
")" + instrumentSpecific;
string scoreText = "Bias Score: " + DoubleToString(biasScore, 1) + " |
Threshold: " + DoubleToString(biasThreshold, 1);

// Create label for Daily Bias


ObjectDelete("DailyBiasLabel");
ObjectCreate("DailyBiasLabel", OBJ_LABEL, 0, 0, 0);
ObjectSetText("DailyBiasLabel", biasText, 10, "Arial Bold", biasDisplayColor);
ObjectSet("DailyBiasLabel", OBJPROP_CORNER, 1);
ObjectSet("DailyBiasLabel", OBJPROP_XDISTANCE, 10);
ObjectSet("DailyBiasLabel", OBJPROP_YDISTANCE, 20);

// Create label for Bias Score


ObjectDelete("BiasScoreLabel");
ObjectCreate("BiasScoreLabel", OBJ_LABEL, 0, 0, 0);
ObjectSetText("BiasScoreLabel", scoreText, 8, "Arial", biasDisplayColor);
ObjectSet("BiasScoreLabel", OBJPROP_CORNER, 1);
ObjectSet("BiasScoreLabel", OBJPROP_XDISTANCE, 10);
ObjectSet("BiasScoreLabel", OBJPROP_YDISTANCE, 35);

// Fill buffer for the daily bias indicator


int arrowOffset = (int)(MathMax(10, atr / Point / 2));

for (int i = 0; i < rates_total; i++) {


// Only show bias arrow on current bar
if (i == 0) {
if (dailyBias > 0) {
// Place bullish arrow below the bar
DailyBiasBuffer[i] = Low[i] - arrowOffset * Point;
}
else if (dailyBias < 0) {
// Place bearish arrow above the bar
DailyBiasBuffer[i] = High[i] + arrowOffset * Point;
}
else {
DailyBiasBuffer[i] = 0; // No arrow for neutral
}
} else {
DailyBiasBuffer[i] = 0; // Empty for past bars
}
}

// Update cached values


lastBiasCalc = time[0];
cachedBiasScore = biasScore;
}

//+------------------------------------------------------------------+
//| Calculate session ranges and key levels |
//+------------------------------------------------------------------+
void CalculateRanges(const int rates_total, const datetime &time[],
const double &high[], const double &low[]) {
static datetime lastRangeCalc = 0;

// Only recalculate if new bar or new session


if(time[0] == lastRangeCalc && !newLondonSession && !newNYSession && !
newAsianSession) {
// Just update current session if needed
if(time[0] >= londonOpen && time[0] < nyOpen) {
if(high[0] > londonHigh) londonHigh = high[0];
if(low[0] < londonLow) londonLow = low[0];
} else if(time[0] >= nyOpen) {
if(high[0] > nyHigh) nyHigh = high[0];
if(low[0] < nyLow) nyLow = low[0];
} else if(time[0] >= asianOpen && time[0] < asianClose) {
if(high[0] > asianHigh) asianHigh = high[0];
if(low[0] < asianLow) asianLow = low[0];
} else if(time[0] >= newDayStart && time[0] < londonOpen) {
// No range calculation needed since we removed full daily range
}
} else {
// Full recalculation
// Update London session high/low
for (int i = rates_total - 1; i >= 0; i--) {
if (time[i] >= londonOpen && time[i] < nyOpen) {
if (high[i] > londonHigh) londonHigh = high[i];
if (low[i] < londonLow) londonLow = low[i];
}
}

// Update NY session high/low


for (int i = rates_total - 1; i >= 0; i--) {
if (time[i] >= nyOpen) {
if (high[i] > nyHigh) nyHigh = high[i];
if (low[i] < nyLow) nyLow = low[i];
}
}

// Update Asian session high/low


for (int i = rates_total - 1; i >= 0; i--) {
if (time[i] >= asianOpen && time[i] < asianClose) {
if (high[i] > asianHigh) asianHigh = high[i];
if (low[i] < asianLow) asianLow = low[i];
}
}
}

// Fill buffer values for the levels


for (int i = 0; i < rates_total; i++) {
if (time[i] >= londonOpen) {
LondonHighBuffer[i] = londonHigh;
LondonLowBuffer[i] = londonLow;
}

if (time[i] >= nyOpen) {


NYHighBuffer[i] = nyHigh;
NYLowBuffer[i] = nyLow;
}

if (time[i] >= asianOpen) {


AsianHighBuffer[i] = asianHigh;
AsianLowBuffer[i] = asianLow;
}
}

// Update calculation timestamp


lastRangeCalc = time[0];
}

//+------------------------------------------------------------------+
//| Find Fair Value Gaps |
//+------------------------------------------------------------------+
void FindFairValueGaps(const int rates_total, const datetime &time[],
const double &high[], const double &low[],
const double &open[], const double &close[]) {
// Reset FVG buffers
ArrayInitialize(FVGHighBuffer, EMPTY_VALUE);
ArrayInitialize(FVGLowBuffer, EMPTY_VALUE);
// Reset FVG count
fvgCount = 0;
// Only scan the most recent 100 bars for FVGs
int startBar = MathMin(rates_total-1, 100);
// Look for FVGs in the recent data
for (int i = 2; i < startBar; i++) {
// Bullish FVG: Low[i] > High[i+2]
if (low[i] > high[i+2]) {
// Store the FVG
if(fvgCount < 100) {
fvgArray[fvgCount].time = time[i+1];
fvgArray[fvgCount].high = low[i];
fvgArray[fvgCount].low = high[i+2];
fvgArray[fvgCount].direction = 1; // Bullish
fvgCount++;
}
// Fill the buffer for only the relevant bars
for (int j = 0; j <= MathMin(i+1, rates_total - 1); j++) {
FVGHighBuffer[j] = low[i];
FVGLowBuffer[j] = high[i+2];
}
}
// Bearish FVG: High[i] < Low[i+2]
if (high[i] < low[i+2]) {
// Store the FVG
if(fvgCount < 100) {
fvgArray[fvgCount].time = time[i+1];
fvgArray[fvgCount].high = low[i+2];
fvgArray[fvgCount].low = high[i];
fvgArray[fvgCount].direction = -1; // Bearish
fvgCount++;
}
// Fill the buffer for only the relevant bars
for (int j = 0; j <= MathMin(i+1, rates_total - 1); j++) {
FVGHighBuffer[j] = low[i+2];
FVGLowBuffer[j] = high[i];
}
}
// Optimize by limiting calculation to only most relevant FVGs
if (fvgCount >= 5) break;
}
}

//+------------------------------------------------------------------+
//| Draw levels on the chart |
//+------------------------------------------------------------------+
void DrawLevels(const int rates_total, const datetime &time[]) {
// Draw Fibonacci levels if enabled
if (ShowFibo) {
// Draw Fibonacci from London session low to high if both exist
if (ShowLondonFibo && londonHigh > 0 && londonLow < 999999) {
string fiboName = "LondonFibo";
ObjectDelete(fiboName);
ObjectCreate(fiboName, OBJ_FIBO, 0, londonOpen, londonLow, nyOpen,
londonHigh);
ObjectSetInteger(0, fiboName, OBJPROP_COLOR, LondonColor);
ObjectSetInteger(0, fiboName, OBJPROP_STYLE, STYLE_SOLID);
ObjectSetInteger(0, fiboName, OBJPROP_WIDTH, 1);
// Set Fibonacci levels for ICT Optimal Trade Entry (OTE)
ObjectSetDouble(0, fiboName, OBJPROP_LEVELVALUE, 0, 0.0);
ObjectSetDouble(0, fiboName, OBJPROP_LEVELVALUE, 1, 0.382);
ObjectSetDouble(0, fiboName, OBJPROP_LEVELVALUE, 2, 0.5);
ObjectSetDouble(0, fiboName, OBJPROP_LEVELVALUE, 3, 0.618);
ObjectSetDouble(0, fiboName, OBJPROP_LEVELVALUE, 4, 0.786);
ObjectSetDouble(0, fiboName, OBJPROP_LEVELVALUE, 5, 1.0);
// Set level descriptions
ObjectSetString(0, fiboName, OBJPROP_LEVELTEXT, 0, "0.0");
ObjectSetString(0, fiboName, OBJPROP_LEVELTEXT, 1, "38.2% - OTE Zone");
ObjectSetString(0, fiboName, OBJPROP_LEVELTEXT, 2, "50.0% - OTE Zone");
ObjectSetString(0, fiboName, OBJPROP_LEVELTEXT, 3, "61.8% - OTE Zone");
ObjectSetString(0, fiboName, OBJPROP_LEVELTEXT, 4, "78.6% - OTE Zone");
ObjectSetString(0, fiboName, OBJPROP_LEVELTEXT, 5, "100.0%");
// Add tooltip
ObjectSetString(0, fiboName, OBJPROP_TOOLTIP, "Fibonacci retracement
levels for session ranges.");
}

// Draw Fibonacci from NY session low to high if both exist


if (ShowNYFibo && nyHigh > 0 && nyLow < 999999) {
string fiboName = "NYFibo";
ObjectDelete(fiboName);
ObjectCreate(fiboName, OBJ_FIBO, 0, nyOpen, nyLow, Time[0], nyHigh);
ObjectSetInteger(0, fiboName, OBJPROP_COLOR, NYColor);
ObjectSetInteger(0, fiboName, OBJPROP_STYLE, STYLE_SOLID);
ObjectSetInteger(0, fiboName, OBJPROP_WIDTH, 1);
// Set Fibonacci levels for ICT Optimal Trade Entry (OTE)
ObjectSetDouble(0, fiboName, OBJPROP_LEVELVALUE, 0, 0.0);
ObjectSetDouble(0, fiboName, OBJPROP_LEVELVALUE, 1, 0.382);
ObjectSetDouble(0, fiboName, OBJPROP_LEVELVALUE, 2, 0.5);
ObjectSetDouble(0, fiboName, OBJPROP_LEVELVALUE, 3, 0.618);
ObjectSetDouble(0, fiboName, OBJPROP_LEVELVALUE, 4, 0.786);
ObjectSetDouble(0, fiboName, OBJPROP_LEVELVALUE, 5, 1.0);
// Set level descriptions
ObjectSetString(0, fiboName, OBJPROP_LEVELTEXT, 0, "0.0");
ObjectSetString(0, fiboName, OBJPROP_LEVELTEXT, 1, "38.2% - OTE Zone");
ObjectSetString(0, fiboName, OBJPROP_LEVELTEXT, 2, "50.0% - OTE Zone");
ObjectSetString(0, fiboName, OBJPROP_LEVELTEXT, 3, "61.8% - OTE Zone");
ObjectSetString(0, fiboName, OBJPROP_LEVELTEXT, 4, "78.6% - OTE Zone");
ObjectSetString(0, fiboName, OBJPROP_LEVELTEXT, 5, "100.0%");
// Add tooltip
ObjectSetString(0, fiboName, OBJPROP_TOOLTIP, "Fibonacci retracement
levels for session ranges.");
}

// Draw Fibonacci from Asian session low to high if both exist


if (ShowAsianFibo && asianHigh > 0 && asianLow < 999999) {
string fiboName = "AsianFibo";
ObjectDelete(fiboName);
ObjectCreate(fiboName, OBJ_FIBO, 0, asianOpen, asianLow, asianClose,
asianHigh);
ObjectSetInteger(0, fiboName, OBJPROP_COLOR, AsianColor);
ObjectSetInteger(0, fiboName, OBJPROP_STYLE, STYLE_SOLID);
ObjectSetInteger(0, fiboName, OBJPROP_WIDTH, 1);
// Set Fibonacci levels for ICT Optimal Trade Entry (OTE)
ObjectSetDouble(0, fiboName, OBJPROP_LEVELVALUE, 0, 0.0);
ObjectSetDouble(0, fiboName, OBJPROP_LEVELVALUE, 1, 0.382);
ObjectSetDouble(0, fiboName, OBJPROP_LEVELVALUE, 2, 0.5);
ObjectSetDouble(0, fiboName, OBJPROP_LEVELVALUE, 3, 0.618);
ObjectSetDouble(0, fiboName, OBJPROP_LEVELVALUE, 4, 0.786);
ObjectSetDouble(0, fiboName, OBJPROP_LEVELVALUE, 5, 1.0);
// Set level descriptions
ObjectSetString(0, fiboName, OBJPROP_LEVELTEXT, 0, "0.0");
ObjectSetString(0, fiboName, OBJPROP_LEVELTEXT, 1, "38.2% - OTE Zone");
ObjectSetString(0, fiboName, OBJPROP_LEVELTEXT, 2, "50.0% - OTE Zone");
ObjectSetString(0, fiboName, OBJPROP_LEVELTEXT, 3, "61.8% - OTE Zone");
ObjectSetString(0, fiboName, OBJPROP_LEVELTEXT, 4, "78.6% - OTE Zone");
ObjectSetString(0, fiboName, OBJPROP_LEVELTEXT, 5, "100.0%");
// Add tooltip
ObjectSetString(0, fiboName, OBJPROP_TOOLTIP, "Fibonacci retracement
levels for session ranges.");
}
}
}

//+------------------------------------------------------------------+
//| Check for trading setups based on ICT model |
//+------------------------------------------------------------------+
void CheckForTradingSetups(const int rates_total, const datetime &time[],
const double &high[], const double &low[],
const double &open[], const double &close[]) {
// Get current price
double currentPrice = Close[0];

// Only check if we're past London open


if (Time[0] < londonOpen) return;

// Check for London Session Liquidity Sweep and Reversal


if (Time[0] >= londonOpen && Time[0] < nyOpen) {
// Check for liquidity sweep of London session high
if (high[0] > londonHigh && high[1] <= londonHigh) {
// Liquidity sweep of London high occurred
if (AlertsOn) Alert("Liquidity sweep of London high occurred at London
session");

// If daily bias is bearish, this is a good opportunity


if (dailyBias < 0) {
// Check for potential market structure shift down
if (close[0] < open[0]) {
Alert("ICT Setup: Bearish London high sweep aligned with daily
bias");
}
}
}

// Check for liquidity sweep of London session low


if (low[0] < londonLow && low[1] >= londonLow) {
// Liquidity sweep of London low occurred
if (AlertsOn) Alert("Liquidity sweep of London low occurred at London
session");

// If daily bias is bullish, this is a good opportunity


if (dailyBias > 0) {
// Check for potential market structure shift up
if (close[0] > open[0]) {
Alert("ICT Setup: Bullish London low sweep aligned with daily
bias");
}
}
}
}

// Check for NY Session Liquidity Sweep and Reversal


if (Time[0] >= nyOpen) {
// Check for liquidity sweep of NY session high
if (high[0] > nyHigh && high[1] <= nyHigh) {
// Liquidity sweep of NY high occurred
if (AlertsOn) Alert("Liquidity sweep of NY high occurred at NY session");

// If daily bias is bearish, this is a good opportunity


if (dailyBias < 0) {
// Check for potential market structure shift down
if (close[0] < open[0]) {
Alert("ICT Setup: Bearish NY high sweep aligned with daily bias");
}
}
}

// Check for liquidity sweep of NY session low


if (low[0] < nyLow && low[1] >= nyLow) {
// Liquidity sweep of NY low occurred
if (AlertsOn) Alert("Liquidity sweep of NY low occurred at NY session");

// If daily bias is bullish, this is a good opportunity


if (dailyBias > 0) {
// Check for potential market structure shift up
if (close[0] > open[0]) {
Alert("ICT Setup: Bullish NY low sweep aligned with daily bias");
}
}
}

// Check for OTE zones in relation to London range


double londonRange = londonHigh - londonLow;
double fib50 = londonLow + londonRange * 0.5;
double fib618 = londonLow + londonRange * 0.618;
double fib382 = londonLow + londonRange * 0.382;

// Check if price is near OTE zones


if ((currentPrice >= fib382 * 0.99 && currentPrice <= fib382 * 1.01) ||
(currentPrice >= fib50 * 0.99 && currentPrice <= fib50 * 1.01) ||
(currentPrice >= fib618 * 0.99 && currentPrice <= fib618 * 0.01)) {

if (AlertsOn) {
if (dailyBias > 0 && currentPrice <= fib618 * 1.01) {
Alert("ICT Bullish OTE: Price testing bullish OTE zone with
bullish bias");
}
else if (dailyBias < 0 && currentPrice >= fib382 * 0.99) {
Alert("ICT Bearish OTE: Price testing bearish OTE zone with
bearish bias");
}
else {
Alert("Price is testing ICT Optimal Trade Entry zone");
}
}
}

// Check for Asian Session OTE entries


double asianRange = asianHigh - asianLow;
double asianFib50 = asianLow + asianRange * 0.5;
double asianFib618 = asianLow + asianRange * 0.618;
double asianFib382 = asianLow + asianRange * 0.382;

// Check if price is near Asian OTE zones during London or NY


if ((currentPrice >= asianFib382 * 0.99 && currentPrice <= asianFib382 *
1.01) ||
(currentPrice >= asianFib50 * 0.99 && currentPrice <= asianFib50 * 1.01)
||
(currentPrice >= asianFib618 * 0.99 && currentPrice <= asianFib618 *
0.01)) {

if (AlertsOn) {
if (dailyBias > 0 && currentPrice <= asianFib618 * 1.01) {
Alert("ICT Asian Bullish OTE: Price testing Asian OTE zone with
bullish bias");
}
else if (dailyBias < 0 && currentPrice >= asianFib382 * 0.99) {
Alert("ICT Asian Bearish OTE: Price testing Asian OTE zone with
bearish bias");
}
else {
Alert("Price is testing Asian session ICT Optimal Trade Entry
zone");
}
}
}
}

// Check if price is approaching any active FVG aligned with daily bias
for (int i = 0; i < fvgCount; i++) {
// Only consider FVGs that align with daily bias
if ((fvgArray[i].direction == 1 && dailyBias > 0) ||
(fvgArray[i].direction == -1 && dailyBias < 0)) {

if (currentPrice >= fvgArray[i].low && currentPrice <= fvgArray[i].high) {


string fvgDirection = fvgArray[i].direction > 0 ? "Bullish" :
"Bearish";
if (AlertsOn) Alert("ICT Setup: Price testing " + fvgDirection + " Fair
Value Gap aligned with daily bias");
}
}
}
}

//+------------------------------------------------------------------+
//| Detect market regime |
//+------------------------------------------------------------------+
void DetectMarketRegime(const int rates_total) {
// Calculate ADX
adxValue = (double)iADX(Symbol(), (ENUM_TIMEFRAMES)PERIOD_CURRENT, 14,
(int)PRICE_CLOSE, (int)MODE_MAIN, 0);

// Calculate Bollinger Bands


upperBB = (double)iBands(Symbol(), (ENUM_TIMEFRAMES)PERIOD_CURRENT,
(int)BBPeriod, (int)BBDeviation, (int)BBDeviation, (int)PRICE_CLOSE,
(int)MODE_UPPER, 0);
lowerBB = (double)iBands(Symbol(), (ENUM_TIMEFRAMES)PERIOD_CURRENT,
(int)BBPeriod, (int)BBDeviation, (int)BBDeviation, (int)PRICE_CLOSE,
(int)MODE_LOWER, 0);
// Calculate middle band manually as SMA
middleBB = (double)iMA(Symbol(), (ENUM_TIMEFRAMES)PERIOD_CURRENT, (int)BBPeriod,
0, (int)MODE_SMA, (int)PRICE_CLOSE, 0);

// Determine market regime


if (adxValue > TrendStrengthThreshold) {
// Trending market
double diPlus = (double)iADX(Symbol(), (ENUM_TIMEFRAMES)PERIOD_CURRENT, 14,
(int)PRICE_CLOSE, (int)MODE_PLUSDI, 0);
double diMinus = (double)iADX(Symbol(), (ENUM_TIMEFRAMES)PERIOD_CURRENT, 14,
(int)PRICE_CLOSE, (int)MODE_MINUSDI, 0);

if (diPlus > diMinus) {


marketRegime = 1; // Bullish trend
} else {
marketRegime = -1; // Bearish trend
}
} else {
// Ranging market
marketRegime = 0;
}
}

//+------------------------------------------------------------------+
//| Visualize market regime |
//+------------------------------------------------------------------+
void VisualizeMarketRegime(const int rates_total, const datetime &time[]) {
// Draw background color based on market regime
if(marketRegime == 1) { // Bullish trend
DrawBackground(time[0], clrGreen);
} else if(marketRegime == -1) { // Bearish trend
DrawBackground(time[0], clrRed);
} else { // Ranging
DrawBackground(time[0], clrYellow);
}

// Display text label indicating market regime


string regimeText = "Market Regime: ";
if(marketRegime == 1) {
regimeText += "Bullish Trend";
} else if(marketRegime == -1) {
regimeText += "Bearish Trend";
} else {
regimeText += "Ranging";
}

// Create or update regime label


ObjectDelete("RegimeLabel");
ObjectCreate("RegimeLabel", OBJ_LABEL, 0, 0, 0);
ObjectSetText("RegimeLabel", regimeText, 10, "Arial", clrWhite);
ObjectSet("RegimeLabel", OBJPROP_CORNER, 1);
ObjectSet("RegimeLabel", OBJPROP_XDISTANCE, 10);
ObjectSet("RegimeLabel", OBJPROP_YDISTANCE, 60);
}

//+------------------------------------------------------------------+
//| Draw background color |
//+------------------------------------------------------------------+
void DrawBackground(datetime currentTime, color bgColor) {
string backgroundName = "MarketRegimeBackground";
ObjectDelete(backgroundName);
ObjectCreate(backgroundName, OBJ_RECTANGLE, 0, D'2023.01.01', 0, TimeCurrent(),
0);
ObjectSetInteger(0, backgroundName, OBJPROP_COLOR, bgColor);
ObjectSetInteger(0, backgroundName, OBJPROP_BACK, true);
ObjectSetInteger(0, backgroundName, OBJPROP_SELECTABLE, false);
ObjectSetInteger(0, backgroundName, OBJPROP_ZORDER, 0);
}

//+------------------------------------------------------------------+
//| Detect price action patterns with enhanced confirmation |
//+------------------------------------------------------------------+
enum PriceActionPattern {
NO_PATTERN,
BULLISH_PIN_BAR,
BEARISH_PIN_BAR,
BULLISH_ENGULFING,
BEARISH_ENGULFING,
INSIDE_BAR,
BREAKOUT_BAR,
BULLISH_HAMMER,
BEARISH_HANGING_MAN,
BULLISH_SWALLOW,
BEARISH_SWALLOW
};

PriceActionPattern DetectPriceActionPattern(
const int rates_total,
const datetime &time[],
const double &open[],
const double &high[],
const double &low[],
const double &close[],
const long &volume[]
) {
PriceActionPattern pattern = NO_PATTERN;
double currentBody = MathAbs(close[0] - open[0]);
double previousBody = MathAbs(close[1] - open[1]);
double currentRange = high[0] - low[0];
double previousRange = high[1] - low[1];
double atr = iATR(Symbol(), PERIOD_CURRENT, 14, 0);

// Minimum size requirements


double minPinBarSize = 2 * atr;
double minEngulfingSize = 1.5 * atr;
double minInsideBarSize = 0.5 * atr;
double minBreakoutSize = 2 * atr;

// Detect pin bars with enhanced confirmation


if (currentBody > 0 && currentRange > 0) {
double upperWick = high[0] - MathMax(open[0], close[0]);
double lowerWick = MathMin(open[0], close[0]) - low[0];

// Bullish pin bar


if (lowerWick >= 2 * currentBody && lowerWick >= 0.6 * currentRange &&
close[0] > open[0] && close[0] < open[1] &&
currentRange >= minPinBarSize &&
close[1] > open[1]) {
pattern = BULLISH_PIN_BAR;
}

// Bearish pin bar


if (upperWick >= 2 * currentBody && upperWick >= 0.6 * currentRange &&
close[0] < open[0] && close[0] > open[1] &&
currentRange >= minPinBarSize &&
close[1] < open[1]) {
pattern = BEARISH_PIN_BAR;
}
}

// Detect engulfing patterns with confirmation


if (close[0] > open[0] && close[1] < open[1] &&
close[0] > open[1] && close[0] > high[1] &&
currentBody >= minEngulfingSize &&
close[2] > open[2]) {
pattern = BULLISH_ENGULFING;
} else if (close[0] < open[0] && close[1] > open[1] &&
open[0] < close[1] && open[0] < low[1] &&
currentBody >= minEngulfingSize &&
close[2] < open[2]) {
pattern = BEARISH_ENGULFING;
}

// Detect inside bars with breakout confirmation


if (high[0] < high[1] && low[0] > low[1] &&
currentRange >= minInsideBarSize &&
(high[2] > high[1] || low[2] < low[1])) {
pattern = INSIDE_BAR;
}

// Detect breakout bars with confirmation


if (high[0] > high[1] && low[0] < low[1] &&
currentRange >= minBreakoutSize &&
(high[0] > high[2] || low[0] < low[2])) {
pattern = BREAKOUT_BAR;
}

// Detect hammer and hanging man patterns


if (currentBody > 0 && currentRange > 0) {
double upperWick = high[0] - MathMax(open[0], close[0]);
double lowerWick = MathMin(open[0], close[0]) - low[0];

// Bullish hammer
if (lowerWick >= 2 * currentBody && lowerWick >= 0.6 * currentRange &&
close[0] > open[0] && close[0] < open[1] &&
currentRange >= minPinBarSize &&
close[1] > open[1]) {
pattern = BULLISH_HAMMER;
}

// Bearish hanging man


if (lowerWick >= 2 * currentBody && lowerWick >= 0.6 * currentRange &&
close[0] < open[0] && close[0] > open[1] &&
currentRange >= minPinBarSize &&
close[1] < open[1]) {
pattern = BEARISH_HANGING_MAN;
}
}

// Detect bullish and bearish swallowing patterns


if (close[0] > open[0] && close[0] > high[1] && open[0] < low[1] &&
currentBody >= minEngulfingSize &&
close[2] > open[2]) {
pattern = BULLISH_SWALLOW;
} else if (close[0] < open[0] && close[0] < low[1] && open[0] > high[1] &&
currentBody >= minEngulfingSize &&
close[2] < open[2]) {
pattern = BEARISH_SWALLOW;
}

return pattern;
}

//+------------------------------------------------------------------+
//| Draw price action arrows with enhanced confirmation |
//+------------------------------------------------------------------+
void DrawPriceActionArrows(
const int rates_total,
const datetime &time[],
const double &open[],
const double &high[],
const double &low[],
const double &close[],
const long &volume[]
) {
PriceActionPattern pattern = DetectPriceActionPattern(rates_total, time, open,
high, low, close, volume);

double arrowPrice = 0; // Initialize arrowPrice here

// Only draw arrow if pattern is detected and confirmed


if (pattern != NO_PATTERN) {
int arrowCode = 0;
color arrowColor;

switch(pattern) {
case BULLISH_PIN_BAR:
case BULLISH_HAMMER:
case BULLISH_SWALLOW:
arrowPrice = low[0] - (high[0] - low[0]) * 0.3;
arrowCode = 233; // Up arrow
arrowColor = BuyArrowColor;
break;

case BEARISH_PIN_BAR:
case BEARISH_HANGING_MAN:
case BEARISH_SWALLOW:
arrowPrice = high[0] + (high[0] - low[0]) * 0.3;
arrowCode = 234; // Down arrow
arrowColor = SellArrowColor;
break;

case BULLISH_ENGULFING:
arrowPrice = low[0] - (high[0] - low[0]) * 0.2;
arrowCode = 22; // Hollow up arrow
arrowColor = BuyArrowColor;
break;

case BEARISH_ENGULFING:
arrowPrice = high[0] + (high[0] - low[0]) * 0.2;
arrowCode = 23; // Hollow down arrow
arrowColor = SellArrowColor;
break;

case INSIDE_BAR:
arrowPrice = (high[0] + low[0]) / 2;
arrowCode = 162; // Diamond
arrowColor = clrOrange;
break;

case BREAKOUT_BAR:
if (high[0] > high[1]) {
arrowPrice = high[1] + (high[0] - high[1]) * 0.5;
arrowCode = 24; // Small up arrow
arrowColor = BuyArrowColor;
} else {
arrowPrice = low[1] - (low[1] - low[0]) * 0.5;
arrowCode = 25; // Small down arrow
arrowColor = SellArrowColor;
}
break;
}

// Additional confirmation from subsequent bars


if (pattern == BULLISH_PIN_BAR || pattern == BULLISH_HAMMER || pattern ==
BULLISH_SWALLOW ||
pattern == BULLISH_ENGULFING) {
if (close[1] > open[1] && high[1] > high[0]) {
BuySignalBuffer[0] = arrowPrice;
SetIndexArrow(9, arrowCode);
}
} else if (pattern == BEARISH_PIN_BAR || pattern == BEARISH_HANGING_MAN ||
pattern == BEARISH_SWALLOW ||
pattern == BEARISH_ENGULFING) {
if (close[1] < open[1] && low[1] < low[0]) {
SellSignalBuffer[0] = arrowPrice;
SetIndexArrow(10, arrowCode);
}
} else if (pattern == INSIDE_BAR || pattern == BREAKOUT_BAR) {
// For neutral patterns, use a different buffer or visual style
// This would require adding additional buffers to the indicator
}
}

// Clear previous arrows for all bars except the current one
for (int i = 1; i < rates_total; i++) {
BuySignalBuffer[i] = EMPTY_VALUE;
SellSignalBuffer[i] = EMPTY_VALUE;
}

// Ensure the current bar's arrow is displayed


if (pattern != NO_PATTERN) {
BuySignalBuffer[0] = arrowPrice;
SellSignalBuffer[0] = arrowPrice;
}
}

//+------------------------------------------------------------------+
//| Detect and draw candlestick patterns |
//+------------------------------------------------------------------+
void DetectAndDrawPatterns(const int rates_total, const datetime &time[],
const double &open[], const double &high[],
const double &low[], const double &close[]) {
// Clear previous pattern arrows for all bars except the current one
if (rates_total < 1) return; // Added check for rates_total

for (int i = 1; i < rates_total; i++) {


BullishPatternBuffer[i] = EMPTY_VALUE;
BearishPatternBuffer[i] = EMPTY_VALUE;
}

// Detect patterns on the most recent bars


for (int i = rates_total - 1; i >= MathMax(0, rates_total - PatternLookback);
i--) {
if (DetectBullishPattern(i, time, open, high, low, close)) {
// Place bullish pattern arrow below the bar
BullishPatternBuffer[i] = low[i] - (high[i] - low[i]) * 0.1;
}

if (DetectBearishPattern(i, time, open, high, low, close)) {


// Place bearish pattern arrow above the bar
BearishPatternBuffer[i] = high[i] + (high[i] - low[i]) * 0.1;
}
}

// Ensure the current bar's pattern arrows are displayed


if (DetectBullishPattern(0, time, open, high, low, close)) {
BullishPatternBuffer[0] = low[0] - (high[0] - low[0]) * 0.1;
}

if (DetectBearishPattern(0, time, open, high, low, close)) {


BearishPatternBuffer[0] = high[0] + (high[0] - low[0]) * 0.1;
}
}

//+------------------------------------------------------------------+
//| Detect bullish candlestick patterns |
//+------------------------------------------------------------------+
bool DetectBullishPattern(const int index, const datetime &time[],
const double &open[], const double &high[],
const double &low[], const double &close[]) {
// Hammer pattern
if (IsHammer(index, open, high, low, close)) {
return true;
}

// Inverted Hammer pattern


if (IsInvertedHammer(index, open, high, low, close)) {
return true;
}

// Bullish Engulfing pattern


if (IsBullishEngulfing(index, open, high, low, close)) {
return true;
}

// Morning Star pattern


if (IsMorningStar(index, open, high, low, close)) {
return true;
}

return false;
}

//+------------------------------------------------------------------+
//| Detect bearish candlestick patterns |
//+------------------------------------------------------------------+
bool DetectBearishPattern(const int index, const datetime &time[],
const double &open[], const double &high[],
const double &low[], const double &close[]) {
// Hanging Man pattern
if (IsHangingMan(index, open, high, low, close)) {
return true;
}

// Shooting Star pattern


if (IsShootingStar(index, open, high, low, close)) {
return true;
}

// Bearish Engulfing pattern


if (IsBearishEngulfing(index, open, high, low, close)) {
return true;
}

// Evening Star pattern


if (IsEveningStar(index, open, high, low, close)) {
return true;
}

return false;
}

//+------------------------------------------------------------------+
//| Check for Hammer pattern |
//+------------------------------------------------------------------+
bool IsHammer(int index, const double &open[], const double &high[],
const double &low[], const double &close[]) {
double body = MathAbs(close[index] - open[index]);
double lowerWick = open[index] - low[index];

if (body > 0 && lowerWick >= 2 * body && lowerWick >= 0.6 * (high[index] -
low[index])) {
return true;
}
return false;
}

//+------------------------------------------------------------------+
//| Check for Inverted Hammer pattern |
//+------------------------------------------------------------------+
bool IsInvertedHammer(int index, const double &open[], const double &high[],
const double &low[], const double &close[]) {
double body = MathAbs(close[index] - open[index]);
double upperWick = high[index] - close[index];

if (body > 0 && upperWick >= 2 * body && upperWick >= 0.6 * (high[index] -
low[index])) {
return true;
}
return false;
}

//+------------------------------------------------------------------+
//| Check for Bullish Engulfing pattern |
//+------------------------------------------------------------------+
bool IsBullishEngulfing(int index, const double &open[], const double &high[],
const double &low[], const double &close[]) {
if (close[index] > open[index] && close[index-1] < open[index-1] &&
close[index] > open[index-1] && close[index] > high[index-1]) {
return true;
}
return false;
}

//+------------------------------------------------------------------+
//| Check for Morning Star pattern |
//+------------------------------------------------------------------+
bool IsMorningStar(int index, const double &open[], const double &high[],
const double &low[], const double &close[]) {
if (index < 2) return false;

if (close[index-2] < open[index-2] &&


MathAbs(close[index-1] - open[index-1]) < 0.2 * (high[index-1] - low[index-
1]) &&
close[index] > open[index] &&
close[index] > (open[index-2] + close[index-2]) / 2) {
return true;
}
return false;
}

//+------------------------------------------------------------------+
//| Check for Hanging Man pattern |
//+------------------------------------------------------------------+
bool IsHangingMan(int index, const double &open[], const double &high[],
const double &low[], const double &close[]) {
double body = MathAbs(close[index] - open[index]);
double lowerWick = open[index] - low[index];

if (body > 0 && lowerWick >= 2 * body && lowerWick >= 0.6 * (high[index] -
low[index]) &&
close[index] < open[index] &&
close[index] > (high[index-1] + low[index-1]) / 2) {
return true;
}
return false;
}

//+------------------------------------------------------------------+
//| Check for Shooting Star pattern |
//+------------------------------------------------------------------+
bool IsShootingStar(int index, const double &open[], const double &high[],
const double &low[], const double &close[]) {
double body = MathAbs(close[index] - open[index]);
double upperWick = high[index] - close[index];

if (body > 0 && upperWick >= 2 * body && upperWick >= 0.6 * (high[index] -
low[index]) &&
close[index] < open[index] &&
close[index] > (high[index-1] + low[index-1]) / 2) {
return true;
}
return false;
}

//+------------------------------------------------------------------+
//| Check for Bearish Engulfing pattern |
//+------------------------------------------------------------------+
bool IsBearishEngulfing(int index, const double &open[], const double &high[],
const double &low[], const double &close[]) {
if (close[index] < open[index] && close[index-1] > open[index-1] &&
close[index] < open[index-1] && close[index] < low[index-1]) {
return true;
}
return false;
}

//+------------------------------------------------------------------+
//| Check for Evening Star pattern |
//+------------------------------------------------------------------+
bool IsEveningStar(int index, const double &open[], const double &high[],
const double &low[], const double &close[]) {
if (index < 2) return false;

if (close[index-2] > open[index-2] &&


MathAbs(close[index-1] - open[index-1]) < 0.2 * (high[index-1] - low[index-
1]) &&
close[index] < open[index] &&
close[index] < (open[index-2] + close[index-2]) / 2) {
return true;
}
return false;
}

//+------------------------------------------------------------------+
//| Calculate RSI values |
//+------------------------------------------------------------------+
void CalculateRSI(const int rates_total, const datetime &time[], const double
&close[]) {
for (int i = 0; i < rates_total; i++) {
RSIValues[i] = iRSI(Symbol(), Period(), RSIDivergencePeriod, PRICE_CLOSE, i);
}
}

//+------------------------------------------------------------------+
//| Detect and draw RSI divergence |
//+------------------------------------------------------------------+
void DetectRSIDivergence(const int rates_total, const datetime &time[],
const double &high[], const double &low[],
const double &close[]) {
// Clear previous divergence arrows for all bars except the current one
for (int i = 1; i < rates_total; i++) {
BullishDivergenceBuffer[i] = EMPTY_VALUE;
BearishDivergenceBuffer[i] = EMPTY_VALUE;
}

// Detect divergence on the most recent bars


for (int i = rates_total - 1; i >= MathMax(0, rates_total -
RSIDivergenceLookback); i--) {
if (DetectBullishRSIDivergence(i, time, low, RSIValues)) {
// Place bullish divergence arrow below the bar
BullishDivergenceBuffer[i] = low[i] - (high[i] - low[i]) * 0.1;
}

if (DetectBearishRSIDivergence(i, time, high, RSIValues)) {


// Place bearish divergence arrow above the bar
BearishDivergenceBuffer[i] = high[i] + (high[i] - low[i]) * 0.1;
}
}

// Ensure the current bar's divergence arrows are displayed


if (DetectBullishRSIDivergence(0, time, low, RSIValues)) {
BullishDivergenceBuffer[0] = low[0] - (high[0] - low[0]) * 0.1;
}

if (DetectBearishRSIDivergence(0, time, high, RSIValues)) {


BearishDivergenceBuffer[0] = high[0] + (high[0] - low[0]) * 0.1;
}
}

//+------------------------------------------------------------------+
//| Detect bullish RSI divergence |
//+------------------------------------------------------------------+
bool DetectBullishRSIDivergence(const int index, const datetime &time[],
const double &low[], const double &rsiValues[]) {
// Check if we have enough data to look back
if (index < RSIDivergenceLookback || index < 0) return false;

// Check for lower price lows


if (low[index] >= low[index - RSIDivergenceLookback]) return false;

// Check for higher RSI lows


double currentRSILow = rsiValues[index];
double previousRSILow = rsiValues[index - RSIDivergenceLookback];

if (currentRSILow <= previousRSILow) return false;

// Check for sufficient divergence


if (previousRSILow - currentRSILow < RSIDivergenceThreshold) return false;

return true;
}

//+------------------------------------------------------------------+
//| Detect bearish RSI divergence |
//+------------------------------------------------------------------+
bool DetectBearishRSIDivergence(const int index, const datetime &time[],
const double &high[], const double &rsiValues[]) {
// Check if we have enough data to look back
if (index < RSIDivergenceLookback || index < 0) return false;

// Check for higher price highs


if (high[index] <= high[index - RSIDivergenceLookback]) return false;

// Check for lower RSI highs


double currentRSIHigh = rsiValues[index];
double previousRSIHigh = rsiValues[index - RSIDivergenceLookback];

if (currentRSIHigh >= previousRSIHigh) return false;

// Check for sufficient divergence


if (previousRSIHigh - currentRSIHigh < RSIDivergenceThreshold) return false;

return true;
}

//+------------------------------------------------------------------+
//| Custom indicator deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason) {
// Clean up objects
ObjectDelete("LondonOpen");
ObjectDelete("NYOpen");
ObjectDelete("LondonFibo");
ObjectDelete("NYFibo");
ObjectDelete("AsianFibo");
ObjectDelete("DailyBiasLabel");
ObjectDelete("TimeZoneLabel");
ObjectDelete("AsianOpen");
ObjectDelete("RegimeLabel");

// Clean up timer
EventKillTimer();
}

//+------------------------------------------------------------------+
//| Timer function for optimal refreshing |
//+------------------------------------------------------------------+
void OnTimer() {
// Refresh indicator only during market hours
datetime currentTime = TimeCurrent();
int currentHour = TimeHour(currentTime);
int currentMinute = TimeMinute(currentTime);

// Only refresh during active trading hours (Asian, London, NY sessions)


// Avoid unnecessary calculations during off-hours
if((currentHour >= 0 && currentHour < 17) || // 0:00-17:00 GMT
(currentHour == 17 && currentMinute < 30)) { // Until 17:30 GMT
ChartRedraw(); // Force indicator recalculation
}
}

//+------------------------------------------------------------------+
//| Check if it's a new day |
//+------------------------------------------------------------------+
bool IsNewDay(datetime currentTime, datetime lastTime) {
return (TimeDay(currentTime) != TimeDay(lastTime)) ||
(TimeMonth(currentTime) != TimeMonth(lastTime)) ||
(TimeYear(currentTime) != TimeYear(lastTime));
}
//+------------------------------------------------------------------+
//| Detect recent price trend |
//+------------------------------------------------------------------+
int DetectPriceTrend(const int rates_total, const double &high[], const double
&low[]) {
int trend = 0; // 0 for no clear trend, 1 for bullish, -1 for bearish

// Check for bullish trend: higher highs and higher lows


if (high[0] > high[1] && high[1] > high[2] &&
low[0] > low[1] && low[1] > low[2]) {
trend = 1;
}

// Check for bearish trend: lower highs and lower lows


if (high[0] < high[1] && high[1] < high[2] &&
low[0] < low[1] && low[1] < low[2]) {
trend = -1;
}

return trend;
}
//+------------------------------------------------------------------+

You might also like