WAP Maverick - (Dual EMA Smoothed VWAP) - [mutantdog]
// This wapSwitch code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © mutantdog

//@version=5
indicator ('WAP Maverick v2.1', 'WAP Maverick', true)


string  S01 =   'open'
string  S02 =   'high'
string  S03 =   'low'
string  S04 =   'close'
string  S11 =   'hl2'
string  S12 =   'hlc3'
string  S13 =   'ohlc4'
string  S14 =   'hlcc4'

string  S51 =   'oc2'
string  S52 =   'hlc2-o2'
string  S53 =   'hl-oc2'
string  S54 =   'cc-ohlc4'


string  T01 =   'Input from chart, can be used to select other indicator. Select AUX in main or side wapSwitch to use. (note: "indicator on indicator" function may be restricted to Premium and Pro+ accounts).'
string  T02 =   'Session size in minutes when Anchor is set to Intraday only. Setting 0 value will use current timeframe.'
string  T03 =   'EMA length used for smoothing, is independant from anchor. WAP is calculated as ema(numerator,length) / ema(denominator,length).'
string  T04 =   'Shifts WAP (and bands) up / down by multiple of Standard Deviation.'
string  T05 =   'Only active bands will be used for alerts. Hi bands based on Arithmetic WAP, Lo bands based on Harmonic WAP.'
string  T06 =   'Up crosses against Arithmetic WAP, down crosses against Harmonic WAP.'
string  T07 =   'Applied to active bands only.'
string  T08 =   'Visual only, does not affect main alerts.'


// ------
// INPUTS
// ------


auxSource   =   input.source    (close,     'Aux In',                                                           tooltip=T01)

wapSource   =   input.string    ('hlc3',    'Source',       [S01, S02, S03, S04, S11, S12, S13, S14, S51, S52, S53, S54, '* AUX'],                  group='WAP')
wapAnchor   =   input.string    ('Week',    '(w)Anchor',    ['Day', 'Week', 'Month', 'Quarter', 'Year', 'Intraday'],                                group='WAP')
wapMinutes  =   input.int       (240,       '(w)Intraday',          minval=0,   maxval=1440,    step=60,        tooltip=T02,                        group='WAP')
emaLength   =   input.int       (21,        '(m)Length',            minval=1,                                   tooltip=T03,                        group='WAP')
devShift    =   input.float     (0,         'Deviate',                                          step=0.05,      tooltip=T04,                        group='WAP')
useMa       =   input.bool      (true,      'EMA Smoothing',                                                                                        group='WAP')


bandMult_a  =   input.float     (1,         'Bands A: Mult',        minval=0,                   step=0.1,                           inline='11',    group='Bands')
activeHi_a  =   input.bool      (false,     'Hi',                                                                                   inline='11',    group='Bands')
activeLo_a  =   input.bool      (false,     'Lo',                                                               tooltip=T05,        inline='11',    group='Bands')

bandMult_b  =   input.float     (2,         'Bands B: Mult',        minval=0,                   step=0.1,                           inline='12',    group='Bands')
activeHi_b  =   input.bool      (false,     'Hi',                                                                                   inline='12',    group='Bands')
activeLo_b  =   input.bool      (false,     'Lo',                                                                                   inline='12',    group='Bands')

bandMult_c  =   input.float     (3,         'Bands C: Mult',        minval=0,                   step=0.1,                           inline='13',    group='Bands')
activeHi_c  =   input.bool      (false,     'Hi',                                                                                   inline='13',    group='Bands')
activeLo_c  =   input.bool      (false,     'Lo',                                                                                   inline='13',    group='Bands')


sideSource  =   input.string    ('close',   'Source',       [S01, S02, S03, S04, S11, S12, S13, S14, S51, S52, S53, S54, '* AUX'],                  group='Side')
sideFilter  =   input.string    ('none',    'Filter',       ['none', 'SMA', 'EMA', 'WMA', 'RMA', 'VWMA', 'HMA', 'VWEMA'],                           group='Side')
sideLength  =   input.int       (8,         'Length',               minval=1,                                                                       group='Side')


showUp_0    =   input.bool      (false,     'Up',                                                                                   inline='33',    group='Crosses')
showDn_0    =   input.bool      (false,     'Down - WAP',                                                       tooltip=T06,        inline='33',    group='Crosses')
showUp_a    =   input.bool      (false,     'Up',                                                                                   inline='34',    group='Crosses')
showDn_a    =   input.bool      (false,     'Down - Bands: A',                                                  tooltip=T07,        inline='34',    group='Crosses')
showUp_b    =   input.bool      (false,     'Up',                                                                                   inline='35',    group='Crosses')
showDn_b    =   input.bool      (false,     'Down - Bands: B',                                                  tooltip=T07,        inline='35',    group='Crosses')
showUp_c    =   input.bool      (false,     'Up',                                                                                   inline='36',    group='Crosses')
showDn_c    =   input.bool      (false,     'Down - Bands: C',                                                  tooltip=T07,        inline='36',    group='Crosses')

showAlerts  =   input.bool      (true,      'Show Alerts',                                                      tooltip=T08,        inline='37',    group='Crosses')


bullHue     =   input.color     (#87CEEB,   '',                                                                                     inline='42',    group='Visual')
bearHue     =   input.color     (#B8860B,   '',                                                                                     inline='42',    group='Visual')
bandHue     =   input.color     (#006666,   '',                                                                                     inline='42',    group='Visual')
neutralHue  =   input.color     (#808080,   '',                                                                                     inline='42',    group='Visual')
sideHue     =   input.color     (#BDB76B,   '',                                                                                     inline='42',    group='Visual')
alertHue    =   input.color     (#D8BFD8,   '',                                                                                     inline='42',    group='Visual')

wapOpacP    =   input.int       (75,        'Opacity: WAP',         minval=0,   maxval=100,         step=5,                         inline='47',    group='Visual')
bandOpacP   =   input.int       (50,        'Bands',                minval=0,   maxval=100,         step=5,                         inline='47',    group='Visual')
wapOpacF    =   input.int       (50,        'Fill: WAP    ',        minval=0,   maxval=100,         step=5,                         inline='48',    group='Visual')
bandOpacF   =   input.int       (15,        'Bands',                minval=0,   maxval=100,         step=5,                         inline='48',    group='Visual')
sideOpac    =   input.int       (30,        'Opacity: Side',        minval=0,   maxval=100,         step=5,                         inline='49',    group='Visual')
alertOpac   =   input.int       (60,        'Alerts',               minval=0,   maxval=100,         step=5,                         inline='49',    group='Visual')


// ---------
// FUNCTIONS
// ---------


source_switch (src, aux) => 
    wapSwitch          =   switch src
        'open'      =>  open
        'high'      =>  high
        'low'       =>  low
        'close'     =>  close
        'hl2'       =>  hl2
        'hlc3'      =>  hlc3
        'ohlc4'     =>  ohlc4
        'hlcc4'     =>  hlcc4
        'oc2'       =>  (open + close) / 2
        'hlc2-o2'   =>  (high + low + close - open) / 2
        'hl-oc2'    =>  high + low - (open + close) / 2
        'cc-ohlc4'  =>  2 * close - ohlc4
        
        '* AUX'     =>  aux
//

wap_wanchor (src, prd, mins) =>
    int sessionsize =   na
    
    sessionsize     :=  mins != 0               ?   mins                        :   timeframe.multiplier
    makesession     =   timeframe.isminutes     ?   str.tostring (sessionsize)  :   timeframe.period
    
    timechange      =   switch prd
        'Day'       =>  ta.change (time ('D'))
        'Week'      =>  ta.change (time ('W'))
        'Month'     =>  ta.change (time ('M'))
        'Quarter'   =>  ta.change (time ('3M'))
        'Year'      =>  ta.change (time ('12M'))
        'Intraday'  =>  ta.change (time (makesession))
        
    na (src[1])     ?   true    :   timechange    
//    

wap_maverick (src, len, anch) =>
    var float       sumSrcVol       =   na
    var float       sumVol          =   na
    var float       sumSrcSrcVol    =   na
    var float       sumVolSrc       =   na

    fixVolume       =   volume > 1  ?   volume  :   1

    sumSrcVol       :=  anch        ?   fixVolume * src                 :   fixVolume * src                 +   sumSrcVol[1]
    sumVol          :=  anch        ?   fixVolume                       :   fixVolume                       +   sumVol[1]
    sumSrcSrcVol    :=  anch        ?   fixVolume * math.pow(src, 2)    :   fixVolume * math.pow(src, 2)    +   sumSrcSrcVol[1]
    sumVolSrc       :=  anch        ?   fixVolume / src                 :   fixVolume / src                 +   sumVolSrc[1] 
    
    var float       mavAri          =   na
    var float       mavHar          =   na
    var float       mavVari         =   na

    mavAri          :=  ta.ema (sumSrcVol, len)     /   ta.ema (sumVol, len)
    mavHar          :=  ta.ema (sumVol, len)        /   ta.ema (sumVolSrc, len)
    mavVari         :=  ta.ema (sumSrcSrcVol, len)  /   ta.ema (sumVol, len)        -   math.pow (mavAri, 2)
    
    mavDev          =   math.sqrt (mavVari)

    [mavAri, mavHar, mavDev]
//

filter_switch (src, len, mode) =>
    filter          =   switch mode
        'none'      =>  src
        'SMA'       =>  ta.sma  (src, len)
        'EMA'       =>  ta.ema  (src, len)
        'WMA'       =>  ta.wma  (src, len)
        'RMA'       =>  ta.rma  (src, len)
        'VWMA'      =>  ta.vwma (src, len)

        'VWEMA'     =>  ta.ema  (src * volume, len)     /   ta.ema (volume, len)
        'HMA'       =>  len >= 2    ?   ta.hma (src, len)   :   src
//


// -------
// PROCESS
// -------


wapSwitch               =   source_switch (wapSource, auxSource)
wapWanchor              =   wap_wanchor (wapSwitch, wapAnchor, wapMinutes)
mavLength               =   useMa   ?   emaLength   :   1

[wAri, wHar, wmDev]     =   wap_maverick (wapSwitch, mavLength, wapWanchor)
wmAri                   =   wAri    +   devShift * wmDev
wmHar                   =   wHar    +   devShift * wmDev
wmMid                   =   (wmAri + wmHar) / 2

aloBand                 =   activeLo_a      ?   wmHar   -   wmDev * bandMult_a      :   na
ahiBand                 =   activeHi_a      ?   wmAri   +   wmDev * bandMult_a      :   na
bloBand                 =   activeLo_b      ?   wmHar   -   wmDev * bandMult_b      :   na
bhiBand                 =   activeHi_b      ?   wmAri   +   wmDev * bandMult_b      :   na
cloBand                 =   activeLo_c      ?   wmHar   -   wmDev * bandMult_c      :   na
chiBand                 =   activeHi_c      ?   wmAri   +   wmDev * bandMult_c      :   na

sideSwitch              =   source_switch (sideSource, auxSource)
sideMain                =   filter_switch (sideSwitch, sideLength, sideFilter)


// ----------------
// VISUALS & ALERTS
// ----------------


wm_gradient (wap, sid, dev, bear, bull, mult) =>
    delt        =   (sid - wap) / dev
    rma2        =   ta.rma (delt, 2)
    rma3        =   ta.rma (delt, 3)

    bear2       =   color.from_gradient (rma2,   -1.5,    0,    color.new (bear, 100 - mult/2),     color.new (bear, 100 - mult/10) )
    bull2       =   color.from_gradient (rma2,      0,  1.5,    color.new (bull, 100 - mult/10),    color.new (bull, 100 - mult/2)  )
    bear3       =   color.from_gradient (rma3,   -2.5,    0,    color.new (bear, 100 - mult),       color.new (bear, 100 - mult/10) )
    bull3       =   color.from_gradient (rma3,      0,  2.5,    color.new (bull, 100 - mult/10),    color.new (bull, 100 - mult)    )

    fill2       =   rma2 > 0    ?   bull2   :   rma2 < 0    ?   bear2   :   na
    fill3       =   rma3 > 0    ?   bull3   :   rma3 < 0    ?   bear3   :   na

    [fill2, fill3]
//    

// COLOURS

bullColour      =   color.new (bullHue,    100 - wapOpacP)
bearColour      =   color.new (bearHue,    100 - wapOpacP)
neutralColour   =   color.new (neutralHue, 100 - wapOpacP)
bandColour      =   color.new (bandHue,    100 - bandOpacP)
sideColour      =   color.new (sideHue,    100 - sideOpac)

alertColour     =   color.new (alertHue,   100 - alertOpac)
bandFill        =   color.new (bandHue,    100 - bandOpacF/2)


ariColour       =   (sideMain > wmAri)  and (sideMain[1] > wmAri[1])    ?   bullColour      :   (sideMain < wmAri)  and (sideMain[1] < wmAri[1])    ?   bearColour      :   neutralColour        
harColour       =   (sideMain > wmHar)  and (sideMain[1] > wmHar[1])    ?   bullColour      :   (sideMain < wmHar)  and (sideMain[1] < wmHar[1])    ?   bearColour      :   neutralColour        
midColour       =   (sideMain > wmMid)  and (sideMain[1] > wmMid[1])    ?   bullColour      :   (sideMain < wmMid)  and (sideMain[1] < wmMid[1])    ?   bearColour      :   neutralColour        

[wapFillA, wapFillB]    =   wm_gradient (wmMid, sideMain, wmDev, bearHue, bullHue, wapOpacF)


// PLOTS

ariPlot     =   plot (wmAri,    'WAP: Arithmetic',      ariColour,      2)
harPlot     =   plot (wmHar,    'WAP: Harmonic',        harColour,      2)
midPlot     =   plot (wmMid,    'WAP: Mid (hidden)',    midColour,      1,      display=display.none)

ahiPlot     =   plot (ahiBand,  'Band A: Hi',           bandColour,     2)
aloPlot     =   plot (aloBand,  'Band A: Lo',           bandColour,     2)
bhiPlot     =   plot (bhiBand,  'Band B: Hi',           bandColour,     2)
bloPlot     =   plot (bloBand,  'Band B: Lo',           bandColour,     2)
chiPlot     =   plot (chiBand,  'Band C: Hi',           bandColour,     2)
cloPlot     =   plot (cloBand,  'Band C: Lo',           bandColour,     2)

sidePlot    =   plot (sideMain,  'Side',                sideColour,     2)


fill (ariPlot,  harPlot,    wapFillA,   'Fill WAP A')
fill (ariPlot,  harPlot,    wapFillB,   'Fill WAP B')

fill (ariPlot,  ahiPlot,    bandFill,   'Fill Band A: Hi')
fill (harPlot,  aloPlot,    bandFill,   'Fill Band A: Lo')
fill (ariPlot,  bhiPlot,    bandFill,   'Fill Band B: Hi')
fill (harPlot,  bloPlot,    bandFill,   'Fill Band B: Lo')
fill (ariPlot,  chiPlot,    bandFill,   'Fill Band C: Hi')
fill (harPlot,  cloPlot,    bandFill,   'Fill Band C: Lo')


// ALERTS

wapUp   =   showUp_0    ?   ta.crossover    (sideMain, wmAri)       :   na 
wapDn   =   showDn_0    ?   ta.crossunder   (sideMain, wmHar)       :   na 

aloUp   =   showUp_a    ?   ta.crossover    (sideMain, aloBand)     :   na
ahiUp   =   showUp_a    ?   ta.crossover    (sideMain, ahiBand)     :   na
bloUp   =   showUp_b    ?   ta.crossover    (sideMain, bloBand)     :   na
bhiUp   =   showUp_b    ?   ta.crossover    (sideMain, bhiBand)     :   na
cloUp   =   showUp_c    ?   ta.crossover    (sideMain, cloBand)     :   na
chiUp   =   showUp_c    ?   ta.crossover    (sideMain, chiBand)     :   na

aloDn   =   showDn_a    ?   ta.crossunder   (sideMain, aloBand)     :   na
ahiDn   =   showDn_a    ?   ta.crossunder   (sideMain, ahiBand)     :   na
bloDn   =   showDn_b    ?   ta.crossunder   (sideMain, bloBand)     :   na
bhiDn   =   showDn_b    ?   ta.crossunder   (sideMain, bhiBand)     :   na
cloDn   =   showDn_c    ?   ta.crossunder   (sideMain, cloBand)     :   na
chiDn   =   showDn_c    ?   ta.crossunder   (sideMain, chiBand)     :   na


atrPlot =   ta.atr (4)

plotshape (showAlerts and wapUp     ?   wmHar   - atrPlot   :   na,   'Buy: WAP',       shape.triangleup,     location.absolute,    alertColour,    size=size.tiny,     display=display.pane)
plotshape (showAlerts and wapDn     ?   wmAri   + atrPlot   :   na,   'Sell: WAP',      shape.triangledown,   location.absolute,    alertColour,    size=size.tiny,     display=display.pane)

plotshape (showAlerts and aloUp     ?   aloBand - atrPlot   :   na,   'Buy: Loband A',  shape.triangleup,     location.absolute,    alertColour,    size=size.tiny,     display=display.pane)
plotshape (showAlerts and ahiUp     ?   ahiBand - atrPlot   :   na,   'Buy: Hiband A',  shape.triangleup,     location.absolute,    alertColour,    size=size.tiny,     display=display.pane)
plotshape (showAlerts and bloUp     ?   bloBand - atrPlot   :   na,   'Buy: Loband B',  shape.triangleup,     location.absolute,    alertColour,    size=size.tiny,     display=display.pane)
plotshape (showAlerts and bhiUp     ?   bhiBand - atrPlot   :   na,   'Buy: Hiband B',  shape.triangleup,     location.absolute,    alertColour,    size=size.tiny,     display=display.pane)
plotshape (showAlerts and cloUp     ?   cloBand - atrPlot   :   na,   'Buy: Loband C',  shape.triangleup,     location.absolute,    alertColour,    size=size.tiny,     display=display.pane)
plotshape (showAlerts and chiUp     ?   chiBand - atrPlot   :   na,   'Buy: Hiband C',  shape.triangleup,     location.absolute,    alertColour,    size=size.tiny,     display=display.pane)

plotshape (showAlerts and aloDn     ?   aloBand + atrPlot   :   na,   'Sell: Loband A', shape.triangledown,   location.absolute,    alertColour,    size=size.tiny,     display=display.pane)
plotshape (showAlerts and ahiDn     ?   ahiBand + atrPlot   :   na,   'Sell: Hiband A', shape.triangledown,   location.absolute,    alertColour,    size=size.tiny,     display=display.pane)
plotshape (showAlerts and bloDn     ?   bloBand + atrPlot   :   na,   'Sell: Loband B', shape.triangledown,   location.absolute,    alertColour,    size=size.tiny,     display=display.pane)
plotshape (showAlerts and bhiDn     ?   bhiBand + atrPlot   :   na,   'Sell: Hiband B', shape.triangledown,   location.absolute,    alertColour,    size=size.tiny,     display=display.pane)
plotshape (showAlerts and cloDn     ?   cloBand + atrPlot   :   na,   'Sell: Loband C', shape.triangledown,   location.absolute,    alertColour,    size=size.tiny,     display=display.pane)
plotshape (showAlerts and chiDn     ?   chiBand + atrPlot   :   na,   'Sell: Hiband C', shape.triangledown,   location.absolute,    alertColour,    size=size.tiny,     display=display.pane)


alertcondition  (ta.crossover   (sideMain, wmAri),                              '00: Side Above WAP',                 'UP SIGNAL:     Side Tracker Above WAP')
alertcondition  (ta.crossunder  (sideMain, wmHar),                              '00: Side Below WAP',                 'DOWN SIGNAL:   Side Tracker Below WAP')

alertcondition  (aloUp or ahiUp or bloUp or bhiUp or cloUp or chiUp,            '01: Side Above [Selected Bands]',    'UP SIGNAL:     Side Tracker Crossed Above Selected Band')
alertcondition  (aloDn or ahiDn or bloDn or bhiDn or cloDn or chiDn,            '01: Side Below [Selected Bands]',    'DOWN SIGNAL:   Side Tracker Crossed Below Selected Band')

alertcondition  (aloUp or ahiUp or bloUp or bhiUp or cloUp or chiUp or wapUp,   '02: Side Above [All Selected]',      'UP SIGNAL:     Side Tracker Crossed Above Selected Band / WAP')
alertcondition  (aloDn or ahiDn or bloDn or bhiDn or cloDn or chiDn or wapDn,   '02: Side Below [All Selected]',      'DOWN SIGNAL:   Side Tracker Crossed Below Selected Band / WAP')


