mql5/Experts/Motivated/Utils/Indicator.mqh
younglubah-gmail 674b5de149 new files added
2026-06-09 05:44:15 +02:00

697 lines
No EOL
16 KiB
MQL5

//+------------------------------------------------------------------+
//| Swing.mqh |
//+------------------------------------------------------------------+
#property strict
#ifndef __SWING_MQH__
#define __SWING_MQH__
#include <Mql5Book\Timer.mqh>
#include <Mql5Book\Indicators.mqh>
#include <Collection\DynamicArrayList.mqh>
#include "TimePrice.mqh"
string location = "DexterrFX - SMC Bible/";
//+------------------------------------------------------------------+
//| Swing |
//+------------------------------------------------------------------+
class Swing : public CIndicator {
private:
string symbol;
ENUM_TIMEFRAMES timeframe;
double highBuffer[];
double lowBuffer[];
datetime highTimes[];
datetime lowTimes[];
CArrayList<TimePrice> highs;
CArrayList<TimePrice> lows;
CArrayList<TimePrice> zigzag;
bool asSeries;
private:
datetime FirstOfPreviousMonths(datetime currentTime, int monthsBack) {
MqlDateTime dt;
TimeToStruct(currentTime, dt);
dt.mon -= monthsBack;
while(dt.mon <= 0) {
dt.mon += 12;
dt.year--;
}
dt.day = 1;
dt.hour = 0;
dt.min = 0;
dt.sec = 0;
return StructToTime(dt);
}
int MapIndex(int i, int total) {
if(i < 0 || i >= total)
return -1;
if(!asSeries)
return i;
return total - 1 - i;
}
bool ComesBefore(TimePrice &a, TimePrice &b) {
if(!asSeries)
return a.x < b.x;
return a.x > b.x;
}
bool SamePoint(TimePrice &a, TimePrice &b) {
return a.x == b.x && a.y == b.y;
}
bool IsBetterSameTypePoint(TimePrice &currentPoint, TimePrice &newPoint, int type) {
if(type > 0)
return newPoint.y > currentPoint.y;
return newPoint.y < currentPoint.y;
}
void AddZigZagPoint(TimePrice &point, int type, TimePrice &workPoints[], int &workTypes[], int &count) {
if(!point.Ok())
return;
if(count <= 0) {
ArrayResize(workPoints, 1);
ArrayResize(workTypes, 1);
workPoints[0] = point;
workTypes[0] = type;
count = 1;
return;
}
int last = count - 1;
if(SamePoint(workPoints[last], point))
return;
if(workTypes[last] == type) {
if(IsBetterSameTypePoint(workPoints[last], point, type))
workPoints[last] = point;
return;
}
ArrayResize(workPoints, count + 1);
ArrayResize(workTypes, count + 1);
workPoints[count] = point;
workTypes[count] = type;
count++;
}
void RebuildSwingList(double &source[], datetime &times[], CArrayList<TimePrice> &target) {
target.Clear();
int totalValues = ArraySize(source);
int totalTimes = ArraySize(times);
int total = MathMin(totalValues, totalTimes);
for(int logical = 0; logical < total; logical++) {
int physical = MapIndex(logical, total);
if(physical < 0)
continue;
if(!IsValidValue(source[physical]))
continue;
if(times[physical] <= 0)
continue;
TimePrice point;
point.Set(logical, times[physical], source[physical]);
if(point.Ok())
target.Add(point);
}
}
void BuildFullList(double &source[], datetime &times[], TimePrice &result[]) {
int totalValues = ArraySize(source);
int totalTimes = ArraySize(times);
int total = MathMin(totalValues, totalTimes);
ArrayResize(result, total);
for(int logical = 0; logical < total; logical++) {
int physical = MapIndex(logical, total);
result[logical].Reset();
result[logical].i = logical;
if(physical < 0)
continue;
result[logical].Set(logical, times[physical], source[physical]);
}
}
void BuildValueOnlyList(double &source[], datetime &times[], TimePrice &result[]) {
ArrayResize(result, 0);
int totalValues = ArraySize(source);
int totalTimes = ArraySize(times);
int total = MathMin(totalValues, totalTimes);
int count = 0;
for(int logical = 0; logical < total; logical++) {
int physical = MapIndex(logical, total);
if(physical < 0)
continue;
if(!IsValidValue(source[physical]))
continue;
if(times[physical] <= 0)
continue;
ArrayResize(result, count + 1);
result[count].Reset();
result[count].Set(logical, times[physical], source[physical]);
count++;
}
}
void BuildZigZagFromSwings() {
zigzag.Clear();
TimePrice highArray[];
TimePrice lowArray[];
highs.GetAll(highArray);
lows.GetAll(lowArray);
int highCount = ArraySize(highArray);
int lowCount = ArraySize(lowArray);
int highIndex = 0;
int lowIndex = 0;
TimePrice workPoints[];
int workTypes[];
int workCount = 0;
while(highIndex < highCount || lowIndex < lowCount) {
bool useHigh = false;
bool useLow = false;
if(highIndex < highCount && lowIndex < lowCount) {
TimePrice h = highArray[highIndex];
TimePrice l = lowArray[lowIndex];
if(h.x == l.x) {
AddZigZagPoint(h, 1, workPoints, workTypes, workCount);
AddZigZagPoint(l, -1, workPoints, workTypes, workCount);
highIndex++;
lowIndex++;
continue;
}
if(ComesBefore(h, l))
useHigh = true;
else
useLow = true;
}
else if(highIndex < highCount) {
useHigh = true;
}
else if(lowIndex < lowCount) {
useLow = true;
}
if(useHigh) {
TimePrice point = highArray[highIndex];
AddZigZagPoint(point, 1, workPoints, workTypes, workCount);
highIndex++;
}
if(useLow) {
TimePrice point = lowArray[lowIndex];
AddZigZagPoint(point, -1, workPoints, workTypes, workCount);
lowIndex++;
}
}
for(int i = 0; i < workCount; i++)
zigzag.Add(workPoints[i]);
}
public:
Swing() {
symbol = _Symbol;
timeframe = _Period;
asSeries = false;
ArrayResize(highBuffer, 0);
ArrayResize(lowBuffer, 0);
ArrayResize(highTimes, 0);
ArrayResize(lowTimes, 0);
}
~Swing() {
ArrayFree(highBuffer);
ArrayFree(lowBuffer);
ArrayFree(highTimes);
ArrayFree(lowTimes);
highs.Reset();
lows.Reset();
zigzag.Reset();
}
void SetAsSeries(bool value) {
asSeries = value;
RebuildSwingList(highBuffer, highTimes, highs);
RebuildSwingList(lowBuffer, lowTimes, lows);
BuildZigZagFromSwings();
}
bool GetAsSeries() {
return asSeries;
}
bool IsValidValue(double value) {
return value != 0.0 && value != EMPTY_VALUE;
}
int Init(string indName, string pSymbol, ENUM_TIMEFRAMES pTimeframe, int InpLeftRightBars = 3, int InpSwingWindow = 1) {
symbol = pSymbol;
timeframe = pTimeframe;
handle = iCustom(symbol, timeframe, location + indName, InpLeftRightBars, InpSwingWindow);
if(handle == INVALID_HANDLE) {
Print("Error creating Swing Indicator: ", GetLastError());
return -1;
}
return handle;
}
int UpdateRange(int bufferIndex, datetime startTime, datetime stopTime, double &dst[], datetime &times[]) {
ArrayResize(dst, 0);
ArrayResize(times, 0);
if(handle == INVALID_HANDLE)
return 0;
if(startTime <= 0 || stopTime <= 0 || stopTime <= startTime)
return 0;
double tempValues[];
datetime tempTimes[];
ArraySetAsSeries(tempValues, false);
ArraySetAsSeries(tempTimes, false);
int copiedValues = CopyBuffer(handle, bufferIndex, startTime, stopTime, tempValues);
int copiedTimes = CopyTime(symbol, timeframe, startTime, stopTime, tempTimes);
if(copiedValues <= 0 || copiedTimes <= 0) {
Print("Swing::UpdateRange failed. buffer=", bufferIndex,
" values=", copiedValues,
" times=", copiedTimes,
" error=", GetLastError(),
" from=", TimeToString(startTime),
" to=", TimeToString(stopTime));
return 0;
}
int total = MathMin(copiedValues, copiedTimes);
ArrayResize(dst, total);
ArrayResize(times, total);
for(int i = 0; i < total; i++) {
dst[i] = tempValues[i];
times[i] = tempTimes[i];
}
return total;
}
int UpdateRange(int bufferIndex, int count, double &dst[], datetime &times[]) {
ArrayResize(dst, 0);
ArrayResize(times, 0);
if(handle == INVALID_HANDLE)
return 0;
if(count <= 0)
return 0;
double tempValues[];
datetime tempTimes[];
ArraySetAsSeries(tempValues, false);
ArraySetAsSeries(tempTimes, false);
int copiedValues = CopyBuffer(handle, bufferIndex, 0, count, tempValues);
int copiedTimes = CopyTime(symbol, timeframe, 0, count, tempTimes);
if(copiedValues <= 0 || copiedTimes <= 0) {
Print("Swing::UpdateRange failed. buffer=", bufferIndex,
" values=", copiedValues,
" times=", copiedTimes,
" error=", GetLastError(),
" count=", count);
return 0;
}
int total = MathMin(copiedValues, copiedTimes);
ArrayResize(dst, total);
ArrayResize(times, total);
for(int i = 0; i < total; i++) {
dst[i] = tempValues[i];
times[i] = tempTimes[i];
}
return total;
}
int UpdateFromMonthsBack(int monthsCount, bool useMonths = true) {
if(monthsCount <= 0) {
Print("Swing::UpdateFromMonthsBack invalid monthsCount=", monthsCount);
Clear();
return 0;
}
int copiedHigh = 0;
int copiedLow = 0;
if(useMonths) {
datetime toTime = TimeCurrent();
datetime fromTime = FirstOfPreviousMonths(toTime, monthsCount);
copiedHigh = UpdateRange(0, fromTime, toTime, highBuffer, highTimes);
copiedLow = UpdateRange(1, fromTime, toTime, lowBuffer, lowTimes);
}
else {
copiedHigh = UpdateRange(0, monthsCount, highBuffer, highTimes);
copiedLow = UpdateRange(1, monthsCount, lowBuffer, lowTimes);
}
RebuildSwingList(highBuffer, highTimes, highs);
RebuildSwingList(lowBuffer, lowTimes, lows);
BuildZigZagFromSwings();
return copiedHigh + copiedLow;
}
int GetHighSize() {
return highs.Size();
}
int GetLowSize() {
return lows.Size();
}
int GetZigZagSize() {
return zigzag.Size();
}
int GetHighBufferSize() {
return ArraySize(highBuffer);
}
int GetLowBufferSize() {
return ArraySize(lowBuffer);
}
int GetFullHighSize() {
return MathMin(ArraySize(highBuffer), ArraySize(highTimes));
}
int GetFullLowSize() {
return MathMin(ArraySize(lowBuffer), ArraySize(lowTimes));
}
double High(int index = 0) {
TimePrice point;
if(!highs.Get(index, point))
return 0.0;
return point.y;
}
double Low(int index = 0) {
TimePrice point;
if(!lows.Get(index, point))
return 0.0;
return point.y;
}
double ZigZag(int index = 0) {
TimePrice point;
if(!zigzag.Get(index, point))
return 0.0;
return point.y;
}
double FullHigh(int index = 0) {
int total = GetFullHighSize();
int i = MapIndex(index, total);
if(i < 0)
return 0.0;
return highBuffer[i];
}
double FullLow(int index = 0) {
int total = GetFullLowSize();
int i = MapIndex(index, total);
if(i < 0)
return 0.0;
return lowBuffer[i];
}
datetime FullHighTime(int index = 0) {
int total = GetFullHighSize();
int i = MapIndex(index, total);
if(i < 0)
return 0;
return highTimes[i];
}
datetime FullLowTime(int index = 0) {
int total = GetFullLowSize();
int i = MapIndex(index, total);
if(i < 0)
return 0;
return lowTimes[i];
}
bool High(int index, TimePrice &point) {
point.Reset();
return highs.Get(index, point);
}
bool Low(int index, TimePrice &point) {
point.Reset();
return lows.Get(index, point);
}
bool ZigZag(int index, TimePrice &point) {
point.Reset();
return zigzag.Get(index, point);
}
bool FullHigh(int index, TimePrice &point) {
point.Reset();
int total = GetFullHighSize();
int i = MapIndex(index, total);
if(i < 0)
return false;
point.Set(index, highTimes[i], highBuffer[i]);
return true;
}
bool FullLow(int index, TimePrice &point) {
point.Reset();
int total = GetFullLowSize();
int i = MapIndex(index, total);
if(i < 0)
return false;
point.Set(index, lowTimes[i], lowBuffer[i]);
return true;
}
bool HighAtBar(int barIndex, TimePrice &point) {
return FullHigh(barIndex, point);
}
bool LowAtBar(int barIndex, TimePrice &point) {
return FullLow(barIndex, point);
}
bool IsHighAtBar(int barIndex) {
double value = FullHigh(barIndex);
return IsValidValue(value);
}
bool IsLowAtBar(int barIndex) {
double value = FullLow(barIndex);
return IsValidValue(value);
}
void GetHighs(TimePrice &result[]) {
highs.GetAll(result);
}
void GetLows(TimePrice &result[]) {
lows.GetAll(result);
}
void GetZigZag(TimePrice &result[]) {
zigzag.GetAll(result);
}
void GetFullHighs(TimePrice &result[]) {
BuildFullList(highBuffer, highTimes, result);
}
void GetFullLows(TimePrice &result[]) {
BuildFullList(lowBuffer, lowTimes, result);
}
void GetHighs(TimePrice &result[], bool includeNonValues) {
if(includeNonValues) {
GetFullHighs(result);
return;
}
GetHighs(result);
}
void GetLows(TimePrice &result[], bool includeNonValues) {
if(includeNonValues) {
GetFullLows(result);
return;
}
GetLows(result);
}
void GetHighValuesOnly(TimePrice &result[]) {
BuildValueOnlyList(highBuffer, highTimes, result);
}
void GetLowValuesOnly(TimePrice &result[]) {
BuildValueOnlyList(lowBuffer, lowTimes, result);
}
void GetHighBuffer(double &result[]) {
int total = ArraySize(highBuffer);
ArrayResize(result, total);
for(int logical = 0; logical < total; logical++) {
int physical = MapIndex(logical, total);
if(physical < 0)
result[logical] = 0.0;
else
result[logical] = highBuffer[physical];
}
}
void GetLowBuffer(double &result[]) {
int total = ArraySize(lowBuffer);
ArrayResize(result, total);
for(int logical = 0; logical < total; logical++) {
int physical = MapIndex(logical, total);
if(physical < 0)
result[logical] = 0.0;
else
result[logical] = lowBuffer[physical];
}
}
void GetHighTimes(datetime &result[]) {
int total = ArraySize(highTimes);
ArrayResize(result, total);
for(int logical = 0; logical < total; logical++) {
int physical = MapIndex(logical, total);
if(physical < 0)
result[logical] = 0;
else
result[logical] = highTimes[physical];
}
}
void GetLowTimes(datetime &result[]) {
int total = ArraySize(lowTimes);
ArrayResize(result, total);
for(int logical = 0; logical < total; logical++) {
int physical = MapIndex(logical, total);
if(physical < 0)
result[logical] = 0;
else
result[logical] = lowTimes[physical];
}
}
void RebuildZigZag() {
BuildZigZagFromSwings();
}
void Clear() {
ArrayResize(highBuffer, 0);
ArrayResize(lowBuffer, 0);
ArrayResize(highTimes, 0);
ArrayResize(lowTimes, 0);
highs.Clear();
lows.Clear();
zigzag.Clear();
}
};
#endif
//+------------------------------------------------------------------+