QFL Indicator Strategy

				
					//@version=6

// © SeerQuant

indicator(
 title = "Quartile For Loop [SeerQuant]",
 shorttitle = "QFL [SeerQuant]", 
 overlay = false
 )

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

// @param: Moving Average Settings
qLength    = input.int(14,       title = "Quartile Length",        inline = "First",    group = " > INDICATOR INPUTS <")
src        = input.source(close, title = "Calculation Source",     inline = "First",    group = " > INDICATOR INPUTS <")
typeSig    = input.bool(false,   title = "Use Alternate Signal?",                       group = " > INDICATOR INPUTS <", tooltip = "Alternative way of scoring. Uses past quartile values instead of price source for iterative scoring.")

// @param: Global Settings
sl         = input.int(5,        title = "Loop Start",             inline = "Global",   group = " > FOR LOOP SETTINGS <")
el         = input.int(55,       title = "Loop End",               inline = "Global",   group = " > FOR LOOP SETTINGS <")
thrUp      = input.float(35,     title = "Threshold Uptrend",      inline = "Global",   group = " > FOR LOOP SETTINGS <")
thrDown    = input.float(-5,     title = "Threshold Downtrend",    inline = "Global",   group = " > FOR LOOP SETTINGS <")

// @param: Style Settings
paint      = input.bool(false, title = "Colour Candles?",                               group = " > STYLE SETTINGS <")

// @param: Colour Scheme
colScheme  = input.string("Default", "Color Scheme", 
                         options = ["Default", "Modern", "Cool", 
                                 "Alternate", "Bright"],                                group = " > STYLE SETTINGS <")

[bull, bear, neutral] = switch colScheme
    "Default"   => [#00ff73, #ff0040, #606060]
    "Modern"    => [#23d7e4, #e11179, #707070]
    "Cool"      => [#00ffcc, #4e4f75, #505050]
    "Alternate" => [#00ff80, #ff6600, #505050]
    "Bright"    => [#e8ec00, #f200fa, #505050]

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

// @function: Weighted quartile function 
f_quartile(src, len) =>
    // Find Q1, Median and Q3
    q1      = ta.percentile_nearest_rank(src, len, 25)
    median  = ta.percentile_nearest_rank(src, len, 50)
    q3      = ta.percentile_nearest_rank(src, len, 75)

    // Weighted average of each quartile, double weighted median.
    (q1 + 2 * median + q3) / 4

// @function: For Loop scoring system, which optional scoring method. 
calcScore(start, end, val, alt) =>
    sum = 0.0
    for i = start to end by 1
        sum += (alt == false ? (src > val[i] ? 1 : -1) : (val > val[i] ? 1 : -1))
    sum

// ----------------- CALCULATIONS ----------------- //

// @description: Call the functions
adaptive_quartile   = f_quartile(src, qLength)
score               = calcScore(sl, el, adaptive_quartile, typeSig)

// @description: Long and short conditions
goLong  = score > thrUp
goShort = score < thrDown

var signal = 0
if goLong and not goShort
    signal := 1
if goShort
    signal := -1

// ----------------- PLOTTING ----------------- //

// @description: Color logic for plotting.
hist_color = signal == 1 ? bull : signal == -1 ? bear : neutral

// @description: Plotting the oscillator.
one   = plot(score,   color = color.new(hist_color, 0),  style = plot.style_line, linewidth=3)
two   = plot(thrUp,   color = color.new(bull,      50),  style = plot.style_line, linewidth=2)
three = plot(thrDown, color = color.new(bear,      50),  style = plot.style_line, linewidth=2)

// @description: Optional input to color the candles with the selected color palette. 
barcolor(paint ? hist_color : na)

// @description: Colored SMA for easy trend detection. 
sma = ta.sma(close, 14)
a = plot(sma, color = hist_color, linewidth = 4, force_overlay = true)

// @description: State tracking for accurate plotting of signals. 
var int prevTrendState = 0 
var int currentTrendState = 0

if score > thrUp
    currentTrendState := 1 
else if score < thrDown
    currentTrendState := -1 
else
    currentTrendState := 0 

bullishTransition = (prevTrendState != 1 and currentTrendState == 1)
bearishTransition = (prevTrendState != -1 and currentTrendState == -1)

if bullishTransition or bearishTransition
    prevTrendState := currentTrendState

// @description: Plot the bullish signal.
plotshape(bullishTransition ? adaptive_quartile - (adaptive_quartile * 0.075) : na, 
          title = "Bullish Transition", 
          style = shape.labelup, 
          location = location.absolute, 
          color = bull, 
          text = "▲", 
          textcolor = #000000, 
          size = size.small, 
          force_overlay = true)

// @description: Plot the bearish signal.
plotshape(bearishTransition ? adaptive_quartile + (adaptive_quartile * 0.075) : na, 
          title = "Bearish Transition", 
          style = shape.labeldown, 
          location = location.absolute, 
          color = bear, 
          text = "▼", 
          textcolor = #000000, 
          size = size.small,
          force_overlay = true)

// ----------------- ALERTS ----------------- //

// Long (Bullish) Condition Alert.
alertcondition(signal == 1,  title = "Quartile For-Loop Postive Trend",  message = "Quartile For-Loop Bullish Signal on: {{exchange}}:{{ticker}}")

// Short/Cash (Bearish) Condition Alert.
alertcondition(signal == -1, title = "Quartile For-Loop Negative Trend", message = "Quartile For-Loop Bearish Signal on: {{exchange}}:{{ticker}}")


// ---------------------------------------------------------------------------------------------------------------- //
				
			
Leave a Reply