last ...
This commit is contained in:
@@ -57,8 +57,10 @@ class XCPivotDetector : public XCBase
|
||||
//
|
||||
// Constructor ...
|
||||
XCPivotDetector(
|
||||
XCAlert *_alert = NULL, //
|
||||
int _maxAllowedProcessableZones = 10 //
|
||||
XCAlert *_alert = NULL, // Alert instance Pointer ...
|
||||
string _pivotPrefix = "XPivot", // Detected Zones Prefix ...
|
||||
bool _supportInvertedZones = false, // Specified Support Inverted Zone or not ...
|
||||
int _maxAllowedProcessableZones = 0 // Max Allowed Processable Zones ...
|
||||
)
|
||||
{
|
||||
//
|
||||
@@ -66,10 +68,12 @@ class XCPivotDetector : public XCBase
|
||||
|
||||
//
|
||||
// Normalize ...
|
||||
if (_maxAllowedProcessableZones <= 5)
|
||||
if (_maxAllowedProcessableZones < 0)
|
||||
{
|
||||
_maxAllowedProcessableZones = 5;
|
||||
_maxAllowedProcessableZones = 0;
|
||||
}
|
||||
mPivotPrefix = _pivotPrefix;
|
||||
mSupportInvertedZones = _supportInvertedZones;
|
||||
mMaxAllowedProcessableZones = _maxAllowedProcessableZones;
|
||||
|
||||
//
|
||||
@@ -167,13 +171,13 @@ class XCPivotDetector : public XCBase
|
||||
}
|
||||
|
||||
//
|
||||
hasPeak = false;
|
||||
hasVale = false;
|
||||
hasPeak = true;
|
||||
hasVale = true;
|
||||
|
||||
//
|
||||
// Loop through Bars for Approved Side ...
|
||||
int jStart = i + 1;
|
||||
int jEnd = i + pivotApproved;
|
||||
int jEnd = i + pivotApproved + 1;
|
||||
for (int j = jStart; j < jEnd; j++)
|
||||
{
|
||||
//
|
||||
@@ -182,8 +186,8 @@ class XCPivotDetector : public XCBase
|
||||
jHigh = iHigh(iBar.symbol, iBar.period, j);
|
||||
|
||||
//
|
||||
hasVale = iBar.low < jLow;
|
||||
hasPeak = iBar.high > jHigh;
|
||||
hasVale = hasVale && (iBar.low < jLow);
|
||||
hasPeak = hasPeak && (iBar.high > jHigh);
|
||||
has = hasVale || hasPeak;
|
||||
if (!has)
|
||||
{
|
||||
@@ -204,7 +208,7 @@ class XCPivotDetector : public XCBase
|
||||
//
|
||||
// Loop through Barse for Approved Side ...
|
||||
jStart = i - pivotApproved;
|
||||
jEnd = i - 1;
|
||||
jEnd = i;
|
||||
for (int j = jStart; j < jEnd; j++)
|
||||
{
|
||||
//
|
||||
@@ -251,7 +255,7 @@ class XCPivotDetector : public XCBase
|
||||
tmpPrice = EMPTY_VALUE;
|
||||
tmpZonePrice = EMPTY_VALUE;
|
||||
jStart = i - pivotApproved;
|
||||
jEnd = i + pivotApproved;
|
||||
jEnd = i + pivotApproved + 1;
|
||||
for (int j = jStart; j < jEnd; j++)
|
||||
{
|
||||
//
|
||||
@@ -297,7 +301,7 @@ class XCPivotDetector : public XCBase
|
||||
tmpPrice = EMPTY_VALUE;
|
||||
tmpZonePrice = EMPTY_VALUE;
|
||||
jStart = i - pivotApproved;
|
||||
jEnd = i + pivotApproved;
|
||||
jEnd = i + pivotApproved + 1;
|
||||
for (int j = jStart; j < jEnd; j++)
|
||||
{
|
||||
//
|
||||
@@ -341,6 +345,46 @@ class XCPivotDetector : public XCBase
|
||||
}
|
||||
// #endregion
|
||||
}
|
||||
|
||||
bool HasPeaks()
|
||||
{
|
||||
return HasChild(peaks);
|
||||
}
|
||||
|
||||
bool HasVales()
|
||||
{
|
||||
return HasChild(vales);
|
||||
}
|
||||
|
||||
int GetYoungestPeak()
|
||||
{
|
||||
//
|
||||
int result = -1;
|
||||
|
||||
//
|
||||
if (HasPeaks())
|
||||
{
|
||||
result = GetYoungest(peaks);
|
||||
}
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
int GetYoungestVale()
|
||||
{
|
||||
//
|
||||
int result = -1;
|
||||
|
||||
//
|
||||
if (HasVales())
|
||||
{
|
||||
result = GetYoungest(vales);
|
||||
}
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
// #endregion
|
||||
|
||||
// #region Event Listener Registration ...
|
||||
@@ -427,9 +471,6 @@ class XCPivotDetector : public XCBase
|
||||
//
|
||||
Clean(mOnPeakDetectedHandlers);
|
||||
Clean(mOnValeDetectedHandlers);
|
||||
|
||||
//
|
||||
mPivotPrefix = "XSDT";
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -448,6 +489,13 @@ class XCPivotDetector : public XCBase
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Validate Peak Box based on Price ...
|
||||
if (!IsBoxValid(peakBox, 0, X_BOUNDARY_PRICE_UP_DOWN))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Update To ...
|
||||
peakBox.to = TimeCurrent();
|
||||
@@ -486,7 +534,7 @@ class XCPivotDetector : public XCBase
|
||||
{
|
||||
//
|
||||
// Validate New Peak based on Youngest One ...
|
||||
hasPeaks = peakBox.upper > peaks[idx].upper;
|
||||
hasPeaks = peakBox.upper < peaks[idx].upper;
|
||||
if (hasPeaks)
|
||||
{
|
||||
//
|
||||
@@ -524,6 +572,13 @@ class XCPivotDetector : public XCBase
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Validate Peak Box based on Price ...
|
||||
if (!IsBoxValid(valeBox, 0, X_BOUNDARY_PRICE_UP_DOWN))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Update To ...
|
||||
valeBox.to = TimeCurrent();
|
||||
@@ -561,7 +616,7 @@ class XCPivotDetector : public XCBase
|
||||
{
|
||||
//
|
||||
// Validate New Vale based on Youngest One ...
|
||||
hasVales = valeBox.lower < vales[idx].lower;
|
||||
hasVales = valeBox.lower > vales[idx].lower;
|
||||
if (hasVales)
|
||||
{
|
||||
//
|
||||
@@ -738,6 +793,7 @@ class XCPivotDetector : public XCBase
|
||||
//
|
||||
// Props ...
|
||||
string mPivotPrefix; // Prefix ...
|
||||
bool mSupportInvertedZones; // Support Inverted Zones ...
|
||||
int mMaxAllowedProcessableZones; // Max Allowed Processable Zones ...
|
||||
|
||||
/**
|
||||
@@ -826,6 +882,7 @@ class XCPivotDetector : public XCBase
|
||||
//
|
||||
Add(i, removeIDX);
|
||||
NotifyPeakBreaked(peaks[i]);
|
||||
HandleBreakedZone(peaks[i], cBar);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -850,6 +907,7 @@ class XCPivotDetector : public XCBase
|
||||
//
|
||||
Add(i, removeIDX);
|
||||
NotifyValeBreaked(vales[i]);
|
||||
HandleBreakedZone(vales[i], cBar);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -894,6 +952,87 @@ class XCPivotDetector : public XCBase
|
||||
CleanupPeaks();
|
||||
CleanupVales();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Breaked Zones ...
|
||||
*
|
||||
* @param box: XBoxZone instance ...
|
||||
* @param bar: XOHCL instance ...
|
||||
*/
|
||||
void HandleBreakedZone(
|
||||
XBoxZone &box,
|
||||
XOHCL &bar //
|
||||
)
|
||||
{
|
||||
//
|
||||
// Validate ...
|
||||
if (!box.IsValid() ||
|
||||
!mSupportInvertedZones //
|
||||
)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
XBoxZone inverted;
|
||||
int maxAllowedInversion = 1;
|
||||
int count = ArraySize(box.breaks);
|
||||
bool has = count < maxAllowedInversion;
|
||||
if (!has)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Invert to Peak ...
|
||||
if (box.IsBullish())
|
||||
{
|
||||
//
|
||||
// Initialize Inverted Box ...
|
||||
has = inverted.Init(
|
||||
box.symbol,
|
||||
box.period,
|
||||
box.upper,
|
||||
box.lower,
|
||||
bar.time, // From ...
|
||||
TimeCurrent(), // To ...
|
||||
X_DIRECTION_BEARISH,
|
||||
"i" + mPivotPrefix // Type ...
|
||||
);
|
||||
if (has)
|
||||
{
|
||||
//
|
||||
Add(bar.time, inverted.breaks);
|
||||
AddRef(inverted, peaks);
|
||||
}
|
||||
}
|
||||
//
|
||||
// Invert to Vale ...
|
||||
else if (box.IsBearish())
|
||||
{
|
||||
//
|
||||
// Initialize Inverted Box ...
|
||||
has = inverted.Init(
|
||||
box.symbol,
|
||||
box.period,
|
||||
box.upper,
|
||||
box.lower,
|
||||
bar.time, // From ...
|
||||
TimeCurrent(), // To ...
|
||||
X_DIRECTION_BULLISH,
|
||||
"i" + mPivotPrefix // Type ...
|
||||
);
|
||||
if (has)
|
||||
{
|
||||
//
|
||||
Add(bar.time, inverted.breaks);
|
||||
AddRef(inverted, vales);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
inverted.Clean();
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -30,13 +30,24 @@
|
||||
|
||||
XCAlert *eaAlert;
|
||||
XCPOIDrawer *eaDrawer;
|
||||
CArrayObj eaDrawnObjects;
|
||||
XCPivotDetector *eaPivotDetector;
|
||||
XCSessionDetector *eaSessionDetector;
|
||||
|
||||
//
|
||||
XCPivotDetector *eaMajorPivotDetector;
|
||||
XCPivotDetector *eaMinorPivotDetector;
|
||||
|
||||
//
|
||||
// Last Processing Pivots Time ...
|
||||
datetime eaLastPivotProcessing = NULL;
|
||||
bool eaDrawMajorPivots = true;
|
||||
bool eaDrawMinorPivots = true;
|
||||
XPOIDrawConfig eaMajorPivotsDrawConfig;
|
||||
XPOIDrawConfig eaMinorPivotsDrawConfig;
|
||||
datetime eaLastMajorPivotProcessing = NULL;
|
||||
datetime eaLastMinorPivotProcessing = NULL;
|
||||
XPOIDrawConfig eaPointedMajorPivotsDrawConfig;
|
||||
XPOIDrawConfig eaPointedMinorPivotsDrawConfig;
|
||||
ENUM_X_DIRECTION eaMajorBias = X_DIRECTION_NONE;
|
||||
ENUM_X_DIRECTION eaMinorBias = X_DIRECTION_NONE;
|
||||
// #endregion
|
||||
|
||||
// #region Global Event Handlers ...
|
||||
@@ -84,12 +95,19 @@ void OnDeinit(const int reason)
|
||||
// Destroy Timer ...
|
||||
// If Initialized ...
|
||||
|
||||
//
|
||||
eaMajorPivotsDrawConfig.Clean();
|
||||
eaMinorPivotsDrawConfig.Clean();
|
||||
eaPointedMajorPivotsDrawConfig.Clean();
|
||||
eaPointedMinorPivotsDrawConfig.Clean();
|
||||
|
||||
//
|
||||
// Cleanup Resources ...
|
||||
ZeroMemory(eaAlert);
|
||||
ZeroMemory(eaDrawer);
|
||||
ZeroMemory(eaPivotDetector);
|
||||
ZeroMemory(eaSessionDetector);
|
||||
ZeroMemory(eaMajorPivotDetector);
|
||||
ZeroMemory(eaMinorPivotDetector);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -103,7 +121,12 @@ void OnTick()
|
||||
|
||||
//
|
||||
// Process Pivot Detector ...
|
||||
HandleProcessPviots();
|
||||
HandleProcessMajorPviots();
|
||||
HandleProcessMinorPviots();
|
||||
|
||||
//
|
||||
// Detecting Bias ...
|
||||
HanldeBiasDetection();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -142,8 +165,8 @@ bool InitializeRequirements()
|
||||
// Initialize Alert ...
|
||||
eaAlert = new XCAlert(
|
||||
ShortName,
|
||||
true, // Enable Alert ...
|
||||
true, // Log Alert ...
|
||||
false, // Enable Alert ...
|
||||
false, // Log Alert ...
|
||||
false, // Terminal Alert ...
|
||||
false, // Mail Alert ...
|
||||
false, // Push Alerts ...
|
||||
@@ -179,20 +202,82 @@ bool InitializeRequirements()
|
||||
}
|
||||
|
||||
//
|
||||
// Initialize Pivot Detector ...
|
||||
eaPivotDetector = new XCPivotDetector(
|
||||
eaAlert // Alert ...
|
||||
// Initialize Major Pivot Detector ...
|
||||
eaMajorPivotDetector = new XCPivotDetector(
|
||||
eaAlert, // Alert ...
|
||||
"X121SDTMajor", // Pivot Prefix ...
|
||||
false, // Support Inverted Zones ...
|
||||
0 // Processable Zones ...
|
||||
);
|
||||
|
||||
//
|
||||
// Register Event Handlers ...
|
||||
eaPivotDetector.AddOnPeakBreakedHandler(OnPeakBreakedHandler);
|
||||
eaPivotDetector.AddOnValeBreakedHandler(OnValeBreakedHandler);
|
||||
eaPivotDetector.AddOnPeakDetectedHandler(OnPeakDetectedHandler);
|
||||
eaPivotDetector.AddOnValeDetectedHandler(OnValeDetectedHandler);
|
||||
eaMajorPivotDetector.AddOnPeakBreakedHandler(OnMajorPeakBreakedHandler);
|
||||
eaMajorPivotDetector.AddOnValeBreakedHandler(OnMajorValeBreakedHandler);
|
||||
eaMajorPivotDetector.AddOnPeakDetectedHandler(OnMajorPeakDetectedHandler);
|
||||
eaMajorPivotDetector.AddOnValeDetectedHandler(OnMajorValeDetectedHandler);
|
||||
|
||||
//
|
||||
result = eaPivotDetector != NULL;
|
||||
// Pivot Draw Config ...
|
||||
eaMajorPivotsDrawConfig.zonesWidth = 2;
|
||||
eaMajorPivotsDrawConfig.zonesFill = false;
|
||||
eaMajorPivotsDrawConfig.ignoreZonesAt = true;
|
||||
eaMajorPivotsDrawConfig.zonesStyle = STYLE_SOLID;
|
||||
eaMajorPivotsDrawConfig.bullishColor = clrAqua;
|
||||
eaMajorPivotsDrawConfig.bearishColor = clrMagenta;
|
||||
|
||||
//
|
||||
// Pointed Pivot Draw Config ...
|
||||
eaPointedMajorPivotsDrawConfig.zonesWidth = 2;
|
||||
eaPointedMajorPivotsDrawConfig.zonesFill = false;
|
||||
eaPointedMajorPivotsDrawConfig.ignoreZonesAt = true;
|
||||
eaPointedMajorPivotsDrawConfig.zonesStyle = STYLE_SOLID;
|
||||
eaPointedMajorPivotsDrawConfig.bullishColor = clrYellow;
|
||||
eaPointedMajorPivotsDrawConfig.bearishColor = clrOrange;
|
||||
|
||||
//
|
||||
result = eaMajorPivotDetector != NULL;
|
||||
if (!result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Initialize Minor Pivot Detector ...
|
||||
eaMinorPivotDetector = new XCPivotDetector(
|
||||
eaAlert, // Alert ...
|
||||
"X121SDTMinor", // Pivot Prefix ...
|
||||
false, // Support Inverted Zones ...
|
||||
0 // Processable Zones ...
|
||||
);
|
||||
|
||||
//
|
||||
// Register Event Handlers ...
|
||||
eaMinorPivotDetector.AddOnPeakBreakedHandler(OnMinorPeakBreakedHandler);
|
||||
eaMinorPivotDetector.AddOnValeBreakedHandler(OnMinorValeBreakedHandler);
|
||||
eaMinorPivotDetector.AddOnPeakDetectedHandler(OnMinorPeakDetectedHandler);
|
||||
eaMinorPivotDetector.AddOnValeDetectedHandler(OnMinorValeDetectedHandler);
|
||||
|
||||
//
|
||||
// Pivot Draw Config ...
|
||||
eaMinorPivotsDrawConfig.zonesWidth = 1;
|
||||
eaMinorPivotsDrawConfig.zonesFill = false;
|
||||
eaMinorPivotsDrawConfig.ignoreZonesAt = true;
|
||||
eaMinorPivotsDrawConfig.bearishColor = clrRed;
|
||||
eaMinorPivotsDrawConfig.bullishColor = clrLime;
|
||||
eaMinorPivotsDrawConfig.zonesStyle = STYLE_DASHDOT;
|
||||
|
||||
//
|
||||
// Pointed Pivot Draw Config ...
|
||||
eaPointedMinorPivotsDrawConfig.zonesWidth = 2;
|
||||
eaPointedMinorPivotsDrawConfig.zonesFill = false;
|
||||
eaPointedMinorPivotsDrawConfig.ignoreZonesAt = true;
|
||||
eaPointedMinorPivotsDrawConfig.bearishColor = clrOrange;
|
||||
eaPointedMinorPivotsDrawConfig.bullishColor = clrYellow;
|
||||
eaPointedMinorPivotsDrawConfig.zonesStyle = STYLE_DASHDOT;
|
||||
|
||||
//
|
||||
result = eaMinorPivotDetector != NULL;
|
||||
if (!result)
|
||||
{
|
||||
return result;
|
||||
@@ -205,7 +290,7 @@ bool InitializeRequirements()
|
||||
/**
|
||||
* Process Pivots ...
|
||||
*/
|
||||
void HandleProcessPviots()
|
||||
void HandleProcessMajorPviots()
|
||||
{
|
||||
//
|
||||
// Initialize Pivot Processing Bar ...
|
||||
@@ -213,7 +298,7 @@ void HandleProcessPviots()
|
||||
bool has = bar.Init(
|
||||
_Symbol,
|
||||
PERIOD_H4,
|
||||
1 // Last Completed 4H Bar ...
|
||||
1 // Last Completed Bar ...
|
||||
);
|
||||
if (!has)
|
||||
{
|
||||
@@ -223,15 +308,18 @@ void HandleProcessPviots()
|
||||
//
|
||||
// Validate Passing Bar ...
|
||||
has =
|
||||
!IsXValid(eaLastPivotProcessing) ||
|
||||
bar.time > eaLastPivotProcessing;
|
||||
!IsXValid(eaLastMajorPivotProcessing) ||
|
||||
bar.time > eaLastMajorPivotProcessing;
|
||||
if (!has)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
eaPivotDetector.Process(
|
||||
eaLastMajorPivotProcessing = bar.time;
|
||||
|
||||
//
|
||||
eaMajorPivotDetector.Process(
|
||||
bar, // XOHCL Bar ...
|
||||
2, // Pivot Approvation Length ...
|
||||
20 // Loopback ...
|
||||
@@ -239,30 +327,141 @@ void HandleProcessPviots()
|
||||
|
||||
//
|
||||
// Handle Draw Pivots ...
|
||||
if (!eaDrawMajorPivots)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
XBoxZone tmps[];
|
||||
CArrayObj *objects;
|
||||
FillNotExists(
|
||||
tmps, // Dest ...
|
||||
eaPivotDetector.peaks, // Source ...
|
||||
eaMajorPivotDetector.peaks, // Source ...
|
||||
false // Force Clean ...
|
||||
);
|
||||
FillNotExists(
|
||||
tmps, // Dest ...
|
||||
eaPivotDetector.vales, // Source ...
|
||||
eaMajorPivotDetector.vales, // Source ...
|
||||
false // Force Clean ...
|
||||
);
|
||||
if (HasChild(tmps))
|
||||
{
|
||||
eaDrawer.DrawBoxes(
|
||||
eaDrawer.DrawZones(
|
||||
tmps, // Boxes ...
|
||||
objects, // Objects to Hold ...
|
||||
false // Ignore Type Name ...
|
||||
eaMajorPivotsDrawConfig // Draw Config ...
|
||||
);
|
||||
}
|
||||
XClean(tmps);
|
||||
AddObjects(objects, eaDrawnObjects);
|
||||
if (eaDrawnObjects.Total() > 0) {
|
||||
DebugBreak();
|
||||
}
|
||||
|
||||
/**
|
||||
* Process Pivots ...
|
||||
*/
|
||||
void HandleProcessMinorPviots()
|
||||
{
|
||||
//
|
||||
// Initialize Pivot Processing Bar ...
|
||||
XOHCL bar;
|
||||
bool has = bar.Init(
|
||||
_Symbol,
|
||||
PERIOD_M15,
|
||||
1 // Last Completed Bar ...
|
||||
);
|
||||
if (!has)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Validate Passing Bar ...
|
||||
has =
|
||||
!IsXValid(eaLastMinorPivotProcessing) ||
|
||||
bar.time > eaLastMinorPivotProcessing;
|
||||
if (!has)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
eaLastMinorPivotProcessing = bar.time;
|
||||
|
||||
//
|
||||
eaMinorPivotDetector.Process(
|
||||
bar, // XOHCL Bar ...
|
||||
5, // Pivot Approvation Length ...
|
||||
40 // Loopback ...
|
||||
);
|
||||
|
||||
//
|
||||
// Handle Draw Pivots ...
|
||||
if (!eaDrawMinorPivots)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
XBoxZone tmps[];
|
||||
FillNotExists(
|
||||
tmps, // Dest ...
|
||||
eaMinorPivotDetector.peaks, // Source ...
|
||||
false // Force Clean ...
|
||||
);
|
||||
FillNotExists(
|
||||
tmps, // Dest ...
|
||||
eaMinorPivotDetector.vales, // Source ...
|
||||
false // Force Clean ...
|
||||
);
|
||||
if (HasChild(tmps))
|
||||
{
|
||||
eaDrawer.DrawZones(
|
||||
tmps, // Boxes ...
|
||||
eaMinorPivotsDrawConfig // Draw Config ...
|
||||
);
|
||||
}
|
||||
XClean(tmps);
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect Bias based on Pivots ...
|
||||
*/
|
||||
void HanldeBiasDetection()
|
||||
{
|
||||
//
|
||||
bool has = false;
|
||||
|
||||
//
|
||||
// Major Bias ...
|
||||
has =
|
||||
eaMajorPivotDetector.HasPeaks() &&
|
||||
eaMajorPivotDetector.HasVales();
|
||||
if (has)
|
||||
{
|
||||
//
|
||||
int youngestPeakIDX = eaMajorPivotDetector.GetYoungestPeak();
|
||||
int youngestValeIDX = eaMajorPivotDetector.GetYoungestVale();
|
||||
has =
|
||||
IsValidIndex(youngestPeakIDX) &&
|
||||
IsValidIndex(youngestValeIDX);
|
||||
if (has)
|
||||
{
|
||||
//
|
||||
eaMajorBias =
|
||||
eaMajorPivotDetector.peaks[youngestPeakIDX].from > eaMajorPivotDetector.vales[youngestValeIDX].from
|
||||
? X_DIRECTION_BEARISH
|
||||
: eaMajorPivotDetector.vales[youngestValeIDX].from > eaMajorPivotDetector.peaks[youngestPeakIDX].from
|
||||
? X_DIRECTION_BULLISH
|
||||
: X_DIRECTION_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
if (HasDirection(eaMajorBias))
|
||||
{
|
||||
Comment("Major Bias: ", ToXString(eaMajorBias));
|
||||
}
|
||||
else
|
||||
{
|
||||
Comment("");
|
||||
}
|
||||
}
|
||||
// #endregion
|
||||
@@ -275,7 +474,7 @@ void HandleProcessPviots()
|
||||
*
|
||||
* @param box: XBoxZone instance ...
|
||||
*/
|
||||
void OnPeakBreakedHandler(XBoxZone &box)
|
||||
void OnMajorPeakBreakedHandler(XBoxZone &box)
|
||||
{
|
||||
// DebugBreak();
|
||||
}
|
||||
@@ -285,7 +484,7 @@ void OnPeakBreakedHandler(XBoxZone &box)
|
||||
*
|
||||
* @param box: XBoxZone instance ...
|
||||
*/
|
||||
void OnValeBreakedHandler(XBoxZone &box)
|
||||
void OnMajorValeBreakedHandler(XBoxZone &box)
|
||||
{
|
||||
// DebugBreak();
|
||||
}
|
||||
@@ -295,9 +494,16 @@ void OnValeBreakedHandler(XBoxZone &box)
|
||||
*
|
||||
* @param box: XBoxZone instance ...
|
||||
*/
|
||||
void OnPeakDetectedHandler(XBoxZone &box)
|
||||
void OnMajorPeakDetectedHandler(XBoxZone &box)
|
||||
{
|
||||
// DebugBreak();
|
||||
//
|
||||
eaDrawer.DrawZone(
|
||||
box, //
|
||||
eaPointedMajorPivotsDrawConfig //
|
||||
);
|
||||
|
||||
//
|
||||
DebugBreak();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -305,10 +511,71 @@ void OnPeakDetectedHandler(XBoxZone &box)
|
||||
*
|
||||
* @param box: XBoxZone instance ...
|
||||
*/
|
||||
void OnValeDetectedHandler(XBoxZone &box)
|
||||
void OnMajorValeDetectedHandler(XBoxZone &box)
|
||||
{
|
||||
//
|
||||
eaDrawer.DrawZone(
|
||||
box, //
|
||||
eaPointedMajorPivotsDrawConfig //
|
||||
);
|
||||
|
||||
//
|
||||
DebugBreak();
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls when a Peak Breaked ...
|
||||
*
|
||||
* @param box: XBoxZone instance ...
|
||||
*/
|
||||
void OnMinorPeakBreakedHandler(XBoxZone &box)
|
||||
{
|
||||
// DebugBreak();
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls when a Vale Breaked ...
|
||||
*
|
||||
* @param box: XBoxZone instance ...
|
||||
*/
|
||||
void OnMinorValeBreakedHandler(XBoxZone &box)
|
||||
{
|
||||
// DebugBreak();
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls when a New Peak Detected ...
|
||||
*
|
||||
* @param box: XBoxZone instance ...
|
||||
*/
|
||||
void OnMinorPeakDetectedHandler(XBoxZone &box)
|
||||
{
|
||||
//
|
||||
eaDrawer.DrawZone(
|
||||
box, //
|
||||
eaPointedMinorPivotsDrawConfig //
|
||||
);
|
||||
|
||||
//
|
||||
DebugBreak();
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls when a New Vale Detected ...
|
||||
*
|
||||
* @param box: XBoxZone instance ...
|
||||
*/
|
||||
void OnMinorValeDetectedHandler(XBoxZone &box)
|
||||
{
|
||||
//
|
||||
eaDrawer.DrawZone(
|
||||
box, //
|
||||
eaPointedMinorPivotsDrawConfig //
|
||||
);
|
||||
|
||||
//
|
||||
DebugBreak();
|
||||
}
|
||||
// #endregion
|
||||
|
||||
// #region Session Detector Event Handlers ...
|
||||
|
||||
@@ -3722,6 +3722,125 @@ bool IsBoxValid(
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate a Box based on Price ...
|
||||
*
|
||||
* @param box: XBoxZone instance, box to Validate ...
|
||||
* @param barIndex: int, Start Validating Bar's Index ...
|
||||
* @param pType: ENUM_X_BOUNDARY_PRICE, Price Type for Validation ...
|
||||
*
|
||||
* @return ( bool )
|
||||
*/
|
||||
bool IsBoxValid(
|
||||
XBoxZone &box,
|
||||
int barIndex = 0,
|
||||
ENUM_X_BOUNDARY_PRICE pType = X_BOUNDARY_PRICE_UP_DOWN //
|
||||
)
|
||||
{
|
||||
//
|
||||
bool result = false;
|
||||
|
||||
//
|
||||
// Normalize Bar Index ...
|
||||
barIndex = NormalizeInt(barIndex, 0);
|
||||
|
||||
//
|
||||
// Validaet ...
|
||||
result =
|
||||
box.IsValid() &&
|
||||
IsXValid(pType);
|
||||
if (!result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
bool isBullish = box.IsBullish();
|
||||
|
||||
//
|
||||
int fromIDX = box.FromIndex();
|
||||
result =
|
||||
IsValidIndex(fromIDX) &&
|
||||
barIndex < fromIDX;
|
||||
if (!result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Loop through ...
|
||||
XOHCL iBar;
|
||||
bool has = false;
|
||||
double appliedPrice = EMPTY_VALUE;
|
||||
for (int i = barIndex; i < fromIDX; i++)
|
||||
{
|
||||
//
|
||||
// Initialize Bar ...
|
||||
iBar.Clean();
|
||||
has = iBar.Init(box.symbol, box.period, i);
|
||||
if (!has)
|
||||
{
|
||||
//
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
|
||||
//
|
||||
// Calculate Applied Price ...
|
||||
switch (pType)
|
||||
{
|
||||
//
|
||||
case X_BOUNDARY_PRICE_UP_DOWN:
|
||||
//
|
||||
appliedPrice =
|
||||
isBullish
|
||||
? iBar.GetDown()
|
||||
: iBar.GetUp();
|
||||
break;
|
||||
|
||||
//
|
||||
case X_BOUNDARY_PRICE_HIGH_LOW:
|
||||
//
|
||||
appliedPrice =
|
||||
isBullish
|
||||
? iBar.low
|
||||
: iBar.high;
|
||||
break;
|
||||
|
||||
//
|
||||
default:
|
||||
appliedPrice = EMPTY_VALUE;
|
||||
break;
|
||||
}
|
||||
has = NotEmptyZero(appliedPrice);
|
||||
if (!has)
|
||||
{
|
||||
//
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
|
||||
//
|
||||
has =
|
||||
has &&
|
||||
result &&
|
||||
(isBullish
|
||||
? appliedPrice >= box.lower
|
||||
: appliedPrice <= box.upper);
|
||||
if (!has) {
|
||||
//
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
|
||||
//
|
||||
iBar.Clean();
|
||||
}
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
void SortBoxes(
|
||||
XBoxZone &items[],
|
||||
|
||||
@@ -0,0 +1,298 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* Context Generator Module ...
|
||||
* a module for Generating Context ...
|
||||
*
|
||||
* Maintainer
|
||||
*
|
||||
* Hadi Khazaee Asl <https://saherelm.ir> (hadi_khazaee_asl@yahoo.com)
|
||||
*/
|
||||
|
||||
//
|
||||
//#region Imports ...
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Constants ...
|
||||
const outputFilePrefix = "x121XSDT";
|
||||
const allowedPatterns = [
|
||||
//
|
||||
// Base Pilot Files ...
|
||||
{
|
||||
kind: "file",
|
||||
mode: "allow",
|
||||
match: "name",
|
||||
pattern: /^x-saherelm.pivot-detector.class.mq5$/i
|
||||
},
|
||||
{
|
||||
kind: "file",
|
||||
mode: "allow",
|
||||
match: "name",
|
||||
pattern: /^x-saherelm.x-pivot-detector.test.mq5$/i
|
||||
},
|
||||
]
|
||||
//#endregion
|
||||
|
||||
//
|
||||
// Reading Required Info
|
||||
const inputPath = process.argv[2];
|
||||
const searchPath = path.resolve(inputPath || process.cwd());
|
||||
|
||||
// Check Given Path is Valid or not ...
|
||||
if (!fs.existsSync(searchPath)) {
|
||||
console.error(`Error: path not found: ${searchPath}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
//
|
||||
// Retrieve Stats of Given Path ...
|
||||
const stat = fs.statSync(searchPath);
|
||||
if (!stat.isDirectory()) {
|
||||
console.error(`Error: path is not a directory: ${searchPath}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
//
|
||||
// Generate Required Data ...
|
||||
const timestamp = getTimestamp(new Date());
|
||||
const folderName = path.basename(searchPath) || "root";
|
||||
const safeFolderName = sanitizeFileName(folderName);
|
||||
|
||||
// Generate Output file Name ...
|
||||
const outputFileName = inputPath
|
||||
? `${outputFilePrefix}-${safeFolderName}-${timestamp}.txt`
|
||||
: `${outputFilePrefix}-${timestamp}.txt`;
|
||||
|
||||
//
|
||||
const outputPath = path.join(
|
||||
process.cwd(),
|
||||
"Documents",
|
||||
"GeneratedContext",
|
||||
outputFileName
|
||||
);
|
||||
|
||||
// Create Output File ...
|
||||
fs.writeFileSync(outputPath, "", "utf8");
|
||||
|
||||
// Navigate to Context Generation ...
|
||||
walk(searchPath);
|
||||
|
||||
//
|
||||
console.log(`Context generated: ${outputPath}`);
|
||||
|
||||
//
|
||||
//#region Required Tools ...
|
||||
/**
|
||||
* Validate Timestamp ...
|
||||
*
|
||||
* @param {*} value
|
||||
* @returns
|
||||
*/
|
||||
function pad(value) {
|
||||
return String(value).padStart(2, "0");
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve Validate ...
|
||||
*
|
||||
* @param {*} date
|
||||
* @returns
|
||||
*/
|
||||
function getTimestamp(date) {
|
||||
//
|
||||
const year = date.getFullYear();
|
||||
const month = pad(date.getMonth() + 1);
|
||||
const day = pad(date.getDate());
|
||||
const hours = pad(date.getHours());
|
||||
const minutes = pad(date.getMinutes());
|
||||
const seconds = pad(date.getSeconds());
|
||||
|
||||
//
|
||||
return `${year}${month}${day}_${hours}${minutes}${seconds}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve Leaf Folder ...
|
||||
*
|
||||
* @param {*} value
|
||||
* @returns
|
||||
*/
|
||||
function sanitizeFileName(value) {
|
||||
return value.replace(/[\\/:*?"<>|]/g, "_");
|
||||
}
|
||||
|
||||
/**
|
||||
* Match Value ...
|
||||
*
|
||||
* @param {*} rule
|
||||
* @param {*} targetPath
|
||||
* @returns
|
||||
*/
|
||||
function getMatchValue(rule, targetPath) {
|
||||
//
|
||||
const normalizedPath = targetPath.replace(/\\/g, "/");
|
||||
if (rule.match === "path") {
|
||||
return normalizedPath;
|
||||
}
|
||||
|
||||
//
|
||||
return path.basename(targetPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Match Patterns ...
|
||||
*
|
||||
* @param {*} targetPath
|
||||
* @param {*} rules
|
||||
* @returns
|
||||
*/
|
||||
function matchesPatterns(targetPath, rules) {
|
||||
//
|
||||
return rules.some(rule => {
|
||||
const value = getMatchValue(rule, targetPath);
|
||||
return rule.pattern.test(value);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Check a Directory Path is Valid for Parsing or not ...
|
||||
*
|
||||
* @param {*} fileName
|
||||
* @returns
|
||||
*/
|
||||
function isAllowedFile(filePath) {
|
||||
//
|
||||
// Extract Deny Rules ...
|
||||
const denyRules = allowedPatterns.filter(
|
||||
p => p.kind === "file" && p.mode === "deny"
|
||||
);
|
||||
|
||||
//
|
||||
// Extract Allowed Rules ...
|
||||
const allowRules = allowedPatterns.filter(
|
||||
p => p.kind === "file" && p.mode === "allow"
|
||||
);
|
||||
|
||||
// Check Deny Rules First ...
|
||||
if (matchesPatterns(filePath, denyRules)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check Allowed Rules ...
|
||||
return matchesPatterns(filePath, allowRules);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check a Directory Path is Valid for Parsing or not ...
|
||||
*
|
||||
* @param {*} directoryPath
|
||||
* @returns
|
||||
*/
|
||||
function isAllowedDirectory(directoryPath) {
|
||||
//
|
||||
// Extract Deny Rules ...
|
||||
const denyRules = allowedPatterns.filter(
|
||||
p => p.kind === "directory" && p.mode === "deny"
|
||||
);
|
||||
|
||||
//
|
||||
// Extract Allowed Rules ...
|
||||
const allowRules = allowedPatterns.filter(
|
||||
p => p.kind === "directory" && p.mode === "allow"
|
||||
);
|
||||
|
||||
//
|
||||
// Check Deny Patterns as First ...
|
||||
if (matchesPatterns(directoryPath, denyRules)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// Check Allow Patterns Exists ...
|
||||
if (allowRules.length === 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// Chck Allowed Patterns Matched ...
|
||||
return matchesPatterns(directoryPath, allowRules);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loop through a Directory and Navigate files for including in Context ...
|
||||
*
|
||||
* @param {*} dir
|
||||
* @returns
|
||||
*/
|
||||
function walk(dir) {
|
||||
//
|
||||
// Reading Directory Content ...
|
||||
let entries;
|
||||
try {
|
||||
entries = fs.readdirSync(dir, { withFileTypes: true });
|
||||
} catch (error) {
|
||||
fs.appendFileSync(
|
||||
outputPath,
|
||||
`\n### ERROR reading directory: ${dir}\n${error.message}\n`,
|
||||
"utf8"
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Loop through Entries ...
|
||||
for (const entry of entries) {
|
||||
//
|
||||
const fullPath = path.join(dir, entry.name);
|
||||
|
||||
//
|
||||
// Ignore if Symlink ...
|
||||
if (entry.isSymbolicLink()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
// Handle if requested Path is Directory ...
|
||||
if (entry.isDirectory()) {
|
||||
//
|
||||
// Allowed Folders ...
|
||||
if (!isAllowedDirectory(fullPath)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
walk(fullPath);
|
||||
}
|
||||
else
|
||||
//
|
||||
// Handle if requested Path is File ...
|
||||
if (entry.isFile()) {
|
||||
//
|
||||
// Allowed File ...
|
||||
if (!isAllowedFile(fullPath)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
// Holds File Content ...
|
||||
let content;
|
||||
try {
|
||||
content = fs.readFileSync(fullPath, "utf8");
|
||||
} catch (error) {
|
||||
content = `// Error reading file: ${error.message}`;
|
||||
}
|
||||
|
||||
//
|
||||
// Append File Content for Context ...
|
||||
fs.appendFileSync(
|
||||
outputPath,
|
||||
`\n### FILE: ${fullPath}\n\n${content}\n`,
|
||||
"utf8"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
//#endregion
|
||||
Reference in New Issue
Block a user