Skip to main content
Latest Crypto Fear & Greed Index


New Pine Script: Cosine Kernel Regression


 This pine script is adapted from Cosine Kernel Regression by QuantraSystems. Credit goes to this brilliant script writer. 

The Cosine Kernel Regressions indicator (CKR) uses mathematical concepts to offer a unique approach to market analysis. This indicator employs Kernel Regressions using bespoke tunable Cosine functions in order to smoothly interpret a variety of market data, providing traders with incredibly clean insights into market trends. Details here.. 

Strategy Description: This stratgey uses many indicators to combine into an indicator that minimizes noises to get as accurate as possible. Order Buy is placed on Oversold signal, and exits the order when Overbought signal.

Recommended Settings:

Pair: RNDRUSDT (Binance)

Time frame: 1 hour

Initial Capital: 100

Base Currency: Default

Order Size: 100% equity

Pyramiding: 1 order

Commission: 0.1 % 


// @version=5
strategy("CKR: capayam.com credit to QuantraSystems", overlay=false, initial_capital = 10, default_qty_type=strategy.percent_of_equity, default_qty_value=100, commission_type=strategy.commission.percent , commission_value=0.1)
import QuantraAI/QuantraMAs/2 as Dynamic

// Desc: refer to Cosine Kernel Regression by QuantraSystems for original pine script.
// Default setting is best with TF1hour

// Input Groups

GRP1          = "Display:"
GRP2          = "Indicator Setup:"
GRP3          = "Kernel Calibration:"

// Indicator Calibrations
src           = input.source(close,          "Source",                                          group = GRP2            )

bool_STOCH    = input.bool  (true,           "",                              inline = "STOCH", group = GRP2            )
bool_RSI      = input.bool  (true,           "",                              inline = "RSI",   group = GRP2            )      
bool_BBPCT    = input.bool  (true,           "",                              inline = "BBPCT", group = GRP2            )
bool_CMO      = input.bool  (true,           "",                              inline = "CMO",   group = GRP2            )
bool_CCI      = input.bool  (true,           "",                              inline = "CCI",   group = GRP2            )
bool_FISH     = input.bool  (true,           "",                              inline = "FISH",  group = GRP2            )
bool_VZO      = input.bool  (true,           "",                              inline = "VZO",   group = GRP2            )

length_STOCH  = input.int   (14,             "Stochastic Length",             inline = "STOCH", group = GRP2            )
length_RSI    = input.int   (14,             "RSI Length",                    inline = "RSI",   group = GRP2            )
length_BBPCT  = input.int   (20,             "BBPCT Length",                  inline = "BBPCT", group = GRP2            )
length_CMO    = input.int   (14,             "Chande Momentum Length",        inline = "CMO",   group = GRP2            )
length_CCI    = input.int   (20,             "CCI Length",                    inline = "CCI",   group = GRP2            )
length_FISH   = input.int   (9,              "Fisher Transform Length",       inline = "FISH",  group = GRP2            )
length_VZO    = input.int   (21,             "VZO Length",                    inline = "VZO",   group = GRP2            )


// Cosine Kernel Setup
varient       = input.string("Tuneable",     "Cosine Kernel Regression Type",                   group = GRP3, options = ["Tuneable", "Stepped"])
lookbackR     = input.int   (60,             "Regression Lookback",                             group = GRP3            )
tuning        = input.float (15.,            "Tuning Coefficient",                              group = GRP3            )


// Display
ColType       = input.string("Fast Trend",   "Choose Mode",                                     group = GRP1, options = ["None",    "Fast Trend", "Slow Trend"], tooltip = "Signal Mode - Barcolor")
ColMode       = input.string("Modern",       "Color Palette Choice",          inline = "Drop",  group = GRP1, options = ["Classic", "Modern", "Robust", "Accented", "Monochrome"])
man           = input.bool  (false,          "Custom Palette",                inline = "Drop",  group = GRP1            )
manUpC        = input.color (#00ff00,      "Custom Up",                     inline = "Man",   group = GRP1            )
manDnC        = input.color (#ff0000,      "Custom Down",                   inline = "Man",   group = GRP1            )


// Color assignment based on the selected palette
[UpC, DnC]       =   switch     ColMode
    "Classic"    => [#00E676, #880E4F]
    "Modern"     => [#5ffae0, #c22ed0]
    "Robust"     => [#ffbb00, #770737]
    "Accented"   => [#9618f7, #ff0078]
    "Monochrome" => [#dee2e6, #495057]


// Override with custom colors if manual palette is selected
[UpCol, DnCol]   =   switch      man
    false        => [UpC,        DnC     ]
    true         => [manUpC,     manDnC  ]



// Define a function to compute the cosine of an input scaled by a frequency tuner
cosine(x, z) =>
    // Where x = source input
    //       y = function output
    //       z = frequency tuner
    var y = 0.
    y := math.cos(z * x)
    y


// Define a kernel that utilizes the cosine function
kernel(x, z) =>
    var y = 0.
    y := cosine(x, z)
    math.abs(x) <= math.pi/(2 * z) ? math.abs(y) : 0.    //    cos(zx) = 0
//  The above restricts the wave to positive values      //     when x = π / 2z


// Kernel Regression                                                      
kernelRegression(src, lookback, tuning) =>                                
                                                                         
    currentWeight = 0.                                                    
    totalWeight   = 0.                                                    
    for i = 0 to math.min(lookback - 1, bar_index)                        
        y = src[i]                                                        
        w = kernel(i / lookback, tuning)                                  
        currentWeight += y * w                                            
        totalWeight   += w                                                
    currentWeight / totalWeight                                          
                                                                         



// Multi Cosine                                                          
multicosine(src, lookback, steps) =>                                      
                                                                         
    regression = 0.                                                      
    for i = 1 to math.min(steps - 1, bar_index)                          
        regression += kernelRegression(src, lookback, i)                  
    regression / steps                                                    
                                                                         


RSI_ReScale   (_res      ) => (      _res - 50   ) * 2.8
STOCH_ReScale (_stoch    ) => (    _stoch - 50   ) * 2
BBPCT_ReScale (_bbpct    ) => (    _bbpct - 0.5  ) * 120
CMO_ReScale   (_chandeMO ) => ( _chandeMO * 1.15 )
CCI_ReScale   (_cci      ) => (      _cci / 2    )
FISH_ReScale  (_fish1    ) => (    _fish1 * 30   )
VZO_ReScale   (_VP, _TV  ) => (_VP / _TV) * 110


DynamicStdev(src, length) =>
    actualLength =    math.min(length, bar_index + 1)
    mean         = Dynamic.SMA(src,     actualLength)
    sumSquares   = 0.0
    for i = 0 to actualLength - 1
        sumSquares := sumSquares + math.pow(nz(src[i]) - mean, 2)
    stdev = math.sqrt(sumSquares / actualLength)
    stdev


DynamicDev(source, length) =>
    mean  = Dynamic.SMA(source, length)
    sum   = 0.0
    for i = 0 to length - 1
        val  = source[i]
        sum := sum + math.abs(val - mean)
    dev = sum / length
   

DynamicRMA(src, length) =>
    srcx = src * 100
    var float rma = na
    rma := length == 1 ?
           Dynamic.SMA(srcx, length) :
           ((rma[1] * (length - 1) ) + srcx) / length
    rma


DynamicRSI(src, length) =>
    var float res = na
    len  =     math.min(length,   bar_index        )
    u    =     math.max(src     - src[1], 0        )
    d    =     math.max(src[1]  - src,     0       )
    rs   =   DynamicRMA(u, len) / DynamicRMA(d, len)
    res := 100 - 100 / (1 + rs)
    RSI_ReScale(res)


DynamicSTOCH(source, hi, lo, length) =>
    len         =    math.min(length,   1 + bar_index)
    lowestLow   =   ta.lowest(lo,           len      )
    highestHigh =  ta.highest(hi,           len      )
    stochastic  =      100 * (source      - lowestLow) /
                             (highestHigh - lowestLow)
    STOCH_ReScale(stochastic)


DynamicBBPCT(length, multi) =>
    basis =   Dynamic.SMA(src, length)
    dev   =   multi * DynamicStdev(src, length)
    upper =   basis + dev
    lower =   basis - dev
    bbpct =  (src   - lower) /
             (upper - lower)
    BBPCT_ReScale(bbpct)

 
DynamicCMO(length) =>
    len  = math.min(length, bar_index + 1)            
    momm = ta.change(src)                            
    m1   = momm >= 0 ?  momm : 0.0                    
    m2   = momm <  0 ? -momm : 0.0                    
    sm1  = math.sum(m1, len)                          
    sm2  = math.sum(m2, len)                          
    div  = sm1 + sm2                                  
    chandeMO = div != 0 ? 100 * (sm1 - sm2) / div : 0
    CMO_ReScale(chandeMO)                            


DynamicCCI(length) =>
    len = math.min(length, bar_index + 1)
    ma  = Dynamic.SMA(src, len)
    cci = (src - ma) / (0.015 * DynamicDev(src, len))
    CCI_ReScale(cci)


DynamicFisher(length) =>
    len     =   math.min(length, 1 + bar_index)
    high_   = ta.highest(hl2,        len      )
    low_    =  ta.lowest(hl2,        len      )
    value1  = 0.0
    value2  = 0.0
    value1 := 0.66 * ((hl2 - low_)  / (high_ - low_) - 0.5)  + 0.67 * nz(value1[1])
    value2 := value1 > 0.99 ? 0.999 : value1 < -.99  ? -.999 : value1
    fish1   = 0.0
    fish1  := 0.5 * math.log((1 + value2) / (1 - value2)) + 0.5 * nz(fish1[1])
    FISH_ReScale(fish1)


DynamicVZO(length) =>
    VP = Dynamic.EMA(math.sign(ta.change(hlc3)) * volume, length / 3)
    TV = Dynamic.EMA(volume, length / 3)
    VZO_ReScale(VP, TV)


// Function to check the status of user-bools
booleanCheck(condition, func) => condition ? func : na


// Function to count active indicators
countCondition(condition)     => condition ? 1 : 0


// Pull all standardized base indicator values
val_RSI   = booleanCheck(bool_RSI,   DynamicRSI    (src, length_RSI)              )
val_STOCH = booleanCheck(bool_STOCH, DynamicSTOCH  (src, high, low, length_STOCH) )
val_BBPCT = booleanCheck(bool_BBPCT, DynamicBBPCT  (length_BBPCT, 2)              )
val_CMO   = booleanCheck(bool_CMO,   DynamicCMO    (length_CMO     )              )
val_CCI   = booleanCheck(bool_CCI,   DynamicCCI    (length_CCI     )              )
val_FISH  = booleanCheck(bool_FISH,  DynamicFisher (length_FISH    )              )
val_VZO   = booleanCheck(bool_VZO,   DynamicVZO    (length_VZO     )              )


// Count the number of active indicators
activeIndicators =
          countCondition(bool_RSI  ) +
          countCondition(bool_STOCH) +
          countCondition(bool_BBPCT) +
          countCondition(bool_CMO  ) +
          countCondition(bool_CCI  ) +
          countCondition(bool_FISH ) +
          countCondition(bool_VZO  )


// Calculate the average only with active indicators
value = activeIndicators > 0 ? (
          nz(val_RSI,   0) +
          nz(val_STOCH, 0) +
          nz(val_BBPCT, 0) +
          nz(val_CMO,   0) +
          nz(val_CCI,   0) +
          nz(val_FISH,  0) +
          nz(val_VZO,   0)
          ) / activeIndicators : na

// Gentle ALMA smoothing
value := Dynamic.ALMA(value, 9, 0, 6)


// Calulate the Output - Depending on the method of Cosine Regression Selected
out  = switch varient
    "Tuneable" => kernelRegression(value, lookbackR, tuning)
    "Stepped"  =>      multicosine(value, lookbackR, tuning)

out2 = switch varient
    "Tuneable" => kernelRegression(value, lookbackR, math.round(tuning / 5))
    "Stepped"  =>      multicosine(value, lookbackR, math.round(tuning / 5))


// Define Alert Conditions
fastTrend_up  = out  > out[1]  and not (out[1]  > out[2])
fastTrend_dn  = out  < out[1]  and not (out[1]  < out[2])
slowTrend_up  = out2 >     0   and not (out2[1] >     0 )
slowTrend_dn  = out2 <     0   and not (out2[1] <     0 )
overbought    = out  >    50   and not (out[1]  >    50 )
oversold      = out  <   -50   and not (out[1]  <   -50 )

fastTrend     = fastTrend_up or fastTrend_dn
slowTrend     = slowTrend_up or slowTrend_dn


                                                                                                           
                                                                                                           
barcol = switch ColType                                                                                    
    "None"                   => na                                                                        
    "Fast Trend"             => out  > out[1]       ?      UpCol : DnCol                                  
    "Slow Trend"             => out2 > 0            ?      UpCol : DnCol                                  
col                          =  out  > out[1]       ?      UpCol : DnCol                                  
col2                         =  color.new((out2 > 0 ?      UpCol : DnCol), 80)                            
                                                                                                           
mid  = plot(  0, "Midline",   color.gray ,               display = display.all         )                
                                                                                                           
                                                                                                           
sig  = plot(out,  "Fast Signal",          col,       3,    display = display.all         ),                
       plot(out,  "",           color.new(col, 85), 10,    display = display.pane        ),                
       plot(out,  "",           color.new(col, 98), 25,    display = display.pane        )                
sig2 = plot(out2, "Slow Signal",          col2,      3,    display = display.all, style = plot.style_area)
                                                                                                           
                                                                                                           
l1   = plot( 100, "",                     na,              display = display.data_window )                
l2   = plot(  50, "",           color.new(DnCol, 50),      display = display.data_window )                
l3   = plot( -50, "",           color.new(UpCol, 50),      display = display.data_window )                
l4   = plot(-100, "",                     na,              display = display.data_window )                
                                                                                                           
                                                                                                           
plotshape  (out, "",  shape.xcross,      color = fastTrend_dn ? color.new(DnCol, 15) : na,                
           location = location.absolute, size  = size.small                              )                
plotshape  (out, "",  shape.circle,      color = fastTrend_up ? color.new(UpCol, 15) : na,                
           location = location.absolute, size  = size.small                              )                
                                                                                                           
fill(l1, l2, 100,   50,         color.new(DnCol, 60),           color.new(chart.bg_color, 30))            
fill(l4, l3, -50, -100,         color.new(chart.bg_color, 30),  color.new(UpCol, 60)     )                
                                                                                                           
barcolor(barcol)                                                                                          
                                                                                                           

symbol = "CKR [QuantraSystems] >>> {{exchange}}:{{ticker}}"

// Fast Trend Alerts
alertcondition(fastTrend_up, "Fast Positive Trend",  symbol + " - Fast Positive Trend!" )
alertcondition(fastTrend_dn, "Fast Negative Trend",  symbol + " - Fast Negative Trend!" )

// Slow Trend Alerts  
alertcondition(slowTrend_up, "Slow Positive Trend",  symbol + " - Slow Positive Trend!" )
alertcondition(slowTrend_dn, "Slow Negative Trend",  symbol + " - Slow Negative Trend!" )

// Combined Alerts
alertcondition(fastTrend,    "Fast Trend Shift",     symbol + " - Fast Trend Shift!"    )
alertcondition(slowTrend,    "Slow Trend Shift",     symbol + " - Slow Trend Shift!"    )

    // Define Buy Exit condition
uptrend_condition = oversold
downtrend_condition = overbought


// Strategy entry and exit conditions
if (uptrend_condition)
    strategy.entry("Buy", strategy.long)
   
if (downtrend_condition)
    strategy.close("Buy")


*Feel free to share your different settings in the comment section


Comments