Files
MQL5Data/Documents/BKP/Qwen/MajorStructure_Bias_EA_1.1.mq5
T
2026-07-12 21:26:53 +03:30

312 lines
11 KiB
Plaintext

//+------------------------------------------------------------------+
//| MajorStructure_Zones_EA.mq5 |
//| Step 1.5: BOS Confirmation + Zone Drawing + Bias |
//+------------------------------------------------------------------+
#property copyright "Professional Trader & AI Assistant"
#property version "1.50"
#property strict
//--- Input Parameters
input int MinorPivotLookback = 3; // تعداد کندل چپ/راست برای شناسایی مینور (در 15m = 3 یعنی 45 دقیقه)
input int MaxBarsToScan = 500; // حداکثر کندل‌های 4H برای جستجو
input color BullishZoneColor = clrLime; // رنگ ناحیه کف ماژور (حمایت)
input color BearishZoneColor = clrRed; // رنگ ناحیه سقف ماژور (مقاومت)
input int ZoneTransparency = 80; // شفافیت ناحیه (0-255)
//--- Global Variables
// نواحی ماژور (High و Low کندل مربوطه)
double majorLowZoneHigh = 0, majorLowZoneLow = 0;
datetime majorLowZoneTime = 0;
int majorLowBarIndex = -1;
double majorHighZoneHigh = 0, majorHighZoneLow = 0;
datetime majorHighZoneTime = 0;
int majorHighBarIndex = -1;
string biasDirection = "NEUTRAL";
// نام آبجکت‌های گرافیکی
string lowZoneName = "MajorLowZone";
string highZoneName = "MajorHighZone";
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
Print("EA v1.5 Initialized. Scanning for BOS-confirmed Major Zones...");
return (INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
// پاک کردن تمام آبجکت‌های رسم شده
ObjectDelete(0, lowZoneName);
ObjectDelete(0, highZoneName);
Comment("");
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
// فقط یک بار در هر کندل جدید 4 ساعته محاسبات را انجام می‌دهیم
static datetime lastBarTime = 0;
datetime currentBarTime = iTime(_Symbol, PERIOD_H4, 0);
if (lastBarTime == currentBarTime)
{
// در تیک‌های میانی، فقط ناحیه جاری را تا زمان حال گسترش می‌دهیم
ExtendZonesToCurrentTime();
return;
}
lastBarTime = currentBarTime;
// 1. دریافت داده‌های تایم فریم 4 ساعته
double high[], low[], close[];
datetime time[];
ArraySetAsSeries(high, true);
ArraySetAsSeries(low, true);
ArraySetAsSeries(close, true);
ArraySetAsSeries(time, true);
int copied = CopyHigh(_Symbol, PERIOD_H4, 0, MaxBarsToScan, high);
CopyLow(_Symbol, PERIOD_H4, 0, MaxBarsToScan, low);
CopyClose(_Symbol, PERIOD_H4, 0, MaxBarsToScan, close);
CopyTime(_Symbol, PERIOD_H4, 0, MaxBarsToScan, time);
if (copied <= 0)
{
Print("Error copying 4H data.");
return;
}
// 2. اسکن تاریخی برای شناسایی BOS و نواحی ماژور
ScanForMajorZones(high, low, close, time, copied);
// 3. تعیین بایاس
DetermineBias();
// 4. رسم نواحی روی چارت
DrawMajorZones();
// 5. نمایش داشبورد
DisplayDashboard();
}
//+------------------------------------------------------------------+
//| اسکن تاریخی برای شناسایی نواحی ماژور با تاییدیه BOS |
//+------------------------------------------------------------------+
void ScanForMajorZones(double &high[], double &low[], double &close[], datetime &time[], int total)
{
// ریست کردن متغیرها
majorLowBarIndex = -1;
majorHighBarIndex = -1;
int lastMinorHighIdx = -1;
int lastMinorLowIdx = -1;
// حلقه از گذشته به حال (اندیس بزرگ به کوچک)
for (int i = total - MinorPivotLookback - 1; i >= MinorPivotLookback; i--)
{
// بررسی آیا کندل i یک سقف مینور است
if (IsMinorPivot(high, i, true))
{
lastMinorHighIdx = i;
}
// بررسی آیا کندل i یک کف مینور است
if (IsMinorPivot(low, i, false))
{
lastMinorLowIdx = i;
}
// بررسی BOS صعودی: آیا Close کندل i بالاتر از آخرین سقف مینور است؟
if (lastMinorHighIdx != -1 && i < lastMinorHighIdx && close[i] > high[lastMinorHighIdx])
{
// BOS صعودی رخ داد -> کف مینور قبلی حالا کف ماژور تایید شده است
if (lastMinorLowIdx != -1 && lastMinorLowIdx > lastMinorHighIdx)
{
majorLowBarIndex = lastMinorLowIdx;
majorLowZoneHigh = high[lastMinorLowIdx];
majorLowZoneLow = low[lastMinorLowIdx];
majorLowZoneTime = time[lastMinorLowIdx];
}
}
// بررسی BOS نزولی: آیا Close کندل i پایین‌تر از آخرین کف مینور است؟
if (lastMinorLowIdx != -1 && i < lastMinorLowIdx && close[i] < low[lastMinorLowIdx])
{
// BOS نزولی رخ داد -> سقف مینور قبلی حالا سقف ماژور تایید شده است
if (lastMinorHighIdx != -1 && lastMinorHighIdx > lastMinorLowIdx)
{
majorHighBarIndex = lastMinorHighIdx;
majorHighZoneHigh = high[lastMinorHighIdx];
majorHighZoneLow = low[lastMinorHighIdx];
majorHighZoneTime = time[lastMinorHighIdx];
}
}
}
}
//+------------------------------------------------------------------+
//| بررسی آیا کندل idx یک پراوت مینور است |
//+------------------------------------------------------------------+
bool IsMinorPivot(double &data[], int idx, bool isHigh)
{
for (int j = 1; j <= MinorPivotLookback; j++)
{
if (isHigh)
{
if (data[idx] <= data[idx - j] || data[idx] <= data[idx + j])
return false;
}
else
{
if (data[idx] >= data[idx - j] || data[idx] >= data[idx + j])
return false;
}
}
return true;
}
//+------------------------------------------------------------------+
//| تعیین بایاس بر اساس قانون تازگی |
//+------------------------------------------------------------------+
void DetermineBias()
{
if (majorHighBarIndex == -1 && majorLowBarIndex == -1)
{
biasDirection = "NEUTRAL (No Major Structure)";
return;
}
if (majorHighBarIndex == -1)
{
biasDirection = "BULLISH (Only Major Low Found)";
return;
}
if (majorLowBarIndex == -1)
{
biasDirection = "BEARISH (Only Major High Found)";
return;
}
// در آرایه سری، اندیس کوچکتر = زمان جدیدتر
if (majorHighBarIndex < majorLowBarIndex)
{
biasDirection = "BEARISH (Short Only)";
}
else if (majorLowBarIndex < majorHighBarIndex)
{
biasDirection = "BULLISH (Long Only)";
}
else
{
biasDirection = "NEUTRAL (Equal Time)";
}
}
//+------------------------------------------------------------------+
//| رسم نواحی ماژور روی چارت |
//+------------------------------------------------------------------+
void DrawMajorZones()
{
// رسم ناحیه کف ماژور (حمایت)
if (majorLowBarIndex != -1)
{
if (ObjectFind(0, lowZoneName) < 0)
{
ObjectCreate(0, lowZoneName, OBJ_RECTANGLE, 0, 0, 0, 0, 0);
ObjectSetInteger(0, lowZoneName, OBJPROP_COLOR, BullishZoneColor);
ObjectSetInteger(0, lowZoneName, OBJPROP_FILL, true);
ObjectSetInteger(0, lowZoneName, OBJPROP_BACK, true);
}
ObjectSetDouble(0, lowZoneName, OBJPROP_PRICE, 0, majorLowZoneHigh);
ObjectSetDouble(0, lowZoneName, OBJPROP_PRICE, 1, majorLowZoneLow);
ObjectSetInteger(0, lowZoneName, OBJPROP_TIME, 0, majorLowZoneTime);
ObjectSetInteger(0, lowZoneName, OBJPROP_TIME, 1, TimeCurrent());
}
// رسم ناحیه سقف ماژور (مقاومت)
if (majorHighBarIndex != -1)
{
if (ObjectFind(0, highZoneName) < 0)
{
ObjectCreate(0, highZoneName, OBJ_RECTANGLE, 0, 0, 0, 0, 0);
ObjectSetInteger(0, highZoneName, OBJPROP_COLOR, BearishZoneColor);
ObjectSetInteger(0, highZoneName, OBJPROP_FILL, true);
ObjectSetInteger(0, highZoneName, OBJPROP_BACK, true);
}
ObjectSetDouble(0, highZoneName, OBJPROP_PRICE, 0, majorHighZoneHigh);
ObjectSetDouble(0, highZoneName, OBJPROP_PRICE, 1, majorHighZoneLow);
ObjectSetInteger(0, highZoneName, OBJPROP_TIME, 0, majorHighZoneTime);
ObjectSetInteger(0, highZoneName, OBJPROP_TIME, 1, TimeCurrent());
}
ChartRedraw();
}
//+------------------------------------------------------------------+
//| گسترش نواحی تا زمان حال (در هر تیک) |
//+------------------------------------------------------------------+
void ExtendZonesToCurrentTime()
{
if (majorLowBarIndex != -1)
{
ObjectSetInteger(0, lowZoneName, OBJPROP_TIME, 1, TimeCurrent());
}
if (majorHighBarIndex != -1)
{
ObjectSetInteger(0, highZoneName, OBJPROP_TIME, 1, TimeCurrent());
}
ChartRedraw();
}
//+------------------------------------------------------------------+
//| نمایش داشبورد روی چارت |
//+------------------------------------------------------------------+
void DisplayDashboard()
{
string dash = "\n========== 4H MAJOR STRUCTURE (BOS) ==========\n";
dash += "Symbol: " + _Symbol + " | Bias: " + biasDirection + "\n";
dash += "--------------------------------------------------\n";
if (majorLowBarIndex != -1)
{
dash += "MAJOR LOW ZONE (Support):\n";
dash += " High: " + DoubleToString(majorLowZoneHigh, _Digits) + "\n";
dash += " Low: " + DoubleToString(majorLowZoneLow, _Digits) + "\n";
dash += " Time: " + TimeToString(majorLowZoneTime, TIME_DATE | TIME_MINUTES) + "\n";
}
else
{
dash += "MAJOR LOW ZONE: Not Found\n";
}
dash += "--------------------------------------------------\n";
if (majorHighBarIndex != -1)
{
dash += "MAJOR HIGH ZONE (Resistance):\n";
dash += " High: " + DoubleToString(majorHighZoneHigh, _Digits) + "\n";
dash += " Low: " + DoubleToString(majorHighZoneLow, _Digits) + "\n";
dash += " Time: " + TimeToString(majorHighZoneTime, TIME_DATE | TIME_MINUTES) + "\n";
}
else
{
dash += "MAJOR HIGH ZONE: Not Found\n";
}
dash += "==================================================\n";
Comment(dash);
Print("Bias: ", biasDirection);
}
//+------------------------------------------------------------------+