month_first_kline

Author: Copyright 2019, MetaQuotes Software Corp.
Miscellaneous
It issuies visual alerts to the screen
0 Views
0 Downloads
0 Favorites
month_first_kline
//+------------------------------------------------------------------+
//|                                            month_first_kline.mq5 |
//|                        Copyright 2019, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2019, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property indicator_chart_window
#property description "每月的第一根k线、第一个周日"
#property description "每季、年的第一根k线"
#property description "每周的第一根k线"
#property description "每旬的第一根k线"

enum LineTimeType {
    Week,               // 周
    TenDay,             // 旬(10天)
    Month,              // 月
    Quarter,            // å­£
    Year,               // å¹´
    nYear               // nå¹´
};

//--- input parameters
input LineTimeType ltt = Month;                         // 线的时间类型
input int n_year = 10;                                  // 线的时间类型 == n年
input bool first_kline = true,                          // 每个月的第一根k线
        first_Sunday = false;                           // 每个月的第一个周日
input color color_first_kline = C'100,100,100',         // 颜色:每个月的第一根k线
        color_first_Sunday = C'150,150,150';            // 颜色:每个月的第一个周日

//---- kline data of start time
input bool flag_time_start_kline = true;                // 忽略EURUSD开始之前的时间
input string time_start_kline = "1999.01.01 00:00";     // EURUSD开始时间

//---- global parameters
string prefix_month_first_kline = "first_kline_of_month-";
string prefix_month_first_Sunday = "month_first_Sunday-";
datetime time_last = NULL;


//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit() {
    int ret;
    string err;

    if (ltt == nYear && n_year < 1) {
        ret = INIT_FAILED;
        err = StringFormat("参数设置错误!n_year: %d", n_year);
        Alert(err);
    } else
        ret = INIT_SUCCEEDED;
    return(ret);
}


void OnDeinit(const int reason) { del_all_line(); }


//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(
        const int rates_total,
        const int prev_calculated,
        const int begin,
        const double &price[]
        ) {
    /* 画每月的标示线 */
    datetime time_curr;

    time_curr = iTime(NULL, 0, 0);
    if (
            ! IsStopped()
            && (first_kline || first_Sunday)
            && (time_last == NULL || time_last < time_curr)
            ) {
        draw_line(time_curr);
        time_last = time_curr;
    }

    ChartRedraw();
    return(rates_total);
}


//+------------------------------------------------------------------+
void del_all_line() {
    /* 删除所有画线 */

    //---- 每月的第一根k线
    ObjectsDeleteAll(0, prefix_month_first_kline, 0, OBJ_VLINE);
    //---- 每月的第一个周日
    ObjectsDeleteAll(0, prefix_month_first_Sunday, 0, OBJ_VLINE);
}


void draw_line_month_first_kline(datetime t_p) {
    string name;

    /* 标示每月的第一根k线 */
    name = prefix_month_first_kline + TimeToString(t_p, TIME_DATE);
    if (ObjectFind(0, name) < 0) {
        ObjectCreate(0, name, OBJ_VLINE, 0, t_p, 0);
        ObjectSetInteger(0, name, OBJPROP_COLOR, color_first_kline);
        ObjectSetInteger(0, name, OBJPROP_STYLE, STYLE_DOT);
        ObjectSetInteger(0, name, OBJPROP_BACK, true);
    }
}


void draw_line_month_first_Sunday(datetime t_p) {
    /* 标示每月的第一个周日00:00
     * 特殊情况:
     *      2019.03.08
     *      2018.03.09
     *      2017.12.08
     *      2017.03.10
     *      2016.07.08
     */
    MqlDateTime x;
    int i;
    datetime t_q;
    string name;

    TimeToStruct(t_p, x);
    i = 7 - x.day_of_week;
    if (i == 1)
        // 周六
        i += 7;
    x.day += i;
    if (
            (x.year == 2019 && x.mon == 3)
            || (x.year == 2018 && x.mon == 3)
            || (x.year == 2017 && x.mon == 12)
            || (x.year == 2017 && x.mon == 3)
            || (x.year == 2016 && x.mon == 7)
            )
        // 特殊情况
        x.day += 7;
    t_q = StructToTime(x);
    name = prefix_month_first_Sunday + TimeToString(t_q, TIME_DATE);
    if (ObjectFind(0, name) < 0) {
        ObjectCreate(0, name, OBJ_VLINE, 0, t_q, 0);
        ObjectSetInteger(0, name, OBJPROP_COLOR, color_first_Sunday);
        ObjectSetInteger(0, name, OBJPROP_STYLE, STYLE_DOT);
        ObjectSetInteger(0, name, OBJPROP_BACK, true);
    }
}


MqlDateTime get_right_time(const datetime dt) {
    /* 计算正确的时间 */
    int n, m;
    MqlDateTime x;

    TimeToStruct(dt, x);
    x.day = 1;
    x.hour = 0;
    x.min = 0;
    x.sec = 0;
    if (ltt == Week) {
        // 周
        n = x.day_of_week;
        if (0 < n) {
            m = (int)StructToTime(x) - n * 24 * 3600;
            TimeToStruct(m, x);
        }
    } else if (ltt == TenDay) {
        // 旬
        if (x.day < 11)
            // 上旬
            x.day = 1;
        else if (x.day < 21)
            // 中旬
            x.day = 11;
        else
            // 下旬
            x.day = 21;
    } else if (ltt == Month)
        // 月
        x.day = 1;
    else if (ltt == Quarter) {
        // å­£
        x.day = 1;
        if (x.mon < 4)
            x.mon = 1;
        else if (x.mon < 7)
            x.mon = 4;
        else if (x.mon < 10)
            x.mon = 7;
        else
            x.mon = 10;
    } else if (ltt == Year || ltt == nYear) {
        // å¹´
        x.day = 1;
        x.mon = 1;
    }
    return(x);
}


void next_time(MqlDateTime &x) {
    /* 下一个时间 */
    int m;

    if (ltt == Week) {
        // 周
        m = (int)StructToTime(x) + 7 * 24 * 3600;
        TimeToStruct(m, x);
    } else if (ltt == TenDay) {
        // 旬
        if (x.day == 1)
            // 上旬
            x.day = 11;
        else if (x.day == 11)
            // 中旬
            x.day = 21;
        else {
            // 下旬
            x.day = 1;
            x.mon += 1;
            if (12 < x.mon) {
                x.mon = 1;
                x.year += 1;
            }
        }
    } else if (ltt == Month) {
        // 月
        x.mon += 1;
        if (12 < x.mon) {
            x.mon = 1;
            x.year += 1;
        }
    } else if (ltt == Quarter) {
        // å­£
        x.mon += 3;
        if (12 < x.mon) {
            x.mon = 1;
            x.year += 1;
        }
    } else if (ltt == Year)
        // å¹´
        x.year += 1;
    else if (ltt == nYear)
        // nå¹´
        x.year += n_year;
}


datetime get_time_start(void) {
    /* 获取开始时间 */
    datetime t_start, tsk;

    if (time_last == NULL)
        t_start = iTime(NULL, 0, -1);
    else
        t_start = time_last;
    tsk = StringToTime(time_start_kline);
    if (flag_time_start_kline && t_start < tsk)
        t_start = tsk;

    return(t_start);
}


void draw_line(const datetime time_curr) {
    datetime t_start, t_stop, t_p;
    MqlDateTime x;

    // 取图表第一根k线
    t_start = get_time_start();
    // 取图表最后一根k线
    t_stop = time_curr;

    x = get_right_time(t_start);
    t_p = StructToTime(x);
    while (t_p < t_stop) {
        //---- 下个月的1号
        next_time(x);
        t_p = StructToTime(x);
        //---- 标示每月的第一根k线
        if (first_kline)
            draw_line_month_first_kline(t_p);
        //---- 标示每月的第一个周日
        if (first_Sunday && ltt != Week)
            draw_line_month_first_Sunday(t_p);
    }
    ChartRedraw();
}
//+------------------------------------------------------------------+

Comments