last ...
This commit is contained in:
@@ -57,8 +57,10 @@ class XCPivotDetector : public XCBase
|
|||||||
//
|
//
|
||||||
// Constructor ...
|
// Constructor ...
|
||||||
XCPivotDetector(
|
XCPivotDetector(
|
||||||
XCAlert *_alert = NULL, //
|
XCAlert *_alert = NULL, // Alert instance Pointer ...
|
||||||
int _maxAllowedProcessableZones = 10 //
|
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 ...
|
// Normalize ...
|
||||||
if (_maxAllowedProcessableZones <= 5)
|
if (_maxAllowedProcessableZones < 0)
|
||||||
{
|
{
|
||||||
_maxAllowedProcessableZones = 5;
|
_maxAllowedProcessableZones = 0;
|
||||||
}
|
}
|
||||||
|
mPivotPrefix = _pivotPrefix;
|
||||||
|
mSupportInvertedZones = _supportInvertedZones;
|
||||||
mMaxAllowedProcessableZones = _maxAllowedProcessableZones;
|
mMaxAllowedProcessableZones = _maxAllowedProcessableZones;
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -167,13 +171,13 @@ class XCPivotDetector : public XCBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
hasPeak = false;
|
hasPeak = true;
|
||||||
hasVale = false;
|
hasVale = true;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Loop through Bars for Approved Side ...
|
// Loop through Bars for Approved Side ...
|
||||||
int jStart = i + 1;
|
int jStart = i + 1;
|
||||||
int jEnd = i + pivotApproved;
|
int jEnd = i + pivotApproved + 1;
|
||||||
for (int j = jStart; j < jEnd; j++)
|
for (int j = jStart; j < jEnd; j++)
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
@@ -182,8 +186,8 @@ class XCPivotDetector : public XCBase
|
|||||||
jHigh = iHigh(iBar.symbol, iBar.period, j);
|
jHigh = iHigh(iBar.symbol, iBar.period, j);
|
||||||
|
|
||||||
//
|
//
|
||||||
hasVale = iBar.low < jLow;
|
hasVale = hasVale && (iBar.low < jLow);
|
||||||
hasPeak = iBar.high > jHigh;
|
hasPeak = hasPeak && (iBar.high > jHigh);
|
||||||
has = hasVale || hasPeak;
|
has = hasVale || hasPeak;
|
||||||
if (!has)
|
if (!has)
|
||||||
{
|
{
|
||||||
@@ -204,7 +208,7 @@ class XCPivotDetector : public XCBase
|
|||||||
//
|
//
|
||||||
// Loop through Barse for Approved Side ...
|
// Loop through Barse for Approved Side ...
|
||||||
jStart = i - pivotApproved;
|
jStart = i - pivotApproved;
|
||||||
jEnd = i - 1;
|
jEnd = i;
|
||||||
for (int j = jStart; j < jEnd; j++)
|
for (int j = jStart; j < jEnd; j++)
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
@@ -251,7 +255,7 @@ class XCPivotDetector : public XCBase
|
|||||||
tmpPrice = EMPTY_VALUE;
|
tmpPrice = EMPTY_VALUE;
|
||||||
tmpZonePrice = EMPTY_VALUE;
|
tmpZonePrice = EMPTY_VALUE;
|
||||||
jStart = i - pivotApproved;
|
jStart = i - pivotApproved;
|
||||||
jEnd = i + pivotApproved;
|
jEnd = i + pivotApproved + 1;
|
||||||
for (int j = jStart; j < jEnd; j++)
|
for (int j = jStart; j < jEnd; j++)
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
@@ -297,7 +301,7 @@ class XCPivotDetector : public XCBase
|
|||||||
tmpPrice = EMPTY_VALUE;
|
tmpPrice = EMPTY_VALUE;
|
||||||
tmpZonePrice = EMPTY_VALUE;
|
tmpZonePrice = EMPTY_VALUE;
|
||||||
jStart = i - pivotApproved;
|
jStart = i - pivotApproved;
|
||||||
jEnd = i + pivotApproved;
|
jEnd = i + pivotApproved + 1;
|
||||||
for (int j = jStart; j < jEnd; j++)
|
for (int j = jStart; j < jEnd; j++)
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
@@ -341,6 +345,46 @@ class XCPivotDetector : public XCBase
|
|||||||
}
|
}
|
||||||
// #endregion
|
// #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
|
// #endregion
|
||||||
|
|
||||||
// #region Event Listener Registration ...
|
// #region Event Listener Registration ...
|
||||||
@@ -427,9 +471,6 @@ class XCPivotDetector : public XCBase
|
|||||||
//
|
//
|
||||||
Clean(mOnPeakDetectedHandlers);
|
Clean(mOnPeakDetectedHandlers);
|
||||||
Clean(mOnValeDetectedHandlers);
|
Clean(mOnValeDetectedHandlers);
|
||||||
|
|
||||||
//
|
|
||||||
mPivotPrefix = "XSDT";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -448,6 +489,13 @@ class XCPivotDetector : public XCBase
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Validate Peak Box based on Price ...
|
||||||
|
if (!IsBoxValid(peakBox, 0, X_BOUNDARY_PRICE_UP_DOWN))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Update To ...
|
// Update To ...
|
||||||
peakBox.to = TimeCurrent();
|
peakBox.to = TimeCurrent();
|
||||||
@@ -486,7 +534,7 @@ class XCPivotDetector : public XCBase
|
|||||||
{
|
{
|
||||||
//
|
//
|
||||||
// Validate New Peak based on Youngest One ...
|
// Validate New Peak based on Youngest One ...
|
||||||
hasPeaks = peakBox.upper > peaks[idx].upper;
|
hasPeaks = peakBox.upper < peaks[idx].upper;
|
||||||
if (hasPeaks)
|
if (hasPeaks)
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
@@ -524,6 +572,13 @@ class XCPivotDetector : public XCBase
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Validate Peak Box based on Price ...
|
||||||
|
if (!IsBoxValid(valeBox, 0, X_BOUNDARY_PRICE_UP_DOWN))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Update To ...
|
// Update To ...
|
||||||
valeBox.to = TimeCurrent();
|
valeBox.to = TimeCurrent();
|
||||||
@@ -561,7 +616,7 @@ class XCPivotDetector : public XCBase
|
|||||||
{
|
{
|
||||||
//
|
//
|
||||||
// Validate New Vale based on Youngest One ...
|
// Validate New Vale based on Youngest One ...
|
||||||
hasVales = valeBox.lower < vales[idx].lower;
|
hasVales = valeBox.lower > vales[idx].lower;
|
||||||
if (hasVales)
|
if (hasVales)
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
@@ -738,6 +793,7 @@ class XCPivotDetector : public XCBase
|
|||||||
//
|
//
|
||||||
// Props ...
|
// Props ...
|
||||||
string mPivotPrefix; // Prefix ...
|
string mPivotPrefix; // Prefix ...
|
||||||
|
bool mSupportInvertedZones; // Support Inverted Zones ...
|
||||||
int mMaxAllowedProcessableZones; // Max Allowed Processable Zones ...
|
int mMaxAllowedProcessableZones; // Max Allowed Processable Zones ...
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -826,6 +882,7 @@ class XCPivotDetector : public XCBase
|
|||||||
//
|
//
|
||||||
Add(i, removeIDX);
|
Add(i, removeIDX);
|
||||||
NotifyPeakBreaked(peaks[i]);
|
NotifyPeakBreaked(peaks[i]);
|
||||||
|
HandleBreakedZone(peaks[i], cBar);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -850,6 +907,7 @@ class XCPivotDetector : public XCBase
|
|||||||
//
|
//
|
||||||
Add(i, removeIDX);
|
Add(i, removeIDX);
|
||||||
NotifyValeBreaked(vales[i]);
|
NotifyValeBreaked(vales[i]);
|
||||||
|
HandleBreakedZone(vales[i], cBar);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -894,6 +952,87 @@ class XCPivotDetector : public XCBase
|
|||||||
CleanupPeaks();
|
CleanupPeaks();
|
||||||
CleanupVales();
|
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;
|
XCAlert *eaAlert;
|
||||||
XCPOIDrawer *eaDrawer;
|
XCPOIDrawer *eaDrawer;
|
||||||
CArrayObj eaDrawnObjects;
|
|
||||||
XCPivotDetector *eaPivotDetector;
|
|
||||||
XCSessionDetector *eaSessionDetector;
|
XCSessionDetector *eaSessionDetector;
|
||||||
|
|
||||||
|
//
|
||||||
|
XCPivotDetector *eaMajorPivotDetector;
|
||||||
|
XCPivotDetector *eaMinorPivotDetector;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Last Processing Pivots Time ...
|
// 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
|
// #endregion
|
||||||
|
|
||||||
// #region Global Event Handlers ...
|
// #region Global Event Handlers ...
|
||||||
@@ -84,12 +95,19 @@ void OnDeinit(const int reason)
|
|||||||
// Destroy Timer ...
|
// Destroy Timer ...
|
||||||
// If Initialized ...
|
// If Initialized ...
|
||||||
|
|
||||||
|
//
|
||||||
|
eaMajorPivotsDrawConfig.Clean();
|
||||||
|
eaMinorPivotsDrawConfig.Clean();
|
||||||
|
eaPointedMajorPivotsDrawConfig.Clean();
|
||||||
|
eaPointedMinorPivotsDrawConfig.Clean();
|
||||||
|
|
||||||
//
|
//
|
||||||
// Cleanup Resources ...
|
// Cleanup Resources ...
|
||||||
ZeroMemory(eaAlert);
|
ZeroMemory(eaAlert);
|
||||||
ZeroMemory(eaDrawer);
|
ZeroMemory(eaDrawer);
|
||||||
ZeroMemory(eaPivotDetector);
|
|
||||||
ZeroMemory(eaSessionDetector);
|
ZeroMemory(eaSessionDetector);
|
||||||
|
ZeroMemory(eaMajorPivotDetector);
|
||||||
|
ZeroMemory(eaMinorPivotDetector);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -103,7 +121,12 @@ void OnTick()
|
|||||||
|
|
||||||
//
|
//
|
||||||
// Process Pivot Detector ...
|
// Process Pivot Detector ...
|
||||||
HandleProcessPviots();
|
HandleProcessMajorPviots();
|
||||||
|
HandleProcessMinorPviots();
|
||||||
|
|
||||||
|
//
|
||||||
|
// Detecting Bias ...
|
||||||
|
HanldeBiasDetection();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -142,8 +165,8 @@ bool InitializeRequirements()
|
|||||||
// Initialize Alert ...
|
// Initialize Alert ...
|
||||||
eaAlert = new XCAlert(
|
eaAlert = new XCAlert(
|
||||||
ShortName,
|
ShortName,
|
||||||
true, // Enable Alert ...
|
false, // Enable Alert ...
|
||||||
true, // Log Alert ...
|
false, // Log Alert ...
|
||||||
false, // Terminal Alert ...
|
false, // Terminal Alert ...
|
||||||
false, // Mail Alert ...
|
false, // Mail Alert ...
|
||||||
false, // Push Alerts ...
|
false, // Push Alerts ...
|
||||||
@@ -179,20 +202,82 @@ bool InitializeRequirements()
|
|||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Initialize Pivot Detector ...
|
// Initialize Major Pivot Detector ...
|
||||||
eaPivotDetector = new XCPivotDetector(
|
eaMajorPivotDetector = new XCPivotDetector(
|
||||||
eaAlert // Alert ...
|
eaAlert, // Alert ...
|
||||||
|
"X121SDTMajor", // Pivot Prefix ...
|
||||||
|
false, // Support Inverted Zones ...
|
||||||
|
0 // Processable Zones ...
|
||||||
);
|
);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Register Event Handlers ...
|
// Register Event Handlers ...
|
||||||
eaPivotDetector.AddOnPeakBreakedHandler(OnPeakBreakedHandler);
|
eaMajorPivotDetector.AddOnPeakBreakedHandler(OnMajorPeakBreakedHandler);
|
||||||
eaPivotDetector.AddOnValeBreakedHandler(OnValeBreakedHandler);
|
eaMajorPivotDetector.AddOnValeBreakedHandler(OnMajorValeBreakedHandler);
|
||||||
eaPivotDetector.AddOnPeakDetectedHandler(OnPeakDetectedHandler);
|
eaMajorPivotDetector.AddOnPeakDetectedHandler(OnMajorPeakDetectedHandler);
|
||||||
eaPivotDetector.AddOnValeDetectedHandler(OnValeDetectedHandler);
|
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)
|
if (!result)
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
@@ -205,7 +290,7 @@ bool InitializeRequirements()
|
|||||||
/**
|
/**
|
||||||
* Process Pivots ...
|
* Process Pivots ...
|
||||||
*/
|
*/
|
||||||
void HandleProcessPviots()
|
void HandleProcessMajorPviots()
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
// Initialize Pivot Processing Bar ...
|
// Initialize Pivot Processing Bar ...
|
||||||
@@ -213,7 +298,7 @@ void HandleProcessPviots()
|
|||||||
bool has = bar.Init(
|
bool has = bar.Init(
|
||||||
_Symbol,
|
_Symbol,
|
||||||
PERIOD_H4,
|
PERIOD_H4,
|
||||||
1 // Last Completed 4H Bar ...
|
1 // Last Completed Bar ...
|
||||||
);
|
);
|
||||||
if (!has)
|
if (!has)
|
||||||
{
|
{
|
||||||
@@ -223,15 +308,18 @@ void HandleProcessPviots()
|
|||||||
//
|
//
|
||||||
// Validate Passing Bar ...
|
// Validate Passing Bar ...
|
||||||
has =
|
has =
|
||||||
!IsXValid(eaLastPivotProcessing) ||
|
!IsXValid(eaLastMajorPivotProcessing) ||
|
||||||
bar.time > eaLastPivotProcessing;
|
bar.time > eaLastMajorPivotProcessing;
|
||||||
if (!has)
|
if (!has)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
eaPivotDetector.Process(
|
eaLastMajorPivotProcessing = bar.time;
|
||||||
|
|
||||||
|
//
|
||||||
|
eaMajorPivotDetector.Process(
|
||||||
bar, // XOHCL Bar ...
|
bar, // XOHCL Bar ...
|
||||||
2, // Pivot Approvation Length ...
|
2, // Pivot Approvation Length ...
|
||||||
20 // Loopback ...
|
20 // Loopback ...
|
||||||
@@ -239,30 +327,141 @@ void HandleProcessPviots()
|
|||||||
|
|
||||||
//
|
//
|
||||||
// Handle Draw Pivots ...
|
// Handle Draw Pivots ...
|
||||||
|
if (!eaDrawMajorPivots)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
XBoxZone tmps[];
|
XBoxZone tmps[];
|
||||||
CArrayObj *objects;
|
|
||||||
FillNotExists(
|
FillNotExists(
|
||||||
tmps, // Dest ...
|
tmps, // Dest ...
|
||||||
eaPivotDetector.peaks, // Source ...
|
eaMajorPivotDetector.peaks, // Source ...
|
||||||
false // Force Clean ...
|
false // Force Clean ...
|
||||||
);
|
);
|
||||||
FillNotExists(
|
FillNotExists(
|
||||||
tmps, // Dest ...
|
tmps, // Dest ...
|
||||||
eaPivotDetector.vales, // Source ...
|
eaMajorPivotDetector.vales, // Source ...
|
||||||
false // Force Clean ...
|
false // Force Clean ...
|
||||||
);
|
);
|
||||||
if (HasChild(tmps))
|
if (HasChild(tmps))
|
||||||
{
|
{
|
||||||
eaDrawer.DrawBoxes(
|
eaDrawer.DrawZones(
|
||||||
tmps, // Boxes ...
|
tmps, // Boxes ...
|
||||||
objects, // Objects to Hold ...
|
eaMajorPivotsDrawConfig // Draw Config ...
|
||||||
false // Ignore Type Name ...
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
XClean(tmps);
|
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
|
// #endregion
|
||||||
@@ -275,7 +474,7 @@ void HandleProcessPviots()
|
|||||||
*
|
*
|
||||||
* @param box: XBoxZone instance ...
|
* @param box: XBoxZone instance ...
|
||||||
*/
|
*/
|
||||||
void OnPeakBreakedHandler(XBoxZone &box)
|
void OnMajorPeakBreakedHandler(XBoxZone &box)
|
||||||
{
|
{
|
||||||
// DebugBreak();
|
// DebugBreak();
|
||||||
}
|
}
|
||||||
@@ -285,7 +484,7 @@ void OnPeakBreakedHandler(XBoxZone &box)
|
|||||||
*
|
*
|
||||||
* @param box: XBoxZone instance ...
|
* @param box: XBoxZone instance ...
|
||||||
*/
|
*/
|
||||||
void OnValeBreakedHandler(XBoxZone &box)
|
void OnMajorValeBreakedHandler(XBoxZone &box)
|
||||||
{
|
{
|
||||||
// DebugBreak();
|
// DebugBreak();
|
||||||
}
|
}
|
||||||
@@ -295,9 +494,16 @@ void OnValeBreakedHandler(XBoxZone &box)
|
|||||||
*
|
*
|
||||||
* @param box: XBoxZone instance ...
|
* @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 ...
|
* @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();
|
// 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
|
// #endregion
|
||||||
|
|
||||||
// #region Session Detector Event Handlers ...
|
// #region Session Detector Event Handlers ...
|
||||||
|
|||||||
@@ -3722,6 +3722,125 @@ bool IsBoxValid(
|
|||||||
return result;
|
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(
|
void SortBoxes(
|
||||||
XBoxZone &items[],
|
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