diff --git a/Classes/x-saherelm.x-restrictions.class.mq5 b/Classes/x-saherelm.x-restrictions.class.mq5 new file mode 100644 index 00000000..435b2308 --- /dev/null +++ b/Classes/x-saherelm.x-restrictions.class.mq5 @@ -0,0 +1,84 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// -------------------------------------- +// Name: XCRestrictions +// Description: provides all Requirements for Apply Restrictions ... +// +// +// 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" + +// +// Definitions ... + +// +// All awailable Restrictions Period ... +enum ENUM_X_TRADE_RESTRICTIONS_PERIOD +{ + X_TRADE_RESTRICATION_NONE, // None + X_TRADE_RESTRICATION_HOURLY, // Per Hour + X_TRADE_RESTRICATION_DAILY, // Per Day + X_TRADE_RESTRICATION_WEEKLY, // Per Week + X_TRADE_RESTRICATION_MONTHLY, // Per Month +}; + +// +// Converts to String ... +string ToXString(ENUM_X_TRADE_RESTRICTIONS_PERIOD value) +{ + // + string result = NULL; + + // + result = EnumToString(value); + + // + return result; +} + +// +// Check Has Restrictions or not ... +bool HasRestrictions(ENUM_X_TRADE_RESTRICTIONS_PERIOD value) +{ + // + bool result = false; + + // + result = value != X_TRADE_RESTRICATION_NONE; + + // + return result; +} + +// +// Implementation ... +class XCRestrictions : public XCBase +{ + // + // Public ... + public: + // + // Protected ... + protected: + // + // Private ... + private: + // +}; + +// \ No newline at end of file diff --git a/Experts/x-saherelm.xom1.ea.mq5 b/Experts/x-saherelm.xom1.ea.mq5 new file mode 100644 index 00000000..9aef09e7 --- /dev/null +++ b/Experts/x-saherelm.xom1.ea.mq5 @@ -0,0 +1,356 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Expert Advisor +// ------------------------------------------------- +// Name: XOM1 +// Description: XOM1 base 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 description "SaherElm XOM1 based Expert Advisor" +#property strict + +// +#define ShortName "XOM1EA" + +// +// Importts ... +#include "../XOM1EA/Classes/xom1ea.expert.class.mq5" + +// +// Inputs ... + +// +// Common ... +input group "Common"; +input long eaMagicNumber = 1694056; // Magic Number +input int eaSlippage = 10; // Slippgae +input string eaLogSuffix = ""; // Log Suffix + +// +// Variables ... + +// +XCXOM1EAExpert *eaExpert; + +// +// Event Handlers ... + +// +// Initialization ... +int OnInit() +{ + // + // Preparing Tags ... + string eaTag = + (IsValid(eaLogSuffix) + ? eaLogSuffix + "_" + : "") + + ShortName; + + // + // Validate Inputs and Required Parameters ... + + // for EA to Works fine ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Initialize Timer ... + if (!InitTimer()) + { + return INIT_FAILED; + } + + // + // Configure EA Expert Class ... + eaExpert = new XCXOM1EAExpert(); + + // + // Setting All Inputs to Expert Adviser Class ... + // + bool isInited = eaExpert.HandleOnInit(); + if (!isInited) + { + return INIT_FAILED; + } + + // + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int 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 + + // + // Destroy Timer ... + eaExpert.HandleOnDeInit(); + + // + delete eaExpert; + ZeroMemory(eaExpert); +} + +// +// On Tick Handler ... +void OnTick() +{ + eaExpert.HandleOnTick(); +} + +// +// Handle On Trade Event ... +void OnTrade() +{ + eaExpert.HandleOnTrade(); +} + +// +// On Timer ... +void OnTimer() +{ + eaExpert.HandleOnTimer(); +} + +// +// Chart Event Handler ... +void OnChartEvent( + const int id, + const long &lparam, + const double &dparam, + const string &sparam // +) +{ + eaExpert.HandleOnChartEvent(id, lparam, dparam, sparam); +} + +// +// Event Listeners ... + +/** + * Handle StopLoss Triggered Positions ... + * + * @param deal: XDeal instance ... + */ +void OnStopLossTriggered(const XDeal &deal) +{ + // eaExpert.HandleOnStopLossTriggered(deal); +} + +/** + * Handle Take Profit Triggered Positions ... + * + * @param deal: XDeal instance ... + */ +void OnTakeProfitTriggered(const XDeal &deal) +{ + // eaExpert.HandleOnTakeProfitTriggered(deal); +} + +/** + * Handle Force Close a Position ... + * + * @param ticket: ULONG ... + * @param position: XPosition instance ... + * @param comment: String ... + */ +void OnPositionForceClosed( + const ulong ticket, + const XPosition &position, + const string comment // +) +{ + // + // eaExpert.HandleOnPositionForceClosed( + // ticket, + // position, + // comment // + // ); +} + +/** + * Handle Deals Changes ... + * + * @param count: Integer, Number of Changes ... + */ +void OnDealsChanged(int count) +{ + // eaExpert.HandleOnDealsChanged(count); +} + +/** + * Handle Orders Changes ... + * + * @param count: Integer, Number of Changes ... + */ +void OnOrdersChanged(int count) +{ + // eaExpert.HandleOnOrdersChanged(count); +} + +/** + * Handle Positions Changes ... + * + * @param count: Integer, Number of Changes ... + */ +void OnPositionsChanged(int count) +{ + // eaExpert.HandleOnPositionsChanged(count); +} + +/** + * Handle Position Modified ... + * + * @param ticket: ulong, Position Ticket ... + * @param profit: double, Position Profit ... + * @param comment: string, Comment ... + */ +void OnPositionModified( + const ulong ticket, + const double profit, + const string comment // +) +{ + // + // eaExpert.HandleOnPositionModified( + // ticket, + // profit, + // comment // + // ); +} + +/** + * Handle Position Partial Closed ... + * + * @param ticket: ulong, Position Ticket ... + * @param profit: double, Position Profit ... + * @param comment: string, Comment ... + */ +void OnPositionPartialClosed( + const ulong ticket, + const double profit, + const string comment // +) +{ + // + // eaExpert.HandleOnPositionPartialClosed( + // ticket, + // profit, + // comment // + // ); +} + +/** + * Handle Trade State Changed ... + * + * @param state: XOnTradeHandlerState instance ... + */ +void OnTradeStateChanged(const XOnTradeHandlerState &state) +{ + // eaExpert.HandleOnTradeStateChanged(state); +} + +// +// Custom Functions ... + +/** + * Validate all Inputs of Expert Adviser ... + * + * @return ( bool ) + */ +bool ValidateInputs() +{ + // + bool result = false; + + // + string errMessage = ""; + + // + bool isCommonValid = ( + // + eaSlippage > 0 && + eaMagicNumber > 0 + // + ); + if (!isCommonValid) + { + // + errMessage += "common configurations error;" + "\n"; + } + + // + result = + // + // Common ... + isCommonValid && + // + // Otere ... + true + // + ; + + // + if (!result) + { + // + // Since here Logger not Initiallized, we Use Raw Print Command ... + Print(ShortName + " Errors: \n", errMessage); + } + + // + return result; +} + +/** + * Initialize Timer ... + * + * @return ( bool ) + */ +bool InitTimer() +{ + // + bool result = false; + + // + // TODO: Initialize Timer if necessary ... + // result = EventSetTimer(1); + // result = EventSetMillisecondTimer(100); + result = true; + + // + return result; +} + +/** + * Destroy Timer ... + */ +void DestroyTimer() +{ + // + // TODO: Use This ... + // EventKillTimer(); +} diff --git a/Helpers/x-saherelm.xom1.helper.mq5 b/Helpers/x-saherelm.xom1.helper.mq5 index 5ca77534..052cb97a 100644 --- a/Helpers/x-saherelm.xom1.helper.mq5 +++ b/Helpers/x-saherelm.xom1.helper.mq5 @@ -114,23 +114,23 @@ struct XOM1Inputs { // // Calculations ... - scMethod = X_PERIOD_AUTO; // How to Find Short Period - scPeriod = NULL; // Short Period - mcMethod = X_PERIOD_AUTO; // How to Find Medium Period - mcPeriod = NULL; // Medium Period - lcMethod = X_PERIOD_AUTO; // How to Find Long Period - lcPeriod = NULL; // Long Period - hcMethod = X_PERIOD_AUTO; // How to Find Hind Period - hcPeriod = NULL; // Hind Period - upperMode = MODE_HIGH; // Peak Method - lowerMode = MODE_LOW; // Vale Method - upperZoneLevel = X_FIBO_LEVEL_618; // Upper Zone Level - lowerZoneLevel = X_FIBO_LEVEL_764; // Lower Zone Level - double sarStep = 0.02; // SAR Step - double sarMax = 0.2; // SAR Maximum - ENUM_MA_METHOD maMethod = MODE_EMA; // MA Method - ENUM_APPLIED_PRICE maAppliedTo = PRICE_CLOSE; // MA Applied To - int maLength = 10; // MA Length + scMethod = X_PERIOD_AUTO; // How to Find Short Period + scPeriod = NULL; // Short Period + mcMethod = X_PERIOD_AUTO; // How to Find Medium Period + mcPeriod = NULL; // Medium Period + lcMethod = X_PERIOD_AUTO; // How to Find Long Period + lcPeriod = NULL; // Long Period + hcMethod = X_PERIOD_AUTO; // How to Find Hind Period + hcPeriod = NULL; // Hind Period + upperMode = MODE_HIGH; // Peak Method + lowerMode = MODE_LOW; // Vale Method + upperZoneLevel = X_FIBO_LEVEL_618; // Upper Zone Level + lowerZoneLevel = X_FIBO_LEVEL_764; // Lower Zone Level + sarStep = 0.02; // SAR Step + sarMax = 0.2; // SAR Maximum + maMethod = MODE_EMA; // MA Method + maAppliedTo = PRICE_CLOSE; // MA Applied To + maLength = 10; // MA Length // // Presentation ... @@ -203,6 +203,24 @@ struct XOM1Conditions // // Buffers ... + double maBuffer[]; + double maColorBuffer[]; + double maStateBuffer[]; + double sarBuffer[]; + double sarColorBuffer[]; + double sarStateBuffer[]; + double peakBuffer[]; + double valeBuffer[]; + double fiboUpperBuffer[]; + double fiboLowerBuffer[]; + double sHHBuffer[]; + double sLLBuffer[]; + double mHHBuffer[]; + double mLLBuffer[]; + double lHHBuffer[]; + double lLLBuffer[]; + double hHHBuffer[]; + double hLLBuffer[]; // // Conditions ... @@ -236,12 +254,52 @@ struct XOM1Conditions // SpecifiedClean(bars); + // + SpecifiedClean(maBuffer); + SpecifiedClean(maColorBuffer); + SpecifiedClean(maStateBuffer); + SpecifiedClean(sarBuffer); + SpecifiedClean(sarColorBuffer); + SpecifiedClean(sarStateBuffer); + SpecifiedClean(peakBuffer); + SpecifiedClean(valeBuffer); + SpecifiedClean(fiboUpperBuffer); + SpecifiedClean(fiboLowerBuffer); + SpecifiedClean(sHHBuffer); + SpecifiedClean(sLLBuffer); + SpecifiedClean(mHHBuffer); + SpecifiedClean(mLLBuffer); + SpecifiedClean(lHHBuffer); + SpecifiedClean(lLLBuffer); + SpecifiedClean(hHHBuffer); + SpecifiedClean(hLLBuffer); + // // Conditions ... // ArraySetAsSeries(bars, true); + // + ArraySetAsSeries(maBuffer, true); + ArraySetAsSeries(maColorBuffer, true); + ArraySetAsSeries(maStateBuffer, true); + ArraySetAsSeries(sarBuffer, true); + ArraySetAsSeries(sarColorBuffer, true); + ArraySetAsSeries(sarStateBuffer, true); + ArraySetAsSeries(peakBuffer, true); + ArraySetAsSeries(valeBuffer, true); + ArraySetAsSeries(fiboUpperBuffer, true); + ArraySetAsSeries(fiboLowerBuffer, true); + ArraySetAsSeries(sHHBuffer, true); + ArraySetAsSeries(sLLBuffer, true); + ArraySetAsSeries(mHHBuffer, true); + ArraySetAsSeries(mLLBuffer, true); + ArraySetAsSeries(lHHBuffer, true); + ArraySetAsSeries(lLLBuffer, true); + ArraySetAsSeries(hHHBuffer, true); + ArraySetAsSeries(hLLBuffer, true); + // ZeroMemory(this); } @@ -398,6 +456,8 @@ class XCXOM1Helper : public XCBaseHelper mInputs.lcPeriod, mInputs.hcMethod, mInputs.hcPeriod, + mInputs.upperMode, + mInputs.lowerMode, mInputs.upperZoneLevel, mInputs.lowerZoneLevel, mInputs.sarStep, @@ -469,8 +529,8 @@ class XCXOM1Helper : public XCBaseHelper // bool GetConditions( XOM1Conditions &conditions, // - int barIndex = 0, // - int loopback = 5 // + int barIndex = 0, // + int loopback = 5 // ) { // @@ -527,6 +587,118 @@ class XCXOM1Helper : public XCBaseHelper // // Buffers ... + // + CopyMA( + zIndex, + loopback, + conditions.maBuffer // + ); + + // + CopyMAState( + zIndex, + loopback, + conditions.maStateBuffer // + ); + + // + CopySar( + zIndex, + loopback, + conditions.sarBuffer // + ); + + // + CopySarState( + zIndex, + loopback, + conditions.sarStateBuffer // + ); + + // + CopyPeak( + zIndex, + loopback, + conditions.peakBuffer // + ); + + // + CopyVale( + zIndex, + loopback, + conditions.valeBuffer // + ); + + // + CopyFiboUpper( + zIndex, + loopback, + conditions.fiboUpperBuffer // + ); + + // + CopyFiboLower( + zIndex, + loopback, + conditions.fiboLowerBuffer // + ); + + // + CopySHH( + zIndex, + loopback, + conditions.sHHBuffer // + ); + + // + CopySLL( + zIndex, + loopback, + conditions.sLLBuffer // + ); + + // + CopyMHH( + zIndex, + loopback, + conditions.mHHBuffer // + ); + + // + CopyMLL( + zIndex, + loopback, + conditions.mLLBuffer // + ); + + // + CopyLHH( + zIndex, + loopback, + conditions.lHHBuffer // + ); + + // + CopyLLL( + zIndex, + loopback, + conditions.lLLBuffer // + ); + + // + CopyHHH( + zIndex, + loopback, + conditions.hHHBuffer // + ); + + // + CopyHLL( + zIndex, + loopback, + conditions.hLLBuffer // + ); + // // Conditions ... @@ -849,6 +1021,113 @@ class XCXOM1Helper : public XCBaseHelper ); } + // + // FIBO Zone ... + + // + // FIBO Upper ... + + // + double GetFiboUpper( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(fiboUpperBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return fiboUpperBuffer[barIndex]; + } + + // + int CopyFiboUpper( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + fiboUpperBuffer, + buffer, + forceClean + // + ); + } + + // + // FIBO Lower ... + + // + double GetFiboLower( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(fiboLowerBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return fiboLowerBuffer[barIndex]; + } + + // + int CopyFiboLower( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + fiboLowerBuffer, + buffer, + forceClean + // + ); + } + // // CYCLES Range ... diff --git a/XOM1EA/Classes/xom1ea.expert.class.mq5 b/XOM1EA/Classes/xom1ea.expert.class.mq5 index e69de29b..617ef8d9 100644 --- a/XOM1EA/Classes/xom1ea.expert.class.mq5 +++ b/XOM1EA/Classes/xom1ea.expert.class.mq5 @@ -0,0 +1,271 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class +// ------------------------------------------------- +// Name: XCXOM1EAExpret ... +// Description: XCXOM1EA Expert Class ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm XCXOM1EA Expert Class" +#property strict + +// +// Imports ... +#include "../../Classes/x-saherelm.base.class.mq5" +#include "../../Classes/x-saherelm.x-alert.class.mq5" +#include "../../Classes/x-saherelm.x-volume.class.mq5" +#include "../Classes/xom1ea.signaller.class.mq5" + +// +// Definitions ... + +// +// Implementation ... +class XCXOM1EAExpert : public XCBase +{ + // + // Public ... + public: + // + // Props ... + + // + // Common ... + long eaMagicNumber; // Magic Number + int eaSlippage; // Slippgae + string eaLogSuffix; // Log Suffix + + // + // Volume ... + ENUM_X_VOLUME_SELECT_TYPE eaVolumeSelect; // Volume Applying Type + double eaStaticVoluem; // Static Volume + double eaDynamicVolumeStepBalance; // Step of Balance for Increase Volume + double eaDynamicVolumeStepVolume; // Step of Volume Increasing + double eaConstantRiskBalance; // Constant Risk Balance per Trade + double eaConstantPercent; // Constant Percent of Balance Per Trade + double eaConstantBalance; // Constant Balance for Calculations + + // + // Alert ... + bool eaEnableAlerts; // Enable Alerts + bool eaSaveAlerts; // Save Alerts + bool eaLogAlerts; // Log Alerts + bool eaMailAlerts; // Mail Alerts + bool eaPushAlerts; // Push Alerts + bool eaTerminalAlerts; // Terminal Alerts + + // + // Requirements ... + + // + XCAlert *eaAlert; // EA Scope Alert Handler ... + XCVolume *eaVolume; // EA Scope Voluem Handler ... + + // + // Validators ... + + /** + * Validate Inputs ... + * + * @return ( bool ) + */ + bool ValidateInputs() + { + // + bool result = false; + + // + // TODO: Handle this ... + result = true; + + // + return result; + } + + // + // Expert Advisor Event Handlers ... + + /** + * Handle Initialization of Expert ... + * + * @return ( bool ) + */ + bool HandleOnInit() + { + // + bool result = false; + + // + // Validate Inputs ... + result = ValidateInputs(); + if (!result) + { + return result; + } + + // + // Initialize Alert Handler ... + eaAlert = new XCAlert(); + eaAlert.SetPrefix(eaLogSuffix); + eaAlert.SetLogAlerts(eaLogAlerts); + eaAlert.SetMailAlerts(eaMailAlerts); + eaAlert.SetPushAlerts(eaPushAlerts); + eaAlert.SetSaveAlerts(eaSaveAlerts); + eaAlert.SetEnableAlerts(eaEnableAlerts); + eaAlert.SetTerminalAlerts(eaTerminalAlerts); + + // + // Initialize Volume Manager ... + // eaVolume = new XCVolume(); + // result = eaVolume.Init( + // eaVolumeSelect, + // eaStaticVoluem, + // eaDynamicVolumeStepBalance, + // eaDynamicVolumeStepVolume, + // eaConstantRiskBalance, + // eaConstantPercent, + // eaConstantBalance // + // ); + // if (!result) + // { + // return result; + // } + + // + // Here we Apply Symbols,Periods and Configs ... + + // + XOM1Inputs iDZoneOMInputs; + iDZoneOMInputs.Default(); + + // + XOM1SignallerConfig iDZoneSignallerConfig; + iDZoneSignallerConfig.processAllTicks = false; + + // + XCXOM1SignallerBase *iDZoneSignaller = NULL; + iDZoneSignaller = new XCXOM1SignallerBase( + "XDZN", + "EURUSDb", + PERIOD_M5, + iDZoneOMInputs, + iDZoneSignallerConfig); + if (iDZoneSignaller != NULL) + { + // + Add( + iDZoneSignaller, + signallers // + ); + } + + // + // Cleanup Resources ... + iDZoneOMInputs.Clean(); + iDZoneSignallerConfig.Clean(); + ZeroMemory(iDZoneSignaller); + + // + return result; + } + + /** + * Handle De Initialization of Expert ... + */ + void HandleOnDeInit() + { + // + + // + delete eaVolume; + ZeroMemory(eaVolume); + + // + string message = "DeInitialized Successfully ..."; + eaAlert.SendAlert(message); + + // + delete eaAlert; + ZeroMemory(eaAlert); + } + + /** + * Handle Tick ... + */ + void HandleOnTick() + { + // + int count = ArraySize(signallers); + bool has = IsValidSize(count); + if (!has) { + return; + } + + // + // Loop through Signallers ... + for (int i = 0; i < count; i++) { + // + // Calling Process Ticks on Signaller ... + signallers[i].ProcessTick(0); + } + } + + /** + * Handle Trade ... + */ + void HandleOnTrade() + { + } + + /** + * Handle Timer ... + */ + void HandleOnTimer() + { + } + + /** + * Handle Chart Event ... + * + * @param id: int, Event id ... + * @param lparam: long, Event Long Parameter ... + * @param dparam: double, Event Double Parameter ... + * @param sparam: string, Event String Parameter ... + */ + void HandleOnChartEvent( + const int id, + const long &lparam, + const double &dparam, + const string &sparam // + ) + { + } + + // + // Trade Event Handlers ... + + // + // Protected ... + protected: + // + // Private ... + private: + // + // Props ... + + // + XCXOM1SignallerBase *signallers[]; // All Registered Signallers ... +}; + +// diff --git a/XOM1EA/Classes/xom1ea.signaller.class.mq5 b/XOM1EA/Classes/xom1ea.signaller.class.mq5 index e69de29b..e949594a 100644 --- a/XOM1EA/Classes/xom1ea.signaller.class.mq5 +++ b/XOM1EA/Classes/xom1ea.signaller.class.mq5 @@ -0,0 +1,384 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class +// ------------------------------------------------- +// Name: XCXOM1Signaller ... +// Description: XOM1EA Signaller Class ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm XOM1EA Signaller Class" +#property strict + +// +// Imports ... +#include "../../Helpers/x-saherelm.xom1.helper.mq5" +#include "../Libraries/xom1ea.lib.mq5" + +// +// Definitions ... + +// +// All Available Signaller Configurations +// which allow to Decide Based on Zones ... +struct XOM1SignallerConfig +{ + // + // Props ... + bool processAllTicks; // Do Process All Ticks ... + + // + // Constructor ... + XOM1SignallerConfig() { + Clean(); + } + + // + // Tools ... + + /** + * Cleanup ... + */ + void Clean() { + ZeroMemory(this); + } +}; + +// +// Implementation ... + +// +// Base Signaller Class ... +// Provides Zone Detection Mechanism ... +class XCXOM1SignallerBase +{ + // + // Public ... + public: + // + // Props ... + string name; // Name ... + string symbol; // Symbol ... + XOM1Zone zones[]; // Detected Zones ... + XOM1Inputs inputs; // Indicator Inputs ... + ENUM_TIMEFRAMES period; // Period ... + XOM1SignallerConfig config; // Configuration ... + + // + // Constructor ... + XCXOM1SignallerBase( + string _name, // Name ... + string _symbol, // Symbol ... + ENUM_TIMEFRAMES _period, // Period ... + XOM1Inputs &_inputs, // Indicator Inputs ... + XOM1SignallerConfig &_config // Config ... + ) + { + // + // Validate ... + bool isValid = + IsSpecifiedValid(_name) && + IsSpecifiedValid(_symbol) && + IsSpecifiedValid(_period) && + _inputs.IsValid(); + if (!isValid) + { + return; + } + + // + // Make Helper Class Instance ... + mHelper = new XCXOM1Helper(); + bool isInited = mHelper.Init( + _symbol, + _period, + _inputs // + ); + if (!isInited) + { + // + delete mHelper; + ZeroMemory(mHelper); + return; + } + + // + // Set Props ... + name = _name; + symbol = _symbol; + period = _period; + inputs = _inputs; + config = _config; + + // + // Set Dfault Values ... + mProcessedTicksCount = 0; + mLastCheckedBarTime = NULL; + } + + // + // Deconstructor ... + ~XCXOM1SignallerBase() + { + // + inputs.Clean(); + + // + SpecifiedClean(zones); + + // + delete mHelper; + ZeroMemory(mHelper); + } + + // + // Actions ... + + /** + * Handle Ticks Process ... + * + * @param barIndex: int + */ + void ProcessTick(int barIndex = 0) + { + // + // Normalize Bar Index ... + if (barIndex < 0) + { + barIndex = 0; + } + + // + // Define Requirements ... + XOHCL iBar; + bool has = false; + bool isNewBar = false; + + // + // Get Current Bar Time ... + datetime cBarTime = GetBarTime( + symbol, + period, + barIndex // + ); + + // + // Validate Bar Time ... + has = IsSpecifiedValid(cBarTime); + if (!has) + { + return; + } + + // + // Check if new Bar, Reset Processed Ticks Count ... + isNewBar = cBarTime > mLastCheckedBarTime; + if (isNewBar) + { + // + mProcessedTicksCount = 0; + ProcessNewBar(barIndex); + } + + // + // Check Allow Process ... + // Process All Ticks ... + // Process New Bars ... + has = config.processAllTicks || + (!config.processAllTicks && isNewBar); + if (!has) + { + return; + } + + // + // Initialize iBar ... + has = iBar.Init( + symbol, + period, + barIndex // + ); + if (!has) + { + // + iBar.Clean(); + return; + } + + // + // Update Indicator Helper ... + mHelper.Update(barIndex); + + // + // Do All Processing Mechanism ... + + // + // Reading Conditions from Helper ... + XOM1Conditions iConditions; + has = mHelper.GetConditions( + iConditions, + barIndex // + ); + if (!has) + { + // + iBar.Clean(); + iConditions.Clean(); + return; + } + + // + int zIdx = 0; + int cIdx = zIdx++; + int pIdx = cIdx++; + int p2Idx = pIdx++; + + // + // Check New Peak or Vale Happens ... + // New Peak Under Last ... + // New Vale Over Last ... + bool isValeReason = iConditions.valeBuffer[cIdx] > iConditions.valeBuffer[pIdx]; + bool isPeakReason = iConditions.peakBuffer[cIdx] < iConditions.peakBuffer[pIdx]; + has = isValeReason || isPeakReason; + if (!has) + { + // + iBar.Clean(); + iConditions.Clean(); + return; + } + + // + // Prepare Reason ... + ENUM_XOM1_ZONE_REASON iReason = isValeReason + ? X_OM1_ZONE_REASON_VALE + : X_OM1_ZONE_REASON_PEAK; + + // + // Extract Upper / Lower Values ... + double iUpper = iConditions.peakBuffer[pIdx]; + double iLower = iConditions.valeBuffer[pIdx]; + + // + // Calculate Mid Range ... + double iMiddle = iLower + ((iUpper - iLower) / 2); + if (iMiddle > 0) + { + iMiddle = NormalizePrice(iMiddle, symbol); + } + + // + // Detect Reason Price ... + double iPrice = + isValeReason + ? iConditions.valeBuffer[cIdx] + : iConditions.peakBuffer[cIdx]; + if (iPrice > 0) + { + iPrice = NormalizePrice(iPrice, symbol); + } + + // + // Detect Reason Direction ... + ENUM_X_DIRECTION iDir = iPrice > iMiddle + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + // Try to Initialize Zone ... + XOM1Zone iZone; + has = iZone.Init( + symbol, + period, + name, // Signaller Name ... + iUpper, + iLower, + iPrice, + iDir, + iReason, + iConditions.bars[pIdx].time // From ... + ); + if (has) + { + // + // Add New Detected Zone to Zones ... + AddRef( + iZone, + zones // + ); + } + + // + // Set Last Works ... + mProcessedTicksCount++; + mLastCheckedBarTime = cBarTime; + + // + // Clean Resources ... + iBar.Clean(); + iZone.Clean(); + iConditions.Clean(); + } + + // + // Virtuals ... + + // + // Protected ... + protected: + // + // Private ... + private: + // + // Props ... + + // + XCXOM1Helper *mHelper; // Indicator Helper ... + + // + int mProcessedTicksCount; // Prcoessed Ticks Count ... + datetime mLastCheckedBarTime; // Last Checked Bar Time ... + + /** + * Handle New Bar's Process ... + * + * @param barIndex: int + */ + void ProcessNewBar(int barIndex = 0) + { + // + // Normalize Bar Index ... + if (barIndex < 0) + { + barIndex = 0; + } + + // + // Try to Update Zone's Lifetime ... + int count = ArraySize(zones); + bool has = count > 0; + if (has) + { + // + // Loop through Zones ... + for (int i = 0; i < count; i++) + { + // + // Update Lifetime by Bar Index ... + zones[i].UpdateByBarIndex(barIndex); + } + } + } +}; + +// \ No newline at end of file diff --git a/XOM1EA/Libraries/xom1ea.lib.mq5 b/XOM1EA/Libraries/xom1ea.lib.mq5 index e69de29b..c5877329 100644 --- a/XOM1EA/Libraries/xom1ea.lib.mq5 +++ b/XOM1EA/Libraries/xom1ea.lib.mq5 @@ -0,0 +1,373 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: XOM1EA Lib +// Description: Library for XOM1EA ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm Library for XOM1EA Signaller" +#property strict + +// +// Imports ... +#include "../../Libraries/x-saherelm.common.lib.mq5" + +// +// Definitions ... + +// +// Zone Creation Reason ... +enum ENUM_XOM1_ZONE_REASON +{ + X_OM1_ZONE_REASON_NONE, + X_OM1_ZONE_REASON_PEAK, + X_OM1_ZONE_REASON_VALE +}; + +/** + * Validate a Zone Creation Reason ... + * + * @param value: ENUM_XOM1_ZONE_REASON + * + * @return ( bool ) + */ +bool IsXValid(ENUM_XOM1_ZONE_REASON value) +{ + // + bool result = false; + + // + result = value != X_OM1_ZONE_REASON_NONE; + + // + return result; +} + +/** + * Converts a Zone Reason to String ... + * + * @param value: ENUM_XOM1_ZONE_REASON + * + * @return ( string ) + */ +string ToXString(ENUM_XOM1_ZONE_REASON value) +{ + // + string result = NULL; + + // + if (!IsXValid(value)) + { + return result; + } + + // + switch (value) + { + // + case X_OM1_ZONE_REASON_PEAK: + result = "PEAK"; + break; + + // + case X_OM1_ZONE_REASON_VALE: + result = "VALE"; + break; + } + + // + return result; +} + +/** + * Converts a Zone Reason to String ... + * + * @param value: ENUM_XOM1_ZONE_REASON + * + * @return ( string ) + */ +ENUM_XOM1_ZONE_REASON FromXString(string value) +{ + // + ENUM_XOM1_ZONE_REASON result = X_OM1_ZONE_REASON_NONE; + + // + if (!IsSpecifiedValid(value)) + { + return result; + } + + // + if (value == ToXString(X_OM1_ZONE_REASON_NONE)) + { + result = X_OM1_ZONE_REASON_NONE; + } + else if (value == ToXString(X_OM1_ZONE_REASON_PEAK)) + { + result = X_OM1_ZONE_REASON_PEAK; + } + else if (value == ToXString(X_OM1_ZONE_REASON_VALE)) + { + result = X_OM1_ZONE_REASON_VALE; + } + + // + return result; +} + +// +// this is a Zone Which +// we start Looking for +// Signal Detecting ... +struct XOM1Zone +{ + // + // Props ... + + // + string symbol; // Symbol + ENUM_TIMEFRAMES period; // Period + string signaller; // Signaller Identifier + datetime from; // Detection Time + datetime to; // Lifetime + ENUM_X_DIRECTION dir; // Direction + ENUM_XOM1_ZONE_REASON reason; // Creation Reason + double upper; // Upper Level + double lower; // Lower Level + double price; // Reason Price + + // + // Constructor ... + XOM1Zone() + { + Clean(); + } + + // + // Tools ... + + /** + * Initialize ... + * + * @param _symbol: Symbol + * @param _period: Period + * @param _signaller: Signaller Identifier + * @param _upper: Upper Value (PEAK) + * @param _lower: Lower Value (VALE) + * @param _price: Price (Changed Peak or Vale) + * @param _dir: Direction + * @param _reason: Creation Reason + * @param _from: Detection Time + * + * @return ( bool ) + */ + bool Init( + string _symbol, + ENUM_TIMEFRAMES _period, + string _signaller, + double _upper, + double _lower, + double _price, + ENUM_X_DIRECTION _dir, + ENUM_XOM1_ZONE_REASON _reason, + datetime _from // + ) + { + // + to = _from; + dir = _dir; + from = _from; + upper = _upper; + lower = _lower; + price = _price; + symbol = _symbol; + period = _period; + reason = _reason; + signaller = _signaller; + + // + bool result = IsValid(); + if (!result) + { + Clean(); + } + + // + return result; + } + + /** + * Update Lifetime by Data ... + * + * @param _to: datetime + */ + void UpdateByDate(datetime _to) + { + // + // Validate ... + bool isValid = IsValid() && + IsSpecifiedValid(_to) && + _to > to; + if (!isValid) + { + return; + } + + // + to = _to; + } + + /** + * Update Lifetime by BarIndex ... + * + * @param barIndex: int + */ + void UpdateByBarIndex(int barIndex) + { + // + // Normalize ... + if (barIndex <= 0) + { + barIndex = 0; + } + + // + if (!IsValid()) + { + return; + } + + // + datetime _to = GetBarTime( + symbol, + period, + barIndex // + ); + if (!IsSpecifiedValid(_to)) + { + return; + } + + // + UpdateByDate(_to); + } + + /** + * Clean ... + */ + void Clean() + { + ZeroMemory(this); + } + + /** + * Validate ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = + // + IsSpecifiedValid(symbol) && + IsSpecifiedValid(period) && + IsSpecifiedValid(signaller) && + IsSpecifiedValid(from) && + IsSpecifiedValid(to) && + to >= from && + HasDirection(dir) && + IsXValid(reason) && + upper > 0 && + lower > 0 && + price > 0 && + upper > lower && + price <= upper && + price >= lower + // + ; + + // + return result; + } + + /** + * Calculate Lifetime Age ... + * + * @return ( int ) + */ + int GetBarLife() + { + // + int result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + int fromIDX = GetBarIndex( + symbol, + period, + from // + ); + int toIDX = GetBarIndex( + symbol, + period, + to // + ); + bool isValid = IsValidIndex(fromIDX) && IsValidIndex(toIDX); + if (!isValid) + { + return result; + } + + // + result = MathAbs(fromIDX - toIDX); + + // + return result; + } + + /** + * Unique Identifier ... + * + * @return ( string ) + */ + string GetTag() + { + // + string result = NULL; + + // + result = "XOM1Zone_" + + symbol + "_" + + ToXString(period) + "_" + + signaller + "_" + + ToXString(dir) + "_" + + ToXString(reason) + "_" + + ToXString(TimeToSeconds(from)); + + // + return result; + } +}; + +// \ No newline at end of file