SRL/SandR2.mq5

343 lines
12 KiB
MQL5
Raw Permalink Normal View History

2025-05-30 16:25:54 +02:00
//+------------------------------------------------------------------+
//| SandR.mq5 |
//| BP |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "BP"
#property link "https://www.mql5.com"
#property version "1.00"
#property indicator_chart_window
#property indicator_buffers 10
#property indicator_plots 10
//--- plot R1
#property indicator_label1 "R1"
#property indicator_type1 DRAW_ARROW
#property indicator_color1 clrBeige
#property indicator_style1 STYLE_SOLID
#property indicator_width1 2
//--- plot S1
#property indicator_label2 "S1"
#property indicator_type2 DRAW_ARROW
#property indicator_color2 clrPowderBlue
#property indicator_style2 STYLE_SOLID
#property indicator_width2 2
//--- plot R2
#property indicator_label3 "R2"
#property indicator_type3 DRAW_ARROW
#property indicator_color3 clrBeige
#property indicator_style3 STYLE_SOLID
#property indicator_width3 1
//--- plot S2
#property indicator_label4 "S2"
#property indicator_type4 DRAW_ARROW
#property indicator_color4 clrPowderBlue
#property indicator_style4 STYLE_SOLID
#property indicator_width4 1
//--- plot R3
#property indicator_label5 "R3"
#property indicator_type5 DRAW_ARROW
#property indicator_color5 clrBeige
#property indicator_style5 STYLE_SOLID
#property indicator_width5 1
//--- plot S3
#property indicator_label6 "S3"
#property indicator_type6 DRAW_ARROW
#property indicator_color6 clrPowderBlue
#property indicator_style6 STYLE_SOLID
#property indicator_width6 1
//--- plot R4
#property indicator_label7 "R4"
#property indicator_type7 DRAW_ARROW
#property indicator_color7 clrBeige
#property indicator_style7 STYLE_SOLID
#property indicator_width7 1
//--- plot S4
#property indicator_label8 "S4"
#property indicator_type8 DRAW_ARROW
#property indicator_color8 clrPowderBlue
#property indicator_style8 STYLE_SOLID
#property indicator_width8 1
//--- plot R5
#property indicator_label9 "R5"
#property indicator_type9 DRAW_ARROW
#property indicator_color9 clrBeige
#property indicator_style9 STYLE_SOLID
#property indicator_width9 1
//--- plot S5
#property indicator_label10 "S5"
#property indicator_type10 DRAW_ARROW
#property indicator_color10 clrPowderBlue
#property indicator_style10 STYLE_SOLID
#property indicator_width10 1
//--- input parameters
input int SRnumber=2; //Number of line (max 5)
input int BarNumber=50; //Number of bars to analyse high and low
input int HistBarNumber=200; //Number of bars to create the score
input double Tolerence=30; //Tolerence in detection of cluster
input int ScoreMinMax = 2; //Bonus for high or low
input int ScoreReverse = 100; //Bonus for reversal bars
input int CrossingPenalty = -100; //Penalty for crossing
input int ScoreLimit = -10000;
//--- indicator buffers
double R1Buffer[];
double R2Buffer[];
double R3Buffer[];
double R4Buffer[];
double R5Buffer[];
double S1Buffer[];
double S2Buffer[];
double S3Buffer[];
double S4Buffer[];
double S5Buffer[];
//-- global variables
double lastOpen;
int sr_number;
double tol;
int maxInd = BarNumber-1;
struct simpleSR{
int score;
double value;
};
struct SR{
bool state;
int rScore;
int histBar_rScore[];
int sScore;
int histBar_sScore[];
double rValue;
double sValue;
};
SR srs[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//--- indicator buffers mapping
SetIndexBuffer(0,R1Buffer,INDICATOR_DATA);
SetIndexBuffer(1,S1Buffer,INDICATOR_DATA);
SetIndexBuffer(2,R2Buffer,INDICATOR_DATA);
SetIndexBuffer(3,S2Buffer,INDICATOR_DATA);
SetIndexBuffer(4,R3Buffer,INDICATOR_DATA);
SetIndexBuffer(5,S3Buffer,INDICATOR_DATA);
SetIndexBuffer(6,R4Buffer,INDICATOR_DATA);
SetIndexBuffer(7,S4Buffer,INDICATOR_DATA);
SetIndexBuffer(8,R5Buffer,INDICATOR_DATA);
SetIndexBuffer(9,S5Buffer,INDICATOR_DATA);
lastOpen = 0;
if(SRnumber>5){
sr_number = 5;
}
else{
sr_number = SRnumber;
}
ArrayResize(srs,BarNumber);
for(int i=0; i<BarNumber; i++){
srs[i].state = false;
srs[i].rScore = 0;
srs[i].rValue = 0;
ArrayResize(srs[i].histBar_rScore,HistBarNumber);
ArrayFill(srs[i].histBar_rScore,0,HistBarNumber,0);
srs[i].sScore = 0;
srs[i].sValue = 0;
ArrayResize(srs[i].histBar_sScore,HistBarNumber);
ArrayFill(srs[i].histBar_sScore,0,HistBarNumber,0);
}
//---
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[])
{
//---
//--- check for rates count
if(rates_total<HistBarNumber){
return(0);
}
int pos;
//PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,rates_total-DrawBar);
pos=prev_calculated-1;
/*if(pos < rates_total - DrawBar){
pos = rates_total - DrawBar;
}*/
if(pos < HistBarNumber){
pos = HistBarNumber+1;
}
for(int t=pos; t < rates_total; t++){
//skip calculation if tick is in the same bar
if(lastOpen == open[t]){
continue;
}
int lastHistBar = t-HistBarNumber;
int firstHistBar = t-1;
//set the tolerence
double max = high[t-BarNumber];
double min = low[t-BarNumber];
for(int i=t-BarNumber; i> t; i++){
if(high[i]>max){
max = high[i];
}
if(low[i]<min){
min = low[i];
}
}
tol = (max-min)/Tolerence;
//slide the array forward
ArrayRemove(srs,0,1);
ArrayResize(srs,BarNumber);
srs[maxInd].state = false;
srs[maxInd].rScore = 0;
srs[maxInd].rValue = 0;
ArrayResize(srs[maxInd].histBar_rScore,HistBarNumber);
ArrayFill(srs[maxInd].histBar_rScore,0,HistBarNumber,0);
srs[maxInd].sScore = 0;
srs[maxInd].sValue = 0;
ArrayResize(srs[maxInd].histBar_sScore,HistBarNumber);
ArrayFill(srs[maxInd].histBar_sScore,0,HistBarNumber,0);
for(int b=0; b<BarNumber; b++){
//slide hist arrays forward
ArrayRemove(srs[b].histBar_rScore,0,1);
ArrayRemove(srs[b].histBar_sScore,0,1);
ArrayResize(srs[b].histBar_rScore,HistBarNumber);
ArrayResize(srs[b].histBar_sScore,HistBarNumber);
srs[b].histBar_rScore[HistBarNumber-1] = 0;
srs[b].histBar_sScore[HistBarNumber-1] = 0;
//update score or create score
int start = lastHistBar;
if(srs[b].state == true) start = firstHistBar;
int i = t-(BarNumber-b);
srs[b].rValue = high[i];
srs[b].sValue = low[i];
for(int j= start; j < t; j++){
int hb = HistBarNumber - (t-j);
if(i!=j){
//test high of bar[i] against all other high
if(high[j]<high[i]+tol && high[j]>high[i]-tol){
srs[b].histBar_rScore[hb] += ScoreMinMax;
if(high[j]>srs[b].rValue) srs[b].rValue = high[j];
}
//test high of bar[i] against close of bar that are going up and followed by a bar going down
if(open[j-1]<close[j-1] && open[j]>close[j] && open[j]<high[i]+tol && open[j]>high[i]-tol){
srs[b].histBar_rScore[hb] += ScoreReverse;
if(open[j]>srs[b].rValue) srs[b].rValue = open[j];
}
//test low of bar[i] against all other low
if(low[j]<low[i]+tol && low[j]>low[i]-tol){
srs[b].histBar_sScore[hb] += ScoreMinMax;
if(low[j]<srs[b].sValue) srs[b].sValue = low[j];
}
//test low of bar[i] against close of bar that are going down and followed by a bar going up
if(open[j-1]>close[j-start] && open[j]<close[j] && open[j]<low[i]+tol && open[j]>low[i]-tol){
srs[b].histBar_sScore[hb] += ScoreReverse;
if(open[j]<srs[b].sValue) srs[b].sValue = open[j];
}
}
}
//decrease the score if resistance or support had been crossed
for(int j= start; j < t; j++){
int hb = HistBarNumber - (t-j);
if(srs[b].rValue>open[j] && srs[b].rValue<close[j]) srs[b].histBar_rScore[hb] += CrossingPenalty;
if(srs[b].sValue<open[j] && srs[b].sValue>close[j]) srs[b].histBar_sScore[hb] += CrossingPenalty;
}
//calculate final scores of the bar
for(int j=0; j<HistBarNumber; j++){
srs[b].rScore += srs[b].histBar_rScore[j];
srs[b].sScore += srs[b].histBar_sScore[j];
}
}
//create clusters
simpleSR S[];
simpleSR R[];
ArrayResize(S,BarNumber);
ArrayResize(R,BarNumber);
for(int b=0; b<BarNumber; b++){
S[b].score = srs[b].sScore;
S[b].value = srs[b].sValue;
R[b].score = srs[b].rScore;
R[b].value = srs[b].rValue;
for(int j=0; j<BarNumber; j++){
if(b!=j){
if(srs[b].sValue > srs[j].sValue-tol && srs[b].sValue < srs[j].sValue+tol){
S[b].score += srs[j].sScore;
if(srs[j].sValue < S[b].value) S[b].value = srs[j].sValue;
}
if(srs[b].rValue > srs[j].rValue-tol && srs[b].rValue < srs[j].rValue+tol){
R[b].score += srs[j].rScore;
if(srs[j].rValue > R[b].value) R[b].value = srs[j].rValue;
}
}
}
}
//select indexes of the 5 highest scores
uint iS[5];
uint iR[5];
ArrayFill(iS,0,5,0);
ArrayFill(iR,0,5,0);
for(int i=0; i<5; i++){
int j=i-1;
for(int b=0; b<BarNumber; b++){
if(j<0){
if(S[b].score > S[iS[i]].score || (S[b].score == S[iS[i]].score && S[b].value < S[iS[i]].value)) iS[i] = b;
if(R[b].score > R[iR[i]].score || (R[b].score == R[iR[i]].score && R[b].value > R[iR[i]].value)) iR[i] = b;
}
else{
if((S[b].score > S[iS[i]].score || (S[b].score == S[iS[i]].score && S[b].value < S[iS[i]].value)) && S[b].score < S[iS[j]].score) iS[i] = b;
if((R[b].score > R[iR[i]].score || (R[b].score == R[iR[i]].score && R[b].value > R[iR[i]].value)) && R[b].score < R[iR[j]].score) iR[i] = b;
}
}
}
//
for(int i=0; i<5; i++){
if(S[iS[i]].score < ScoreLimit || i >= sr_number) S[iS[i]].value = 0;
if(R[iR[i]].score < ScoreLimit || i >= sr_number) R[iR[i]].value = 0;
}
//transfer values to the buffers
S1Buffer[t] = S[iS[0]].value;
S2Buffer[t] = S[iS[1]].value;
S3Buffer[t] = S[iS[2]].value;
S4Buffer[t] = S[iS[3]].value;
S5Buffer[t] = S[iS[4]].value;
R1Buffer[t] = R[iR[0]].value;
R2Buffer[t] = R[iR[1]].value;
R3Buffer[t] = R[iR[2]].value;
R4Buffer[t] = R[iR[3]].value;
R5Buffer[t] = R[iR[4]].value;
lastOpen = open[t];
}
//--- return value of prev_calculated for next call
return(rates_total);
}
//+------------------------------------------------------------------+