681 lines
15 KiB
Plaintext
681 lines
15 KiB
Plaintext
///////////////////////////////////////////////////////
|
|
//
|
|
// SaherElm IT Center MQL5 Expert Advisor
|
|
// -------------------------------------------------
|
|
// Name: XBaseEA
|
|
// Description: Session Detector Test Expert Advisor ...
|
|
//
|
|
// Maintainer:
|
|
// ------------
|
|
// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com)
|
|
//
|
|
//////////////////////////////////////////////////////
|
|
//
|
|
// Global Properties ...
|
|
#property copyright "Copyright 2023, SaherElm IT Center"
|
|
#property link "https://saherelm.ir"
|
|
#property version "1.00"
|
|
#property icon "../Images/SaherElm_Logo_Color.ico"
|
|
#property description "SaherElm Session Detector Test Expert Advisor"
|
|
#property strict
|
|
|
|
// #region Imports ...
|
|
#include "../Classes/x-saherelm.pivot-detector.class.mq5"
|
|
#include "../Classes/x-saherelm.session-detector.class.mq5"
|
|
#include "../Classes/x-saherelm.x-poi.drawer.class.mq5"
|
|
// #endregion
|
|
|
|
// #region Global Variables ...
|
|
#define ShortName "XPivotDetectorTestEA"
|
|
|
|
XCAlert *eaAlert;
|
|
XCPOIDrawer *eaDrawer;
|
|
XCSessionDetector *eaSessionDetector;
|
|
|
|
//
|
|
XCPivotDetector *eaMajorPivotDetector;
|
|
XCPivotDetector *eaMinorPivotDetector;
|
|
|
|
//
|
|
// Last Processing Pivots Time ...
|
|
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
|
|
|
|
// #region Global Event Handlers ...
|
|
/**
|
|
* Initialize EA Process ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int OnInit()
|
|
{
|
|
//
|
|
bool result = true;
|
|
|
|
//
|
|
result = InitializeRequirements();
|
|
if (!result)
|
|
{
|
|
return INIT_FAILED;
|
|
}
|
|
|
|
//
|
|
return INIT_SUCCEEDED;
|
|
}
|
|
|
|
/**
|
|
* De Initialize Expert ...
|
|
*
|
|
* @param reason: int, DeInitialization Reason ...
|
|
*
|
|
* REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function
|
|
* REASON_REMOVE 1 Program removed from a chart
|
|
* REASON_RECOMPILE 2 Program recompiled
|
|
* REASON_CHARTCHANGE 3 A symbol or a chart period is changed
|
|
* REASON_CHARTCLOSE 4 Chart closed
|
|
* REASON_PARAMETERS 5 Inputs changed by a user
|
|
* REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings
|
|
* REASON_TEMPLATE 7 Another chart template applied
|
|
* REASON_INITFAILED 8 The OnInit() handler returned a non-zero value
|
|
* REASON_CLOSE 9 Terminal closed
|
|
*
|
|
*/
|
|
void OnDeinit(const int reason)
|
|
{
|
|
//
|
|
// Destroy Timer ...
|
|
// If Initialized ...
|
|
|
|
//
|
|
eaMajorPivotsDrawConfig.Clean();
|
|
eaMinorPivotsDrawConfig.Clean();
|
|
eaPointedMajorPivotsDrawConfig.Clean();
|
|
eaPointedMinorPivotsDrawConfig.Clean();
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
ZeroMemory(eaAlert);
|
|
ZeroMemory(eaDrawer);
|
|
ZeroMemory(eaSessionDetector);
|
|
ZeroMemory(eaMajorPivotDetector);
|
|
ZeroMemory(eaMinorPivotDetector);
|
|
}
|
|
|
|
/**
|
|
* Handle Tick for Processing ...
|
|
*/
|
|
void OnTick()
|
|
{
|
|
//
|
|
// Perform Session Detector Process ...
|
|
eaSessionDetector.Process();
|
|
|
|
//
|
|
// Process Pivot Detector ...
|
|
HandleProcessMajorPviots();
|
|
HandleProcessMinorPviots();
|
|
|
|
//
|
|
// Detecting Bias ...
|
|
HanldeBiasDetection();
|
|
}
|
|
|
|
/**
|
|
* Handle On Chart Event Processing ...
|
|
|
|
* @param id: int, Specified Event ID ...
|
|
* @param lparam: long, type event parameter
|
|
* @param dparam: double, type event parameter
|
|
* @param sparam: string, type event parameter
|
|
*/
|
|
void OnChartEvent(
|
|
const int id,
|
|
const long &lparam,
|
|
const double &dparam,
|
|
const string &sparam //
|
|
)
|
|
{
|
|
}
|
|
// #endregion
|
|
|
|
// #region Custom Actions ...
|
|
/**
|
|
* Initial Requirements of EA ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool InitializeRequirements()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
eaDrawer = new XCPOIDrawer();
|
|
|
|
//
|
|
// Initialize Alert ...
|
|
eaAlert = new XCAlert(
|
|
ShortName,
|
|
false, // Enable Alert ...
|
|
false, // Log Alert ...
|
|
false, // Terminal Alert ...
|
|
false, // Mail Alert ...
|
|
false, // Push Alerts ...
|
|
false // Save Alerts ...
|
|
);
|
|
result = eaAlert != NULL;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Initialize Session Detector ...
|
|
eaSessionDetector = new XCSessionDetector(
|
|
eaAlert, // Alert ...
|
|
true, // Use Server Time ...
|
|
0 // Timezone Offset ...
|
|
);
|
|
|
|
//
|
|
// Register Event Handlers ...
|
|
eaSessionDetector.AddOnSessionEndHandler(OnSessionEndHandler);
|
|
eaSessionDetector.AddOnOverlapEndHandler(OnOverlapEndHandler);
|
|
eaSessionDetector.AddOnSessionStartHandler(OnSessionStartHandler);
|
|
eaSessionDetector.AddOnOverlapStartHandler(OnOverlapStartHandler);
|
|
eaSessionDetector.AddOnSessionStateChangeHandler(OnSessionStateChangeHandler);
|
|
|
|
//
|
|
result = eaSessionDetector != NULL;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Initialize Major Pivot Detector ...
|
|
eaMajorPivotDetector = new XCPivotDetector(
|
|
eaAlert, // Alert ...
|
|
"X121SDTMajor", // Pivot Prefix ...
|
|
false, // Support Inverted Zones ...
|
|
0 // Processable Zones ...
|
|
);
|
|
|
|
//
|
|
// Register Event Handlers ...
|
|
eaMajorPivotDetector.AddOnPeakBreakedHandler(OnMajorPeakBreakedHandler);
|
|
eaMajorPivotDetector.AddOnValeBreakedHandler(OnMajorValeBreakedHandler);
|
|
eaMajorPivotDetector.AddOnPeakDetectedHandler(OnMajorPeakDetectedHandler);
|
|
eaMajorPivotDetector.AddOnValeDetectedHandler(OnMajorValeDetectedHandler);
|
|
|
|
//
|
|
// 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)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Process Pivots ...
|
|
*/
|
|
void HandleProcessMajorPviots()
|
|
{
|
|
//
|
|
// Initialize Pivot Processing Bar ...
|
|
XOHCL bar;
|
|
bool has = bar.Init(
|
|
_Symbol,
|
|
PERIOD_H4,
|
|
1 // Last Completed Bar ...
|
|
);
|
|
if (!has)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Validate Passing Bar ...
|
|
has =
|
|
!IsXValid(eaLastMajorPivotProcessing) ||
|
|
bar.time > eaLastMajorPivotProcessing;
|
|
if (!has)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
eaLastMajorPivotProcessing = bar.time;
|
|
|
|
//
|
|
eaMajorPivotDetector.Process(
|
|
bar, // XOHCL Bar ...
|
|
2, // Pivot Approvation Length ...
|
|
20 // Loopback ...
|
|
);
|
|
|
|
//
|
|
// Handle Draw Pivots ...
|
|
if (!eaDrawMajorPivots)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
XBoxZone tmps[];
|
|
FillNotExists(
|
|
tmps, // Dest ...
|
|
eaMajorPivotDetector.peaks, // Source ...
|
|
false // Force Clean ...
|
|
);
|
|
FillNotExists(
|
|
tmps, // Dest ...
|
|
eaMajorPivotDetector.vales, // Source ...
|
|
false // Force Clean ...
|
|
);
|
|
if (HasChild(tmps))
|
|
{
|
|
eaDrawer.DrawZones(
|
|
tmps, // Boxes ...
|
|
eaMajorPivotsDrawConfig // Draw Config ...
|
|
);
|
|
}
|
|
XClean(tmps);
|
|
}
|
|
|
|
/**
|
|
* 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
|
|
|
|
// #region Custom Event Handlers ...
|
|
|
|
// #region Pivot Detector Event Handlers ...
|
|
/**
|
|
* Calls when a Peak Breaked ...
|
|
*
|
|
* @param box: XBoxZone instance ...
|
|
*/
|
|
void OnMajorPeakBreakedHandler(XBoxZone &box)
|
|
{
|
|
// DebugBreak();
|
|
}
|
|
|
|
/**
|
|
* Calls when a Vale Breaked ...
|
|
*
|
|
* @param box: XBoxZone instance ...
|
|
*/
|
|
void OnMajorValeBreakedHandler(XBoxZone &box)
|
|
{
|
|
// DebugBreak();
|
|
}
|
|
|
|
/**
|
|
* Calls when a New Peak Detected ...
|
|
*
|
|
* @param box: XBoxZone instance ...
|
|
*/
|
|
void OnMajorPeakDetectedHandler(XBoxZone &box)
|
|
{
|
|
//
|
|
eaDrawer.DrawZone(
|
|
box, //
|
|
eaPointedMajorPivotsDrawConfig //
|
|
);
|
|
|
|
//
|
|
DebugBreak();
|
|
}
|
|
|
|
/**
|
|
* Calls when a New Vale Detected ...
|
|
*
|
|
* @param box: XBoxZone instance ...
|
|
*/
|
|
void OnMajorValeDetectedHandler(XBoxZone &box)
|
|
{
|
|
//
|
|
eaDrawer.DrawZone(
|
|
box, //
|
|
eaPointedMajorPivotsDrawConfig //
|
|
);
|
|
|
|
//
|
|
DebugBreak();
|
|
}
|
|
|
|
/**
|
|
* Calls when a Peak Breaked ...
|
|
*
|
|
* @param box: XBoxZone instance ...
|
|
*/
|
|
void OnMinorPeakBreakedHandler(XBoxZone &box)
|
|
{
|
|
// 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
|
|
|
|
// #region Session Detector Event Handlers ...
|
|
/**
|
|
* Handle Session Start Event ...
|
|
*
|
|
* @param session: ENUM_X_SESSION_TYPE
|
|
* @param startTime: datetime
|
|
*/
|
|
void OnSessionStartHandler(
|
|
ENUM_X_SESSION_TYPE session,
|
|
datetime startTime //
|
|
)
|
|
{
|
|
// Print("Session Started: ", EnumToString(session), " at ", TimeToString(startTime));
|
|
|
|
// //
|
|
// // Custom Testing ...
|
|
// if (session == X_SESSION_NEWYORK)
|
|
// {
|
|
// DebugBreak();
|
|
// }
|
|
}
|
|
|
|
/**
|
|
* Handle Session End Event ...
|
|
*
|
|
* @param session: ENUM_X_SESSION_TYPE
|
|
* @param startTime: datetime
|
|
*/
|
|
void OnSessionEndHandler(
|
|
ENUM_X_SESSION_TYPE session,
|
|
datetime startTime //
|
|
)
|
|
{
|
|
// Print("Session Ended: ", EnumToString(session), " at ", TimeToString(startTime));
|
|
|
|
// //
|
|
// // Custom Testing ...
|
|
// if (session == X_SESSION_NEWYORK)
|
|
// {
|
|
// DebugBreak();
|
|
// }
|
|
}
|
|
|
|
/**
|
|
* Handle Overlap Start Event ...
|
|
*
|
|
* @param session: ENUM_X_SESSION_OVERLAP_TYPE
|
|
* @param startTime: datetime
|
|
*/
|
|
void OnOverlapStartHandler(
|
|
ENUM_X_SESSION_OVERLAP_TYPE overlap,
|
|
datetime startTime //
|
|
)
|
|
{
|
|
// Print("Overlap Started: ", EnumToString(overlap), " at ", TimeToString(startTime));
|
|
|
|
// //
|
|
// // Custom Testing ...
|
|
// if (overlap == X_OVERLAP_LONDON_NEWYORK)
|
|
// {
|
|
// DebugBreak();
|
|
// }
|
|
}
|
|
|
|
/**
|
|
* Handle Overlap End Event ...
|
|
*
|
|
* @param session: ENUM_X_SESSION_OVERLAP_TYPE
|
|
* @param startTime: datetime
|
|
*/
|
|
void OnOverlapEndHandler(
|
|
ENUM_X_SESSION_OVERLAP_TYPE overlap,
|
|
datetime startTime //
|
|
)
|
|
{
|
|
// Print("Overlap Ended: ", EnumToString(overlap), " at ", TimeToString(startTime));
|
|
|
|
// //
|
|
// // Custom Testing ...
|
|
// if (overlap == X_OVERLAP_LONDON_NEWYORK)
|
|
// {
|
|
// DebugBreak();
|
|
// }
|
|
}
|
|
|
|
/**
|
|
* Handle Session State Change Event ...
|
|
*
|
|
* @param session: ENUM_X_SESSION_TYPE
|
|
* @param state: ENUM_X_SESSION_STATE
|
|
*/
|
|
void OnSessionStateChangeHandler(
|
|
ENUM_X_SESSION_TYPE session,
|
|
ENUM_X_SESSION_STATE state //
|
|
)
|
|
{
|
|
// Print("Session State Changed: ", EnumToString(session), " State: ", EnumToString(state));
|
|
}
|
|
// #endregion
|
|
|
|
// #endregion |