Beispiel #1
0
async def view_command(ctx, ticker=""):
    """Displays image from Finviz [Finviz]"""

    try:

        # Debug
        if cfg.DEBUG:
            print(f"!stocks.ta.view {ticker}")

        # Check for argument
        if ticker == "":
            raise Exception("Stock ticker is required")
        image_data = finviz_model.get_finviz_image(ticker)
        dataBytesIO = io.BytesIO(image_data)
        im = Image.open(dataBytesIO)

        fig, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI)
        ax.set_axis_off()
        fig.subplots_adjust(left=0, right=1, top=1, bottom=0)

        plt.imshow(im)

        plt.savefig("ta_view.png")
        uploaded_image = gst_imgur.upload_image("ta_view.png",
                                                title="something")
        image_link = uploaded_image.link
        if cfg.DEBUG:
            print(f"Image URL: {image_link}")
        title = "Stocks: [Finviz] Trendlines & Data " + 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_view.png")

        await ctx.send(embed=embed)

    except Exception as e:
        embed = discord.Embed(
            title="ERROR Stocks: [Finviz] Trendlines & Data",
            colour=cfg.COLOR,
            description=e,
        )
        embed.set_author(
            name=cfg.AUTHOR_NAME,
            icon_url=cfg.AUTHOR_ICON_URL,
        )

        await ctx.send(embed=embed)
Beispiel #2
0
async def cci_command(ctx,
                      ticker="",
                      length="14",
                      scalar="0.015",
                      start="",
                      end=""):
    """Displays chart with commodity channel index [Yahoo Finance]"""

    try:

        # Debug
        if cfg.DEBUG:
            logger.debug(
                "!stocks.ta.cci %s %s %s %s %s",
                ticker,
                length,
                scalar,
                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)
        # pylint
        try:
            length = int(length)
        except ValueError as e:
            raise Exception("Length has to be an integer") from e
        try:
            scalar = float(scalar)
        except ValueError as e:
            raise Exception("Scalar has to be an integer") from e

        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.cci(df_stock["High"], df_stock["Low"],
                                   df_stock["Adj Close"], length, scalar)

        fig, axes = plt.subplots(2, 1, figsize=plot_autoscale(), dpi=PLOT_DPI)
        ax = axes[0]
        ax.set_title(f"{ticker} CCI")
        ax.plot(df_stock.index, df_stock["Adj Close"].values, "k", lw=2)
        ax.set_xlim(df_stock.index[0], df_stock.index[-1])
        ax.set_ylabel("Share Price ($)")
        ax.grid(b=True, which="major", color="#666666", linestyle="-")

        ax2 = axes[1]
        ax2.plot(df_ta.index, df_ta.values, "b", lw=2)
        ax2.set_xlim(df_stock.index[0], df_stock.index[-1])
        ax2.axhspan(100, plt.gca().get_ylim()[1], facecolor="r", alpha=0.2)
        ax2.axhspan(plt.gca().get_ylim()[0], -100, facecolor="g", alpha=0.2)
        ax2.axhline(100, linewidth=3, color="r", ls="--")
        ax2.axhline(-100, linewidth=3, color="g", ls="--")
        ax2.grid(b=True, which="major", color="#666666", linestyle="-")

        ax3 = ax2.twinx()
        ax3.set_ylim(ax2.get_ylim())
        ax3.set_yticks([-100, 100])
        ax3.set_yticklabels(["OVERSOLD", "OVERBOUGHT"])

        plt.gcf().autofmt_xdate()
        fig.tight_layout(pad=1)

        plt.savefig("ta_cci.png")
        uploaded_image = gst_imgur.upload_image("ta_cci.png",
                                                title="something")
        image_link = uploaded_image.link
        if cfg.DEBUG:
            logger.debug("Image URL: %s", image_link)
        title = "Stocks: Commodity-Channel-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_cci.png")

        await ctx.send(embed=embed)

    except Exception as e:
        embed = discord.Embed(
            title="ERROR Stocks: Commodity-Channel-Index",
            colour=cfg.COLOR,
            description=e,
        )
        embed.set_author(
            name=cfg.AUTHOR_NAME,
            icon_url=cfg.AUTHOR_ICON_URL,
        )

        await ctx.send(embed=embed)
Beispiel #3
0
async def adx_command(ctx,
                      ticker="",
                      length="14",
                      scalar="100",
                      drift="1",
                      start="",
                      end=""):
    """Displays chart with average directional movement index [Yahoo Finance]"""

    try:

        # Debug
        if cfg.DEBUG:
            print(
                f"!stocks.ta.adx {ticker} {length} {scalar} {drift} {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 length.lstrip("-").isnumeric():
            raise Exception("Number has to be an integer")
        length = float(length)
        if not scalar.lstrip("-").isnumeric():
            raise Exception("Number has to be an integer")
        scalar = float(scalar)
        if not drift.lstrip("-").isnumeric():
            raise Exception("Number has to be an integer")
        drift = float(drift)

        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 = trend_indicators_model.adx("1440min", df_stock, length, scalar,
                                           drift)

        # Output Data
        fig, ax = plt.subplots(2, 1, figsize=plot_autoscale(), dpi=PLOT_DPI)
        ax0 = ax[0]
        ax0.plot(df_stock.index, df_stock["Close"].values, "k", lw=2)
        ax0.set_title(f"Average Directional Movement Index (ADX) on {ticker}")
        ax0.set_xlim(df_stock.index[0], df_stock.index[-1])
        ax0.set_ylabel("Share Price ($)")
        ax0.grid(b=True, which="major", color="#666666", linestyle="-")

        ax1 = ax[1]
        ax1.plot(df_ta.index, df_ta.iloc[:, 0].values, "b", lw=2)
        ax1.plot(df_ta.index, df_ta.iloc[:, 1].values, "g", lw=1)
        ax1.plot(df_ta.index, df_ta.iloc[:, 2].values, "r", lw=1)
        ax1.set_xlim(df_stock.index[0], df_stock.index[-1])
        ax1.axhline(25, linewidth=3, color="k", ls="--")
        ax1.legend(
            [
                f"ADX ({df_ta.columns[0]})",
                f"+DI ({df_ta.columns[1]})",
                f"- DI ({df_ta.columns[2]})",
            ],
            loc="upper left",
        )
        ax1.set_xlabel("Time")
        ax1.grid(b=True, which="major", color="#666666", linestyle="-")

        ax1.set_ylim([0, 100])

        fig.tight_layout()
        plt.gcf().autofmt_xdate()

        plt.savefig("ta_adx.png")
        uploaded_image = gst_imgur.upload_image("ta_adx.png",
                                                title="something")
        image_link = uploaded_image.link
        if cfg.DEBUG:
            print(f"Image URL: {image_link}")
        title = "Stocks: Average-Directional-Movement-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_adx.png")

        await ctx.send(embed=embed)

    except Exception as e:
        embed = discord.Embed(
            title="ERROR Stocks: Average-Directional-Movement-Index",
            colour=cfg.COLOR,
            description=e,
        )
        embed.set_author(
            name=cfg.AUTHOR_NAME,
            icon_url=cfg.AUTHOR_ICON_URL,
        )

        await ctx.send(embed=embed)
Beispiel #4
0
async def historical_command(ctx, signal="", start=""):
    """Displays historical price comparison between similar companies [Yahoo Finance]"""
    try:

        # Debug user input
        if cfg.DEBUG:
            logger.debug("!stocks.scr.historical %s %s", signal, start)

        # Check for argument
        if signal == "" or signal not in list(so.d_signals_desc.keys):
            raise Exception("Invalid preset selected!")

        register_matplotlib_converters()

        screen = ticker.Ticker()

        if signal in finviz_model.d_signals:
            screen.set_filter(signal=finviz_model.d_signals[signal])

        else:
            preset_filter = configparser.RawConfigParser()
            preset_filter.optionxform = str  # type: ignore
            preset_filter.read(so.presets_path + signal + ".ini")

            d_general = preset_filter["General"]
            d_filters = {
                **preset_filter["Descriptive"],
                **preset_filter["Fundamental"],
                **preset_filter["Technical"],
            }

            d_filters = {k: v for k, v in d_filters.items() if v}

            if d_general["Signal"]:
                screen.set_filter(filters_dict=d_filters,
                                  signal=d_general["Signal"])
            else:
                screen.set_filter(filters_dict=d_filters)

        if start == "":
            start = datetime.now() - timedelta(days=365)
        else:
            start = datetime.strptime(start, cfg.DATE_FORMAT)

        # Output Data
        l_min = []
        l_leg = []
        l_stocks = screen.ScreenerView(verbose=0)

        if len(l_stocks) > 10:
            description = (
                "\nThe limit of stocks to compare with are 10. Hence, 10 random similar stocks will be displayed."
                "\nThe selected list will be: ")
            random.shuffle(l_stocks)
            l_stocks = sorted(l_stocks[:10])
            description = description + (", ".join(l_stocks))
            logger.debug(description)

        plt.figure(figsize=plot_autoscale(), dpi=PLOT_DPI)

        while l_stocks:
            l_parsed_stocks = []
            for symbol in l_stocks:
                try:
                    df_similar_stock = yf.download(
                        symbol,
                        start=datetime.strftime(start, "%Y-%m-%d"),
                        progress=False,
                        threads=False,
                    )
                    if not df_similar_stock.empty:
                        plt.plot(
                            df_similar_stock.index,
                            df_similar_stock["Adj Close"].values,
                        )
                        l_min.append(df_similar_stock.index[0])
                        l_leg.append(symbol)

                    l_parsed_stocks.append(symbol)
                except Exception as e:
                    error = (
                        f"{e}\nDisregard previous error, which is due to API Rate limits from Yahoo Finance. "
                        f"Because we like '{symbol}', and we won't leave without getting data from it."
                    )
                    embed = discord.Embed(
                        title=
                        "ERROR Stocks: [Yahoo Finance] Historical Screener",
                        colour=cfg.COLOR,
                        description=error,
                    )
                    embed.set_author(
                        name=cfg.AUTHOR_NAME,
                        icon_url=cfg.AUTHOR_ICON_URL,
                    )

                    await ctx.send(embed=embed)

            for parsed_stock in l_parsed_stocks:
                l_stocks.remove(parsed_stock)

        if signal:
            plt.title(
                f"Screener Historical Price using {finviz_model.d_signals[signal]} signal"
            )
        else:
            plt.title(f"Screener Historical Price using {signal} preset")

        plt.xlabel("Time")
        plt.ylabel("Share Price ($)")
        plt.legend(l_leg)
        plt.grid(b=True, which="major", color="#666666", linestyle="-")
        plt.minorticks_on()
        plt.grid(b=True,
                 which="minor",
                 color="#999999",
                 linestyle="-",
                 alpha=0.2)
        # ensures that the historical data starts from same datapoint
        plt.xlim([max(l_min), df_similar_stock.index[-1]])

        plt.savefig("scr_historical.png")
        uploaded_image = gst_imgur.upload_image("scr_historical.png",
                                                title="something")
        image_link = uploaded_image.link
        if cfg.DEBUG:
            logger.debug("Image URL: %s", image_link)
        title = "Stocks: [Yahoo Finance] Historical Screener"
        embed = discord.Embed(title=title,
                              description=description,
                              colour=cfg.COLOR)
        embed.set_author(
            name=cfg.AUTHOR_NAME,
            icon_url=cfg.AUTHOR_ICON_URL,
        )
        embed.set_image(url=image_link)
        os.remove("scr_historical.png")

        await ctx.send(embed=embed)

    except Exception as e:
        embed = discord.Embed(
            title="ERROR Stocks: [Yahoo Finance] Historical Screener",
            colour=cfg.COLOR,
            description=e,
        )
        embed.set_author(
            name=cfg.AUTHOR_NAME,
            icon_url=cfg.AUTHOR_ICON_URL,
        )

        await ctx.send(embed=embed)
Beispiel #5
0
async def qtrcontracts_command(ctx, num="", analysis=""):
    """Displays a look at government contracts [quiverquant.com]"""
    try:
        # Debug user input
        if cfg.DEBUG:
            print(f"!stocks.gov.qtrcontracts {num} {analysis}")

        if num == "":
            num = 20
        else:
            if not num.lstrip("-").isnumeric():
                raise Exception("Number has to be an integer")
            num = int(num)

        possible_args = ["total", "upmom", "downmom"]
        if analysis == "":
            analysis = "total"
        elif analysis not in possible_args:
            raise Exception(
                "Enter a valid analysis argument, options are: total, upmom and downmom"
            )

        # Retrieve Data
        df_contracts = quiverquant_model.get_government_trading(
            "quarter-contracts")

        if df_contracts.empty:
            raise Exception("No quarterly government contracts found")

        tickers = quiverquant_model.analyze_qtr_contracts(analysis, num)

        # Output Data
        if analysis in {"upmom", "downmom"}:
            description = tickers.to_string()
            fig, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI)
            max_amount = 0
            quarter_ticks = []
            for symbol in tickers:
                amounts = (
                    df_contracts[df_contracts["Ticker"] == symbol].sort_values(
                        by=["Year", "Qtr"])["Amount"].values)

                qtr = (
                    df_contracts[df_contracts["Ticker"] == symbol].sort_values(
                        by=["Year", "Qtr"])["Qtr"].values)
                year = (
                    df_contracts[df_contracts["Ticker"] == symbol].sort_values(
                        by=["Year", "Qtr"])["Year"].values)

                ax.plot(np.arange(0, len(amounts)),
                        amounts / 1_000_000,
                        "-*",
                        lw=2,
                        ms=15)

                if len(amounts) > max_amount:
                    max_amount = len(amounts)
                    quarter_ticks = [
                        f"{quarter[0]} - Q{quarter[1]} "
                        for quarter in zip(year, qtr)
                    ]

            ax.set_xlim([-0.5, max_amount - 0.5])
            ax.set_xticks(np.arange(0, max_amount))
            ax.set_xticklabels(quarter_ticks)
            ax.grid()
            ax.legend(tickers)
            titles = {
                "upmom": "Highest increasing quarterly Government Contracts",
                "downmom": "Highest decreasing quarterly Government Contracts",
            }
            ax.set_title(titles[analysis])
            ax.set_xlabel("Date")
            ax.set_ylabel("Amount ($1M)")
            fig.tight_layout()

            plt.savefig("gov_qtrcontracts.png")
            uploaded_image = gst_imgur.upload_image("gov_qtrcontracts.png",
                                                    title="something")
            image_link = uploaded_image.link
            if cfg.DEBUG:
                print(f"Image URL: {image_link}")
            title = "Stocks: [quiverquant.com] Government contracts"
            embed = discord.Embed(title=title,
                                  description=description,
                                  colour=cfg.COLOR)
            embed.set_author(
                name=cfg.AUTHOR_NAME,
                icon_url=cfg.AUTHOR_ICON_URL,
            )
            embed.set_image(url=image_link)
            os.remove("gov_qtrcontracts.png")

            await ctx.send(embed=embed)

        elif analysis == "total":

            tickers.index = [
                ind + " " * (7 - len(ind)) for ind in tickers.index
            ]
            tickers[:] = [
                str(round(val[0] / 1e9, 2)) for val in tickers.values
            ]
            tickers.columns = ["Amount [M]"]

            tickers_str = tabulate(
                tickers,
                headers=tickers.columns,
                showindex=True,
                numalign="right",
                stralign="center",
            )

            embed = discord.Embed(
                title="Stocks: [quiverquant.com] Government contracts",
                description=tickers_str,
                colour=cfg.COLOR,
            )
            embed.set_author(
                name=cfg.AUTHOR_NAME,
                icon_url=cfg.AUTHOR_ICON_URL,
            )

            await ctx.send(embed=embed)

    except Exception as e:
        embed = discord.Embed(
            title="ERROR Stocks: [quiverquant.com] Government contracts",
            colour=cfg.COLOR,
            description=e,
        )
        embed.set_author(
            name=cfg.AUTHOR_NAME,
            icon_url=cfg.AUTHOR_ICON_URL,
        )

        await ctx.send(embed=embed)
Beispiel #6
0
async def obv_command(ctx, ticker="", start="", end=""):
    """Displays chart with on balance volume [Yahoo Finance]"""

    try:

        # Debug
        if cfg.DEBUG:
            print(f"!stocks.ta.obv {ticker} {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)

        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)]

        # Output Data
        bar_colors = [
            "r" if x[1].Open < x[1].Close else "g"
            for x in df_stock.iterrows()
        ]

        bar_width = timedelta(days=1)

        divisor = 1_000_000
        df_vol = df_stock["Volume"].dropna()
        df_vol = df_vol.values / divisor
        df_ta = volume_model.obv("1440min", df_stock)
        df_cal = df_ta.values
        df_cal = df_cal / divisor

        fig, axes = plt.subplots(
            3,
            1,
            gridspec_kw={"height_ratios": [2, 1, 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"{ticker} OBV")
        ax.set_xlim(df_stock.index[0], df_stock.index[-1])
        ax.set_ylabel("Price")
        ax.grid(b=True, which="major", color="#666666", linestyle="-")
        ax.minorticks_on()
        ax.grid(b=True,
                which="minor",
                color="#999999",
                linestyle="-",
                alpha=0.2)
        ax2 = axes[1]
        ax2.set_xlim(df_stock.index[0], df_stock.index[-1])
        ax2.set_ylabel("Volume [M]")
        ax2.bar(
            df_stock.index,
            df_vol,
            color=bar_colors,
            alpha=0.8,
            width=bar_width,
        )
        ax3 = axes[2]
        ax3.set_ylabel("OBV [M]")
        ax3.set_xlabel("Time")
        ax3.plot(df_ta.index, df_cal, "b", lw=1)
        ax3.set_xlim(df_stock.index[0], df_stock.index[-1])
        ax3.grid(b=True, which="major", color="#666666", linestyle="-")
        ax3.minorticks_on()
        ax3.grid(b=True,
                 which="minor",
                 color="#999999",
                 linestyle="-",
                 alpha=0.2)

        plt.gcf().autofmt_xdate()
        fig.tight_layout(pad=1)

        plt.savefig("ta_obv.png")
        uploaded_image = gst_imgur.upload_image("ta_obv.png",
                                                title="something")
        image_link = uploaded_image.link
        if cfg.DEBUG:
            print(f"Image URL: {image_link}")
        title = "Stocks: On-Balance-Volume " + 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_obv.png")

        await ctx.send(embed=embed)

    except Exception as e:
        embed = discord.Embed(
            title="ERROR Stocks: On-Balance-Volume",
            colour=cfg.COLOR,
            description=e,
        )
        embed.set_author(
            name=cfg.AUTHOR_NAME,
            icon_url=cfg.AUTHOR_ICON_URL,
        )

        await ctx.send(embed=embed)
Beispiel #7
0
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)
Beispiel #8
0
async def fisher_command(ctx, ticker="", length="14", start="", end=""):
    """Displays chart with fisher transformation [Yahoo Finance]"""

    try:

        # Debug
        if cfg.DEBUG:
            print(f"!stocks.ta.fisher {ticker} {length} {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 length.lstrip("-").isnumeric():
            raise Exception("Number has to be an integer")
        length = float(length)

        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.fisher("1440min", df_stock, length)

        # Output Data
        fig, axes = plt.subplots(2, 1, figsize=plot_autoscale(), dpi=PLOT_DPI)
        ax = axes[0]
        ax.set_title(f"{ticker} Fisher Transform")
        ax.plot(df_stock.index, df_stock["Adj Close"].values, "k", lw=1)
        ax.set_xlim(df_stock.index[0], df_stock.index[-1])
        ax.set_ylabel("Price")
        ax.grid(b=True, which="major", color="#666666", linestyle="-")

        ax2 = axes[1]
        ax2.plot(
            df_ta.index,
            df_ta.iloc[:, 0].values,
            "b",
            lw=2,
            label="Fisher",
        )
        ax2.plot(
            df_ta.index,
            df_ta.iloc[:, 1].values,
            "fuchsia",
            lw=2,
            label="Signal",
        )
        ax2.set_xlim(df_stock.index[0], df_stock.index[-1])
        ax2.axhspan(2, plt.gca().get_ylim()[1], facecolor="r", alpha=0.2)
        ax2.axhspan(plt.gca().get_ylim()[0], -2, facecolor="g", alpha=0.2)
        ax2.axhline(2, linewidth=3, color="r", ls="--")
        ax2.axhline(-2, linewidth=3, color="g", ls="--")
        ax2.grid(b=True, which="major", color="#666666", linestyle="-")
        ax2.set_xlim(df_stock.index[0], df_stock.index[-1])
        ax2.axhspan(2, plt.gca().get_ylim()[1], facecolor="r", alpha=0.2)
        ax2.axhspan(plt.gca().get_ylim()[0], -2, facecolor="g", alpha=0.2)
        ax2.axhline(2, linewidth=3, color="r", ls="--")
        ax2.axhline(-2, linewidth=3, color="g", ls="--")
        ax2.grid(b=True, which="major", color="#666666", linestyle="-")
        ax2.set_yticks([-2, 0, 2])
        ax2.set_yticklabels(["-2 STDEV", "0", "+2 STDEV"])

        plt.gcf().autofmt_xdate()
        fig.tight_layout(pad=1)

        plt.legend()

        plt.savefig("ta_fisher.png")
        uploaded_image = gst_imgur.upload_image("ta_fisher.png",
                                                title="something")
        image_link = uploaded_image.link
        if cfg.DEBUG:
            print(f"Image URL: {image_link}")
        title = "Stocks: Fisher-Transform " + 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_fisher.png")

        await ctx.send(embed=embed)

    except Exception as e:
        embed = discord.Embed(
            title="ERROR Stocks: Fisher-Transform",
            colour=cfg.COLOR,
            description=e,
        )
        embed.set_author(
            name=cfg.AUTHOR_NAME,
            icon_url=cfg.AUTHOR_ICON_URL,
        )

        await ctx.send(embed=embed)
Beispiel #9
0
async def aroon_command(ctx,
                        ticker="",
                        length="25",
                        scalar="100",
                        start="",
                        end=""):
    """Displays chart with aroon indicator [Yahoo Finance]"""

    try:

        # Debug
        if cfg.DEBUG:
            logger.debug(
                "!stocks.ta.aroon %s %s %s %s %s",
                ticker,
                length,
                scalar,
                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 length.lstrip("-").isnumeric():
            raise Exception("Number has to be an integer")
        length = int(length)
        if not scalar.lstrip("-").isnumeric():
            raise Exception("Number has to be an integer")
        scalar = float(scalar)

        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 = trend_indicators_model.aroon(df_stock["High"], df_stock["Low"],
                                             length, scalar)

        fig, ax = plt.subplots(3, 1, figsize=plot_autoscale(), dpi=PLOT_DPI)
        ax0 = ax[0]
        ax0.plot(df_stock.index, df_stock["Adj Close"].values, "k", lw=2)

        ax0.set_title(f"Aroon on {ticker}")
        ax0.set_xlim(df_stock.index[0], df_stock.index[-1])
        ax0.set_ylabel("Share Price ($)")
        ax0.grid(b=True, which="major", color="#666666", linestyle="-")

        ax1 = ax[1]
        ax1.plot(df_ta.index, df_ta.iloc[:, 0].values, "r", lw=2)
        ax1.plot(df_ta.index, df_ta.iloc[:, 1].values, "g", lw=2)
        ax1.set_xlim(df_stock.index[0], df_stock.index[-1])
        ax1.axhline(50, linewidth=1, color="k", ls="--")
        ax1.legend(
            [
                f"Aroon DOWN ({df_ta.columns[0]})",
                f"Aroon UP ({df_ta.columns[1]})"
            ],
            loc="upper left",
        )
        ax1.grid(b=True, which="major", color="#666666", linestyle="-")
        ax1.set_ylim([0, 100])

        ax2 = ax[2]
        ax2.plot(df_ta.index, df_ta.iloc[:, 2].values, "b", lw=2)
        ax2.set_xlim(df_stock.index[0], df_stock.index[-1])
        ax2.set_xlabel("Time")
        ax2.legend([f"Aroon OSC ({df_ta.columns[2]})"], loc="upper left")
        ax2.grid(b=True, which="major", color="#666666", linestyle="-")
        ax2.set_ylim([-100, 100])

        fig.tight_layout(pad=1)
        plt.gcf().autofmt_xdate()

        plt.savefig("ta_aroon.png")
        uploaded_image = gst_imgur.upload_image("ta_aroon.png",
                                                title="something")
        image_link = uploaded_image.link
        if cfg.DEBUG:
            logger.debug("Image URL: %s", image_link)
        title = "Stocks: Aroon-Indicator " + 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_aroon.png")

        await ctx.send(embed=embed)

    except Exception as e:
        embed = discord.Embed(
            title="ERROR Stocks: Aroon-Indicator",
            colour=cfg.COLOR,
            description=e,
        )
        embed.set_author(
            name=cfg.AUTHOR_NAME,
            icon_url=cfg.AUTHOR_ICON_URL,
        )

        await ctx.send(embed=embed)
Beispiel #10
0
async def ftd_command(ctx, ticker="", start="", end=""):
    """Fails-to-deliver data [SEC]"""

    try:
        # Debug user input
        if cfg.DEBUG:
            logger.debug("!stocks.dps.ftd %s %s %s", ticker, start, end)

        # Check for argument
        if ticker == "":
            raise Exception("Stock ticker is required")

        ticker = ticker.upper()

        stock = yf.download(ticker, progress=False)
        if stock.empty:
            raise Exception("Stock ticker is invalid")

        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)

        # Retrieve data
        ftds_data = sec_model.get_fails_to_deliver(ticker, start, end, 0)

        # Debug user output
        if cfg.DEBUG:
            logger.debug(ftds_data.to_string())

        plt.figure(dpi=PLOT_DPI)
        # Output data
        plt.bar(
            ftds_data["SETTLEMENT DATE"],
            ftds_data["QUANTITY (FAILS)"] / 1000,
        )
        plt.ylabel("Shares [K]")
        plt.title(f"Fails-to-deliver Data for {ticker}")
        plt.grid(b=True, which="major", color="#666666", linestyle="-", alpha=0.2)
        plt.gca().xaxis.set_major_formatter(mdates.DateFormatter("%Y/%m/%d"))
        plt.gca().xaxis.set_major_locator(mdates.DayLocator(interval=7))
        plt.gcf().autofmt_xdate()
        plt.xlabel("Days")
        _ = plt.gca().twinx()
        stock = discordbot.helpers.load(ticker, start)
        stock_ftd = stock[stock.index > start]
        stock_ftd = stock_ftd[stock_ftd.index < end]
        plt.plot(stock_ftd.index, stock_ftd["Adj Close"], color="tab:orange")
        plt.ylabel("Share Price [$]")
        plt.savefig("dps_ftd.png")
        plt.close("all")
        uploaded_image = gst_imgur.upload_image("dps_ftd.png", title="something")
        image_link = uploaded_image.link

        title = "Stocks: [SEC] Failure-to-deliver " + 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("dps_ftd.png")

        await ctx.send(embed=embed)

    except Exception as e:
        embed = discord.Embed(
            title=f"ERROR Stocks: [SEC] Failure-to-deliver {ticker}",
            colour=cfg.COLOR,
            description=e,
        )
        embed.set_author(
            name=cfg.AUTHOR_NAME,
            icon_url=cfg.AUTHOR_ICON_URL,
        )

        await ctx.send(embed=embed)
Beispiel #11
0
async def feargreed_command(ctx, indicator=""):
    """CNN Fear and Greed Index [CNN]"""

    try:
        # Debug user input
        if cfg.DEBUG:
            print(f"\n!economy.feargreed {indicator}")

        # Check for argument
        possible_indicators = ("", "jbd", "mv", "pco", "mm", "sps", "spb", "shd")

        if indicator not in possible_indicators:
            raise Exception(
                f"Select a valid indicator from {', '.join(possible_indicators)}"
            )

        # Retrieve data
        fig = plt.figure(figsize=[1, 1], dpi=10)

        report, _ = cnn_model.get_feargreed_report(indicator, fig)
        cnn_view.fear_and_greed_index(indicator=indicator, export="png")
        plt.close("all")

        # Output data
        now = datetime.datetime.now()
        image_path = os.path.join(
            cfg.GST_PATH,
            "exports",
            "economy",
            f"feargreed_{now.strftime('%Y%m%d_%H%M%S')}.png",
        )

        i = 0
        while not os.path.exists(image_path) and i < 10:
            now -= datetime.timedelta(seconds=1)
            image_path = os.path.join(
                cfg.GST_PATH,
                "exports",
                "economy",
                f"feargreed_{now.strftime('%Y%m%d_%H%M%S')}.png",
            )
            i += 1

        embed = discord.Embed(
            title="Economy: [CNN] Fear Geed Index",
            description=report,
            colour=cfg.COLOR,
        )
        embed.set_author(
            name=cfg.AUTHOR_NAME,
            icon_url=cfg.AUTHOR_ICON_URL,
        )

        if os.path.exists(image_path):
            uploaded_image = gst_imgur.upload_image(
                image_path, title="FearGreed Charts"
            )
            embed.set_image(url=uploaded_image.link)

        else:
            if cfg.DEBUG:
                print("Error with uploading the the image to Imgur.")

        await ctx.send(embed=embed)

    except Exception as e:
        embed = discord.Embed(
            title="ERROR Economy: [CNN] Feargreed",
            colour=cfg.COLOR,
            description=e,
        )
        embed.set_author(
            name=cfg.AUTHOR_NAME,
            icon_url=cfg.AUTHOR_ICON_URL,
        )

        await ctx.send(embed=embed)
Beispiel #12
0
async def bbands_command(ctx,
                         ticker="",
                         length="5",
                         n_std="2",
                         mamode="sma",
                         start="",
                         end=""):
    """Displays chart with bollinger bands [Yahoo Finance]"""

    try:

        # Debug
        if cfg.DEBUG:
            # pylint: disable=logging-too-many-args
            logger.debug(
                "!stocks.ta.bbands %s %s %s %s %s %s",
                ticker,
                length,
                n_std,
                mamode,
                start,
                end,
            )

        # Check for argument
        possible_ma = [
            "dema",
            "ema",
            "fwma",
            "hma",
            "linreg",
            "midpoint",
            "pwma",
            "rma",
            "sinwma",
            "sma",
            "swma",
            "t3",
            "tema",
            "trima",
            "vidya",
            "wma",
            "zlma",
        ]

        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 length.lstrip("-").isnumeric():
            raise Exception("Number has to be an integer")
        length = float(length)
        if not n_std.lstrip("-").isnumeric():
            raise Exception("Number has to be an integer")
        n_std = float(n_std)

        if mamode not in possible_ma:
            raise Exception("Invalid ma entered")

        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 = volatility_model.bbands(df_stock["Adj Close"], length, n_std,
                                        mamode)

        # Output Data
        fig, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI)
        ax.plot(df_stock.index, df_stock["Adj Close"].values, color="k", lw=3)
        ax.plot(df_ta.index, df_ta.iloc[:, 0].values, "r", lw=2)
        ax.plot(df_ta.index, df_ta.iloc[:, 1].values, "b", lw=1.5, ls="--")
        ax.plot(df_ta.index, df_ta.iloc[:, 2].values, "g", lw=2)
        ax.set_title(f"{ticker} Bollinger Bands")
        ax.set_xlim(df_stock.index[0], df_stock.index[-1])
        ax.set_xlabel("Time")
        ax.set_ylabel("Share Price ($)")

        ax.legend(
            [ticker, df_ta.columns[0], df_ta.columns[1], df_ta.columns[2]])
        ax.fill_between(
            df_ta.index,
            df_ta.iloc[:, 0].values,
            df_ta.iloc[:, 2].values,
            alpha=0.1,
            color="b",
        )
        ax.grid(b=True, which="major", color="#666666", linestyle="-")

        plt.gcf().autofmt_xdate()
        fig.tight_layout(pad=1)

        plt.savefig("ta_bbands.png")
        uploaded_image = gst_imgur.upload_image("ta_bbands.png",
                                                title="something")
        image_link = uploaded_image.link
        if cfg.DEBUG:
            logger.debug("Image URL: %s", image_link)
        title = "Stocks: Bollinger-Bands " + 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_bbands.png")

        await ctx.send(embed=embed)

    except Exception as e:
        embed = discord.Embed(
            title="ERROR Stocks: Bollinger-Bands",
            colour=cfg.COLOR,
            description=e,
        )
        embed.set_author(
            name=cfg.AUTHOR_NAME,
            icon_url=cfg.AUTHOR_ICON_URL,
        )

        await ctx.send(embed=embed)
Beispiel #13
0
async def kc_command(ctx,
                     ticker="",
                     length="20",
                     scalar="2",
                     mamode="sma",
                     offset="0",
                     start="",
                     end=""):
    """Displays chart with keltner channel [Yahoo Finance]"""

    try:

        # Debug
        if cfg.DEBUG:
            print(
                f"!stocks.ta.kc {ticker} {length} {scalar} {mamode} {offset} {start} {end}"
            )

        # Check for argument
        possible_ma = ["sma", "ema", "wma", "hma", "zlma"]

        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 length.lstrip("-").isnumeric():
            raise Exception("Number has to be an integer")
        length = float(length)
        if not scalar.lstrip("-").isnumeric():
            raise Exception("Number has to be an integer")
        scalar = float(scalar)
        if not offset.lstrip("-").isnumeric():
            raise Exception("Number has to be an integer")
        offset = float(offset)

        if mamode not in possible_ma:
            raise Exception("Invalid ma entered")

        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 = volatility_model.kc("1440min", df_stock, length, scalar,
                                    mamode, offset)

        # Output Data
        fig, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI)
        ax.plot(df_stock.index, df_stock["Adj Close"].values, color="fuchsia")
        ax.plot(df_ta.index,
                df_ta.iloc[:, 0].values,
                "b",
                lw=1.5,
                label="upper")
        ax.plot(df_ta.index, df_ta.iloc[:, 1].values, "b", lw=1.5, ls="--")
        ax.plot(df_ta.index,
                df_ta.iloc[:, 2].values,
                "b",
                lw=1.5,
                label="lower")
        ax.set_title(f"{ticker} Keltner Channels")
        ax.set_xlim(df_stock.index[0], df_stock.index[-1])
        ax.set_xlabel("Time")
        ax.set_ylabel("Price")

        ax.legend(
            [ticker, df_ta.columns[0], df_ta.columns[1], df_ta.columns[2]])
        ax.fill_between(
            df_ta.index,
            df_ta.iloc[:, 0].values,
            df_ta.iloc[:, 2].values,
            alpha=0.1,
            color="b",
        )
        ax.grid(b=True, which="major", color="#666666", linestyle="-")

        plt.gcf().autofmt_xdate()
        fig.tight_layout(pad=1)

        plt.legend()

        plt.savefig("ta_kc.png")
        uploaded_image = gst_imgur.upload_image("ta_kc.png", title="something")
        image_link = uploaded_image.link
        if cfg.DEBUG:
            print(f"Image URL: {image_link}")
        title = "Stocks: Keltner-Channel " + 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_kc.png")

        await ctx.send(embed=embed)

    except Exception as e:
        embed = discord.Embed(
            title="ERROR Stocks: Keltner-Channel",
            colour=cfg.COLOR,
            description=e,
        )
        embed.set_author(
            name=cfg.AUTHOR_NAME,
            icon_url=cfg.AUTHOR_ICON_URL,
        )

        await ctx.send(embed=embed)
Beispiel #14
0
async def toplobbying_command(ctx, num="", raw=""):
    """Displays top lobbying firms [quiverquant.com]"""
    try:
        # Debug user input
        if cfg.DEBUG:
            logger.debug("!stocks.gov.toplobbying %s %s", num, raw)

        if num == "":
            num = 10
        else:
            if not num.lstrip("-").isnumeric():
                raise Exception("Number has to be an integer")
            num = int(num)

        if raw in ["false", "False", "FALSE", ""]:
            raw = False

        if raw in ["true", "True", "TRUE"]:
            raw = True

        if raw not in [True, False]:
            raise Exception("raw argument has to be true or false")

        # Retrieve Data
        df_lobbying = quiverquant_model.get_government_trading(
            "corporate-lobbying")

        if df_lobbying.empty:
            raise Exception("No corporate lobbying found")

        df_lobbying["Amount"] = df_lobbying.Amount.astype(float).fillna(
            0) / 100_000

        lobbying_by_ticker = pd.DataFrame(
            df_lobbying.groupby("Ticker")["Amount"].agg("sum")).sort_values(
                by="Amount", ascending=False)
        fig, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI)
        lobbying_by_ticker.head(num).plot(kind="bar", ax=ax)
        ax.set_xlabel("Ticker")
        ax.set_ylabel("Total Amount ($100k)")
        ax.set_title(
            f"Corporate Lobbying Spent since {df_lobbying['Date'].min()}")
        fig.tight_layout()

        plt.savefig("ta_toplobbying.png")
        uploaded_image = gst_imgur.upload_image("ta_toplobbying.png",
                                                title="something")
        image_link = uploaded_image.link
        if cfg.DEBUG:
            logger.debug("Image URL: %s", image_link)
        title = "Stocks: [quiverquant.com] Top Lobbying Firms"
        if raw:
            description = lobbying_by_ticker.head(num).to_string()
            embed = discord.Embed(title=title,
                                  description=description,
                                  colour=cfg.COLOR)
        else:
            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_toplobbying.png")

        await ctx.send(embed=embed)

    except Exception as e:
        embed = discord.Embed(
            title="ERROR Stocks: [quiverquant.com] Top Lobbying Firms",
            colour=cfg.COLOR,
            description=e,
        )
        embed.set_author(
            name=cfg.AUTHOR_NAME,
            icon_url=cfg.AUTHOR_ICON_URL,
        )

        await ctx.send(embed=embed)
Beispiel #15
0
async def psi_command(ctx, ticker=""):
    """Price vs short interest volume [Stockgrid]"""

    try:
        # Debug user input
        if cfg.DEBUG:
            logger.debug("!stocks.dps.psi %s", ticker)

        # Check for argument
        if ticker == "":
            raise Exception("Stock ticker is required")

        ticker = ticker.upper()

        stock = yf.download(ticker, progress=False)
        if stock.empty:
            raise Exception("Stock ticker is invalid")

        # Retrieve data
        df, prices = stockgrid_model.get_short_interest_volume(ticker)

        # Debug user output
        if cfg.DEBUG:
            logger.debug(df.to_string())

        # Output data
        title = f"Stocks: [Stockgrid] Price vs Short Interest Volume {ticker}"
        embed = discord.Embed(title=title, colour=cfg.COLOR)
        embed.set_author(
            name=cfg.AUTHOR_NAME,
            icon_url=cfg.AUTHOR_ICON_URL,
        )

        _, axes = plt.subplots(
            2,
            1,
            dpi=PLOT_DPI,
            gridspec_kw={"height_ratios": [2, 1]},
        )

        axes[0].bar(
            df["date"],
            df["total_volume"] / 1_000_000,
            width=timedelta(days=1),
            color="b",
            alpha=0.4,
            label="Total Volume",
        )
        axes[0].bar(
            df["date"],
            df["short_volume"] / 1_000_000,
            width=timedelta(days=1),
            color="r",
            alpha=0.4,
            label="Short Volume",
        )

        axes[0].set_ylabel("Volume (1M)")
        ax2 = axes[0].twinx()
        ax2.plot(
            df["date"].values,
            prices[len(prices) - len(df):],  # noqa: E203
            c="k",
            label="Price",
        )
        ax2.set_ylabel("Price ($)")

        lines, labels = axes[0].get_legend_handles_labels()
        lines2, labels2 = ax2.get_legend_handles_labels()
        ax2.legend(lines + lines2, labels + labels2, loc="upper left")

        axes[0].grid()
        axes[0].ticklabel_format(style="plain", axis="y")
        plt.title(f"Price vs Short Volume Interest for {ticker}")
        plt.gcf().autofmt_xdate()

        axes[1].plot(
            df["date"].values,
            100 * df["short_volume%"],
            c="green",
            label="Short Vol. %",
        )

        axes[1].set_ylabel("Short Vol. %")

        axes[1].grid(axis="y")
        lines, labels = axes[1].get_legend_handles_labels()
        axes[1].legend(lines, labels, loc="upper left")
        axes[1].set_ylim([0, 100])
        file_name = ticker + "_psi.png"
        plt.savefig(file_name)
        plt.close("all")
        uploaded_image = gst_imgur.upload_image(file_name, title="something")
        image_link = uploaded_image.link
        embed.set_image(url=image_link)
        os.remove(file_name)

        await ctx.send(embed=embed)

    except Exception as e:
        embed = discord.Embed(
            title=
            f"ERROR Stocks: [Stockgrid] Price vs Short Interest Volume {ticker}",
            colour=cfg.COLOR,
            description=e,
        )
        embed.set_author(
            name=cfg.AUTHOR_NAME,
            icon_url=cfg.AUTHOR_ICON_URL,
        )

        await ctx.send(embed=embed)
Beispiel #16
0
async def topbuys_command(ctx,
                          gov_type="",
                          past_transactions_months="",
                          num="",
                          raw=""):
    """Displays most purchased stocks by the congress/senate/house [quiverquant.com]"""
    try:
        # Debug user input
        if cfg.DEBUG:
            logger.debug(
                "!stocks.gov.topbuys %s %s %s %s",
                gov_type,
                past_transactions_months,
                num,
                raw,
            )

        if past_transactions_months == "":
            past_transactions_months = 5
        else:
            if not past_transactions_months.lstrip("-").isnumeric():
                raise Exception("Number has to be an integer")
            past_transactions_months = int(past_transactions_months)

        if num == "":
            num = 10
        else:
            if not num.lstrip("-").isnumeric():
                raise Exception("Number has to be an integer")
            num = int(num)

        if raw in ["false", "False", "FALSE", ""]:
            raw = False

        if raw in ["true", "True", "TRUE"]:
            raw = True

        if raw not in [True, False]:
            raise Exception("raw argument has to be true or false")

        possible_args = ["congress", "senate", "house"]
        if gov_type == "":
            gov_type = "congress"
        elif gov_type not in possible_args:
            raise Exception(
                "Enter a valid government argument, options are: congress, senate and house"
            )

        # Retrieve Data
        df_gov = quiverquant_model.get_government_trading(gov_type)

        if df_gov.empty:
            logger.debug("No %s trading data found", gov_type)
            return

        df_gov = df_gov.sort_values("TransactionDate", ascending=False)
        start_date = datetime.now() - timedelta(days=past_transactions_months *
                                                30)

        df_gov["TransactionDate"] = pd.to_datetime(df_gov["TransactionDate"])

        df_gov = df_gov[df_gov["TransactionDate"] > start_date].dropna()
        # Catch bug where error shown for purchase of >5,000,000
        df_gov["Range"] = df_gov["Range"].apply(
            lambda x: "$5,000,001-$5,000,001" if x == ">$5,000,000" else x)
        df_gov["min"] = df_gov["Range"].apply(
            lambda x: x.split("-")[0].strip("$").replace(",", "").strip())
        df_gov["max"] = df_gov["Range"].apply(
            lambda x: x.split("-")[1].replace(",", "").strip().strip("$")
            if "-" in x else x.strip("$").replace(",", ""))
        df_gov["lower"] = df_gov[["min", "max", "Transaction"]].apply(
            lambda x: float(x["min"])
            if x["Transaction"] == "Purchase" else -float(x["max"]),
            axis=1,
        )
        df_gov["upper"] = df_gov[["min", "max", "Transaction"]].apply(
            lambda x: float(x["max"])
            if x["Transaction"] == "Purchase" else -float(x["min"]),
            axis=1,
        )

        df_gov = df_gov.sort_values("TransactionDate", ascending=True)
        if raw:
            df = pd.DataFrame(
                df_gov.groupby("Ticker")["upper"].sum().div(1000).sort_values(
                    ascending=False).head(n=num))
            description = "```" + df.to_string() + "```"

        fig, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI)

        df_gov.groupby("Ticker")["upper"].sum().div(1000).sort_values(
            ascending=False).head(n=num).plot(kind="bar", rot=0, ax=ax)

        ax.set_ylabel("Amount [1k $]")
        ax.set_title(
            f"Top {num} purchased stocks over last {past_transactions_months} "
            f"months (upper bound) for {gov_type.upper()}")
        plt.gcf().axes[0].yaxis.get_major_formatter().set_scientific(False)
        fig.tight_layout()

        plt.savefig("gov_topbuys.png")
        uploaded_image = gst_imgur.upload_image("gov_topbuys.png",
                                                title="something")
        image_link = uploaded_image.link
        if cfg.DEBUG:
            logger.debug("Image URL: %s", image_link)
        title = f"Stocks: [quiverquant.com] Top purchases for {gov_type.upper()}"
        if raw:
            embed = discord.Embed(title=title,
                                  description=description,
                                  colour=cfg.COLOR)
        else:
            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("gov_topbuys.png")

        await ctx.send(embed=embed)

    except Exception as e:
        embed = discord.Embed(
            title=
            f"ERROR Stocks: [quiverquant.com] Top purchases for {gov_type.upper()}",
            colour=cfg.COLOR,
            description=e,
        )
        embed.set_author(
            name=cfg.AUTHOR_NAME,
            icon_url=cfg.AUTHOR_ICON_URL,
        )

        await ctx.send(embed=embed)
Beispiel #17
0
async def macd_command(ctx,
                       ticker="",
                       fast="12",
                       slow="26",
                       signal="9",
                       start="",
                       end=""):
    """Displays chart with moving average convergence/divergence [Yahoo Finance]"""

    try:

        # Debug
        if cfg.DEBUG:
            print(
                f"!stocks.ta.macd {ticker} {fast} {slow} {signal} {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.lstrip("-").isnumeric():
            raise Exception("Number has to be an integer")
        fast = float(fast)
        if not slow.lstrip("-").isnumeric():
            raise Exception("Number has to be an integer")
        slow = float(slow)
        if not signal.lstrip("-").isnumeric():
            raise Exception("Number has to be an integer")
        signal = float(signal)

        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.macd("1440min", df_stock, fast, slow, signal)

        # Output Data
        fig, axes = plt.subplots(2, 1, figsize=plot_autoscale(), dpi=PLOT_DPI)
        ax = axes[0]
        ax.set_title(f"{ticker} MACD")
        ax.plot(df_stock.index, df_stock["Adj Close"].values, "k", lw=2)
        ax.set_xlim(df_stock.index[0], df_stock.index[-1])
        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, "b", lw=2)
        ax2.plot(df_ta.index, df_ta.iloc[:, 2].values, "r", lw=2)
        ax2.bar(df_ta.index, df_ta.iloc[:, 1].values, color="g")
        ax2.legend(
            [
                f"MACD Line {df_ta.columns[0]}",
                f"Signal Line {df_ta.columns[2]}",
                f"Histogram {df_ta.columns[1]}",
            ],
            loc="upper left",
        )
        ax2.set_xlim(df_stock.index[0], df_stock.index[-1])
        ax2.grid(b=True, which="major", color="#666666", linestyle="-")

        plt.gcf().autofmt_xdate()
        fig.tight_layout(pad=1)

        plt.savefig("ta_macd.png")
        uploaded_image = gst_imgur.upload_image("ta_cci.png",
                                                title="something")
        image_link = uploaded_image.link
        if cfg.DEBUG:
            print(f"Image URL: {image_link}")
        title = "Stocks: Moving-Average-Convergence-Divergence " + 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_macd.png")

        await ctx.send(embed=embed)

    except Exception as e:
        embed = discord.Embed(
            title="ERROR Stocks: Moving-Average-Convergence-Divergence",
            colour=cfg.COLOR,
            description=e,
        )
        embed.set_author(
            name=cfg.AUTHOR_NAME,
            icon_url=cfg.AUTHOR_ICON_URL,
        )

        await ctx.send(embed=embed)
Beispiel #18
0
async def pt_command(ctx, ticker="", raw="", start=""):
    """Displays price targets [Business Insider]"""

    try:
        # Debug
        if cfg.DEBUG:
            logger.debug("!stocks.dd.pt %s", ticker)

        # 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 raw in ["false", "False", "FALSE", ""]:
            raw = False

        if raw in ["true", "True", "TRUE"]:
            raw = True

        if raw not in [True, False]:
            raise Exception("raw argument has to be true or false")

        df_analyst_data = business_insider_model.get_price_target_from_analysts(
            ticker)
        stock = discordbot.helpers.load(ticker, start)

        if df_analyst_data.empty or stock.empty:
            raise Exception("Enter valid ticker")

        # Output Data

        if raw:
            df_analyst_data.sort_index(ascending=False)
            report = "´´´" + df_analyst_data.to_string() + "´´´"
            embed = discord.Embed(
                title="Stocks: [Business Insider] Price Targets",
                description=report,
                colour=cfg.COLOR,
            ).set_author(
                name=cfg.AUTHOR_NAME,
                icon_url=cfg.AUTHOR_ICON_URL,
            )
            ctx.send(embed=embed)
        else:
            plt.figure(dpi=PLOT_DPI)
            if start:
                df_analyst_data = df_analyst_data[start:]

            plt.plot(stock.index, stock["Adj Close"].values, lw=3)

            plt.plot(df_analyst_data.groupby(by=["Date"]).mean())

            plt.scatter(df_analyst_data.index,
                        df_analyst_data["Price Target"],
                        c="r",
                        s=40)

            plt.legend(
                ["Closing Price", "Average Price Target", "Price Target"])

            plt.title(f"{ticker} (Time Series) and Price Target")
            plt.xlim(stock.index[0], stock.index[-1])
            plt.xlabel("Time")
            plt.ylabel("Share Price")
            plt.grid(b=True, which="major", color="#666666", linestyle="-")
            plt.gcf().autofmt_xdate()
            plt.savefig("ta_pt.png")
            uploaded_image = gst_imgur.upload_image("ta_pt.png",
                                                    title="something")
            image_link = uploaded_image.link
            if cfg.DEBUG:
                logger.debug("Image URL: %s", image_link)
            title = "Stocks: [Business Insider] Price Targets " + 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_pt.png")

            await ctx.send(embed=embed)

    except Exception as e:
        embed = discord.Embed(
            title="ERROR Stocks: [Business Insider] Price Targets",
            colour=cfg.COLOR,
            description=e,
        )
        embed.set_author(
            name=cfg.AUTHOR_NAME,
            icon_url=cfg.AUTHOR_ICON_URL,
        )

        await ctx.send(embed=embed)
Beispiel #19
0
async def gtrades_command(ctx,
                          ticker="",
                          gov_type="",
                          past_transactions_months="",
                          raw=""):
    """Displays government trades [quiverquant.com]"""
    try:
        # Debug user input
        if cfg.DEBUG:
            print(
                f"!stocks.gov.gtrades {ticker} {gov_type} {past_transactions_months} {raw}"
            )

        if past_transactions_months == "":
            past_transactions_months = 10
        else:
            if not past_transactions_months.lstrip("-").isnumeric():
                raise Exception("Number has to be an integer")
            past_transactions_months = float(past_transactions_months)

        if raw in ["false", "False", "FALSE", ""]:
            raw = False

        if raw in ["true", "True", "TRUE"]:
            raw = True

        if raw not in [True, False]:
            raise Exception("raw argument has to be true or false")

        if ticker == "":
            raise Exception("A ticker is required")

        possible_args = ["congress", "senate", "house"]
        if gov_type == "":
            gov_type = "congress"
        elif gov_type not in possible_args:
            raise Exception(
                "Enter a valid government argument, options are: congress, senate and house"
            )

        # Retrieve Data
        df_gov = quiverquant_model.get_government_trading(gov_type, ticker)

        if df_gov.empty:
            raise Exception(f"No {gov_type} trading data found")

        # Output Data
        df_gov = df_gov.sort_values("TransactionDate", ascending=False)

        start_date = datetime.now() - timedelta(days=past_transactions_months *
                                                30)

        df_gov["TransactionDate"] = pd.to_datetime(df_gov["TransactionDate"])

        df_gov = df_gov[df_gov["TransactionDate"] > start_date]

        if df_gov.empty:
            print(f"No recent {gov_type} trading data found\n")
            return

        df_gov["min"] = df_gov["Range"].apply(
            lambda x: x.split("-")[0].strip("$").replace(",", "").strip())
        df_gov["max"] = df_gov["Range"].apply(
            lambda x: x.split("-")[1].replace(",", "").strip().strip("$")
            if "-" in x else x.strip("$").replace(",", "").split("\n")[0])

        df_gov["lower"] = df_gov[["min", "max", "Transaction"]].apply(
            lambda x: int(float(x["min"]))
            if x["Transaction"] == "Purchase" else -int(float(x["max"])),
            axis=1,
        )
        df_gov["upper"] = df_gov[["min", "max", "Transaction"]].apply(
            lambda x: int(float(x["max"]))
            if x["Transaction"] == "Purchase" else -1 * int(float(x["min"])),
            axis=1,
        )

        df_gov = df_gov.sort_values("TransactionDate", ascending=True)

        fig, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI)

        ax.fill_between(
            df_gov["TransactionDate"].unique(),
            df_gov.groupby("TransactionDate")["lower"].sum().values / 1000,
            df_gov.groupby("TransactionDate")["upper"].sum().values / 1000,
        )

        ax.set_xlim([
            df_gov["TransactionDate"].values[0],
            df_gov["TransactionDate"].values[-1],
        ])
        ax.grid()
        ax.set_title(f"{gov_type.capitalize()} trading on {ticker}")
        ax.set_xlabel("Date")
        ax.set_ylabel("Amount ($1k)")
        plt.gca().xaxis.set_major_formatter(mdates.DateFormatter("%Y/%m/%d"))
        plt.gcf().autofmt_xdate()
        fig.tight_layout()

        plt.savefig("gov_gtrades.png")
        uploaded_image = gst_imgur.upload_image("gov_gtrades.png",
                                                title="something")
        image_link = uploaded_image.link
        if cfg.DEBUG:
            print(f"Image URL: {image_link}")
        title = "Stocks: [quiverquant.com] Government Trades"
        if raw:
            description = df_gov.to_string()
            embed = discord.Embed(title=title,
                                  description=description,
                                  colour=cfg.COLOR)
        else:
            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("gov_gtrades.png")

        await ctx.send(embed=embed)

    except Exception as e:
        embed = discord.Embed(
            title="ERROR Stocks: [quiverquant.com] Government Trades",
            colour=cfg.COLOR,
            description=e,
        )
        embed.set_author(
            name=cfg.AUTHOR_NAME,
            icon_url=cfg.AUTHOR_ICON_URL,
        )

        await ctx.send(embed=embed)
Beispiel #20
0
async def contracts_command(ctx, ticker="", past_transaction_days="", raw=""):
    """Displays contracts associated with tickers [quiverquant.com]"""
    try:
        # Debug user input
        if cfg.DEBUG:
            logger.debug(
                "!stocks.gov.contracts %s %s %s", ticker, past_transaction_days, raw
            )

        if past_transaction_days == "":
            past_transaction_days = 10
        else:
            if not past_transaction_days.lstrip("-").isnumeric():
                raise Exception("Number has to be an integer")
            past_transaction_days = int(past_transaction_days)

        if raw in ["false", "False", "FALSE", ""]:
            raw = False

        if raw in ["true", "True", "TRUE"]:
            raw = True

        if raw not in [True, False]:
            raise Exception("raw argument has to be true or false")

        if ticker == "":
            raise Exception("A ticker is required")

        # Retrieve Data
        df_contracts = quiverquant_model.get_government_trading("contracts", ticker)

        if df_contracts.empty:
            raise Exception("No government contracts found")

        # Output Data
        df_contracts["Date"] = pd.to_datetime(df_contracts["Date"]).dt.date

        df_contracts = df_contracts[
            df_contracts["Date"].isin(
                df_contracts["Date"].unique()[:past_transaction_days]
            )
        ]

        df_contracts.drop_duplicates(inplace=True)

        fig, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI)

        df_contracts.groupby("Date").sum().div(1000).plot(kind="bar", rot=0, ax=ax)
        ax.set_ylabel("Amount ($1k)")
        ax.set_title(f"Sum of latest government contracts to {ticker}")
        fig.tight_layout()

        plt.savefig("gov_contracts.png")
        uploaded_image = gst_imgur.upload_image("gov_contracts.png", title="something")
        image_link = uploaded_image.link
        if cfg.DEBUG:
            logger.debug("Image URL: %s", image_link)
        title = f"Stocks: [quiverquant.com] Contracts by {ticker}"
        if raw:
            description = df_contracts.to_string()
            embed = discord.Embed(
                title=title, description=description, colour=cfg.COLOR
            )
        else:
            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("gov_contracts.png")

        await ctx.send(embed=embed)

    except Exception as e:
        embed = discord.Embed(
            title=f"ERROR Stocks: [quiverquant.com] Contracts by {ticker}",
            colour=cfg.COLOR,
            description=e,
        )
        embed.set_author(
            name=cfg.AUTHOR_NAME,
            icon_url=cfg.AUTHOR_ICON_URL,
        )

        await ctx.send(embed=embed)
Beispiel #21
0
async def donchian_command(ctx,
                           ticker="",
                           upper_length="25",
                           lower_length="100",
                           start="",
                           end=""):
    """Displays chart with donchian channel [Yahoo Finance]"""

    try:

        # Debug
        if cfg.DEBUG:
            logger.debug(
                "!stocks.ta.donchian %s %s %s %s %s",
                ticker,
                upper_length,
                lower_length,
                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 upper_length.lstrip("-").isnumeric():
            raise Exception("Number has to be an integer")
        upper_length = float(upper_length)
        if not lower_length.lstrip("-").isnumeric():
            raise Exception("Number has to be an integer")
        lower_length = float(lower_length)

        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 = volatility_model.donchian(df_stock["High"], df_stock["Low"],
                                          upper_length, lower_length)

        # Output Data
        fig, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI)
        ax.plot(df_stock.index, df_stock["Adj Close"].values, color="k", lw=3)
        ax.plot(df_ta.index,
                df_ta.iloc[:, 0].values,
                "b",
                lw=1.5,
                label="upper")
        ax.plot(df_ta.index, df_ta.iloc[:, 1].values, "b", lw=1.5, ls="--")
        ax.plot(df_ta.index,
                df_ta.iloc[:, 2].values,
                "b",
                lw=1.5,
                label="lower")
        ax.set_title(f"{ticker} donchian")
        ax.set_xlim(df_stock.index[0], df_stock.index[-1])
        ax.set_xlabel("Time")
        ax.set_ylabel("Price ($)")

        ax.legend(
            [ticker, df_ta.columns[0], df_ta.columns[1], df_ta.columns[2]])
        ax.fill_between(
            df_ta.index,
            df_ta.iloc[:, 0].values,
            df_ta.iloc[:, 2].values,
            alpha=0.1,
            color="b",
        )
        ax.grid(b=True, which="major", color="#666666", linestyle="-")

        plt.gcf().autofmt_xdate()
        fig.tight_layout(pad=1)

        plt.legend()

        plt.savefig("ta_donchian.png")
        uploaded_image = gst_imgur.upload_image("ta_donchian.png",
                                                title="something")
        image_link = uploaded_image.link
        if cfg.DEBUG:
            logger.debug("Image URL: %s", image_link)
        title = "Stocks: Donchian-Channels " + 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_donchian.png")

        await ctx.send(embed=embed)

    except Exception as e:
        embed = discord.Embed(
            title="ERROR Stocks: Donchian-Channels",
            colour=cfg.COLOR,
            description=e,
        )
        embed.set_author(
            name=cfg.AUTHOR_NAME,
            icon_url=cfg.AUTHOR_ICON_URL,
        )

        await ctx.send(embed=embed)
Beispiel #22
0
async def cg_command(ctx, ticker="", length="14", start="", end=""):
    """Displays chart with centre of gravity [Yahoo Finance]"""

    try:

        # Debug
        if cfg.DEBUG:
            logger.debug(
                "!stocks.ta.cg %s %s %s %s",
                ticker,
                length,
                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 length.lstrip("-").isnumeric():
            raise Exception("Number has to be an integer")
        length = float(length)

        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_close = df_stock["Adj Close"]
        df_close.columns = ["values"]
        df_ta = momentum_model.cg(df_close, length)

        # Output Data
        fig, axes = plt.subplots(2, 1, figsize=plot_autoscale(), dpi=PLOT_DPI)
        ax = axes[0]
        ax.set_title(f"{ticker} Centre of Gravity")
        ax.plot(df_stock.index, df_stock["Adj Close"].values, "k", lw=1)
        ax.set_xlim(df_stock.index[0], df_stock.index[-1])
        ax.set_ylabel("Share Price ($)")
        ax.grid(b=True, which="major", color="#666666", linestyle="-")

        ax2 = axes[1]
        ax2.plot(df_ta.index, df_ta.values, "b", lw=2, label="CG")
        # shift cg 1 bar forward for signal
        signal = df_ta.values
        signal = np.roll(signal, 1)
        ax2.plot(df_ta.index, signal, "g", lw=1, label="Signal")
        ax2.set_xlim(df_stock.index[0], df_stock.index[-1])
        ax2.grid(b=True, which="major", color="#666666", linestyle="-")

        plt.gcf().autofmt_xdate()
        fig.tight_layout(pad=1)
        plt.legend()

        plt.savefig("ta_cg.png")
        uploaded_image = gst_imgur.upload_image("ta_cg.png", title="something")
        image_link = uploaded_image.link
        if cfg.DEBUG:
            logger.debug("Image URL: %s", image_link)
        title = "Stocks: Center-of-Gravity " + 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_cg.png")

        await ctx.send(embed=embed)

    except Exception as e:
        embed = discord.Embed(
            title="ERROR Stocks: Center-of-Gravity",
            colour=cfg.COLOR,
            description=e,
        )
        embed.set_author(
            name=cfg.AUTHOR_NAME,
            icon_url=cfg.AUTHOR_ICON_URL,
        )

        await ctx.send(embed=embed)
Beispiel #23
0
async def ad_command(ctx, ticker="", is_open="False", start="", end=""):
    """Displays chart with accumulation/distribution line [Yahoo Finance]"""

    try:

        # Debug
        if cfg.DEBUG:
            logger.debug("!stocks.ta.ad %s %s %s %s", ticker, is_open, 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 is_open in ["false", "False", "FALSE", ""]:
            is_open = False

        if is_open in ["true", "True", "TRUE"]:
            is_open = True

        if is_open not in [True, False]:
            raise Exception("is_open argument has to be true or false")

        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)]

        bar_colors = [
            "r" if x[1].Open < x[1].Close else "g" for x in df_stock.iterrows()
        ]

        divisor = 1_000_000
        df_vol = df_stock["Volume"].dropna()
        df_vol = df_vol.values / divisor
        df_ta = volume_model.ad(df_stock, is_open)
        df_cal = df_ta.values
        df_cal = df_cal / divisor

        fig, axes = plt.subplots(
            3,
            1,
            gridspec_kw={"height_ratios": [2, 1, 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"{ticker} AD")
        ax.set_xlim(df_stock.index[0], df_stock.index[-1])
        ax.set_ylabel("Price")
        ax.grid(b=True, which="major", color="#666666", linestyle="-")

        ax2 = axes[1]
        ax2.set_ylabel("Volume [M]")
        ax2.bar(
            df_stock.index,
            df_vol,
            color=bar_colors,
            alpha=0.8,
            width=0.3,
        )
        ax2.set_xlim(df_stock.index[0], df_stock.index[-1])

        ax3 = axes[2]
        ax3.set_ylabel("A/D [M]")
        ax3.set_xlabel("Time")
        ax3.plot(df_ta.index, df_cal, "b", lw=1)
        ax3.set_xlim(df_stock.index[0], df_stock.index[-1])
        ax3.axhline(0, linewidth=2, color="k", ls="--")
        ax3.grid(b=True, which="major", color="#666666", linestyle="-")

        plt.gcf().autofmt_xdate()
        fig.tight_layout(pad=1)

        plt.savefig("ta_ad.png")
        uploaded_image = gst_imgur.upload_image("ta_ad.png", title="something")
        image_link = uploaded_image.link
        if cfg.DEBUG:
            logger.debug("Image URL: %s", image_link)
        title = "Stocks: Accumulation/Distribution Line " + 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_ad.png")

        await ctx.send(embed=embed)

    except Exception as e:
        embed = discord.Embed(
            title="ERROR Stocks: Accumulation/Distribution Line",
            colour=cfg.COLOR,
            description=e,
        )
        embed.set_author(
            name=cfg.AUTHOR_NAME,
            icon_url=cfg.AUTHOR_ICON_URL,
        )

        await ctx.send(embed=embed)
Beispiel #24
0
async def histcont_command(ctx, ticker=""):
    """Displays historical quarterly-contracts [quiverquant.com]"""
    try:
        # Debug user input
        if cfg.DEBUG:
            logger.debug("!stocks.gov.histcont %s", ticker)

        if ticker == "":
            raise Exception("A ticker is required")

        # Retrieve Data
        df_contracts = quiverquant_model.get_government_trading(
            "quarter-contracts", ticker=ticker)

        if df_contracts.empty:
            logger.debug("No quarterly government contracts found")
            return

        # Output Data
        amounts = df_contracts.sort_values(by=["Year", "Qtr"])["Amount"].values

        qtr = df_contracts.sort_values(by=["Year", "Qtr"])["Qtr"].values
        year = df_contracts.sort_values(by=["Year", "Qtr"])["Year"].values

        quarter_ticks = [
            f"{quarter[0]}" if quarter[1] == 1 else ""
            for quarter in zip(year, qtr)
        ]
        fig, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI)

        ax.plot(np.arange(0, len(amounts)), amounts / 1000, "-*", lw=2, ms=15)

        ax.set_xlim([-0.5, len(amounts) - 0.5])
        ax.set_xticks(np.arange(0, len(amounts)))
        ax.set_xticklabels(quarter_ticks)
        ax.grid()
        ax.set_title(
            f"Historical Quarterly Government Contracts for {ticker.upper()}")
        ax.set_xlabel("Date")
        ax.set_ylabel("Amount ($1k)")
        fig.tight_layout()

        plt.savefig("gov_histcont.png")
        uploaded_image = gst_imgur.upload_image("gov_histcont.png",
                                                title="something")
        image_link = uploaded_image.link
        if cfg.DEBUG:
            logger.debug("Image URL: %s", image_link)
        title = "Stocks: Historical Quarterly Government Contract " + 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("gov_histcont.png")

        await ctx.send(embed=embed)

    except Exception as e:
        embed = discord.Embed(
            title="ERROR Stocks: Historical Quarterly Government Contract",
            colour=cfg.COLOR,
            description=e,
        )
        embed.set_author(
            name=cfg.AUTHOR_NAME,
            icon_url=cfg.AUTHOR_ICON_URL,
        )

        await ctx.send(embed=embed)
Beispiel #25
0
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)
Beispiel #26
0
async def spos_command(ctx, ticker=""):
    """Net short vs position [Stockgrid]"""

    try:
        # Debug user input
        if cfg.DEBUG:
            logger.debug("!stocks.dps.spos %s", ticker)

        # Check for argument
        if ticker == "":
            raise Exception("Stock ticker is required")

        ticker = ticker.upper()

        stock = yf.download(ticker, progress=False)
        if stock.empty:
            raise Exception("Stock ticker is invalid")

        # Retrieve data
        df = stockgrid_model.get_net_short_position(ticker)

        # Debug user output
        if cfg.DEBUG:
            logger.debug(df.to_string())

        # Output data
        title = f"Stocks: [Stockgrid] Net Short vs Position {ticker}"
        embed = discord.Embed(title=title, colour=cfg.COLOR)
        embed.set_author(
            name=cfg.AUTHOR_NAME,
            icon_url=cfg.AUTHOR_ICON_URL,
        )

        fig = plt.figure(dpi=PLOT_DPI)

        ax = fig.add_subplot(111)
        ax.bar(
            df["dates"],
            df["dollar_net_volume"] / 1_000,
            color="r",
            alpha=0.4,
            label="Net Short Vol. (1k $)",
        )
        ax.set_ylabel("Net Short Vol. (1k $)")

        ax2 = ax.twinx()
        ax2.plot(
            df["dates"].values,
            df["dollar_dp_position"],
            c="tab:blue",
            label="Position (1M $)",
        )
        ax2.set_ylabel("Position (1M $)")

        lines, labels = ax.get_legend_handles_labels()
        lines2, labels2 = ax2.get_legend_handles_labels()
        ax2.legend(lines + lines2, labels + labels2, loc="upper left")

        ax.grid()
        plt.title(f"Net Short Vol. vs Position for {ticker}")
        plt.gcf().autofmt_xdate()
        file_name = ticker + "_spos.png"
        plt.savefig(file_name)
        plt.close("all")
        uploaded_image = gst_imgur.upload_image(file_name, title="something")
        image_link = uploaded_image.link
        embed.set_image(url=image_link)
        os.remove(file_name)

        await ctx.send(embed=embed)

    except Exception as e:
        embed = discord.Embed(
            title=f"ERROR Stocks: [Stockgrid] Net Short vs Position {ticker}",
            colour=cfg.COLOR,
            description=e,
        )
        embed.set_author(
            name=cfg.AUTHOR_NAME,
            icon_url=cfg.AUTHOR_ICON_URL,
        )

        await ctx.send(embed=embed)
Beispiel #27
0
async def adosc_command(
    ctx, ticker="", is_open="False", fast="3", slow="10", start="", end=""
):
    """Displays chart with chaikin oscillator [Yahoo Finance]"""

    try:
        # Debug
        if cfg.DEBUG:
            # pylint: disable=logging-too-many-args
            logger.debug(
                "!stocks.ta.adosc %s %s %s %s %s",
                ticker,
                is_open,
                fast,
                slow,
                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.lstrip("-").isnumeric():
            raise Exception("Number has to be an integer")
        fast = float(fast)
        if not slow.lstrip("-").isnumeric():
            raise Exception("Number has to be an integer")
        slow = float(slow)

        if is_open in ["false", "False", "FALSE", ""]:
            is_open = False

        if is_open in ["true", "True", "TRUE"]:
            is_open = True

        if is_open not in [True, False]:
            raise Exception("raw argument has to be true or false")

        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)]

        # Output Data
        bar_colors = [
            "r" if x[1].Open < x[1].Close else "g" for x in df_stock.iterrows()
        ]

        divisor = 1_000_000
        df_vol = df_stock["Volume"].dropna()
        df_vol = df_vol.values / divisor
        df_ta = volume_model.adosc(df_stock, is_open, fast, slow)
        df_cal = df_ta.values
        df_cal = df_cal / divisor

        fig, axes = plt.subplots(
            3,
            1,
            figsize=plot_autoscale(),
            dpi=PLOT_DPI,
        )
        ax = axes[0]
        ax.set_title(f"{ticker} AD Oscillator")
        ax.plot(df_stock.index, df_stock["Adj Close"].values, "fuchsia", lw=1)
        ax.set_xlim(df_stock.index[0], df_stock.index[-1])
        ax.set_ylabel("Price")
        ax.grid(b=True, which="major", color="#666666", linestyle="-")

        ax1 = axes[1]
        ax1.set_ylabel("Volume [M]")

        ax1.bar(
            df_stock.index,
            df_vol,
            color=bar_colors,
            alpha=0.8,
            width=0.3,
        )
        ax1.set_xlim(df_stock.index[0], df_stock.index[-1])

        ax2 = axes[2]
        ax2.set_ylabel("AD Osc [M]")
        ax2.set_xlabel("Time")
        ax2.plot(df_ta.index, df_cal, "b", lw=2, label="AD Osc")
        ax2.set_xlim(df_stock.index[0], df_stock.index[-1])
        ax2.grid(b=True, which="major", color="#666666", linestyle="-")

        plt.gcf().autofmt_xdate()
        fig.tight_layout(pad=1)
        plt.legend()

        plt.savefig("ta_adosc.png")
        uploaded_image = gst_imgur.upload_image("ta_adosc.png", title="something")
        image_link = uploaded_image.link
        if cfg.DEBUG:
            logger.debug("Image URL: %s", image_link)
        title = "Stocks: Accumulation/Distribution Oscillator " + 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_adosc.png")

        await ctx.send(embed=embed)

    except Exception as e:
        embed = discord.Embed(
            title="ERROR Stocks: Accumulation/Distribution Oscillator",
            colour=cfg.COLOR,
            description=e,
        )
        embed.set_author(
            name=cfg.AUTHOR_NAME,
            icon_url=cfg.AUTHOR_ICON_URL,
        )

        await ctx.send(embed=embed)
Beispiel #28
0
async def rsi_command(ctx,
                      ticker="",
                      length="14",
                      scalar="100",
                      drift="1",
                      start="",
                      end=""):
    """Displays chart with relative strength index [Yahoo Finance]"""

    try:

        # Debug
        if cfg.DEBUG:
            print(
                f"!stocks.ta.rsi {ticker} {length} {scalar} {drift} {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 length.lstrip("-").isnumeric():
            raise Exception("Number has to be an integer")
        length = float(length)
        if not scalar.lstrip("-").isnumeric():
            raise Exception("Number has to be an integer")
        scalar = float(scalar)
        if not drift.lstrip("-").isnumeric():
            raise Exception("Number has to be an integer")
        drift = float(drift)

        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.rsi("1440min", df_stock, length, scalar, drift)

        # 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" {ticker} RSI{length} ")
        ax.set_xlim(df_stock.index[0], df_stock.index[-1])
        ax.set_ylabel("Share Price ($)")
        ax.grid(b=True, which="major", color="#666666", linestyle="-")

        ax2 = axes[1]
        ax2.plot(df_ta.index, df_ta.values, "b", lw=2)
        ax2.set_xlim(df_stock.index[0], df_stock.index[-1])
        ax2.axhspan(70, 100, facecolor="r", alpha=0.2)
        ax2.axhspan(0, 30, facecolor="g", alpha=0.2)
        ax2.axhline(70, linewidth=3, color="r", ls="--")
        ax2.axhline(30, 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([30, 70])
        ax3.set_yticklabels(["OVERSOLD", "OVERBOUGHT"])

        plt.gcf().autofmt_xdate()
        fig.tight_layout(pad=1)

        plt.savefig("ta_rsi.png")
        uploaded_image = gst_imgur.upload_image("ta_rsi.png",
                                                title="something")
        image_link = uploaded_image.link
        if cfg.DEBUG:
            print(f"Image URL: {image_link}")
        title = "Stocks: 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_rsi.png")

        await ctx.send(embed=embed)

    except Exception as e:
        embed = discord.Embed(
            title="ERROR Stocks: 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)
Beispiel #29
0
async def fib_command(ctx, ticker="", start="", end=""):
    """Displays chart with fibonacci retracement [Yahoo Finance]"""

    try:

        # Debug
        if cfg.DEBUG:
            print(f"!stocks.ta.fib {ticker} {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)

        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)]

        start = start.strftime("%Y-%m-%d")
        end = end.strftime("%Y-%m-%d")
        (
            df_fib,
            min_date,
            max_date,
            min_pr,
            max_pr,
        ) = custom_indicators_model.calculate_fib_levels(df_stock, 120, start, end)

        levels = df_fib.Price
        fig, ax = plt.subplots(figsize=(plot_autoscale()), dpi=cfp.PLOT_DPI)

        ax.plot(df_stock["Adj Close"], "b")
        ax.plot([min_date, max_date], [min_pr, max_pr], c="k")

        for i in levels:
            ax.axhline(y=i, c="g", alpha=0.5)

        for i in range(5):
            ax.fill_between(df_stock.index, levels[i], levels[i + 1], alpha=0.6)

        ax.set_ylabel("Price")
        ax.set_title(f"Fibonacci Support for {ticker.upper()}")
        ax.set_xlim(df_stock.index[0], df_stock.index[-1])

        ax1 = ax.twinx()
        ax1.set_ylim(ax.get_ylim())
        ax1.set_yticks(levels)
        ax1.set_yticklabels([0, 0.235, 0.382, 0.5, 0.618, 1])

        plt.gcf().autofmt_xdate()
        fig.tight_layout(pad=1)

        plt.savefig("ta_fib.png")
        uploaded_image = gst_imgur.upload_image("ta_fib.png", title="something")
        image_link = uploaded_image.link
        if cfg.DEBUG:
            print(f"Image URL: {image_link}")
        title = "Stocks: Fibonacci-Retracement-Levels " + ticker
        str_df_fib = "```" + df_fib.to_string(index=False) + "```"
        embed = discord.Embed(title=title, colour=cfg.COLOR, description=str_df_fib)
        embed.set_author(
            name=cfg.AUTHOR_NAME,
            icon_url=cfg.AUTHOR_ICON_URL,
        )
        embed.set_image(url=image_link)
        os.remove("ta_fib.png")

        await ctx.send(embed=embed)

    except Exception as e:
        embed = discord.Embed(
            title="ERROR Stocks: Fibonacci-Retracement-Levels",
            colour=cfg.COLOR,
            description=e,
        )
        embed.set_author(
            name=cfg.AUTHOR_NAME,
            icon_url=cfg.AUTHOR_ICON_URL,
        )

        await ctx.send(embed=embed)
Beispiel #30
0
async def dpotc_command(ctx, ticker=""):
    """Dark pools (ATS) vs OTC data [FINRA]"""

    try:
        # Debug user input
        if cfg.DEBUG:
            print(f"\n!stocks.dps.dpotc {ticker}")

        # Check for argument
        if ticker == "":
            raise Exception("Stock ticker is required")

        ticker = ticker.upper()

        stock = yf.download(ticker, progress=False)
        if stock.empty:
            raise Exception("Stock ticker is invalid")

        # Retrieve data
        ats, otc = finra_model.getTickerFINRAdata(ticker)

        # Debug user output
        if cfg.DEBUG:
            print(ats.to_string())
            print(otc.to_string())

        # Output data
        title = f"Stocks: [FINRA] Dark Pools (ATS) vs OTC {ticker}"
        embed = discord.Embed(title=title, colour=cfg.COLOR)
        embed.set_author(
            name=cfg.AUTHOR_NAME,
            icon_url=cfg.AUTHOR_ICON_URL,
        )

        if ats.empty and otc.empty:
            embed = embed.set_description("No data found.")  # pylint: disable=no-member
        _, _ = plt.subplots(dpi=PLOT_DPI)

        plt.subplot(3, 1, (1, 2))
        if not ats.empty and not otc.empty:
            plt.bar(
                ats.index,
                (ats["totalWeeklyShareQuantity"] + otc["totalWeeklyShareQuantity"])
                / 1_000_000,
                color="tab:orange",
            )
            plt.bar(
                otc.index,
                otc["totalWeeklyShareQuantity"] / 1_000_000,
                color="tab:blue",
            )
            plt.legend(["ATS", "OTC"])

        elif not ats.empty:
            plt.bar(
                ats.index,
                ats["totalWeeklyShareQuantity"] / 1_000_000,
                color="tab:orange",
            )
            plt.legend(["ATS"])

        elif not otc.empty:
            plt.bar(
                otc.index,
                otc["totalWeeklyShareQuantity"] / 1_000_000,
                color="tab:blue",
            )
            plt.legend(["OTC"])

        plt.ylabel("Total Weekly Shares [Million]")
        plt.grid(b=True, which="major", color="#666666", linestyle="-", alpha=0.2)
        plt.title(f"Dark Pools (ATS) vs OTC (Non-ATS) Data for {ticker}")

        plt.subplot(313)
        if not ats.empty:
            plt.plot(
                ats.index,
                ats["totalWeeklyShareQuantity"] / ats["totalWeeklyTradeCount"],
                color="tab:orange",
            )
            plt.legend(["ATS"])

            if not otc.empty:
                plt.plot(
                    otc.index,
                    otc["totalWeeklyShareQuantity"] / otc["totalWeeklyTradeCount"],
                    color="tab:blue",
                )
                plt.legend(["ATS", "OTC"])

        else:
            plt.plot(
                otc.index,
                otc["totalWeeklyShareQuantity"] / otc["totalWeeklyTradeCount"],
                color="tab:blue",
            )
            plt.legend(["OTC"])

        plt.ylabel("Shares per Trade")
        plt.grid(b=True, which="major", color="#666666", linestyle="-", alpha=0.2)
        plt.gcf().autofmt_xdate()
        plt.gca().xaxis.set_major_formatter(mdates.DateFormatter("%m/%d"))
        plt.gca().xaxis.set_major_locator(mdates.DayLocator(interval=4))
        plt.xlabel("Weeks")
        file_name = ticker + "_dpotc.png"
        plt.savefig(file_name)
        plt.close("all")
        uploaded_image = gst_imgur.upload_image(file_name, title="something")
        image_link = uploaded_image.link
        embed.set_image(url=image_link)
        os.remove(file_name)

        await ctx.send(embed=embed)

    except Exception as e:
        embed = discord.Embed(
            title=f"ERROR Stocks: [FINRA] Dark Pools (ATS) vs OTC {ticker}",
            colour=cfg.COLOR,
            description=e,
        )
        embed.set_author(
            name=cfg.AUTHOR_NAME,
            icon_url=cfg.AUTHOR_ICON_URL,
        )

        await ctx.send(embed=embed)