diff --git a/Classes/Indicators/x-saherelm.mid.class.mq5 b/Classes/Indicators/x-saherelm.mid.class.mq5 new file mode 100644 index 00000000..e2eef797 --- /dev/null +++ b/Classes/Indicators/x-saherelm.mid.class.mq5 @@ -0,0 +1,367 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// ---------------------------------------------- +// Name: XSCBaseInd +// Description: provides Indicator implementation +// 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.xind.class.mq5" + +// +// XSCMid Indicator Buffers ... +enum ENUM_XSCMID_BUFFERS +{ + XSCMID_MAIN_LINE = 0, // Main Buffer ... + XSCMID_STATE_LINE = 1, // State Buffer ... +}; + +// +// XSCMid Indicator Inputs ... +struct XSCMidInputs +{ + // + // Props ... + + // + int length; // Market Length ... + + // + // Constructor ... + XSCMidInputs() + { + Clean(); + } + + // + // Tools ... + + // + // Initial Inputs ... + bool Init( + int mLength // Market Length + ) + { + // + bool result = false; + + // + result = + // + mLength >= 2 + // + ; + if (!result) + { + return result; + } + + // + this.length = mLength; + + // + result = IsValid(); + + // + return result; + } + + // + // Cleanup ... + void Clean() + { + // + this.length = 0; + } + + // + // Default ... + void Default() + { + // + this.length = 2; + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + length > 1 + // + ; + + // + return result; + } + + // + // Retrieve Max Length ... + int Max() + { + // + int result = 0; + + // + result = MathMax(this.length, this.length); + + // + return result; + } +}; + +// +// a Simple Indicator ... + +class XSCMid : public XSCBaseInd +{ + // + // Public ... +public: + // + // Props ... + + // + // Constructor(s) ... + void XSCMid( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period // Trading TimeFrame + ) : XSCBaseInd(symbol, period) + { + // + string token = GetTag(); + + // + SetAlertPrefix(token); + } + + // + // Deconstructor ... + void ~XSCMid() {} + + // + // Initialize Indicator ... + bool Init( + XSCMidInputs &inputs // Indicator Inputs ... + ) + { + // + bool result = false; + + // + result = inputs.IsValid(); + if (!result) + { + return result; + } + + // + // Set Inputs ... + this.mInputs = inputs; + + // + // Validate Indicator State ... + result = this.IsValid(); + if (!result) + { + return result; + } + + // + // Register Required Buffers ... + XBuffer main; + result = main.Init( + "XSCMid", + false // + ); + if (!result) + { + return result; + } + + // + result = SetBuffer(main); + if (!result) + { + return result; + } + + // + // Calculate First Time ... + Calculate(); + + // + return result; + } + + // + // Property Getter(s) / Setter(s) ... + + // + XSCMidInputs GetInputs() + { + return mInputs; + } + + // + bool SetInputs( + XSCMidInputs &inputs // Indicator Inputs + ) + { + return Init(inputs); + } + + // + // Override(s) ... + + // + // Get Tag ... + string GetTag() override + { + // + string result = NULL; + + // + result = GetToken(); + + // + return result; + } + + // + // Get Token ... + string GetToken() override + { + // + string result = NULL; + + // + result = GetSpecificToken(this); + + // + return result; + } + + // + // Validate Inputs ... + bool IsValidInputs() override + { + return mInputs.IsValid(); + } + + // + // Calculate Buffers ... + void Calculate() override + { + // + int max = mInputs.Max(); + int totalBars = CountBars(); + int prevCalculated = GetCalculatedBars(); + + // + // Prepare Buffers Index ... + int mainIDX = GetBufferIndex("XSCMid"); + + // + int start = 0; + + // + if (prevCalculated == 0) + { + // + if (max > 0) + { + for (int i = 0; i < max; i++) + { + // + for (int j = 0; j < CountBuffers(); j++) + { + mBuffers[j].Add(0); + } + } + } + } + else + { + start = prevCalculated - 1; + } + + // + // Loop through Bars ... + for (int i = start; i < totalBars - 1 && !IsStopped(); i++) + { + // + XOHCL iBar; + iBar.Init( + mSymbol, + mPeriod, + i // + ); + + // + double iValue = iBar.close; + + // + Print("BarIndex: " + ToString(i), ", iValue: ", iValue); + + // + if (i > ArraySize(mBuffers[mainIDX].values) - 1) + { + ArrayResize(mBuffers[mainIDX].values, i + 1); + } + + // + mBuffers[mainIDX].values[i] = iValue; + } + + // + // Prevent Double Calculation Same Bars ... + mCalculatedBars = totalBars; + } + + // + // De Initialize Class ... + void DeInit(int reason) + { + } + + // + // Tools ... + + // + // Reading Values ... + + // + // Protected ... +protected: + // + // Private ... +private: + // + // Props ... + + // + // Inputs ... + XSCMidInputs mInputs; +}; \ No newline at end of file diff --git a/Classes/x-saherelm.base.class.mq5 b/Classes/x-saherelm.base.class.mq5 index cde0dd8e..7c37e1d4 100644 --- a/Classes/x-saherelm.base.class.mq5 +++ b/Classes/x-saherelm.base.class.mq5 @@ -86,3 +86,5 @@ protected: // Private ... private: }; + +// \ No newline at end of file diff --git a/Classes/x-saherelm.xind.mq5 b/Classes/x-saherelm.xind.class.mq5 similarity index 53% rename from Classes/x-saherelm.xind.mq5 rename to Classes/x-saherelm.xind.class.mq5 index fe4b9c37..3b359a15 100644 --- a/Classes/x-saherelm.xind.mq5 +++ b/Classes/x-saherelm.xind.class.mq5 @@ -164,7 +164,7 @@ struct XBuffer } // - ArraySetAsSeries(values, false); + ArraySetAsSeries(values, true); // int count = Count(); @@ -255,6 +255,39 @@ struct XBuffer } }; +// +struct XBufferPlotStyle +{ + // + int width; // Width + color clr; // Color + uchar arrow; // Arrow Code + ENUM_DRAW_TYPE type; // Type + ENUM_LINE_STYLE style; // Style + + // + // Constructor ... + XBufferPlotStyle() + { + Default(); + } + + // + // Tools ... + + // + // Default ... + void Default() + { + // + width = 1; + arrow = 0; + clr = CLR_NONE; + type = DRAW_NONE; + style = STYLE_SOLID; + } +}; + // // Base Indicator Class ... class XSCBaseInd : public XSCBaseAlert @@ -265,16 +298,44 @@ public: // // Props ... + // + // Indicators Buffers ... + XBuffer mBuffers[]; + // // Constructor(s) ... - void XSCBaseInd() : XSCBaseAlert() + void XSCBaseInd( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period // Trading TimeFrame + ) : XSCBaseAlert() { + // + mSymbol = symbol; + mPeriod = period; + + // + mCalculatedBars = 0; } // // Deconstructor ... void ~XSCBaseInd() {} + // + // Property Getter(s) / Setter(s) ... + + // + string GetSymbol() + { + return mSymbol; + } + + // + ENUM_TIMEFRAMES GetPeriod() + { + return mPeriod; + } + // // Overrides ... @@ -285,40 +346,7 @@ public: virtual string GetToken(); // - // Indicator Initializitation - virtual bool Init( - string symbol, // Trading Symbol - ENUM_TIMEFRAMES period // Trading TimeFrame - ) - { - // - bool result = false; - - // - result = - // - IsSpecifiedValid(symbol) && - IsSpecifiedValid(period) - // - ; - if (!result) - { - return result; - } - - // - mSymbol = symbol; - mPeriod = period; - - // - mCalculatedBars = 0; - - // - return result; - } - - // - virtual bool DeInit(); // Indicator DeInitialization + virtual void DeInit(int reason); // Indicator DeInitialization // // Validate Inputs ... @@ -329,10 +357,18 @@ public: // // Calculate ... + virtual void Calculate() {} // // Tools ... + // + // Retrieve Calculate Bars ... + int GetCalculatedBars() + { + return mCalculatedBars; + } + // // Count available Bars ... int CountBars() @@ -359,27 +395,33 @@ public: } // - // TODO: Implement this ... + result = + // + IsSpecifiedValid(mSymbol) && + IsSpecifiedValid(mPeriod) + // + ; // return result; } // - // Protected ... -protected: - // - // Props ... + // Calculate Limit ... + // this means Required Bars for Calculation ... + int CalculateLimit() + { + // + int result = 0; - // - string mSymbol; // Trading Symbol - ENUM_TIMEFRAMES mPeriod; // Trading TimeFrame + // + int totalBars = CountBars(); + int calculatedBars = GetCalculatedBars(); + result = MathAbs(totalBars - calculatedBars); - // - int mCalculatedBars; // Calculated Bars - - // - // Tools ... + // + return result; + } // // Buffer Registrations ... @@ -401,7 +443,7 @@ protected: int result = -1; // - if (!IsValid(title)) + if (!IsSpecifiedValid(title)) { return result; } @@ -515,12 +557,277 @@ protected: } // - // Private ... -private: + int CopyBuffer( + string mTitle, // Required Buffer Title + double &buffer[], // Buffer Dest + int start = 0, // Start + int count = 0 // Count, if 0 Whole + ) + { + // + int result = 0; + + // + // Validate State ... + if (!IsValid()) + { + return result; + } + + // + // Clean(buffer); + + // + int bufferIDX = GetBufferIndex(mTitle); + if (bufferIDX < 0) + { + return result; + } + + // + Calculate(); + + // + for (int i = start; i < start + count - 1; i++) + { + // + result++; + buffer[i] = mBuffers[bufferIDX].values[i]; + } + + // + return result; + } + + // + // Protected ... +protected: // // Props ... // - // Indicators Buffers ... - XBuffer mBuffers[]; -} \ No newline at end of file + string mSymbol; // Trading Symbol + ENUM_TIMEFRAMES mPeriod; // Trading TimeFrame + + // + int mCalculatedBars; // Calculated Bars + + // + // Tools ... + + // + // Private ... +private: + // + // Props ... +}; + +// +// Tools ... + +// +// Register a Buffer as Indexed Buffer ... +void SetIndexBuffer( + int &index, // the Index refrence for Buffer + double &buffer[], // Buffer to Set + XBufferPlotStyle &style, // Style to Apply to Buffer + double &colorBuffer[], // Color Buffer + string label = NULL, // Buffer Label + bool showData = true, // Show Data on Data Window + double empty = -1, // Set 0 or EMPTY_VALUE used for setting Empty Value + int drawBegin = -1 // if Set More Than -1 applied +) +{ + // + // Set Buffer Index ... + SetIndexBuffer(index, buffer, INDICATOR_DATA); + + // + // Show Date ... + PlotIndexSetInteger(index, PLOT_SHOW_DATA, showData); + + // + // Set Buffer Label ... + if (IsValid(label)) + { + PlotIndexSetString(index, PLOT_LABEL, label); + } + + // + if (empty == 0 || empty == EMPTY_VALUE) + { + PlotIndexSetDouble(index, PLOT_EMPTY_VALUE, empty); + } + + // + if (drawBegin > -1) + { + PlotIndexSetInteger(index, PLOT_DRAW_BEGIN, drawBegin); + } + + // + if (style.type == DRAW_ARROW) + { + PlotIndexSetInteger(index, PLOT_ARROW, style.arrow); + } + + // + PlotIndexSetInteger(index, PLOT_LINE_STYLE, style.style); + PlotIndexSetInteger(index, PLOT_LINE_WIDTH, style.width); + + // + string drawTypeStr = EnumToString(style.type); + bool hasColorBuffer = Contains("COLOR", drawTypeStr); + + // + if (!hasColorBuffer) + { + PlotIndexSetInteger(index, PLOT_LINE_COLOR, style.clr); + } + else + { + // + // Since Color Buffers must add as next Index of it's own Buffer + // here before applied Color Buffer increase index ... + index++; + + // + SetIndexBuffer(index, colorBuffer, INDICATOR_COLOR_INDEX); + } + + // + // Increase Index for Next Buffer ... + index++; +} + +// +void SetIndexCandleBuffers( + int &index, // the Index refrence for Buffer + string openLabel, // Open Label + double &open[], // Open Buffer + string highLabel, // High Label + double &high[], // High Buffer + string lowLabel, // Low Label + double &low[], // Low Buffer + string closeLabel, // Close Label + double &close[], // Close Buffer + bool showData = true, // Show Data on Data Window + double empty = -1, // Set 0 or EMPTY_VALUE used for setting Empty Value + int drawBegin = -1 // if Set More Than -1 applied +) +{ + // + bool hasLabel = + // + IsValid(openLabel) && + IsValid(highLabel) && + IsValid(lowLabel) && + IsValid(closeLabel) + // + ; + + // + string label = + !hasLabel + ? NULL + : openLabel + ";" + highLabel + ";" + lowLabel + ";" + closeLabel; + + // + // Set Buffer Index ... + SetIndexBuffer(index, open, INDICATOR_DATA); + + // + // Set Draw Candles Type ... + PlotIndexSetInteger(index, PLOT_LINE_STYLE, DRAW_CANDLES); + + // + // Show Date ... + PlotIndexSetInteger(index, PLOT_SHOW_DATA, showData); + + // + // Set Buffer Label ... + if (IsValid(label)) + { + PlotIndexSetString(index, PLOT_LABEL, label); + } + + // + if (empty == 0 || empty == EMPTY_VALUE) + { + PlotIndexSetDouble(index, PLOT_EMPTY_VALUE, empty); + } + + // + if (drawBegin > -1) + { + PlotIndexSetInteger(index, PLOT_DRAW_BEGIN, drawBegin); + } + + // + index++; + + // + // Set Buffer Index ... + SetIndexBuffer(index, high, INDICATOR_DATA); + index++; + + // + // Set Buffer Index ... + SetIndexBuffer(index, low, INDICATOR_DATA); + index++; + + // + // Set Buffer Index ... + SetIndexBuffer(index, close, INDICATOR_DATA); + index++; +} + +// +void SetIndexCandleBuffers( + int &index, // the Index refrence for Buffer + string openLabel, // Open Label + double &open[], // Open Buffer + string highLabel, // High Label + double &high[], // High Buffer + string lowLabel, // Low Label + double &low[], // Low Buffer + string closeLabel, // Close Label + double &close[], // Close Buffer + double &colorBuffer[], // Candle Color Buffer + bool showData = true, // Show Data on Data Window + double empty = -1, // Set 0 or EMPTY_VALUE used for setting Empty Value + int drawBegin = -1 // if Set More Than -1 applied +) +{ + // + SetIndexCandleBuffers( + index, + openLabel, + open, + highLabel, + high, + lowLabel, + low, + closeLabel, + close, + showData, + empty, + drawBegin // + ); + + // + int mFirstIndex = index - 4; + + // + // Set Draw Candles Type ... + PlotIndexSetInteger(mFirstIndex, PLOT_LINE_STYLE, DRAW_COLOR_CANDLES); + + // + // Set Color Buffer ... + SetIndexBuffer(index, colorBuffer, INDICATOR_COLOR_INDEX); + + // + index++; +} + +// \ No newline at end of file diff --git a/Documents/BKP/Templates/x-saherelmindicator.template.class.mq5 b/Documents/BKP/Templates/x-saherelmindicator.template.class.mq5 new file mode 100644 index 00000000..b4a2e338 --- /dev/null +++ b/Documents/BKP/Templates/x-saherelmindicator.template.class.mq5 @@ -0,0 +1,59 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// ---------------------------------------------- +// Name: XSCBaseInd +// Description: provides Indicator implementation +// 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.xind.class.mq5" + +// +// a Simple Indicator ... + +class XSCMid : public XSCBaseInd +{ + // + // Public ... +public: + // + // Props ... + + // + // Constructor(s) ... + + // + // Deconstructor ... + + // + // Property Getter(s) / Setter(s) ... + + // + // Override(s) ... + + // + // Tools ... + + // + // Protected ... +protected: + // + // Private ... +private: +}; \ No newline at end of file diff --git a/Indicators/x-saherelm.xmidtest.mq5 b/Indicators/x-saherelm.xmidtest.mq5 new file mode 100644 index 00000000..bce0e1d1 --- /dev/null +++ b/Indicators/x-saherelm.xmidtest.mq5 @@ -0,0 +1,229 @@ +/////////////////////////////////////////////////////// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------- +// Name: XMidTest +// Description: DONCHAIN Channel ... +// +// 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 XMidTest Indicator" +#property strict + +// +// Imports ... +#include "../Classes/Indicators/x-saherelm.mid.class.mq5" + +// +#define ShortName "XMidTest" + +// +#property indicator_chart_window + +// +#property indicator_buffers 1 +#property indicator_plots 1 + +// +// Variables ... +XSCMid *mMid; + +// +#property indicator_type1 DRAW_LINE +double mainBuffer[]; +double mainColorBuffer[]; + +// +// Initialization ... +int OnInit() +{ + // + // Initialize Indicator Class ... + bool isInited = InitIndicatorClass(); + if (!isInited) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init Succeed ... + 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 + + // + mMid.DeInit(reason); + delete mMid; +} + +// +// Calculating what we want ... +int OnCalculate( + const int rates_total, // Total Bars on Chart ... + const int prev_calculated, // Total Calculated Bars on Charts ... + const datetime &time[], // History of Open Time ... + const double &open[], // History of Open Price ... + const double &high[], // History of High Price ... + const double &low[], // History of Low Price ... + const double &close[], // History of Close Price ... + const long &tick_volume[], // History of Tick Volumes on Bar ... + const long &volume[], // History of Trade Volumes ... + const int &spread[] // History of Spread Price ... +) +{ + // + // this counts Available Bars ... + int limit; + + // + // Check Calculated Bars ... + int midCalculatedBars = mMid.GetCalculatedBars(); + if (!IsValidSize(midCalculatedBars)) + { + return prev_calculated; + } + + // + // Calculating Limit ... + limit = (prev_calculated > rates_total || prev_calculated <= 0) ? rates_total : (rates_total - prev_calculated) + 1; + + // + + // + Print("Limit: ", limit, "last "); + + // + // int midMainBufferCopied = mMid.CopyBuffer( + // "XSCMid", + // mainBuffer, + // 0, + // rates_total // + // ); + // if (!IsValidSize(midMainBufferCopied)) + // { + // return prev_calculated; + // } + + // + // ChartRedraw(); + + // + return rates_total; +} + +// +// CUSTOM Functions ... + +// +// Validate Input Args for Initialization ... +bool InitIndicatorClass() +{ + // + bool result = false; + + // + // Initialize and Prepare + // Inputs of Indicator ... + XSCMidInputs inputs; + result = inputs.Init(2); + if (!result) + { + return result; + } + + // + // Instantiate Class ... + mMid = new XSCMid( + _Symbol, + _Period // + ); + + // + // Now Initialize Indicator Class using Given Inputs ... + result = mMid.Init( + inputs // + ); + + // + return result; +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + // Start Styling and Indexing Buffers ... + + // + int mainIDX = mMid.GetBufferIndex("XSCMid"); + XBuffer mainBufferStruct; + mMid.GetBuffer( + "XSCMid", + mainBufferStruct // + ); + + // + int bufferIndex = 0; + + // + int max = mMid.GetInputs().Max(); + + // + // mainBufferStruct.asSeries + // ArraySetAsSeries(mainBuffer, mainBufferStruct.asSeries); + + // + XBufferPlotStyle mainBufferStyle; + mainBufferStyle.clr = clrAqua; + mainBufferStyle.type = DRAW_LINE; + + // + SetIndexBuffer( + bufferIndex, + mainBuffer, + mainBufferStyle, + mainColorBuffer, + "XMID", + true, + 0, + max // + ); +} + +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} diff --git a/Libraries/x-saherelm.common.lib.mq5 b/Libraries/x-saherelm.common.lib.mq5 index e2bd85a6..79e5cf98 100644 --- a/Libraries/x-saherelm.common.lib.mq5 +++ b/Libraries/x-saherelm.common.lib.mq5 @@ -4685,7 +4685,7 @@ int Copy( // if (count == 0) { - count = ArraySize(source); + count = ArraySize(source) - 1 - start; } //