MQL5 自訂指標進階:緩衝區顏色切換與子視窗繪製

📌 本文重點
深入 MQL5 自訂指標開發:多緩衝區管理、動態顏色切換(紅/藍)、子視窗振盪器繪製、彩色直方圖,以及從 EA 呼叫自訂指標。

彩色線指標:價格在均線上方顯示藍色,下方顯示紅色

#property indicator_chart_window
#property indicator_buffers 3
#property indicator_plots   2

// 繪圖 0:彩色均線
#property indicator_label1  "彩色均線"
#property indicator_type1   DRAW_COLOR_LINE
#property indicator_color1  clrDodgerBlue, clrRed, clrGray
#property indicator_style1  STYLE_SOLID
#property indicator_width1  2

// 繪圖 1:訊號箭頭
#property indicator_label2  "訊號"
#property indicator_type2   DRAW_ARROW
#property indicator_color2  clrGold
#property indicator_width2  2

double g_maBuffer[];
double g_colorBuffer[];   // 顏色索引 0=藍 1=紅 2=灰
double g_signalBuffer[];

input int InpPeriod = 20;
input ENUM_MA_METHOD InpMethod = MODE_EMA;
int g_maHandle = INVALID_HANDLE;

int OnInit()
{
    SetIndexBuffer(0, g_maBuffer,     INDICATOR_DATA);
    SetIndexBuffer(1, g_colorBuffer,  INDICATOR_COLOR_INDEX);
    SetIndexBuffer(2, g_signalBuffer, INDICATOR_DATA);
    PlotIndexSetInteger(1, PLOT_ARROW, 233);
    PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, EMPTY_VALUE);
    PlotIndexSetDouble(1, PLOT_EMPTY_VALUE, EMPTY_VALUE);
    g_maHandle = iMA(_Symbol, _Period, InpPeriod, 0, InpMethod, PRICE_CLOSE);
    IndicatorSetString(INDICATOR_SHORTNAME, "彩色MA("+IntegerToString(InpPeriod)+")");
    return (g_maHandle != INVALID_HANDLE) ? INIT_SUCCEEDED : INIT_FAILED;
}

void OnDeinit(const int r) { IndicatorRelease(g_maHandle); }

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[])
{
    int start = (prev_calculated == 0) ? InpPeriod : prev_calculated - 1;
    if (rates_total < InpPeriod) return 0;

    double maValues[];
    ArraySetAsSeries(maValues, false);
    if (CopyBuffer(g_maHandle, 0, 0, rates_total, maValues) <= 0) return prev_calculated;

    for (int i = start; i < rates_total; i++)
    {
        g_maBuffer[i]     = maValues[i];
        g_signalBuffer[i] = EMPTY_VALUE;

        // 根據價格與 MA 位置決定顏色
        if      (close[i] > maValues[i]) g_colorBuffer[i] = 0; // 藍
        else if (close[i] < maValues[i]) g_colorBuffer[i] = 1; // 紅
        else                              g_colorBuffer[i] = 2; // 灰

        // 偵測穿越,繪製箭頭
        if (i > 0 && maValues[i-1] != EMPTY_VALUE)
        {
            if (close[i-1] <= maValues[i-1] && close[i] > maValues[i])
                g_signalBuffer[i] = low[i] - 5*_Point;
            if (close[i-1] >= maValues[i-1] && close[i] < maValues[i])
                g_signalBuffer[i] = high[i] + 5*_Point;
        }
    }
    return rates_total;
}

子視窗彩色 MACD 直方圖

#property indicator_separate_window
#property indicator_buffers 3
#property indicator_plots   2

#property indicator_type1   DRAW_COLOR_HISTOGRAM
#property indicator_color1  clrMediumSeaGreen, clrCrimson
#property indicator_width1  2
#property indicator_type2   DRAW_LINE
#property indicator_color2  clrSilver
#property indicator_style2  STYLE_DOT

double g_hist[], g_histColor[], g_zero[];
input int InpFast=12, InpSlow=26, InpSignal=9;
int g_macdHandle = INVALID_HANDLE;

int OnInit()
{
    SetIndexBuffer(0, g_hist,      INDICATOR_DATA);
    SetIndexBuffer(1, g_histColor, INDICATOR_COLOR_INDEX);
    SetIndexBuffer(2, g_zero,      INDICATOR_DATA);
    g_macdHandle = iMACD(_Symbol, _Period, InpFast, InpSlow, InpSignal, PRICE_CLOSE);
    return (g_macdHandle != INVALID_HANDLE) ? INIT_SUCCEEDED : INIT_FAILED;
}

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[])
{
    int start = (prev_calculated == 0) ? InpSlow+InpSignal : prev_calculated-1;
    double macd[], sig[];
    ArraySetAsSeries(macd,false); ArraySetAsSeries(sig,false);
    if (CopyBuffer(g_macdHandle,0,0,rates_total,macd)<=0) return prev_calculated;
    if (CopyBuffer(g_macdHandle,1,0,rates_total,sig)<=0)  return prev_calculated;
    for (int i=start; i<rates_total; i++)
    {
        double h = macd[i] - sig[i];
        g_hist[i]      = h;
        g_histColor[i] = (h >= 0) ? 0 : 1;
        g_zero[i]      = 0.0;
    }
    return rates_total;
}

從 EA 呼叫自訂指標

// 假設指標檔名為 MyColorMA.ex5
int handle = iCustom(_Symbol, _Period, "MyColorMA", 20, MODE_EMA);

// 取得值(buffer 0)
double val[1]; ArraySetAsSeries(val,true);
if (CopyBuffer(handle, 0, 1, 1, val) >= 1)
    Print("MA Value = ", val[0]);

// 取得顏色索引(buffer 1)
double col[1]; ArraySetAsSeries(col,true);
if (CopyBuffer(handle, 1, 1, 1, col) >= 1)
    Print("Color Index = ", col[0]); // 0=藍, 1=紅, 2=灰

本文由 James Lee 撰寫。內容僅供教育目的,不構成投資建議。

Similar Posts

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *