SHK Pro Heikin Ashi Signals
Сообщите нам, если считаете, что материал размещён без разрешения.
Сообщить о материале
Обращение по товару «shk professional heikin ashi 1.00.mq5» отправится на рассмотрение. Укажите контакт для ответа и опишите причину.
О программе
SHK Pro Heikin Ashi Signals — индикатор для MetaTrader 5, реализующий аналитическую систему на основе свечей Хайкин Аши. Он рассчитывает значения HA Open, HA High, HA Low и HA Close, отображая их на графике с помощью графических объектов с цветовой индикацией направления тренда.
Индикатор поддерживает три режима цветового кодирования: стандартный, основанный на тренде и основанный на моментуме. Визуализация включает сигнальные круги моментов и подтверждённые стрелки BUY/SELL, которые формируются при совпадении изменения цвета HA-свечей с дивергенцией MACD.
Система сигналов предусматривает несколько уровней подтверждения: количество подтверждающих свечей, проверку по закрытию и фильтрацию по силе тел свечей. Настраиваемые уведомления включают всплывающие окна, push-уведомления, электронную почту и звуковые сигналы с возможностью задания периода охлаждения.
Режим работы с закрытыми свечами обеспечивает отсутствие перерисовки, а параметр MaxBarsToCalculate ограничивает объём обрабатываемой истории для оптимизации производительности.
Настройки программы
| Настройка | Описание |
|---|---|
| MaxBarsToCalculate | Максимальное количество баров для расчёта индикатора. |
| ShowHeikinAshiCandles | Включает отображение HA-свечей на графике. |
| ShowOriginalCandlesFaint | Отображает исходные свечи графика приглушённым цветом на фоне HA-свечей. |
| EnableSignals | Включает или отключает генерацию торговых сигналов. |
| UseClosedBarsOnly | Использует только закрытые свечи для расчёта сигналов, исключая перерисовку на формирующемся баре. |
| CandleMode | Режим цветового кодирования HA-свечей: стандартный, основанный на тренде или на моментуме. |
| BullColor | Цвет для отрисовки бычьих HA-свечей. |
| BearColor | Цвет для отрисовки медвежьих HA-свечей. |
| StrongBullColor | Цвет для отрисовки сильных бычьих HA-свечей. |
| StrongBearColor | Цвет для отрисовки сильных медвежьих HA-свечей. |
| NeutralColor | Цвет для отрисовки нейтральных HA-свечей (уравновешенных). |
| ConfirmationCandles | Количество свечей, необходимых для подтверждения изменения цвета HA. |
| SignalLookbackBars | Количество баров назад от текущего бара для сканирования сигналов при полном пересчёте. |
| MinBodyPercent | Минимальный процент тела свечи относительно диапазона для формирования сигналов. |
| SignalOnHAColorChange | При активации сигналы формируются при подтверждённом изменении цвета HA-свечей. |
| RequireMACDDivergenceConfirmation | Требует наличия дивергенции MACD для формирования подтверждённых стрелок. |
| MACDFastEMA | Период быстрой скользящей средней для расчёта MACD. |
| MACDSlowEMA | Период медленной скользящей средней для расчёта MACD. |
| MACDSignalEMA | Период сигнальной линии MACD. |
| DivergencePivotLookback | Количество баров для поиска пивотов при определении дивергенции MACD. |
| DivergenceSearchBars | Количество баров назад для поиска предыдущего пивота при определении дивергенции MACD. |
| DivergenceConfirmWindow | Количество баров назад, в пределах которых ищется подтверждённая дивергенция MACD. |
| RequireStrongCandleForCircle | Требует повышенной силы свечи (короткая тень или большой объём тела) для формирования круга момента. |
| CancelSignalOnOppositeHA | Отменяет ожидающий сигнал при появлении свечи противоположного направления HA. |
| ConfirmByCloseBreak | При подтверждении сигнала проверяет пробой уровня закрытием свечи, а не максимумом/минимумом. |
| ArrowOffsetATR | Смещение стрелок BUY/SELL от уровня свечи в единицах ATR. |
| CircleOffsetATR | Смещение сигнальных кругов моментов от уровня свечи в единицах ATR. |
| VisualATRPeriod | Период расчёта ATR для визуального смещения стрелок и кругов. |
| EnablePopupAlert | Включает всплывающие оповещения на графике. |
| EnablePushAlert | Включает push-уведомления на мобильное устройство. |
| EnableEmailAlert | Включает отправку оповещений по электронной почте. |
| EnableSoundAlert | Включает звуковые оповещения при появлении сигналов. |
| BuySoundFile | Путь к звуковому файлу для оповещения о покупке. |
| SellSoundFile | Путь к звуковому файлу для оповещения о продаже. |
| AlertCooldownSeconds | Период охлаждения между последовательными оповещениями одного направления в секундах. |
| AlertOnlyRealtime | Ограничивает отправку оповещений только для закрытых свечей в реальном времени. |
Поиск по коду файла
#property version "1.12"
#property description "Professional Heikin Ashi candle engine with HA color change plus MACD divergence confirmed BUY/SELL arrows. Closed bar, EA integration friendly."
#property strict
#property indicator_chart_window
#property indicator_buffers 10
#property indicator_color1 clrNONE
#property indicator_color2 clrNONE
#property indicator_color3 clrNONE
#property indicator_color4 clrNONE
#property indicator_color5 clrNONE
enum CandleColorMode
{
COLOR_STANDARD = 0,
COLOR_TREND_BASED = 1,
COLOR_MOMENTUM_BASED = 2
};
input int MaxBarsToCalculate = 3000;
input bool ShowHeikinAshiCandles = true;
input bool ShowOriginalCandlesFaint = false;
input bool EnableSignals = true;
input bool UseClosedBarsOnly = true;
input CandleColorMode CandleMode = COLOR_STANDARD;
input color BullColor = clrLime;
input color BearColor = clrRed;
input color StrongBullColor = clrDodgerBlue;
input color StrongBearColor = clrOrange;
input color NeutralColor = clrGray;
input int ConfirmationCandles = 1;
input int SignalLookbackBars = 1000;
input double MinBodyPercent = 0.0;
input bool SignalOnHAColorChange = true;
input bool RequireMACDDivergenceConfirmation = true;
input int MACDFastEMA = 12;
input int MACDSlowEMA = 26;
input int MACDSignalEMA = 5;
input int DivergencePivotLookback = 2;
input int DivergenceSearchBars = 200;
input int DivergenceConfirmWindow = 30;
input bool RequireStrongCandleForCircle = false;
input bool CancelSignalOnOppositeHA = true;
input bool ConfirmByCloseBreak = true;
input double ArrowOffsetATR = 0.25;
input double CircleOffsetATR = 0.15;
input int VisualATRPeriod = 14;
input bool EnablePopupAlert = true;
input bool EnablePushAlert = false;
input bool EnableEmailAlert = false;
input bool EnableSoundAlert = false;
input string BuySoundFile = "alert.wav";
input string SellSoundFile = "alert2.wav";
input int AlertCooldownSeconds = 120;
input bool AlertOnlyRealtime = true;
double HAOpen[];
double HAHigh[];
double HALow[];
double HAClose[];
double HAColor[];
double BuyCircle[];
double SellCircle[];
double BuyArrow[];
double SellArrow[];
double ATRBuf[];
double MacdFastBuf[];
double MacdSlowBuf[];
double MacdSignalBuf[];
double MacdHistBuf[];
bool BullDivConfirmed[];
bool BearDivConfirmed[];
double TRBuf[];
double TRPrefix[];
double HABodyBuf[];
double HABodyPrefix[];
#define COL_BULL 0
#define COL_BEAR 1
#define COL_STRONG_BULL 2
#define COL_STRONG_BEAR 3
#define COL_NEUTRAL 4
#define MOM_BODY_WINDOW 14
#define STRONG_WICK_FRAC 0.10
#define CIRCLE_WICK_FRAC 0.15
#define ARROW_BUY_CODE 233
#define ARROW_SELL_CODE 234
#define CIRCLE_CODE 108
int g_firstBar = 1;
int g_confCandles = 3;
bool g_buyPending = false;
double g_buyRefHigh = 0.0;
int g_buyBarsLeft = 0;
bool g_sellPending = false;
double g_sellRefLow = 0.0;
int g_sellBarsLeft = 0;
datetime g_lastClosedTime = 0;
datetime g_lastAlertTime = 0;
int g_lastAlertDir = 0;
datetime g_lastAlertWall = 0;
int g_macdCalcStart = 0;
int g_prevFirstBar = -1;
int g_draw_first = -1;
int g_draw_last = -1;
bool IsBullishHA(const int i)
{
return(HAClose[i] > HAOpen[i]);
}
bool IsBearishHA(const int i)
{
return(HAClose[i] < HAOpen[i]);
}
double GetBodyPercent(const int i)
{
double range = HAHigh[i] - HALow[i];
if(range <= 0.0)
return(0.0);
return(MathAbs(HAClose[i] - HAOpen[i]) / range * 100.0);
}
void ComputeHABodyCache(const int i)
{
double body = MathAbs(HAClose[i] - HAOpen[i]);
HABodyBuf[i] = body;
if(i == g_firstBar)
HABodyPrefix[i] = body;
else
HABodyPrefix[i] =
HABodyPrefix[i - 1] + body;
}
double AvgHABody(const int i,
const int win,
const int firstBar)
{
int w = win;
if(w < 1) w = 1;
int st = i - w;
if(st < firstBar)
return(0.0);
double sum = HABodyPrefix[i - 1];
if(st > firstBar)
sum -= HABodyPrefix[st - 1];
return(sum / w);
}
int GetCandleColorIndex(const int i)
{
double range = HAHigh[i] - HALow[i];
bool bull = IsBullishHA(i);
bool bear = IsBearishHA(i);
if(!bull && !bear)
return(COL_NEUTRAL);
if(CandleMode == COLOR_STANDARD)
return(bull ? COL_BULL : COL_BEAR);
if(CandleMode == COLOR_TREND_BASED)
{
if(range <= 0.0)
return(bull ? COL_BULL : COL_BEAR);
double lowerWick =
MathMin(HAOpen[i], HAClose[i]) - HALow[i];
double upperWick =
HAHigh[i] - MathMax(HAOpen[i], HAClose[i]);
if(bull)
{
return(lowerWick <= STRONG_WICK_FRAC * range
? COL_STRONG_BULL
: COL_BULL);
}
return(upperWick <= STRONG_WICK_FRAC * range
? COL_STRONG_BEAR
: COL_BEAR);
}
double body = MathAbs(HAClose[i] - HAOpen[i]);
double avgBody =
AvgHABody(i, MOM_BODY_WINDOW, g_firstBar);
if(avgBody > 0.0 && body >= 1.2 * avgBody)
return(bull ? COL_STRONG_BULL : COL_STRONG_BEAR);
return(bull ? COL_BULL : COL_BEAR);
}
void ComputeHABar(const int i,
const double &open[],
const double &high[],
const double &low[],
const double &close[])
{
double haClose =
(open[i] + high[i] + low[i] + close[i]) / 4.0;
double haOpen =
(HAOpen[i - 1] + HAClose[i - 1]) / 2.0;
double haHigh =
MathMax(high[i], MathMax(haOpen, haClose));
double haLow =
MathMin(low[i], MathMin(haOpen, haClose));
HAOpen[i] = haOpen;
HAClose[i] = haClose;
HAHigh[i] = haHigh;
HALow[i] = haLow;
}
void InitHASeed(const int firstBar,
const double &open[],
const double &high[],
const double &low[],
const double &close[])
{
double haClose =
(open[firstBar] +
high[firstBar] +
low[firstBar] +
close[firstBar]) / 4.0;
double haOpen =
(open[firstBar] + close[firstBar]) / 2.0;
HAClose[firstBar] = haClose;
HAOpen[firstBar] = haOpen;
HAHigh[firstBar] =
MathMax(high[firstBar],
MathMax(haOpen, haClose));
HALow[firstBar] =
MathMin(low[firstBar],
MathMin(haOpen, haClose));
}
void ComputeTR(const int i,
const double &high[],
const double &low[],
const double &close[],
const int firstBar)
{
double tr = high[i] - low[i];
if(i > firstBar)
{
double a = MathAbs(high[i] - close[i - 1]);
double b = MathAbs(low[i] - close[i - 1]);
if(a > tr) tr = a;
if(b > tr) tr = b;
}
TRBuf[i] = tr;
if(i == firstBar)
TRPrefix[i] = tr;
else
TRPrefix[i] = TRPrefix[i - 1] + tr;
}
double GetVisualATR(const int i,
const double &high[],
const double &low[],
const double &close[],
const int firstBar)
{
int p = VisualATRPeriod;
if(p < 1)
p = 1;
int st = i - p + 1;
if(st < firstBar)
st = firstBar;
ComputeTR(i, high, low, close, firstBar);
double sum = TRPrefix[i];
if(st > firstBar)
sum -= TRPrefix[st - 1];
int count = i - st + 1;
double atr =
count > 0
? sum / count
: TRBuf[i];
ATRBuf[i] = atr;
return(atr);
}
bool IsMacdPeak(const int i,
const int lookback,
const int firstBar,
const int lastBar)
{
if(i - lookback < firstBar ||
i + lookback > lastBar)
return(false);
for(int k = 1; k <= lookback; k++)
{
if(MacdHistBuf[i] <= MacdHistBuf[i - k] ||
MacdHistBuf[i] <= MacdHistBuf[i + k])
return(false);
}
return(true);
}
bool IsMacdTrough(const int i,
const int lookback,
const int firstBar,
const int lastBar)
{
if(i - lookback < firstBar ||
i + lookback > lastBar)
return(false);
for(int k = 1; k <= lookback; k++)
{
if(MacdHistBuf[i] >= MacdHistBuf[i - k] ||
MacdHistBuf[i] >= MacdHistBuf[i + k])
return(false);
}
return(true);
}
void ComputeMACDDivergence(const int rates_total,
const int firstBar,
const int lastClosed,
const double &high[],
const double &low[],
const double &close[])
{
if(ArraySize(MacdFastBuf) < rates_total)
{
ArrayResize(MacdFastBuf, rates_total);
ArrayResize(MacdSlowBuf, rates_total);
ArrayResize(MacdSignalBuf, rates_total);
ArrayResize(MacdHistBuf, rates_total);
ArrayResize(BullDivConfirmed, rates_total);
ArrayResize(BearDivConfirmed, rates_total);
ArrayInitialize(MacdFastBuf, 0.0);
ArrayInitialize(MacdSlowBuf, 0.0);
ArrayInitialize(MacdSignalBuf, 0.0);
ArrayInitialize(MacdHistBuf, 0.0);
ArrayInitialize(BullDivConfirmed, false);
ArrayInitialize(BearDivConfirmed, false);
g_macdCalcStart = firstBar;
}
if(!RequireMACDDivergenceConfirmation)
return;
int fast = MACDFastEMA;
int slow = MACDSlowEMA;
int signal = MACDSignalEMA;
int pivotLookback = DivergencePivotLookback;
int searchBars = DivergenceSearchBars;
if(fast < 1) fast = 1;
if(slow < 1) slow = 1;
if(signal < 1) signal = 1;
if(pivotLookback < 1) pivotLookback = 1;
if(searchBars < 1) searchBars = 1;
if(lastClosed < firstBar + pivotLookback * 2 + 2)
return;
double fastAlpha = 2.0 / ((double)fast + 1.0);
double slowAlpha = 2.0 / ((double)slow + 1.0);
double signalAlpha = 2.0 / ((double)signal + 1.0);
int macdStart = (g_macdCalcStart < firstBar) ? firstBar : g_macdCalcStart;
if(macdStart > lastClosed) macdStart = lastClosed;
if(macdStart == firstBar)
{
ArrayInitialize(BullDivConfirmed, false);
ArrayInitialize(BearDivConfirmed, false);
}
for(int i = macdStart; i <= lastClosed; i++)
{
double price = close[i];
if(i == firstBar)
{
MacdFastBuf[i] = price;
MacdSlowBuf[i] = price;
MacdSignalBuf[i] = 0.0;
MacdHistBuf[i] = 0.0;
continue;
}
MacdFastBuf[i] =
fastAlpha * price +
(1.0 - fastAlpha) * MacdFastBuf[i - 1];
MacdSlowBuf[i] =
slowAlpha * price +
(1.0 - slowAlpha) * MacdSlowBuf[i - 1];
double macdMain =
MacdFastBuf[i] - MacdSlowBuf[i];
MacdSignalBuf[i] =
signalAlpha * macdMain +
(1.0 - signalAlpha) * MacdSignalBuf[i - 1];
MacdHistBuf[i] =
macdMain - MacdSignalBuf[i];
}
g_macdCalcStart = lastClosed + 1;
int lastPivot = lastClosed - pivotLookback;
int pivotCheckStart = (macdStart - pivotLookback < firstBar + pivotLookback) ? firstBar + pivotLookback : macdStart - pivotLookback;
for(int i = pivotCheckStart; i <= lastPivot; i++)
{
int confirmationBar = i + pivotLookback;
if(confirmationBar < rates_total)
{
BullDivConfirmed[confirmationBar] = false;
BearDivConfirmed[confirmationBar] = false;
}
if(IsMacdTrough(i, pivotLookback, firstBar, lastClosed))
{
int prevTrough = -1;
int oldest = i - searchBars;
if(oldest < firstBar + pivotLookback) oldest = firstBar + pivotLookback;
for(int j = i - 1; j >= oldest; j--)
{
if(IsMacdTrough(j, pivotLookback, firstBar, lastClosed))
{
prevTrough = j;
break;
}
}
if(prevTrough >= 0 &&
low[i] < low[prevTrough] &&
MacdHistBuf[i] > MacdHistBuf[prevTrough])
{
if(confirmationBar < rates_total)
BullDivConfirmed[confirmationBar] = true;
}
}
if(IsMacdPeak(i, pivotLookback, firstBar, lastClosed))
{
int prevPeak = -1;
int oldest = i - searchBars;
if(oldest < firstBar + pivotLookback) oldest = firstBar + pivotLookback;
for(int j = i - 1; j >= oldest; j--)
{
if(IsMacdPeak(j, pivotLookback, firstBar, lastClosed))
{
prevPeak = j;
break;
}
}
if(prevPeak >= 0 &&
high[i] > high[prevPeak] &&
MacdHistBuf[i] < MacdHistBuf[prevPeak])
{
if(confirmationBar < rates_total)
BearDivConfirmed[confirmationBar] = true;
}
}
}
}
bool RecentMACDDivergenceConfirmed(const int i,
const bool bullish)
{
if(!RequireMACDDivergenceConfirmation)
return(true);
int window = DivergenceConfirmWindow;
if(window < 0) window = 0;
int first = i - window;
if(first < g_firstBar) first = g_firstBar;
for(int k = i; k >= first; k--)
{
if(bullish && BullDivConfirmed[k]) return(true);
if(!bullish && BearDivConfirmed[k]) return(true);
}
return(false);
}
void ClearSignalBuffers(const int from,
const int to)
{
for(int i = from; i <= to; i++)
{
BuyCircle[i] = EMPTY_VALUE;
SellCircle[i] = EMPTY_VALUE;
BuyArrow[i] = EMPTY_VALUE;
SellArrow[i] = EMPTY_VALUE;
}
}
void ClearAllBuffers(const int total)
{
for(int i = 0; i < total; i++)
{
HAOpen[i] = EMPTY_VALUE;
HAHigh[i] = EMPTY_VALUE;
HALow[i] = EMPTY_VALUE;
HAClose[i] = EMPTY_VALUE;
HAColor[i] = 0.0;
ATRBuf[i] = 0.0;
BuyCircle[i] = EMPTY_VALUE;
SellCircle[i] = EMPTY_VALUE;
BuyArrow[i] = EMPTY_VALUE;
SellArrow[i] = EMPTY_VALUE;
TRBuf[i] = 0.0;
TRPrefix[i] = 0.0;
HABodyBuf[i] = 0.0;
HABodyPrefix[i] = 0.0;
}
}
void ResetSignalState()
{
g_buyPending = false;
g_buyRefHigh = 0.0;
g_buyBarsLeft = 0;
g_sellPending = false;
g_sellRefLow = 0.0;
g_sellBarsLeft = 0;
}
void FireAlert(const int dir,
const string typeText,
const double price,
const datetime candleTime)
{
if(!(EnablePopupAlert ||
EnablePushAlert ||
EnableEmailAlert ||
EnableSoundAlert))
return;
if(candleTime == g_lastAlertTime &&
dir == g_lastAlertDir)
return;
if(g_lastAlertWall > 0 &&
dir == g_lastAlertDir &&
(TimeCurrent() - g_lastAlertWall) < AlertCooldownSeconds)
return;
string tf = IntegerToString(Period());
string msg =
"SHK Heikin Ashi Signals | " +
Symbol() + " " +
tf + " | " +
typeText +
" | Price: " +
DoubleToString(price, Digits) +
" | Time: " +
TimeToString(candleTime, TIME_DATE | TIME_MINUTES);
if(EnablePopupAlert)
Alert(msg);
if(EnablePushAlert)
SendNotification(msg);
if(EnableEmailAlert)
SendMail("SHK Heikin Ashi Signal", msg);
if(EnableSoundAlert)
{
if(dir > 0)
PlaySound(BuySoundFile);
else
PlaySound(SellSoundFile);
}
g_lastAlertTime = candleTime;
g_lastAlertDir = dir;
g_lastAlertWall = TimeCurrent();
}
bool HasConfirmedHAColorChange(const int i,
const bool bullish)
{
int candles = g_confCandles;
if(candles < 1) candles = 1;
int runStart = i - candles + 1;
int previous = runStart - 1;
if(runStart < g_firstBar + 1 ||
previous < g_firstBar)
return(false);
for(int k = runStart; k <= i; k++)
{
if(bullish && !IsBullishHA(k)) return(false);
if(!bullish && !IsBearishHA(k)) return(false);
if(GetBodyPercent(k) < MinBodyPercent) return(false);
}
if(bullish)
return(IsBearishHA(previous));
return(IsBullishHA(previous));
}
void ProcessColorChangeArrow(const int i,
const datetime &time[],
const double atr,
const bool allowAlert)
{
if(HasConfirmedHAColorChange(i, true) &&
RecentMACDDivergenceConfirmed(i, true))
{
BuyArrow[i] =
HALow[i] - ArrowOffsetATR * atr;
if(allowAlert)
{
FireAlert(+1,
"STRONG BUY HA + MACD DivПоказано первые 50% кода (символов: 22824)
Открыть по тарифу
Купите тариф с пакетом открытий или войдите, если тариф уже есть. Открытый файл останется в вашем кабинете навсегда.
Разовая покупка файла
На этой странице откроется полный исходный код файла вместо ознакомительного фрагмента.
Зачем нужен email? После подтверждения оплаты файл сохранится в кабинете на этот email. Если аккаунта ещё нет, мы создадим его и пришлём ссылку для задания пароля. Если аккаунт уже есть, покупка добавится в него. Укажите адрес, к которому у вас есть доступ.
Чтобы оформить заказ, введите email и перейдите к оплате.