Adaptive Fisherized CMO
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © simwai

//@version=5
indicator('Adaptive Fisherized CMO', 'AF_CMO', false)

// -- Input --
string signalMode = input.string('MA', 'Choose Signal Mode', options=['Overbought/Oversold', 'Zero Line', 'MA', 'MA Overbought/Oversold', 'None'], group='General', inline='1') 
bool areAdditionalExitsEnabled = input.bool(true, 'Enable Additional Exits', tooltip='Exits on MA Cross', group='General', inline='2')
bool isInnerBgEnabled = input.bool(true, 'Enable Inner Background Plot', tooltip='Between outer and inner band', group='General', inline='3')
bool isOuterBgEnabled = input.bool(true, 'Enable Outer Background Plot', tooltip='Between outer band and CMO', group='General', inline='3')
bool areColorsReversed = input.bool(false, 'Enable Oversold/Overbought Color Reversion', group='General', inline='4')

bool isTrendFilterEnabled = input.bool(true, 'Enable KAMA Trend Filter', group='Trend Filter', inline='1')
bool isTrendPlotEnabled = input.bool(false, 'Enable KAMA Trend Plot', group='Trend Filter', inline='1')
string kamaTimeframe = input.timeframe('240', 'Choose Timeframe', group='Trend Filter', inline='2')
int kamaLength = input.int(89, 'KAMA Length', group='Trend Filter', inline='3')
int kamaLookback = input.int(3, 'KAMA Lookback', group='Trend Filter', inline='3')

string resolution = input.timeframe(defval='', title='Resolution', group='CMO', inline='1')
int min = input.int(defval=34, minval=2, title='Min Length', group='CMO', inline='2', tooltip='Used as min length for adaptive mode')
int cmoLength = input.int(defval=100, minval=2, title='Length', group='CMO', inline='2', tooltip='Used as length for CMO or max length when adaptive mode is enabled')
float lowerBandValue = input.float(-0.5, 'Lower Band', group='CMO', inline='3')
float upperBandValue = input.float(0.5, 'Upper Band', group='CMO', inline='3')
bool isFisherized = input.bool(defval=false, title='Enable Fisherization', group='CMO', inline='4')
string adaptiveMode = input.string('Homodyne Discriminator', 'Choose Adaptive Mode', options=['Inphase-Quadrature Transform', 'Median', 'Homodyne Discriminator', 'None'], group='CMO', inline='5')

bool isMaPlotEnabled = input.bool(true, 'Enable MA Plot', inline='1')
string maType = input.string(defval='T3', title='Choose MA Type', options=['SMA', 'SMMA', 'T3', 'VWMA'], group='MA', inline='2')
int maLength = input.int(13, title='Length', group='MA', inline='2')
float t3Hot = input.float(title='T3 Smoothing Factor', defval=0.5, minval=0.00001, maxval=1, step=0.1, group='MA', inline='3', tooltip='Called hot in code')
string t3Type = input.string(title='T3 Type', defval='Normal', options=['Normal', 'New'], group='MA', inline='3')

bool isHannWindowPriceSmoothingEnabled = input.bool(true, 'Enable Hann Window Price Smoothing', group='Smoothing', inline='1')
int hannWindowLength = input.int(3, 'Hann Window Length', minval=2, group='Smoothing', inline='2')

bool isNetEnabled = input.bool(true, 'Enable NET', group='Smoothing', inline='3', tooltip='Ehlers Noise Elmimination Technique')
int netLength = input.int(9, 'NET Length', minval=2, group='Smoothing', inline='4')

// -- Colors --
color maximumYellowRed = color.rgb(255, 203, 98) // yellow
color rajah = color.rgb(242, 166, 84) // orange
color magicMint = color.rgb(171, 237, 198)
color lightPurple = color.rgb(193, 133, 243)
color languidLavender = color.rgb(232, 215, 255)
color maximumBluePurple = color.rgb(181, 161, 226)
color skyBlue = color.rgb(144, 226, 244)
color lightGray = color.rgb(214, 214, 214)
color quickSilver = color.rgb(163, 163, 163)
color mediumAquamarine = color.rgb(104, 223, 153)
color carrotOrange = color.rgb(239, 146, 46)

color transpGray = color.new(lightGray, 50)
color transpMagicMint = color.new(magicMint, 50)
color transpRajah = color.new(rajah, 50)
color transpMaximumYellowRed = color.new(maximumYellowRed, 50)

// -- Global States --
[src, _volume] = request.security(syminfo.tickerid, resolution, [close[1], volume[1]], barmerge.gaps_off, barmerge.lookahead_on)
float kamaClose = request.security(syminfo.tickerid, kamaTimeframe, close[1], barmerge.gaps_off, barmerge.lookahead_on)

// -- Functions --
// Chande Momentum Oscillator (CMO)
f1(m) => m >= 0.0 ? m : 0.0
f2(m) => m >= 0.0 ? 0.0 : -m
percent(nom, div) => 100 * nom / div

cmo(float _src, int _cmoLength) =>
    if (bar_index > _cmoLength)
        float mommOut = ta.change(_src)
        float m1 = f1(mommOut)
        float m2 = f2(mommOut)
        float sm1 = math.sum(m1, _cmoLength)
        float sm2 = math.sum(m2, _cmoLength)
        float cmo = percent(sm1 - sm2, sm1 + sm2)

// Apply normalization
normalize(float _src, int _min, int _max) =>
    var float _historicMin = 1.0
    var float _historicMax = -1.0
    _historicMin := math.min(nz(_src, _historicMin), _historicMin)
    _historicMax := math.max(nz(_src, _historicMax), _historicMax)
    _min + (_max - _min) * (_src - _historicMin) / math.max(_historicMax - _historicMin, 1)

// Inverse Fisher Transformation (IFT)
fisherize(float _value) => (math.exp(2 * _value) - 1) / (math.exp(2 * _value) + 1)

// Convert length to alpha
getAlpha(float _length) => 2 / (_length + 1)

// Get dominant cyber cycle – Median – Credits to @blackcat1402
getMedianDc(float Price, float alpha=0.07, simple float CycPart=0.5) =>
    Smooth = 0.00
    Cycle = 0.00
    Q1 = 0.00
    I1 = 0.00
    DeltaPhase = 0.00
    MedianDelta = 0.00
    DC = 0.00
    InstPeriod = 0.00
    Period = 0.00
    I2 = 0.00
    Q2 = 0.00
    IntPeriod = 0

    Smooth := (Price + 2 * nz(Price[1]) + 2 * nz(Price[2]) + nz(Price[3])) / 6
    Cycle := (1 - .5 * alpha) * (1 - .5 * alpha) * (Smooth - 2 * nz(Smooth[1]) + nz(Smooth[2])) + 2 * (1 - alpha) * nz(Cycle[1]) - (1 - alpha) * (1 - alpha) * nz(Cycle[2])
    Cycle := bar_index < 7 ? (Price - 2 * nz(Price[1]) + nz(Price[2])) / 4 : Cycle

    Q1 := (.0962 * Cycle + .5769 * nz(Cycle[2]) - .5769 * nz(Cycle[4]) - .0962 * nz(Cycle[6])) * (.5 + .08 * nz(InstPeriod[1]))
    I1 := nz(Cycle[3])
    DeltaPhase := Q1 != 0 and nz(Q1[1]) != 0 ? (I1 / Q1 - nz(I1[1]) / nz(Q1[1])) / (1 + I1 * nz(I1[1]) / (Q1 * nz(Q1[1]))) : DeltaPhase
    DeltaPhase := DeltaPhase < 0.1 ? 0.1 : DeltaPhase
    DeltaPhase := DeltaPhase > 1.1 ? 1.1 : DeltaPhase

    MedianDelta := ta.median(DeltaPhase, 5)
    DC := MedianDelta == 0.00 ? 15.00 : 6.28318 / MedianDelta + .5
    InstPeriod := .33 * DC + .67 * nz(InstPeriod[1])
    Period := .15 * InstPeriod + .85 * nz(Period[1])
    
    IntPeriod := math.round(Period * CycPart) < 1 ? 1 : math.round(Period * CycPart)
    IntPeriod

// Get dominant cyber cycle – Inphase-Quadrature -- Credits to @DasanC
getIQ(float src, int min, int max) =>
    PI = 3.14159265359
    P = src - src[7]
    lenIQ = 0.0
    lenC = 0.0
    imult = 0.635
    qmult = 0.338
    inphase = 0.0
    quadrature = 0.0
    re = 0.0
    im = 0.0
    deltaIQ = 0.0
    instIQ = 0.0
    V = 0.0

    inphase := 1.25 * (P[4] - imult * P[2]) + imult * nz(inphase[3])
    quadrature := P[2] - qmult * P + qmult * nz(quadrature[2])
    re := 0.2 * (inphase * inphase[1] + quadrature * quadrature[1]) + 0.8 * nz(re[1])
    im := 0.2 * (inphase * quadrature[1] - inphase[1] * quadrature) + 0.8 * nz(im[1])
    if re != 0.0
        deltaIQ := math.atan(im / re)
        deltaIQ
    for i = 0 to max by 1
        V += deltaIQ[i]
        if V > 2 * PI and instIQ == 0.0
            instIQ := i
            instIQ
    if instIQ == 0.0
        instIQ := nz(instIQ[1])
        instIQ
    lenIQ := 0.25 * instIQ + 0.75 * nz(lenIQ[1], 1)
    length = lenIQ < min ? min : lenIQ > max ? max : lenIQ
    math.round(length)

// Get Dominant Cyber Cycle - Homodyne Discriminator With Hilbert Dominant Cycle – Credits to @blackcat1402
getHdDc(float Price, int min, int max, simple float CycPart = 0.5) =>
    Smooth = 0.00
    Detrender = 0.00
    I1 = 0.00
    Q1 = 0.00
    jI = 0.00
    jQ = 0.00
    I2 = 0.00
    Q2 = 0.00
    Re = 0.00
    Im = 0.00
    Period = 0.00
    SmoothPeriod = 0.00
    pi = 2 * math.asin(1)
    DomCycle = 0.0

    // Hilbert Transform
    Smooth := bar_index > 7 ? (4 * Price + 3 * nz(Price[1]) + 2 * nz(Price[2]) + nz(Price[3])) / 10 : Smooth
    Detrender := bar_index > 7 ? (.0962 * Smooth + .5769 * nz(Smooth[2]) - .5769 * nz(Smooth[4]) - .0962 * nz(Smooth[6])) * (.075 * nz(Period[1]) + .54) : Detrender
    // Compute InPhase and Quadrature components
    Q1 := bar_index > 7 ? (.0962 * Detrender + .5769 * nz(Detrender[2]) - .5769 * nz(Detrender[4]) - .0962 * nz(Detrender[6])) * (.075 * nz(Period[1]) + .54) : Q1
    I1 := bar_index > 7 ? nz(Detrender[3]) : I1

    // Advance the phase of I1 and Q1 by 90 degrees
    jI := (.0962 * I1 + .5769 * nz(I1[2]) - .5769 * nz(I1[4]) - .0962 * nz(I1[6])) * (.075 * nz(Period[1]) + .54)
    jQ := (.0962 * Q1 + .5769 * nz(Q1[2]) - .5769 * nz(Q1[4]) - .0962 * nz(Q1[6])) * (.075 * nz(Period[1]) + .54)

    // Phasor addition for 3 bar averaging
    I2 := I1 - jQ
    Q2 := Q1 + jI

    // Smooth the I and Q components before applying the discriminator
    I2 := .2 * I2 + .8 * nz(I2[1])
    Q2 := .2 * Q2 + .8 * nz(Q2[1])

    // Homodyne Discriminator
    Re := I2 * nz(I2[1]) + Q2 * nz(Q2[1])
    Im := I2 * nz(Q2[1]) - Q2 * nz(I2[1])
    Re := .2 * Re + .8 * nz(Re[1])
    Im := .2 * Im + .8 * nz(Im[1])

    Period := Im != 0 and Re != 0 ? 2 * pi / math.atan(Im / Re) : Period
    Period := Period > 1.5 * nz(Period[1]) ? 1.5 * nz(Period[1]) : Period
    Period := Period < .67 * nz(Period[1]) ? .67 * nz(Period[1]) : Period

    Period := Period < min ? min : Period
    Period := Period > max ? max : Period
    Period := .2 * Period + .8 * nz(Period[1])
    SmoothPeriod := .33 * Period + .67 * nz(SmoothPeriod[1])

    DomCycle := math.ceil(CycPart * SmoothPeriod) < 1 ? 1 : math.ceil(CycPart * SmoothPeriod)

    // Limit dominant cycle
    DomCycle := DomCycle < min ? min : DomCycle > max ? max : DomCycle
    math.round(DomCycle)

// Noise Elimination Technology (NET) – Credits to @blackcat1402
doNet(float _series, simple int _smoothingLength, int _lowerBand=-1, int _upperBand=1) =>
    var netX = array.new_float(102)
    var netY = array.new_float(102)
    num = 0.00 
    denom = 0.00 
    net = 0.00
    trigger = 0.00

    for count = 1 to _smoothingLength 
        array.set(netX, count, nz(_series[count - 1]))
        array.set(netY, count, -count)

    num := 0

    for count = 2 to _smoothingLength 
        for k = 1 to count - 1 
            num := num - math.sign(nz(array.get(netX, count)) - nz(array.get(netX, k)))
    denom := 0.5 * _smoothingLength * (_smoothingLength - 1)
    net := num / denom
    trigger := 0.05 + 0.9 * nz(net[1]) 
    trigger := normalize(trigger, _lowerBand, _upperBand)

// Hann Window Smoothing – Credits to @cheatcountry
doHannWindow(float _series, float _hannWindowLength) =>
    sum = 0.0, coef = 0.0
    for i = 1 to _hannWindowLength
        cosine = 1 - math.cos(2 * math.pi * i / (_hannWindowLength + 1))
        sum := sum + (cosine * nz(_series[i - 1]))
        coef := coef + cosine
    h = coef != 0 ? sum / coef : 0

// T3 – Credits to @loxx
t3(float _src, float _length, float hot=1, string clean='T3')=>
    a = hot
    _c1 = -a * a * a
    _c2 = 3 * a * a + 3 * a * a * a
    _c3 = -6 * a * a - 3 * a - 3 * a * a * a
    _c4 = 1 + 3 * a + a * a * a + 3 * a * a
    
    alpha = 0.
    
    if (clean == 'T3 New')
        alpha := 2.0 / (2.0 + (_length - 1.0) / 2.0)
    else 
        alpha := 2.0 / (1.0 + _length)

    _t30 = _src, _t31 = _src
    _t32 = _src, _t33 = _src
    _t34 = _src, _t35 = _src
    
    _t30 := nz(_t30[1]) + alpha * (_src -  nz(_t30[1]))
    _t31 := nz(_t31[1]) + alpha * (_t30 - nz(_t31[1]))
    _t32 := nz(_t32[1]) + alpha * (_t31 - nz(_t32[1]))
    _t33 := nz(_t33[1]) + alpha * (_t32 - nz(_t33[1]))
    _t34 := nz(_t34[1]) + alpha * (_t33 - nz(_t34[1]))
    _t35 := nz(_t35[1]) + alpha * (_t34 - nz(_t35[1]))
    out =
         _c1 * _t35 + _c2 * _t34 +
         _c3 * _t33 +  _c4 * _t32
    out

// Simple Moving Average (SMA)
sma(float _src, int _period) =>
    sum = 0.0
    for i = 0 to _period - 1
        sum := sum + _src[i] / _period
    sum

// Standard Deviation
isZero(val, eps) => math.abs(val) <= eps

sum(fst, snd) =>
    EPS = 1e-10
    res = fst + snd
    if isZero(res, EPS)
        res := 0
    else
        if not isZero(res, 1e-4)
            res := res
        else
            15

stdev(src, length) =>
    avg = sma(src, length)
    sumOfSquareDeviations = 0.0
    for i = 0 to length - 1
        sum = sum(src[i], - avg)
        sumOfSquareDeviations := sumOfSquareDeviations + sum * sum

    stdev = math.sqrt(sumOfSquareDeviations / length)

// Measure of difference between the series and it's ma
dev(float source, int length, float ma) =>
    mean = sma(source, length)
    sum = 0.0
    for i = 0 to length - 1
        val = source[i]
        sum := sum + math.abs(val - mean)
    dev = sum/length

// Exponential Moving Average (EMA)
ema(float _src, int _period) =>
    alpha = 2 / (_period + 1)
    sum = 0.0
    sum := na(sum[1]) ? sma(_src, _period) : alpha * _src + (1 - alpha) * nz(sum[1])

// Smoothed Moving Average (SMMA)
smma(float _src, int _period) =>
    tmpSMA = sma(_src, _period)
    tmpVal = 0.0
    tmpVal := na(tmpVal[1]) ? tmpSMA : (tmpVal[1] * (_period - 1) + _src) / _period

// Kaufman's Adaptive Moving Average (KAMA)
kama(float _src, int _period) =>
    if (bar_index > _period)
        tmpVal = 0.0
        tmpVal := nz(tmpVal[1]) +  math.pow(((math.sum(math.abs(_src - _src[1]), _period) != 0) ? (math.abs(_src - _src[_period]) / math.sum(math.abs(_src - _src[1]), _period)) : 0) * (0.666 - 0.0645) + 0.0645, 2) * (_src - nz(tmpVal[1]))
        tmpVal

// Volume Weighted Moving Averga (VWMA)
vwma(float _src, int _period) =>
    sma(_src * _volume, _period) / sma(_volume, _period)

ma(float source, int length, string type) =>
    float ma = switch type
        'SMA' => sma(source, length)
        'EMA' => ema(source, length)
        'SMMA' => smma(source, length)
        'VWMA' => vwma(source, length)
        'T3' => t3(source, length, t3Hot, t3Type)
        => source

// -- CMO Calculation --
if (isHannWindowPriceSmoothingEnabled)
    src := doHannWindow(src, hannWindowLength)

int _cmoLength = switch adaptiveMode
    'Inphase-Quadrature Transform' => getIQ(src, min, cmoLength)
    'Median' => getMedianDc(src, getAlpha(cmoLength)),
    'Homodyne Discriminator' => getHdDc(src, min, cmoLength)
    => cmoLength

if (_cmoLength > min and adaptiveMode != 'None')
    cmoLength := min

float cmo = cmo(src, _cmoLength)
float cmoMa = ma(cmo, maLength, maType)

if (isFisherized)
    cmo := fisherize(cmo)
    cmoMa := fisherize(cmoMa)
else
    cmo := normalize(cmo, -1, 1)
    cmoMa := normalize(cmoMa, -1, 1)

if (isNetEnabled)
    cmo := doNet(cmo, netLength)
    cmoMa := doNet(cmoMa, netLength)

bool cmoLong = cmo >= 0
bool cmoShort = cmo < 0

float upperLevel = upperBandValue
float lowerLevel = lowerBandValue

plot(isMaPlotEnabled ? cmoMa : na, 'CMO MA', skyBlue)

topBand = plot(1, 'Top Band', color=transpGray)
upperBand = plot(upperLevel, 'Upper Band', color=transpGray)
zeroLine = plot(0, 'Zero Line', color=transpGray)
lowerBand = plot(lowerLevel, 'Lower Band', color=transpGray)
bottomBand = plot(-1, 'Bottom Band', color=transpGray)
cmoPlot = plot(cmo, title='CMO', color=languidLavender)

fill(zeroLine, upperBand, color=not isTrendPlotEnabled and isInnerBgEnabled ? ((cmo > 0) ? (areColorsReversed ? transpMagicMint : transpRajah) : na) : na)
fill(upperBand, topBand, color=not isTrendPlotEnabled and isOuterBgEnabled ? (cmo >= upperLevel ? (areColorsReversed ? color.new(magicMint, 75) : color.new(rajah, 75)) : na) : na)
fill(zeroLine, lowerBand, color=not isTrendPlotEnabled and isInnerBgEnabled ? ((cmo < 0) ? (areColorsReversed ? transpRajah : transpMagicMint) : na) : na)
fill(lowerBand, bottomBand, color=not isTrendPlotEnabled and isOuterBgEnabled ? (cmo < lowerLevel ? (areColorsReversed ? color.new(rajah, 75) : color.new(magicMint, 75)) : na) : na)

bool enterLong = false
bool enterShort = false
bool exitLong = false
bool exitShort = false

// KAMA Trend Detection
float kama = kama(kamaClose, kamaLength)

float trendSensitivity = syminfo.mintick / 5
bool isKamaSide = math.abs(kama[kamaLookback] - kama) < trendSensitivity
bool isKamaUp = (not isKamaSide) and kama[kamaLookback] < kama 
bool isKamaDown = (not isKamaSide) and kama[kamaLookback] > kama

fill(upperBand, zeroLine, isTrendPlotEnabled ? (isKamaSide ? color.new(maximumYellowRed, 50) : isKamaUp ? color.new(mediumAquamarine, 50) : isKamaDown ? maximumBluePurple : na) : na)
fill(lowerBand, zeroLine, isTrendPlotEnabled ? (isKamaSide ? color.new(maximumYellowRed, 50) : isKamaDown ? color.new(maximumBluePurple, 50) : isKamaUp ? mediumAquamarine : na) : na)

var string openTrade = ''
var string signalCache = ''

if (signalMode == 'Overbought/Oversold')
    enterLong := ta.crossover(cmo, lowerLevel)
    enterShort := ta.crossunder(cmo, upperLevel)
    exitLong := enterShort
    exitShort := enterLong
if (signalMode == 'MA')
    enterLong := ta.crossover(cmo, cmoMa)
    enterShort := ta.crossunder(cmo, cmoMa)
    exitLong := enterShort
    exitShort := enterLong
if (signalMode == 'Zero Line')
    enterLong := ta.crossover(cmo, 0)
    enterShort := ta.crossunder(cmo, 0)
    exitLong := enterShort
    exitShort := enterLong
if (signalMode == 'MA Overbought/Oversold')
    enterLong := ta.crossover(cmo, cmoMa) and cmo < lowerLevel
    enterShort := ta.crossunder(cmo, cmoMa) and cmo > upperLevel
    exitLong := enterShort
    exitShort := enterLong

exitLong := areAdditionalExitsEnabled and (exitLong or ta.cross(cmoMa, cmo))
exitShort := areAdditionalExitsEnabled and (exitShort or ta.cross(cmoMa, cmo))

// -- Signal Cache --
// It shouldn't happen that multiple signals are executed in one instance
// The cache tries to order the signals correctly

if (isTrendFilterEnabled)
    if (isKamaUp and enterShort)
        enterShort := false
    if (isKamaDown and enterLong)
        enterLong := false
    if (isKamaSide and (enterLong or enterShort))
        enterShort := false
        enterLong := false
    if (openTrade == 'long' and isKamaDown)
        exitLong := true
    if (openTrade == 'short' and isKamaUp)
        exitShort := true

if (signalCache == 'long entry')
    signalCache := ''
    enterLong := true
else if (signalCache == 'short entry')
    signalCache := ''
    enterShort := true

if (openTrade == '')
    if (exitShort and (not enterLong))
        exitShort := false
    if (exitLong and (not enterShort))
        exitLong := false

    if (enterLong and exitShort)
        openTrade := 'long'
        exitShort := false
    else if (enterShort and exitLong)
        openTrade := 'short'
        exitLong := false
    else if (enterLong)
        openTrade := 'long'
    else if (enterShort)
        openTrade := 'short'
else if (openTrade == 'long')
    if (exitShort)
        exitShort := false
    if (enterLong)
        enterLong := false
    if (enterShort and not exitLong)
        exitLong := true
        signalCache := 'short entry'

    if (enterShort and exitLong)
        enterShort := false
        signalCache := 'short entry'
    if (exitLong)
        openTrade := ''
else if (openTrade == 'short')
    if (exitLong)
        exitLong := false
    if (enterShort)
        enterShort := false
    if (enterLong and not exitShort)
        exitShort := true
        signalCache := 'long entry'

    if (enterLong and exitShort)
        enterLong := false
        signalCache := 'long entry'
    if (exitShort)
        openTrade := ''

plotshape(enterLong ? -1.2 : na, title='BUY', style=shape.triangleup, color=magicMint, size=size.tiny, location=location.absolute)
plotshape(enterShort ? 1.2 : na, title='SELL', style=shape.triangledown, color=rajah, size=size.tiny, location=location.absolute)
plotshape(exitLong ? -1.2 : na, title='BE', style=shape.circle, color=mediumAquamarine, size=size.tiny, location=location.absolute)
plotshape(exitShort ? 1.2 : na, title='SE', style=shape.circle, color=carrotOrange, size=size.tiny, location=location.absolute)

alertcondition(enterLong, title='ENTER LONG', message='CMO – ENTER LONG')
alertcondition(exitLong, title='EXIT LONG', message='CMO – EXIT LONG')
alertcondition(enterShort, title='ENTER SHORT', message='CMO – ENTER SHORT')
alertcondition(exitShort, title='EXIT SHORT', message='CMO – EXIT SHORT')