保持敬畏之心
交易是一场持久战

MQL4(62):自定义指标源代码

这是系列教学的最后一篇文章,不知大家学会了多少,想进一步交流的加学长的微信:u31u31。
下面是课程中的自定义指标源代码:
#property copyright "版权归“图道交易”学长所有"
#property indicator_chart_window
#property indicator_buffers 3             // 定义3个“画图”缓冲区,分别用于:中轨、上轨、下轨
#property indicator_color1  DeepSkyBlue
#property indicator_color2  DeepSkyBlue
#property indicator_color3  DeepSkyBlue

// ===== 可调参数,交易员的“武器库” =====
extern int    BandsPeriod = 20;      // 均线和标准差的计算周期
extern int    BandsShift  = 0;       // 指标整体水平位移
extern int    BandsMethod = MODE_EMA;  // 均线类型,EMA对新价格更敏感,SMA则更平滑
extern int    BandsPrice  = PRICE_CLOSE; // 价格类型,收盘价是大部分策略的基石
extern double Deviations  = 2.0;     // 标准差倍数,决定通道宽度,是捕捉“机会”与“风险”的关键

/* ===== 指标数据缓冲区 =====
 * 这里是我们存放计算结果的“仓库”,MT4会根据这些数组来绘制指标线。
 */
double EMA[];
double UpperBand[];
double LowerBand[];

//+------------------------------------------------------------------+
//| 指标初始化函数,程序加载时只运行一次,好比开工前的准备工作。     |
//+------------------------------------------------------------------+
int OnInit()
{
    //--- 关联缓冲区并设置显示标签
    SetIndexBuffer(0, EMA);
    SetIndexLabel(0, "EMA (" + BandsPeriod + ")");

    SetIndexBuffer(1, UpperBand);
    SetIndexLabel(1, "Upper Band (" + DoubleToStr(Deviations, 1) + ")");

    SetIndexBuffer(2, LowerBand);
    SetIndexLabel(2, "Lower Band (" + DoubleToStr(Deviations, 1) + ")");

    //--- 统一设置线型
    SetIndexStyle(0, DRAW_LINE);
    SetIndexStyle(1, DRAW_LINE);
    SetIndexStyle(2, DRAW_LINE);

    //--- 处理指标的水平位移,让指标快人一步或慢人一拍,有时能发现不同周期共振的秘密
    if(BandsShift != 0)
    {
        SetIndexShift(0, BandsShift);
        SetIndexShift(1, BandsShift);
        SetIndexShift(2, BandsShift);
    }

    //--- 给指标起个“小名”,显示在图表左上角,一目了然
    IndicatorShortName("EMA Bands (" + BandsPeriod + "," + DoubleToStr(Deviations, 1) + ")");

    return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| 指标被移除时执行,可以做一些清理工作。                           |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
    // 通常我们在这里释放一些资源,不过这个指标比较简单,暂时留空。
}

//+------------------------------------------------------------------+
//| 核心计算函数,每个报价(tick)来临时都会被调用,性能是关键!       |
//+------------------------------------------------------------------+
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 < BandsPeriod)
        return(0);

    /* --- MT4的优化核心:只计算新K线,避免重复劳动 ---
     * 首次加载(prev_calculated == 0),需要从头算到尾。
     * 后续有了新K线,只用计算增量部分(rates_total - prev_calculated)即可。
     * 这是编写高效指标和EA的必会技巧,新手最容易忽略这点导致程序卡顿。
     */
    int start_pos;
    if(prev_calculated == 0)
        start_pos = rates_total - 1;
    else
        start_pos = rates_total - prev_calculated;

    //--- 从最新的K线开始,倒着计算,直到完成所有需要计算的K线
    for(int i = start_pos; i >= 0; i--)
    {
        EMA[i]       = iMA(NULL, 0, BandsPeriod, 0, BandsMethod, BandsPrice, i);
        double StdDev  = iStdDev(NULL, 0, BandsPeriod, 0, BandsMethod, BandsPrice, i);
        UpperBand[i] = EMA[i] + (StdDev * Deviations);
        LowerBand[i] = EMA[i] - (StdDev * Deviations);
    }
    return(rates_total);
}
赞(0)
未经允许不得转载:图道交易 » MQL4(62):自定义指标源代码
分享到

评论 抢沙发