This commit is contained in:
2025-01-18 12:16:28 +03:30
parent 9cdd5b4c7d
commit e74f64c51e
10 changed files with 2111 additions and 1003 deletions
@@ -426,656 +426,6 @@ class XC121SMCCycleHelper : public XCBase
return result;
}
/**
* Detect Market Structure ...
*
* @param model: XMarketStructure instance Reference ...
*
* @return ( bool )
*/
bool DetectMarketStructure(
XMarketStructure &model //
)
{
//
bool result = false;
//
model.Clean();
//
int barIndex = 0;
//
string symbol = GetSymbol();
ENUM_TIMEFRAMES period = GetPeriod();
//
model.symbol = symbol;
model.period = period;
//
int highestPeakIndex = -1;
double highestPeakVale = 0;
double highestPeak =
mX121Helper
.xpvHelper
.GetHighestPeak(
barIndex,
highestPeakIndex,
highestPeakVale //
);
//
int lowestValeIndex = -1;
double lowestValePeak = 0;
double lowestVale =
mX121Helper
.xpvHelper
.GetLowestVale(
barIndex,
lowestValeIndex,
lowestValePeak //
);
//
result = IsValidIndex(highestPeakIndex) &&
IsValidIndex(lowestValeIndex);
if (!result)
{
return result;
}
//
model.bias =
highestPeakIndex < lowestValeIndex
? X_DIRECTION_BEARISH
: highestPeakIndex > lowestValeIndex
? X_DIRECTION_BULLISH
: X_DIRECTION_NONE;
//
result = HasDirection(model.bias);
if (!result)
{
return result;
}
//
bool isBullish = IsBullish(model.bias);
//
// Looking for Change Of Character Proved ...
//
// Bullish Bias:
// - Price Must Break Up Lowst Vale's Peak;
// - Create a Vale Above Lowest Vale's Peak;
//
// Bearish Bias:
// - Price Must Breake Down HighestPeak's Vale;
// - Create a Peak Under Highest Peak's Vale;
//
// Checking Peak Breake Up ...
int lowestValePeakBreakeUpIndex = -1;
for (int i = lowestValeIndex; i >= barIndex; i--)
{
//
XOHCL iBar;
result = GetBar(iBar, i);
if (!result)
{
continue;
}
//
bool isBreake = IsBarBreak(
lowestValePeak,
X_DIRECTION_BULLISH,
iBar //
);
if (isBreake)
{
//
lowestValePeakBreakeUpIndex = i;
break;
}
}
bool isValidBreakeUpLowestValePeak = IsValidIndex(lowestValePeakBreakeUpIndex) &&
lowestValePeakBreakeUpIndex <= lowestValeIndex;
//
// Checking Vale Breake Down ...
int highestPeakValeBreakeDownIndex = -1;
for (int i = highestPeakIndex; i >= barIndex; i--)
{
//
XOHCL iBar;
result = GetBar(iBar, i);
if (!result)
{
continue;
}
//
bool isBreake = IsBarBreak(
highestPeakVale,
X_DIRECTION_BEARISH,
iBar //
);
if (isBreake)
{
//
highestPeakValeBreakeDownIndex = i;
break;
}
}
bool isValidBreakeDownHighestPeakVale = IsValidIndex(highestPeakValeBreakeDownIndex) &&
highestPeakValeBreakeDownIndex <= highestPeakIndex;
//
result = isBullish
? isValidBreakeUpLowestValePeak
: isValidBreakeDownHighestPeakVale;
if (!result)
{
return result;
}
//
// Checking Create a Vale above Peak ...
int valeAboveLowestValePeakIndex = -1;
double valeAboveLowestValePeakPeak = 0;
for (int i = lowestValePeakBreakeUpIndex; i >= barIndex; i--)
{
//
double iVale = mX121Helper.xpvHelper.GetVale(i);
//
bool isValid =
iVale > 0 &&
iVale > lowestValePeak;
if (isValid)
{
//
valeAboveLowestValePeakIndex = i;
valeAboveLowestValePeakPeak = mX121Helper.xpvHelper.GetPeak(i);
break;
}
}
bool isValidValeAboveLowestValePeak = IsValidIndex(valeAboveLowestValePeakIndex) &&
valeAboveLowestValePeakIndex < lowestValePeakBreakeUpIndex;
//
// Checking Create a Peak below Vale ...
int peakBelowHighestPeakValeIndex = -1;
double peakBelowHighestPeakValeVale = 0;
for (int i = highestPeakValeBreakeDownIndex; i >= barIndex; i--)
{
//
double iPeak = mX121Helper.xpvHelper.GetPeak(i);
//
bool isValid =
iPeak > 0 &&
iPeak < highestPeakVale;
if (isValid)
{
//
peakBelowHighestPeakValeIndex = i;
peakBelowHighestPeakValeVale = mX121Helper.xpvHelper.GetVale(i);
break;
}
}
bool isValidPeakBelowHighestPeakVale = IsValidIndex(peakBelowHighestPeakValeIndex) &&
peakBelowHighestPeakValeIndex < highestPeakValeBreakeDownIndex;
//
result = isBullish ? isValidValeAboveLowestValePeak
: isValidPeakBelowHighestPeakVale;
if (!result)
{
return result;
}
//
// Now we Have to Detect Valid Peaks and Valid Vales Here ...
// based on Detected Range ...
//
XPVPivotPoint iPeakPoint;
XPVPivotPoint iValePoint;
XPriceZones peakPriceZone;
XPriceZones valePriceZone;
//
XPOIState state;
mPOIDetector.GetState(
state //
);
//
int minRepetition = 5;
//
int from =
isBullish
? valeAboveLowestValePeakIndex
: peakBelowHighestPeakValeIndex;
for (int i = from; i >= barIndex; i--)
{
//
XOHCL iBar;
bool isInited = GetBar(iBar, i);
//
double iPeak = mX121Helper.xpvHelper.GetPeak(i);
double iVale = mX121Helper.xpvHelper.GetVale(i);
//
bool hasPeakPriceInsideZone = CalculatePriceInsideZones(
peakPriceZone,
state,
iPeak //
);
bool hasValePriceInsideZone = CalculatePriceInsideZones(
valePriceZone,
state,
iVale //
);
//
if (hasPeakPriceInsideZone)
{
//
// Peak ...
if (!iPeakPoint.IsValid())
{
//
// Initialization ...
iPeakPoint.value = iPeak;
iPeakPoint.repetition = 1;
iPeakPoint.type = XPV_PEAK;
iPeakPoint.time = iBar.time;
}
else
{
//
if (iPeakPoint.value == iPeak)
{
iPeakPoint.repetition++;
}
else
{
//
if (iPeakPoint.repetition > minRepetition)
{
//
AddRef(
iPeakPoint,
model.peaks //
);
//
AddRef(
peakPriceZone,
model.peakPriceZones //
);
}
//
iPeakPoint.Clean();
peakPriceZone.Clean();
iPeakPoint.value = iPeak;
iPeakPoint.repetition = 1;
iPeakPoint.type = XPV_PEAK;
iPeakPoint.time = iBar.time;
}
}
}
//
if (hasValePriceInsideZone)
{
//
// Vale ...
if (!iValePoint.IsValid())
{
//
// Initialization ...
iValePoint.value = iVale;
iValePoint.repetition = 1;
iValePoint.type = XPV_VALE;
iValePoint.time = iBar.time;
}
else
{
//
if (iValePoint.value == iVale)
{
iValePoint.repetition++;
}
else
{
//
if (iValePoint.repetition > minRepetition)
{
//
AddRef(
iValePoint,
model.vales //
);
//
AddRef(
valePriceZone,
model.valePriceZones //
);
}
//
iValePoint.Clean();
valePriceZone.Clean();
iValePoint.value = iVale;
iValePoint.repetition = 1;
iValePoint.type = XPV_VALE;
iValePoint.time = iBar.time;
}
}
}
}
//
// in Bullish Bias we Looking for Vales Oder ...
// in Bearish Bias we Looking for Peaks Oder ...
//
// Bullish Bias Drawn ...
if (isBullish)
{
//
result = GetBar(
model.lowestValeBar,
lowestValeIndex //
);
if (!result)
{
return result;
}
//
if (isValidBreakeUpLowestValePeak)
{
//
result = GetBar(
model.lowestValePeakBreakeUpBar,
lowestValePeakBreakeUpIndex //
);
if (!result)
{
return result;
}
}
//
if (isValidValeAboveLowestValePeak)
{
//
result = GetBar(
model.valeAboveLowestValePeakBar,
valeAboveLowestValePeakIndex //
);
if (!result)
{
return result;
}
}
}
//
// Bearish Bias Drawn ...
if (!isBullish)
{
//
result = GetBar(
model.highestPeakBar,
highestPeakIndex //
);
if (!result)
{
return result;
}
//
if (isValidBreakeDownHighestPeakVale)
{
//
result = GetBar(
model.highestPeakValeBreakeDownBar,
highestPeakValeBreakeDownIndex //
);
if (!result)
{
return result;
}
}
//
if (isValidPeakBelowHighestPeakVale)
{
//
result = GetBar(
model.peakBelowHighestPeakValeBar,
peakBelowHighestPeakValeIndex //
);
if (!result)
{
return result;
}
}
}
//
result = model.IsValid();
//
return result;
}
/**
* Detect Market Structure Method 2 ...
*
* @param model: XMarketStructure instance Reference ...
*
* @return ( bool )
*/
bool DetectMarketStructure(
ENUM_X_DIRECTION &dir,
int pivotsCount = 3 //
)
{
//
bool result = false;
//
int barIndex = 0;
//
if (pivotsCount < 3)
{
pivotsCount = 3;
}
//
dir = X_DIRECTION_NONE;
string symbol = GetSymbol();
ENUM_TIMEFRAMES period = GetPeriod();
//
int hpIndex = -1;
int hpIndexes[];
double hpValues[];
//
int lvIndex = -1;
int lvIndexes[];
double lvValues[];
//
for (int i = 0; i < pivotsCount; i++)
{
//
hpIndex = barIndex;
lvIndex = barIndex;
//
double lastHP = 0;
double lastLV = 0;
//
int hpCount = ArraySize(hpIndexes);
int lvCount = ArraySize(lvIndexes);
//
if (IsValidSize(hpCount))
{
//
lastHP = hpValues[hpCount - 1];
hpIndex = hpIndexes[hpCount - 1];
}
//
if (IsValidSize(lvCount))
{
//
lastLV = lvValues[lvCount - 1];
lvIndex = lvIndexes[lvCount - 1];
}
//
if (lastHP == 0)
{
//
lastHP = mX121Helper
.xpvHelper
.GetPeak(hpIndex);
}
//
if (lastLV == 0)
{
//
lastLV = mX121Helper
.xpvHelper
.GetVale(lvIndex);
}
//
int highestPeakIndex = -1;
double highesrPeak =
mX121Helper
.xpvHelper
.GetHigherPeak(
highestPeakIndex,
lastHP,
hpIndex //
);
if (IsValidIndex(highestPeakIndex))
{
//
Add(
highestPeakIndex,
hpIndexes //
);
//
Add(
highesrPeak,
hpValues //
);
}
//
int lowestValeIndex = -1;
double lowestVale =
mX121Helper
.xpvHelper
.GetLowerVale(
lowestValeIndex,
lastLV,
lvIndex //
);
if (IsValidIndex(lowestValeIndex))
{
//
Add(
lowestValeIndex,
lvIndexes //
);
//
Add(
lowestVale,
lvValues //
);
}
//
bool canBreak = ArraySize(hpIndexes) >= pivotsCount ||
ArraySize(lvIndexes) >= pivotsCount;
if (canBreak)
{
break;
}
}
//
ArrayReverse(hpValues);
ArrayReverse(hpIndexes);
int countHPs = ArraySize(hpIndexes);
//
ArrayReverse(lvValues);
ArrayReverse(lvIndexes);
int countLVs = ArraySize(lvIndexes);
//
bool isValidHPs = countHPs >= pivotsCount;
bool isValidLVs = countLVs >= pivotsCount;
//
result = isValidHPs ||
isValidLVs;
if (!result)
{
return result;
}
//
if (isValidHPs && isValidLVs)
{
//
hpIndex = hpIndexes[countHPs - 1];
lvIndex = lvIndexes[countLVs - 1];
}
//
dir =
!isValidHPs && isValidLVs
? X_DIRECTION_BULLISH
: !isValidLVs && isValidHPs
? X_DIRECTION_BEARISH
: hpIndex < lvIndex
? X_DIRECTION_BEARISH
: lvIndex < hpIndex
? X_DIRECTION_BULLISH
: X_DIRECTION_ALL;
//
return result;
}
//
// Tools ...
@@ -1166,91 +516,5 @@ class XC121SMCCycleHelper : public XCBase
ChartSetInteger(chartId, CHART_COLOR_VOLUME, mVolumesColor);
}
/**
* Fill Pivot Tick Zone ...
*
* @param pivot: XPVPivot instance Reference ...
*/
void CalculatePivotTickZone(
XPVPivot &pivot //
)
{
//
string symbol = GetSymbol();
ENUM_TIMEFRAMES period = GetPeriod();
//
bool isInited = false;
//
datetime from = pivot.from;
XOHCL iFromBar;
int iFromBarIndex = iBarShift(
symbol,
period,
from //
);
isInited = iFromBar.Init(
symbol,
period,
iFromBarIndex //
);
if (!isInited)
{
return;
}
//
datetime to = pivot.to;
XOHCL iToBar;
int iToBarIndex = iBarShift(
symbol,
period,
to //
);
isInited = iToBar.Init(
symbol,
period,
iToBarIndex //
);
if (!isInited)
{
return;
}
//
if (iFromBarIndex <= iToBarIndex)
{
return;
}
//
XCTicksZone *iZone;
iZone = new XCTicksZone();
//
int ticksLevels = mPOIDetector.TicksRangeZoneLevel();
int ticksRange = mPOIDetector.TicksRangeZoneRange();
isInited = ticksLevels > 0 &&
ticksRange > 0;
if (!isInited)
{
return;
}
//
isInited = iZone.Init(
iFromBar,
iToBar //
);
if (!isInited)
{
return;
}
//
pivot.state.ticksZone = iZone;
}
//
};