RoundLevels_v3

Miscellaneous
It sends emails
0 Views
0 Downloads
0 Favorites
RoundLevels_v3
//+------------------------------------------------------------------+
//|                                                  RoundLevels.mq4 |
//|                                      https://t.me/ForexEaPremium |
//+------------------------------------------------------------------+
#property copyright "https://t.me/ForexEaPremium"
#property link      "https://t.me/ForexEaPremium"
#property version   "2.03"
#property strict

#property description "Generates round level zone background shading on chart."

#property indicator_chart_window
#property indicator_plots 0

input int Levels = 5; // Levels - number of level zones in each direction.
input int Interval = 50; // Interval between zones in points.
input int ZoneWidth = 10; // Zone width in points.
input color ColorUp = clrFireBrick;
input color ColorDn = clrDarkGreen;
input bool InvertZones = false; // Invert zones to shade the areas between round numbers.
input bool DrawLines = false; // Draw lines on levels.
input color LineColor = clrDarkGray;
input int LineWidth = 1;
input ENUM_LINE_STYLE LineStyle = STYLE_DASHDOT;
input bool ZonesAsBackground = true;
input bool LinesAsBackground = false;
input bool ShowLineLabels = false;
input color LineLabelColor = clrWhite;
input string ObjectPrefix = "RoundLevels";
input string Comment_1 = "======================="; // Notification Options
input bool EnableNotify = false;                    // Enable Notifications Feature
input bool SendAlert = true;                        // Send Alert Notification
input bool SendApp = false;                         // Send Notification to Mobile
input bool SendEmail = false;                       // Send Notification via Email
input int AlertDelay = 5;                           // Alert Delay, seconds

enum direction
{
    Up,
    Down
};

datetime LastNotificationTime;

void OnInit()
{
    LastNotificationTime = TimeCurrent();
}

void OnDeinit(const int reason)
{
    ObjectsDeleteAll(0, ObjectPrefix);
}

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[])
{
    double starting_price = NormalizeDouble(SymbolInfoDouble(_Symbol, SYMBOL_BID), _Digits);

    for (int i = 0; i < Levels; i++)
    {
        // Calculate price levels below and above the current price.
        double lvl_down = FindNextLevel(NormalizeDouble(starting_price - i * Interval * _Point, _Digits), Down);
        double lvl_up = FindNextLevel(NormalizeDouble(starting_price + i * Interval * _Point, _Digits), Up);
        // Calculate and draw rectangle below current price.
        string name = ObjectPrefix + "D" + IntegerToString(i);
        double price1, price2;
        if (InvertZones)
        {
            price1 = lvl_down - (ZoneWidth / 2 * _Point);
            price2 = lvl_down - ((Interval - ZoneWidth / 2) * _Point);
        }
        else
        {
            price1 = lvl_down + (ZoneWidth / 2 * _Point);
            price2 = lvl_down - (ZoneWidth / 2 * _Point);
        }
        DrawRectangle(name, price1, price2, ColorDn);
        name = ObjectPrefix + "LD" + IntegerToString(i);
        if (DrawLines) DrawLine(name, lvl_down);
        Notify(price1, price2);

        // Calculate and draw rectangle above current price.
        name = ObjectPrefix + "U" + IntegerToString(i);
        if (InvertZones)
        {
            price1 = lvl_up + ((Interval - ZoneWidth / 2) * _Point);
            price2 = lvl_up + (ZoneWidth / 2 * _Point);
        }
        else
        {
            price1 = lvl_up + (ZoneWidth / 2 * _Point);
            price2 = lvl_up - (ZoneWidth / 2 * _Point);
        }
        DrawRectangle(name, price1, price2, ColorUp);
        name = ObjectPrefix + "LU" + IntegerToString(i);
        if (DrawLines) DrawLine(name, lvl_up);
        Notify(price1, price2);
    }

    // Center level required for inverted zones.
    if (InvertZones)
    {
        double lvl_down = FindNextLevel(NormalizeDouble(starting_price, _Digits), Down);
        double lvl_up = FindNextLevel(NormalizeDouble(starting_price, _Digits), Up);
        string name = ObjectPrefix + "C";
        double price1 = lvl_up - (ZoneWidth / 2 * _Point);
        double price2 = lvl_down + (ZoneWidth / 2 * _Point);
        DrawRectangle(name, price1, price2, (ColorDn + ColorUp) / 2);
        Notify(price1, price2);
    }
    
    return 0;
}

double FindNextLevel(const double sp, const direction dir)
{
    // Multiplier for getting number of points in the price.
    double multiplier = MathPow(10, _Digits);
    // Integer price (nubmer of points in the price).
    int integer_price = (int)MathRound(sp * MathPow(10, _Digits));
    // Distance from the next round number down.
    int distance = integer_price % Interval;
    if (dir == Down)
    {
        return NormalizeDouble(MathRound(integer_price - distance) / multiplier, _Digits);
    }
    else if (dir == Up)
    {
        return NormalizeDouble((integer_price + (Interval - distance)) / multiplier, _Digits);
    }
    return EMPTY_VALUE;
}

void DrawRectangle(const string name, const double price1, const double price2, const color colour)
{
    if (ObjectFind(0, name) < 0) ObjectCreate(0, name, OBJ_RECTANGLE, 0, 0, 0);
    ObjectSetDouble(0, name, OBJPROP_PRICE, 0, price1);
    ObjectSetDouble(0, name, OBJPROP_PRICE, 1, price2);
    ObjectSetInteger(0, name, OBJPROP_TIME, 0, D'1970.01.01');
    ObjectSetInteger(0, name, OBJPROP_TIME, 1, D'3000.12.31');
    ObjectSetInteger(0, name, OBJPROP_COLOR, colour);
    ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);
    ObjectSetInteger(0, name, OBJPROP_BACK, ZonesAsBackground);
    ObjectSetInteger(0, name, OBJPROP_FILL, true);
    if ((!DrawLines) && (ShowLineLabels))
    {
        DrawLineLabel(name + "_LL", (price1 + price2) / 2);
    }
}

void DrawLine(const string name, const double price)
{
    if (ObjectFind(0, name) < 0) ObjectCreate(0, name, OBJ_HLINE, 0, 0, 0);
    ObjectSetDouble(0, name, OBJPROP_PRICE, 0, price);
    ObjectSetInteger(0, name, OBJPROP_COLOR, LineColor);
    ObjectSetInteger(0, name, OBJPROP_STYLE, LineStyle);
    ObjectSetInteger(0, name, OBJPROP_WIDTH, LineWidth);
    ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);
    ObjectSetInteger(0, name, OBJPROP_BACK, LinesAsBackground);
    if (ShowLineLabels)
    {
        DrawLineLabel(name + "_LL", price);
    }
}

void DrawLineLabel(const string name, const double price)
{
    if (ObjectFind(0, name) < 0) ObjectCreate(0, name, OBJ_ARROW_RIGHT_PRICE, 0, 0, 0);
    ObjectSetDouble(0, name, OBJPROP_PRICE, 0, price);
    ObjectSetInteger(0, name, OBJPROP_TIME, 0, iTime(Symbol(), Period(), 0));
    ObjectSetInteger(0, name, OBJPROP_COLOR, LineLabelColor);
    ObjectSetInteger(0, name, OBJPROP_WIDTH, LineWidth);
    ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);
    ObjectSetInteger(0, name, OBJPROP_BACK, false);
}

void Notify(double price1, double price2)
{
    if ((!EnableNotify) || ((!SendAlert) && (!SendApp) && (!SendEmail))) return;
    if (TimeCurrent() - LastNotificationTime < AlertDelay) return;

    if ((SymbolInfoDouble(Symbol(), SYMBOL_BID) > MathMax(price2, price1)) || (SymbolInfoDouble(Symbol(), SYMBOL_BID) < MathMin(price2, price1))) return;
    
    string EmailSubject = "RoundLevels " + Symbol() + " Notification";
    string EmailBody = AccountInfoString(ACCOUNT_COMPANY) + " - " + AccountInfoString(ACCOUNT_NAME) + " - " + IntegerToString(AccountInfoInteger(ACCOUNT_LOGIN)) + "\r\nRoundLevels Notification for " + Symbol() + " @ " + EnumToString((ENUM_TIMEFRAMES)Period()) + "\r\n";
    string AlertText = "RoundLevels - " + Symbol() + " @ " + EnumToString((ENUM_TIMEFRAMES)Period()) + " ";
    string AppText = AccountInfoString(ACCOUNT_COMPANY) + " - " + AccountInfoString(ACCOUNT_NAME) + " - " + IntegerToString(AccountInfoInteger(ACCOUNT_LOGIN)) + " - RoundLevels - " + Symbol() + " @ " + EnumToString((ENUM_TIMEFRAMES)Period()) + " - ";
    
    string Text = "Bid Price (" + DoubleToString(SymbolInfoDouble(Symbol(), SYMBOL_BID), _Digits) + ") inside a Zone (" + DoubleToString(price2, _Digits) + "-" + DoubleToString(price1, _Digits) + ")";

    EmailBody += Text;
    AlertText += Text;
    AppText += Text;
    if (SendAlert) Alert(AlertText);
    if (SendEmail)
    {
        if (!SendMail(EmailSubject, EmailBody)) Print("Error sending email " + IntegerToString(GetLastError()));
    }
    if (SendApp)
    {
        if (!SendNotification(AppText)) Print("Error sending notification " + IntegerToString(GetLastError()));
    }
    
    LastNotificationTime = TimeCurrent();
}
//+------------------------------------------------------------------+

Comments

Markdown supported. Formatting help

Markdown Formatting Guide

Element Markdown Syntax
Heading # H1
## H2
### H3
Bold **bold text**
Italic *italicized text*
Link [title](https://www.example.com)
Image ![alt text](image.jpg)
Code `code`
Code Block ```
code block
```
Quote > blockquote
Unordered List - Item 1
- Item 2
Ordered List 1. First item
2. Second item
Horizontal Rule ---