yields a normalized, unitless quantity, a number of standard deviations above or below the mean. By producing a value relative to key reference areas: +2 standard deviations, mean, -2 standard deviations, it captures the behavior of bollinger bands. With the remarkable shape conformation between the bollinger feature and CCI, the bollinger bands depict a 2-D graphical illustration of momentum. When the bollinger bands contract to a narrow range, momentum indicator noise becomes apparent, as the weak bandwidth amplifies superficial momentum shifts.
Although John Bollinger promotes a 20 period moving average as a reference frame, a 40 period momentum profile dwells primarily above zero in an uptrend, and below zero in a downtrend. Conventional scientific techniques suggest a 40 sample population count represents a minimum threshold to ensure statistical significance. Hence, statistical knowledge may explain why institutional investors recognize the 50 period moving average as the boundary between buy and sell. A notable departure from this guideline includes the relative strength index, RSI, where a 14 period momentum value corresponds to a 40 period CCI. When comparing performance, put the indicators side by side to observe response times.
cci.py:
import os
import shutil
import math
import matplotlib as mpl
import matplotlib.pyplot as plt
# obtain market data
def acquire(sym,interval):
if not os.path.isfile("../data/%s.csv" %sym):
shutil.copy("../QSTK-0.2.8/QSTK/QSData/Yahoo/%s.csv" %sym, "../data")
data = open("../data/%s.csv" %sym,'r')
stream = data.read()
data.close()
field = 7
entry = ""
val = []
matrix = []
for ch in stream:
entry = entry + ch
if ch==',' or ch=='\n':
if len(entry)>1:
val.append(entry[:-1])
entry = ""
if len(val)>=field:
if interval[1] >= val[0] >= interval[0]:
matrix.append(val)
val = []
matrix.sort()
return matrix
def plot(label,matrix,mean,cci,delta,period):
x = []
y = [[]for l in range(2)]
Y = []
hd = 0
hs = [-100,100]
xl = [-10,period-delta+10]
mpl.rc('text', color='#C8A078')
mpl.rc('figure', facecolor='black', edgecolor='black')
mpl.rc('axes', edgecolor='#C6BDBA', labelcolor='#C8A078', facecolor='black', linewidth=2)
mpl.rc('xtick', color='#C8A078')
mpl.rc('ytick', color='#C8A078')
plt.tick_params(bottom=False, top=False, left=False, right=False)
plt.figure(1)
plt.subplot(211)
for i in range(delta-1,period):
x.append(float(i-delta+1))
y[0].append(mean[i])
y[1].append(cci[i])
Y.append(float(matrix[i][6]))
plt.plot(x, Y, color='#004040', linewidth=2)
plt.plot(x, y[0], color='#640064', linewidth=2)
plt.xlim(xl)
plt.title("%s Stockchart: Jan 2008 to Dec 2009" %label, fontsize=25)
plt.xticks(fontsize=20)
plt.yticks(fontsize=20)
plt.ylabel("Price", fontsize=25)
plt.subplot(212)
plt.hlines(hs, xl[0], xl[1], linestyles='solid', color='#F5A078', linewidth=1)
plt.hlines(hd, xl[0], xl[1], linestyles='dotted', color='#F5A078', linewidth=2)
plt.plot(x, y[1], color='#004000', linewidth=2)
plt.xlim(xl)
plt.xticks(fontsize=20)
plt.yticks(fontsize=20)
plt.xlabel("Trade days", fontsize=25)
plt.ylabel("CCI", fontsize=25)
plt.show()
def cci(symbol,delta,interval):
# input GOOGL info
matrix = acquire(symbol,interval)
period = len(matrix)
# evaluate statistical parameters over lookback period
# --------------------------------------------------------------------------------------------
#
# need extra month to accommodate stockchart
#
# --------------------------------------------------------------------------------------------
print("\n\t Date\t\t Index\t\tPrice\t\tMean\t\tAbDev\t\tCCI\n")
pt = [0.0 for p in range(period)]
med = [0.0 for q in range(period)]
mean = [0.0 for r in range(period)]
ad = [0.0 for s in range(period)]
cci = [0.0 for t in range(period)]
for i in range(delta-1,period):
sm = 0.0
sad = 0.0
init = False
for j in range(i-delta+1,i+1):
pt[j] = (float(matrix[j][2]) + float(matrix[j][3]) + float(matrix[j][4]))/3.0*float(matrix[j][6])/float(matrix[j][4])
sm = sm + pt[j]
if init:
if pt[j] > pth:
pth = pt[j]
if pt[j] < ptl:
ptl = pt[j]
else:
pth = pt[j]
ptl = pt[j]
init = True
med[i] = (pth + ptl)/2.0
mean[i] = sm/float(delta)
for j in range(i-delta+1,i+1):
d = abs(pt[j] - med[i])
sad = sad + d
ad[i] = sad/float(delta)
cci[i] = (pt[i] - mean[i])/ad[i]/0.015
print("\t%s\t\t%i\t\t%s\t\t%.4g\t\t%.4g\t\t%.4g" %(matrix[i][0],i,matrix[i][6],mean[i],ad[i],cci[i]))
# display results
print("\n # %i-period lookback cycles =\t%i\n" %(delta,period-delta))
plot(symbol,matrix,mean,cci,delta,period)
return cci
def main():
delta = 20
symbol = "GOOGL"
interval = ["2007-12-04","2009-12-31"]
cf = cci(symbol,delta,interval)
main()
bollinger.py:
import os
import shutil
import math
import matplotlib as mpl
import matplotlib.pyplot as plt
# obtain market data
def acquire(sym,interval):
if not os.path.isfile("../data/%s.csv" %sym):
shutil.copy("../QSTK-0.2.8/QSTK/QSData/Yahoo/%s.csv" %sym, "../data")
data = open("../data/%s.csv" %sym,'r')
stream = data.read()
data.close()
field = 7
entry = ""
val = []
matrix = []
for ch in stream:
entry = entry + ch
if ch==',' or ch=='\n':
if len(entry)>1:
val.append(entry[:-1])
entry = ""
if len(val)>=field:
if interval[1] >= val[0] >= interval[0]:
matrix.append(val)
val = []
matrix.sort()
return matrix
def plot(label,matrix,mean,std,rat,delta,period):
x = []
y = [[]for l in range(4)]
Y = []
hd = 0
hs = [-2,2]
xl = [-10,period-delta+10]
mpl.rc('text', color='#C8A078')
mpl.rc('figure', facecolor='black', edgecolor='black')
mpl.rc('axes', edgecolor='#C6BDBA', labelcolor='#C8A078', facecolor='black', linewidth=2)
mpl.rc('xtick', color='#C8A078')
mpl.rc('ytick', color='#C8A078')
plt.tick_params(bottom=False, top=False, left=False, right=False)
plt.figure(1)
plt.subplot(211)
for i in range(delta-1,period):
x.append(float(i-delta+1))
y[0].append(mean[i])
y[1].append(mean[i] - std[i])
y[2].append(mean[i] + std[i])
y[3].append(rat[i])
Y.append(float(matrix[i][6]))
plt.plot(x, Y, color='#004040', linewidth=2)
plt.plot(x, y[0], color='#F5A078', linewidth=2)
plt.plot(x, y[1], color='#640064', linewidth=2)
plt.plot(x, y[2], color='#640064', linewidth=2)
plt.xlim(xl)
plt.title("%s Stockchart: Jan 2008 to Dec 2009" %label, fontsize=25)
plt.xticks(fontsize=20)
plt.yticks(fontsize=20)
plt.ylabel("Price", fontsize=25)
plt.subplot(212)
plt.hlines(hs, xl[0], xl[1], linestyles='solid', color='#F5A078', linewidth=1)
plt.hlines(hd, xl[0], xl[1], linestyles='dotted', color='#F5A078', linewidth=2)
plt.plot(x, y[3], color='#004000', linewidth=2)
plt.xlim(xl)
plt.xticks(fontsize=20)
plt.yticks(fontsize=20)
plt.xlabel("Trade days", fontsize=25)
plt.ylabel("Bollinger Feature", fontsize=25)
plt.show()
def bollinger(symbol,delta,interval):
# input GOOGL info
matrix = acquire(symbol,interval)
period = len(matrix)
# evaluate statistical parameters over lookback period
# --------------------------------------------------------------------------------------------
#
# need extra month to accommodate stockchart
#
# --------------------------------------------------------------------------------------------
print("\n\t Date\t\t Index\t\tPrice\t\tMean\t\tStDev\t\tFeature\n")
std = [0.0 for r in range(period)]
mean = [0.0 for s in range(period)]
rat = [0.0 for t in range(period)]
for i in range(delta-1,period):
sm = 0.0
sd2 = 0.0
for j in range(i-delta+1,i+1):
sm = sm + float(matrix[j][6])
mean[i] = sm/float(delta)
for j in range(i-delta+1,i+1):
d = float(matrix[j][6]) - mean[i]
sd2 = sd2 + d**2.0
std[i] = math.sqrt(sd2/float(delta))
rat[i] = (float(matrix[i][6]) - mean[i])/std[i]
print("\t%s\t\t%i\t\t%s\t\t%.4g\t\t%.4g\t\t%.4g" %(matrix[i][0],i,matrix[i][6],mean[i],std[i],rat[i]))
# display results
print("\n # %i-period lookback cycles =\t%i\n" %(delta,period-delta))
plot(symbol,matrix,mean,std,rat,delta,period)
return rat
def main():
delta = 20
symbol = "GOOGL"
interval = ["2007-12-04","2009-12-31"]
bf = bollinger(symbol,delta,interval)
main()
Bollinger_Ratio_Triangle.pln:
using System;
using System.Drawing;
using PowerLanguage.Function;
namespace PowerLanguage.Indicator
{
[SameAsSymbol(true)]
public class Bollinger_Ratio_Triangle : IndicatorObject
{
private TriAverage m_triaverage1;
private TriAverage m_triaverage2;
private VariableSeries<Double> ratio;
private Function.NormGradientColor m_normgradientcolor1;
private int m_applicationtype;
private IPlotObject Plot1;
private IPlotObject Plot2;
private IPlotObject Plot3;
private IPlotObject Plot4;
private IPlotObject Plot5;
public Bollinger_Ratio_Triangle(object ctx) :
base(ctx){
axis = 0;
numdevsdn = -2;
numdevsup = 2;
avelength = 6;
bollength = 20;
gridforegroundcolor = Color.Black;
dncolor = Color.Red;
upcolor = Color.Yellow;
colornormlength = 14;
}
private ISeries<double> bollingerprice { get; set; }
[Input]
public int avelength { get; set; }
[Input]
public int bollength { get; set; }
[Input]
public double numdevsup { get; set; }
[Input]
public double numdevsdn { get; set; }
[Input]
public int axis { get; set; }
[Input]
public int colornormlength { get; set; }
[Input]
public Color upcolor { get; set; }
[Input]
public Color dncolor { get; set; }
[Input]
public Color gridforegroundcolor { get; set; }
protected override void Create(){
m_triaverage1 = new TriAverage(this);
m_triaverage2 = new TriAverage(this);
ratio = new VariableSeries<Double>(this);
m_normgradientcolor1 = new Function.NormGradientColor(this);
Plot1 = AddPlot(new PlotAttributes("Axis", 0, Color.Gray, Color.Empty, 0, 0, true));
Plot2 = AddPlot(new PlotAttributes("Low", 0, Color.Gray, Color.Empty, 0, 0, true));
Plot3 = AddPlot(new PlotAttributes("High", 0, Color.Gray, Color.Empty, 0, 0, true));
Plot4 = AddPlot(new PlotAttributes("Ratio", 0, Color.Cyan, Color.Empty, 0, 0, true));
Plot5 = AddPlot(new PlotAttributes("Ave", 0, Color.Blue, Color.Empty, 0, 0, true));
}
protected override void StartCalc(){
bollingerprice = Bars.Close;
m_triaverage1.price = bollingerprice;
m_triaverage1.length = bollength;
m_triaverage2.price = ratio;
m_triaverage2.length = avelength;
m_normgradientcolor1.dataseriesvalue = m_triaverage2;
m_normgradientcolor1.crosseszero = true;
m_normgradientcolor1.colornormlength = colornormlength;
m_normgradientcolor1.upcolor = upcolor;
m_normgradientcolor1.dncolor = dncolor;
m_applicationtype = (int) Environment.ApplicationCode;
}
protected override void CalcBar(){
var m_avg = m_triaverage1[0];
var m_sdev = bollingerprice.StandardDeviationCustom(bollength, 1);
if(m_sdev > 0.0) ratio.Value = (bollingerprice[0] - m_avg)/m_sdev;
else ratio.Value = 0.0;
Plot1.Set(0, axis);
Plot2.Set(0, numdevsdn);
Plot3.Set(0, numdevsup);
Plot4.Set(0, ratio[0]);
Plot5.Set(0, m_triaverage2[0]);
if (!upcolor.IsEmpty && !dncolor.IsEmpty){
var m_colorlevel = m_normgradientcolor1.Value;
if (m_applicationtype == 1){
Plot5.Colors[0] = m_colorlevel;
}
else{
if (m_applicationtype > 1){
Plot5.Colors[0] = gridforegroundcolor;
Plot5.BGColor = m_colorlevel;
}
}
}
}
}
}
$ python cci.py
Date Index Price Mean AbDev CCI
2008-01-02 19 342.94 348.1 5.419 -53.97
2008-01-03 20 343.01 348.1 5.457 -76.75
2008-01-04 21 328.83 347.3 6.251 -158
2008-01-07 22 324.95 345.8 7.813 -176.4
2008-01-08 23 316.16 344 8.949 -172.8
2008-01-09 24 326.93 342.1 9.924 -135.9
2008-01-10 25 323.69 340.6 9.773 -111
2008-01-11 26 319.44 339.1 10.1 -126.1
2008-01-14 27 327.24 338.1 10.19 -76.45
2008-01-15 28 319.14 336.8 10.54 -102.1
...
2009-12-17 514 297.27 293.4 3.038 97.45
2009-12-18 515 298.51 294 3.052 101.9
2009-12-21 516 299.64 294.7 2.43 126.4
2009-12-22 517 300.86 295.2 2.591 137.7
2009-12-23 518 306.15 295.9 3.08 194.4
2009-12-24 519 309.55 296.7 4.065 196.9
2009-12-28 520 311.75 297.8 5.569 164.4
2009-12-29 521 310.01 298.8 6.139 129.7
2009-12-30 522 311.68 299.6 6.174 121.7
2009-12-31 523 310.30 300.4 6.248 114.8
# 20-period lookback cycles = 504
$ python bollinger.py
Date Index Price Mean StDev Feature
2008-01-02 19 342.94 348.1 6.618 -0.7855
2008-01-03 20 343.01 348.2 6.594 -0.7823
2008-01-04 21 328.83 347.1 7.81 -2.343
2008-01-07 22 324.95 345.5 8.773 -2.34
2008-01-08 23 316.16 343.4 10.39 -2.62
2008-01-09 24 326.93 341.8 10.29 -1.442
2008-01-10 25 323.69 340.5 10.82 -1.549
2008-01-11 26 319.44 338.9 11.5 -1.694
2008-01-14 27 327.24 337.9 11.6 -0.9205
2008-01-15 28 319.14 336.6 12.15 -1.437
...
2009-12-17 514 297.27 293.5 3.39 1.1
2009-12-18 515 298.51 294.1 3.177 1.379
2009-12-21 516 299.64 294.8 2.678 1.79
2009-12-22 517 300.86 295.3 2.862 1.937
2009-12-23 518 306.15 296 3.598 2.812
2009-12-24 519 309.55 296.9 4.582 2.771
2009-12-28 520 311.75 297.9 5.357 2.58
2009-12-29 521 310.01 298.8 5.769 1.936
2009-12-30 522 311.68 299.7 6.34 1.895
2009-12-31 523 310.30 300.5 6.604 1.488
# 20-period lookback cycles = 504
$ python cci.py
Date Index Price Mean AbDev CCI
2008-01-31 39 282.43 326.5 25.94 -122.3
2008-02-01 40 258.21 324.4 29.12 -145.9
2008-02-04 41 247.96 322 31.72 -150.5
2008-02-05 42 253.65 319.4 31.83 -143.3
2008-02-06 43 251.11 316.7 31.84 -135.4
2008-02-07 44 252.73 314.1 32.63 -125.6
2008-02-08 45 258.60 311.7 32.46 -111.3
2008-02-11 46 260.84 309.4 32.31 -102
2008-02-12 47 259.30 307.3 32.26 -96.53
2008-02-13 48 267.58 305.2 32.08 -83.6
...
2009-12-17 514 297.27 285.7 8.699 93.02
2009-12-18 515 298.51 286.3 8.912 92.88
2009-12-21 516 299.64 286.8 9.164 90.99
2009-12-22 517 300.86 287.4 9.212 95.23
2009-12-23 518 306.15 288.1 8.592 129.9
2009-12-24 519 309.55 289.1 8.208 159.4
2009-12-28 520 311.75 290 8.145 176.3
2009-12-29 521 310.01 291 8.204 160.3
2009-12-30 522 311.68 292.1 8.158 153.6
2009-12-31 523 310.30 293.2 7.685 156.3
# 40-period lookback cycles = 484
$ python bollinger.py
Date Index Price Mean StDev Feature
2008-01-31 39 282.43 326.3 27.03 -1.622
2008-02-01 40 258.21 324.2 28.9 -2.282
2008-02-04 41 247.96 321.6 30.95 -2.38
2008-02-05 42 253.65 319 32.14 -2.033
2008-02-06 43 251.11 316.3 33.22 -1.963
2008-02-07 44 252.73 313.7 33.93 -1.796
2008-02-08 45 258.60 311.4 34.48 -1.531
2008-02-11 46 260.84 309.2 34.79 -1.389
2008-02-12 47 259.30 306.9 35.09 -1.358
2008-02-13 48 267.58 305 35.06 -1.067
...
2009-12-17 514 297.27 285.9 9.432 1.205
2009-12-18 515 298.51 286.4 9.529 1.268
2009-12-21 516 299.64 287 9.627 1.314
2009-12-22 517 300.86 287.6 9.738 1.364
2009-12-23 518 306.15 288.4 9.925 1.791
2009-12-24 519 309.55 289.4 10.03 2.013
2009-12-28 520 311.75 290.3 10.38 2.07
2009-12-29 521 310.01 291.3 10.22 1.831
2009-12-30 522 311.68 292.4 9.961 1.935
2009-12-31 523 310.30 293.4 9.61 1.755
# 40-period lookback cycles = 484