Indicator · Pine Script v4 · On the chart

Coppock Curve Strategy

by capissimo

This study builds a Coppock curve from two rate-of-change readings smoothed by a weighted moving average and marks signals on the price chart.

View on GitHub

Repaints

GitHub stars114on the repository
Pine versionv4older, still runs
Lines of code177
Settings12inputs
LicenceNone statedfile: MPL-2.0
Last update1 year ago7 Nov 2024

Add It to Your TradingView Chart

  1. 1Copy the scriptPress Copy script above, or the copy button on the code below.
  2. 2Open the Pine EditorOpen a TradingView chart and choose Pine Editor at the bottom of the screen.
  3. 3Paste over the templateCreate a new indicator, select all of the template text and paste. Press Save and give it a name.
  4. 4Add it to the chartPress Add to chart, then adjust the settings with the gear icon next to its name.

Source Code

177 lines of Pine Script v4 from scripts/119-Coppock-Curve-Strategy.pine, published under MPL-2.0 (file header). Keep the author's credit and licence lines when you reuse it.

119-Coppock-Curve-Strategy.pine
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © capissimo

//@version=4
study('Coppock Curve Strategy', '', true)

//  Coppock Curve Strategy

//  Description:

//     The Coppock Indicator is a long-term price momentum oscillator 
//     which is used primarily to pinpoint major bottoms in the stock market.
//     Crosses above the zero line indicate buying pressure, crosses below the zero
//     line indicate selling pressure.

//     This script generates a long entry signal when the Coppock value crosses over 
//     a signal line, and/or generates a short entry signal when the value crosses
//     under a signal line.

//     Also it generates a long exit signal when the Coppock value crosses under
//     a signal line, and/or generates a short exit signal when the value crosses
//     over a signal line.

//  Signals can be filtered out by volatility, volume or both. To minimize 
//  repainting use higher percentage values of Time Threshold parameter.

//-------------------- Inputs    

ptype     = input('Close',     'Price Type',                    options=['Open','High','Low','Close','HL2','OC2','OHL3','HLC3','OHLC4'])
shortlag  = input(11,          'Short Lag |1..n|',              minval=1)  // 14, 20
longlag   = input(22,          'Long Lag |1..n|',               minval=1)  // 28, 40
wmalag    = input(2,           'WMA Lag |1..n|',                minval=1)  // 8, 10
method    = input('Trigger',   'Method',                        options=['Center','Trigger'])
triglag   = input(5,           'Trigger Lag',                   minval=1)
ftype     = input('Volatility','Filtering by',                  options=['Volatility','Volume','Both','None'])
tthres    = input(0.01,        'Time Threshold (%) |0.0..1.0|', minval=0.0, maxval=1.0, step=0.01)
holding_p = input(5,           'Holding Period |1..n|',         minval=1)

//-------------------- System Variables

var int BUY  =  1
var int SELL = -1
var int HOLD =  0

//-------------------- Series

var bool  long    = na
var bool  short   = na
var int   signal  = HOLD
var float trigger = 0.0
var float copzz   = ohlc4
var int   hp_counter = 0

//-------------------- Custom Functions    

coppock(ds, lag, short, long) => s = roc(ds, short), l = roc(ds, long), wma(s + l, lag)

volumeBreak(thres) =>  
    rsivol   = rsi(volume, 14)  
    osc      = hma(rsivol, 10)  
    osc > thres                     

volatilityBreak(volmin, volmax) => atr(volmin) > atr(volmax)

//-------------------- Logic

tbase   = (time - time[1]) / 1000
tcurr   = (timenow - time_close[1]) / 1000
barlife = tcurr / tbase

base =  ptype=='Open'  ? open 
      : ptype=='High'  ? high
      : ptype=='Low'   ? low
      : ptype=='Close' ? close
      : ptype=='OC2'   ? (open+close)/2 
      : ptype=='HL2'   ? hl2 
      : ptype=='OHL3'  ? (open+high+low)/3 
      : ptype=='HLC3'  ? hlc3 
      :                  ohlc4

filter =   ftype=='Volatility' ? volatilityBreak(1, 10) 
         : ftype=='Volume'     ? volumeBreak(49) 
         : ftype=='Both'       ? volatilityBreak(1, 10) and volumeBreak(49)
         :                       true

//-- Core
cop = coppock(base, wmalag, shortlag, longlag)

if method=='Center'
    long    := crossover(cop,  HOLD) 
    short   := crossunder(cop, HOLD) 
if method=='Trigger'
    trigger := sma(cop, triglag)
    long  := crossover(cop,  trigger) 
    short := crossunder(cop, trigger) 

signal := long and filter ? BUY : short and filter ? SELL : nz(signal[1])
copzz  := long and filter ? low : short and filter ? high : nz(copzz[1])

changed = change(signal)
hp_counter := changed ? 0 : hp_counter + 1
//--

startLongTrade  = barlife > tthres and changed and signal==BUY    
startShortTrade = barlife > tthres and changed and signal==SELL   
endLongTrade    = (changed and signal==SELL) or (signal==BUY  and hp_counter==holding_p and not changed) 
endShortTrade   = (changed and signal==BUY)  or (signal==SELL and hp_counter==holding_p and not changed) 

//-------------------- Visualization    

plot(copzz, "C-Curve", cop > cop[1] ? color.blue : color.red, 2, transp=0)

plotshape(startLongTrade  ? copzz : na, 'Buy',  shape.labelup,   location.absolute, color.blue, text='c', size=size.tiny) 
plotshape(startShortTrade ? copzz : na, 'Sell', shape.labeldown, location.absolute, color.red,  text='c', size=size.tiny) 
plot(endLongTrade         ? ohlc4   : na, 'StopBuy',  color.blue, 2, plot.style_cross)
plot(endShortTrade        ? ohlc4   : na, 'StopSell', color.red,  2, plot.style_cross)

//-------------------- Notification

if changed and signal==BUY 
    alert('Buy Alert', alert.freq_once_per_bar)  // alert.freq_once_per_bar_close
if changed and signal==SELL 
    alert('Sell Alert', alert.freq_once_per_bar)
    
alertcondition(startLongTrade,  'Buy Alert',  'Go Long!')
alertcondition(startShortTrade, 'Sell Alert', 'Go Short!')

//-------------------- Backtest

show_info = input(false, '===Information===')
lot_size  = input(0.01,  'Lot Size', options=[0.01,0.1,0.2,0.3,0.5,1,2,3,5,10,20,30,50,100,1000]) 
ubase     = input(false, 'Use Base Price?')

bidask = ubase ? base : open 

var float start_long_trade  = bidask  
var float long_trades       = 0.
var float start_short_trade = bidask  
var float short_trades      = 0.
var int   wins              = 0
var int   trade_count       = 0

if startLongTrade 
    start_long_trade := bidask 
if endLongTrade
    ldiff         = (bidask - start_long_trade)
    wins         := ldiff > 0 ? 1 : 0
    long_trades  := ldiff * lot_size   
    trade_count  := 1
if startShortTrade 
    start_short_trade := bidask
if endShortTrade
    sdiff         = (start_short_trade - bidask)
    wins         := sdiff > 0 ? 1 : 0
    short_trades := sdiff * lot_size 
    trade_count  := 1
    
cumreturn   = cum(long_trades) + cum(short_trades)  //-- cumulative return 
totaltrades = cum(trade_count)
totalwins   = cum(wins)  
totallosses = totaltrades - totalwins == 0 ? 1 : totaltrades - totalwins

//------------------- Information

var label lbl = na

info =  ptype
      + '\nCR='        + tostring(cumreturn,             '#.#') 
      + '\nTrades: '   + tostring(totaltrades,           '#')
      + '\nWin/Loss: ' + tostring(totalwins/totallosses, '#.##') 
      + '\nWinrate: '  + tostring(totalwins/totaltrades, '#.#%')       
      + '\nBar Time: ' + tostring(barlife,               '#.#%')

if show_info and barstate.islast  
    lbl := label.new(bar_index, ohlc4, info, xloc.bar_index, yloc.price, 
                     color.new(color.blue, 100), label.style_label_left, color.black, size.small, text.align_left)
    label.delete(lbl[1])

Overview

Long entries occur when the curve crosses above zero or a simple moving-average trigger, and short entries occur on the opposite cross; the reverse cross is the exit cue. Volatility, volume, or both can filter signals, while the holding period, lot size, and time threshold change signal duration and live-bar timing. It does not place orders, and a low time threshold can leave signals changing before the bar closes.

Details

Published by

capissimo on GitHub

Type

Indicator, Pine Script v4

Draws

On the price chart

Category

Oscillators & momentum

Markets

Any symbol

Timeframes

Any timeframe

Risk Notes

  • Signals can change on the live bar or after it closes (repainting)

Settings

The inputs you can change from the gear icon on the chart. Defaults are the author's.

SettingTypeDefaultVariable
Price TypestringCloseptype
Short Lag |1..n|int11shortlag
Long Lag |1..n|int22longlag
WMA Lag |1..n|int2wmalag
MethodstringTriggermethod
Trigger Lagint5triglag
Filtering bystringVolatilityftype
Time Threshold (%) |0.0..1.0|float0.01tthres
Holding Period |1..n|int5holding_p
===Information===boolfalseshow_info
Lot Sizefloat0.01lot_size
Use Base Price?boolfalseubase
Third-party code. ForexR did not write, test or endorse this script, and the summary above was generated automatically from its code and README. Indicators describe the past, and a strategy's backtest can look better than live trading, especially when a script repaints. Check it in the Strategy Tester and on a demo account before you rely on it.

Similar Pine Scripts

948 stars

The Adaptive RSI Moving Average (ARSIMA) is an overlay indicator that dynamically adjusts its smoothing factor based on the Relative Strength Index (RSI). When the RSI moves toward extreme overbought or oversold conditions, the smoothing factor increases to ma

Indicator v4 Moving averagesOscillators & momentum
Updated 10 days ago · GPL-3.0 GitHub repository of Adaptive RSI Moving Average

This overlay indicator screens a pasted list of up to forty symbols and draws a table on the price chart. It classifies bullish or bearish setups from the percent change between the current candle and the candle 250 bars back, then shows RSI with a simple movi

Indicator v5 Oscillators & momentumVolume
Updated 1 year ago · MPL-2.0 GitHub repository of Momentum Setup - Ankush Bajaj Momentum Investing Setup

This indicator plots trade entry and exit signals on the price chart by combining Bollinger Bands with optional filter conditions. It calculates standard Bollinger Bands along with RSI, Aroon, and moving average filters. Reversal signals trigger when price bre

Indicator v4 Volatility & bandsOscillators & momentum
Updated 2 months ago · None stated GitHub repository of Bollinger Bands Winner IND [Alorse]
318 stars

This indicator plots three moving averages on the price chart alongside colored fills between the lines to visualize trend structure. Internally, it calculates a Stochastic RSI oscillator to detect oversold reversals. When the Stochastic %K line rises above 10

Indicator v5 Moving averagesOscillators & momentum
Updated 2 months ago · MIT GitHub repository of TVT 3X Scale In Out
285 stars

Mean Reversion Study is an indicator that identifies trade setups combining exponential moving averages, RSI extremes, and engulfing candlestick patterns. It highlights bullish setups when a bullish engulfing candle forms below the EMA while RSI is oversold, a

Indicator v4 Mean reversionCandlestick patterns
Updated 3 years ago · None stated GitHub repository of Mean Reversion Study

More indicators

Trade Your Charts With a Regulated Broker

Compare brokers that connect to TradingView, with spreads, minimum deposits and leverage side by side.

Compare brokers