def cusum(other_args: List[str], stock: pd.DataFrame): """Cumulative sum algorithm (CUSUM) to detect abrupt changes in data Parameters ---------- other_args : str Command line arguments to be processed with argparse ticker : str Ticker of the stock stock : pd.DataFrame Stock data """ parser = argparse.ArgumentParser( add_help=False, prog="cusum", description=""" Cumulative sum algorithm (CUSUM) to detect abrupt changes in data """, ) parser.add_argument( "-t", "--threshold", dest="threshold", type=float, default=(max(stock["Adj Close"].values) - min(stock["Adj Close"].values)) / 40, help="threshold", ) parser.add_argument( "-d", "--drift", dest="drift", type=float, default=(max(stock["Adj Close"].values) - min(stock["Adj Close"].values)) / 80, help="drift", ) try: ns_parser = parse_known_args_and_warn(parser, other_args) if not ns_parser: return stock = stock["Adj Close"] detect_cusum(stock.values, ns_parser.threshold, ns_parser.drift, True, True) if gtff.USE_ION: plt.ion() plt.show() print("") except Exception as e: print(e, "\n") return
def display_cusum(df: pd.DataFrame, target: str, threshold: float, drift: float): """Cumulative sum algorithm (CUSUM) to detect abrupt changes in data Parameters ---------- df : pd.DataFrame Dataframe target : str Column of data to look at threshold : float Threshold value drift : float Drift parameter """ detect_cusum(df[target].values, threshold, drift, True, True) if gtff.USE_ION: plt.ion() plt.show() print("")
def calculate_cusum(data, threshold, drift): ta, tai, taf, amp = detect_cusum(data['Data'], threshold, drift, ending=True, show=False) data["Cumulative Sum Algorithm"] = 0 start = False for i in range(5, len(data["Cumulative Sum Algorithm"])): if i in tai: start = True elif i in taf: start = False if start: data["Cumulative Sum Algorithm"].at[i] = 1 plt.clf() return "Cumulative Sum Algorithm"
def cu_changepoint(f, window=25): # change point detection based on cusum # no generic way to set up threshold and drift # f, window = pre_changepoint(ts_, window=window) # ycol = 'dtrend_diff' # dtrend # used to detect changes in trend # ts = f[ycol].values ts = f['dtrend_diff'].values if f['period'].isnull().sum() == 0: window = f.loc[f.index[0], 'period'] min_ix = f.index.min() m = 8.0 threshold = m * f['dtrend_diff'].std() thres = threshold while thres >= threshold / m: drift = f['dtrend_diff'].std() while drift > f['dtrend_diff'].std() / 10: ta, tai, taf, amp = detect_cusum(ts, threshold=thres, drift=drift, ending=False, show=False) print('thres: ' + str(thres) + ' drift: ' + str(drift) + ' ta: ' + str(min_ix + ta) + ' tai: ' + str(min_ix + tai) + ' taf: ' + str(taf)) drift /= 2 thres /= 2
def analyseStocks(symbol, investAmount, thresholdMargin=50000): df = getDailyDataFromMarketstack(symbol, '2020-07-01') if df.empty: return ('empty', symbol, 0, 0) minClose = min(df['Close']) maxClose = max(df['Close']) lastClose = df['Close'][-1] difMinMax = maxClose - minClose dateValue = pd.DataFrame() dateValue['Date'] = df['Date'] dateValue['Value'] = df['Close'] lastFallDelta = getLastFallDelta(dateValue) #logging.debug("minClose: ", minClose, " maxClose: ", maxClose, "lastClose: ", lastClose, " diffMinMax: ", difMinMax, ' lastFallDelta: ', lastFallDelta) ta, tai, taf, amp = detect_cusum(df['Close'], 200, .05, True, False) #logging.debug(ta, tai, taf, amp) stocksToBuy = getAdjustedStocksToBuy(lastClose, investAmount) totalInvestCost = lastClose * stocksToBuy + transactionTax(investAmount) logging.debug("totalinvestcost: %s", totalInvestCost) potentialStocksSold = maxClose * stocksToBuy + transactionTax(investAmount) potentialRevenue = potentialStocksSold - totalInvestCost logging.info("potentialRevenue last fall: %s", potentialRevenue) if (int(potentialRevenue) > thresholdMargin): logging.debug("Comprar") return ('buy', symbol, lastClose, potentialRevenue) return ('pass', symbol, lastClose, potentialRevenue)
def display_cusum( df: pd.DataFrame, target: str, threshold: float, drift: float, external_axes: Optional[List[plt.Axes]] = None, ): """Cumulative sum algorithm (CUSUM) to detect abrupt changes in data Parameters ---------- df : pd.DataFrame Dataframe target : str Column of data to look at threshold : float Threshold value drift : float Drift parameter external_axes : Optional[List[plt.Axes]], optional External axes (2 axes are expected in the list), by default None """ target_series = df[target].values # The code for this plot was adapted from detecta's sources because at the # time of writing this detect_cusum had a bug related to external axes support. # see https://github.com/demotu/detecta/pull/3 tap, tan = 0, 0 ta, tai, taf, _ = detect_cusum( x=target_series, threshold=threshold, drift=drift, ending=True, show=False, ) # Thus some variable names are left unchanged and unreadable... gp, gn = np.zeros(target_series.size), np.zeros(target_series.size) for i in range(1, target_series.size): s = target_series[i] - target_series[i - 1] gp[i] = gp[i - 1] + s - drift # cumulative sum for + change gn[i] = gn[i - 1] - s - drift # cumulative sum for - change if gp[i] < 0: gp[i], tap = 0, i if gn[i] < 0: gn[i], tan = 0, i if gp[i] > threshold or gn[i] > threshold: # change detected! ta = np.append(ta, i) # alarm index tai = np.append(tai, tap if gp[i] > threshold else tan) # start gp[i], gn[i] = 0, 0 # reset alarm if external_axes is None: _, axes = plt.subplots( 2, 1, sharex=True, figsize=plot_autoscale(), dpi=PLOT_DPI, ) (ax1, ax2) = axes else: if len(external_axes) != 2: logger.error("Expected list of two axis items.") console.print("[red]Expected list of 2 axis items./n[/red]") return (ax1, ax2) = external_axes target_series_indexes = range(df[target].size) ax1.plot(target_series_indexes, target_series) if len(ta): ax1.plot( tai, target_series[tai], ">", markerfacecolor=theme.up_color, markersize=5, label="Start", ) ax1.plot( taf, target_series[taf], "<", markerfacecolor=theme.down_color, markersize=5, label="Ending", ) ax1.plot( ta, target_series[ta], "o", markerfacecolor=theme.get_colors()[-1], markeredgecolor=theme.get_colors()[-2], markeredgewidth=1, markersize=3, label="Alarm", ) ax1.legend() ax1.set_xlim(-0.01 * target_series.size, target_series.size * 1.01 - 1) ax1.set_ylabel("Amplitude") ymin, ymax = ( target_series[np.isfinite(target_series)].min(), target_series[np.isfinite(target_series)].max(), ) y_range = ymax - ymin if ymax > ymin else 1 ax1.set_ylim(ymin - 0.1 * y_range, ymax + 0.1 * y_range) ax1.set_title( "Time series and detected changes " + f"(threshold= {threshold:.3g}, drift= {drift:.3g}): N changes = {len(tai)}", fontsize=10, ) theme.style_primary_axis(ax1) ax2.plot(target_series_indexes, gp, label="+") ax2.plot(target_series_indexes, gn, label="-") ax2.set_xlim(-0.01 * target_series.size, target_series.size * 1.01 - 1) ax2.set_xlabel("Data points") ax2.set_ylim(-0.01 * threshold, 1.1 * threshold) ax2.axhline(threshold) theme.style_primary_axis(ax2) ax2.set_title( "Time series of the cumulative sums of positive and negative changes", fontsize=10, ) ax2.legend() if external_axes is None: theme.visualize_output()
plt.plot(y) plt.xlabel('Samples') plt.show()''' '''x1 = [0, 0, 3, 7, 9] y1 = [0, 8, 12, 13, 14] x2 = [0, 0, 1, 1, 2, 3, 9] y2 = [0, 13, 13, 14, 14, 15, 15] plt.xlim((0,9)) plt.ylim((0,16)) plt.xlabel('False Positive') plt.ylabel('True Positive') plt.plot(x1, y1, label = 'CUSUM') plt.plot(x2, y2, label = 'NLMS') plt.legend() plt.show()''' start2 = time() ta, tai, taf, amp = detect_cusum(data_test, 2000, 10000, True, True) end2 = time() time1 = end1 - start1 time2 = end2 - start2 x1 = ['NLMS', 'CUSUM'] y1 = [time1, time2] plt.bar(x1, y1) plt.ylabel("Time(sec)") plt.show() a = 1