Candle GainLossInfo

Author: Copyright 2024, Kursustrading.my.id
Price Data Components
Series array that contains the highest prices of each barSeries array that contains open prices of each barSeries array that contains close prices for each bar
0 Views
0 Downloads
0 Favorites
Candle GainLossInfo
#property copyright "Copyright 2024, Kursustrading.my.id"
#property link      "https://belajarfx.my.id"
#property version   "1.00"

#property description "Shows percentage and point gain/loss for a candle."
#property description "Can calculate gain/loss compared either to the previous Close or to the current Open."

// The indicator uses only objects for display, but the line below is required for it to work.
#property indicator_chart_window
#property indicator_plots 0

input double PercentageLimit = 1.0; // PercentageLimit - Will not display number if percentage gain/loss is below limit.
input int PointsLimit = 1000; // PointsLimit - Will not display number if points gain/loss is below limit.
// If true, will compare Close of the current candle to Close of the previous one. Otherwise compares current Close to current Open.
input bool CloseToClose = true;
input color DisplayLossColor = clrRed;
input color DisplayGainColor = clrLimeGreen;
input int MaxBars = 100; // MaxBars: More bars - more objects - more lag and memory usage.
input string FontFace = "Verdana";
input int FontSize = 10;
input string ObjectPrefix = "GLI-";

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

void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
{
    // Redraw visible labels.
    if (id == CHARTEVENT_CHART_CHANGE) RedrawVisibleLabels();
}

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[])
{
    string name, perc, points;
    int index = rates_total - 1;
    double start;

    int counted_bars = prev_calculated;
    if (counted_bars > 0) counted_bars--;
    int limit = counted_bars;
    if (rates_total - counted_bars > MaxBars) limit = rates_total - MaxBars;

    for (int i = rates_total - 1; i >= limit; i--)
    {
        if ((CloseToClose) && (i > 0)) start = Close[i - 1];
        else start = Open[i];

        name = ObjectPrefix + "Percent-" + TimeToString(Time[i], TIME_DATE | TIME_MINUTES);
        ObjectDelete(0, name);
        if (((Close[i] - start) / start) * 100 >= PercentageLimit) // Gain percent display
        {
            perc = DoubleToString(((Close[i] - start) / start) * 100, 1) + "%";
            ObjectCreate(0, name, OBJ_TEXT, 0, Time[i], High[i]);
            ObjectSetString(0, name, OBJPROP_TEXT, perc);
            ObjectSetInteger(0, name, OBJPROP_FONTSIZE, FontSize);
            ObjectSetString(0, name, OBJPROP_FONT, FontFace);
            ObjectSetInteger(0, name, OBJPROP_COLOR, DisplayGainColor);
            int visible_bars = (int)ChartGetInteger(0, CHART_VISIBLE_BARS);
            int first_bar = (int)ChartGetInteger(0, CHART_FIRST_VISIBLE_BAR);
            int last_bar = first_bar - visible_bars + 1;
            if ((i <= first_bar) && (i >= last_bar)) RedrawOneLabel(i, last_bar);
            ObjectSetInteger(0, name, OBJPROP_ANCHOR, ANCHOR_UPPER);
            ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);
            ObjectSetInteger(0, name, OBJPROP_HIDDEN, true);
        }
        else if (((start - Close[i]) / start) * 100 >= PercentageLimit) // Loss percent display
        {
            perc = DoubleToString(((start - Close[i]) / start) * 100, 1) + "%";
            ObjectCreate(0, name, OBJ_TEXT, 0, Time[i], High[i]);
            ObjectSetString(0, name, OBJPROP_TEXT, perc);
            ObjectSetInteger(0, name, OBJPROP_FONTSIZE, FontSize);
            ObjectSetString(0, name, OBJPROP_FONT, FontFace);
            ObjectSetInteger(0, name, OBJPROP_COLOR, DisplayLossColor);
            int visible_bars = (int)ChartGetInteger(0, CHART_VISIBLE_BARS);
            int first_bar = (int)ChartGetInteger(0, CHART_FIRST_VISIBLE_BAR);
            int last_bar = first_bar - visible_bars + 1;
            if ((i <= first_bar) && (i >= last_bar)) RedrawOneLabel(i, last_bar);
            ObjectSetInteger(0, name, OBJPROP_ANCHOR, ANCHOR_UPPER);
            ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);
            ObjectSetInteger(0, name, OBJPROP_HIDDEN, true);
        }

        name = ObjectPrefix + "Points-" + TimeToString(Time[i], TIME_DATE | TIME_MINUTES);
        ObjectDelete(0, name);
        if ((Close[i] - start) / _Point >= PointsLimit) // Gain points display
        {
            points = DoubleToString((Close[i] - start) / _Point, 0);
            ObjectCreate(0, name, OBJ_TEXT, 0, Time[i], Low[i]);
            ObjectSetString(0, name, OBJPROP_TEXT, points);
            ObjectSetInteger(0, name, OBJPROP_FONTSIZE, FontSize);
            ObjectSetString(0, name, OBJPROP_FONT, FontFace);
            ObjectSetInteger(0, name, OBJPROP_COLOR, DisplayGainColor);
            ObjectSetInteger(0, name, OBJPROP_ANCHOR, ANCHOR_UPPER);
            ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);
            ObjectSetInteger(0, name, OBJPROP_HIDDEN, true);
        }
        else if ((start - Close[i]) / _Point >= PointsLimit) // Loss points display
        {
            points = DoubleToString((start - Close[i]) / _Point, 0);
            ObjectCreate(0, name, OBJ_TEXT, 0, Time[i], Low[i]);
            ObjectSetString(0, name, OBJPROP_TEXT, points);
            ObjectSetInteger(0, name, OBJPROP_FONTSIZE, FontSize);
            ObjectSetString(0, name, OBJPROP_FONT, FontFace);
            ObjectSetInteger(0, name, OBJPROP_COLOR, DisplayLossColor);
            ObjectSetInteger(0, name, OBJPROP_ANCHOR, ANCHOR_UPPER);
            ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);
            ObjectSetInteger(0, name, OBJPROP_HIDDEN, true);
        }
    }

    return rates_total;
}

// Required only for labels above High.
void RedrawVisibleLabels()
{
   int visible_bars = (int)ChartGetInteger(0, CHART_VISIBLE_BARS);
   int first_bar = (int)ChartGetInteger(0, CHART_FIRST_VISIBLE_BAR);
   int last_bar = first_bar - visible_bars + 1;
   
   // Process all bars on the current screen.
   for (int i = first_bar; i >= last_bar; i--) RedrawOneLabel(i, last_bar);
}

void RedrawOneLabel(const int i, const int last_bar)
{
   int x, y, cw;
   uint w, h;
   datetime t;
   double p, high;
   string length, name;

   // For further use.
   high = iHigh(NULL, 0, i);

   name = GenerateObjectName("Percent-", iTime(NULL, Period(), i));
   if (ObjectFind(0, name) == -1) return;
   // Needed only for y; x is used as a dummy.
   ChartTimePriceToXY(0, 0, iTime(NULL, Period(), last_bar), high, x, y);
   // Get the height of the text based on font and its size. Negative because OS-dependent, *10 because set in 1/10 of pt.
   TextSetFont(FontFace, FontSize * -10);
   length = DoubleToString(MathRound((high - MathMax(iOpen(NULL, 0, i), iClose(NULL, 0, i))) / _Point), 0);
   TextGetSize(length, w, h);

   // Normal shift of the text upward will result in negative Y coordinate and the price level will be moved down.
   // To work around this, we have to calculate the "price difference" of the necessary "pixel difference" (price height of h).
   // Then, add it to the High of the bar.
   if (y - (int)h - 2 < 0)
   {
      if (!ChartXYToTimePrice(0, x, y + h + 2, cw, t, p)) Print("Error: ", GetLastError());
      double diff = high - p;
      p = high + diff;
   }
   // Normal way.
   else ChartXYToTimePrice(0, x, y - h - 2, cw, t, p);

   ObjectSetDouble(0, name, OBJPROP_PRICE, p);
}

string GenerateObjectName(const string prefix, const datetime time)
{
   return ObjectPrefix + prefix + TimeToString(time, TIME_DATE | TIME_MINUTES);
}
//+------------------------------------------------------------------+

Comments