Files
MQL5Data/Documents/BKP/pivots.mq5
T
2024-07-01 02:39:01 +03:30

846 lines
14 KiB
Plaintext

//
struct XPivot
{
//
double pivot; // Pivot Price ...
int breaks; // Number of Breaks ...
int rejects; // Number of Rejects ...
//
void XPivot()
{
Clean();
}
//
// Tools ...
//
// Cleanup ...
void Clean()
{
//
pivot = 0;
breaks = 0;
rejects = 0;
}
//
// Validate ...
bool IsValid()
{
//
bool result = false;
//
result = pivot > 0;
//
return result;
}
};
//
struct XPivotTracker
{
//
XPivot pivots[];
//
// Constructor ...
void XPivotTracker()
{
Clean();
}
//
// Tools ...
//
// Cleanup ...
void Clean()
{
//
Clean(pivots);
}
//
int Count()
{
return ArraySize(pivots);
}
//
double Get(int index)
{
//
double result = 0;
//
NormalizeIndex(index, pivots);
//
XPivot iPivot = pivots[index];
//
result = iPivot.pivot;
//
return result;
}
//
XPivot GetPivot(int index)
{
//
XPivot result;
//
NormalizeIndex(index, pivots);
//
result = pivots[index];
//
return result;
}
//
bool Add(double mPivot)
{
//
bool result = false;
//
result = mPivot > 0 && !Has(mPivot);
if (!result)
{
return result;
}
//
XPivot pivot;
pivot.pivot = mPivot;
//
AddRef(
pivot,
pivots //
);
//
result = true;
//
return result;
}
//
int Adds(double &mPivots[])
{
//
int result = 0;
//
int pivotsCount = ArraySize(mPivots);
if (!IsValidSize(pivotsCount))
{
return result;
}
//
for (int i = 0; i < pivotsCount; i++)
{
//
double iPivot = mPivots[i];
//
bool isAdded = Add(iPivot);
if (isAdded)
{
result++;
}
}
//
return result;
}
//
int FindIndex(double mPivot)
{
//
int result = -1;
//
if (mPivot <= 0)
{
return result;
}
//
int count = Count();
if (!IsValidSize(count))
{
return result;
}
//
for (int i = 0; i < count; i++)
{
//
XPivot iPivot = pivots[i];
//
if (iPivot.pivot == mPivot)
{
//
result = i;
break;
}
}
//
return result;
}
//
double Has(double mPivot)
{
//
bool result = false;
//
int pivotIDX = FindIndex(mPivot);
result = pivotIDX >= 0;
//
return result;
}
//
int Reject(double mPivot)
{
//
int result = 0;
//
int pivotIDX = FindIndex(mPivot);
if (pivotIDX < 0)
{
return result;
}
//
pivots[pivotIDX].rejects++;
//
result = pivots[pivotIDX].rejects;
//
return result;
}
//
int Break(double mPivot)
{
//
int result = 0;
//
int pivotIDX = FindIndex(mPivot);
if (pivotIDX < 0)
{
return result;
}
//
pivots[pivotIDX].breaks++;
//
result = pivots[pivotIDX].breaks;
//
return result;
}
//
bool Remove(double mPivot)
{
//
bool result = false;
//
int pivotIDX = FindIndex(mPivot);
result = pivotIDX >= 0;
if (!result)
{
return result;
}
//
result = ArrayRemove(
pivots,
pivotIDX,
1 //
);
//
return result;
}
//
bool HasChild()
{
//
bool result = false;
//
int count = Count();
result = IsValidSize(count);
//
return result;
}
};
//
// Model Support and Resistance
// for Specific Bar ...
struct XOHCLSupRes
{
//
// Props ...
//
/// Resistances ...
double res[];
//
// Supports ...
double sup[];
//
// Constructor ...
XOHCLSupRes()
{
Clean();
}
//
// Init ...
bool Init(
double price, // Price ...
const double &pivots[], // Provided Pivot Points ...
int count = 3, // Number of Requireds ...
double step = 0 // Distance between each item with it's Last Side ...
)
{
//
bool result = false;
//
Clean();
//
if (price <= 0)
{
return result;
}
//
int pivotsCount = ArraySize(pivots);
if (pivotsCount <= 0)
{
return result;
}
//
if (count <= 0 ||
count > pivotsCount - 1)
{
return result;
}
//
double lastR = 0;
double tmpR[];
//
double lastS = 0;
double tmpS[];
//
// Extract Supports ...
// which prices is under low of candle ...
//
// Extract Resistance ...
// which prices is over high of candle ...
for (int i = 0; i < pivotsCount; i++)
{
//
double iFlat = pivots[i];
//
if (iFlat > price)
{
//
bool canAdd =
step <= 0
? true
: lastR == 0 || MathAbs(iFlat - lastR) >= step;
if (canAdd)
{
//
Add(
iFlat,
tmpR);
//
lastR = iFlat;
}
}
else if (iFlat < price)
{
//
bool canAdd =
step <= 0
? true
: lastS == 0 || MathAbs(iFlat - lastS) >= step;
if (canAdd)
{
//
Add(
iFlat,
tmpS);
//
lastS = iFlat;
}
}
}
//
// Sorting Founded Resistance and Supports ...
//
// Since Resistance Levels must be Increasing ...
ArraySort(tmpR);
//
// Since Support Levels must be Decreasing ...
ArraySort(tmpS);
ArrayReverse(tmpS);
//
// Fill Resistance ...
int tmpRCount = ArraySize(tmpR);
if (tmpRCount > 0)
{
//
if (tmpRCount < count)
{
//
ArrayCopy(
res,
tmpR);
}
else
{
//
ArrayCopy(
res,
tmpR,
0,
0,
count);
}
}
//
// Fill Supports ...
int tmpSCount = ArraySize(tmpS);
if (tmpSCount > 0)
{
//
if (tmpSCount < count)
{
//
ArrayCopy(
sup,
tmpS);
}
else
{
//
ArrayCopy(
sup,
tmpS,
0,
0,
count);
}
}
//
result = IsValid();
//
return result;
}
//
// Tools ...
//
// Cleanup ...
void Clean()
{
//
Clean(sup);
Clean(res);
}
//
// Validate ...
bool IsValid()
{
//
bool result = false;
//
result =
//
CountSupports() > 0 ||
CountResistances() > 0
//
;
//
return result;
}
//
int CountSupports()
{
return ArraySize(sup);
}
//
int CountResistances()
{
return ArraySize(res);
}
};
//
// Track Value Changes ...
template <typename T>
struct XValueTracker
{
//
// Definitions ...
//
// Model a Value Change ...
struct XValueChange
{
//
// Props ...
datetime at; // Change Time
T from; // Before Change Value
T to; // After Change Value
//
// Constructor ...
XValueChange()
{
Clean();
}
//
// Cleanup ...
void Clean()
{
//
at = NULL;
from = NULL;
to = NULL;
}
//
// Validate ...
bool IsValid()
{
//
bool result = false;
//
result = IsValid(at);
if (!result)
{
return result;
}
//
result = NotEmpty(from) &&
NotEmpty(to);
//
return result;
}
};
//
// Props ...
XValueChange changes[]; // Hold Changes
//
// Constructor ...
XValueTracker()
{
Clean();
}
//
// Track a Change Happens Or Not ...
bool Track(
const T &source[] // Data Source for Track Changes
)
{
//
bool result = false;
//
if (ArraySize(source) <= 1)
{
return result;
}
//
datetime time = TimeCurrent();
//
double from = source[1];
double to = source[0];
//
result = to != from;
if (result)
{
return result;
}
//
XValueChange lastChange;
bool hasLastChange =
GetLastItem(
lastChange,
changes
//
);
result =
!hasLastChange
? true
: lastChange.at < time &&
lastChange.to != to &&
lastChange.from != from;
if (!result)
{
return result;
}
//
lastChange.Clean();
//
lastChange.to = to;
lastChange.at = time;
lastChange.from = from;
//
AddRef(
lastChange,
changes
//
);
//
return result;
}
//
// Tools ...
//
// Cleanup ...
void Clean()
{
Clean(changes);
}
};
//
int GenerateEQMOrders(
XSignal &orders[], // Result
XPosition &position, // Supported Position
XOHCLSupRes &supRes, // Data Source
bool longs = true,
bool shorts = true //
)
{
//
int result = 0;
//
Clean(orders);
//
if (!supRes.IsValid() ||
!position.IsValid())
{
return result;
}
//
if (longs)
{
//
double longLevels[];
//
Copy(
supRes.res,
longLevels //
);
//
double minSup = GetMin(
supRes.sup //
);
if (minSup > 0)
{
//
Add(
minSup,
longLevels //
);
}
//
ArraySort(longLevels);
//
if (ArraySize(longLevels) > 2)
{
//
for (int i = 0; i < ArraySize(longLevels) - 2; i++)
{
//
double iSL = longLevels[i];
double iEntry = longLevels[i + 1];
double iTP = longLevels[i + 2];
//
XSignal iSignal;
bool isPrepared = iSignal.PrepareStopLong(
position.symbol,
XEQMSupportToken,
position.period,
iEntry,
position.volume,
iSL,
iTP //
);
if (isPrepared)
{
//
string comment = GenerateSupportTag(position.ticket);
iSignal.comment = comment;
//
AddRef(
iSignal,
orders //
);
}
}
}
}
//
if (shorts)
{
//
double shortLevels[];
//
Copy(
supRes.sup,
shortLevels //
);
//
double maxRes = GetMax(
supRes.res //
);
if (maxRes > 0)
{
//
Add(
maxRes,
shortLevels //
);
}
//
ArraySort(shortLevels);
ArrayReverse(shortLevels);
//
if (ArraySize(shortLevels) > 2)
{
//
for (int i = 0; i < ArraySize(shortLevels) - 2; i++)
{
//
double iSL = shortLevels[i];
double iEntry = shortLevels[i + 1];
double iTP = shortLevels[i + 2];
//
XSignal iSignal;
bool isPrepared = iSignal.PrepareStopShort(
position.symbol,
XEQMSupportToken,
position.period,
iEntry,
position.volume,
iSL,
iTP //
);
if (isPrepared)
{
//
string comment = GenerateSupportTag(position.ticket);
iSignal.comment = comment;
//
AddRef(
iSignal,
orders //
);
}
}
}
}
//
result = ArraySize(orders);
//
return result;
}