608 lines
11 KiB
Plaintext
608 lines
11 KiB
Plaintext
///////////////////////////////////////////////////////
|
|
//
|
|
// SaherElm IT Center MQL5 Class Library
|
|
// ----------------------------------------------
|
|
// Name: XSCTrend
|
|
// Description: provides all Trend requirements ...
|
|
//
|
|
//
|
|
// Maintainer:
|
|
// ------------
|
|
// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com)
|
|
//
|
|
//////////////////////////////////////////////////////
|
|
//
|
|
// Global Properties ...
|
|
#property library
|
|
#property copyright "Copyright 2023, SaherElm IT Center"
|
|
#property link "https://www.saherelm.ir"
|
|
#property version "1.00"
|
|
#property strict
|
|
|
|
//
|
|
// Imports ...
|
|
#include "../Classes/x-saherelm.base.class.mq5"
|
|
#include "../Libraries/x-saherelm.draw.lib.mq5"
|
|
|
|
//
|
|
// All Required Inputs ...
|
|
struct XSCTrendInput
|
|
{
|
|
//
|
|
int numberOfShoulders; // Number of Shoulders
|
|
|
|
//
|
|
color clrUpper; // Upper Colors
|
|
color clrLower; // Lower Colors
|
|
color clrHighs; // Highs Colors
|
|
color clrLows; // Lows Colors
|
|
|
|
//
|
|
// Constructor ...
|
|
void XSCTrendInput()
|
|
{
|
|
Clean();
|
|
}
|
|
|
|
//
|
|
// Tools ...
|
|
|
|
//
|
|
// Cleanup ...
|
|
void Clean()
|
|
{
|
|
//
|
|
numberOfShoulders = 0;
|
|
|
|
//
|
|
clrUpper = CLR_NONE;
|
|
clrLower = CLR_NONE;
|
|
clrHighs = CLR_NONE;
|
|
clrLows = CLR_NONE;
|
|
}
|
|
|
|
//
|
|
// Defualt Configs ...
|
|
void Default()
|
|
{
|
|
//
|
|
numberOfShoulders = 7;
|
|
|
|
//
|
|
clrUpper = clrRed;
|
|
clrLower = clrGreen;
|
|
|
|
//
|
|
clrHighs = clrAqua;
|
|
clrLows = clrMagenta;
|
|
}
|
|
|
|
//
|
|
// Validate ...
|
|
bool IsValid()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result =
|
|
//
|
|
numberOfShoulders >= 2
|
|
//
|
|
;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
};
|
|
|
|
//
|
|
// Class Definitions ...
|
|
class XSCTrend : public XSCBase
|
|
{
|
|
//
|
|
// Public ...
|
|
public:
|
|
//
|
|
// Props ...
|
|
|
|
//
|
|
// Constructor ...
|
|
void XSCTrend(
|
|
string symbol,
|
|
ENUM_TIMEFRAMES period //
|
|
) : XSCBase()
|
|
{
|
|
//
|
|
mSymbol = symbol;
|
|
mPeriod = period;
|
|
}
|
|
|
|
//
|
|
// Deconstructor ...
|
|
void ~XSCTrend() {}
|
|
|
|
//
|
|
// Initialize ...
|
|
bool Init(XSCTrendInput &inputs)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = inputs.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
mInputs = inputs;
|
|
|
|
//
|
|
result = zBar.Init(
|
|
mSymbol,
|
|
mPeriod,
|
|
0 //
|
|
);
|
|
|
|
//
|
|
int firstSwingLowIndex = FindSwing(
|
|
zBar.symbol,
|
|
zBar.period,
|
|
X_SWING_LOW,
|
|
mInputs.numberOfShoulders,
|
|
zBar.Index() + 1 //
|
|
);
|
|
result = firstSwingLowBar.Init(
|
|
zBar.symbol,
|
|
zBar.period,
|
|
firstSwingLowIndex //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int secondSwingLowIndex = FindSwing(
|
|
zBar.symbol,
|
|
zBar.period,
|
|
X_SWING_LOW,
|
|
mInputs.numberOfShoulders,
|
|
firstSwingLowIndex + 1 //
|
|
);
|
|
|
|
//
|
|
result = secondSwingLowBar.Init(
|
|
zBar.symbol,
|
|
zBar.period,
|
|
secondSwingLowIndex //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int firstSwingHighIndex = FindSwing(
|
|
zBar.symbol,
|
|
zBar.period,
|
|
X_SWING_HIGH,
|
|
mInputs.numberOfShoulders,
|
|
zBar.Index() + 1 //
|
|
);
|
|
result = firstSwingHighBar.Init(
|
|
zBar.symbol,
|
|
zBar.period,
|
|
firstSwingHighIndex //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int secondSwingHighIndex = FindSwing(
|
|
zBar.symbol,
|
|
zBar.period,
|
|
X_SWING_HIGH,
|
|
mInputs.numberOfShoulders,
|
|
firstSwingHighIndex + 1 //
|
|
);
|
|
result = secondSwingHighBar.Init(
|
|
zBar.symbol,
|
|
zBar.period,
|
|
secondSwingHighIndex //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Getter(s) / Setter(s) ...
|
|
|
|
//
|
|
string GetSymbol()
|
|
{
|
|
return mSymbol;
|
|
}
|
|
|
|
//
|
|
ENUM_TIMEFRAMES GetPeriod()
|
|
{
|
|
return mPeriod;
|
|
}
|
|
|
|
//
|
|
XSCTrendInput GetInputs()
|
|
{
|
|
return mInputs;
|
|
}
|
|
|
|
//
|
|
bool SetInputs(XSCTrendInput &inputs)
|
|
{
|
|
return Init(inputs);
|
|
}
|
|
|
|
//
|
|
XOHCL GetBar()
|
|
{
|
|
return zBar;
|
|
}
|
|
|
|
//
|
|
XOHCL GetFirstSwingLowBar()
|
|
{
|
|
return firstSwingLowBar;
|
|
}
|
|
|
|
//
|
|
XOHCL GetSecondSwingLowBar()
|
|
{
|
|
return secondSwingLowBar;
|
|
}
|
|
|
|
//
|
|
XOHCL GetFirstSwingHighBar()
|
|
{
|
|
return firstSwingHighBar;
|
|
}
|
|
|
|
//
|
|
XOHCL GetSecondSwingHighBar()
|
|
{
|
|
return secondSwingHighBar;
|
|
}
|
|
|
|
//
|
|
// Tools ...
|
|
|
|
//
|
|
// Validate ...
|
|
bool IsValid()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result =
|
|
//
|
|
zBar.IsValid() &&
|
|
firstSwingLowBar.IsValid() &&
|
|
secondSwingLowBar.IsValid() &&
|
|
firstSwingHighBar.IsValid() &&
|
|
secondSwingHighBar.IsValid()
|
|
//
|
|
;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Retrieve Title Prefix ...
|
|
string GetIdentifier()
|
|
{
|
|
//
|
|
string result = NULL;
|
|
|
|
//
|
|
if (!IsValid())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = mSymbol + "_" +
|
|
ToString(mPeriod) + "_" +
|
|
ToFormatString(zBar.time);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Remove Draws ...
|
|
bool Remove(
|
|
long chartId = 0,
|
|
int subWindow = 0 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
string prefix = GetIdentifier();
|
|
result = IsSpecifiedValid(prefix);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = RemoveDraw(
|
|
prefix,
|
|
chartId,
|
|
subWindow //
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool Draw(
|
|
long chartId = 0,
|
|
string prefix = NULL,
|
|
int subWindow = 0,
|
|
string upperPrefix = "Upper",
|
|
string lowerPrefix = "Lower",
|
|
string highsPrefix = "Highs",
|
|
string lowsPrefix = "Lows" //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Normalize Prefixes ...
|
|
|
|
//
|
|
if (!IsSpecifiedValid(upperPrefix))
|
|
{
|
|
upperPrefix = "Upper";
|
|
}
|
|
|
|
//
|
|
if (!IsSpecifiedValid(lowerPrefix))
|
|
{
|
|
lowerPrefix = "Lower";
|
|
}
|
|
|
|
//
|
|
if (!IsSpecifiedValid(highsPrefix))
|
|
{
|
|
highsPrefix = "Highs";
|
|
}
|
|
|
|
//
|
|
if (!IsSpecifiedValid(lowsPrefix))
|
|
{
|
|
lowsPrefix = "Lows";
|
|
}
|
|
|
|
//
|
|
string identifier = GetIdentifier();
|
|
result = IsSpecifiedValid(identifier);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double support = secondSwingLowBar.low;
|
|
datetime supportTime =
|
|
secondSwingLowBar.time > secondSwingHighBar.time
|
|
? secondSwingHighBar.time
|
|
: secondSwingLowBar.time;
|
|
string supportName =
|
|
//
|
|
identifier +
|
|
(IsSpecifiedValid(prefix)
|
|
? "_" + prefix + "_"
|
|
: "") +
|
|
"_" + lowerPrefix + "_" +
|
|
""
|
|
//
|
|
;
|
|
|
|
//
|
|
double resistance = secondSwingHighBar.high;
|
|
datetime resistanceTime =
|
|
secondSwingLowBar.time > secondSwingHighBar.time
|
|
? secondSwingHighBar.time
|
|
: secondSwingLowBar.time;
|
|
|
|
string resistanceName =
|
|
//
|
|
identifier +
|
|
(IsSpecifiedValid(prefix)
|
|
? "_" + prefix + "_"
|
|
: "") +
|
|
"_" + upperPrefix + "_" +
|
|
""
|
|
//
|
|
;
|
|
|
|
//
|
|
double newLow = firstSwingLowBar.low;
|
|
datetime newLowTime = firstSwingLowBar.time;
|
|
|
|
//
|
|
double oldLow = secondSwingLowBar.low;
|
|
datetime oldLowTime = secondSwingLowBar.time;
|
|
string lowsName =
|
|
//
|
|
identifier +
|
|
(IsSpecifiedValid(prefix)
|
|
? "_" + prefix + "_"
|
|
: "") +
|
|
"_" + lowsPrefix + "_" +
|
|
""
|
|
//
|
|
;
|
|
|
|
//
|
|
double newHigh = firstSwingHighBar.high;
|
|
datetime newHighTime = firstSwingHighBar.time;
|
|
|
|
//
|
|
double oldHigh = secondSwingHighBar.high;
|
|
datetime oldHighTime = secondSwingHighBar.time;
|
|
string highsName =
|
|
//
|
|
identifier +
|
|
(IsSpecifiedValid(prefix)
|
|
? "_" + prefix + "_"
|
|
: "") +
|
|
"_" + highsPrefix + "_" +
|
|
""
|
|
//
|
|
;
|
|
|
|
//
|
|
// Draw Support ...
|
|
result = DrawTrendLine(
|
|
chartId,
|
|
supportName,
|
|
subWindow,
|
|
supportTime,
|
|
support,
|
|
newLowTime,
|
|
support,
|
|
mInputs.clrLower,
|
|
STYLE_SOLID,
|
|
2,
|
|
false,
|
|
false,
|
|
true // Ray Right ...
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Draw Resistance ...
|
|
result = DrawTrendLine(
|
|
chartId,
|
|
resistanceName,
|
|
subWindow,
|
|
resistanceTime,
|
|
resistance,
|
|
newHighTime,
|
|
resistance,
|
|
mInputs.clrUpper,
|
|
STYLE_SOLID,
|
|
2,
|
|
false,
|
|
false,
|
|
true // Ray Right ...
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Draw Highs ...
|
|
result = DrawTrendLine(
|
|
chartId,
|
|
highsName,
|
|
subWindow,
|
|
oldHighTime,
|
|
oldHigh,
|
|
newHighTime,
|
|
newHigh,
|
|
mInputs.clrHighs,
|
|
STYLE_SOLID,
|
|
2,
|
|
false,
|
|
false,
|
|
true // Ray Right ...
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Draw Lows ...
|
|
result = DrawTrendLine(
|
|
chartId,
|
|
lowsName,
|
|
subWindow,
|
|
oldLowTime,
|
|
oldLow,
|
|
newLowTime,
|
|
newLow,
|
|
mInputs.clrLows,
|
|
STYLE_SOLID,
|
|
2,
|
|
false,
|
|
false,
|
|
true // Ray Right ...
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Protected ...
|
|
protected:
|
|
//
|
|
// Private ...
|
|
private:
|
|
//
|
|
// Props ...
|
|
string mSymbol; // Trading Symbol ...
|
|
ENUM_TIMEFRAMES mPeriod; // Trading Period ...
|
|
|
|
//
|
|
XSCTrendInput mInputs; // Configs ...
|
|
|
|
//
|
|
XOHCL zBar;
|
|
XOHCL firstSwingLowBar;
|
|
XOHCL secondSwingLowBar;
|
|
XOHCL firstSwingHighBar;
|
|
XOHCL secondSwingHighBar;
|
|
};
|
|
|
|
// |