149 行
11 KiB
MQL5
149 行
11 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| EhlersHurstCoefficient.mq5 |
|
|
//| Copyright 2020, Andrei Novichkov. |
|
|
//| Main Site: http://fxstill.com |
|
|
//| Telegram: https://t.me/fxstill (Literature on cryptocurrencies,|
|
|
//| development and code. ) |
|
|
//+------------------------------------------------------------------+
|
|
#property copyright "Copyright 2020, Andrei Novichkov."
|
|
#property link "http://fxstill.com"
|
|
#property version "1.00"
|
|
#property description "Telegram Channel: https://t.me/fxstill\n"
|
|
#property description "The Hurst Coefficient:\nJohn Ehlers, \"Cycle Analytics For Traders\", pg.67-68"
|
|
|
|
#property indicator_separate_window
|
|
|
|
#property indicator_applied_price PRICE_CLOSE
|
|
|
|
#property indicator_buffers 4
|
|
#property indicator_plots 1
|
|
|
|
#property indicator_type1 DRAW_COLOR_LINE
|
|
#property indicator_width1 2
|
|
#property indicator_style1 STYLE_SOLID
|
|
#property indicator_color1 clrGreen, clrRed, clrLimeGreen
|
|
|
|
input int length = 30; //Length
|
|
input int ssflength = 20; //SuperSmoother filter Length
|
|
|
|
double a, b, c1, c2, c3;
|
|
int hl;
|
|
double smoothHurst[], hurst[], cf[], dimen[];
|
|
|
|
static const int MINBAR = length;
|
|
|
|
int OnInit() {
|
|
|
|
SetIndexBuffer (0, smoothHurst, INDICATOR_DATA);
|
|
SetIndexBuffer (1, cf, INDICATOR_COLOR_INDEX);
|
|
SetIndexBuffer (2, hurst, INDICATOR_CALCULATIONS);
|
|
SetIndexBuffer (3, dimen, INDICATOR_CALCULATIONS);
|
|
ArraySetAsSeries ( smoothHurst, true);
|
|
ArraySetAsSeries ( cf, true);
|
|
ArraySetAsSeries ( hurst, true);
|
|
ArraySetAsSeries ( dimen, true);
|
|
|
|
|
|
IndicatorSetString (INDICATOR_SHORTNAME,"EhlersHurstCoefficient");
|
|
IndicatorSetInteger(INDICATOR_DIGITS,_Digits);
|
|
|
|
a = MathExp(-M_SQRT2 * M_PI / ssflength);
|
|
b = 2 * a * MathCos(M_SQRT2 * M_PI / ssflength);
|
|
c2 = b;
|
|
c3 = -MathPow(a, 2);
|
|
c1 = 1 - c2 - c3;
|
|
hl = (int)MathCeil(length / 2);
|
|
|
|
return INIT__SUCCEEDED();
|
|
}
|
|
|
|
void GetValue(const double& price[], int shift) {
|
|
|
|
int ih = iHighest(NULL, 0, MODE_CLOSE, length, shift);
|
|
int il = iLowest (NULL, 0, MODE_CLOSE, length, shift);
|
|
if (ih == -1 || il == -1) return;
|
|
|
|
double n3 = (price[ih] - price[il]) / length;
|
|
double hh = price[shift];
|
|
double ll = price[shift];
|
|
|
|
for (int i = shift; i < shift + hl; i++) {
|
|
if (price[i] > hh) hh = price[i];
|
|
if (price[i] < ll) ll = price[i];
|
|
}
|
|
|
|
double n1 = (hh - ll) / hl;
|
|
|
|
hh = price[shift + hl];
|
|
ll = price[shift + hl];
|
|
|
|
for (int i = shift + hl; i < shift + length; i++) {
|
|
if (price[i] > hh) hh = price[i];
|
|
if (price[i] < ll) ll = price[i];
|
|
}
|
|
|
|
double n2 = (hh - ll) / hl;
|
|
|
|
dimen[shift] = (n1 > 0 && n2 > 0 && n3 > 0) ?
|
|
0.5 * ( (log(n1 + n2) - log(n3)) / log(2) + dimen[shift + 1]) : 0;
|
|
|
|
hurst[shift] = 2 - dimen[shift];
|
|
|
|
double s1 = ZerroIfEmpty(smoothHurst[shift + 1]);// == EMPTY_VALUE)? 0: smoothHurst[shift + 1];
|
|
double s2 = ZerroIfEmpty(smoothHurst[shift + 2]);// == EMPTY_VALUE)? 0: smoothHurst[shift + 2];
|
|
|
|
smoothHurst[shift] = c1 * (hurst[shift] + hurst[shift + 1]) / 2 + c2 * s1 + c3 * s2;
|
|
|
|
if (smoothHurst[shift] < 0.5) cf[shift] = 1 ;
|
|
else
|
|
if (smoothHurst[shift] > 0.5) cf[shift] = 2 ;
|
|
}//void GetValue(const double& price[], int shift)
|
|
int INIT__SUCCEEDED() {
|
|
PlaySound("ok.wav");
|
|
string cm = "Subscribe! https://t.me/fxstill";
|
|
Print(cm);
|
|
Comment("\n"+cm);
|
|
return INIT_SUCCEEDED;
|
|
}
|
|
double ZerroIfEmpty(double value) {
|
|
if (value >= EMPTY_VALUE || value <= -EMPTY_VALUE) return 0.0;
|
|
return value;
|
|
}
|
|
void OnDeinit(const int reason) {
|
|
Comment("");
|
|
}
|
|
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[]) {
|
|
if(rates_total <= MINBAR) return 0;
|
|
ArraySetAsSeries(close,true);
|
|
ArraySetAsSeries(high, true);
|
|
ArraySetAsSeries(low, true);
|
|
int limit = rates_total - prev_calculated;
|
|
if (limit == 0) { // Пришел новый тик
|
|
} else if (limit == 1) { // Образовался новый бар
|
|
GetValue(close, 1);
|
|
return(rates_total);
|
|
} else if (limit > 1) { // Первый вызов индикатора, смена таймфрейма, подгрузка данных из истории
|
|
ArrayInitialize(smoothHurst, EMPTY_VALUE);
|
|
ArrayInitialize(cf, 0);
|
|
ArrayInitialize(hurst, 0);
|
|
ArrayInitialize(dimen, 0);
|
|
limit = rates_total - MINBAR;
|
|
for(int i = limit; i >= 1 && !IsStopped(); i--){
|
|
GetValue(close, i);
|
|
}//for(int i = limit + 1; i >= 0 && !IsStopped(); i--)
|
|
return(rates_total);
|
|
}
|
|
GetValue(close, 0);
|
|
|
|
return(rates_total);
|
|
}
|
|
//+------------------------------------------------------------------+
|