안녕하세요, 트레이더 여러분! 오늘은 메타트레이더 5에서 사용할 수 있는 헐 이동 평균(Hull Moving Average, HMA) 지표에 대해 알아보려고 합니다. 이 지표는 가격의 추세를 보다 명확히 파악할 수 있게 도와줍니다.
헐 이동 평균은 다음과 같은 네 가지 입력 매개변수를 가지고 있습니다:
- InpHmaPeriod = 20
- InpColorKind = single_color
- InpColorIndex = color_index_3
- InpMaxHistoryBars = 240
각 매개변수의 의미는 직관적입니다. ENUM_COLOR_KIND 설정은 단일 색상과 다중 색상 모드 간에 전환할 수 있게 해줍니다. 기본값은 단일 색상 모드입니다. 다중 색상 모드에서는 상승할 때는 다른 색상, 하락할 때는 또 다른 색상으로 표시됩니다. 단일 색상 모드에서는 ENUM_COLOR_INDEX가 헐 이동 평균의 색상을 설정합니다. 기본 색상은 회색이며, 상승 시에는 초록색, 하락 시에는 빨간색으로 표시됩니다. 아래 이미지를 통해 확인해보세요.


이제 헐 이동 평균을 구현하는 코드 예제를 살펴보겠습니다:
//+------------------------------------------------------------------+
//| MelzHull.mq5 |
//| Copyright 2022, wm1@gmx.de |
//| https://melz.one |
//+------------------------------------------------------------------+
/*
=== 헐 이동 평균 구현
이 지표에서 단일 색상과 다중 색상 모드를 선택할 수 있습니다.
*/
enum ENUM_COLOR_KIND {
single_color,
multi_color
};
enum ENUM_COLOR_INDEX {
color_index_0,
color_index_1,
color_index_2,
color_index_3,
color_index_4,
color_index_5,
color_index_6
};
#property copyright "Copyright 2022 by W. Melz, wm1@gmx.de"
#property link "https://melz.one"
#property version "1.00"
#property description "나의 헐 이동 평균 구현"
#property indicator_chart_window //
#property indicator_buffers 4 //
#property indicator_plots 1 //
#property indicator_type1 DRAW_COLOR_LINE //
#property indicator_color1 clrGray,clrGreen,clrRed,clrBlue,clrGreenYellow,clrDodgerBlue,clrFireBrick
#property indicator_width1 1 //
#property indicator_label1 "HMA"
input int InpHmaPeriod = 20; //
input ENUM_COLOR_KIND InpColorKind = single_color;
input ENUM_COLOR_INDEX InpColorIndex = color_index_3;
input int InpMaxHistoryBars = 240;
double valueBuffer[];
double colorBuffer[];
double fullWMABuffer[];
double halfWMABuffer[];
int hmaPeriod, fullPeriod, halfPeriod, sqrtPeriod, maxHistoryBars;
int OnInit() {
ENUM_INIT_RETCODE result = checkInput();
SetIndexBuffer(0, valueBuffer, INDICATOR_DATA);
SetIndexBuffer(1, colorBuffer, INDICATOR_COLOR_INDEX);
SetIndexBuffer(2, fullWMABuffer, INDICATOR_CALCULATIONS);
SetIndexBuffer(3, halfWMABuffer, INDICATOR_CALCULATIONS);
IndicatorSetInteger(INDICATOR_DIGITS, _Digits);
string shortName = StringFormat("HMA(%d)", hmaPeriod);
IndicatorSetString(INDICATOR_SHORTNAME, shortName);
fullPeriod = hmaPeriod;
halfPeriod = fullPeriod / 2;
sqrtPeriod = (int)round(sqrt((double)fullPeriod));
return (result);
}
void OnDeinit(const int reason) {
ArrayFree(valueBuffer);
ArrayFree(colorBuffer);
ArrayFree(fullWMABuffer);
ArrayFree(halfWMABuffer);
}
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 < maxHistoryBars + hmaPeriod)
return (0);
int startBar;
if (prev_calculated == 0) {
startBar = rates_total - maxHistoryBars - hmaPeriod - 1;
PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, startBar + hmaPeriod);
CalcHma(startBar, rates_total, close);
}
if (rates_total - prev_calculated == 1) {
startBar = rates_total - 1;
CalcHma(startBar, rates_total, close);
}
return (rates_total);
}
void CalcHma(int startBar, const int rates_total, const double &buf[]) {
for (int bar = startBar; bar < rates_total && !IsStopped(); bar++) {
double sum = 0.0;
double wMA = 0.0;
int wf = 1;
int sumWf = 0;
for (int i = fullPeriod - 1; i >= 0 ; i--) {
sum += buf[(bar - i)] * wf;
sumWf += wf;
wf += 1;
}
wMA = sum / sumWf;
fullWMABuffer[bar] = wMA;
sum = 0.0;
wMA = 0.0;
wf = 1;
sumWf = 0;
for (int i = halfPeriod - 1; i >= 0 ; i--) {
sum += buf[(bar - i)] * wf;
sumWf += wf;
wf += 1;
}
wMA = sum / sumWf;
halfWMABuffer[bar] = wMA;
sum = 0.0;
wf = 1;
sumWf = 0;
for (int i = sqrtPeriod - 1; i >= 0 ; i--) {
sum += (2 * halfWMABuffer[bar - i] - fullWMABuffer[bar - i]) * wf;
sumWf += wf;
wf += 1;
}
wMA = sum / sumWf;
valueBuffer[bar] = wMA;
colorBuffer[bar] = getColor(bar);
}
}
double getColor(int bar) {
double retval;
if (InpColorKind == single_color)
retval = InpColorIndex;
else {
retval = 0;
if (valueBuffer[bar - 1] < valueBuffer[bar])
retval = 1;
if (valueBuffer[bar - 1] > valueBuffer[bar])
retval = 2;
}
return (retval);
}
//+------------------------------------------------------------------+
이 코드를 통해 헐 이동 평균을 쉽게 사용할 수 있습니다. 트레이딩에 도움이 되길 바랍니다!