Help converting “Quantile based signed volume analysis 1.1” indicator from mq5

Viewing 6 posts - 1 through 6 (of 6 total)
  • Author
    Posts
  • #142537 quote
    AtApi
    Participant
    Junior

    Please help converting this “Quantile based signed volume analysis 1.1” indicator from mq5.

    The original code include several prices to be used as input but it is really not necessary and just the close would do it.

    //------------------------------------------------------------------
    //
    //------------------------------------------------------------------
    #property copyright "www.forex-tsd.com"
    #property link      "www.forex-tsd.com"
    
    #property indicator_separate_window
    #property indicator_buffers 9
    #property indicator_plots   4
    #property indicator_label1  "Quantile volume"
    #property indicator_type1   DRAW_FILLING
    #property indicator_color1  clrDodgerBlue,clrSandyBrown
    #property indicator_label2  "Quantile volume"
    #property indicator_type2   DRAW_FILLING
    #property indicator_color2  clrDodgerBlue,clrSandyBrown
    #property indicator_label3  "Quantile volume"
    #property indicator_type3   DRAW_LINE
    #property indicator_color3  clrGray
    #property indicator_style3  STYLE_SOLID
    #property indicator_width3  2
    #property indicator_label4  "Quantile volume"
    #property indicator_type4   DRAW_LINE
    #property indicator_color4  clrGray
    #property indicator_style4  STYLE_SOLID
    #property indicator_width4  2
    
    //
    //
    //
    //
    //
    
    enum enPrices
    {
       pr_close,      // Close
       pr_open,       // Open
       pr_high,       // High
       pr_low,        // Low
       pr_median,     // Median
       pr_typical,    // Typical
       pr_weighted,   // Weighted
       pr_average,    // Average (high+low+open+close)/4
       pr_medianb,    // Average median body (open+close)/2
       pr_tbiased,    // Trend biased price
       pr_tbiased2,   // Trend biased price - extremes
       pr_haclose,    // Heiken ashi close
       pr_haopen ,    // Heiken ashi open
       pr_hahigh,     // Heiken ashi high
       pr_halow,      // Heiken ashi low
       pr_hamedian,   // Heiken ashi median
       pr_hatypical,  // Heiken ashi typical
       pr_haweighted, // Heiken ashi weighted
       pr_haaverage,  // Heiken ashi average
       pr_hamedianb,  // Heiken ashi median body
       pr_hatbiased,  // Heiken ashi trend biased price
       pr_hatbiased2  // Heiken ashi trend biased price - extremes
    };
    
    input int      Periods             = 20;       // Calculation period
    input enPrices Price               = pr_close; // Price 
    input double   UpQuantilePercent   = 90;       // Upper quantile percent
    input double   DownQuantilePercent = 10;       // Lower quantile percent
    input double   AtrUpperPercent     = 75;       // Upper atr percent
    input double   AtrLowerPercent     = 25;       // Lower atr percent
    input bool     LimitToZeroes       = true;     // Limit display to zero level?
    input bool     UseRealVolume       = false;    // Use real volume?
    
    //
    //
    //
    //
    //
    
    double fillUp[];
    double fillUpz[];
    double fillDn[];
    double fillDnz[];
    double bufferUp[];
    double bufferDn[];
    double quantUp[];
    double quantDn[];
    double prices[];
    
    //------------------------------------------------------------------
    //
    //------------------------------------------------------------------
    //
    //
    //
    //
    //
    
    int OnInit()
    {
       SetIndexBuffer(0,fillUp  ,INDICATOR_DATA); SetIndexBuffer(1,fillUpz,INDICATOR_DATA);
       SetIndexBuffer(2,fillDn  ,INDICATOR_DATA); SetIndexBuffer(3,fillDnz,INDICATOR_DATA);
       SetIndexBuffer(4,bufferUp,INDICATOR_DATA);
       SetIndexBuffer(5,bufferDn,INDICATOR_DATA);
       SetIndexBuffer(6,quantUp ,INDICATOR_CALCULATIONS);
       SetIndexBuffer(7,quantDn ,INDICATOR_CALCULATIONS);
       SetIndexBuffer(8,prices  ,INDICATOR_CALCULATIONS);
          
          //
          //
          //
          //
          //
          
       IndicatorSetString(INDICATOR_SHORTNAME,"Quantile based signed volume analysis 1 ("+(string)Periods+","+(string)UpQuantilePercent+","+(string)DownQuantilePercent+")");
       return(0);
    }
    void OnDeinit(const int reason) { return; }
    
    //------------------------------------------------------------------
    //
    //------------------------------------------------------------------
    //
    //
    //
    //
    //
    
    int OnCalculate (const int rates_total,      // size of input time series 
                     const int prev_calculated,  // bars handled in previous call 
                     const datetime& time[],     // Time 
                     const double& open[],       // Open 
                     const double& high[],       // High 
                     const double& low[],        // Low 
                     const double& close[],      // Close 
                     const long& tick_volume[],  // Tick Volume 
                     const long& volume[],       // Real Volume 
                     const int& spread[]         // Spread 
       )
    {
       for (int i=(int)MathMax(prev_calculated-1,0); i<rates_total; i++)
       {
          prices[i]  = getPrice(Price,open,close,high,low,rates_total,i);
          quantUp[i] = iQuantile(Periods,UpQuantilePercent  ,i);
          quantDn[i] = iQuantile(Periods,DownQuantilePercent,i);
          
          //
          //
          //
          //
          //
          
          bufferUp[i] = 0;
          bufferDn[i] = 0;
          for (int k=0; k<Periods && i-k-1>=0; k++)
          {
             double atr  = MathMax(close[i-k-1],high[i-k])-MathMin(close[i-k-1],low[i-k]);
             double sign = 0;
                if (prices[i-k] > low[i-k]+atr*AtrUpperPercent/100.0 && prices[i-k]>prices[i-k-1]) sign =  1;
                if (prices[i-k] < low[i-k]+atr*AtrLowerPercent/100.0 && prices[i-k]<prices[i-k-1]) sign = -1;
                if (!UseRealVolume)
                {
                   if (prices[i-k] > quantUp[i-k]) bufferUp[i]+= sign*tick_volume[i-k]*prices[i-k]*atr;
                   if (prices[i-k] < quantDn[i-k]) bufferDn[i]+= sign*tick_volume[i-k]*prices[i-k]*atr;
                }
                else
                {
                   if (prices[i-k] > quantUp[i-k]) bufferUp[i]+= sign*volume[i-k]*prices[i-k]*atr;
                   if (prices[i-k] < quantDn[i-k]) bufferDn[i]+= sign*volume[i-k]*prices[i-k]*atr;
                }               
          }
          if (LimitToZeroes)
          {
             bufferUp[i] = MathMax(bufferUp[i],0);
             bufferDn[i] = MathMin(bufferDn[i],0);
          }
          fillUp[i] = bufferUp[i]; fillUpz[i] = 0;       
          fillDn[i] = bufferDn[i]; fillDnz[i] = 0;       
       }
       return(rates_total);
    }
    
    //------------------------------------------------------------------
    //
    //------------------------------------------------------------------
    //
    //
    //
    //
    //
    
    double quantileArray[];
    double iQuantile(int period, double qp, int i)
    {
       if (ArraySize(quantileArray)!=period) ArrayResize(quantileArray,period);
                      for(int k=0; k<period && (i-k)>=0; k++) quantileArray[k] = prices[i-k];
           ArraySort(quantileArray);
    
       //
       //
       //
       //
       //
       
       double index = (period-1)*qp/100.00;
       int    ind   = (int)index;
       double delta = index - ind;
       if (ind == NormalizeDouble(index,5))
             return(            quantileArray[ind]);
       else  return((1.0-delta)*quantileArray[ind]+delta*quantileArray[ind+1]);
    }
    
    //------------------------------------------------------------------
    //
    //------------------------------------------------------------------
    //
    //
    //
    //
    //
    //
    
    
    double workHa[][4];
    double getPrice(int price, const double& open[], const double& close[], const double& high[], const double& low[], int bars, int i,  int instanceNo=0)
    {
      if (price>=pr_haclose)
       {
          if (ArrayRange(workHa,0)!= bars) ArrayResize(workHa,bars);
             
             //
             //
             //
             //
             //
             
             double haOpen;
             if (i>0)
                    haOpen  = (workHa[i-1][instanceNo+2] + workHa[i-1][instanceNo+3])/2.0;
             else   haOpen  = (open[i]+close[i])/2;
             double haClose = (open[i] + high[i] + low[i] + close[i]) / 4.0;
             double haHigh  = MathMax(high[i], MathMax(haOpen,haClose));
             double haLow   = MathMin(low[i] , MathMin(haOpen,haClose));
    
             if(haOpen  <haClose) { workHa[i][instanceNo+0] = haLow;  workHa[i][instanceNo+1] = haHigh; } 
             else                 { workHa[i][instanceNo+0] = haHigh; workHa[i][instanceNo+1] = haLow;  } 
                                    workHa[i][instanceNo+2] = haOpen;
                                    workHa[i][instanceNo+3] = haClose;
             //
             //
             //
             //
             //
             
             switch (price)
             {
                case pr_haclose:     return(haClose);
                case pr_haopen:      return(haOpen);
                case pr_hahigh:      return(haHigh);
                case pr_halow:       return(haLow);
                case pr_hamedian:    return((haHigh+haLow)/2.0);
                case pr_hamedianb:   return((haOpen+haClose)/2.0);
                case pr_hatypical:   return((haHigh+haLow+haClose)/3.0);
                case pr_haweighted:  return((haHigh+haLow+haClose+haClose)/4.0);
                case pr_haaverage:   return((haHigh+haLow+haClose+haOpen)/4.0);
                case pr_hatbiased:
                   if (haClose>haOpen)
                         return((haHigh+haClose)/2.0);
                   else  return((haLow+haClose)/2.0);        
                case pr_hatbiased2:
                   if (haClose>haOpen) return(haHigh);
                   if (haClose<haOpen) return(haLow);
                                       return(haClose);        
             }
       }
       
       //
       //
       //
       //
       //
       
       switch (price)
       {
          case pr_close:     return(close[i]);
          case pr_open:      return(open[i]);
          case pr_high:      return(high[i]);
          case pr_low:       return(low[i]);
          case pr_median:    return((high[i]+low[i])/2.0);
          case pr_medianb:   return((open[i]+close[i])/2.0);
          case pr_typical:   return((high[i]+low[i]+close[i])/3.0);
          case pr_weighted:  return((high[i]+low[i]+close[i]+close[i])/4.0);
          case pr_average:   return((high[i]+low[i]+close[i]+open[i])/4.0);
          case pr_tbiased:   
                   if (close[i]>open[i])
                         return((high[i]+close[i])/2.0);
                   else  return((low[i]+close[i])/2.0);        
          case pr_tbiased2:   
                   if (close[i]>open[i]) return(high[i]);
                   if (close[i]<open[i]) return(low[i]);
                                         return(close[i]);        
       }
       return(0);
    }

    Many Thanks!

    quantile_based_volume.png quantile_based_volume.png
    #142543 quote
    Nicolas
    Keymaster
    Master

    Added to my conversion list. Will only be compatible for PRT v11 and upwards.

    AtApi thanked this post
    #142545 quote
    AtApi
    Participant
    Junior

    Thank you Nicolas!!!

    #144263 quote
    AtApi
    Participant
    Junior

    Hello,

    i was wondering if you have any update on this conversion..

    Thanks again!

    #144505 quote
    Nicolas
    Keymaster
    Master

    Sorry I am stuck because of the sorting of the array. There is still no instruction to do it, it is planned to add it in the future, that’s why I was not replying to your query..

    Since finding the quantile of a data serie is the base of this indicator, I can’t accurately translate this indicator by now.

    jonpt88 thanked this post
    #144907 quote
    AtApi
    Participant
    Junior

    Ok, i understand.. Thanks anyway Nicolas!

    jonpt88 thanked this post
Viewing 6 posts - 1 through 6 (of 6 total)
  • You must be logged in to reply to this topic.

Help converting “Quantile based signed volume analysis 1.1” indicator from mq5


ProBuilder: Indicators & Custom Tools

New Reply
Author
author-avatar
AtApi @atapi Participant
Summary

This topic contains 5 replies,
has 2 voices, and was last updated by AtApi
5 years, 4 months ago.

Topic Details
Forum: ProBuilder: Indicators & Custom Tools
Language: English
Started: 08/25/2020
Status: Active
Attachments: 1 files
Logo Logo
Loading...