diff --git a/Documents/BKP/Temp/z-zone.mq5 b/Documents/BKP/Temp/z-zone.mq5 new file mode 100644 index 00000000..a6421c48 --- /dev/null +++ b/Documents/BKP/Temp/z-zone.mq5 @@ -0,0 +1,805 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// ---------------------------------------------- +// Name: XSCZone +// Description: provides all Zone 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 +#include +#include "../Classes/x-saherelm.base.class.mq5" +#include "../Libraries/x-saherelm.draw.lib.mq5" +#include + +// +// Definitions ... +#define defZoneBGColor CLR_NONE // clrLightGray +#define defZoneLBLColor clrWhite + +// +// All Required Inputs ... +struct XSCZonesInput +{ + // + int length; // Calculation Length + int numberOfZones; // Number of Zones + + // + double levels[]; // Levels Percentage + color colors[]; // level Colors + + // + // Constructor ... + void XSCZonesInput() + { + Clean(); + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + length = 0; + numberOfZones = 0; + + // + Clean(levels); + Clean(colors); + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + length >= 5 && + numberOfZones >= 2 + // + ; + + // + return result; + } + + // + // Add Specified Level/Color ... + void AddLevelColor( + double level, + color clr // + ) + { + // + Add( + level, + levels); + + // + Add( + clr, + colors // + ); + } + + // + // Retrieve Sort Indexed Levels Color ... + void RetrieveSortedLevels( + double &_levels[], + color &_colors[] // + ) + { + // + Clean(_levels); + Clean(_colors); + + // + int levelsCount = ArraySize(levels); + int colorsCount = ArraySize(colors); + + // + bool hasChild = IsValidSize(levelsCount) && + IsValidSize(colorsCount); + if (!hasChild) + { + return; + } + + // + // Create Temp Levels ... + double tmpLevels[]; + Copy( + levels, + tmpLevels // + ); + ArraySort(tmpLevels); + ArrayReverse(tmpLevels); + + // + // Size of Looping ... + int minSize = MathMin(levelsCount, colorsCount); + + // + for (int i = 0; i < minSize; i++) + { + // + double iLevel = tmpLevels[i]; + + // + int iLevelIDX = FindIndex( + iLevel, + levels // + ); + if (!IsValidIndex(iLevelIDX)) + { + continue; + } + + // + Add( + levels[iLevelIDX], + _levels // + ); + + // + Add( + colors[iLevelIDX], + _colors // + ); + } + } +}; + +// +// Class ... + +// +// Specific Zone ... +class XSCZone : public CObject +{ + // + // Public ... +public: + // + // Props ... + double high; + double low; + int ticks; + double percent; + + // + // Compare Two Zone With Each Other ... + virtual int Compare( + const CObject *node, + const int mode = 0 // + ) const + { + // + const XSCZone *other = (XSCZone *)node; + + // + return other.ticks - ticks; + } + + // + // Create Object ... + + // + // Protected ... +protected: + // + // Private ... +private: +}; + +// +// Zones ... + +// +class XSCZones : public XSCBase +{ + // + // Public ... +public: + // + // Constructor(s) ... + void XSCZones( + string symbol, + ENUM_TIMEFRAMES period // + ) : XSCBase() + { + // + this.mSymbol = symbol; + this.mPeriod = period; + } + + // + void ~XSCZones() + { + // + mZones.Clear(); + mChartObjects.Clear(); + } + + // + // Initialize Zones by Providing required + // Input Variables ... + bool Init( + XSCZonesInput &inputs // Inputs ... + ) + { + // + bool result = false; + + // + // Validate Inputs ... + result = inputs.IsValid(); + if (!result) + { + return result; + } + + // + // Set Inputs ... + mInputs = inputs; + + // + // Do Calculatins ... + Calculate(); + + // + return result; + } + + // + XSCZonesInput GetInputs() + { + return mInputs; + } + + // + bool SetInputs(XSCZonesInput &inputs) + { + return Init(inputs); + } + + // + // Overrides ... + + // + string GetTag() override + { + return "XZONE"; + } + + // + // Retrieve Title Prefix ... + string GetIdentifier() + { + // + string result = NULL; + + // + if (!IsValid()) + { + return result; + } + + // + result = GetTag() + "_" + + mSymbol + "_" + + ToString(mPeriod) + + ToFormatString(mStartTime) + "_" + + ToFormatString(mEndTime); + + // + return result; + } + + // + bool IsValid() + { + // + bool result = false; + + // + result = + // + mZones.Total() > 0 + // + ; + + // + return result; + } + + // + // Add Specified Level/Color ... + void AddLevelColor( + double level, + color clr // + ) + { + // + mInputs.AddLevelColor( + level, + clr // + ); + } + + // + void Calculate() + { + // + // Prevent Double Calculating ... + int bars = iBars( + mSymbol, + mPeriod // + ); + if (mCalculatedBars == bars) + { + return; + } + + // + mCalculatedBars = bars; + + // + // Calculate Start and End Time ... + + // + mStartTime = iTime( + mSymbol, + mPeriod, + mInputs.length + 1 // + ); + + // + mEndTime = iTime( + mSymbol, + mPeriod, + 0 // + ); + + // + // Retrieve Ticks between Times ... + Clean(mTicks); + CopyTicksRange( + mSymbol, + mTicks, + COPY_TICKS_ALL, + mStartTime * 1000, + mEndTime * 1000 // + ); + + // + // Retrieve Highs ... + Clean(mHighs); + CopyHigh( + mSymbol, + mPeriod, + mStartTime, + mEndTime, + mHighs // + ); + + // + // Find Highest Value in Range ... + int highIDX = ArrayMaximum(mHighs); + mRangeHigh = mHighs[highIDX]; + + // + // Retrieve Lows ... + Clean(mLows); + CopyLow( + mSymbol, + mPeriod, + mStartTime, + mEndTime, + mLows // + ); + + // + // Find Lowest Value in Range ... + int lowIDX = ArrayMinimum(mLows); + mRangeLow = mLows[lowIDX]; + + // + datetime mTimes[]; + CopyTime( + mSymbol, + mPeriod, + mStartTime, + mEndTime, + mTimes // + ); + mRangeHighTime = mTimes[highIDX]; + mRangeLowTime = mTimes[lowIDX]; + + // + double mRangeSize = GetRange(); + + // + // Prepare Zones Array ... + mZones.Clear(); + + // + // Create Zones ... + for (int i = 0; i < mInputs.numberOfZones; i++) + { + // + // Instance a New Zone ... + XSCZone *iZone = new XSCZone(); + + // + // Calculate Each Zones High / Low based on Range ... + double iH = mRangeHigh - mRangeSize * i / mInputs.numberOfZones; + double iL = mRangeHigh - mRangeSize * (i + 1) / mInputs.numberOfZones; + + // + // Set Zone High Low Properties ... + iZone.low = iL; + iZone.high = iH; + + // + // Add Zone to Zone Array Objects ... + mZones.Add(iZone); + } + + // + // Calculate Each Zone Ticks ... + int mTicksCount = CountTicks(); + for (int i = 0; i < mTicksCount; i++) + { + // + // Retrieve i Index Tick Object ... + MqlTick iTick = mTicks[i]; + + // + // Loop Through Zones ... + for (int j = 0; j < mZones.Total(); j++) + { + // + // Retrieve j Index Zone Object ... + XSCZone *jZone = mZones.At(j); + + // + bool isInRange = IsTickInZoneRange( + iTick, + jZone // + ); + if (isInRange) + { + // + jZone.ticks++; + break; + } + } + } + + // + // Calculating Zone Percents ... + for (int i = 0; i < mZones.Total(); i++) + { + // + XSCZone *iZone = mZones.At(i); + + // + double percent = CalculateZoneTickPercent(iZone); + iZone.percent = percent; + } + + // + mZones.Sort(); + } + + // + int CountZones() + { + return mZones.Total(); + } + + // + XSCZone *GetZone(int index) + { + return mZones.At(index); + } + + // + double CalculateZoneTickPercent( + XSCZone *zone, + int normalizationDigits = 2 // + ) + { + // + double result = 0; + + // + if (normalizationDigits < 2 || normalizationDigits > 5) + { + normalizationDigits = 2; + } + + // + int ticksCount = CountTicks(); + if (ticksCount <= 0) + { + return result; + } + + // + result = (double)zone.ticks / ticksCount * 100; + result = NormalizeDouble(result, normalizationDigits); + + // + return result; + } + + // + bool Draw( + long chartId = 0, + string prefix = "XSCZone", + int subWindow = 0, + bool redraw = false // + ) + { + // + bool result = false; + + // + if (redraw) + { + mChartObjects.Clear(); + } + + // + if (StringLen(prefix) <= 0) + { + prefix = "XSCZone"; + } + + // + int zonesCount = mZones.Total(); + result = IsValidSize(zonesCount); + if (!result) + { + return result; + } + + // + mZones.Sort(); + + // + int ticksCount = CountTicks(); + result = IsValidSize(ticksCount); + if (!result) + { + return result; + } + + // + double levels[]; + color colors[]; + mInputs.RetrieveSortedLevels( + levels, + colors // + ); + int levelsCount = ArraySize(levels); + int colorsCount = ArraySize(colors); + bool canSetLevels = IsValidSize(levelsCount) && + IsValidSize(colorsCount) && + levelsCount == colorsCount; + + // + // Loop Through Zones ... + for (int i = 0; i < zonesCount; i++) + { + // + XSCZone *iZone = mZones.At(i); + + // + // Generate Chart Object Names ... + string iRectName = prefix + ToString(i); + string iLabelName = iRectName + "_lbl"; + + // + // Creating Rectangles ... + CChartObjectRectangle *iRect = new CChartObjectRectangle(); + result = iRect.Create( + chartId, + iRectName, + subWindow, + mStartTime, + iZone.high, + mEndTime, + iZone.low // + ); + if (!result) + { + break; + } + + // + // Set Default Rectangle Color ... + // iRect.Color(defZoneBGColor); + iRect.Fill(true); + + // + // Create Label ... + CChartObjectLabel *iLabel = new CChartObjectLabel(); + result = iLabel.Create( + chartId, + iLabelName, + subWindow, + mStartTime, + iZone.high // + ); + if (!result) + { + break; + } + + // + iLabel.Color(defZoneLBLColor); + + // + iLabel.Description(ToString(iZone.percent) + "%"); + + // + // Set Levels and Colors if Provided ... + if (canSetLevels) + { + // + color iRectColor = defZoneBGColor; + for (int z = 0; z < levelsCount; z++) + { + // + double zLevel = levels[z]; + color zColor = colors[z]; + + // + if (iZone.ticks >= ticksCount * zLevel) + { + // + iRectColor = zColor; + break; + } + } + + // + iRect.Color(iRectColor); + } + + // + mChartObjects.Add(iRect); + mChartObjects.Add(iLabel); + } + + // + return result; + } + + // + bool Remove( + long chartId = 0, + string prefix = "XSCZone", + int subWindow = 0, + bool redraw = false // + ) + { + // + bool result = false; + + // + mChartObjects.Clear(); + + // + result = + // + true + // + ; + + // + return result; + } + + // + // Protected ... +protected: + // + // Props ... + + // + datetime mStartTime; + datetime mEndTime; + + // + MqlTick mTicks[]; + double mHighs[]; + double mLows[]; + double mRangeHigh; + datetime mRangeHighTime; + double mRangeLow; + datetime mRangeLowTime; + + // + CArrayObj mZones; + CArrayObj mChartObjects; + + // + // Tools ... + + // + int CountTicks() + { + return ArraySize(mTicks); + } + + // + double GetRange() + { + return mRangeHigh - mRangeLow; + } + + // + // Check a Tick is in a Zone rage or not ... + bool IsTickInZoneRange( + MqlTick &tick, // Tick For Checking + XSCZone *zone // Zone For Checking + ) + { + // + bool result = false; + + // + result = + // + tick.bid >= zone.low && + tick.bid <= zone.high + // + ; + + // + return result; + } + + // + // Private ... +private: + // + // Props ... + + // + string mSymbol; // Analyzing Symbol + ENUM_TIMEFRAMES mPeriod; // Analyzing Period + + // + XSCZonesInput mInputs; // Configurations + + // + int mCalculatedBars; // Calculated Bars ... +}; \ No newline at end of file