358 lines
16 KiB
MQL5
358 lines
16 KiB
MQL5
|
//+------------------------------------------------------------------+
|
||
|
//| ProbableTarget.mq5 |
|
||
|
//| Copyright 2021, MetaQuotes Ltd. |
|
||
|
//| https://www.mql5.com |
|
||
|
//+------------------------------------------------------------------+
|
||
|
#property copyright "Copyright 2021, MetaQuotes Ltd."
|
||
|
#property link "https://www.mql5.com"
|
||
|
#property version "1.00"
|
||
|
#property indicator_separate_window
|
||
|
//#property indicator_minimum 1
|
||
|
//#property indicator_maximum 10
|
||
|
#property indicator_buffers 10
|
||
|
#property indicator_plots 8
|
||
|
|
||
|
//--- plot targetProfit
|
||
|
#property indicator_label1 "Target profit(%)"
|
||
|
#property indicator_type1 DRAW_LINE
|
||
|
#property indicator_color1 clrGreen
|
||
|
#property indicator_style1 STYLE_SOLID
|
||
|
#property indicator_width1 2
|
||
|
//--- plot stopLoss
|
||
|
#property indicator_label2 "Stop loss(%)"
|
||
|
#property indicator_type2 DRAW_LINE
|
||
|
#property indicator_color2 clrRed
|
||
|
#property indicator_style2 STYLE_SOLID
|
||
|
#property indicator_width2 2
|
||
|
//--- plot maxAbsoluteReached
|
||
|
#property indicator_label3 "Max absolute(%)"
|
||
|
#property indicator_type3 DRAW_LINE
|
||
|
#property indicator_color3 clrBrown
|
||
|
#property indicator_style3 STYLE_SOLID
|
||
|
#property indicator_width3 1
|
||
|
//--- plot smaMaxAbsoluteReached
|
||
|
#property indicator_label4 "Sma max absolute(%)"
|
||
|
#property indicator_type4 DRAW_LINE
|
||
|
#property indicator_color4 clrBrown
|
||
|
#property indicator_style4 STYLE_SOLID
|
||
|
#property indicator_width4 1
|
||
|
//--- plot maxReachedInBothDirection
|
||
|
#property indicator_label5 "Max Reached in both direc(%)"
|
||
|
#property indicator_type5 DRAW_LINE
|
||
|
#property indicator_color5 clrDodgerBlue
|
||
|
#property indicator_style5 STYLE_SOLID
|
||
|
#property indicator_width5 1
|
||
|
//--- plot smaMaxReachedInBothDirection
|
||
|
#property indicator_label6 "Sma max Reached in both direc(%)"
|
||
|
#property indicator_type6 DRAW_LINE
|
||
|
#property indicator_color6 clrDodgerBlue
|
||
|
#property indicator_style6 STYLE_SOLID
|
||
|
#property indicator_width6 1
|
||
|
//--- plot maxReachedInBothDirectionFuzzyMode
|
||
|
#property indicator_label7 "Mode max reached in both direct(%)"
|
||
|
#property indicator_type7 DRAW_LINE
|
||
|
#property indicator_color7 clrDodgerBlue
|
||
|
#property indicator_style7 STYLE_SOLID
|
||
|
#property indicator_width7 1
|
||
|
//--- plot signDiffInPercent
|
||
|
#property indicator_label8 "Load balance from extreme by bar(%)"
|
||
|
#property indicator_type8 DRAW_LINE
|
||
|
#property indicator_color8 clrChocolate
|
||
|
#property indicator_style8 STYLE_SOLID
|
||
|
#property indicator_width8 1
|
||
|
|
||
|
//--- plot maxByBarInPercent
|
||
|
#property indicator_label9 "Max extreme by bar(%)"
|
||
|
#property indicator_type9 DRAW_LINE
|
||
|
#property indicator_color9 clrYellow
|
||
|
#property indicator_style9 STYLE_SOLID
|
||
|
#property indicator_width9 1
|
||
|
//--- plot minByBarInPercent
|
||
|
#property indicator_label10 "Min extreme by bar(%)"
|
||
|
#property indicator_type10 DRAW_LINE
|
||
|
#property indicator_color10 clrYellow
|
||
|
#property indicator_style10 STYLE_SOLID
|
||
|
#property indicator_width10 1
|
||
|
|
||
|
#include <MovingAverages.mqh>
|
||
|
|
||
|
//inputs
|
||
|
input double fuzzyFactor = 0.10;
|
||
|
input int reachedPeriodLength = 24;
|
||
|
input int maxPeriodLength = 24;
|
||
|
|
||
|
//--- indicator buffers
|
||
|
double maxAbsoluteReachedBuffer[];
|
||
|
double smaMaxAbsoluteReachedBuffer[];
|
||
|
double maxReachedInBothDirectionBuffer[];
|
||
|
double smaMaxReachedInBothDirectionBuffer[];
|
||
|
double maxReachedInBothDirectionFuzzyModeBuffer[];
|
||
|
double signDiffInPercentBuffer[];
|
||
|
double targetProfitBuffer[];
|
||
|
double stopLossBuffer[];
|
||
|
double maxByBarInPercentBuffer[];
|
||
|
double minByBarInPercentBuffer[];
|
||
|
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| Custom indicator initialization function |
|
||
|
//+------------------------------------------------------------------+
|
||
|
int OnInit() {
|
||
|
//chart settings
|
||
|
ChartSetInteger(0,CHART_COLOR_BACKGROUND,0);
|
||
|
ChartSetInteger(0, CHART_FOREGROUND,16777215);
|
||
|
ChartSetInteger(0,CHART_COLOR_CHART_UP,7451452);
|
||
|
ChartSetInteger(0,CHART_COLOR_CHART_DOWN,255);
|
||
|
ChartSetInteger(0,CHART_COLOR_CANDLE_BULL,7451452);
|
||
|
ChartSetInteger(0,CHART_COLOR_CANDLE_BEAR,255);
|
||
|
ChartSetInteger(0,CHART_COLOR_CHART_LINE,65280);
|
||
|
ChartSetInteger(0,CHART_COLOR_GRID,2697513);
|
||
|
ChartSetInteger(0,CHART_SHIFT,1);
|
||
|
ChartSetInteger(0,CHART_SHOW_ASK_LINE,1);
|
||
|
ChartSetInteger(0,CHART_SHOW_BID_LINE,1);
|
||
|
ChartSetInteger(0,CHART_SHOW_LAST_LINE,1);
|
||
|
ChartSetInteger(0,CHART_SHOW_PERIOD_SEP,1);
|
||
|
|
||
|
//--- indicator buffers mapping
|
||
|
SetIndexBuffer(0,targetProfitBuffer,INDICATOR_DATA);
|
||
|
SetIndexBuffer(1,stopLossBuffer,INDICATOR_DATA);
|
||
|
SetIndexBuffer(2,maxAbsoluteReachedBuffer,INDICATOR_DATA);
|
||
|
SetIndexBuffer(3,smaMaxAbsoluteReachedBuffer,INDICATOR_DATA);
|
||
|
SetIndexBuffer(4,maxReachedInBothDirectionBuffer,INDICATOR_DATA);
|
||
|
SetIndexBuffer(5,smaMaxReachedInBothDirectionBuffer,INDICATOR_DATA);
|
||
|
SetIndexBuffer(6,maxReachedInBothDirectionFuzzyModeBuffer,INDICATOR_DATA);
|
||
|
SetIndexBuffer(7,signDiffInPercentBuffer,INDICATOR_DATA);
|
||
|
SetIndexBuffer(8,maxByBarInPercentBuffer,INDICATOR_DATA);
|
||
|
SetIndexBuffer(9,minByBarInPercentBuffer,INDICATOR_DATA);
|
||
|
|
||
|
// as series
|
||
|
ArraySetAsSeries(maxAbsoluteReachedBuffer,true);
|
||
|
ArraySetAsSeries(smaMaxAbsoluteReachedBuffer,true);
|
||
|
ArraySetAsSeries(maxReachedInBothDirectionBuffer,true);
|
||
|
ArraySetAsSeries(smaMaxReachedInBothDirectionBuffer,true);
|
||
|
ArraySetAsSeries(maxReachedInBothDirectionFuzzyModeBuffer,true);
|
||
|
ArraySetAsSeries(signDiffInPercentBuffer,true);
|
||
|
ArraySetAsSeries(targetProfitBuffer,true);
|
||
|
ArraySetAsSeries(stopLossBuffer,true);
|
||
|
ArraySetAsSeries(maxByBarInPercentBuffer,true);
|
||
|
ArraySetAsSeries(minByBarInPercentBuffer,true);
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| |
|
||
|
//+------------------------------------------------------------------+
|
||
|
return(INIT_SUCCEEDED);
|
||
|
}
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| Custom indicator iteration function |
|
||
|
//+------------------------------------------------------------------+
|
||
|
int OnCalculate(const int rates_total,
|
||
|
const int prev_calculated,
|
||
|
const datetime &time[],
|
||
|
const double &open[],
|
||
|
const double &high[],
|
||
|
const double &low[],
|
||
|
const double &close[],
|
||
|
const long &tick_volume[],
|
||
|
const long &volume[],
|
||
|
const int &spread[]) {
|
||
|
//--- convert to series
|
||
|
ArraySetAsSeries(open,true);
|
||
|
ArraySetAsSeries(close,true);
|
||
|
ArraySetAsSeries(high,true);
|
||
|
ArraySetAsSeries(low,true);
|
||
|
|
||
|
if(rates_total<reachedPeriodLength || rates_total<maxPeriodLength)
|
||
|
return(0);
|
||
|
//--- calc
|
||
|
int maxLength = MathMax(reachedPeriodLength, maxPeriodLength);
|
||
|
int forLength = rates_total - maxLength;
|
||
|
|
||
|
for(int i=0; i<forLength && !IsStopped(); i++) {
|
||
|
ReachedInfo reachedInfo = getReachedInfo(i, open, high, low);
|
||
|
maxAbsoluteReachedBuffer[i] = reachedInfo.getMaxAbsoluteReached();
|
||
|
maxReachedInBothDirectionBuffer[i] = MathMin(reachedInfo.getMaxAboveReached(), reachedInfo.getMaxBelowReached());
|
||
|
signDiffInPercentBuffer[i] = reachedInfo.getSignDiffInPercent();
|
||
|
|
||
|
maxByBarInPercentBuffer[i] = MathMax(absDiffInPercent(open[i], low[i]), absDiffInPercent(open[i], high[i]));
|
||
|
minByBarInPercentBuffer[i] = MathMin(absDiffInPercent(open[i], low[i]), absDiffInPercent(open[i], high[i]));
|
||
|
if(i >= maxLength) {
|
||
|
int shift = i - maxLength;
|
||
|
|
||
|
double smaMaxAbsoluteReachedSumatory = 0;
|
||
|
double smaMaxReachedInBothDirectionSumatory = 0;
|
||
|
int occurrences [];
|
||
|
ArrayResize(occurrences,reachedPeriodLength);
|
||
|
ArrayFill(occurrences,0,reachedPeriodLength,0);
|
||
|
double fuzzyValue [];
|
||
|
ArrayResize(fuzzyValue,reachedPeriodLength);
|
||
|
ArrayFill(fuzzyValue,0,reachedPeriodLength,-1);
|
||
|
|
||
|
for(int j = shift; j< shift + maxLength && !IsStopped(); j++) {
|
||
|
if(j < shift + maxPeriodLength) {
|
||
|
smaMaxAbsoluteReachedSumatory += maxAbsoluteReachedBuffer[j];
|
||
|
}
|
||
|
if(j < shift + reachedPeriodLength) {
|
||
|
smaMaxReachedInBothDirectionSumatory += maxReachedInBothDirectionBuffer[j];
|
||
|
fuzzyValue[j - shift] = getRangeFuzzy(maxReachedInBothDirectionBuffer[j]);
|
||
|
occurrences[j - shift] = countOccurrences(fuzzyValue, fuzzyValue[j - shift]);
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
smaMaxAbsoluteReachedBuffer[shift] = smaMaxAbsoluteReachedSumatory / maxPeriodLength ;
|
||
|
smaMaxReachedInBothDirectionBuffer[shift] = smaMaxReachedInBothDirectionSumatory / reachedPeriodLength ;
|
||
|
int maxIndex = ArrayMaximum(occurrences, 0, WHOLE_ARRAY);
|
||
|
|
||
|
maxReachedInBothDirectionFuzzyModeBuffer[shift] = maxIndex != -1 ? fuzzyValue[maxIndex] : -1;
|
||
|
targetProfitBuffer[shift] = getTargetInPercent(shift);
|
||
|
stopLossBuffer[shift] = getStopLossPercent(shift);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//--- return value of prev_calculated for next call
|
||
|
return(rates_total);
|
||
|
}
|
||
|
//+------------------------------------------------------------------+
|
||
|
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| |
|
||
|
//+------------------------------------------------------------------+
|
||
|
double absDiffInPercent(const double initExtreme, const double endExtreme) {
|
||
|
return MathAbs(((endExtreme - initExtreme) * 100) / initExtreme);
|
||
|
}
|
||
|
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| |
|
||
|
//+------------------------------------------------------------------+
|
||
|
double getTargetInPercent(int index) {
|
||
|
if(maxReachedInBothDirectionFuzzyModeBuffer[index] > maxReachedInBothDirectionBuffer[index] && smaMaxReachedInBothDirectionBuffer[index] > maxReachedInBothDirectionBuffer[index])
|
||
|
return maxReachedInBothDirectionFuzzyModeBuffer[index];
|
||
|
double minTmp = MathMin(smaMaxReachedInBothDirectionBuffer[index], maxReachedInBothDirectionFuzzyModeBuffer[index]);
|
||
|
double min = MathMin(minTmp, maxReachedInBothDirectionBuffer[index]);
|
||
|
double smaFactor = smaMaxReachedInBothDirectionBuffer[index] != 0 ? MathAbs(1- (maxReachedInBothDirectionBuffer[index] / smaMaxReachedInBothDirectionBuffer[index])) <= 0.25 : false;
|
||
|
double modeFactor = maxReachedInBothDirectionFuzzyModeBuffer[index] != 0 ? MathAbs(1- (maxReachedInBothDirectionBuffer[index] / maxReachedInBothDirectionFuzzyModeBuffer[index])) <= 0.25 : false;
|
||
|
double target = (smaFactor || modeFactor) ? maxReachedInBothDirectionBuffer[index] : min;
|
||
|
return target;
|
||
|
}
|
||
|
|
||
|
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| |
|
||
|
//+------------------------------------------------------------------+
|
||
|
double getStopLossPercent(int index) {
|
||
|
double stopLoss = MathMax(maxAbsoluteReachedBuffer[index], smaMaxAbsoluteReachedBuffer[index]);
|
||
|
return stopLoss;
|
||
|
}
|
||
|
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| |
|
||
|
//+------------------------------------------------------------------+
|
||
|
class ReachedInfo {
|
||
|
double maxAbsoluteReached;
|
||
|
double maxAboveReached;
|
||
|
double maxBelowReached;
|
||
|
double signDiffInPercent;
|
||
|
|
||
|
public:
|
||
|
ReachedInfo(double maxAbsoluteReachedParam, double maxAboveReachedParam, double maxBelowReachedParam, double signDiffInPercentParam) {
|
||
|
maxAbsoluteReached = maxAbsoluteReachedParam;
|
||
|
maxAboveReached = maxAboveReachedParam;
|
||
|
maxBelowReached = maxBelowReachedParam;
|
||
|
signDiffInPercent = signDiffInPercentParam;
|
||
|
};
|
||
|
ReachedInfo(ReachedInfo &reachedInfo) {
|
||
|
maxAbsoluteReached = reachedInfo.getMaxAbsoluteReached();
|
||
|
maxAboveReached = reachedInfo.getMaxAboveReached();
|
||
|
maxBelowReached = reachedInfo.getMaxBelowReached();
|
||
|
signDiffInPercent = reachedInfo.getSignDiffInPercent();
|
||
|
};
|
||
|
void setMaxAbsoluteReached(double maxAbsoluteReachedParam) {
|
||
|
maxAbsoluteReached = maxAbsoluteReachedParam;
|
||
|
}
|
||
|
void setMaxAboveReached(double maxAboveReachedParam) {
|
||
|
maxAboveReached = maxAboveReachedParam;
|
||
|
}
|
||
|
void setMaxBelowReached(double maxBelowReachedParam) {
|
||
|
maxBelowReached = maxBelowReachedParam;
|
||
|
}
|
||
|
void setSignDiffInPercent(double signDiffInPercentParam) {
|
||
|
signDiffInPercent = signDiffInPercentParam;
|
||
|
}
|
||
|
|
||
|
double getMaxAbsoluteReached() {
|
||
|
return maxAbsoluteReached;
|
||
|
}
|
||
|
double getMaxAboveReached() {
|
||
|
return maxAboveReached;
|
||
|
}
|
||
|
double getMaxBelowReached() {
|
||
|
return maxBelowReached;
|
||
|
}
|
||
|
double getSignDiffInPercent() {
|
||
|
return signDiffInPercent;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| |
|
||
|
//+------------------------------------------------------------------+
|
||
|
ReachedInfo getReachedInfo(int index, const double &open[], const double &high[], const double &low[]) {
|
||
|
double init = open[index];
|
||
|
double lowInit = low[index];
|
||
|
double highInit = high[index];
|
||
|
double maxAbsoluteReached = MathMax(absDiffInPercent(init, highInit), absDiffInPercent(init, lowInit));
|
||
|
double maxAboveReached = absDiffInPercent(init, highInit);
|
||
|
double maxBelowReached = absDiffInPercent(init, lowInit);
|
||
|
double signDiffInPercent = absDiffInPercent(init, highInit) - absDiffInPercent(init, lowInit);
|
||
|
|
||
|
int forLength = MathMax(reachedPeriodLength, maxPeriodLength);
|
||
|
|
||
|
for(int i=index + 1; i<index + forLength; i++) {
|
||
|
double absDiffInPercentTmp;
|
||
|
if(high[i] > init) {
|
||
|
absDiffInPercentTmp = absDiffInPercent(init, high[i]);
|
||
|
signDiffInPercent = signDiffInPercent + absDiffInPercentTmp;
|
||
|
if(absDiffInPercentTmp > maxAboveReached && i < reachedPeriodLength + index)
|
||
|
maxAboveReached = absDiffInPercentTmp;
|
||
|
if(absDiffInPercentTmp > maxAbsoluteReached && i < maxPeriodLength + index)
|
||
|
maxAbsoluteReached = absDiffInPercentTmp;
|
||
|
}
|
||
|
|
||
|
if(low[i] < init) {
|
||
|
absDiffInPercentTmp = absDiffInPercent(init, low[i]);
|
||
|
signDiffInPercent = signDiffInPercent - absDiffInPercentTmp;
|
||
|
if(absDiffInPercentTmp > maxBelowReached && i < reachedPeriodLength + index)
|
||
|
maxBelowReached = absDiffInPercentTmp;
|
||
|
if(absDiffInPercentTmp > maxAbsoluteReached && i < maxPeriodLength + index)
|
||
|
maxAbsoluteReached = absDiffInPercentTmp;
|
||
|
}
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
ReachedInfo reachedInfo(maxAbsoluteReached, maxAboveReached, maxBelowReached, signDiffInPercent);
|
||
|
return reachedInfo;
|
||
|
}
|
||
|
|
||
|
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| |
|
||
|
//+------------------------------------------------------------------+
|
||
|
double getRangeFuzzy(double value) {
|
||
|
int tmp = MathRound(value / fuzzyFactor);
|
||
|
return tmp > 0 ? tmp * fuzzyFactor : fuzzyFactor;
|
||
|
}
|
||
|
//+------------------------------------------------------------------+
|
||
|
|
||
|
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| |
|
||
|
//+------------------------------------------------------------------+
|
||
|
int countOccurrences(const double &array[], const double condition) {
|
||
|
int cnt=0;
|
||
|
for(int i=0; i<reachedPeriodLength; i++) {
|
||
|
if(condition == array[i])
|
||
|
cnt+=1;
|
||
|
}
|
||
|
return cnt;
|
||
|
}
|
||
|
//+------------------------------------------------------------------+
|