Computational Investing
Chris Harris
11 Nov 2014


Introduction


Beyond price action, a second initiative builds on indicator development, with a goal to use indicator signals as a means to drive quantitative investment decisions. Although one could envision indicator values as triggers to buy or sell stocks, by modifying event.py, in the quantitative analysis routine, only the indicators themselves will receive attention here. When considering momentum signals, the commodity channel index, CCI, will serve as a baseline. To flatten or linearize bollinger bands:

bollinger feature = ( price - mean ) / standard deviation


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.


Python Code


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()


Python Code


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()


PowerLanguage .NET Code

Multichart bollinger feature with trailing 6 period moving average


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;
                    }
                }
            }
        }
    }
}


Results


$ 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



Figure 1: GOOGL Stockchart; day, 20 period cci


figure1



Figure 2: GOOGL Stockchart; day, 20 period bf


figure2



Figure 3: GOOGL Stockchart; day, 40 period cci


figure3



Figure 4: GOOGL Stockchart; day, 40 period bf


figure4



Figure 5: YM Future Chart; 30 min, 20 period bf


figure5



Figure 6: YM Future Chart; 30 min, 40 period bf


figure6



Figure 7: YM Future Chart; 4096 tick, 20 period bf


figure7



Figure 8: YM Future Chart; 4096 tick, 40 period bf


figure8