156 lines
11 KiB
MQL5
156 lines
11 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| BoomSpikeBoxMitigationFinal.mq5 |
|
|
//| Spike pattern + entry line that expires at mitigation |
|
|
//+------------------------------------------------------------------+
|
|
#property indicator_chart_window
|
|
#property version "1.0"
|
|
#property strict
|
|
|
|
//==== Input Parameters ====
|
|
input color BoxColor = clrBlue;
|
|
input color LineColor = clrLimeGreen;
|
|
input int BoxWidth = 2;
|
|
input int LineWidth = 1;
|
|
input ENUM_LINE_STYLE BoxStyle = STYLE_SOLID;
|
|
input ENUM_LINE_STYLE LineStyle = STYLE_SOLID;
|
|
|
|
//==== Zone Struct ====
|
|
struct Zone
|
|
{
|
|
datetime boxTime;
|
|
double entryPrice;
|
|
string lineName;
|
|
bool mitigated;
|
|
};
|
|
|
|
Zone zones[100];
|
|
int zoneCount = 0;
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Initialization |
|
|
//+------------------------------------------------------------------+
|
|
int OnInit()
|
|
{
|
|
zoneCount = 0;
|
|
ObjectsDeleteAll(0, "Box_");
|
|
ObjectsDeleteAll(0, "Line_");
|
|
return INIT_SUCCEEDED;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| OnDeinit |
|
|
//+------------------------------------------------------------------+
|
|
void OnDeinit(const int reason)
|
|
{
|
|
ObjectsDeleteAll(0, "Box_");
|
|
ObjectsDeleteAll(0, "Line_");
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| OnCalculate |
|
|
//+------------------------------------------------------------------+
|
|
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[])
|
|
{
|
|
if (rates_total < 10)
|
|
return prev_calculated;
|
|
|
|
// ---- Pattern Detection ----
|
|
for (int i = rates_total - 4; i >= 2; i--)
|
|
{
|
|
double body1 = MathAbs(open[i] - close[i]);
|
|
double wick1 = high[i] - low[i];
|
|
bool isGreenSpike1 = close[i] > open[i] && body1 > 0.7 * wick1;
|
|
|
|
bool isRedMid = close[i+1] < open[i+1];
|
|
|
|
double body3 = MathAbs(open[i+2] - close[i+2]);
|
|
double wick3 = high[i+2] - low[i+2];
|
|
bool isGreenSpike2 = close[i+2] > open[i+2] && body3 > 0.7 * wick3;
|
|
|
|
if (isGreenSpike1 && isRedMid && isGreenSpike2)
|
|
{
|
|
datetime boxTime = time[i+2];
|
|
double entryPrice = open[i+1];
|
|
|
|
// Check duplicate
|
|
bool exists = false;
|
|
for (int j = 0; j < zoneCount; j++)
|
|
{
|
|
if (zones[j].boxTime == boxTime)
|
|
{
|
|
exists = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!exists && zoneCount < ArraySize(zones))
|
|
{
|
|
double top = MathMax(MathMax(high[i], high[i+1]), high[i+2]);
|
|
double bottom = MathMin(MathMin(low[i], low[i+1]), low[i+2]);
|
|
|
|
string boxName = "Box_" + IntegerToString((int)boxTime);
|
|
ObjectCreate(0, boxName, OBJ_RECTANGLE, 0, time[i], top, boxTime, bottom);
|
|
ObjectSetInteger(0, boxName, OBJPROP_COLOR, BoxColor);
|
|
ObjectSetInteger(0, boxName, OBJPROP_WIDTH, BoxWidth);
|
|
ObjectSetInteger(0, boxName, OBJPROP_STYLE, BoxStyle);
|
|
ObjectSetInteger(0, boxName, OBJPROP_BACK, true);
|
|
|
|
// Draw extending entry line
|
|
datetime futureTime = TimeCurrent() + PeriodSeconds() * 100;
|
|
string lineName = "Line_" + IntegerToString((int)boxTime);
|
|
ObjectCreate(0, lineName, OBJ_TREND, 0, boxTime, entryPrice, futureTime, entryPrice);
|
|
ObjectSetInteger(0, lineName, OBJPROP_COLOR, LineColor);
|
|
ObjectSetInteger(0, lineName, OBJPROP_WIDTH, LineWidth);
|
|
ObjectSetInteger(0, lineName, OBJPROP_STYLE, LineStyle);
|
|
|
|
zones[zoneCount].boxTime = boxTime;
|
|
zones[zoneCount].entryPrice = entryPrice;
|
|
zones[zoneCount].lineName = lineName;
|
|
zones[zoneCount].mitigated = false;
|
|
|
|
zoneCount++;
|
|
}
|
|
}
|
|
}
|
|
|
|
// ---- Mitigation Detection ----
|
|
for (int j = 0; j < zoneCount; j++)
|
|
{
|
|
if (zones[j].mitigated)
|
|
continue;
|
|
|
|
for (int i = 1; i < rates_total; i++)
|
|
{
|
|
if (time[i] <= zones[j].boxTime)
|
|
continue;
|
|
|
|
if (low[i] <= zones[j].entryPrice && high[i] >= zones[j].entryPrice)
|
|
{
|
|
if (ObjectFind(0, zones[j].lineName) >= 0)
|
|
ObjectDelete(0, zones[j].lineName);
|
|
|
|
string fixedName = zones[j].lineName + "_Fixed";
|
|
ObjectCreate(0, fixedName, OBJ_TREND, 0,
|
|
zones[j].boxTime, zones[j].entryPrice,
|
|
time[i], zones[j].entryPrice);
|
|
ObjectSetInteger(0, fixedName, OBJPROP_COLOR, LineColor);
|
|
ObjectSetInteger(0, fixedName, OBJPROP_WIDTH, LineWidth);
|
|
ObjectSetInteger(0, fixedName, OBJPROP_STYLE, LineStyle);
|
|
|
|
zones[j].mitigated = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return rates_total;
|
|
}
|