1011 lines
19 KiB
Plaintext
1011 lines
19 KiB
Plaintext
///////////////////////////////////////////////////////
|
|
// SaherElm IT Center MQL5 Indicator
|
|
// -------------------------------------------
|
|
// Name: XCHVP
|
|
// Description: XCHVP Cycles ...
|
|
//
|
|
// 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 XCHVP Indicator"
|
|
#property strict
|
|
|
|
//
|
|
#define ShortName "XCHVP"
|
|
|
|
//
|
|
// Includes Common Library ...
|
|
#include "../Classes/x-saherelm.zone.class.mq5"
|
|
#include "../Libraries/x-saherelm.draw.lib.mq5"
|
|
|
|
//
|
|
// Inputs ...
|
|
|
|
//
|
|
input group "Market";
|
|
input int numberOfLevels = 10; // Number of Levels in Each Zone
|
|
input int numberOfZones = 2; // Number of Zones in Each Cycle
|
|
|
|
//
|
|
input group "Cycles";
|
|
|
|
//
|
|
input group "Short";
|
|
input ENUM_X_PERIOD_METHOD scMethod = X_PERIOD_AUTO; // How to Find Period
|
|
input ENUM_TIMEFRAMES scPeriod = NULL; // Time Period
|
|
|
|
//
|
|
input group "Medium";
|
|
input ENUM_X_PERIOD_METHOD mcMethod = X_PERIOD_AUTO; // How to Find Period
|
|
input ENUM_TIMEFRAMES mcPeriod = NULL; // Time Period
|
|
|
|
//
|
|
input group "Long";
|
|
input ENUM_X_PERIOD_METHOD lcMethod = X_PERIOD_AUTO; // How to Find Period
|
|
input ENUM_TIMEFRAMES lcPeriod = NULL; // Time Period
|
|
|
|
//
|
|
input group "Hind";
|
|
input ENUM_X_PERIOD_METHOD hcMethod = X_PERIOD_AUTO; // How to Find Period
|
|
input ENUM_TIMEFRAMES hcPeriod = NULL; // Time Period
|
|
|
|
//
|
|
// Presentation ...
|
|
input group "Presentation";
|
|
|
|
//
|
|
input bool showShort = true; // Show Short Cycle
|
|
input bool showMedium = true; // Show Medium Cycle
|
|
input bool showLong = true; // Show Long Cycle
|
|
input bool showHind = true; // Show Hind Cycle
|
|
|
|
//
|
|
input color shortColor = clrAqua; // Short CycleColor
|
|
input color mediumColor = clrMagenta; // Medium Cycle Color
|
|
input color longColor = clrSeaGreen; // Long Cycle Color
|
|
input color hindColor = clrYellow; // Hind Cycle Color
|
|
|
|
//
|
|
// Buffers ...
|
|
|
|
//
|
|
#property indicator_chart_window
|
|
|
|
//
|
|
#property indicator_buffers 0
|
|
#property indicator_plots 0
|
|
|
|
//
|
|
// Variables, Properties and etc ...
|
|
|
|
//
|
|
int maxLength;
|
|
|
|
//
|
|
// Current ...
|
|
|
|
//
|
|
// Short ...
|
|
int mSCycleLength = 0;
|
|
ENUM_TIMEFRAMES mSCPeriod = NULL;
|
|
double mSLow;
|
|
double mSHigh;
|
|
double mSLows[];
|
|
double mSHighs[];
|
|
MqlTick mSTicks[];
|
|
CArrayObj mSZones;
|
|
datetime mSLowTime;
|
|
datetime mSHighTime;
|
|
datetime mSLastCalculateTime = NULL;
|
|
|
|
//
|
|
// Medium ...
|
|
int mMCycleLength = 0;
|
|
ENUM_TIMEFRAMES mMCPeriod = NULL;
|
|
double mMLow;
|
|
double mMHigh;
|
|
double mMLows[];
|
|
double mMHighs[];
|
|
MqlTick mMTicks[];
|
|
CArrayObj mMZones;
|
|
datetime mMLowTime;
|
|
datetime mMHighTime;
|
|
datetime mMLastCalculateTime = NULL;
|
|
|
|
//
|
|
// Long ...
|
|
int mLCycleLength = 0;
|
|
ENUM_TIMEFRAMES mLCPeriod = NULL;
|
|
double mLLow;
|
|
double mLHigh;
|
|
double mLLows[];
|
|
double mLHighs[];
|
|
MqlTick mLTicks[];
|
|
CArrayObj mLZones;
|
|
datetime mLLowTime;
|
|
datetime mLHighTime;
|
|
datetime mLLastCalculateTime = NULL;
|
|
|
|
//
|
|
// Hind ...
|
|
int mHCycleLength = 0;
|
|
ENUM_TIMEFRAMES mHCPeriod = NULL;
|
|
double mHLow;
|
|
double mHHigh;
|
|
double mHLows[];
|
|
double mHHighs[];
|
|
MqlTick mHTicks[];
|
|
CArrayObj mHZones;
|
|
datetime mHLowTime;
|
|
datetime mHHighTime;
|
|
datetime mHLastCalculateTime = NULL;
|
|
|
|
//
|
|
// Event Handlers ...
|
|
|
|
//
|
|
// Initialization ...
|
|
int OnInit()
|
|
{
|
|
//
|
|
// Validate Inputs ...
|
|
if (!ValidateInputs())
|
|
{
|
|
return INIT_PARAMETERS_INCORRECT;
|
|
}
|
|
|
|
//
|
|
if (!InitMarketCycles())
|
|
{
|
|
return INIT_PARAMETERS_INCORRECT;
|
|
}
|
|
|
|
//
|
|
// because in some cases we may have more than one input for
|
|
// calculation and we must prevent any calculation
|
|
// untill we pass the biggest input length, here we get max Input length
|
|
// and then wait until pass it ...
|
|
maxLength = ExtractMaxLengthOfInputs();
|
|
|
|
//
|
|
// Define Index Buffers ...
|
|
DefineBuffers();
|
|
|
|
//
|
|
// Set Indicator ShortName ...
|
|
SetIndicatorName();
|
|
|
|
//
|
|
drawPrefix = ShortName;
|
|
|
|
//
|
|
string comment =
|
|
//
|
|
"Short: " + ToString(mSCPeriod) + "\n" +
|
|
"Medium: " + ToString(mMCPeriod) + "\n" +
|
|
"Long: " + ToString(mLCPeriod) + "\n" +
|
|
"Hind: " + ToString(mHCPeriod) + "\n"
|
|
//
|
|
;
|
|
Comment(comment);
|
|
|
|
//
|
|
// 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
|
|
|
|
//
|
|
Comment("");
|
|
RemoveDraws();
|
|
}
|
|
|
|
//
|
|
// 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 ...
|
|
)
|
|
{
|
|
//
|
|
// Prepare Buffers ...
|
|
ArraySetAsSeries(time, true);
|
|
ArraySetAsSeries(open, true);
|
|
ArraySetAsSeries(high, true);
|
|
ArraySetAsSeries(low, true);
|
|
ArraySetAsSeries(close, true);
|
|
ArraySetAsSeries(tick_volume, true);
|
|
ArraySetAsSeries(volume, true);
|
|
ArraySetAsSeries(spread, true);
|
|
|
|
//
|
|
// this counts Available Bars ...
|
|
int limit;
|
|
|
|
//
|
|
limit = (prev_calculated > rates_total || prev_calculated <= 0) ? rates_total : (rates_total - prev_calculated) + 1;
|
|
|
|
//
|
|
// Main Loop ...
|
|
for (int i = limit - 1; i >= 0 && !IsStopped(); i--)
|
|
{
|
|
//
|
|
// Print("BarIndex: ", i);
|
|
|
|
//
|
|
CalculateBuffers(
|
|
//
|
|
i,
|
|
prev_calculated,
|
|
rates_total,
|
|
//
|
|
open,
|
|
high,
|
|
close,
|
|
low,
|
|
tick_volume
|
|
//
|
|
);
|
|
}
|
|
|
|
//
|
|
return rates_total;
|
|
}
|
|
|
|
//
|
|
// Functions ...
|
|
|
|
//
|
|
// Validate Input Args for Initialization ...
|
|
bool ValidateInputs()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result =
|
|
//
|
|
numberOfLevels > 0 &&
|
|
numberOfZones > 0 &&
|
|
(IsValid(scMethod, scPeriod) &&
|
|
IsValid(mcMethod, mcPeriod) &&
|
|
IsValid(lcMethod, lcPeriod) &&
|
|
IsValid(hcMethod, hcPeriod))
|
|
//
|
|
;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Initialize Market Cycles ...
|
|
bool InitMarketCycles()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Current Cycle Initialization ...
|
|
|
|
//
|
|
int cPeriodSeconds = PeriodSeconds(_Period);
|
|
|
|
//
|
|
// Short Cycle Initialization ...
|
|
|
|
//
|
|
// Find Cycle Period ...
|
|
if (scMethod == X_PERIOD_AUTO)
|
|
{
|
|
//
|
|
// Select Period ...
|
|
mSCPeriod = GetCyclePeriod(
|
|
X_MARKET_CYCLE_SHORT,
|
|
_Period //
|
|
);
|
|
}
|
|
else
|
|
{
|
|
mSCPeriod = scPeriod;
|
|
}
|
|
|
|
//
|
|
result = IsValid(mSCPeriod);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
mSCycleLength = PeriodSeconds(mSCPeriod) / cPeriodSeconds;
|
|
result = mSCycleLength > 0;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Medium Cycle Initialization ...
|
|
|
|
//
|
|
// Find Cycle Period ...
|
|
if (mcMethod == X_PERIOD_AUTO)
|
|
{
|
|
//
|
|
// Select Period ...
|
|
mMCPeriod = GetCyclePeriod(
|
|
X_MARKET_CYCLE_MEDIUM,
|
|
_Period //
|
|
);
|
|
}
|
|
else
|
|
{
|
|
mMCPeriod = mcPeriod;
|
|
}
|
|
|
|
//
|
|
result = IsValid(mMCPeriod);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
mMCycleLength = PeriodSeconds(mMCPeriod) / cPeriodSeconds;
|
|
result = mMCycleLength > 0;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Long Cycle Initialization ...
|
|
|
|
//
|
|
// Find Cycle Period ...
|
|
if (lcMethod == X_PERIOD_AUTO)
|
|
{
|
|
//
|
|
// Select Period ...
|
|
mLCPeriod = GetCyclePeriod(
|
|
X_MARKET_CYCLE_LONG,
|
|
_Period //
|
|
);
|
|
}
|
|
else
|
|
{
|
|
mLCPeriod = lcPeriod;
|
|
}
|
|
|
|
//
|
|
result = IsValid(mLCPeriod);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
mLCycleLength = PeriodSeconds(mLCPeriod) / cPeriodSeconds;
|
|
result = mLCycleLength > 0;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Hind Cycle Initialization ...
|
|
|
|
//
|
|
// Find Cycle Period ...
|
|
if (hcMethod == X_PERIOD_AUTO)
|
|
{
|
|
//
|
|
// Select Period ...
|
|
mHCPeriod = GetCyclePeriod(
|
|
X_MARKET_CYCLE_HIND,
|
|
_Period //
|
|
);
|
|
}
|
|
else
|
|
{
|
|
mHCPeriod = hcPeriod;
|
|
}
|
|
|
|
//
|
|
result = IsValid(mHCPeriod);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
mHCycleLength = PeriodSeconds(mHCPeriod) / cPeriodSeconds;
|
|
result = mHCycleLength > 0;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Retrieve all Exists Input Max Length ...
|
|
// use for Start Of Drawing ...
|
|
int ExtractMaxLengthOfInputs()
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
result = MathMax(mSCycleLength, mMCycleLength);
|
|
result = MathMax(result, mLCycleLength);
|
|
result = MathMax(result, mHCycleLength);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Set Indicator Short Name and also we can define Buffers Labels ...
|
|
void SetIndicatorName()
|
|
{
|
|
IndicatorSetString(INDICATOR_SHORTNAME, ShortName);
|
|
}
|
|
|
|
//
|
|
// Define Indexes and Styles ...
|
|
void DefineBuffers()
|
|
{
|
|
}
|
|
|
|
//
|
|
// Calculations ...
|
|
|
|
//
|
|
// Calculate Buffers ...
|
|
void CalculateBuffers(
|
|
int bar_index, // Selected Bar Index
|
|
const int prevCalculated,
|
|
const int ratesTotal,
|
|
const double &open[],
|
|
const double &high[],
|
|
const double &close[],
|
|
const double &low[],
|
|
const long &tickVolume[] //
|
|
)
|
|
{
|
|
//
|
|
CalculateCycles(
|
|
bar_index,
|
|
prevCalculated,
|
|
ratesTotal,
|
|
open,
|
|
high,
|
|
close,
|
|
low,
|
|
tickVolume //
|
|
);
|
|
}
|
|
|
|
//
|
|
void CalculateCycles(
|
|
int bar_index, // Selected Bar Index
|
|
const int prevCalculated,
|
|
const int ratesTotal,
|
|
const double &open[],
|
|
const double &high[],
|
|
const double &close[],
|
|
const double &low[],
|
|
const long &tickVolume[] //
|
|
)
|
|
{
|
|
//
|
|
// SHORT ...
|
|
CalculateCycle(
|
|
bar_index,
|
|
prevCalculated,
|
|
ratesTotal,
|
|
open,
|
|
high,
|
|
close,
|
|
low,
|
|
tickVolume,
|
|
//
|
|
mSCPeriod,
|
|
mSCycleLength,
|
|
mSLastCalculateTime,
|
|
mSTicks,
|
|
mSZones,
|
|
//
|
|
mSHigh,
|
|
mSHighTime,
|
|
mSHighs,
|
|
//
|
|
mSLow,
|
|
mSLowTime,
|
|
mSLows,
|
|
//
|
|
showShort,
|
|
shortColor
|
|
//
|
|
);
|
|
|
|
//
|
|
// MEDIUM ...
|
|
CalculateCycle(
|
|
bar_index,
|
|
prevCalculated,
|
|
ratesTotal,
|
|
open,
|
|
high,
|
|
close,
|
|
low,
|
|
tickVolume,
|
|
//
|
|
mMCPeriod,
|
|
mMCycleLength,
|
|
mMLastCalculateTime,
|
|
mMTicks,
|
|
mMZones,
|
|
//
|
|
mMHigh,
|
|
mMHighTime,
|
|
mMHighs,
|
|
//
|
|
mMLow,
|
|
mMLowTime,
|
|
mMLows,
|
|
//
|
|
showMedium,
|
|
mediumColor
|
|
//
|
|
);
|
|
|
|
//
|
|
// LONG ...
|
|
CalculateCycle(
|
|
bar_index,
|
|
prevCalculated,
|
|
ratesTotal,
|
|
open,
|
|
high,
|
|
close,
|
|
low,
|
|
tickVolume,
|
|
//
|
|
mLCPeriod,
|
|
mLCycleLength,
|
|
mLLastCalculateTime,
|
|
mLTicks,
|
|
mLZones,
|
|
//
|
|
mLHigh,
|
|
mLHighTime,
|
|
mLHighs,
|
|
//
|
|
mLLow,
|
|
mLLowTime,
|
|
mLLows,
|
|
//
|
|
showLong,
|
|
longColor
|
|
//
|
|
);
|
|
|
|
//
|
|
// HIND ...
|
|
CalculateCycle(
|
|
bar_index,
|
|
prevCalculated,
|
|
ratesTotal,
|
|
open,
|
|
high,
|
|
close,
|
|
low,
|
|
tickVolume,
|
|
//
|
|
mHCPeriod,
|
|
mHCycleLength,
|
|
mHLastCalculateTime,
|
|
mHTicks,
|
|
mHZones,
|
|
//
|
|
mHHigh,
|
|
mHHighTime,
|
|
mHHighs,
|
|
//
|
|
mHLow,
|
|
mHLowTime,
|
|
mHLows,
|
|
//
|
|
showHind,
|
|
hindColor
|
|
//
|
|
);
|
|
}
|
|
|
|
//
|
|
void CalculateCycle(
|
|
int bar_index, // Selected Bar Index
|
|
const int prevCalculated,
|
|
const int ratesTotal,
|
|
const double &open[],
|
|
const double &high[],
|
|
const double &close[],
|
|
const double &low[],
|
|
const long &tickVolume[],
|
|
//
|
|
ENUM_TIMEFRAMES period,
|
|
int cycleLength,
|
|
datetime &lastCalculatedTime,
|
|
MqlTick &ticks[],
|
|
CArrayObj &pZones,
|
|
//
|
|
double &pHigh,
|
|
datetime &pHighTime,
|
|
double &highs[],
|
|
//
|
|
double &pLow,
|
|
datetime &pLowTime,
|
|
double &lows[],
|
|
//
|
|
bool canDraw,
|
|
color drawColor
|
|
//
|
|
)
|
|
{
|
|
//
|
|
// Calculate Reuired Data ...
|
|
|
|
//
|
|
int maxRequiredLength = ExtractMaxLengthOfInputs();
|
|
int requiredItemsLength = (numberOfZones) * maxRequiredLength;
|
|
if (bar_index > requiredItemsLength)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
datetime bar_time = iTime(
|
|
_Symbol,
|
|
_Period,
|
|
bar_index //
|
|
);
|
|
if (IsValid(lastCalculatedTime) &&
|
|
lastCalculatedTime >= bar_time)
|
|
{
|
|
lastCalculatedTime = NULL;
|
|
return;
|
|
}
|
|
|
|
//
|
|
datetime periodStartTime = GetPeriodStartTime(
|
|
_Symbol,
|
|
period,
|
|
bar_time //
|
|
);
|
|
|
|
//
|
|
// Retrieve Ticks between Times ...
|
|
Clean(ticks);
|
|
int copedTicks = CopyTicksRange(
|
|
_Symbol,
|
|
ticks,
|
|
COPY_TICKS_ALL,
|
|
periodStartTime * 1000,
|
|
bar_time * 1000 //
|
|
);
|
|
if (copedTicks <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Retrieve Highs ...
|
|
Clean(highs);
|
|
int copiedHighs = CopyHigh(
|
|
_Symbol,
|
|
period,
|
|
periodStartTime,
|
|
bar_time,
|
|
highs //
|
|
);
|
|
if (copiedHighs <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Retrieve Highs ...
|
|
Clean(lows);
|
|
int copiedLows = CopyLow(
|
|
_Symbol,
|
|
period,
|
|
periodStartTime,
|
|
bar_time,
|
|
lows //
|
|
);
|
|
if (copiedLows <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
datetime mTimes[];
|
|
int copiedTimes = CopyTime(
|
|
_Symbol,
|
|
period,
|
|
periodStartTime,
|
|
bar_time,
|
|
mTimes //
|
|
);
|
|
if (copiedTimes <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
int highIDX = ArrayMaximum(highs);
|
|
pHigh = highs[highIDX];
|
|
|
|
//
|
|
int lowIDX = ArrayMinimum(lows);
|
|
pLow = lows[lowIDX];
|
|
|
|
//
|
|
pHighTime = mTimes[highIDX];
|
|
pLowTime = mTimes[lowIDX];
|
|
|
|
//
|
|
double rangeSize = pHigh - pLow;
|
|
|
|
//
|
|
// Create Zones ...
|
|
pZones.Clear();
|
|
for (int i = 0; i < numberOfLevels; i++)
|
|
{
|
|
//
|
|
// Instance a New Zone ...
|
|
XSCZone *iZone = new XSCZone();
|
|
iZone.end = bar_time;
|
|
iZone.period = period;
|
|
iZone.start = periodStartTime;
|
|
|
|
//
|
|
// Calculate Each Zones High / Low based on Range ...
|
|
double iH = pHigh - rangeSize * i / numberOfLevels;
|
|
double iL = pHigh - rangeSize * (i + 1) / numberOfLevels;
|
|
|
|
//
|
|
// Set Zone High Low Properties ...
|
|
iZone.low = iL;
|
|
iZone.high = iH;
|
|
|
|
//
|
|
// Add Zone to Zone Array Objects ...
|
|
pZones.Add(iZone);
|
|
}
|
|
|
|
//
|
|
// Calculate Each Zone Ticks ...
|
|
int ticksCount = ArraySize(ticks);
|
|
for (int i = 0; i < ticksCount; i++)
|
|
{
|
|
//
|
|
// Retrieve i Index Tick Object ...
|
|
MqlTick iTick = ticks[i];
|
|
|
|
//
|
|
// Loop Through Zones ...
|
|
for (int j = 0; j < pZones.Total(); j++)
|
|
{
|
|
//
|
|
// Retrieve j Index Zone Object ...
|
|
XSCZone *jZone = pZones.At(j);
|
|
|
|
//
|
|
bool isInRange = IsTickInZoneRange(
|
|
iTick,
|
|
jZone //
|
|
);
|
|
if (isInRange)
|
|
{
|
|
//
|
|
jZone.ticks++;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Calculating Zone Percents ...
|
|
for (int i = 0; i < pZones.Total(); i++)
|
|
{
|
|
//
|
|
XSCZone *iZone = pZones.At(i);
|
|
|
|
//
|
|
double percent = CalculateZoneTickPercent(ticks, iZone);
|
|
iZone.percent = percent;
|
|
}
|
|
|
|
//
|
|
pZones.Sort();
|
|
|
|
//
|
|
// Draw Cycle ...
|
|
if (canDraw)
|
|
{
|
|
DrawCycleZones(pZones, drawColor);
|
|
}
|
|
|
|
//
|
|
// Print("----------------");
|
|
// Print("BarTime: ", bar_time);
|
|
// Print("PEriodStartTime: ", periodStartTime);
|
|
// Print("Period: ", ToString(period));
|
|
// Print("Length: ", cycleLength);
|
|
|
|
//
|
|
lastCalculatedTime = bar_time;
|
|
}
|
|
|
|
//
|
|
// Draw Specific Cycles Zone ...
|
|
void DrawCycleZones(
|
|
CArrayObj &zones,
|
|
color clr //
|
|
)
|
|
{
|
|
//
|
|
int count = zones.Total();
|
|
if (!IsValidSize(count))
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Sort Zones ...
|
|
zones.Sort();
|
|
|
|
//
|
|
string tag = NULL;
|
|
int maxZoneIDX = -1;
|
|
XSCZone *maxZone = NULL;
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XSCZone *iZone = zones.At(i);
|
|
|
|
//
|
|
if (!IsValid(tag))
|
|
{
|
|
tag = iZone.GetTag();
|
|
}
|
|
|
|
//
|
|
if (maxZone == NULL || maxZone.ticks < iZone.ticks)
|
|
{
|
|
//
|
|
maxZone = iZone;
|
|
maxZoneIDX = i;
|
|
}
|
|
|
|
//
|
|
// Draw Start Vertical Line ...
|
|
string startVLName = tag + "_" + "Start";
|
|
DrawVerticalLine(
|
|
ChartID(),
|
|
startVLName,
|
|
0,
|
|
iZone.start,
|
|
clr,
|
|
STYLE_SOLID,
|
|
1 //
|
|
);
|
|
}
|
|
|
|
//
|
|
// Draw Levels Rectangle ...
|
|
string levelRectName = tag + "_" + ToString(maxZoneIDX) + "_Level";
|
|
DrawRectangle(
|
|
ChartID(),
|
|
levelRectName,
|
|
0,
|
|
maxZone.start,
|
|
maxZone.high,
|
|
maxZone.end,
|
|
maxZone.low,
|
|
clr,
|
|
STYLE_SOLID,
|
|
1 //
|
|
);
|
|
}
|
|
|
|
//
|
|
// 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;
|
|
}
|
|
|
|
//
|
|
double CalculateZoneTickPercent(
|
|
MqlTick &ticks[],
|
|
XSCZone *zone,
|
|
int normalizationDigits = 2 //
|
|
)
|
|
{
|
|
//
|
|
double result = 0;
|
|
|
|
//
|
|
if (normalizationDigits < 2 || normalizationDigits > 5)
|
|
{
|
|
normalizationDigits = 2;
|
|
}
|
|
|
|
//
|
|
int ticksCount = ArraySize(ticks);
|
|
if (ticksCount <= 0)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = (double)zone.ticks / ticksCount * 100;
|
|
result = NormalizeDouble(result, normalizationDigits);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
// |