Divergence Panel
Похожие материалы по тегам
Сообщите нам, если считаете, что материал размещён без разрешения.
Сообщить о материале
Обращение по товару «divergencepanel.mq5» отправится на рассмотрение. Укажите контакт для ответа и опишите причину.
О программе
DivergencePanel — пользовательский индикатор для MetaTrader 5, отображающий панель дивергенций по нескольким таймфреймам. Панель строится в окне графика и содержит по одной строке на каждый таймфрейм (M1, M5, M15, M30, H1, H4, D1, W1, MN1) и шесть столбцов: пять закрытых бар и текущий бар. В каждой ячейке отображаются квадраты, соответствующие включённым осцилляторам: зелёный цвет означает бычью дивергенцию, красный — медвежью, пустой цвет — отсутствие сигнала.
Индикатор рассчитывает набор технических осцилляторов (MACD, гистограмма MACD, RSI, Stochastic, CCI, Momentum, OBV, VWMACD, CMF, MFI) на каждом из девяти таймфреймов. Для каждого осциллятора выполняется поиск дивергенций относительно пивотов, определяемых по ценам закрытия или по теням свечей. Поддерживаются регулярные и скрытые дивергенции. Отображение сигналов следует правилу замены: более новый сигнал того же направления заменяет предыдущий, если между ними не сформировался новый пивот соответствующей стороны.
Панель обновляется по таймеру и при пересчёте индикатора. Текущий бар отображается как предварительный и не изменяет закрытые столбцы при включённом подтверждении. Настройки позволяют управлять параметрами поиска пивотов, типами дивергенций, набором осцилляторов, а также внешним видом панели (размеры, цвета, шрифт).
Настройки программы
| Настройка | Описание |
|---|---|
| SepPivots | Разделитель группы настроек поиска пивотов и дивергенций. |
| InpSpan | Количество бар слева и справа от бара, необходимое для подтверждения пивота. |
| InpSource | Источник для определения пивотов: цены закрытия или тени свечей. |
| InpKinds | Тип отображаемых дивергенций: регулярные, скрытые или оба типа. |
| InpMinCount | Минимальное количество дивергенций на баре, необходимое для отображения сигнала. |
| InpMaxPivots | Максимальное количество пивотов, проверяемых в обратном направлении при поиске дивергенций. |
| InpMaxReach | Максимальное количество бар, проверяемых в обратном направлении при поиске дивергенций. |
| InpConfirm | Если включено, сигнал на закрытом баре подтверждается только после закрытия следующего бара; текущий бар не влияет на закрытые столбцы. |
| InpLastOnly | Если включено, сохраняется только последняя дивергенция каждого направления, как на графическом индикаторе. |
| InpBars | Количество бар, загружаемых для каждого таймфрейма при расчёте. |
| SepOsc | Разделитель группы настроек выбора осцилляторов. |
| InpUseMacd | Включает использование осциллятора MACD при поиске дивергенций. |
| InpUseHist | Включает использование гистограммы MACD при поиске дивергенций. |
| InpUseRsi | Включает использование осциллятора RSI при поиске дивергенций. |
| InpUseStoch | Включает использование осциллятора Stochastic при поиске дивергенций. |
| InpUseCci | Включает использование осциллятора CCI при поиске дивергенций. |
| InpUseMom | Включает использование осциллятора Momentum при поиске дивергенций. |
| InpUseObv | Включает использование осциллятора OBV при поиске дивергенций. |
| InpUseVwmacd | Включает использование осциллятора VWMACD при поиске дивергенций. |
| InpUseCmf | Включает использование осциллятора CMF при поиске дивергенций. |
| InpUseMfi | Включает использование осциллятора MFI при поиске дивергенций. |
| SepPanel | Разделитель группы настроек внешнего вида панели. |
| InpX | Горизонтальное смещение панели от левого верхнего угла графика. |
| InpY | Вертикальное смещение панели от левого верхнего угла графика. |
| InpSquare | Размер стороны квадрата в пикселях. |
| InpGap | Расстояние между квадратами внутри ячейки. |
| InpFontSize | Размер шрифта текстовых элементов панели. |
| InpEmptySlots | Если включено, пустые квадраты отображаются на панели; иначе они скрыты. |
| InpShowBg | Если включено, отображается фон панели с рамкой и чередующимися полосами. |
| InpBullColor | Цвет квадратов, обозначающих бычью дивергенцию. |
| InpBearColor | Цвет квадратов, обозначающих медвежью дивергенцию. |
| InpEmptyColor | Цвет пустых квадратов, не содержащих сигнала. |
| InpBgColor | Цвет фона панели. |
| InpBorderColor | Цвет рамки и разделительных линий панели. |
| InpStripeColor | Цвет чередующихся полос фона строк панели. |
| InpTitleColor | Цвет заголовка панели. |
| InpTextColor | Цвет основного текста панели, например названий таймфреймов и заголовков столбцов. |
| InpAccentColor | Цвет акцентных элементов панели, например заголовка текущего бара и выделения текущего таймфрейма. |
Поиск по коду файла
#property version "1.20"
#property description "Divergence Panel - same engine and display rules as MultiIndicatorDivergence"
#property strict
#property indicator_chart_window
enum ENUM_PIVOT_SOURCE { PIVOT_CLOSE, PIVOT_WICKS };
enum ENUM_DIV_KINDS { KINDS_REGULAR, KINDS_HIDDEN, KINDS_BOTH };
input string SepPivots = "------------";
input int InpSpan = 5; // pivot period, bars on each side
input ENUM_PIVOT_SOURCE InpSource = PIVOT_CLOSE; // pivot source
input ENUM_DIV_KINDS InpKinds = KINDS_REGULAR; // divergence type
input int InpMinCount = 1; // minimum divergences on a bar
input int InpMaxPivots = 10; // pivots checked back
input int InpMaxReach = 100; // bars checked back
input bool InpConfirm = true; // wait for the next bar to confirm
input bool InpLastOnly = false; // keep only the latest divergence (same as the chart indicator)
input int InpBars = 1200; // bars loaded per timeframe
input string SepOsc = "------------";
input bool InpUseMacd = true;
input bool InpUseHist = true;
input bool InpUseRsi = true;
input bool InpUseStoch = true;
input bool InpUseCci = true;
input bool InpUseMom = true;
input bool InpUseObv = true;
input bool InpUseVwmacd = true;
input bool InpUseCmf = true;
input bool InpUseMfi = true;
input string SepPanel = "------------";
input int InpX = 8;
input int InpY = 18;
input int InpSquare = 7;
input int InpGap = 2;
input int InpFontSize = 8;
input bool InpEmptySlots = true;
input bool InpShowBg = true;
input color InpBullColor = C'0,214,143';
input color InpBearColor = C'255,82,82';
input color InpEmptyColor = C'52,56,66';
input color InpBgColor = C'22,25,31';
input color InpBorderColor= C'62,67,80';
input color InpStripeColor= C'30,34,42';
input color InpTitleColor = C'235,238,245';
input color InpTextColor = C'150,157,172';
input color InpAccentColor= C'255,196,61';
#define OSCILLATORS 10
#define KINDS 4
#define PIVOT_SLOTS 20
#define MIN_REACH 5
#define NO_VALUE DBL_MAX
#define WARMUP 400
#define BULL_REGULAR 0
#define BEAR_REGULAR 1
#define BULL_HIDDEN 2
#define BEAR_HIDDEN 3
#define TFS 9
#define SLOTS 10
#define COLS 6
#define PAD 8
#define COL_GAP 12
#define TAG "DP_"
int g_tfs[TFS] = {PERIOD_M1,PERIOD_M5,PERIOD_M15,PERIOD_M30,PERIOD_H1,PERIOD_H4,PERIOD_D1,PERIOD_W1,PERIOD_MN1};
string g_tfNames[TFS] = {"M1","M5","M15","M30","H1","H4","D1","W1","MN1"};
struct ScanRules {
int span;
bool wicks;
bool regular;
bool hidden;
int maxPivots;
int maxReach;
bool liveBar;
bool lastOnly;
int minCount;
bool enabled[OSCILLATORS];
};
struct PivotStack {
int bar[PIVOT_SLOTS];
double level[PIVOT_SLOTS];
int count;
};
struct Pivots {
PivotStack highs;
PivotStack lows;
};
double g_emaFast[], g_emaSlow[], g_macd[], g_signal[], g_hist[];
double g_gain[], g_loss[], g_rsi[], g_rawK[], g_stoch[];
double g_cci[], g_mom[], g_obv[], g_vwmacd[], g_cmf[], g_mfi[];
double g_high[], g_low[], g_close[];
long g_vol[];
ScanRules g_rules;
int g_state[TFS][COLS][SLOTS];
bool g_pending = false;
double MeanAt(const double &v[], const int i, const int n, const int first) {
if(i-n+1 < first) return(NO_VALUE);
double sum = 0;
for(int k = i-n+1; k <= i; k++) {
if(v[k] == NO_VALUE) return(NO_VALUE);
sum += v[k];
}
return(sum / n);
}
double EmaAt(const double &src[], const double &dst[], const int i, const int n, const int first) {
if(src[i] == NO_VALUE) return(NO_VALUE);
if(i > first && dst[i-1] != NO_VALUE) {
double alpha = 2.0 / (n + 1);
return(alpha * src[i] + (1 - alpha) * dst[i-1]);
}
return(MeanAt(src, i, n, first));
}
void MacdAt(const double &close[], double &fast[], double &slow[], double &line[],
double &signal[], double &hist[], const int i, const int first) {
fast[i] = EmaAt(close, fast, i, 12, first);
slow[i] = EmaAt(close, slow, i, 26, first);
line[i] = (fast[i] == NO_VALUE || slow[i] == NO_VALUE) ? NO_VALUE : fast[i] - slow[i];
signal[i] = EmaAt(line, signal, i, 9, first);
hist[i] = (signal[i] == NO_VALUE) ? NO_VALUE : line[i] - signal[i];
}
void RsiAt(const double &close[], double &gain[], double &loss[], double &rsi[],
const int i, const int first) {
const int n = 14;
gain[i] = NO_VALUE;
loss[i] = NO_VALUE;
rsi[i] = NO_VALUE;
if(i-1 < first) return;
double up = MathMax(close[i] - close[i-1], 0.0);
double down = MathMax(close[i-1] - close[i], 0.0);
if(gain[i-1] != NO_VALUE) {
gain[i] = (up + (n-1)*gain[i-1]) / n;
loss[i] = (down + (n-1)*loss[i-1]) / n;
} else {
if(i-n < first) return;
double sumUp = 0, sumDown = 0;
for(int k = i-n+1; k <= i; k++) {
sumUp += MathMax(close[k] - close[k-1], 0.0);
sumDown += MathMax(close[k-1] - close[k], 0.0);
}
gain[i] = sumUp / n;
loss[i] = sumDown / n;
}
if(loss[i] == 0) rsi[i] = (gain[i] > 0) ? 100 : NO_VALUE;
else rsi[i] = 100 - 100 / (1 + gain[i]/loss[i]);
}
void StochAt(const double &high[], const double &low[], const double &close[], double &raw[],
double &smooth[], const int i, const int first) {
raw[i] = NO_VALUE;
if(i-13 >= first) {
double top = high[i], bottom = low[i];
for(int k = i-13; k < i; k++) {
top = MathMax(top, high[k]);
bottom = MathMin(bottom, low[k]);
}
if(top > bottom) raw[i] = 100 * (close[i] - bottom) / (top - bottom);
}
smooth[i] = MeanAt(raw, i, 3, first);
}
double CciAt(const double &close[], const int i, const int first) {
double mean = MeanAt(close, i, 10, first);
if(mean == NO_VALUE) return(NO_VALUE);
double dev = 0;
for(int k = i-9; k <= i; k++) dev += MathAbs(close[k] - mean);
dev /= 10;
return(dev > 0 ? (close[i] - mean) / (0.015 * dev) : NO_VALUE);
}
double MomentumAt(const double &close[], const int i, const int first) {
return(i-10 >= first ? close[i] - close[i-10] : NO_VALUE);
}
double ObvAt(const double &close[], const long &volume[], const double &obv[], const int i, const int first) {
if(i <= first || obv[i-1] == NO_VALUE) return(0);
double move = close[i] - close[i-1];
double sign = (move > 0) ? 1 : (move < 0 ? -1 : 0);
return(obv[i-1] + sign * (double)volume[i]);
}
double VwmaAt(const double &close[], const long &volume[], const int i, const int n, const int first) {
if(i-n+1 < first) return(NO_VALUE);
double weighted = 0, total = 0;
for(int k = i-n+1; k <= i; k++) {
weighted += close[k] * (double)volume[k];
total += (double)volume[k];
}
return(total > 0 ? weighted / total : NO_VALUE);
}
double VwmacdAt(const double &close[], const long &volume[], const int i, const int first) {
double fast = VwmaAt(close, volume, i, 12, first);
double slow = VwmaAt(close, volume, i, 26, first);
return((fast == NO_VALUE || slow == NO_VALUE) ? NO_VALUE : fast - slow);
}
double CmfAt(const double &high[], const double &low[], const double &close[], const long &volume[], const int i, const int first) {
const int n = 21;
if(i-n+1 < first) return(NO_VALUE);
double flow = 0, total = 0;
for(int k = i-n+1; k <= i; k++) {
double range = high[k] - low[k];
if(range <= 0) return(NO_VALUE);
flow += ((close[k] - low[k]) - (high[k] - close[k])) / range * (double)volume[k];
total += (double)volume[k];
}
return(total > 0 ? flow / total : NO_VALUE);
}
double MfiAt(const double &close[], const long &volume[], const int i, const int first) {
const int n = 14;
if(i-n < first) return(NO_VALUE);
double rising = 0, falling = 0;
for(int k = i-n+1; k <= i; k++) {
double move = close[k] - close[k-1];
if(move > 0) rising += (double)volume[k] * close[k];
if(move < 0) falling += (double)volume[k] * close[k];
}
if(falling == 0) return(rising > 0 ? 100 : NO_VALUE);
return(100 - 100 / (1 + rising / falling));
}
bool Beyond(const double b, const double a, const int dir) {
if(b == NO_VALUE || a == NO_VALUE) return(false);
return(dir > 0 ? b > a : b < a);
}
bool IsTurn(const double &v[], const int c, const int span, const int dir) {
for(int k = 1; k <= span; k++) {
if(dir * (v[c] - v[c-k]) <= 0) return(false);
if(dir * (v[c] - v[c+k]) < 0) return(false);
}
return(true);
}
void PushPivot(PivotStack &stack, const int bar, const double level) {
for(int k = MathMin(stack.count, PIVOT_SLOTS-1); k > 0; k--) {
stack.bar[k] = stack.bar[k-1];
stack.level[k] = stack.level[k-1];
}
stack.bar[0] = bar;
stack.level[0] = level;
stack.count = MathMin(stack.count + 1, PIVOT_SLOTS);
}
void TrackPivots(Pivots &pv, const int bar, bool &newTop, bool &newBottom) {
newTop = false;
newBottom = false;
int c = bar - g_rules.span;
if(c - g_rules.span < 0) return;
newTop = g_rules.wicks ? IsTurn(g_high, c, g_rules.span, 1) : IsTurn(g_close, c, g_rules.span, 1);
newBottom = g_rules.wicks ? IsTurn(g_low, c, g_rules.span, -1) : IsTurn(g_close, c, g_rules.span, -1);
if(newTop) PushPivot(pv.highs, c, g_rules.wicks ? g_high[c] : g_close[c]);
if(newBottom) PushPivot(pv.lows, c, g_rules.wicks ? g_low[c] : g_close[c]);
}
bool ClearPath(const double &osc[], const double &close[], const int bar, const int from, const int reach, const int dir) {
double stepOsc = (osc[bar-from] - osc[bar-reach]) / (reach - from);
double stepPx = (close[bar-from] - close[bar-reach]) / (reach - from);
double lineOsc = osc[bar-from] - stepOsc;
double linePx = close[bar-from] - stepPx;
for(int k = from + 1; k < reach; k++) {
if(Beyond(lineOsc, osc[bar-k], dir) || Beyond(linePx, close[bar-k], dir)) return(false);
lineOsc -= stepOsc;
linePx -= stepPx;
}
return(true);
}
int SeekPivot(const double &osc[], const double &close[], const double &probe[],
const int bar, const PivotStack &stack, const int dir, const bool hidden) {
if(!g_rules.liveBar && !Beyond(osc[bar], osc[bar-1], dir) && !Beyond(close[bar], close[bar-1], dir))
return(0);
int from = g_rules.liveBar ? 0 : 1;
int end = bar - from;
int depth = MathMin(g_rules.maxPivots, stack.count);
for(int n = 0; n < depth; n++) {
int reach = bar - stack.bar[n];
if(reach > g_rules.maxReach) break;
if(reach <= MIN_REACH) continue;
int pivot = stack.bar[n];
bool shape;
if(hidden)
shape = Beyond(osc[pivot], osc[end], dir) && Beyond(probe[end], stack.level[n], dir);
else
shape = Beyond(osc[end], osc[pivot], dir) && Beyond(stack.level[n], probe[end], dir);
if(shape && ClearPath(osc, close, bar, from, reach, dir))
return(reach);
}
return(0);
}
void ScanOsc(const double &osc[], const int bar, const Pivots &pv, int &found[]) {
ArrayInitialize(found, 0);
if(g_rules.wicks) {
if(g_rules.regular) {
found[BULL_REGULAR] = SeekPivot(osc, g_close, g_low, bar, pv.lows, 1, false);
found[BEAR_REGULAR] = SeekPivot(osc, g_close, g_high, bar, pv.highs, -1, false);
}
if(g_rules.hidden) {
found[BULL_HIDDEN] = SeekPivot(osc, g_close, g_low, bar, pv.lows, 1, true);
found[BEAR_HIDDEN] = SeekPivot(osc, g_close, g_high, bar, pv.highs, -1, true);
}
} else {
if(g_rules.regular) {
found[BULL_REGULAR] = SeekPivot(osc, g_close, g_close, bar, pv.lows, 1, false);
found[BEAR_REGULAR] = SeekPivot(osc, g_close, g_close, bar, pv.highs, -1, false);
}
if(g_rules.hidden) {
found[BULL_HIDDEN] = SeekPivot(osc, g_close, g_close, bar, pv.lows, 1, true);
found[BEAR_HIDDEN] = SeekPivot(osc, Показано первые 50% кода (символов: 18494)
Открыть по тарифу
Купите тариф с пакетом открытий или войдите, если тариф уже есть. Открытый файл останется в вашем кабинете навсегда.
Разовая покупка файла
На этой странице откроется полный исходный код файла вместо ознакомительного фрагмента.
Зачем нужен email? После подтверждения оплаты файл сохранится в кабинете на этот email. Если аккаунта ещё нет, мы создадим его и пришлём ссылку для задания пароля. Если аккаунт уже есть, покупка добавится в него. Укажите адрес, к которому у вас есть доступ.
Чтобы оформить заказ, введите email и перейдите к оплате.