Dynamic Price Swing
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
//@version=4

//**********************************************************************************************************
// Gradient Color Bars incorporated based on Color Gradient Function script by e2e4mfck
//**********************************************************************************************************


// ██████╗██████╗ ███████╗ █████╗ ████████╗███████╗██████╗     ██████╗ ██╗   ██╗    
//██╔════╝██╔══██╗██╔════╝██╔══██╗╚══██╔══╝██╔════╝██╔══██╗    ██╔══██╗╚██╗ ██╔╝                       
//██║     ██████╔╝█████╗  ███████║   ██║   █████╗  ██║  ██║    ██████╔╝ ╚████╔╝                        
//██║     ██╔══██╗██╔══╝  ██╔══██║   ██║   ██╔══╝  ██║  ██║    ██╔══██╗  ╚██╔╝                         
//╚██████╗██║  ██║███████╗██║  ██║   ██║   ███████╗██████╔╝    ██████╔╝   ██║                          
// ╚═════╝╚═╝  ╚═╝╚══════╝╚═╝  ╚═╝   ╚═╝   ╚══════╝╚═════╝     ╚═════╝    ╚═╝                          
                                                                                                     
//███████╗ ██████╗ ██╗     ██╗   ██╗████████╗██╗ ██████╗ ███╗   ██╗███████╗ ██╗ █████╗ ███████╗ █████╗ 
//██╔════╝██╔═══██╗██║     ██║   ██║╚══██╔══╝██║██╔═══██╗████╗  ██║██╔════╝███║██╔══██╗╚════██║██╔══██╗
//███████╗██║   ██║██║     ██║   ██║   ██║   ██║██║   ██║██╔██╗ ██║███████╗╚██║╚██████║    ██╔╝╚█████╔╝
//╚════██║██║   ██║██║     ██║   ██║   ██║   ██║██║   ██║██║╚██╗██║╚════██║ ██║ ╚═══██║   ██╔╝ ██╔══██╗
//███████║╚██████╔╝███████╗╚██████╔╝   ██║   ██║╚██████╔╝██║ ╚████║███████║ ██║ █████╔╝   ██║  ╚█████╔╝
//╚══════╝ ╚═════╝ ╚══════╝ ╚═════╝    ╚═╝   ╚═╝ ╚═════╝ ╚═╝  ╚═══╝╚══════╝ ╚═╝ ╚════╝    ╚═╝   ╚════╝ 
                                                                                                     

strategy(shorttitle='DPS',title='Dynamic Price Swing', overlay=true, initial_capital = 1000, process_orders_on_close=false, close_entries_rule="ANY", default_qty_type = strategy.percent_of_equity, default_qty_value = 100, commission_type=strategy.commission.percent, commission_value=0.18, calc_on_every_tick=false)


// ————— Constants
var string SH1 = "Red ⮀ Green"
var string SH2 = "Purple ⮀ Blue"
var string SH3 = "Yellow ⮀  DarkGreen"
var string SH4 = "White ⮀ Black"
var string SH5 = "White ⮀ Blue"
var string SH6 = "White ⮀ Red"
var string SH7 = "Rainbow"

bgcolor(color.new(#000000,15), title="Dark Background")
white = color.new(color.white, 50)



// -----------------  Strategy Inputs -------------------------------------------------------------

//Instructions
general = input(false, "Backtest Dates, Strategy Selection, and Risk Management Inputs apply to all strategies")

//Backtest dates with auto finish date of today
start = input(defval = timestamp("21 June 2021 00:00 -0500"), title = "Start Time", type = input.time, group="Backtest Dates")
finish = input(defval = timestamp("31 December 2021 00:00 -0600"), title = "End Time", type = input.time, group="Backtest Dates")
window()  => time >= start and time <= finish ? true : false       // create function "within window of time"

// Strategy Selection - Long, Short, or Both
general2 = input(false, "Average Price Channel strategy buys and sells when price crosses above or below the previous highest high and lowest low", group="Strategy Descriptions")
general3 = input(false, "Moving Average strategy buys and sells when the price crosses above or below the selected price band, which also is shaded based on what you select.", group="Strategy Descriptions")
general4 = input(false, "Fibonacci strategy buys and sells when the price crosses above the Fibonacci level selected.", group="Strategy Descriptions")
general5 = input(false, "Peaks and Valleys buys and sells based on the combined crossing of the VWMA, ALMA, and Average MACD True Range trend lines.", group="Strategy Descriptions")
general5b = input(false, "The settings for each strategy is grouped. Only the inputs indicated for the selected strategy will impact the triggers.", group="Strategy Descriptions")
general5c = input(false, "All strategies use the Risk Management and Up/Down Trend Settings.", group="Strategy Descriptions")
trigger = input ("Average Price Channel", "Select a Price Swing Trigger", options=["Average Price Channel", "Moving Average", "Fibonacci", "Peaks and Valleys"], group="Strategy Selection")
usePrice = trigger=="Average Price Channel" ? true : false
useMA = trigger == "Moving Average" ? true : false
useFib = trigger == "Fibonacci" ? true : false
usePV = trigger == "Peaks and Valleys" ? true : false
general6 = input(false, "Use Long/Short only for backtest comparisons. Long is if you are starting with FIAT, Short is if you are starting with crypto.", group="Strategy Selection")
strat = input(title="Trade Types", defval="Long/Short", options=["Long Only", "Long/Short", "Short Only"], group="Strategy Selection")
strat_val = strat == "Long Only" ? 1 : strat == "Long/Short" ? 0 : -1

// ————— Inputs
var bool    _1          = input(false,      "═══════════⥑ Gradient ⥏═══════════", group="Visualization Selection")
var bool    colorbars   = input(true,       "Use Gradient Color Bars?", group="Visualization Selection")
var string	i_scheme    = input(SH1,	    " 》Color Scheme",  options = [SH1, SH2, SH3, SH4, SH5, SH6, SH7], group="Visualization Selection")
var bool	i_invert    = input(false,      "Invert Colors", group="Visualization Selection")
var bool	i_barcolor  = input(false,      "Colorize Bars", group="Visualization Selection")
// }

// —————————— Color array {
var color[] c_gradients = array.new_color(na)

// Risk Management Inputs
general7 = input(false, "You can control your gains and losses with these inputs that should be self-explanatory.", group="Risk Management")
sl= input(50.0, "Stop Loss %", minval = 0, maxval = 100, step = 0.01, group="Risk Management")
stoploss = sl/100
tp = input(50.0, "Target Profit %", minval = 0, maxval = 100, step = 0.01, group="Risk Management")
TargetProfit = tp/100
ld = input(10, "Stop Trading After This Many Losing Days", type=input.integer, minval=0, maxval=100, step=1, group="Risk Management")
strategy.risk.max_cons_loss_days(count=ld)
ml = input(50, "Maximum % of Equity Lost to Halt Trading", type=input.integer, minval=1, maxval=100, step=1, group="Risk Management")
strategy.risk.max_drawdown(value=ml, type=strategy.percent_of_equity)

// General Settings
general8 = input(false, "This section is for adjusting the EMA length and price lookback period for identifying upward/downward zones. You can add the Triple EMA indicator to a new pane to visually tweak these settings.", group="Up/Down Trend Settings")
fastLength = input(5, minval=1, title="EMA Fast Length", group="Up/Down Trend Settings")
slowLength = input(12, minval=1, title="EMA Slow Length", group="Up/Down Trend Settings")
general9 = input(false, "The Average # of bars is what you observe as the number of up and down bars in a cycle", group="Up/Down Trend Settings")
general10 = input(false, "For example, if a crypto's chart has 6 up and 4 down for each cycle before it repeats", group="Up/Down Trend Settings")
general11 = input(false, "then your Average # of bars is 10 and your Price Lookback Period is 5 (half of the Avg #)", group="Up/Down Trend Settings")
AvgLkbk = input(20, minval=1, title="Average # of bars in Up/Down Trend", group="Up/Down Trend Settings")
lkbk = input(10,"Price Lookback Period", group="Up/Down Trend Settings")
high_source = input(high,"High Source", group="Up/Down Trend Settings")
low_source= input(low,"Low Source", group="Up/Down Trend Settings")
diff1 = input(2.5, "High Price Knife Percentage (% difference to trigger a quick sell)", group="Price Channel Settings")
diff = diff1/100


// Moving Average Inputs
general12 = input(false, "For the Moving Average Strategy - define the percentage from the center price line you want trades to occur", group="Moving Average Settings")
general13 = input(false, "the default is to use the first band (shaded in green and red) or you can choose to use the second or third price channel bands.", group="Moving Average Settings")
InnerValue = input(1.6, title="1st Price Band %", group="Moving Average Settings")
OuterValue = input(2.6, title="2nd Price Band %", group="Moving Average Settings")
ExtremeValue = input(4.2, title="Extreme Price Band %", group="Moving Average Settings")
BandUse = input("First", "Select Price Band to Trigger Trades", options=["First", "Second", "Extremes"], group="Strategy Selection")
band = BandUse == "First" ? 1 : BandUse == "Second" ? 2 : BandUse == "Extremes" ? 3 : na


// Fib Inputs
general14 = input(false, "The standard Fibonacci retracement levels are available in the drop down selection for the Fibonacci strategy.", group="Fibonacci Settings")
general15 = input(false, "Level 1 is where the trade will happen if the price crosses and the zone is up (for sell) and down (for buy)", group="Fibonacci Settings")
general16 = input(false, "Level 2 is where the trade will always happen when the price crosses regardless of trend indicators.", group="Fibonacci Settings")
Fib1 = input(1.618, "Fibonacci Level 1", options=[1.382, 1.618, 1.786, 2.000, 2.272, 2.382, 2.618, 3, 3.382, 3.618], group="Fibonacci Settings")
Fib2 = input(2.618, "Fibonacci Level 2", options=[1.382, 1.618, 1.786, 2.000, 2.272, 2.382, 2.618, 3, 3.382, 3.618], group="Fibonacci Settings")

// Peaks and Valleys Inputs
general17 = input(false, "Peaks and Valleys is a more aggressive form of the moving average strategy. You can change the type of MA to have faster scalps.", group="Peaks and Valleys Options")
maInput = input(title="MA Type (EMA is default - the rest experimental)", defval="EMA", options=["EMA", "SMA", "VWMA", "WMA"],  group="Peaks and Valleys Options")


//Entry area for custom bot messages (i.e. Quadency, 3Commas, etc)
general18 = input(false, "Here you can either copy and paste a trigger message for a bot or a custom message for an Email or SMS alert", group="Bot Webhook Messages")
general19 = input(false, "replace the alert body message with {{strategy.order.alert_message}} for a single message to map to alll long/short triggers.", group="Bot Webhook Messages")
message_long_entry  = input("long entry message", group="Bot Webhook Messages")
message_long_exit   = input("long exit message", group="Bot Webhook Messages")
message_short_entry = input("short entry message", group="Bot Webhook Messages")
message_short_exit  = input("short exit message", group="Bot Webhook Messages")


// ================================================================ Where the Magic Happens ========================================================================

// -------------------------------- Price Channel Calculation ----------------------------------

high1 = highest(high_source, AvgLkbk)
high2 = highest(high_source, lkbk)
lasthigh = max(high1, high2)
low1 = lowest(low_source, AvgLkbk)
low2 = lowest(low_source, lkbk)
lastlow = min(low1, low2)
hiHighs = lasthigh[1]
loLows = lastlow[1]
mids = (hiHighs + loLows)/2

plot(series = usePrice ?  mids: na, title="Price Midline", color=white, linewidth=1)
plot(series = usePrice ?  hiHighs: na, title="Price High Line", color=white, linewidth=1)
plot(series = usePrice ? loLows: na, title="Price Low Line", color=white, linewidth=1)


// --------------------------------- Moving Averages -------------------------------------------

// Improved Price Channels

CMA = mids

CenteredMA= plot(series = usePrice ? na : CMA, color=color.blue , linewidth=2)

HMA     = usePrice ? hiHighs : CMA + (CMA * (InnerValue / 100))
HMA2    = usePrice ? na : useFib ? CMA + (atr(lkbk)*Fib1) : CMA + (CMA * (OuterValue / 100))
HMA3    = usePrice ? na : useFib ? CMA + (atr(lkbk)*Fib2) : CMA + (CMA * (ExtremeValue / 100))

LMA     = usePrice ? loLows : CMA - (CMA * (InnerValue / 100))
LMA2    = usePrice ? na : useFib ? CMA - (atr(lkbk)*Fib1) : CMA - (CMA * (OuterValue / 100))
LMA3    = usePrice ? na : useFib ? CMA - (atr(lkbk)*Fib2) : CMA - (CMA * (ExtremeValue / 100))


// For Price Channels

ma3 = sma(close, 3), vwma3 = vwma(close, 3)
ma5 = sma(close, 5), vwma5 = vwma(close, 5)
ma9 = sma(close, 9), vwma9 = vwma(close, 9)
ma10 = sma(close,10)
ma15 = sma(close,15)


// For Fibonacci
MA1 = ema(close,5),HA1 = ema(high,5),LA1 = ema(low,5)
MA2 = ema(close,8),HA2 = ema(high,8),LA2 = ema(low,8)
MA3 = ema(close,13),HA3 = ema(high,13),LA3 = ema(low,13)
MA4 = ema(close,21),HA4 = ema(high,21),LA4 = ema(low,21)
MA5 = ema(close,34),HA5 = ema(high,34),LA5 = ema(low,34)
MA6 = ema(close,55),HA6 = ema(high,55),LA6 = ema(low,55)
MA7 = ema(close,89),HA7 = ema(high,89),LA7 = ema(low,89)


// For Peaks and Valleys

getMA(src, length) =>
    ma = 0.0
    if maInput == "EMA"
        ma := ema(src, length)
    if maInput == "SMA"
        ma := sma(src, length)
    if maInput == "VWMA"
        ma := vwma(src, length)
    if maInput == "WMA"
        ma := wma(src, length)
    ma


FastAvgValue = getMA(close, fastLength)
SlowAvgValue = getMA(close, slowLength)

fHi = highest(high, fastLength)
fLo = lowest(low, fastLength)

sHi = highest(high, slowLength)
sLo = lowest(low, slowLength)

FastStoch = (FastAvgValue - fHi) / (fHi - fLo)
SlowStoch = (SlowAvgValue - sLo) / (sHi - sLo)


STMACD = (FastStoch - SlowStoch) * 100
STMACDAvg = getMA(STMACD, AvgLkbk)


// ====================================== Trend Direction Calculations ===========================================
// -------------- Volume Trend------------------
cumUp = 0.0
cntUp = 0
cumDown = 0.0
cntDown = 0
for i=0 to lkbk-1
    if close[i] > open[i]
        cumUp := cumUp + volume[i]
        cntUp := cntUp + 1
    else
        cumDown := cumDown + volume[i]
        cntDown := cntDown + 1

averagevolumeup = (cumUp/cntUp)
averagevolumedown = -(cumDown/cntDown)

volUp = (averagevolumeup) <= volume and close > open
volDown = (averagevolumedown) >= -volume and close < open

flow = cumUp - cumDown

//Call bullshit when trend doesn't agree with the numbers (fake pumps and dumps)

BullShit1 = flow > 0 and flow[1] > 0 and volDown
BullShit2 = flow < 0 and flow[1] < 0 and volUp

BullShit = BullShit1 or BullShit2

upVol = volUp and flow > 0 and not BullShit
downVol = volDown and flow < 0 and not BullShit


// ----------------- Range Breakout Trend -------------------
src = high_source

smoothrng(x, t, m)=>
    wper      = (t*2) - 1
    avrng     = ema(abs(x - x[1]), t)
    smoothrng = ema(avrng, wper)*m
    smoothrng

smrng = smoothrng(close, slowLength, lkbk)

rngfilt(x, r)=>
    rngfilt  = x
    rngfilt := x > nz(rngfilt[1]) ? ((x - r) < nz(rngfilt[1]) ? nz(rngfilt[1]) : (x - r)) : ((x + r) > nz(rngfilt[1]) ? nz(rngfilt[1]) : (x + r))
    rngfilt
filt = rngfilt(src, smrng)

upward   = 0.0
upward  := filt > filt[1] ? nz(upward[1]) + 1 : filt < filt[1] ? 0 : nz(upward[1])
downward = 0.0
downward := filt < filt[1] ? nz(downward[1]) + 1 : filt > filt[1] ? 0 : nz(downward[1])

hband = filt + smrng
lband = filt - smrng

uptrend1 = (src > filt) and (src > src[1]) and (upward > 0)
uptrend2 = (src > filt) and (src < src[1]) and (upward > 0)
longCond = uptrend1 or uptrend2

downtrend1 = (src < filt) and (src < src[1]) and (downward > 0)
downtrend2 = (src < filt) and (src > src[1]) and (downward > 0)
shortCond = downtrend1 or downtrend2

CondIni = 0
CondIni := longCond ? 1 : shortCond ? -1 : CondIni[1]
stroking = longCond and CondIni[1] == -1

//  Arnaud Legoux Moving Average ( ALMA ) 

xrf(values, length) =>
    r_val = float(na)
    if length >= 1
        for i = 0 to length by 1
            if na(r_val) or not na(values[i])
                r_val  :=  values[i]
                r_val
    r_val

ma20 = sma(close,20)
ma50 = sma(close,50)
ma200 = sma(close,200)
change2 = cmo(close, 2)
change9 = cmo(close, 9)

trendline =  alma((close-sma(close,40))/sma(close,40)*100,21,0.85,6)
tradingline = ema(ema(ema((2*close+high+low)/4,4),4),4)
fastLine = ( sma((tradingline-xrf(tradingline,1))/xrf(tradingline,1)*100,1))*10
slowLine = alma( sma((tradingline-xrf(tradingline,1))/xrf(tradingline,1)*100,2),3,0.85,6)*10

pd = (high[1] - close[1]) / close[1]

// Breakout (upward momentum) and Dumpout (downward momentumm) conditions based on ALMA indicator triggers combined with volume trend as a crosscheck to reduce false alerts
// Fakeout based on patterns where the high point of the price is a reverse knife (when high is greater than 2% of the close price) - this typically leads to a small dump of FOOMO sellers

breakout = fastLine>slowLine and fastLine<0 and longCond
dumpout = fastLine<slowLine and fastLine>0 and shortCond
fakeout = pd > diff or high >= HMA3


// ------------------------ Price Channel Plots --------------------------------------------------------



Ctr_Top = (useMA or useFib) ? (band==1 ? mids : band==2 ? HMA : band == 3 ? HMA2: na) : mids
Ctr_Bottom = (useMA or useFib) ? (band==1 ? mids : band==2 ? LMA : band == 3 ? LMA2: na) : mids
upper_function = (useMA or useFib) ? (band==1 ? HMA : band==2 ? HMA2 : band == 3 ? HMA3: na) : hiHighs
lower_function = (useMA or useFib) ? (band==1 ? LMA : band==2 ? LMA2 : band == 3 ? LMA3: na) : loLows

Ctr1       = plot(Ctr_Top, color=white)
Ctr2    = plot(Ctr_Bottom, color=white)
Upper   = plot(upper_function, color=white)
Lower   = plot(lower_function, color=white)

upper_color = color.new(color.green, 90)
lower_color = color.new(color.red, 90)


fill(Ctr1, Upper, upper_color)
fill(Ctr2, Lower, lower_color)



// ————— Fill the array with colors only on the first iteration of the script
if barstate.isfirst
    if i_scheme == SH1
        array.push(c_gradients, #ff0000), array.push(c_gradients, #ff2c00), array.push(c_gradients, #fe4200), array.push(c_gradients, #fc5300), array.push(c_gradients, #f96200), array.push(c_gradients, #f57000), array.push(c_gradients, #f07e00), array.push(c_gradients, #ea8a00), array.push(c_gradients, #e39600), array.push(c_gradients, #dca100), array.push(c_gradients, #d3ac00), array.push(c_gradients, #c9b600), array.push(c_gradients, #bfc000), array.push(c_gradients, #b3ca00), array.push(c_gradients, #a6d400), array.push(c_gradients, #97dd00), array.push(c_gradients, #86e600), array.push(c_gradients, #71ee00), array.push(c_gradients, #54f700), array.push(c_gradients, #1eff00)
    else if i_scheme == SH2
        array.push(c_gradients, #ff00d4), array.push(c_gradients, #f71fda), array.push(c_gradients, #ef2ee0), array.push(c_gradients, #e63ae5), array.push(c_gradients, #de43ea), array.push(c_gradients, #d44bee), array.push(c_gradients, #cb52f2), array.push(c_gradients, #c158f6), array.push(c_gradients, #b75df9), array.push(c_gradients, #ac63fb), array.push(c_gradients, #a267fe), array.push(c_gradients, #966bff), array.push(c_gradients, #8b6fff), array.push(c_gradients, #7e73ff), array.push(c_gradients, #7276ff), array.push(c_gradients, #6479ff), array.push(c_gradients, #557bff), array.push(c_gradients, #437eff), array.push(c_gradients, #2e80ff), array.push(c_gradients, #0082ff)
    else if i_scheme == SH3
        array.push(c_gradients, #fafa6e), array.push(c_gradients, #e0f470), array.push(c_gradients, #c7ed73), array.push(c_gradients, #aee678), array.push(c_gradients, #97dd7d), array.push(c_gradients, #81d581), array.push(c_gradients, #6bcc86), array.push(c_gradients, #56c28a), array.push(c_gradients, #42b98d), array.push(c_gradients, #2eaf8f), array.push(c_gradients, #18a48f), array.push(c_gradients, #009a8f), array.push(c_gradients, #00908d), array.push(c_gradients, #008589), array.push(c_gradients, #007b84), array.push(c_gradients, #0c707d), array.push(c_gradients, #196676), array.push(c_gradients, #215c6d), array.push(c_gradients, #275263), array.push(c_gradients, #2a4858)
    else if i_scheme == SH4
        array.push(c_gradients, #ffffff), array.push(c_gradients, #f0f0f0), array.push(c_gradients, #e1e1e1), array.push(c_gradients, #d2d2d2), array.push(c_gradients, #c3c3c3), array.push(c_gradients, #b5b5b5), array.push(c_gradients, #a7a7a7), array.push(c_gradients, #999999), array.push(c_gradients, #8b8b8b), array.push(c_gradients, #7e7e7e), array.push(c_gradients, #707070), array.push(c_gradients, #636363), array.push(c_gradients, #575757), array.push(c_gradients, #4a4a4a), array.push(c_gradients, #3e3e3e), array.push(c_gradients, #333333), array.push(c_gradients, #272727), array.push(c_gradients, #1d1d1d), array.push(c_gradients, #121212), array.push(c_gradients, #000000)
    else if i_scheme == SH5
        array.push(c_gradients, #ffffff), array.push(c_gradients, #f4f5fa), array.push(c_gradients, #e9ebf5), array.push(c_gradients, #dee1f0), array.push(c_gradients, #d3d7eb), array.push(c_gradients, #c8cde6), array.push(c_gradients, #bdc3e1), array.push(c_gradients, #b2b9dd), array.push(c_gradients, #a7b0d8), array.push(c_gradients, #9ca6d3), array.push(c_gradients, #919dce), array.push(c_gradients, #8594c9), array.push(c_gradients, #7a8bc4), array.push(c_gradients, #6e82bf), array.push(c_gradients, #6279ba), array.push(c_gradients, #5570b5), array.push(c_gradients, #4768b0), array.push(c_gradients, #385fab), array.push(c_gradients, #2557a6), array.push(c_gradients, #004fa1)
    else if i_scheme == SH6
        array.push(c_gradients, #ffffff), array.push(c_gradients, #fff4f1), array.push(c_gradients, #ffe9e3), array.push(c_gradients, #ffded6), array.push(c_gradients, #ffd3c8), array.push(c_gradients, #fec8bb), array.push(c_gradients, #fdbdae), array.push(c_gradients, #fbb2a1), array.push(c_gradients, #f8a794), array.push(c_gradients, #f69c87), array.push(c_gradients, #f3917b), array.push(c_gradients, #f0856f), array.push(c_gradients, #ec7a62), array.push(c_gradients, #e86e56), array.push(c_gradients, #e4634a), array.push(c_gradients, #df563f), array.push(c_gradients, #db4933), array.push(c_gradients, #d63a27), array.push(c_gradients, #d0291b), array.push(c_gradients, #cb0e0e)
    else if i_scheme == SH7
        array.push(c_gradients, #E50000), array.push(c_gradients, #E6023B), array.push(c_gradients, #E70579), array.push(c_gradients, #E908B7), array.push(c_gradients, #E00BEA), array.push(c_gradients, #A70DEB), array.push(c_gradients, #6E10ED), array.push(c_gradients, #3613EE), array.push(c_gradients, #162DEF), array.push(c_gradients, #1969F1), array.push(c_gradients, #1CA4F2), array.push(c_gradients, #1FDFF4), array.push(c_gradients, #22F5D2), array.push(c_gradients, #25F69C), array.push(c_gradients, #28F867), array.push(c_gradients, #2CF933), array.push(c_gradients, #5DFA2F), array.push(c_gradients, #96FC32), array.push(c_gradients, #CDFD35), array.push(c_gradients, #FFF938)
    
    // Invert colors in array
    if i_invert
        array.reverse(c_gradients)
        
// ————— Rescale function 
// Credits to LucF, https://www.pinecoders.com/faq_and_code/#how-can-i-rescale-an-indicator-from-one-scale-to-another
f_rescale(_src, _min, _max) =>
    // Rescales series with known min/max to the color array size.
    // Dependency : c_gradients array
    // _src       : series to rescale.
    // _min, _max : min/max values of series to rescale.
    var int _size = array.size(c_gradients) - 1
    int _colorStep = int(_size * (_src - _min)) / int(max(_max - _min, 10e-10))
    _colorStep := _colorStep > _size ? _size : _colorStep < 0 ? 0 : _colorStep
    int(_colorStep)

// ————— Result
// Dependency : c_gradients array
f_colGrad(_src, _min, _max) => array.get(c_gradients, f_rescale(_src, _min, _max))

// Example:
// resultColor = f_colGrad(_src, _min, _max)
// }

// ————— Rsi as a source
rsi = rsi(close, 100)

// ————— Bollinger bands on top of Rsi as gradient's min and max
[_, rsiUpperBand, rsiLowerBand] = bb(rsi, 200, 1.618)

// ————— Colorize the bounded source
color c_rsi = f_colGrad(rsi, rsiLowerBand, rsiUpperBand)

barcolor(i_barcolor ? crossover(STMACD, STMACDAvg) ? color.red : crossunder(STMACD, STMACDAvg) ? color.yellow : BullShit ? color.white : c_rsi : na)

// ============================================================================= Entry and Exit Logic ======================================================================

// Entry Logic

//Logic for Channel Buy/Sell

CB1 = low < loLows and longCond and window()
CB2 = breakout and window()
Channel_Buy = CB1 or CB2

CS1 = high >= hiHighs and shortCond and window()
CS2 = dumpout and window()
CS3 = fakeout and window()
Channel_Sell = CS1 or CS2 or CS3


//Logic for Moving Average
MS1 = (band == 1 ? high > HMA : band == 2 ? high > HMA2 : band == 3 ? high > HMA3 : na) and shortCond and window()
MS2 = (band == 1 ? high > HMA : band == 2 ? high > HMA2 : band == 3 ? high > HMA3 : na) and crossunder(STMACD, STMACDAvg) and window()
MA_Sell = MS1 or MS2

MB1 = (band == 1 ? low<LMA : band == 2 ? low < LMA2 : band == 3 ? low < LMA3 : na)  and longCond and window()
MB2 = (band == 1 ? low<LMA : band == 2 ? low < LMA2 : band == 3 ? low < LMA3 : na) and crossover(STMACD, STMACDAvg) and window()
MA_Buy = MB1 or MB2

//Logic for Fib
Fib_Sell1 = high[1]>=HMA2 and high>=HMA3 and window()
Fib_Sell2 = high[1]>=HMA2 and close<HMA3 and window()
Fib_Sell3 = high >= HMA2 and BullShit and window()
Fib_Sell4 = high > HMA3 and window()
Fib_Sell = Fib_Sell1 or Fib_Sell2 or Fib_Sell3 or Fib_Sell4

Fib_Buy1 = low[3]<=LMA3 and low[2]<=LMA3 and low[1]<=LMA3 and low<=LMA3 and window()
Fib_Buy2 = low<=LMA3 and BullShit and window()
Fib_Buy3 = low <= LMA2 and crossover(STMACD, STMACDAvg) and window()
Fib_Buy = Fib_Buy1 or Fib_Buy2 or Fib_Buy3



//----- Logic for Peaks and Valleys -----------------------------
// LB is Long Buy logic and SB is Short Buy Logic
// LS is for Long Sell and is the same for Short Sells

LB = low < loLows and crossover(STMACD, STMACDAvg) and window()
SB = low < loLows and BullShit and window()
PVBuy = LB or SB

SS1 = high >= hiHighs and crossunder(STMACD, STMACDAvg) and window()
LS1 = BullShit and high >= hiHighs and window()
PVSell = LS1 or SS1


// ------------------------ Strategy Trades -------------------------------------------------------------

GoLong = usePrice ? Channel_Buy : useMA ? MA_Buy : useFib ? Fib_Buy : usePV ? PVBuy : false
GoShort = usePrice ? Channel_Sell : useMA ? MA_Sell : useFib ? Fib_Sell : usePV ? PVSell : false

CloseShort= usePrice ? Channel_Buy : useMA ? MA_Buy : useFib ? Fib_Buy : usePV ? PVBuy : false
CloseLong = usePrice ? Channel_Sell : useMA ? MA_Sell : useFib ? Fib_Sell : usePV ? PVSell : false

// Strategy Open and Close
if (GoLong and strat_val==0 and strategy.position_size==0 and barstate.isconfirmed)
    strategy.entry(id="MIXED", long=true, oca_type=strategy.oca.cancel, oca_name="Mixed Entry", alert_message = message_long_entry)

if (GoLong and strat_val==1 and strategy.position_size==0 and barstate.isconfirmed)
    strategy.entry("LONG", strategy.long, alert_message = message_long_entry)

if (GoShort and strat_val==0 and strategy.position_size==0 and strategy.position_size[1]==0 and barstate.isconfirmed)
    strategy.entry(id="MIXED", long=false, oca_type=strategy.oca.cancel, oca_name="Mixed Entry", alert_message = message_short_entry)

if (GoShort and strat_val==-1 and strategy.position_size==0 and barstate.isconfirmed) 
    strategy.entry("SHORT", strategy.short, alert_message = message_short_entry)

if(CloseLong and strategy.position_size > 0 and strat_val==1 and barstate.isconfirmed)
    strategy.close("LONG", alert_message = message_long_exit)

if(CloseLong and strategy.position_size > 0 and strat_val==0 and barstate.isconfirmed)
    strategy.close("MIXED", alert_message = message_long_exit)

if(CloseShort and strategy.position_size < 0 and strat_val==-1 and barstate.isconfirmed)
    strategy.close("SHORT", alert_message = message_short_exit)

if(CloseShort and strategy.position_size < 0 and strat_val==0 and barstate.isconfirmed)
    strategy.close("MIXED", alert_message = message_short_exit)


// -------------------- RISK MANAGEMENT FUNCTIONS ------------------------
//Calculate stop and take profit prices
longStopPrice  = strategy.position_avg_price * (1 - stoploss)
longTakePrice  = strategy.position_avg_price * (1 + TargetProfit)
shortStopPrice = strategy.position_avg_price * (1 + stoploss)
shortTakePrice = strategy.position_avg_price * (1 - TargetProfit)


//Set exit strategy parameters
if (strategy.position_size > 0 and strat_val==1)
    strategy.exit(id="Exit Long", from_entry = "LONG", stop = longStopPrice, limit = longTakePrice, alert_message = message_long_exit)

if (strategy.position_size > 0 and strat_val==0)
    strategy.exit(id="Exit Mixed", from_entry = "MIXED", oca_name="Mixed Entry", stop = longStopPrice, limit = longTakePrice, alert_message = message_long_exit)

if (strategy.position_size < 0 and strat_val==-1)
    strategy.exit(id="Exit Short", from_entry = "SHORT", stop = shortStopPrice, limit = shortTakePrice, alert_message = message_short_exit)

if (strategy.position_size < 0 and strat_val==0)
    strategy.exit(id="Exit Mixed", from_entry = "MIXED", oca_name="Mixed Entry", stop = shortStopPrice, limit = shortTakePrice, alert_message = message_short_exit)

