Macd indicator crossover code

0 32
Avatar for Sisiwit
3 years ago
Topics: Code, Programming, Python

Code Below

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

// © Sisiwit

//@version=4

study("MACD-X, More Than MACD by Sisiwit", shorttitle="MACD-X by Sisiwit")

macdType      = input("MACD-SOURCE", "MACD Calculation Method", 

                         options=["MACD-TRADITIONAL", 

                                  "MACD-HISTOGRAM",

                                  "MACD-LEADER", 

                                  "MACD-SOURCE",

                                  "MACD-TRIX"])

sourceType    = input("Current Price (close)", "Source", 

                         options=["Current Price (close)", 

                                  "Average of High, Low, and Close Price (hlc3)", 

                                  "On Balance Volume (obv)", 

                                  "Accumulation Distribution (accdist)", 

                                  "Price Volume Trend (pvt)"])

fast_length   = input(12,    "Fast Length", type=input.integer)

slow_length   = input(26,    "Slow Length", type=input.integer)

signal_length = input(9 ,    "Signal Smoothing", type=input.integer, minval = 1, maxval = 50)

dummy_1       = input(false, "═══════ ═════ ═══   Options   ═══ ═════ ═══════")

exponential   = input(true , "Use Exponential Moving Average")

macdTrdDisp   = input(false, "Add Traditional MACD (MACD-X will be auto Highlighted)")

var highlight = input(false, "Highlight MACD-X/Signal-X Area")

dispLabel     = input(false, "Display Label")

histLabel     = input(0,     "  Historical Label Readings", minval=0)

dummy_2       = input(false, "═══════ ═════ ═══   Add-Ons   ═══ ═════ ═══════")

dispSqueeze   = input(false, "► Display Squeeze Indicator Add-On ═════")

bbkcLength    = input(20,    "  SQZ : Bollinger Bands/Keltner's Channel Length", minval = 1)

bbMult        = input(2,     "  SQZ : Bollinger Bands MultFactor"  , type=input.float, step=0.25)

kcMult        = input(1.25,  "  SQZ : Keltner's Channel MultFactor", type=input.float, step=0.25)

colorRsi      = input(false, "► Change MACD Color when RSI Over[Bouht/Sold] Add-On ═════")

rsiLength     = input(14,    "  RSI : Length")

rsiOverBought = input(70,    "  RSI : Overbought Threshold", minval = 51, maxval = 99)

rsiOverSold   = input(30,    "  RSI : Oversold Threshold"  , minval = 1 , maxval = 49)

hstThesh      = input(false, "► Display Histogram Threshold Bands Add-On ═════")

stDevL        = input(1.75,  "  Threshold Bands: Lower Deviation" , type=input.float, minval = 0, step = .25, maxval = 5)

stDevH        = input(2.25,  "  Threshold Bands: Higher Deviation", type=input.float, minval = 0, step = .25, maxval = 5)

vbcb          = input(true,  "► Volume Based Colored Bars Add-On ═════")

vwcbLen       = input(21,    "  VWCB : Volume MA Length", minval=1)

vwcbUpper     = input(1.618, "  VWCB : Upper Theshold", minval = 0.1, step = .1)

vwcbLower     = input(.618,  "  VWCB : Lower Theshold", minval = 0.1, step = .1)

isBackTest    = input(true,  "═══════ ═ Backtest On/Off ═ ═══════")

// Functions ════════════════════════════════════════════════════════════════════════════════════ //

ma(s,l) => exponential ? ema(s,l) : sma(s,l)

// -Calculation ═════════════════════════════════════════════════════════════════════════════════ //

//------------------------------------------------------------------------------

// Source Selection

source = sourceType == "Current Price (close)" ? close : 

     sourceType == "Average of High, Low, and Close Price (hlc3)" ? hlc3 : 

     nz(volume) and sourceType == "On Balance Volume (obv)" ? obv : 

     nz(volume) and sourceType == "Accumulation Distribution (accdist)" ? accdist : 

     nz(volume) and sourceType == "Price Volume Trend (pvt)" ? pvt : na

//------------------------------------------------------------------------------

// MACD Calculations (macd, signal, histogram)

fast_ma = ma(source, fast_length)

slow_ma = ma(source, slow_length)

macd  = fast_ma - slow_ma

macdx = if macdType == "MACD-TRADITIONAL"

    macd

else if macdType == "MACD-HISTOGRAM"

    macd - ma(macd, signal_length)

else if macdType == "MACD-LEADER"

    macd + ma(source - fast_ma, fast_length) - ma(source - slow_ma, slow_length)

else if macdType == "MACD-SOURCE"

    ma(source - avg(fast_ma, slow_ma), signal_length)

else if macdType == "MACD-TRIX"

    10000 * change(ema(ema(ema(log(source), signal_length * 2), signal_length * 2), signal_length * 2))

signal  = ma(macd , signal_length)

signalx = ma(macdx, signal_length)

histx   = macdx - signalx

//------------------------------------------------------------------------------

// Highlight

highlight := macdTrdDisp ? true : highlight

//------------------------------------------------------------------------------

// RSI Calculation

rsiValue = colorRsi ? rsi(source, rsiLength) : na

//------------------------------------------------------------------------------

// TTM Squeeze Indicator Calculation

var bool inSqz = na, var bool noSqz = na, var bool unSqz = na

if dispSqueeze

    [_, bbUpper, bbLower] = bb(close, bbkcLength, bbMult)

    [_, kcUpper, kcLower] = kc(close, bbkcLength, kcMult, true)

    inSqz  := (bbLower > kcLower) and (bbUpper < kcUpper)

    noSqz  := (bbLower < kcLower) and (bbUpper > kcUpper)

    unSqz  := (inSqz == false) and (noSqz == false)

//------------------------------------------------------------------------------

// Theshold Bands Calculation with BB build-in function 

[_, upperL, lowerL] = if hstThesh

    bb(histx, 233, stDevL)

[_, upperH, lowerH] = if hstThesh

    bb(histx, 233, stDevH)

//------------------------------------------------------------------------------

// Volume Based Colored Bars by KIVANÇ ÖZBİLGİÇ

mean = sma(volume, vwcbLen)

[vbcbColor, vbcbTxt] = if close < open

    if volume > mean * vwcbUpper

        [#910000, "High Volume"]

    else if volume >= mean * vwcbLower and volume <= mean * vwcbUpper

        [color.red, "Average Volume"] 

    else 

        [color.orange, "Low Volume"]

else

    if volume > mean * vwcbUpper

        [#006400, "High Volume"]

    else if volume >= mean * vwcbLower and volume <= mean * vwcbUpper

        [color.green, "Average Volume"] 

    else 

        [#7FFFD4, "Low Volume"]

// -Color ═══════════════════════════════════════════════════════════════════════════════════════ //

histColor = histx >=0 ? 

     (histx[1] < histx ? #006400 : color.green) : 

     (histx[1] < histx ? color.red : #910000)

// -Label ═══════════════════════════════════════════════════════════════════════════════════════ //

//------------------------------------------------------------------------------

// Label Text

status   = histLabel > 0 ? "\n\nHistorical Bar Readings - " + tostring(histLabel) + " bar(s) earlier" : "\n\nCurrent Bar Readings"

msCross  = bar_index - valuewhen(cross(macdx, signalx), bar_index, 0)

macdMom  = change(histx) <= 0 ? "Falling - Last Signal Cross "  : "Growing - Last Signal Cross "

macdText = "Method : " + macdType + ", Source : " + sourceType + status + "\nMACD : " + macdMom + tostring(msCross) + " bar(s)"

rsiText  = colorRsi ? rsiValue > rsiOverBought ? "\nRSI : Value " + tostring(round(rsiValue)) + " - in OverBought Zone" : rsiValue < rsiOverSold ? "\nRSI : Value " + tostring(round(rsiValue)) + " - in OverSold Zone" : "\nRSI : Value " + tostring(round(rsiValue)) : na

sqzText  = dispSqueeze ? inSqz or unSqz ? "\nSQZ : No Trade Recommended" : histx >= 0 ? "\nSQZ : Buy Probability (macd > signal)" : "\nSQZ : Sell Probability (macd < signal)" : na

vbcbText = nz(volume) and vbcb ? "\nVolume : " + vbcbTxt + " (" + tostring(round(volume)) + ")" : na

// -Plot ════════════════════════════════════════════════════════════════════════════════════════ //

//------------------------------------------------------------------------------

// MACD - Signal - Histogram

plot(histx, "Histogram-X", color=histColor, style=plot.style_columns )

p1 = plot(macdx  , "MACD-X"  , color=rsiValue > rsiOverBought ? #910000 : rsiValue < rsiOverSold ? #006400 : #0094ff)

p2 = plot(signalx, "Signal-X", color=#ff6a00)

plot(macdTrdDisp ? macd   : na, "MACD"  , color=#0094ff)

plot(macdTrdDisp ? signal : na, "Signal", color=#ff6a00)

fill(p1, p2, color = highlight ? macdx > signalx ? rsiValue > rsiOverBought ? #910000 : rsiValue < rsiOverSold ? #006400 : #0094ff : rsiValue > rsiOverBought ? #910000 : rsiValue < rsiOverSold ? #006400 : #ff6a00 : na, transp = 55)

//------------------------------------------------------------------------------

// TTM Squeeze Indicator with MACD-X as Momentum Oscillator 

plotshape(dispSqueeze ? unSqz or inSqz       ? true : na : na, style=shape.diamond     , location=location.top, color=color.gray , title="In Squeeze")

plotshape(dispSqueeze ? noSqz and histx >= 0 ? true : na : na, style=shape.triangleup  , location=location.top, color=color.green, title="Squeeze Release")

plotshape(dispSqueeze ? noSqz and histx <  0 ? true : na : na, style=shape.triangledown, location=location.top, color=color.red  , title="Squeeze Release")

//------------------------------------------------------------------------------

// Label

if dispLabel and not isBackTest

    label macdLabel = label.new(time, 0, text=macdText[histLabel] + rsiText[histLabel] + sqzText[histLabel] + vbcbText[histLabel]

     ,tooltip="evaluation given herein does not constitute professional and/or financial advice"

     ,color=#0094ff, xloc=xloc.bar_time, style=label.style_label_left, textcolor=color.white, textalign=text.align_left)

    label.set_x(macdLabel, label.get_x(macdLabel) + round(change(time) * 3))

    label.delete(macdLabel[1])

//------------------------------------------------------------------------------

// Theshold Bands

bu2 = plot(upperL, "Lower Theshold Line - Overbought", display=display.none)

bu3 = plot(upperH, "Upper Theshold Line - Overbought", display=display.none)

fill(bu2, bu3, color=color.red,   transp=85, title="Overbought Background")

bl2 = plot(lowerL, "Upper Theshold Line - Oversold"  , display=display.none)

bl3 = plot(lowerH, "Lower Theshold Line - Oversold"  , display=display.none)

fill(bl2, bl3, color=color.green, transp=85, title="Oversold Background")

//------------------------------------------------------------------------------

// Volume Based Colored Bars by KIVANÇ ÖZBİLGİÇ

barcolor(nz(volume) and vbcb ? vbcbColor : na, title = "Volume Based Colored Bars by [KıvançÖZBİLGİÇ]")

//------------------------------------------------------------------------------

// Alert : macdx and signalx crosses

alarm = cross(macdx, signalx)

alertcondition(barstate.islast ? alarm[1] : alarm, title="Trading Opportunity", message="Probable Trade Opportunity\n{{exchange}}:{{ticker}}->\nPrice = {{close}},\nTime = {{time}}")

// -Backtest ==================================================================================== //

dasCapital   = input(1000., "initial capital")

stopLoss     = input(1.,    "Stop Loss %", step=.1) / 100

lenBckTst    = input(1,     "Backtest Period (Year)", step = .25)

srcInOut     = input(close, "Source : Entry/Exit Price Assumption")

lblInOutSL   = input(true,  "Show Entry/Take Profit(Exit)/Stop Loss Labels")

startBckTst  = time > timenow - lenBckTst * 31556952000 

var inTrade    = false

var entryPrice = 0. 

var exitPrice  = 0. 

    

if isBackTest

    var capital    = dasCapital

    var trades     = 0

    var win        = 0

    var loss       = 0

    crossover  = crossover (macdx, signalx)

    crossunder = crossunder(macdx, signalx)

    

    longCondition  = barstate.islast ? crossover [1] : crossover

    shortCondition = barstate.islast ? crossunder[1] : crossunder

    stopLossCondition = inTrade ? close < entryPrice * (1 - stopLoss) : 0

    if startBckTst and longCondition and not inTrade

        entryPrice := srcInOut

        inTrade    := true

        trades     := trades + 1

    

        if lblInOutSL

            label longLabel = label.new(bar_index, signalx, text="L"

             ,tooltip="entry price  : " + tostring(entryPrice) + "\nentry value : " + tostring(capital, "#.##")

             ,color=color.green, style=label.style_label_up, textcolor=color.white, textalign=text.align_center, size=size.tiny)

    if (shortCondition or stopLossCondition) and inTrade

        exitPrice  := srcInOut

        inTrade    := false

        capital    := capital * (exitPrice / entryPrice)

        if exitPrice > entryPrice

            win    := win  + 1

        else

            loss   := loss + 1

    

        if lblInOutSL

            txt = stopLossCondition ? "SL" : "TP"

            label shortLabel = label.new(bar_index, signalx, text=txt

                 ,tooltip="change .......... : " + tostring((exitPrice / entryPrice - 1) * 100, "#.##") + "%\nentry/exit price : " + tostring(entryPrice) + " / " + tostring(exitPrice) + "\nnew capital ..... : " + tostring(capital, "#.##")

                 ,color=color.red, style=label.style_label_down, textcolor=color.white, textalign=text.align_center, size=size.tiny)

    var years    = (timenow - time) / 31556952000

    var yearsTxt = ""

    var remarks  = ""

    if years < lenBckTst

        lenBckTst := years

        yearsTxt  := tostring(lenBckTst, "#.##") + " Years***"

        remarks   := "\n\n*   trade statistics for longs entries only\n  final value, if trade active displays estimated final value\n* max available data for selected timeframe : # of bars - " + tostring(bar_index)

    else

        yearsTxt  := tostring(lenBckTst, "#.##") + " Year(s)"

        remarks   := "\n\n*   trade statistics for longs entries only\n**  final value, if trade open displies estimated final value"

    inTradeTxt = inTrade ? "inTrade" : "not inTrade"

    estimated  = inTrade ? capital * (close / entryPrice) : capital

    entryTxt   = inTrade ? tostring(entryPrice) : "not inTrade"

    lastTrdTxt = inTrade ? ", Gain/Loss " + tostring((estimated/capital - 1) * 100, "#.##") + "%, Stop Loss " + tostring(entryPrice * (1 - stopLoss)) : ""

    tooltipTxt = macdText[histLabel] + rsiText[histLabel] + sqzText[histLabel] + vbcbText[histLabel] +

     "\nps: evaluation given herein does not constitute professional and/or financial advice" +

     "\n\nBacktest :\nentires/exit caclulations\n" + 

     "-long entry , when macdx crosses above signal line\n" +

     "-take profit, when macdx crosses below signal line\n" +

     "-stop loss if last value falls by " + tostring(stopLoss * 100) + "% of entry price" + remarks

    label indiLabel = label.new(time, 0 

         ,text="☼☾ Trade Statistics*, Trade Period - " + yearsTxt +

          "\nMethod/Source : " + macdType + " / " + sourceType +

          "\n═════════════════════════════════════" +

          "\nSuccess Ratio ...... : " + tostring((win/trades)*100, "#") + "%" + ", # of Trades - " + tostring(trades) + ", Win/Loss - " + tostring(win) + "/" + tostring(loss) +

          "\nGain/Loss % ........ : " + tostring((estimated/dasCapital - 1) * 100, "#") + "%" + ", Initial/Final Value** - " + tostring(dasCapital) + " / " + tostring(estimated, "#") +

          "\n\nCurrent TradeStatus - " + inTradeTxt + lastTrdTxt +

          "\n═════════════════════════════════════" +

          "\nEntry Price/Value . : " + entryTxt + " / " + tostring(capital, "#.##") + " " + inTradeTxt +

          "\nLast Price/Value ... : " + tostring(close) + " / " + tostring(estimated , "#.##") + " " + inTradeTxt

         ,tooltip=tooltipTxt

         ,color=inTrade ? estimated/dasCapital > 1 ? color.teal : color.maroon : color.gray, xloc=xloc.bar_time, style=label.style_label_left, textcolor=color.white, textalign=text.align_left)

    label.set_x(indiLabel, label.get_x(indiLabel) + round(change(time) * 3))

    label.delete(indiLabel[1])

bgcolor(startBckTst and startBckTst != startBckTst[1] ? color.blue : na, title="Backtest Starting Bar")

1
$ 0.00
Avatar for Sisiwit
3 years ago
Topics: Code, Programming, Python

Comments