|
| 1 | +def gentrends(x, window=1/3.0, charts=True): |
| 2 | + """ |
| 3 | + Returns a Pandas dataframe with support and resistance lines. |
| 4 | +
|
| 5 | + :param x: One-dimensional data set |
| 6 | + :param window: How long the trendlines should be. If window < 1, then it |
| 7 | + will be taken as a percentage of the size of the data |
| 8 | + :param charts: Boolean value saying whether to print chart to screen |
| 9 | + """ |
| 10 | + |
| 11 | + import numpy as np |
| 12 | + import pandas.io.data as pd |
| 13 | + |
| 14 | + x = np.array(x) |
| 15 | + |
| 16 | + if window < 1: |
| 17 | + window = int(window * len(x)) |
| 18 | + |
| 19 | + max1 = np.where(x == max(x))[0][0] # find the index of the abs max |
| 20 | + min1 = np.where(x == min(x))[0][0] # find the index of the abs min |
| 21 | + |
| 22 | + # First the max |
| 23 | + if max1 + window > len(x): |
| 24 | + max2 = max(x[0:(max1 - window)]) |
| 25 | + else: |
| 26 | + max2 = max(x[(max1 + window):]) |
| 27 | + |
| 28 | + # Now the min |
| 29 | + if min1 - window < 0: |
| 30 | + min2 = min(x[(min1 + window):]) |
| 31 | + else: |
| 32 | + min2 = min(x[0:(min1 - window)]) |
| 33 | + |
| 34 | + # Now find the indices of the secondary extrema |
| 35 | + max2 = np.where(x == max2)[0][0] # find the index of the 2nd max |
| 36 | + min2 = np.where(x == min2)[0][0] # find the index of the 2nd min |
| 37 | + |
| 38 | + # Create & extend the lines |
| 39 | + maxslope = (x[max1] - x[max2]) / (max1 - max2) # slope between max points |
| 40 | + minslope = (x[min1] - x[min2]) / (min1 - min2) # slope between min points |
| 41 | + a_max = x[max1] - (maxslope * max1) # y-intercept for max trendline |
| 42 | + a_min = x[min1] - (minslope * min1) # y-intercept for min trendline |
| 43 | + b_max = x[max1] + (maxslope * (len(x) - max1)) # extend to last data pt |
| 44 | + b_min = x[min1] + (minslope * (len(x) - min1)) # extend to last data point |
| 45 | + maxline = np.linspace(a_max, b_max, len(x)) # Y values between max's |
| 46 | + minline = np.linspace(a_min, b_min, len(x)) # Y values between min's |
| 47 | + |
| 48 | + # OUTPUT |
| 49 | + trends = np.transpose(np.array((x, maxline, minline))) |
| 50 | + trends = pd.DataFrame(trends, index=np.arange(0, len(x)), |
| 51 | + columns=['Data', 'Max Line', 'Min Line']) |
| 52 | + |
| 53 | + if charts is True: |
| 54 | + from matplotlib.pyplot import plot, grid, show |
| 55 | + plot(trends) |
| 56 | + grid() |
| 57 | + show() |
| 58 | + |
| 59 | + return trends, maxslope, minslope |
| 60 | + |
| 61 | +def segtrends(x, segments=2, charts=True): |
| 62 | + """ |
| 63 | + Turn minitrends to iterative process more easily adaptable to |
| 64 | + implementation in simple trading systems; allows backtesting functionality. |
| 65 | +
|
| 66 | + :param x: One-dimensional data set |
| 67 | + :param window: How long the trendlines should be. If window < 1, then it |
| 68 | + will be taken as a percentage of the size of the data |
| 69 | + :param charts: Boolean value saying whether to print chart to screen |
| 70 | + """ |
| 71 | + |
| 72 | + import numpy as np |
| 73 | + y = np.array(x) |
| 74 | + |
| 75 | + # Implement trendlines |
| 76 | + segments = int(segments) |
| 77 | + maxima = np.ones(segments) |
| 78 | + minima = np.ones(segments) |
| 79 | + segsize = int(len(y)/segments) |
| 80 | + for i in range(1, segments+1): |
| 81 | + ind2 = i*segsize |
| 82 | + ind1 = ind2 - segsize |
| 83 | + maxima[i-1] = max(y[ind1:ind2]) |
| 84 | + minima[i-1] = min(y[ind1:ind2]) |
| 85 | + |
| 86 | + # Find the indexes of these maxima in the data |
| 87 | + x_maxima = np.ones(segments) |
| 88 | + x_minima = np.ones(segments) |
| 89 | + for i in range(0, segments): |
| 90 | + x_maxima[i] = np.where(y == maxima[i])[0][0] |
| 91 | + x_minima[i] = np.where(y == minima[i])[0][0] |
| 92 | + |
| 93 | + if charts: |
| 94 | + import matplotlib.pyplot as plt |
| 95 | + plt.plot(y) |
| 96 | + plt.grid(True) |
| 97 | + |
| 98 | + for i in range(0, segments-1): |
| 99 | + maxslope = (maxima[i+1] - maxima[i]) / (x_maxima[i+1] - x_maxima[i]) |
| 100 | + a_max = maxima[i] - (maxslope * x_maxima[i]) |
| 101 | + b_max = maxima[i] + (maxslope * (len(y) - x_maxima[i])) |
| 102 | + maxline = np.linspace(a_max, b_max, len(y)) |
| 103 | + |
| 104 | + minslope = (minima[i+1] - minima[i]) / (x_minima[i+1] - x_minima[i]) |
| 105 | + a_min = minima[i] - (minslope * x_minima[i]) |
| 106 | + b_min = minima[i] + (minslope * (len(y) - x_minima[i])) |
| 107 | + minline = np.linspace(a_min, b_min, len(y)) |
| 108 | + |
| 109 | + if charts: |
| 110 | + plt.plot(maxline, 'g') |
| 111 | + plt.plot(minline, 'r') |
| 112 | + |
| 113 | + if charts: |
| 114 | + plt.show() |
| 115 | + |
| 116 | + # OUTPUT |
| 117 | + return x_maxima, maxima, x_minima, minima |
| 118 | + |
| 119 | +def minitrends(x, window=20, charts=True): |
| 120 | + """ |
| 121 | + Turn minitrends to iterative process more easily adaptable to |
| 122 | + implementation in simple trading systems; allows backtesting functionality. |
| 123 | +
|
| 124 | + :param x: One-dimensional data set |
| 125 | + :param window: How long the trendlines should be. If window < 1, then it |
| 126 | + will be taken as a percentage of the size of the data |
| 127 | + :param charts: Boolean value saying whether to print chart to screen |
| 128 | + """ |
| 129 | + |
| 130 | + import numpy as np |
| 131 | + |
| 132 | + y = np.array(x) |
| 133 | + if window < 1: # if window is given as fraction of data length |
| 134 | + window = float(window) |
| 135 | + window = int(window * len(y)) |
| 136 | + x = np.arange(0, len(y)) |
| 137 | + dy = y[window:] - y[:-window] |
| 138 | + crit = dy[:-1] * dy[1:] < 0 |
| 139 | + |
| 140 | + # Find whether max's or min's |
| 141 | + maxi = (y[x[crit]] - y[x[crit] + window] > 0) & \ |
| 142 | + (y[x[crit]] - y[x[crit] - window] > 0) * 1 |
| 143 | + mini = (y[x[crit]] - y[x[crit] + window] < 0) & \ |
| 144 | + (y[x[crit]] - y[x[crit] - window] < 0) * 1 |
| 145 | + maxi = maxi.astype(float) |
| 146 | + mini = mini.astype(float) |
| 147 | + maxi[maxi == 0] = np.nan |
| 148 | + mini[mini == 0] = np.nan |
| 149 | + xmax = x[crit] * maxi |
| 150 | + xmax = xmax[~np.isnan(xmax)] |
| 151 | + xmax = xmax.astype(int) |
| 152 | + xmin = x[crit] * mini |
| 153 | + xmin = xmin[~np.isnan(xmin)] |
| 154 | + xmin = xmin.astype(int) |
| 155 | + |
| 156 | + # See if better max or min in region |
| 157 | + yMax = np.array([]) |
| 158 | + xMax = np.array([]) |
| 159 | + for i in xmax: |
| 160 | + indx = np.where(xmax == i)[0][0] + 1 |
| 161 | + try: |
| 162 | + Y = y[i:xmax[indx]] |
| 163 | + yMax = np.append(yMax, Y.max()) |
| 164 | + xMax = np.append(xMax, np.where(y == yMax[-1])[0][0]) |
| 165 | + except: |
| 166 | + pass |
| 167 | + yMin = np.array([]) |
| 168 | + xMin = np.array([]) |
| 169 | + for i in xmin: |
| 170 | + indx = np.where(xmin == i)[0][0] + 1 |
| 171 | + try: |
| 172 | + Y = y[i:xmin[indx]] |
| 173 | + yMin = np.append(yMin, Y.min()) |
| 174 | + xMin = np.append(xMin, np.where(y == yMin[-1])[0][0]) |
| 175 | + except: |
| 176 | + pass |
| 177 | + if y[-1] > yMax[-1]: |
| 178 | + yMax = np.append(yMax, y[-1]) |
| 179 | + xMax = np.append(xMax, x[-1]) |
| 180 | + if y[0] not in yMax: |
| 181 | + yMax = np.insert(yMax, 0, y[0]) |
| 182 | + xMax = np.insert(xMax, 0, x[0]) |
| 183 | + if y[-1] < yMin[-1]: |
| 184 | + yMin = np.append(yMin, y[-1]) |
| 185 | + xMin = np.append(xMin, x[-1]) |
| 186 | + if y[0] not in yMin: |
| 187 | + yMin = np.insert(yMin, 0, y[0]) |
| 188 | + xMin = np.insert(xMin, 0, x[0]) |
| 189 | + |
| 190 | + # Plot results if desired |
| 191 | + if charts is True: |
| 192 | + from matplotlib.pyplot import plot, show, grid |
| 193 | + plot(x, y) |
| 194 | + plot(xMax, yMax, '-o') |
| 195 | + plot(xMin, yMin, '-o') |
| 196 | + grid(True) |
| 197 | + show() |
| 198 | + # Return arrays of critical points |
| 199 | + return xMax, yMax, xMin, yMin |
| 200 | + |
| 201 | +def iterlines(x, window=30, charts=True): |
| 202 | + """ |
| 203 | + Turn minitrends to iterative process more easily adaptable to |
| 204 | + implementation in simple trading systems; allows backtesting functionality. |
| 205 | +
|
| 206 | + :param x: One-dimensional data set |
| 207 | + :param window: How long the trendlines should be. If window < 1, then it |
| 208 | + will be taken as a percentage of the size of the data |
| 209 | + :param charts: Boolean value saying whether to print chart to screen |
| 210 | + """ |
| 211 | + |
| 212 | + import numpy as np |
| 213 | + |
| 214 | + x = np.array(x) |
| 215 | + n = len(x) |
| 216 | + if window < 1: |
| 217 | + window = int(window * n) |
| 218 | + sigs = np.zeros(n, dtype=float) |
| 219 | + |
| 220 | + i = window |
| 221 | + while i != n: |
| 222 | + if x[i] > max(x[i-window:i]): sigs[i] = 1 |
| 223 | + elif x[i] < min(x[i-window:i]): sigs[i] = -1 |
| 224 | + i += 1 |
| 225 | + |
| 226 | + xmin = np.where(sigs == -1.0)[0] |
| 227 | + xmax = np.where(sigs == 1.0)[0] |
| 228 | + ymin = x[xmin] |
| 229 | + ymax = x[xmax] |
| 230 | + if charts is True: |
| 231 | + from matplotlib.pyplot import plot, grid, show |
| 232 | + plot(x) |
| 233 | + plot(xmin, ymin, 'ro') |
| 234 | + plot(xmax, ymax, 'go') |
| 235 | + grid(True) |
| 236 | + show() |
| 237 | + |
| 238 | + return sigs |
0 commit comments