AntRobot/indicators/ProbableTarget.mq5

358 lines
16 KiB
MQL5
Raw Permalink Normal View History

2025-05-30 14:40:14 +02:00
//+------------------------------------------------------------------+
//| 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;
}
//+------------------------------------------------------------------+