VWOP: Volume Weighted & Oscillated Price
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © EsIstTurnt

//@version=5
indicator("Volume Weighted & Oscillated Price",shorttitle = "VWOP",overlay=true)
vwosc(src,len1=16,len2=24,len3=32,len4=40,osclen=16,string osctype="RSI",matype="LRC",curve="<>")=>
    float osc = switch osctype          //                                                                  \
        "RSI"     => ta.rsi(src, osclen)//                                                                   \
        "CCI"     => ta.cci(src, osclen)//                                                                    \ 
        "COG"     => ta.cog(src, osclen)//                                                                     \ 
        "MFI"     => ta.mfi(src, osclen)//                                                                      -Select oscillator type to use for calculation below 
        "CMO"     => ta.cmo(src, osclen)//                                                                     /
        "TSI"     => ta.tsi(src, osclen,math.round(osclen*1.5))//                                             /
        "COPPOCK" => ta.wma(ta.roc(src,math.round(1.1*osclen))+ta.roc(src,math.round(1.4*osclen)),osclen)   //
        =>ta.rsi(src,osclen)//                                                                              /

    max=ta.max(osc)//  \
    min=ta.min(osc)//   -Get min and max values for selected oscillator, along with the difference between them 
    dif=max-min    //  /


    int lev = switch curve                                     //                                              -Calculate Variable Length, len1 should be lowest and len4 should
        //                                                                                                         be highest if custom lengths are chosen for the below to apply
        "<>" =>  osc-min < 0.25*dif or max-osc < 0.25*dif?len1://                                           \
          osc-min   < 0.35*dif or max-osc < 0.35*dif?len2://                                                 \ 
          osc-min   < 0.45*dif or max-osc < 0.45*dif?len3://                                                 / -Length with higher values as oscillator value approaches midpoint
          len4//                                                                                            /
        "><" => osc-min < 0.25*dif or max-osc < 0.25*dif?len4://                                            \
          osc-min   < 0.35*dif or max-osc < 0.35*dif?len3://                                                 \ 
          osc-min   < 0.45*dif or max-osc < 0.45*dif?len2://                                                 / -Length with lower values as oscillator approaches midpoint
          len1//                                                                                            /
        "<"  =>  osc-min   < 0.25*dif  ?len1://                                                             \
          osc-min   < 0.35*dif  ?math.round(math.avg(len1,len2))://                                          \
          osc-min   < 0.45*dif  ?len2://                                                                      \
          osc-min   < 0.55*dif  ?math.round(math.avg(len2,len3))://                                            -Length with higher values as oscillator value increases
          osc-min   < 0.65*dif  ?len3://                                                                      /
          osc-min   < 0.75*dif  ?math.round(math.avg(len3,len4))://                                          /
          len4//                                                                                            /
        ">"  => max-osc < 0.25*dif?len1://                                                                  \
          max-osc < 0.35*dif?math.round(math.avg(len1,len2))://                                              \
          max-osc < 0.45*dif?len2://                                                                          \
          max-osc < 0.55*dif?math.round(math.avg(len2,len3))://                                                -Length with lower values as oscillator value increases
          max-osc < 0.65*dif?len3://                                                                          /
          max-osc < 0.75*dif?math.round(math.avg(len3,len4))://                                              /  
          len4//                                                                                            /

    float ma=switch matype //                                                                               \
        "VWAP"=> ta.vwap  (math.sum(ta.vwap  (src)        * (volume),lev) / math.sum(volume,lev)      )  //  \
        "SWMA"=> ta.swma  (math.sum(ta.swma  (src)        * (volume),lev) / math.sum(volume,lev)      )  //   \
        "VWMA"=> ta.vwma  (math.sum(ta.vwma  (src,len1)   * (volume),lev) / math.sum(volume,lev), len2)  //    \
        "SMA" => ta.sma   (math.sum(ta.sma   (src,len1)   * (volume),lev) / math.sum(volume,lev), len2)  //     -VWAP Calculation, typical price is replaced by selected moving average "matype" and then multiplied by the volume,
        "EMA" => ta.ema   (math.sum(ta.ema   (src,len1)   * (volume),lev) / math.sum(volume,lev), len2)  //    /   then math.sum is used with the oscillating length created above to get a total value which is then divided by 
        "RMA" => ta.rma   (math.sum(ta.rma   (src,len1)   * (volume),lev) / math.sum(volume,lev), len2)  //   /    the sum of the volume using the same oscillating length value. Result is then passed through the selected
        "WMA" => ta.wma   (math.sum(ta.wma   (src,len1)   * (volume),lev) / math.sum(volume,lev), len2)  //  /     "matype" once more to give the final result.
        "LRC" => ta.linreg(math.sum(ta.linreg(src,len1,0) * (volume),lev) / math.sum(volume,lev), len2,0)// /
    ma//              

line=(vwosc(close,osctype="COPPOCK",curve="<") )
plot(line,color=color.new(#eca400,0))