async def stoch_command(ctx, ticker="", fast_k="14", slow_d="3", slow_k="3", start="", end=""): """Displays chart with stochastic relative strength average [Yahoo Finance]""" try: # Debug if cfg.DEBUG: print( f"!stocks.ta.stoch {ticker} {fast_k} {slow_k} {slow_d} {start} {end}" ) # Check for argument if ticker == "": raise Exception("Stock ticker is required") if start == "": start = datetime.now() - timedelta(days=365) else: start = datetime.strptime(start, cfg.DATE_FORMAT) if end == "": end = datetime.now() else: end = datetime.strptime(end, cfg.DATE_FORMAT) if not fast_k.lstrip("-").isnumeric(): raise Exception("Number has to be an integer") fast_k = float(fast_k) if not slow_k.lstrip("-").isnumeric(): raise Exception("Number has to be an integer") slow_k = float(slow_k) if not slow_d.lstrip("-").isnumeric(): raise Exception("Number has to be an integer") slow_d = float(slow_d) ticker = ticker.upper() df_stock = discordbot.helpers.load(ticker, start) if df_stock.empty: raise Exception("Stock ticker is invalid") # Retrieve Data df_stock = df_stock.loc[(df_stock.index >= start) & (df_stock.index < end)] df_ta = momentum_model.stoch("1440min", df_stock, fast_k, slow_d, slow_k) # Output Data fig, axes = plt.subplots(2, 1, figsize=plot_autoscale(), dpi=PLOT_DPI) ax = axes[0] ax.plot(df_stock.index, df_stock["Adj Close"].values, "k", lw=2) ax.set_title( f"Stochastic Relative Strength Index (STOCH RSI) on {ticker}") ax.set_xlim(df_stock.index[0], df_stock.index[-1]) ax.set_xticklabels([]) ax.set_ylabel("Share Price ($)") ax.grid(b=True, which="major", color="#666666", linestyle="-") ax2 = axes[1] ax2.plot(df_ta.index, df_ta.iloc[:, 0].values, "k", lw=2) ax2.plot(df_ta.index, df_ta.iloc[:, 1].values, "b", lw=2, ls="--") ax2.set_xlim(df_stock.index[0], df_stock.index[-1]) ax2.axhspan(80, 100, facecolor="r", alpha=0.2) ax2.axhspan(0, 20, facecolor="g", alpha=0.2) ax2.axhline(80, linewidth=3, color="r", ls="--") ax2.axhline(20, linewidth=3, color="g", ls="--") ax2.grid(b=True, which="major", color="#666666", linestyle="-") ax2.set_ylim([0, 100]) ax3 = ax2.twinx() ax3.set_ylim(ax2.get_ylim()) ax3.set_yticks([20, 80]) ax3.set_yticklabels(["OVERSOLD", "OVERBOUGHT"]) ax2.legend([f"%K {df_ta.columns[0]}", f"%D {df_ta.columns[1]}"], loc="lower left") plt.gcf().autofmt_xdate() fig.tight_layout(pad=1) plt.savefig("ta_stoch.png") uploaded_image = gst_imgur.upload_image("ta_stoch.png", title="something") image_link = uploaded_image.link if cfg.DEBUG: print(f"Image URL: {image_link}") title = "Stocks: Stochastic-Relative-Strength-Index " + ticker embed = discord.Embed(title=title, colour=cfg.COLOR) embed.set_author( name=cfg.AUTHOR_NAME, icon_url=cfg.AUTHOR_ICON_URL, ) embed.set_image(url=image_link) os.remove("ta_stoch.png") await ctx.send(embed=embed) except Exception as e: embed = discord.Embed( title="ERROR Stocks: Stochastic-Relative-Strength-Index", colour=cfg.COLOR, description=e, ) embed.set_author( name=cfg.AUTHOR_NAME, icon_url=cfg.AUTHOR_ICON_URL, ) await ctx.send(embed=embed)
def stoch_command( ticker: str = "", interval: int = 15, past_days: int = 0, fast_k="14", slow_d="3", slow_k="4", start="", end="", extended_hours: bool = False, heikin_candles: bool = False, news: bool = False, ): """Displays chart with stochastic relative strength average [Yahoo Finance]""" # Debug if imps.DEBUG: logger.debug( "ta stoch %s %s %s %s %s %s %s %s %s %s %s", ticker, interval, past_days, fast_k, slow_k, slow_d, start, end, extended_hours, heikin_candles, news, ) # Check for argument if ticker == "": raise Exception("Stock ticker is required") if not fast_k.lstrip("-").isnumeric(): raise Exception("Number has to be an integer") fast_k = int(fast_k) if not slow_k.lstrip("-").isnumeric(): raise Exception("Number has to be an integer") slow_k = int(slow_k) if not slow_d.lstrip("-").isnumeric(): raise Exception("Number has to be an integer") slow_d = int(slow_d) # Retrieve Data df_stock, start, end, bar_start = load_candle.stock_data( ticker=ticker, interval=interval, past_days=past_days, extended_hours=extended_hours, start=start, end=end, heikin_candles=heikin_candles, ) df_ta = df_stock.loc[(df_stock.index >= start) & (df_stock.index < end)] if df_ta.empty: raise Exception("No Data Found") df_ta = df_ta.join( momentum_model.stoch( df_stock["High"], df_stock["Low"], df_stock["Adj Close"], fast_k, slow_d, slow_k, )) # Output Data if interval != 1440: df_ta = df_ta.loc[(df_ta.index >= bar_start) & (df_ta.index < end)] df_ta = df_ta.fillna(0.0) plot = load_candle.candle_fig( df_ta, ticker, interval, extended_hours, news, bar=bar_start, int_bar=interval, rows=2, cols=1, shared_xaxes=True, vertical_spacing=0.07, row_width=[0.4, 0.6], specs=[[{ "secondary_y": True }], [{ "secondary_y": False }]], ) title = f"<b>{plot['plt_title']} STOCH RSI</b>" fig = plot["fig"] idx = 6 if interval != 1440 else 11 fig.add_trace( go.Scatter( name=f"%K {fast_k}, {slow_d}, {slow_k}", x=df_ta.index, y=df_ta.iloc[:, idx].values, line=dict(width=1.8), mode="lines", opacity=1, ), row=2, col=1, ) fig.add_trace( go.Scatter( name=f"%D {fast_k}, {slow_d}, {slow_k}", x=df_ta.index, y=df_ta.iloc[:, (idx + 1)].values, line=dict(width=1.8, dash="dash"), opacity=1, ), row=2, col=1, ) fig.add_hrect( y0=80, y1=100, fillcolor="red", opacity=0.2, layer="below", line_width=0, row=2, col=1, ) fig.add_hrect( y0=0, y1=20, fillcolor="green", opacity=0.2, layer="below", line_width=0, row=2, col=1, ) fig.add_hline( y=80, fillcolor="green", opacity=1, layer="below", line_width=3, line=dict(color="red", dash="dash"), row=2, col=1, ) fig.add_hline( y=20, fillcolor="green", opacity=1, layer="below", line_width=3, line=dict(color="green", dash="dash"), row=2, col=1, ) fig.update_layout( margin=dict(l=0, r=0, t=50, b=20), template=imps.PLT_TA_STYLE_TEMPLATE, colorway=imps.PLT_TA_COLORWAY, title=title, title_x=0.01, title_font_size=14, dragmode="pan", ) imagefile = "ta_stoch.png" # Check if interactive settings are enabled plt_link = "" if imps.INTERACTIVE: plt_link = imps.inter_chart(fig, imagefile, callback=False) fig.update_layout( width=800, height=500, ) imagefile = imps.image_border(imagefile, fig=fig) return { "title": f"Stocks: Stochastic-Relative-Strength-Index {ticker.upper()}", "description": plt_link, "imagefile": imagefile, }
def view_stoch( s_ticker: str, s_interval: str, df_stock: pd.DataFrame, fastkperiod: int, slowdperiod: int, slowkperiod: int, export: str, ): """Plot stochastic oscillator signal Parameters ---------- s_ticker : str Stock ticker s_interval : str Interval of data df_stock : pd.DataFrame Dataframe of prices fastkperiod : int Fast k period slowdperiod : int Slow d period slowkperiod : int Slow k period export : str Format to export data """ df_ta = momentum_model.stoch(s_interval, df_stock, fastkperiod, slowdperiod, slowkperiod) fig, axes = plt.subplots(2, 1, figsize=plot_autoscale(), dpi=PLOT_DPI) ax = axes[0] if s_interval == "1440min": ax.plot(df_stock.index, df_stock["Adj Close"].values, "k", lw=2) else: ax.plot(df_stock.index, df_stock["Close"].values, "k", lw=2) ax.set_title( f"Stochastic Relative Strength Index (STOCH RSI) on {s_ticker}") ax.set_xlim(df_stock.index[0], df_stock.index[-1]) ax.set_xticklabels([]) ax.set_ylabel("Share Price ($)") ax.grid(b=True, which="major", color="#666666", linestyle="-") ax2 = axes[1] ax2.plot(df_ta.index, df_ta.iloc[:, 0].values, "k", lw=2) ax2.plot(df_ta.index, df_ta.iloc[:, 1].values, "b", lw=2, ls="--") ax2.set_xlim(df_stock.index[0], df_stock.index[-1]) ax2.axhspan(80, 100, facecolor="r", alpha=0.2) ax2.axhspan(0, 20, facecolor="g", alpha=0.2) ax2.axhline(80, linewidth=3, color="r", ls="--") ax2.axhline(20, linewidth=3, color="g", ls="--") ax2.grid(b=True, which="major", color="#666666", linestyle="-") ax2.set_ylim([0, 100]) ax3 = ax2.twinx() ax3.set_ylim(ax2.get_ylim()) ax3.set_yticks([20, 80]) ax3.set_yticklabels(["OVERSOLD", "OVERBOUGHT"]) ax2.legend([f"%K {df_ta.columns[0]}", f"%D {df_ta.columns[1]}"], loc="lower left") if gtff.USE_ION: plt.ion() plt.gcf().autofmt_xdate() fig.tight_layout(pad=1) plt.show() print("") export_data( export, os.path.dirname(os.path.abspath(__file__)).replace("common", "stocks"), "stoch", df_ta, )
def stoch_command(ticker="", fast_k="14", slow_d="3", slow_k="3", start="", end=""): """Displays chart with stochastic relative strength average [Yahoo Finance]""" # Debug if cfg.DEBUG: logger.debug( "ta-stoch %s %s %s %s %s %s", ticker, fast_k, slow_k, slow_d, start, end, ) # Check for argument if ticker == "": raise Exception("Stock ticker is required") if start == "": start = datetime.now() - timedelta(days=365) else: start = datetime.strptime(start, cfg.DATE_FORMAT) if end == "": end = datetime.now() else: end = datetime.strptime(end, cfg.DATE_FORMAT) if not fast_k.lstrip("-").isnumeric(): raise Exception("Number has to be an integer") fast_k = int(fast_k) if not slow_k.lstrip("-").isnumeric(): raise Exception("Number has to be an integer") slow_k = int(slow_k) if not slow_d.lstrip("-").isnumeric(): raise Exception("Number has to be an integer") slow_d = int(slow_d) ticker = ticker.upper() df_stock = helpers.load(ticker, start) if df_stock.empty: raise Exception("Stock ticker is invalid") # Retrieve Data df_stock = df_stock.loc[(df_stock.index >= start) & (df_stock.index < end)] df_ta = momentum_model.stoch( df_stock["High"], df_stock["Low"], df_stock["Adj Close"], fast_k, slow_d, slow_k, ) fig = make_subplots( rows=2, cols=1, shared_xaxes=True, vertical_spacing=0.07, row_width=[0.5, 0.7], ) fig.add_trace( go.Scatter( x=df_stock.index, y=df_stock["Adj Close"].values, line=dict(color="#fdc708", width=2), opacity=1, showlegend=False, ), row=1, col=1, ) K = df_ta.columns[0].replace("_", " ") D = df_ta.columns[1].replace("_", " ") fig.add_trace( go.Scatter( name=f"%K {K}", x=df_stock.index, y=df_ta.iloc[:, 0].values, line=dict(width=1.8), opacity=1, ), row=2, col=1, ) fig.add_trace( go.Scatter( name=f"%D {D}", x=df_stock.index, y=df_ta.iloc[:, 1].values, line=dict(width=1.8, dash="dash"), opacity=1, ), row=2, col=1, ) fig.add_hrect( y0=80, y1=100, fillcolor="red", opacity=0.2, layer="below", line_width=0, row=2, col=1, ) fig.add_hrect( y0=0, y1=20, fillcolor="green", opacity=0.2, layer="below", line_width=0, row=2, col=1, ) fig.add_hline( y=80, fillcolor="green", opacity=1, layer="below", line_width=3, line=dict(color="red", dash="dash"), row=2, col=1, ) fig.add_hline( y=20, fillcolor="green", opacity=1, layer="below", line_width=3, line=dict(color="green", dash="dash"), row=2, col=1, ) fig.update_layout( margin=dict(l=0, r=0, t=40, b=20), template=cfg.PLT_TA_STYLE_TEMPLATE, colorway=cfg.PLT_TA_COLORWAY, title=f"Stochastic Relative Strength Index (STOCH RSI) on {ticker}", title_x=0.5, yaxis_title="Stock Price ($)", yaxis=dict( fixedrange=False, ), xaxis=dict( rangeslider=dict(visible=False), type="date", ), dragmode="pan", legend=dict(yanchor="top", y=0.99, xanchor="left", x=0.01), ) config = dict({"scrollZoom": True}) imagefile = "ta_stoch.png" # Check if interactive settings are enabled plt_link = "" if cfg.INTERACTIVE: html_ran = helpers.uuid_get() fig.write_html(f"in/stoch_{html_ran}.html", config=config) plt_link = f"[Interactive]({cfg.INTERACTIVE_URL}/stoch_{html_ran}.html)" fig.update_layout( width=800, height=500, ) imagefile = helpers.image_border(imagefile, fig=fig) return { "title": f"Stocks: Stochastic-Relative-Strength-Index {ticker}", "description": plt_link, "imagefile": imagefile, }
async def stoch_command( ctx, ticker="", fast_k="14", slow_d="3", slow_k="3", start="", end="" ): """Displays chart with stochastic relative strength average [Yahoo Finance]""" try: # Debug if cfg.DEBUG: logger.debug( "!stocks.ta.stoch %s %s %s %s %s %s", ticker, fast_k, slow_k, slow_d, start, end, ) # Check for argument if ticker == "": raise Exception("Stock ticker is required") if start == "": start = datetime.now() - timedelta(days=365) else: start = datetime.strptime(start, cfg.DATE_FORMAT) if end == "": end = datetime.now() else: end = datetime.strptime(end, cfg.DATE_FORMAT) if not fast_k.lstrip("-").isnumeric(): raise Exception("Number has to be an integer") fast_k = int(fast_k) if not slow_k.lstrip("-").isnumeric(): raise Exception("Number has to be an integer") slow_k = int(slow_k) if not slow_d.lstrip("-").isnumeric(): raise Exception("Number has to be an integer") slow_d = int(slow_d) ticker = ticker.upper() df_stock = discordbot.helpers.load(ticker, start) if df_stock.empty: raise Exception("Stock ticker is invalid") # Retrieve Data df_stock = df_stock.loc[(df_stock.index >= start) & (df_stock.index < end)] df_ta = momentum_model.stoch( df_stock["High"], df_stock["Low"], df_stock["Adj Close"], fast_k, slow_d, slow_k, ) fig = make_subplots( rows=2, cols=1, shared_xaxes=True, vertical_spacing=0.07, row_width=[0.5, 0.7], ) fig.add_trace( go.Scatter( x=df_stock.index, y=df_stock["Adj Close"].values, line=dict(color="#fdc708", width=2), opacity=1, showlegend=False, ), row=1, col=1, ) K = df_ta.columns[0].replace("_", " ") D = df_ta.columns[1].replace("_", " ") fig.add_trace( go.Scatter( name=f"%K {K}", x=df_stock.index, y=df_ta.iloc[:, 0].values, line=dict(width=1.8), opacity=1, ), row=2, col=1, ) fig.add_trace( go.Scatter( name=f"%D {D}", x=df_stock.index, y=df_ta.iloc[:, 1].values, line=dict(width=1.8, dash="dash"), opacity=1, ), row=2, col=1, ) fig.add_hrect( y0=80, y1=100, fillcolor="red", opacity=0.2, layer="below", line_width=0, row=2, col=1, ) fig.add_hrect( y0=0, y1=20, fillcolor="green", opacity=0.2, layer="below", line_width=0, row=2, col=1, ) fig.add_hline( y=80, fillcolor="green", opacity=1, layer="below", line_width=3, line=dict(color="red", dash="dash"), row=2, col=1, ) fig.add_hline( y=20, fillcolor="green", opacity=1, layer="below", line_width=3, line=dict(color="green", dash="dash"), row=2, col=1, ) fig.update_layout( margin=dict(l=0, r=0, t=40, b=20), template=cfg.PLT_TA_STYLE_TEMPLATE, colorway=cfg.PLT_TA_COLORWAY, title=f"Stochastic Relative Strength Index (STOCH RSI) on {ticker}", title_x=0.5, yaxis_title="Stock Price ($)", yaxis=dict( fixedrange=False, ), xaxis=dict( rangeslider=dict(visible=False), type="date", ), dragmode="pan", legend=dict(yanchor="top", y=0.99, xanchor="left", x=0.01), ) config = dict({"scrollZoom": True}) imagefile = "ta_stoch.png" # Check if interactive settings are enabled plt_link = "" if cfg.INTERACTIVE: html_ran = random.randint(69, 69420) fig.write_html(f"in/stoch_{html_ran}.html", config=config) plt_link = f"[Interactive]({cfg.INTERACTIVE_URL}/stoch_{html_ran}.html)" fig.update_layout( width=800, height=500, ) fig.write_image(imagefile) img = Image.open(imagefile) im_bg = Image.open(cfg.IMG_BG) h = img.height + 240 w = img.width + 520 # Paste fig onto background img and autocrop background img = img.resize((w, h), Image.ANTIALIAS) x1 = int(0.5 * im_bg.size[0]) - int(0.5 * img.size[0]) y1 = int(0.5 * im_bg.size[1]) - int(0.5 * img.size[1]) x2 = int(0.5 * im_bg.size[0]) + int(0.5 * img.size[0]) y2 = int(0.5 * im_bg.size[1]) + int(0.5 * img.size[1]) img = img.convert("RGB") im_bg.paste(img, box=(x1 - 5, y1, x2 - 5, y2)) im_bg.save(imagefile, "PNG", quality=100) image = Image.open(imagefile) image = autocrop_image(image, 0) image.save(imagefile, "PNG", quality=100) image = disnake.File(imagefile) print(f"Image {imagefile}") embed = disnake.Embed( title=f"Stocks: Stochastic-Relative-Strength-Index {ticker}", description=plt_link, colour=cfg.COLOR, ) embed.set_image(url=f"attachment://{imagefile}") embed.set_author( name=cfg.AUTHOR_NAME, icon_url=cfg.AUTHOR_ICON_URL, ) os.remove(imagefile) await ctx.send(embed=embed, file=image) except Exception as e: embed = disnake.Embed( title="ERROR Stocks: Stochastic-Relative-Strength-Index", colour=cfg.COLOR, description=e, ) embed.set_author( name=cfg.AUTHOR_NAME, icon_url=cfg.AUTHOR_ICON_URL, ) await ctx.send(embed=embed, delete_after=30.0)
def display_stoch( ohlc: pd.DataFrame, fastkperiod: int = 14, slowdperiod: int = 3, slowkperiod: int = 3, s_ticker: str = "", export: str = "", external_axes: Optional[List[plt.Axes]] = None, ) -> None: """Plot stochastic oscillator signal Parameters ---------- ohlc : pd.DataFrame Dataframe of prices fastkperiod : int Fast k period slowdperiod : int Slow d period slowkperiod : int Slow k period s_ticker : str Stock ticker export : str Format to export data external_axes : Optional[List[plt.Axes]], optional External axes (3 axes are expected in the list), by default None """ df_ta = momentum_model.stoch( ohlc["High"], ohlc["Low"], ohlc["Adj Close"], fastkperiod, slowdperiod, slowkperiod, ) # This plot has 3 axes if not external_axes: _, axes = plt.subplots(2, 1, sharex=True, figsize=plot_autoscale(), dpi=PLOT_DPI) ax1, ax2 = axes ax3 = ax2.twinx() else: if len(external_axes) != 3: logger.error("Expected list of three axis items.") console.print("[red]Expected list of 3 axis items./n[/red]") return ax1, ax2, ax3 = external_axes plot_data = pd.merge(ohlc, df_ta, how="outer", left_index=True, right_index=True) plot_data = reindex_dates(plot_data) ax1.plot(plot_data.index, plot_data["Adj Close"].values) ax1.set_title( f"Stochastic Relative Strength Index (STOCH RSI) on {s_ticker}") ax1.set_xlim(plot_data.index[0], plot_data.index[-1]) ax1.set_ylabel("Share Price ($)") theme.style_primary_axis( ax1, data_index=plot_data.index.to_list(), tick_labels=plot_data["date"].to_list(), ) ax2.plot(plot_data.index, plot_data[df_ta.columns[0]].values) ax2.plot(plot_data.index, plot_data[df_ta.columns[1]].values, ls="--") ax2.set_xlim(plot_data.index[0], plot_data.index[-1]) theme.style_primary_axis( ax2, data_index=plot_data.index.to_list(), tick_labels=plot_data["date"].to_list(), ) ax3.set_ylim(ax2.get_ylim()) ax3.axhspan(80, 100, facecolor=theme.down_color, alpha=0.2) ax3.axhspan(0, 20, facecolor=theme.up_color, alpha=0.2) ax3.axhline(80, color=theme.down_color, ls="--") ax3.axhline(20, color=theme.up_color, ls="--") theme.style_twin_axis(ax3) ax2.set_yticks([20, 80]) ax2.set_yticklabels(["OVERSOLD", "OVERBOUGHT"]) ax2.legend([f"%K {df_ta.columns[0]}", f"%D {df_ta.columns[1]}"]) if external_axes is None: theme.visualize_output() export_data( export, os.path.dirname(os.path.abspath(__file__)).replace("common", "stocks"), "stoch", df_ta, )