This commit is contained in:
2025-09-21 05:59:18 +03:30
parent 73a97a80b3
commit 98b62aba96
6 changed files with 3108 additions and 196 deletions
+65
View File
@@ -889,6 +889,71 @@ class XCPOIDrawer : public XCBase
return result;
}
/**
* Draw Specified Trend Line ...
*
* @param fromPrice: double, from Price ...
* @param fromTime: datetime, from Time ...
* @param toPrice: double, to Price ...
* @param toTime: datetime, to Time ...
* @param name: Object Name ...
* @param rayRight: bool, ray to Right ...
* @param rayLeft: boo, ray to Left ...
*
* @return ( bool )
*/
bool DrawTrendLine(
double fromPrice,
datetime fromTime,
double toPrice,
datetime toTime,
CChartObjectTrend *&object,
string name,
bool rayRight = false,
bool rayLeft = false //
)
{
//
bool result = false;
//
// Prepare ...
object = new CChartObjectTrend();
//
// Validate ...
result =
toPrice > 0 &&
fromPrice > 0 &&
IsSpecifiedValid(toTime) &&
IsSpecifiedValid(fromTime) &&
toTime > fromTime;
if (!result)
{
return result;
}
//
// Create Object ...
result = object.Create(
ChartIdentification(),
name,
SubWindowIdentification(),
fromTime,
fromPrice,
toTime,
toPrice //
);
if (result) {
//
object.RayLeft(rayLeft);
object.RayRight(rayRight);
}
//
return result;
}
/**
* Draw Trend Line based on Swings Points ...
*
File diff suppressed because it is too large Load Diff
+78 -2
View File
@@ -164,6 +164,7 @@ int eaCTHandler = INVALID_HANDLE; // Candle Timer Handler ...
//
bool eaIsNewBar; // Check New Bar ...
XZigZagAnalysis zigzagAnalysis;
ENUM_X_DIRECTION trendDir = X_DIRECTION_NONE;
//
@@ -1198,13 +1199,88 @@ void DetectPatterns()
cBar,
fima2Signaller.fimaHelper,
zigzags,
3 //
15 //
);
has = IsValidSize(zigzagsCount);
if (has)
{
//
Print("Detected ZigZags Points: ", zigzagsCount);
// Analyse Using ZigZag ...
XZigZagAnalysis cZGAnalysis;
//
// Check ZG Analysis Exists ...
has = cZGAnalysis.Analyse(
cBar,
zigzags //
);
//
// Check Exists ZG Analysis isn't Same Trend as Prev ...
has =
has &&
(!zigzagAnalysis.IsValid()
? true
: !zigzagAnalysis.IsSameTrendAs(cZGAnalysis));
if (has)
{
//
// Update Prev Analysis ...
zigzagAnalysis = cZGAnalysis;
//
// Notify Only When New Trending Happens ...
Print("Detected ZigZags Pivots Analysis: ", zigzagAnalysis.GetMessage());
//
// Draw Trend Line ...
//
string iObjID = zigzagAnalysis.GetObjectID();
string iNameType = ToXString(zigzagAnalysis.dir) + "_Trend";
//
// Upper Line ...
string iUpperName = iNameType + "_Upper_" + iObjID;
CChartObjectTrend *iUpperObj;
has = eaDrawer.DrawTrendLine(
zigzagAnalysis.lastPeak.value,
zigzagAnalysis.lastPeak.time,
zigzagAnalysis.recentPeak.value,
zigzagAnalysis.recentPeak.time,
iUpperObj,
ToMD5(iUpperName),
true //
);
//
// Lower Line ...
string iLowerName = iNameType + "_Lower_" + iObjID;
CChartObjectTrend *iLowerObj;
has =
has &&
eaDrawer.DrawTrendLine(
zigzagAnalysis.lastVale.value,
zigzagAnalysis.lastVale.time,
zigzagAnalysis.recentVale.value,
zigzagAnalysis.recentVale.time,
iLowerObj,
ToMD5(iLowerName),
true //
);
//
if (has) {
//
// Apply Style on Trend Lines ...
//
draws.Add(iUpperObj);
draws.Add(iLowerObj);
}
}
//
}
}
}
+17 -192
View File
@@ -99,7 +99,6 @@ input bool showMAFast = true; // Show MA Fast
input bool showMASlow = true; // Show MA Slow
input bool showMABand = true; // Show MA Band
input bool showZigZag = true; // Show ZigZag
input bool showZigZagPV = true; // Show ZigZag PV
input bool showFiboZone = true; // Show Fibo Zone
//
@@ -134,8 +133,8 @@ input int valeArrowCode = 159; // Vales Arrow Code
#property indicator_chart_window
//
#property indicator_buffers 31
#property indicator_plots 13
#property indicator_buffers 29
#property indicator_plots 11
//
// Plot Buffers ...
@@ -155,7 +154,7 @@ double maFastColorBuffer[];
//
#property indicator_label1 "FastMA"
#property indicator_type1 DRAW_COLOR_LINE
#property indicator_color1 CLR_NONE, clrAquamarine, clrAquamarine, clrAquamarine // clrYellow, clrOrangeRed, clrGray
#property indicator_color1 CLR_NONE, clrLime, clrLime, clrLime // clrYellow, clrOrangeRed, clrGray
#property indicator_width1 3
//
@@ -173,7 +172,7 @@ double maSlowColorBuffer[];
//
#property indicator_label2 "SlowMA"
#property indicator_type2 DRAW_COLOR_LINE
#property indicator_color2 CLR_NONE, clrLightCoral, clrLightCoral, clrLightCoral // clrLime, clrRed, clrGray
#property indicator_color2 CLR_NONE, clrRed, clrRed, clrRed // clrLime, clrRed, clrGray
#property indicator_width2 3
//
@@ -278,67 +277,39 @@ double zigzagBuffer[];
#property indicator_color9 clrYellow
#property indicator_width9 2
//
// ZG Peak ...
//
#define zigzagPeakBufferIndex 12
#define zigzagPeakBufferPlotIndex 9
double zigzagPeakBuffer[];
//
#property indicator_label10 "XZG Peak"
#property indicator_type10 DRAW_ARROW
#property indicator_color10 clrYellow
#property indicator_width10 3
//
// ZG Vale ...
//
#define zigzagValeBufferIndex 13
#define zigzagValeBufferPlotIndex 10
double zigzagValeBuffer[];
//
#property indicator_label11 "XZG Peak"
#property indicator_type11 DRAW_ARROW
#property indicator_color11 clrDarkOrange
#property indicator_width11 3
//
// MA Upper Boundary ...
//
#define maUpperBufferIndex 14
#define maUpperBufferPlotIndex 11
#define maUpperBufferIndex 12
#define maUpperBufferPlotIndex 9
double maUpperBuffer[];
//
#property indicator_label12 "UpperMA"
#property indicator_type12 DRAW_LINE
#property indicator_color12 clrAqua
#property indicator_width12 3
#property indicator_label10 "UpperMA"
#property indicator_type10 DRAW_LINE
#property indicator_color10 clrAqua
#property indicator_width10 3
//
// MA Lower Boundary ...
//
#define maLowerBufferIndex 15
#define maLowerBufferPlotIndex 12
#define maLowerBufferIndex 13
#define maLowerBufferPlotIndex 10
double maLowerBuffer[];
//
#property indicator_label13 "LowerMA"
#property indicator_type13 DRAW_LINE
#property indicator_color13 clrMagenta
#property indicator_width13 3
#property indicator_label11 "LowerMA"
#property indicator_type11 DRAW_LINE
#property indicator_color11 clrMagenta
#property indicator_width11 3
//
// Data Buffers ...
//
#define mLastBufferIndex 15
#define mLastBufferIndex 13
//
// MA ...
@@ -622,32 +593,6 @@ int OnCalculate(
return prev_calculated;
}
//
// Calculating Limit ...
limit = prev_calculated == 0
? rates_total - 1
: rates_total - prev_calculated;
if (limit <= 0)
{
limit = rates_total - 1;
}
//
// Main Loop ...
for (int i = limit; i < rates_total - 1 && !IsStopped(); i++)
{
//
Print("Calculating Bar Index: ", i);
//
// Calculate Peaks and Vales ...
CalculateZigZagPV(
i,
prev_calculated,
rates_total //
);
}
//
// Prepare Buffers ...
ArraySetAsSeries(time, true);
@@ -984,38 +929,6 @@ void DefineBuffers()
PlotIndexSetInteger(zigzagBufferPlotIndex, PLOT_DRAW_BEGIN, 0);
PlotIndexSetDouble(zigzagBufferPlotIndex, PLOT_EMPTY_VALUE, 0);
//
// ZigZag PV ...
//
ENUM_DRAW_TYPE zigzagPVDrawType = showZigZagPV ? DRAW_ARROW : DRAW_NONE;
//
// ZG Peak ...
//
SetIndexBuffer(zigzagPeakBufferIndex, zigzagPeakBuffer, INDICATOR_DATA);
//
PlotIndexSetInteger(zigzagPeakBufferPlotIndex, PLOT_SHOW_DATA, showZigZagPV);
PlotIndexSetInteger(zigzagPeakBufferPlotIndex, PLOT_DRAW_TYPE, zigzagPVDrawType);
PlotIndexSetInteger(zigzagPeakBufferPlotIndex, PLOT_DRAW_BEGIN, 0);
PlotIndexSetDouble(zigzagPeakBufferPlotIndex, PLOT_EMPTY_VALUE, 0);
//
// ZG Vale ...
//
SetIndexBuffer(zigzagValeBufferIndex, zigzagValeBuffer, INDICATOR_DATA);
//
PlotIndexSetInteger(zigzagValeBufferPlotIndex, PLOT_SHOW_DATA, showZigZagPV);
PlotIndexSetInteger(zigzagValeBufferPlotIndex, PLOT_DRAW_TYPE, zigzagPVDrawType);
PlotIndexSetInteger(zigzagValeBufferPlotIndex, PLOT_DRAW_BEGIN, 0);
PlotIndexSetDouble(zigzagValeBufferPlotIndex, PLOT_EMPTY_VALUE, 0);
//
// MA Band ...
@@ -2007,94 +1920,6 @@ int CalculateZigZag(
return result;
}
/**
* Calculate Peaks and Vales ...
*
* @param barIndex: Integer, Represent Current Bar ...
* @param prevCalculated: Integer, Represent Previous Calculated Bars ...
* @param ratesTotal: Integer, Represents All Available Bars ...
* @param open: Double Array, History of Open Prices ...
* @param high: Double Array, History of High Prices ...
* @param close: Double Array, History of Close Prices ...
* @param low: Double Array, History of Low Prices ...
* @param tickVolume: Long, History of Tick Volumes on Bar ...
*/
void CalculateZigZagPV(
int barIndex,
const int prevCalculated,
const int ratesTotal //
)
{
//
double iZigZagValue = zigzagBuffer[barIndex];
//
// Print("Calculate Bar Index: ", barIndex, ", ZG: ", iZigZagValue, ", ", prevCalculated, ", ", ratesTotal);
//
// Peak ...
double iHighValue = highsBuffer[barIndex];
double iHighTimeDouble = highsTimeBuffer[barIndex];
datetime iHighTime = (datetime)((int)iHighTimeDouble);
if (iHighValue != 0 && iHighValue != EMPTY_VALUE && iZigZagValue == iHighValue)
{
//
peakBuffer[barIndex] = iHighValue;
//
lastZigZagPeak = iHighValue;
lastZigZagPeakTime = iHighTime;
}
else
{
//
double iValue = emptyValue;
if (
lastZigZagPeak != emptyValue &&
lastZigZagPeak != EMPTY_VALUE &&
IsSpecifiedValid(lastZigZagPeakTime))
{
iValue = lastZigZagPeak;
}
//
peakBuffer[barIndex] = iValue;
}
//
// Vale ...
double iLowValue = lowsBuffer[barIndex];
double iLowTimeDouble = lowsTimeBuffer[barIndex];
datetime iLowTime = (datetime)((int)iLowTimeDouble);
if (iLowValue != 0 && iLowValue != EMPTY_VALUE && iZigZagValue == iLowValue)
{
//
valeBuffer[barIndex] = iLowValue;
//
lastZigZagVale = iLowValue;
lastZigZagValeTime = iLowTime;
}
else
{
//
double iValue = emptyValue;
if (
lastZigZagVale != emptyValue &&
lastZigZagVale != EMPTY_VALUE &&
IsSpecifiedValid(lastZigZagValeTime))
{
iValue = lastZigZagVale;
}
//
valeBuffer[barIndex] = iValue;
}
//
// ChartRedraw();
}
//
void CalculateCycleRanges(
int barIndex,
+1
View File
@@ -17,6 +17,7 @@
#property link "https://saherelm.ir"
#property version "1.00"
#property description "SaherElm XZG Indicator"
#property icon "../Images/SaherElm_Logo_Color.ico"
#property strict
//
+543 -2
View File
@@ -341,6 +341,9 @@ struct XZigZagPoint
}
}
//
// Logging Tools ...
/**
* Extract Specified Token of Struct ...
*
@@ -368,7 +371,7 @@ struct XZigZagPoint
}
//
result = GetTag() + "_" + ToXString(dir) + "_" + ToXString(type) + "_" + ToXString(TimeToSeconds(time));
result = GetTag() + "_" + symbol + "_" + ToXString(period) + "_" + ToXString(dir) + "_" + ToXString(type) + "_" + ToXString(TimeToSeconds(time));
//
return result;
@@ -403,6 +406,10 @@ struct XZigZagPoint
//
result =
ToXString(dir) + spacer + GetTag() + ":" + spacer +
"Symbol: " + symbol + spacer +
"Period: " + ToXString(period) + spacer +
"Type: " + ToXString(type) + spacer +
"Direction: " + ToXString(dir) + spacer +
"Value: " + ToXString(value) + spacer +
"Time: " + ToXString(time) + spacer;
@@ -426,6 +433,17 @@ struct XZigZagAnalysis
//
ENUM_X_DIRECTION dir; // Direction ...
//
// Pivots ...
//
XZigZagPoint lastPeak;
XZigZagPoint recentPeak;
//
XZigZagPoint lastVale;
XZigZagPoint recentVale;
//
// Constructor ...
XZigZagAnalysis()
@@ -433,6 +451,253 @@ struct XZigZagAnalysis
Clean();
}
//
// Initialize ...
/**
* Analyse Market Structure ...
*
* @param bar: XOHCL, Specified Bar ...
* @param points: XZigZagPoint, Specified ZigZag Points Collection ...
*
* @return ( bool )
*/
bool Analyse(
XOHCL &bar,
XZigZagPoint &points[] //
)
{
//
bool result = false;
//
// Validate ...
result = bar.IsValid() &&
HasChild(points) &&
bar.symbol == points[0].symbol;
if (!result)
{
//
Clean();
return result;
}
//
// AssignSymbol and Period ...
time = bar.time;
symbol = bar.symbol;
period = bar.period;
//
// Detect At lease Two PEAK and Two Vale ...
XZigZagPoint tmpPoints[];
Copy(
points,
tmpPoints //
);
//
// Detect Highs ...
//
// Highest High ...
//
XZigZagPoint iZGPeak1;
XZigZagPoint iZGPeak2;
//
// First ...
int idx = GetHighest(
tmpPoints,
X_ZIGZAG_POINT_TYPE_PEAK //
);
result = IsValidIndex(idx);
if (!result)
{
//
Clean();
iZGPeak1.Clean();
iZGPeak2.Clean();
SpecifiedClean(tmpPoints);
//
return result;
}
iZGPeak1 = tmpPoints[idx];
ArrayRemove(
tmpPoints,
idx,
1 //
);
//
// Second ...
idx = GetHighest(
tmpPoints,
X_ZIGZAG_POINT_TYPE_PEAK //
);
result = IsValidIndex(idx);
if (!result)
{
//
Clean();
iZGPeak1.Clean();
iZGPeak2.Clean();
SpecifiedClean(tmpPoints);
//
return result;
}
iZGPeak2 = tmpPoints[idx];
ArrayRemove(
tmpPoints,
idx,
1 //
);
//
// Detect Lows ...
//
XZigZagPoint iZGVale1;
XZigZagPoint iZGVale2;
//
// First ...
idx = GetLowest(
tmpPoints,
X_ZIGZAG_POINT_TYPE_VALE //
);
result = IsValidIndex(idx);
if (!result)
{
//
Clean();
iZGPeak1.Clean();
iZGPeak2.Clean();
iZGVale1.Clean();
iZGVale2.Clean();
SpecifiedClean(tmpPoints);
//
return result;
}
iZGVale1 = tmpPoints[idx];
ArrayRemove(
tmpPoints,
idx,
1 //
);
//
// Second ...
idx = GetLowest(
tmpPoints,
X_ZIGZAG_POINT_TYPE_VALE //
);
result = IsValidIndex(idx);
if (!result)
{
//
Clean();
iZGPeak1.Clean();
iZGPeak2.Clean();
iZGVale1.Clean();
iZGVale2.Clean();
SpecifiedClean(tmpPoints);
//
return result;
}
iZGVale2 = tmpPoints[idx];
ArrayRemove(
tmpPoints,
idx,
1 //
);
//
// Check Directions ...
bool isBullish =
//
(iZGPeak1.time > iZGPeak2.time &&
iZGVale1.time < iZGVale2.time)
//
;
bool isBearish =
//
(iZGPeak1.time < iZGPeak2.time &&
iZGVale1.time > iZGVale2.time)
//
;
result =
(isBullish && !isBearish) ||
(isBearish && !isBullish);
if (!result)
{
//
Clean();
iZGPeak1.Clean();
iZGPeak2.Clean();
iZGVale1.Clean();
iZGVale2.Clean();
SpecifiedClean(tmpPoints);
//
return result;
}
//
// Setting Direction ...
dir =
isBullish
? X_DIRECTION_BULLISH
: isBearish
? X_DIRECTION_BEARISH
: X_DIRECTION_NONE;
//
// Setting Points ...
Copy(
points,
pivots //
);
//
// Assigning Peaks and Vales ...
if (result)
{
//
lastPeak = iZGPeak1;
lastVale = iZGVale1;
recentPeak = iZGPeak2;
recentVale = iZGVale2;
}
//
// Calculate Support and Resistance ...
//
// Validate ...
result = IsValid();
if (!result)
{
Clean();
}
//
// Cleanup Resources ...
iZGPeak1.Clean();
iZGPeak2.Clean();
iZGVale1.Clean();
iZGVale2.Clean();
SpecifiedClean(tmpPoints);
//
return result;
}
//
// Tools ...
@@ -448,6 +713,12 @@ struct XZigZagAnalysis
dir = X_DIRECTION_NONE;
SpecifiedClean(pivots);
//
lastPeak.Clean();
lastVale.Clean();
recentPeak.Clean();
recentVale.Clean();
//
ZeroMemory(this);
}
@@ -464,11 +735,19 @@ struct XZigZagAnalysis
//
result =
//
HasChild(pivots) &&
HasDirection(dir) &&
IsSpecifiedValid(time) &&
IsSpecifiedValid(symbol) &&
IsSpecifiedValid(period);
IsSpecifiedValid(period) &&
//
lastPeak.IsValid() &&
lastVale.IsValid() &&
recentPeak.IsValid() &&
recentVale.IsValid()
//
;
//
return result;
@@ -603,7 +882,269 @@ struct XZigZagAnalysis
return result;
}
/**
* Check to model Has Same Direction ...
*
* @param item: XZigZagAnalysis, dest model for Checking ...
*
* @return ( bool )
*/
bool IsSameDirectionAs(XZigZagAnalysis &item)
{
//
bool result = false;
//
result =
IsValid() &&
item.IsValid() &&
dir == item.dir;
//
return result;
}
/**
* Check to model Has Analysis Trend ...
*
* @param item: XZigZagAnalysis, dest model for Checking ...
*
* @return ( bool )
*/
bool IsSameTrendAs(XZigZagAnalysis &item)
{
//
bool result = false;
//
result =
IsValid() &&
item.IsValid() &&
IsSameMarketAs(item) &&
IsSameDirectionAs(item);
//
return result;
}
//
// Loggint Tools ...
/**
* Extract Specified Token of Struct ...
*
* @return ( string )
*/
string GetTag()
{
return GetToken(this);
}
/**
* Represent an String Unique Identifier for Chart Objects ...
*
* @return ( string )
*/
string GetObjectID()
{
//
string result = "";
//
if (!IsValid())
{
return result;
}
//
result = GetTag() + "_" + symbol + "_" + ToXString(period) + "_" + ToXString(dir) + "_" + ToXString(TimeToSeconds(time));
//
return result;
}
/**
* Represent a Point as String ...
*
* @param spacer: string, How to Represent Spaces ...
*
* @return ( string )
*/
string GetMessage(string spacer = NULL)
{
//
string result = "";
//
// Normalize Spacer ...
if (!IsSpecifiedValid(spacer))
{
spacer = " ";
}
//
// Validate ...
if (!IsValid())
{
return result;
}
//
result =
ToXString(dir) + spacer + GetTag() + ":" + spacer +
"Symbol: " + symbol + spacer +
"Period: " + ToXString(period) + spacer +
"Direction: " + ToXString(dir) + spacer +
"Time: " + ToXString(time) + spacer;
//
return result;
}
//
};
//
// Extensions ...
/**
* Get Highest ZigZagPoint Index in Specified Collection ...
*
* @param items: XZigZagPoint, Specified Points Collection to Search ...
* @param type: ENUM_X_ZIGZAG_POINT_TYPE, Specified Points Type ...
*
* @return ( int )
*/
int GetHighest(
XZigZagPoint &items[],
ENUM_X_ZIGZAG_POINT_TYPE type = X_ZIGZAG_POINT_TYPE_NONE //
)
{
//
int result = -1;
//
// Validate ...
if (!HasChild(items))
{
return result;
}
//
bool has = false;
XZigZagPoint iPoint;
int count = ArraySize(items);
for (int i = 0; i < count; i++)
{
//
// Passed Type ...
has = !IsXValid(type)
? true
: type == items[i].type;
//
// Check Can Assign ...
has =
has &&
(!iPoint.IsValid() ||
(iPoint.IsValid() &&
items[i].value > iPoint.value));
if (has)
{
//
result = i;
iPoint = items[i];
}
}
//
// Validate Result ...
has =
iPoint.IsValid() &&
IsValidIndex(result);
if (!has)
{
//
result = -1;
iPoint.Clean();
return result;
}
//
iPoint.Clean();
//
return result;
}
/**
* Get Lowest ZigZagPoint Index in Specified Collection ...
*
* @param items: XZigZagPoint, Specified Points Collection to Search ...
* @param type: ENUM_X_ZIGZAG_POINT_TYPE, Specified Points Type ...
*
* @return ( int )
*/
int GetLowest(
XZigZagPoint &items[],
ENUM_X_ZIGZAG_POINT_TYPE type = X_ZIGZAG_POINT_TYPE_NONE //
)
{
//
int result = -1;
//
// Validate ...
if (!HasChild(items))
{
return result;
}
//
bool has = false;
XZigZagPoint iPoint;
int count = ArraySize(items);
for (int i = 0; i < count; i++)
{
//
// Passed Type ...
has = !IsXValid(type)
? true
: type == items[i].type;
//
// Check Can Assign ...
has =
has &&
(!iPoint.IsValid() ||
(iPoint.IsValid() &&
items[i].value < iPoint.value));
if (has)
{
//
result = i;
iPoint = items[i];
}
}
//
// Validate Result ...
has =
iPoint.IsValid() &&
IsValidIndex(result);
if (!has)
{
//
result = -1;
iPoint.Clean();
return result;
}
//
iPoint.Clean();
//
return result;
}
//