Simthandile sim new indicator

MQL5 Indicadores Conversão

Termos de Referência

calcVolume(void)
  {
//---
   MqlRates rates[];

   if(CopyRates(_Symbol, PERIOD_CURRENT, startTime, endTime, rates) > 0)
     {
      double rangeHigh = rates[0].high, rangeLow = rates[0].low;
      int  count = MathAbs(iBarShift(_Symbol, PERIOD_CURRENT, startTime) -
                           iBarShift(_Symbol, PERIOD_CURRENT, endTime)) + 1;

      //---VERTICAL PRICE RANGE
      for(int b = 0; b < ArraySize(rates); b++)
        {
         if(rates[b].high > rangeHigh)
            rangeHigh = rates[b].high;

         if(rates[b].low < rangeLow)
            rangeLow = rates[b].low;
        }
      //--- SET ANALYSIS RANGE RECTANGLE PROPERLY
      ObjectSetDouble(0, _VOLUME_RANGE, OBJPROP_PRICE, 0, rangeHigh);
      ObjectSetDouble(0, _VOLUME_RANGE, OBJPROP_PRICE, 1, rangeLow);
      ChartRedraw();
      //--- ADAPTIVE BIN CONSTRUCTION
      int numberOfBins = int(count / 4);
      numberOfBins = MathMax(5, numberOfBins);
      double step = (rangeHigh - rangeLow) / numberOfBins;
      st_priceVolume bins[];
      ArrayResize(bins, numberOfBins);
      double binHigh = EMPTY_VALUE,  binLow = EMPTY_VALUE;
      bool useRealVol = (rates[0].real_volume > 0);

      //--- VOLUME ACCUMULATION USING SELECTED PRICE MODEL
      for(int w = 0; w < numberOfBins; w++)
        {
         binLow = rangeLow + step * w;
         binHigh = binLow + step;
         for(int c = 0; c < ArraySize(rates); c++)
           {
            if(getPrice(rates[c]) >= binLow && getPrice(rates[c]) <= binHigh)
              {
               bins[w].volume += (useRealVol) ? rates[c].real_volume : rates[c].tick_volume;
               bins[w].price = NormalizeDouble(getPrice(rates[c]), _Digits);
              }
           }        
        }
      //--- VOLUME EXTREMES
      long maxVol = 0, minVol = LONG_MAX;
      for(int b = 0; b < ArraySize(bins); b++)
        {
         if(bins[b].volume > maxVol)
            maxVol = bins[b].volume;

         if(bins[b].volume < minVol)
            minVol = bins[b].volume;
        }
      //--- PROFILE SCALING
      int extendBars = 0;
      int maxProfileLength =  int(count * 0.4);
      int minProfileLength = (int)MathRound(maxProfileLength * 0.05);
      minProfileLength = MathMax(2, minProfileLength);// CLAMP
      color clr = clrRed;
      double dominance = EMPTY_VALUE;
      //--- PROFILE RENDERING
      bool pocDrawn = false;
      for(int p = 0; p < ArraySize(bins); p++)
        {
         binLow = rangeLow + step * p;
         binHigh = binLow + step;

         extendBars = minProfileLength + (int)MathRound(normalizeMinMax(bins[p].volume, maxVol, minVol)
                      * (maxProfileLength - minProfileLength));
         dominance = (double)extendBars / maxProfileLength;
         clr = (dominance >= 0.8) ? clrBlue :
               (dominance >= 0.6) ? clrPurple :
               (dominance >= 0.5) ? clrBrown :
               (dominance >= 0.4) ? clrLime :
               (dominance >= 0.2) ? clrTeal :
               (dominance >= 0.15) ? clrBlueViolet :
               clrGray;

         createRect(_PROFILE + (string)p, startTime, binHigh, startTime + (PeriodSeconds()*extendBars), binLow, clr);
         if(bins[p].volume == maxVol && !pocDrawn)
           {
            //--- DRAW MAXIMUM VOLUME'S POC
            createHLine(_PROFILE_POC + (string)p, NormalizeDouble(bins[p].price, _Digits), clr, "POC");
            pocDrawn = true;
           }
        }
      ChartRedraw();
     }
  }

Initialization and Cleanup

Having established the supporting helper functions, we now implement the standard MQL5 event handlers, beginning with OnInit() and OnDeinit(). During initialization, the indicator creates the ON/OFF menu button, providing users with a convenient way to enable or disable the interactive Crosshair Volume Profile. Conversely, when the indicator is removed, the cleanup routine is executed to delete all indicator-generated chart objects and restore the chart's default interaction settings, ensuring the chart is left in a clean and consistent state.
//+------------------------------------------------------------------+
//|                   INITIALIZATION FUNCTION                        |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
   createMenuButton();
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//|                  DEINITIALIZATION FUNCTION                       |
//+------------------------------------------------------------------+
void OnDeinit(const int32_t reason)
  {
//---
   clearChart();
  }

Iteration Engine (OnCalculate)

Unlike conventional indicators that recalculate whenever new market data arrives, this indicator is designed around user interaction rather than incoming candles. For this reason, the OnCalculate() function is intentionally left empty, simply returning rates_total to satisfy the standard MQL5 indicator interface. All Volume Profile computations are instead triggered by Crosshair-driven chart events, ensuring the indicator updates only when the user selects or modifies an analysis range. This event-driven approach aligns with the interactive nature of the indicator while avoiding unnecessary recalculations on every incoming tick or bar.

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int32_t rates_total,
                const int32_t 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 int32_t &spread[])
  {
//--- EMPTY
   return(rates_total);
  }

Interactive Engine

At the heart of the indicator is the OnChartEvent() function, which handles all chart events and drives the interactive behavior of the Crosshair Volume Profile. Rather than relying on incoming market data, the indicator responds to user actions such as button clicks, mouse movement, keyboard input, and right-click operations. This event-driven architecture enables users to interactively define an analysis range and generate the Volume Profile only when required.

//+------------------------------------------------------------------+
//|                      CHARTEVENT FUNCTION                         |
//+------------------------------------------------------------------+
void OnChartEvent(const int32_t id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
  {
//---
   st_priceVolume tp;
   static bool isDragging = false;
   int key = (int)lparam;
   static ulong lastClick = 0;
   switch(id)
     {
      case CHARTEVENT_OBJECT_CLICK:
         //--- TOGGLE MENU BUTTON
         if(sparam == _MENU_BUTTON)
           {
            toggleMenuButton();
           }
         break;
      case CHARTEVENT_KEYDOWN:
         //--- PROFILE DELETION: "C" DOUBLE-CLICK
         if(key == 67)
           {
            ulong now = GetTickCount();
            bool doubleClick = (now - lastClick <= 300);
            lastClick = now;
            if(doubleClick && ObjectFind(0, _VOLUME_RANGE) > -1)
              {
               ObjectsDeleteAll(0, _PROFILE);
               ObjectDelete(0, _VOLUME_RANGE);
               if(ObjectGetString(0, _MENU_BUTTON, OBJPROP_TEXT) == "ON")
                 {
                  toggleMenuButton();
                 }
               ChartRedraw();
              }
           }
         break;
      case CHARTEVENT_MOUSE_MOVE:
         if(isDragging)
           {
            //--- UPDATE OBJECTS ALONG THE CURSOR POSITION USING getCursorPriceTime()
            tp = getCursorPriceTime((short)lparam, (short)dparam);
            tp.time = (tp.time >= iTime(_Symbol, PERIOD_CURRENT, 0)) ?
                      iTime(_Symbol, PERIOD_CURRENT, 1) : tp.time;
            ObjectMove(0, _V_END_LINE, 0, tp.time, 0);
            ObjectMove(0, _H_LINE, 0, 0, tp.price);
            ObjectMove(0, _VOLUME_RANGE, 1, tp.time, tp.price);
            endTime = tp.time;
            ChartRedraw();
           }
         //--- RIGHT-CLICK
         if(((uchar)sparam & MOUSE_RIGHT) != 0)
           {
            tp = getCursorPriceTime((short)lparam, (short)dparam);

            if(!isDragging)
              {
               //--- CREATE CROSSHAIR
               isDragging = true;
               color clr = (color)ChartGetInteger(0, CHART_COLOR_BACKGROUND);
               ObjectsDeleteAll(0, _PROFILE);
               ChartRedraw();
               startTime = tp.time;
               createVLine(_V_START_LINE, tp.time);
               createVLine(_V_END_LINE, 0);
               createHLine(_H_LINE, 0, (clr == clrBlack) ?
                           clrWhite : clrBlack);
               //--- POSITION RECTANGLE ANCHOR (0) AT THE HIGH OF BAR AT RIGHT-CLICK POSITION
               int index = iBarShift(_Symbol, PERIOD_CURRENT, tp.time);
               double price = iHigh(_Symbol, PERIOD_CURRENT, index);
               createRect(_VOLUME_RANGE, tp.time, price, 0, 0, clrOldLace, "ANALYSIS RANGE");
               ChartRedraw();
              }
           }
         else
           {
            //--- RIGHT-CLICK RELEASE
            if(isDragging)
              {
               //--- DELETE CROSSHAIR
               ObjectDelete(0, _V_START_LINE);
               ObjectDelete(0, _V_END_LINE);
               ObjectDelete(0, _H_LINE);
               ChartRedraw();
               isDragging = false;
               //--- RENDER VOLUME PROFILE
               calcVolume();
              }
           }
         break;

Respondido

1
Desenvolvedor 1
Classificação
(395)
Projetos
556
41%
Arbitragem
30
57% / 3%
Expirado
57
10%
Livre
Publicou: 11 códigos
2
Desenvolvedor 2
Classificação
(2)
Projetos
4
0%
Arbitragem
0
Expirado
0
Livre
3
Desenvolvedor 3
Classificação
(1)
Projetos
1
0%
Arbitragem
1
0% / 100%
Expirado
0
Livre
4
Desenvolvedor 4
Classificação
(185)
Projetos
199
47%
Arbitragem
4
50% / 25%
Expirado
1
1%
Trabalhando
5
Desenvolvedor 5
Classificação
(8)
Projetos
8
0%
Arbitragem
2
50% / 0%
Expirado
1
13%
Trabalhando
6
Desenvolvedor 6
Classificação
(1)
Projetos
1
0%
Arbitragem
0
Expirado
0
Livre
7
Desenvolvedor 7
Classificação
(10)
Projetos
12
33%
Arbitragem
0
Expirado
2
17%
Trabalhando
Publicou: 1 código
8
Desenvolvedor 8
Classificação
(13)
Projetos
14
64%
Arbitragem
0
Expirado
0
Livre
9
Desenvolvedor 9
Classificação
(1)
Projetos
1
0%
Arbitragem
0
Expirado
1
100%
Livre
10
Desenvolvedor 10
Classificação
(2)
Projetos
2
0%
Arbitragem
1
0% / 100%
Expirado
0
Livre
11
Desenvolvedor 11
Classificação
(3)
Projetos
9
67%
Arbitragem
0
Expirado
0
Trabalhando
12
Desenvolvedor 12
Classificação
Projetos
0
0%
Arbitragem
0
Expirado
0
Livre
13
Desenvolvedor 13
Classificação
Projetos
0
0%
Arbitragem
0
Expirado
0
Livre
Publicou: 2 códigos
14
Desenvolvedor 14
Classificação
Projetos
0
0%
Arbitragem
0
Expirado
0
Livre
15
Desenvolvedor 15
Classificação
(3)
Projetos
4
0%
Arbitragem
1
100% / 0%
Expirado
1
25%
Livre
16
Desenvolvedor 16
Classificação
Projetos
0
0%
Arbitragem
0
Expirado
0
Livre
Publicou: 1 código
17
Desenvolvedor 17
Classificação
Projetos
0
0%
Arbitragem
0
Expirado
0
Livre
Publicou: 2 códigos
18
Desenvolvedor 18
Classificação
(2676)
Projetos
3420
68%
Arbitragem
77
48% / 14%
Expirado
343
10%
Trabalhando
Publicou: 1 código
19
Desenvolvedor 19
Classificação
(2)
Projetos
2
50%
Arbitragem
0
Expirado
0
Livre
20
Desenvolvedor 20
Classificação
Projetos
0
0%
Arbitragem
0
Expirado
0
Livre
21
Desenvolvedor 21
Classificação
Projetos
0
0%
Arbitragem
0
Expirado
0
Livre
22
Desenvolvedor 22
Classificação
(4)
Projetos
8
0%
Arbitragem
3
33% / 67%
Expirado
4
50%
Livre
23
Desenvolvedor 23
Classificação
Projetos
0
0%
Arbitragem
0
Expirado
0
Livre
24
Desenvolvedor 24
Classificação
Projetos
0
0%
Arbitragem
0
Expirado
0
Livre
25
Desenvolvedor 25
Classificação
(1)
Projetos
1
0%
Arbitragem
0
Expirado
0
Livre
Publicou: 3 códigos
26
Desenvolvedor 26
Classificação
Projetos
0
0%
Arbitragem
0
Expirado
0
Livre
27
Desenvolvedor 27
Classificação
(2)
Projetos
2
50%
Arbitragem
0
Expirado
0
Livre
28
Desenvolvedor 28
Classificação
(10)
Projetos
14
43%
Arbitragem
0
Expirado
3
21%
Livre
29
Desenvolvedor 29
Classificação
(64)
Projetos
145
46%
Arbitragem
21
38% / 24%
Expirado
32
22%
Livre
30
Desenvolvedor 30
Classificação
(3)
Projetos
1
0%
Arbitragem
5
0% / 100%
Expirado
0
Livre
31
Desenvolvedor 31
Classificação
(4)
Projetos
6
67%
Arbitragem
0
Expirado
0
Livre
Publicou: 2 códigos
32
Desenvolvedor 32
Classificação
(264)
Projetos
310
75%
Arbitragem
15
67% / 0%
Expirado
6
2%
Trabalhando
33
Desenvolvedor 33
Classificação
Projetos
0
0%
Arbitragem
0
Expirado
0
Livre
34
Desenvolvedor 34
Classificação
Projetos
0
0%
Arbitragem
0
Expirado
0
Livre

Informações sobre o projeto

Orçamento
40 - 300 USD
Prazo
de 1 para 10 dias