def view_vwap( s_ticker: str, df_stock: pd.DataFrame, offset: int = 0, s_interval: str = "", export: str = "", ): """Plots EMA technical indicator Parameters ---------- s_ticker : str Ticker df_stock : pd.DataFrame Dataframe of prices offset : int Offset variable s_interval : str Interval of data export : str Format to export data """ df_stock.index = df_stock.index.tz_localize(None) df_stock["Day"] = [idx.date() for idx in df_stock.index] day_df = df_stock[df_stock.Day == df_stock.Day[-1]] df_vwap = overlap_model.vwap(day_df, offset) mc = mpf.make_marketcolors( up="green", down="red", edge="black", wick="black", volume="in", ohlc="i" ) s = mpf.make_mpf_style(marketcolors=mc, gridstyle=":", y_on_right=True) addplot_result = mpf.make_addplot(df_vwap, color="k") mpf.plot( day_df, style=s, type="candle", addplot=addplot_result, volume=True, title=f"\n{s_ticker} {s_interval} VWAP", ) if gtff.USE_ION: plt.ion() plt.show() console.print("") export_data( export, os.path.dirname(os.path.abspath(__file__)).replace("common", "stocks"), "VWAP", df_vwap, )
def view_vwap( s_ticker: str, ohlc: pd.DataFrame, offset: int = 0, s_interval: str = "", export: str = "", external_axes: Optional[List[plt.Axes]] = None, ): """Plots EMA technical indicator Parameters ---------- s_ticker : str Ticker ohlc : pd.DataFrame Dataframe of prices offset : int Offset variable s_interval : str Interval of data 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 """ ohlc.index = ohlc.index.tz_localize(None) ohlc["Day"] = [idx.date() for idx in ohlc.index] day_df = ohlc[ohlc.Day == ohlc.Day[-1]] df_vwap = overlap_model.vwap(day_df, offset) candle_chart_kwargs = { "type": "candle", "style": theme.mpf_style, "volume": True, "xrotation": theme.xticks_rotation, "scale_padding": { "left": 0.3, "right": 1.2, "top": 0.8, "bottom": 0.8 }, "update_width_config": { "candle_linewidth": 0.6, "candle_width": 0.8, "volume_linewidth": 0.8, "volume_width": 0.8, }, "warn_too_much_data": 10000, } # This plot has 2 axes if external_axes is None: candle_chart_kwargs["returnfig"] = True candle_chart_kwargs["figratio"] = (10, 7) candle_chart_kwargs["figscale"] = 1.10 candle_chart_kwargs["figsize"] = plot_autoscale() candle_chart_kwargs["addplot"] = mpf.make_addplot( df_vwap, width=theme.line_width) fig, _ = mpf.plot(day_df, **candle_chart_kwargs) fig.suptitle( f"{s_ticker} {s_interval} VWAP", x=0.055, y=0.965, horizontalalignment="left", ) theme.visualize_output(force_tight_layout=False) else: if len(external_axes) != 3: console.print("[red]Expected list of 3 axis items./n[/red]") return (ax1, ax2, ax3) = external_axes candle_chart_kwargs["ax"] = ax1 candle_chart_kwargs["volume"] = ax2 candle_chart_kwargs["addplot"] = mpf.make_addplot( df_vwap, width=theme.line_width, ax=ax3) mpf.plot(day_df, **candle_chart_kwargs) export_data( export, os.path.dirname(os.path.abspath(__file__)).replace("common", "stocks"), "VWAP", df_vwap, )
def candle_command( ticker: str = "", interval: int = 15, past_days: int = 0, extended_hours: bool = False, start="", end="", news: bool = False, heikin_candles: bool = False, vwap: bool = False, ): """Shows candle plot of loaded ticker or crypto. [Source: Yahoo Finance or Binance API] Parameters ---------- ticker : Stock Ticker interval : Chart Minute Interval, 1440 for Daily past_days: Past Days to Display. Default: 0(Not for Daily) extended_hours: Display Pre/After Market Hours. Default: False start: YYYY-MM-DD format end: YYYY-MM-DD format news: Display clickable news markers on interactive chart. Default: False heikin_candles: Heikin Ashi candles. Default: False """ logger.info( "candle %s %s %s %s %s %s %s %s", ticker, interval, past_days, extended_hours, start, end, news, heikin_candles, ) # 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, news=news, heikin_candles=heikin_candles, ) df_stock = df_stock.loc[(df_stock.index >= start) & (df_stock.index < end)] df_stock = df_stock.join(overlap_model.vwap(df_stock, 0)) # Check that loading a stock was not successful if df_stock.empty: raise Exception(f"No data found for {ticker.upper()}.") # Output Data if interval != 1440: df_stock = df_stock.loc[(df_stock.index >= bar_start) & (df_stock.index < end)] plot = load_candle.candle_fig( df_stock, ticker, interval, extended_hours, news, bar=bar_start, int_bar=interval, ) title = f"{plot['plt_title']} Chart" fig = plot["fig"] if interval != 1440 and vwap: fig.add_trace( go.Scatter( name="VWAP", x=df_stock.index, y=df_stock["VWAP_D"], opacity=0.65, line=dict(color="#00e6c3", width=2), showlegend=True, ), secondary_y=True, ) fig.update_layout( margin=dict(l=0, r=0, t=40, b=20), template=imps.PLT_CANDLE_STYLE_TEMPLATE, title=title, title_x=0.5, title_font_size=14, ) imagefile = "candle.png" # Check if interactive settings are enabled plt_link = "" if imps.INTERACTIVE: plt_link = imps.inter_chart(fig, imagefile, callback=True) fig.update_layout( width=800, height=500, ) imagefile = imps.image_border(imagefile, fig=fig) return { "title": title, "description": plt_link, "imagefile": imagefile, }
async def candle_command( ctx, ticker: str = "", interval: int = 15, past_days: int = 1, start="", end="", ): """Shows candle plot of loaded ticker. [Source: Yahoo Finance, IEX Cloud or Alpha Vantage] Parameters ---------- ticker: str Ticker name interval: int chart mins or daily past_days: int Display the past * days. Default: 1(Not for Daily) start: str start date format YYYY-MM-DD end: str end date format YYYY-MM-DD """ try: logger.info("candle %s %s %s %s", ticker, interval, start, end) 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) futures = "=F" if interval == 1440: df_stock_candidate = yf.download( ticker, start=start, end=end, progress=False, ) # Check that loading a stock was not successful if df_stock_candidate.empty: raise Exception(f"No data found for {ticker.upper()}") df_stock_candidate.index.name = "date" else: s_int = str(interval) + "m" d_granularity = { "1m": past_days, "5m": past_days, "15m": past_days, "30m": past_days, "60m": past_days, } s_start_dt = datetime.utcnow() - timedelta( days=d_granularity[s_int]) s_date_start = s_start_dt.strftime("%Y-%m-%d") df_stock_candidate = yf.download( ticker, start=s_date_start if s_start_dt > start else start.strftime("%Y-%m-%d"), progress=False, interval=s_int, prepost=True, ) # Check that loading a stock was not successful if df_stock_candidate.empty: raise Exception(f"No data found for {ticker.upper()}.") df_stock_candidate.index = df_stock_candidate.index.tz_localize(None) df_stock_candidate.index.name = "date" df_stock = df_stock_candidate price_df = df_stock.loc[(df_stock.index >= start) & (df_stock.index < end)] df_vwap = overlap_model.vwap(price_df, 0) plt_title = [f"{ticker.upper()} Intraday {interval}min", "Volume"] title = f"Intraday {interval}min Chart for {ticker.upper()}" if interval == 1440: plt_title = [f"{ticker.upper()} Daily", "Volume"] title = f"Daily Chart for {ticker.upper()}" fig = make_subplots( rows=2, cols=1, shared_xaxes=True, vertical_spacing=0.06, subplot_titles=plt_title, row_width=[0.2, 0.7], ) fig.add_trace( go.Candlestick( x=df_stock.index, open=df_stock.Open, high=df_stock.High, low=df_stock.Low, close=df_stock.Close, name="OHLC", showlegend=False, ), row=1, col=1, ) colors = [ "green" if row.Open < row["Adj Close"] else "red" for _, row in df_stock.iterrows() ] fig.add_trace( go.Bar( x=df_stock.index, y=df_stock.Volume, name="Volume", marker_color=colors, showlegend=False, ), row=2, col=1, ) fig.update_layout( margin=dict(l=0, r=0, t=25, b=20), template=cfg.PLT_CANDLE_STYLE_TEMPLATE, yaxis_title="Stock Price ($)", yaxis=dict( fixedrange=False, showspikes=True, ), xaxis=dict( rangeslider=dict(visible=False), type="date", showspikes=True, ), legend=dict(orientation="h", yanchor="bottom", y=1.02, xanchor="right", x=1), dragmode="pan", hovermode="x unified", ) if interval != 1440: fig.add_trace( go.Scatter( name="VWAP", x=df_stock.index, y=df_vwap["VWAP_D"], opacity=1, line=dict(color="#d81aea", width=2), showlegend=True, ), ) if futures in ticker.upper(): fig.update_xaxes(rangebreaks=[ dict(bounds=["fri", "sun"]), dict(bounds=[17, 17.5], pattern="hour"), ], ) else: fig.update_xaxes(rangebreaks=[ dict(bounds=["sat", "mon"]), dict(bounds=[19, 9.5], pattern="hour"), ], ) config = dict({"scrollZoom": True}) rand = random.randint(69, 69420) imagefile = f"candle{rand}.png" # Check if interactive settings are enabled plt_link = "" if cfg.INTERACTIVE: fig.write_html(f"in/candle_{rand}.html", config=config) plt_link = f"[Interactive]({cfg.INTERACTIVE_URL}/candle_{rand}.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=title, 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: Intraday", colour=cfg.COLOR, description=e, ) await ctx.send(embed=embed, delete_after=30.0)
def candle_command( ticker: str = "", interval: int = 15, past_days: int = 1, start="", end="", ): """Shows candle plot of loaded ticker. [Source: Yahoo Finance, IEX Cloud or Alpha Vantage] Parameters ---------- ticker: str Ticker name interval: int chart mins or daily past_days: int Display the past * days. Default: 1(Not for Daily) start: str start date format YYYY-MM-DD end: str end date format YYYY-MM-DD """ logger.info("candle %s %s %s %s", ticker, interval, start, end) 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) futures = "=F" or "^" crypto = "-USD" if interval == 1440: df_stock_candidate = yf.download( ticker, start=start, end=end, progress=False, ) # Check that loading a stock was not successful if df_stock_candidate.empty: raise Exception(f"No data found for {ticker.upper()}") df_stock_candidate.index.name = "date" else: s_int = str(interval) + "m" d_granularity = { "1m": past_days, "5m": past_days, "15m": past_days, "30m": past_days, "60m": past_days, } s_start_dt = datetime.utcnow() - timedelta(days=d_granularity[s_int]) s_date_start = s_start_dt.strftime("%Y-%m-%d") df_stock_candidate = yf.download( ticker, start=s_date_start if s_start_dt > start else start.strftime("%Y-%m-%d"), progress=False, interval=s_int, prepost=True, ) # Check that loading a stock was not successful if df_stock_candidate.empty: raise Exception(f"No data found for {ticker.upper()}.") df_stock_candidate.index = df_stock_candidate.index.tz_localize(None) df_stock_candidate.index.name = "date" df_stock = df_stock_candidate price_df = df_stock.loc[(df_stock.index >= start) & (df_stock.index < end)] df_vwap = overlap_model.vwap(price_df, 0) plt_title = [f"{ticker.upper()} Intraday {interval}min", "Volume"] title = f"Intraday {interval}min Chart for {ticker.upper()}" if interval == 1440: plt_title = [f"{ticker.upper()} Daily", "Volume"] title = f"Daily Chart for {ticker.upper()}" fig = make_subplots( shared_xaxes=True, vertical_spacing=0.09, subplot_titles=plt_title, specs=[[{ "secondary_y": True }]], ) fig.add_trace( go.Candlestick( x=df_stock.index, open=df_stock.Open, high=df_stock.High, low=df_stock.Low, close=df_stock.Close, name="OHLC", showlegend=False, ), secondary_y=True, ) fig.add_trace( go.Bar( x=df_stock.index, y=df_stock.Volume, name="Volume", yaxis="y2", marker_color="#d81aea", opacity=0.4, showlegend=False, ), secondary_y=False, ) if interval != 1440: fig.add_trace( go.Scatter( name="VWAP", x=df_stock.index, y=df_vwap["VWAP_D"], opacity=0.65, line=dict(color="#fdc708", width=2), showlegend=True, ), secondary_y=True, ) fig.update_xaxes(showspikes=True, spikesnap="cursor", spikemode="across") fig.update_yaxes(showspikes=True, spikethickness=2) fig.update_layout( margin=dict(l=0, r=0, t=40, b=20), template=cfg.PLT_CANDLE_STYLE_TEMPLATE, yaxis2_title="Price ($)", yaxis_title="Volume", yaxis=dict( showgrid=False, fixedrange=False, side="left", titlefont=dict(color="#d81aea"), tickfont=dict(color="#d81aea"), nticks=20, ), yaxis2=dict( side="right", fixedrange=False, anchor="x", layer="above traces", overlaying="y", nticks=20, ), xaxis=dict( rangeslider=dict(visible=False), type="date", showspikes=True, ), legend=dict(orientation="h", yanchor="bottom", y=1.02, xanchor="right", x=1), dragmode="pan", hovermode="x unified", spikedistance=1000, hoverdistance=100, ) if futures in ticker.upper(): fig.update_xaxes(rangebreaks=[ dict(bounds=["sat", "sun"]), dict(bounds=[17, 17.50], pattern="hour"), ], ) elif crypto not in ticker.upper() and interval != 1440: fig.update_xaxes(rangebreaks=[ dict(bounds=["sat", "mon"]), dict(bounds=[20, 9.50], pattern="hour"), ], ) config = dict({"scrollZoom": True}) imagefile = "candle.png" # Check if interactive settings are enabled plt_link = "" if cfg.INTERACTIVE: html_ran = helpers.uuid_get() fig.write_html(f"in/candle_{html_ran}.html", config=config) plt_link = f"[Interactive]({cfg.INTERACTIVE_URL}/candle_{html_ran}.html)" fig.update_layout( width=800, height=500, ) imagefile = helpers.image_border(imagefile, fig=fig) return { "title": title, "description": plt_link, "imagefile": imagefile, }