def view_ma( ma_type: str, s_ticker: str, s_interval: str, df_stock: pd.DataFrame, length: List[int], offset: int, export: str = "", ) -> pd.DataFrame: """Plots MA technical indicator Parameters ---------- ma_type: str Type of moving average. Either "EMA" "ZLMA" or "SMA" s_ticker : str Ticker s_interval : str Interval of data df_stock : pd.DataFrame Dataframe of prices length : List[int] Length of EMA window export : str Format to export data """ if s_interval == "1440min": price_df = pd.DataFrame(df_stock["Adj Close"].values, columns=["Price"], index=df_stock.index) else: price_df = pd.DataFrame(df_stock["Close"].values, columns=["Price"], index=df_stock.index) l_legend = [s_ticker] for win in length: if ma_type == "EMA": df_ta = overlap_model.ema(s_interval, df_stock, win, offset) l_legend.append(f"EMA {win}") elif ma_type == "SMA": df_ta = overlap_model.sma(s_interval, df_stock, win, offset) l_legend.append(f"SMA {win}") elif ma_type == "WMA": df_ta = overlap_model.wma(s_interval, df_stock, win, offset) l_legend.append(f"WMA {win}") elif ma_type == "HMA": df_ta = overlap_model.hma(s_interval, df_stock, win, offset) l_legend.append(f"HMA {win}") elif ma_type == "ZLMA": df_ta = overlap_model.zlma(s_interval, df_stock, win, offset) l_legend.append(f"ZLMA {win}") price_df = price_df.join(df_ta) fig, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI) ax.set_title(f"{s_ticker} {ma_type.upper()}") ax.plot(price_df.index, price_df["Price"], lw=3, c="k") ax.set_xlabel("Time") ax.set_xlim([price_df.index[0], price_df.index[-1]]) ax.set_ylabel(f"{s_ticker} Price") for idx in range(1, price_df.shape[1]): ax.plot(price_df.iloc[:, idx]) ax.legend(l_legend) ax.grid(b=True, which="major", color="#666666", linestyle="-") 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"), f"{ma_type.lower()}{'_'.join([str(win) for win in length])}", price_df, )
def sma_command(ticker="", window="", offset="", start="", end=""): """Displays chart with simple moving average [Yahoo Finance]""" # Debug if cfg.DEBUG: logger.debug( "ta-sma %s %s %s %s %s", ticker, window, offset, 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) l_legend = [ticker] if window == "": window = [20, 50] else: window_temp = list() for wind in window.split(","): try: window_temp.append(float(wind)) except Exception as e: raise Exception("Window needs to be a float") from e window = window_temp ticker = ticker.upper() stock = helpers.load(ticker, start) if stock.empty: raise Exception("Stock ticker is invalid") # Retrieve Data price_df = pd.DataFrame(stock["Adj Close"].values, columns=["Price"], index=stock.index) i = 1 for win in window: sma_data = overlap_model.sma(values=stock["Adj Close"], length=win, offset=offset) price_df = price_df.join(sma_data) l_legend.append(f"SMA {win}") i += 1 # Output Data start = start.strftime("%Y-%m-%d") end = end.strftime("%Y-%m-%d") price_df = price_df.loc[(price_df.index >= start) & (price_df.index < end)] fig = go.Figure() fig.add_trace( go.Scatter( name=f"{ticker}", x=price_df.index, y=price_df["Price"], line=dict(color="#fdc708", width=2), opacity=1, ), ) for i in range(1, price_df.shape[1]): trace_name = price_df.columns[i].replace("_", " ") fig.add_trace( go.Scatter( name=trace_name, x=price_df.index, y=price_df.iloc[:, i], opacity=1, ), ) fig.update_layout( margin=dict(l=0, r=0, t=50, b=20), template=cfg.PLT_TA_STYLE_TEMPLATE, colorway=cfg.PLT_TA_COLORWAY, title=f"{ticker} SMA", title_x=0.5, yaxis_title="Stock Price ($)", xaxis_title="Time", 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_sma.png" # Check if interactive settings are enabled plt_link = "" if cfg.INTERACTIVE: html_ran = helpers.uuid_get() fig.write_html(f"in/sma_{html_ran}.html", config=config) plt_link = f"[Interactive]({cfg.INTERACTIVE_URL}/sma_{html_ran}.html)" fig.update_layout( width=800, height=500, ) imagefile = helpers.image_border(imagefile, fig=fig) return { "title": f"Stocks: Simple-Moving-Average {ticker}", "description": plt_link, "imagefile": imagefile, }
async def sma_command(ctx, ticker="", window="", offset="", start="", end=""): """Displays chart with simple moving average [Yahoo Finance]""" try: # Debug if cfg.DEBUG: print(f"!stocks.ta.sma {ticker} {window} {offset} {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) l_legend = [ticker] if window == "": window = [20, 50] else: window_temp = list() for wind in window.split(","): try: window_temp.append(float(wind)) except Exception as e: raise Exception("Window needs to be a float") from e window = window_temp if offset == "": offset = 0 else: if not offset.lstrip("-").isnumeric(): raise Exception("Number has to be an integer") offset = float(offset) ticker = ticker.upper() stock = discordbot.helpers.load(ticker, start) if stock.empty: raise Exception("Stock ticker is invalid") # Retrieve Data price_df = pd.DataFrame(stock["Adj Close"].values, columns=["Price"], index=stock.index) i = 1 for win in window: sma_data = overlap_model.sma(s_interval="1440min", df_stock=stock, length=win, offset=offset) price_df = price_df.join(sma_data) l_legend.append(f"SMA {win}") i += 1 # Output Data start = start.strftime("%Y-%m-%d") end = end.strftime("%Y-%m-%d") price_df = price_df.loc[(price_df.index >= start) & (price_df.index < end)] fig, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI) ax.set_title(f"{ticker} SMA") ax.plot(price_df.index, price_df["Price"], lw=3, c="k") ax.set_xlabel("Time") ax.set_xlim([price_df.index[0], price_df.index[-1]]) ax.set_ylabel(f"{ticker} Price") for idx in range(1, price_df.shape[1]): ax.plot(price_df.iloc[:, idx]) ax.legend(l_legend) ax.grid(b=True, which="major", color="#666666", linestyle="-") plt.gcf().autofmt_xdate() fig.tight_layout(pad=1) plt.savefig("ta_sma.png") uploaded_image = gst_imgur.upload_image("ta_sma.png", title="something") image_link = uploaded_image.link if cfg.DEBUG: print(f"Image URL: {image_link}") title = "Stocks: Simple-Moving-Average " + 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_sma.png") await ctx.send(embed=embed) except Exception as e: embed = discord.Embed( title="ERROR Stocks: Simple-Moving-Average", colour=cfg.COLOR, description=e, ) embed.set_author( name=cfg.AUTHOR_NAME, icon_url=cfg.AUTHOR_ICON_URL, ) await ctx.send(embed=embed)
def view_ma( series: pd.Series, length: List[int] = None, offset: int = 0, ma_type: str = "EMA", s_ticker: str = "", export: str = "", external_axes: Optional[List[plt.Axes]] = None, ) -> None: """Plots MA technical indicator Parameters ---------- series : pd.Series Series of prices length : List[int] Length of EMA window ma_type: str Type of moving average. Either "EMA" "ZLMA" or "SMA" s_ticker : str Ticker export : str Format to export data external_axes : Optional[List[plt.Axes]], optional External axes (1 axis is expected in the list), by default None """ # Define a dataframe for adding EMA series to it price_df = pd.DataFrame(series) l_legend = [s_ticker] if not length: length = [20, 50] for win in length: if ma_type == "EMA": df_ta = overlap_model.ema(series, win, offset) l_legend.append(f"EMA {win}") elif ma_type == "SMA": df_ta = overlap_model.sma(series, win, offset) l_legend.append(f"SMA {win}") elif ma_type == "WMA": df_ta = overlap_model.wma(series, win, offset) l_legend.append(f"WMA {win}") elif ma_type == "HMA": df_ta = overlap_model.hma(series, win, offset) l_legend.append(f"HMA {win}") elif ma_type == "ZLMA": df_ta = overlap_model.zlma(series, win, offset) l_legend.append(f"ZLMA {win}") price_df = price_df.join(df_ta) plot_data = reindex_dates(price_df) # This plot has 1 axis if external_axes is None: _, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI) else: if len(external_axes) != 1: console.print("[red]Expected list of one axis item./n[/red]") return (ax, ) = external_axes ax.plot(plot_data.index, plot_data.iloc[:, 1].values) ax.set_xlim([plot_data.index[0], plot_data.index[-1]]) ax.set_ylabel(f"{s_ticker} Price") for idx in range(2, plot_data.shape[1]): ax.plot(plot_data.iloc[:, idx]) ax.set_title(f"{s_ticker} {ma_type.upper()}") ax.legend(l_legend) theme.style_primary_axis( ax, data_index=plot_data.index.to_list(), tick_labels=plot_data["date"].to_list(), ) if external_axes is None: theme.visualize_output() export_data( export, os.path.dirname(os.path.abspath(__file__)).replace("common", "stocks"), f"{ma_type.lower()}{'_'.join([str(win) for win in length])}", price_df, )
async def sma_command(ctx, ticker="", window="", offset="", start="", end=""): """Displays chart with simple moving average [Yahoo Finance]""" try: # Debug if cfg.DEBUG: logger.debug( "!stocks.ta.sma %s %s %s %s %s", ticker, window, offset, 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) l_legend = [ticker] if window == "": window = [20, 50] else: window_temp = list() for wind in window.split(","): try: window_temp.append(float(wind)) except Exception as e: raise Exception("Window needs to be a float") from e window = window_temp ticker = ticker.upper() stock = discordbot.helpers.load(ticker, start) if stock.empty: raise Exception("Stock ticker is invalid") # Retrieve Data price_df = pd.DataFrame(stock["Adj Close"].values, columns=["Price"], index=stock.index) i = 1 for win in window: sma_data = overlap_model.sma(values=stock["Adj Close"], length=win, offset=offset) price_df = price_df.join(sma_data) l_legend.append(f"SMA {win}") i += 1 # Output Data start = start.strftime("%Y-%m-%d") end = end.strftime("%Y-%m-%d") price_df = price_df.loc[(price_df.index >= start) & (price_df.index < end)] fig = go.Figure() fig.add_trace( go.Scatter( name=f"{ticker}", x=price_df.index, y=price_df["Price"], line=dict(color="#fdc708", width=2), opacity=1, ), ) for i in range(1, price_df.shape[1]): trace_name = price_df.columns[i].replace("_", " ") fig.add_trace( go.Scatter( name=trace_name, x=price_df.index, y=price_df.iloc[:, i], opacity=1, ), ) fig.update_layout( margin=dict(l=0, r=0, t=50, b=20), template=cfg.PLT_TA_STYLE_TEMPLATE, colorway=cfg.PLT_TA_COLORWAY, title=f"{ticker} SMA", title_x=0.5, yaxis_title="Stock Price ($)", xaxis_title="Time", 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_sma.png" # Check if interactive settings are enabled plt_link = "" if cfg.INTERACTIVE: html_ran = random.randint(69, 69420) fig.write_html(f"in/sma_{html_ran}.html", config=config) plt_link = f"[Interactive]({cfg.INTERACTIVE_URL}/sma_{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: Simple-Moving-Average {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: Simple-Moving-Average", 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 view_ma( values: pd.Series, length: List[int] = None, offset: int = 0, ma_type: str = "EMA", s_ticker: str = "", export: str = "", ) -> pd.DataFrame: """Plots MA technical indicator Parameters ---------- values : pd.Series Series of prices length : List[int] Length of EMA window ma_type: str Type of moving average. Either "EMA" "ZLMA" or "SMA" s_ticker : str Ticker export : str Format to export data """ # Define a dataframe for adding EMA values to it price_df = pd.DataFrame(values) l_legend = [s_ticker] if not length: length = [20, 50] for win in length: if ma_type == "EMA": df_ta = overlap_model.ema(values, win, offset) l_legend.append(f"EMA {win}") elif ma_type == "SMA": df_ta = overlap_model.sma(values, win, offset) l_legend.append(f"SMA {win}") elif ma_type == "WMA": df_ta = overlap_model.wma(values, win, offset) l_legend.append(f"WMA {win}") elif ma_type == "HMA": df_ta = overlap_model.hma(values, win, offset) l_legend.append(f"HMA {win}") elif ma_type == "ZLMA": df_ta = overlap_model.zlma(values, win, offset) l_legend.append(f"ZLMA {win}") price_df = price_df.join(df_ta) fig, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI) ax.set_title(f"{s_ticker} {ma_type.upper()}") ax.plot(values.index, values.values, lw=3, c="k") ax.set_xlabel("Time") ax.set_xlim([price_df.index[0], price_df.index[-1]]) ax.set_ylabel(f"{s_ticker} Price") for idx in range(1, price_df.shape[1]): ax.plot(price_df.iloc[:, idx]) ax.legend(l_legend) ax.grid(b=True, which="major", color="#666666", linestyle="-") if gtff.USE_ION: plt.ion() plt.gcf().autofmt_xdate() fig.tight_layout(pad=1) plt.show() console.print("") export_data( export, os.path.dirname(os.path.abspath(__file__)).replace("common", "stocks"), f"{ma_type.lower()}{'_'.join([str(win) for win in length])}", price_df, )