def toplobbying_command(num: int = 10, raw: bool = False):
    """Displays top lobbying firms [quiverquant.com]"""
    # Debug user input
    if cfg.DEBUG:
        logger.debug("gov-toplobbying %s %s", num, raw)

    # 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")
    imagefile = "ta_toplobbying.png"

    imagefile = image_border(imagefile)
    return {
        "title": "Stocks: [quiverquant.com] Top Lobbying Firms",
        "imagefile": imagefile,
    }
示例#2
0
def view_command(ticker=""):
    """Displays image from Finviz [Finviz]"""

    # Debug
    if cfg.DEBUG:
        logger.debug("ta view %s", 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)
    im = im.resize((800, 340), Image.ANTIALIAS)
    imagefile = "ta_view.png"

    im.save(dataBytesIO, "PNG", quality=100)
    dataBytesIO.seek(0)
    imagefile = image_border(imagefile, base64=dataBytesIO)
    im.close()

    return {
        "title": f"Stocks: [Finviz] Trendlines & Data {ticker.upper()}",
        "imagefile": imagefile,
    }
示例#3
0
def histcont_command(ticker=""):
    """Displays historical quarterly-contracts [quiverquant.com]"""
    # Debug user input
    if cfg.DEBUG:
        logger.debug("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")
        raise Exception("No quarterly government contracts found")

    # 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")
    imagefile = "gov_histcont.png"

    imagefile = image_border(imagefile)
    return {
        "title": "Stocks: Historical Quarterly Government Contract ",
        "imagefile": imagefile,
    }
示例#4
0
def contracts_command(
    ticker: str = "", past_transaction_days: Union[int, str] = 10, raw: bool = False
):
    """Displays contracts associated with tickers [quiverquant.com]"""
    past_transaction_days = int(past_transaction_days)
    # Debug user input
    if cfg.DEBUG:
        logger.debug("gov-contracts %s %s %s", ticker, past_transaction_days, raw)

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

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

    if df_contracts.empty:
        return {
            "title": f"Stocks: [quiverquant.com] Contracts by {ticker}",
            "description": f"{ticker} does not have any contracts",
        }

    # 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")
    imagefile = "gov_contracts.png"

    imagefile = image_border(imagefile)
    return {
        "title": f"Stocks: [quiverquant.com] Contracts by {ticker}",
        "imagefile": imagefile,
    }
示例#5
0
def feargreed_command(indicator=""):
    """CNN Fear and Greed Index [CNN]"""

    # Debug user input
    if cfg.DEBUG:
        logger.debug("econ-futures")

    # 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)}"  # nosec
        )
    # Output data

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

    report, im = cnn_model.get_feargreed_report(indicator, fig)
    ax.axes.xaxis.set_visible(False)
    ax.axes.yaxis.set_visible(False)

    if indicator:
        ax.imshow(im)

    imagefile = "feargreed.png"
    dataBytesIO = io.BytesIO()

    plt.savefig(dataBytesIO)
    plt.close("all")

    dataBytesIO.seek(0)
    imagefile = image_border(imagefile, base64=dataBytesIO)

    return {
        "title": "Economy: [CNN] Fear Geed Index",
        "imagefile": imagefile,
        "description": report,
    }
示例#6
0
def donchian_command(ticker="",
                     upper_length="25",
                     lower_length="100",
                     start="",
                     end=""):
    """Displays chart with donchian channel [Yahoo Finance]"""

    # Debug
    if cfg.DEBUG:
        logger.debug(
            "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 = 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)
    df_ta = df_ta.fillna(0.0)

    # Output Data
    fig, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI)
    ax.plot(df_stock.index, df_stock["Adj Close"].values, lw=3)
    ax.plot(df_ta.index, df_ta.iloc[:, 0].values, lw=1.5, label="upper")
    ax.plot(df_ta.index, df_ta.iloc[:, 1].values, lw=1.5, ls="--")
    ax.plot(df_ta.index, df_ta.iloc[:, 2].values, 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,
    )
    ax.grid(b=True, which="major", color="#666666", linestyle="-")

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

    plt.legend()
    imagefile = "ta_donchian.png"

    dataBytesIO = io.BytesIO()
    plt.savefig(dataBytesIO)
    plt.close("all")

    dataBytesIO.seek(0)
    imagefile = image_border(imagefile, base64=dataBytesIO)

    return {
        "title": f"Stocks: Donchian-Channels {ticker}",
        "imagefile": imagefile,
    }
示例#7
0
def cg_command(ticker="", length="14", start="", end=""):
    """Displays chart with centre of gravity [Yahoo Finance]"""

    # Debug
    if cfg.DEBUG:
        logger.debug(
            "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 = bots.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()
    imagefile = "ta_cg.png"
    plt.savefig(imagefile)

    imagefile = image_border(imagefile)

    return {
        "title": f"Stocks: Center-of-Gravity {ticker}",
        "imagefile": imagefile,
    }
示例#8
0
def historical_command(signal: str = "", start=""):
    """Displays historical price comparison between similar companies [Yahoo Finance]"""

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

    # Check for argument
    if signal not in so.d_signals_desc:
        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."
                )

                return {
                    "title":
                    "ERROR Stocks: [Yahoo Finance] Historical Screener",
                    "description": error,
                }

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

    imagefile = "scr_historical.png"
    plt.savefig(imagefile)
    imagefile = image_border(imagefile)

    return {
        "title": "Stocks: [Yahoo Finance] Historical Screener",
        "description": description,
        "imagefile": imagefile,
    }
示例#9
0
def spos_command(ticker: str = ""):
    """Net short vs position [Stockgrid]"""

    # Debug user input
    if cfg.DEBUG:
        logger.debug("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}"

    fig = make_subplots(shared_xaxes=True, specs=[[{"secondary_y": True}]])

    fig.add_trace(
        go.Scatter(
            name="Position ($)",
            x=df["dates"].values,
            y=df["dollar_dp_position"] * 1_000,
            line=dict(color="#fdc708", width=2),
            opacity=1,
            showlegend=False,
        ),
        secondary_y=True,
    )
    fig.add_trace(
        go.Bar(
            name="Net Short Vol. ($)",
            x=df["dates"],
            y=df["dollar_net_volume"],
            opacity=1,
            showlegend=False,
        ),
        secondary_y=False,
    )
    # Set y-axes titles
    fig.update_xaxes(dtick="M1", tickformat="%b %d\n%Y")
    fig.update_yaxes(title_text="<b>Position</b> ($)", secondary_y=True)
    fig.update_traces(hovertemplate="%{y:.2s}")
    fig.update_layout(
        margin=dict(l=0, r=10, t=40, b=20),
        template=cfg.PLT_TA_STYLE_TEMPLATE,
        colorway=cfg.PLT_TA_COLORWAY,
        title=f"Net Short Vol. vs Position for {ticker}",
        title_x=0.5,
        yaxis_title="<b>Net Short Vol.</b> ($)",
        yaxis=dict(
            side="left",
            showgrid=False,
            fixedrange=False,
            layer="above traces",
            titlefont=dict(color="#d81aea"),
            tickfont=dict(color="#d81aea"),
            nticks=10,
        ),
        xaxis=dict(
            rangeslider=dict(visible=False),
            type="date",
            fixedrange=False,
        ),
        xaxis2=dict(
            rangeslider=dict(visible=False),
            type="date",
            fixedrange=False,
        ),
        dragmode="pan",
        legend=dict(orientation="h",
                    yanchor="bottom",
                    y=1.02,
                    xanchor="right",
                    x=1),
        yaxis2=dict(
            side="right",
            position=0.15,
            fixedrange=False,
            titlefont=dict(color="#fdc708"),
            tickfont=dict(color="#fdc708"),
            nticks=10,
        ),
        hovermode="x unified",
    )
    config = dict({"scrollZoom": True})
    imagefile = "dps_spos.png"

    # Check if interactive settings are enabled
    plt_link = ""
    if cfg.INTERACTIVE:
        html_ran = helpers.uuid_get()
        fig.write_html(f"in/spos_{html_ran}.html", config=config)
        plt_link = f"[Interactive]({cfg.INTERACTIVE_URL}/spos_{html_ran}.html)"

    fig.update_layout(
        width=800,
        height=500,
    )

    imagefile = helpers.image_border(imagefile, fig=fig)

    return {
        "title": title,
        "description": plt_link,
        "imagefile": imagefile,
    }
示例#10
0
def vol_command(
    ticker: str = None,
    expiry: str = "",
    min_sp: float = None,
    max_sp: float = None,
):
    """Options VOL"""

    # Debug
    if cfg.DEBUG:
        logger.debug("opt-vol %s %s %s %s", ticker, expiry, min_sp, max_sp)

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

    dates = yfinance_model.option_expirations(ticker)

    if not dates:
        raise Exception("Stock ticker is invalid")

    options = yfinance_model.get_option_chain(ticker, expiry)
    current_price = yfinance_model.get_price(ticker)

    if min_sp is None:
        min_strike = 0.75 * current_price
    else:
        min_strike = min_sp

    if max_sp is None:
        max_strike = 1.25 * current_price
    else:
        max_strike = max_sp

    calls = options.calls
    puts = options.puts
    call_v = calls.set_index("strike")["volume"] / 1000
    put_v = puts.set_index("strike")["volume"] / 1000

    df_opt = pd.merge(put_v, call_v, left_index=True, right_index=True)
    dmax = df_opt.values.max()

    fig = go.Figure()
    fig.add_trace(
        go.Scatter(
            x=call_v.index,
            y=call_v.values,
            name="Calls",
            mode="lines+markers",
            line=dict(color="green", width=3),
        ))
    fig.add_trace(
        go.Scatter(
            x=put_v.index,
            y=put_v.values,
            name="Puts",
            mode="lines+markers",
            line=dict(color="red", width=3),
        ))
    fig.add_trace(
        go.Scatter(
            x=[current_price, current_price],
            y=[0, dmax],
            mode="lines",
            line=dict(color="gold", width=2),
            name="Current Price",
        ))
    fig.update_xaxes(
        range=[min_strike, max_strike],
        constrain="domain",
    )
    fig.update_layout(
        margin=dict(l=0, r=0, t=60, b=20),
        template=cfg.PLT_SCAT_STYLE_TEMPLATE,
        title=f"Volume for {ticker.upper()} expiring {expiry}",
        title_x=0.5,
        legend_title="",
        xaxis_title="Strike",
        yaxis_title="Volume (1k)",
        xaxis=dict(rangeslider=dict(visible=False), ),
        legend=dict(yanchor="top", y=0.99, xanchor="left", x=0.01),
        dragmode="pan",
    )
    config = dict({"scrollZoom": True})
    imagefile = "opt_vol.png"

    # Check if interactive settings are enabled
    plt_link = ""
    if cfg.INTERACTIVE:
        html_ran = helpers.uuid_get()
        fig.write_html(f"in/vol_{html_ran}.html", config=config)
        plt_link = f"[Interactive]({cfg.INTERACTIVE_URL}/vol_{html_ran}.html)"

    fig.update_layout(
        width=800,
        height=500,
    )

    imagefile = helpers.image_border(imagefile, fig=fig)

    return {
        "title": f"Volume for {ticker.upper()} expiring {expiry}",
        "description": plt_link,
        "imagefile": imagefile,
    }
示例#11
0
def obv_command(ticker="", start="", end=""):
    """Displays chart with on balance volume [Yahoo Finance]"""

    # Debug
    if cfg.DEBUG:
        logger.debug(
            "ta-obv %s %s %s",
            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 = 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
    divisor = 1_000_000
    df_vol = df_stock["Volume"].dropna()
    df_vol = df_vol.values / divisor
    df_ta = volume_model.obv(df_stock)
    df_cal = df_ta.values
    df_cal = df_cal / divisor

    fig = make_subplots(
        rows=3,
        cols=1,
        shared_xaxes=True,
        vertical_spacing=0.06,
        row_width=[0.2, 0.2, 0.2],
    )
    fig.add_trace(
        go.Scatter(
            name=ticker,
            x=df_stock.index,
            y=df_stock["Adj Close"].values,
            line=dict(color="#fdc708", width=2),
            opacity=1,
        ),
        row=1,
        col=1,
    )
    colors = [
        "green" if row.Open < row["Adj Close"] else "red"
        for _, row in df_stock.iterrows()
    ]
    fig.add_trace(
        go.Bar(
            x=df_stock.index,
            y=df_vol,
            name="Volume [M]",
            marker_color=colors,
        ),
        row=2,
        col=1,
    )
    fig.add_trace(
        go.Scatter(
            name="OBC [M]",
            x=df_ta.index,
            y=df_ta.iloc[:, 0].values,
            line=dict(width=2),
            opacity=1,
        ),
        row=3,
        col=1,
    )
    fig.update_layout(
        margin=dict(l=10, r=0, t=40, b=20),
        template=cfg.PLT_TA_STYLE_TEMPLATE,
        colorway=cfg.PLT_TA_COLORWAY,
        title=f"{ticker} OBV",
        title_x=0.4,
        yaxis_title="Stock Price ($)",
        yaxis2_title="Volume [M]",
        yaxis3_title="OBV [M]",
        yaxis=dict(fixedrange=False, ),
        xaxis=dict(
            rangeslider=dict(visible=False),
            type="date",
        ),
        dragmode="pan",
        legend=dict(orientation="h",
                    yanchor="bottom",
                    y=1.02,
                    xanchor="right",
                    x=1),
    )
    config = dict({"scrollZoom": True})
    imagefile = "ta_obv.png"

    # Check if interactive settings are enabled
    plt_link = ""
    if cfg.INTERACTIVE:
        html_ran = helpers.uuid_get()
        fig.write_html(f"in/obv_{html_ran}.html", config=config)
        plt_link = f"[Interactive]({cfg.INTERACTIVE_URL}/obv_{html_ran}.html)"

    fig.update_layout(
        width=800,
        height=500,
    )
    imagefile = helpers.image_border(imagefile, fig=fig)

    return {
        "title": f"Stocks: On-Balance-Volume {ticker}",
        "description": plt_link,
        "imagefile": imagefile,
    }
示例#12
0
def gtrades_command(
    ticker: str = "",
    gov_type="",
    past_transactions_months: int = 10,
    raw: bool = False,
):
    """Displays government trades [quiverquant.com]"""
    # Debug user input
    if cfg.DEBUG:
        logger.debug(
            "gov-gtrades %s %s %s %s",
            ticker,
            gov_type,
            past_transactions_months,
            raw,
        )

    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:
        logger.debug("No recent %s trading data found", gov_type)
        raise Exception(f"No recent {gov_type} trading data found")

    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")
    imagefile = "gov_gtrades.png"

    imagefile = image_border(imagefile)
    return {
        "title": "Stocks: [quiverquant.com] Government Trades",
        "imagefile": imagefile,
    }
示例#13
0
def dpotc_command(ticker: str = ""):
    """Dark pools (ATS) vs OTC data [FINRA]"""

    # Debug user input
    if cfg.DEBUG:
        logger.debug("dps-dpotc %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
    ats, otc = finra_model.getTickerFINRAdata(ticker)

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

    # Output data
    title = f"Stocks: [FINRA] Dark Pools (ATS) vs OTC {ticker}"

    if ats.empty and otc.empty:
        raise Exception("Stock ticker is invalid")

    fig = make_subplots(
        rows=2,
        cols=1,
        shared_xaxes=True,
        vertical_spacing=0.07,
        row_width=[0.4, 0.6],
        specs=[[{
            "secondary_y": True
        }], [{
            "secondary_y": False
        }]],
    )

    if not ats.empty and not otc.empty:
        fig.add_trace(
            go.Bar(
                x=ats.index,
                y=(ats["totalWeeklyShareQuantity"] +
                   otc["totalWeeklyShareQuantity"]),
                name="ATS",
                opacity=0.8,
            ),
            row=1,
            col=1,
            secondary_y=False,
        )
        fig.add_trace(
            go.Bar(
                x=otc.index,
                y=otc["totalWeeklyShareQuantity"],
                name="OTC",
                opacity=0.8,
                yaxis="y2",
                offset=0.0001,
            ),
            row=1,
            col=1,
        )

    elif not ats.empty:
        fig.add_trace(
            go.Bar(
                x=ats.index,
                y=(ats["totalWeeklyShareQuantity"] +
                   otc["totalWeeklyShareQuantity"]),
                name="ATS",
                opacity=0.8,
            ),
            row=1,
            col=1,
            secondary_y=False,
        )

    elif not otc.empty:
        fig.add_trace(
            go.Bar(
                x=otc.index,
                y=otc["totalWeeklyShareQuantity"],
                name="OTC",
                opacity=0.8,
                yaxis="y2",
                secondary_y=False,
            ),
            row=1,
            col=1,
        )

    if not ats.empty:
        fig.add_trace(
            go.Scatter(
                name="ATS",
                x=ats.index,
                y=ats["totalWeeklyShareQuantity"] /
                ats["totalWeeklyTradeCount"],
                line=dict(color="#fdc708", width=2),
                opacity=1,
                showlegend=False,
                yaxis="y2",
            ),
            row=2,
            col=1,
        )

        if not otc.empty:
            fig.add_trace(
                go.Scatter(
                    name="OTC",
                    x=otc.index,
                    y=otc["totalWeeklyShareQuantity"] /
                    otc["totalWeeklyTradeCount"],
                    line=dict(color="#d81aea", width=2),
                    opacity=1,
                    showlegend=False,
                ),
                row=2,
                col=1,
            )
    else:
        fig.add_trace(
            go.Scatter(
                name="OTC",
                x=otc.index,
                y=otc["totalWeeklyShareQuantity"] /
                otc["totalWeeklyTradeCount"],
                line=dict(color="#d81aea", width=2),
                opacity=1,
                showlegend=False,
            ),
            row=2,
            col=1,
        )

    fig.update_xaxes(showspikes=True, spikesnap="cursor", spikemode="across")
    fig.update_yaxes(showspikes=True, spikethickness=2)
    fig.update_layout(
        margin=dict(l=20, r=0, t=10, b=20),
        template=cfg.PLT_CANDLE_STYLE_TEMPLATE,
        colorway=cfg.PLT_TA_COLORWAY,
        title=f"Dark Pools (ATS) vs OTC (Non-ATS) Data for {ticker}",
        title_x=0.5,
        yaxis3_title="Shares per Trade",
        yaxis_title="Total Weekly Shares",
        xaxis2_title="Weeks",
        yaxis=dict(
            fixedrange=False,
            side="left",
            nticks=20,
        ),
        yaxis2=dict(
            fixedrange=False,
            showgrid=False,
            overlaying="y",
            anchor="x",
            layer="above traces",
        ),
        yaxis3=dict(
            fixedrange=False,
            nticks=10,
        ),
        xaxis=dict(
            rangeslider=dict(visible=False),
            type="date",
            showspikes=True,
            nticks=20,
        ),
        legend=dict(orientation="h",
                    yanchor="bottom",
                    y=1.02,
                    xanchor="right",
                    x=1),
        barmode="group",
        bargap=0.5,
        bargroupgap=0,
        dragmode="pan",
        hovermode="x unified",
        spikedistance=1000,
        hoverdistance=100,
    )
    config = dict({"scrollZoom": True})
    imagefile = "dps_dpotc.png"

    # Check if interactive settings are enabled
    plt_link = ""
    if cfg.INTERACTIVE:
        html_ran = helpers.uuid_get()
        fig.write_html(f"in/dpotc_{html_ran}.html", config=config)
        plt_link = f"[Interactive]({cfg.INTERACTIVE_URL}/dpotc_{html_ran}.html)"

    fig.update_layout(
        width=800,
        height=500,
    )

    imagefile = helpers.image_border(imagefile, fig=fig)

    return {
        "title": title,
        "description": plt_link,
        "imagefile": imagefile,
    }
示例#14
0
def candle_command(
    ticker: str = "",
    interval: int = 15,
    past_days: int = 1,
    start="",
    end="",
):
    """Shows candle plot of loaded ticker. [Source: Yahoo Finance, IEX Cloud or Alpha Vantage]

    Parameters
    ----------
    ticker: str
        Ticker name
    interval: int
        chart mins or daily
    past_days: int
        Display the past * days. Default: 1(Not for Daily)
    start: str
        start date format YYYY-MM-DD
    end: str
        end date format YYYY-MM-DD
    """

    logger.info("candle %s %s %s %s", ticker, interval, start, end)

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

    futures = "=F" or "^"
    crypto = "-USD"
    if interval == 1440:
        df_stock_candidate = yf.download(
            ticker,
            start=start,
            end=end,
            progress=False,
        )

        # Check that loading a stock was not successful
        if df_stock_candidate.empty:
            raise Exception(f"No data found for {ticker.upper()}")

        df_stock_candidate.index.name = "date"
    else:
        s_int = str(interval) + "m"
        d_granularity = {
            "1m": past_days,
            "5m": past_days,
            "15m": past_days,
            "30m": past_days,
            "60m": past_days,
        }
        s_start_dt = datetime.utcnow() - timedelta(days=d_granularity[s_int])
        s_date_start = s_start_dt.strftime("%Y-%m-%d")

        df_stock_candidate = yf.download(
            ticker,
            start=s_date_start
            if s_start_dt > start else start.strftime("%Y-%m-%d"),
            progress=False,
            interval=s_int,
            prepost=True,
        )

    # Check that loading a stock was not successful
    if df_stock_candidate.empty:
        raise Exception(f"No data found for {ticker.upper()}.")

    df_stock_candidate.index = df_stock_candidate.index.tz_localize(None)
    df_stock_candidate.index.name = "date"
    df_stock = df_stock_candidate
    price_df = df_stock.loc[(df_stock.index >= start) & (df_stock.index < end)]

    df_vwap = overlap_model.vwap(price_df, 0)

    plt_title = [f"{ticker.upper()} Intraday {interval}min", "Volume"]
    title = f"Intraday {interval}min Chart for {ticker.upper()}"
    if interval == 1440:
        plt_title = [f"{ticker.upper()} Daily", "Volume"]
        title = f"Daily Chart for {ticker.upper()}"

    fig = make_subplots(
        shared_xaxes=True,
        vertical_spacing=0.09,
        subplot_titles=plt_title,
        specs=[[{
            "secondary_y": True
        }]],
    )
    fig.add_trace(
        go.Candlestick(
            x=df_stock.index,
            open=df_stock.Open,
            high=df_stock.High,
            low=df_stock.Low,
            close=df_stock.Close,
            name="OHLC",
            showlegend=False,
        ),
        secondary_y=True,
    )
    fig.add_trace(
        go.Bar(
            x=df_stock.index,
            y=df_stock.Volume,
            name="Volume",
            yaxis="y2",
            marker_color="#d81aea",
            opacity=0.4,
            showlegend=False,
        ),
        secondary_y=False,
    )
    if interval != 1440:
        fig.add_trace(
            go.Scatter(
                name="VWAP",
                x=df_stock.index,
                y=df_vwap["VWAP_D"],
                opacity=0.65,
                line=dict(color="#fdc708", width=2),
                showlegend=True,
            ),
            secondary_y=True,
        )
    fig.update_xaxes(showspikes=True, spikesnap="cursor", spikemode="across")
    fig.update_yaxes(showspikes=True, spikethickness=2)
    fig.update_layout(
        margin=dict(l=0, r=0, t=40, b=20),
        template=cfg.PLT_CANDLE_STYLE_TEMPLATE,
        yaxis2_title="Price ($)",
        yaxis_title="Volume",
        yaxis=dict(
            showgrid=False,
            fixedrange=False,
            side="left",
            titlefont=dict(color="#d81aea"),
            tickfont=dict(color="#d81aea"),
            nticks=20,
        ),
        yaxis2=dict(
            side="right",
            fixedrange=False,
            anchor="x",
            layer="above traces",
            overlaying="y",
            nticks=20,
        ),
        xaxis=dict(
            rangeslider=dict(visible=False),
            type="date",
            showspikes=True,
        ),
        legend=dict(orientation="h",
                    yanchor="bottom",
                    y=1.02,
                    xanchor="right",
                    x=1),
        dragmode="pan",
        hovermode="x unified",
        spikedistance=1000,
        hoverdistance=100,
    )
    if futures in ticker.upper():
        fig.update_xaxes(rangebreaks=[
            dict(bounds=["sat", "sun"]),
            dict(bounds=[17, 17.50], pattern="hour"),
        ], )
    elif crypto not in ticker.upper() and interval != 1440:
        fig.update_xaxes(rangebreaks=[
            dict(bounds=["sat", "mon"]),
            dict(bounds=[20, 9.50], pattern="hour"),
        ], )
    config = dict({"scrollZoom": True})
    imagefile = "candle.png"

    # Check if interactive settings are enabled
    plt_link = ""
    if cfg.INTERACTIVE:
        html_ran = helpers.uuid_get()
        fig.write_html(f"in/candle_{html_ran}.html", config=config)
        plt_link = f"[Interactive]({cfg.INTERACTIVE_URL}/candle_{html_ran}.html)"

    fig.update_layout(
        width=800,
        height=500,
    )
    imagefile = helpers.image_border(imagefile, fig=fig)

    return {
        "title": title,
        "description": plt_link,
        "imagefile": imagefile,
    }
示例#15
0
def psi_command(ticker: str = ""):
    """Price vs short interest volume [Stockgrid]"""

    # Debug user input
    if cfg.DEBUG:
        logger.debug("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
    fig = make_subplots(
        rows=2,
        cols=1,
        shared_xaxes=True,
        vertical_spacing=0.06,
        row_width=[0.3, 0.6],
        specs=[[{
            "secondary_y": True
        }], [{
            "secondary_y": False
        }]],
    )
    fig.add_trace(
        go.Scatter(
            name=ticker,
            x=df["date"].values,
            y=prices[len(prices) - len(df):],
            line=dict(color="#fdc708", width=2),
            opacity=1,
            showlegend=False,
        ),
        row=1,
        col=1,
        secondary_y=False,
    )
    fig.add_trace(
        go.Bar(
            x=df["date"],
            y=df["total_volume"] / 1_000_000,
            name="Total Volume",
            yaxis="y2",
        ),
        row=1,
        col=1,
        secondary_y=True,
    )
    fig.add_trace(
        go.Bar(
            x=df["date"],
            y=df["short_volume"] / 1_000_000,
            name="Short Volume",
            yaxis="y2",
        ),
        row=1,
        col=1,
        secondary_y=True,
    )
    fig.add_trace(
        go.Scatter(
            name="Short Vol. %",
            x=df["date"].values,
            y=100 * df["short_volume%"],
            line=dict(width=2),
            opacity=1,
            showlegend=False,
        ),
        row=2,
        col=1,
        secondary_y=False,
    )
    fig.update_traces(hovertemplate="%{y:.2f}")
    fig.update_xaxes(showspikes=True, spikesnap="cursor", spikemode="across")
    fig.update_yaxes(showspikes=True, spikethickness=2)
    fig.update_layout(
        margin=dict(l=10, r=0, t=40, b=20),
        template=cfg.PLT_TA_STYLE_TEMPLATE,
        colorway=cfg.PLT_TA_COLORWAY,
        title=f"Price vs Short Volume Interest for {ticker}",
        title_x=0.45,
        yaxis_title="Stock Price ($)",
        yaxis2_title="FINRA Volume [M]",
        yaxis3_title="Short Vol. %",
        yaxis=dict(
            side="right",
            fixedrange=False,
            titlefont=dict(color="#fdc708"),
            tickfont=dict(color="#fdc708"),
            nticks=20,
        ),
        yaxis2=dict(
            side="left",
            fixedrange=False,
            anchor="x",
            overlaying="y",
            titlefont=dict(color="#d81aea"),
            tickfont=dict(color="#d81aea"),
            nticks=20,
        ),
        yaxis3=dict(
            fixedrange=False,
            titlefont=dict(color="#9467bd"),
            tickfont=dict(color="#9467bd"),
            nticks=20,
        ),
        xaxis=dict(
            rangeslider=dict(visible=False),
            type="date",
        ),
        dragmode="pan",
        legend=dict(orientation="h",
                    yanchor="bottom",
                    y=1.02,
                    xanchor="right",
                    x=1),
        hovermode="x unified",
        spikedistance=1000,
        hoverdistance=100,
    )
    config = dict({"scrollZoom": True})
    imagefile = "dps_psi.png"

    # Check if interactive settings are enabled
    plt_link = ""
    if cfg.INTERACTIVE:
        html_ran = helpers.uuid_get()
        fig.write_html(f"in/psi_{html_ran}.html", config=config)
        plt_link = f"[Interactive]({cfg.INTERACTIVE_URL}/psi_{html_ran}.html)"

    fig.update_layout(
        width=800,
        height=500,
    )

    imagefile = helpers.image_border(imagefile, fig=fig)

    return {
        "title":
        f"Stocks: [Stockgrid] Price vs Short Interest Volume {ticker}",
        "description": plt_link,
        "imagefile": imagefile,
    }
示例#16
0
def qtrcontracts_command(num: int = 20, analysis=""):
    """Displays a look at government contracts [quiverquant.com]"""
    # Debug user input
    if cfg.DEBUG:
        logger.debug("gov-qtrcontracts %s %s", num, analysis)

    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")
        imagefile = "gov_qtrcontracts.png"

        imagefile = image_border(imagefile)
        output = {
            "title": "Stocks: [quiverquant.com] Government Contracts",
            "imagefile": imagefile,
            "description": description,
        }

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

        output = {
            "title": "Stocks: [quiverquant.com] Government Contracts",
            "description": tickers.to_string(),
        }

    return output
示例#17
0
def vsurf_command(
    ticker: str = "",
    z: str = "IV",
):
    """Display vol surface

    Parameters
    ----------
    ticker: Stock Ticker
    z : The variable for the Z axis
    """

    # Debug
    if cfg.DEBUG:
        logger.debug("opt-oi %s %s", ticker, z)

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

    data = yfinance_model.get_iv_surface(ticker)
    if data.empty:
        raise Exception(f"No options data found for {ticker}.\n")

    Y = data.dte
    X = data.strike
    if z == "IV":
        Z = data.impliedVolatility
        label = "Volatility"
    elif z == "OI":
        Z = data.openInterest
        label = "Open Interest"
    elif z == "LP":
        Z = data.lastPrice
        label = "Last Price"

    points3D = np.vstack((X, Y, Z)).T
    points2D = points3D[:, :2]
    tri = Delaunay(points2D)
    I, J, K = tri.simplices.T

    lighting_effects = dict(ambient=0.5,
                            diffuse=0.5,
                            roughness=0.5,
                            specular=0.4,
                            fresnel=0.4)
    fig = go.Figure(data=[
        go.Mesh3d(
            z=Z,
            x=X,
            y=Y,
            i=I,
            j=J,
            k=K,
            intensity=Z,
            colorscale=cfg.PLT_3DMESH_COLORSCALE,
            hovertemplate="<b>DTE</b>: %{y} <br><b>Strike</b>: %{x} <br><b>" +
            z + "</b>: %{z}<extra></extra>",
            showscale=False,
            flatshading=True,
            lighting=lighting_effects,
        )
    ])
    fig.update_layout(scene=dict(
        xaxis=dict(
            title="Strike",
            tickfont=dict(size=11),
            titlefont=dict(size=12),
        ),
        yaxis=dict(title="DTE", ),
        zaxis=dict(title=z, ),
    ), )
    fig.update_layout(
        margin=dict(l=0, r=0, t=40, b=20),
        template=cfg.PLT_3DMESH_STYLE_TEMPLATE,
        title=f"{label} Surface for {ticker.upper()}",
        title_x=0.5,
        hoverlabel=cfg.PLT_3DMESH_HOVERLABEL,
        scene_camera=dict(
            up=dict(x=0, y=0, z=2),
            center=dict(x=0, y=0, z=-0.3),
            eye=dict(x=1.25, y=1.25, z=0.69),
        ),
        scene=cfg.PLT_3DMESH_SCENE,
    )
    config = dict({"scrollZoom": True})
    imagefile = "opt-vsurf.png"

    # Check if interactive settings are enabled
    plt_link = ""
    if cfg.INTERACTIVE:
        html_ran = helpers.uuid_get()
        fig.write_html(f"in/vsurf_{html_ran}.html", config=config)
        plt_link = f"[Interactive]({cfg.INTERACTIVE_URL}/vsurf_{html_ran}.html)"

    fig.update_layout(
        width=800,
        height=500,
    )

    imagefile = helpers.image_border(imagefile, fig=fig)

    return {
        "title": f"{label} Surface for {ticker.upper()}",
        "description": plt_link,
        "imagefile": imagefile,
    }
示例#18
0
def cc_hist_command(ticker: str = None,
                    expiry: str = "",
                    strike: float = 10,
                    opt_type: str = ""):
    """Plot historical option prices

    Parameters
    ----------
    ticker: str
        Stock ticker
    expiry: str
        expiration date
    strike: float
        Option strike price
    put: bool
        Calls for call
        Puts for put
    """

    # Debug
    if cfg.DEBUG:
        print(f"opt-hist {ticker} {strike} {opt_type} {expiry}")

    # Check for argument
    if ticker is None:
        raise Exception("Stock ticker is required")
    yf_ticker = yf.Ticker(ticker)
    dates = list(yf_ticker.options)

    if not dates:
        raise Exception("Stock ticker is invalid")

    options = yf.Ticker(ticker).option_chain(expiry)

    if opt_type == "Calls":
        options = options.calls
    if opt_type == "Puts":
        options = options.puts

    chain_id = options.loc[options.strike == strike,
                           "contractSymbol"].values[0]
    df_hist = yf.download(chain_id)
    df_hist.index.name = "date"

    plt_title = [
        f"\n{ticker.upper()} {strike} {opt_type} expiring {expiry} Historical",
        "Volume",
    ]

    fig = make_subplots(
        rows=2,
        cols=1,
        shared_xaxes=True,
        vertical_spacing=0.06,
        subplot_titles=plt_title,
        row_width=[0.2, 0.7],
    )
    fig.add_trace(
        go.Candlestick(
            x=df_hist.index,
            open=df_hist.Open,
            high=df_hist.High,
            low=df_hist.Low,
            close=df_hist.Close,
            name="OHLC",
        ),
        row=1,
        col=1,
    )
    colors = [
        "green" if row.Open < row["Close"] else "red"
        for _, row in df_hist.iterrows()
    ]  # pylint: disable=E1120
    fig.add_trace(
        go.Bar(
            x=df_hist.index,
            y=df_hist.Volume,
            name="Volume",
            marker_color=colors,
        ),
        row=2,
        col=1,
    )
    fig.update_layout(
        margin=dict(l=0, r=0, t=25, b=5),
        template=cfg.PLT_CANDLE_STYLE_TEMPLATE,
        showlegend=False,
        yaxis_title="Premium",
        xaxis=dict(
            rangeslider=dict(visible=False),
            type="date",
        ),
        dragmode="pan",
    )
    fig.update_xaxes(rangebreaks=[
        dict(bounds=["sat", "mon"]),
    ], )
    config = dict({"scrollZoom": True})
    rand = np.random.randint(70000)
    imagefile = f"opt_hist{rand}.png"
    fig.write_image(imagefile)
    imagefile = image_border(imagefile)

    # Check if interactive settings are enabled
    plt_link = ""
    if cfg.INTERACTIVE:
        fig.write_html(f"in/cc_hist_{rand}.html", config=config)
        plt_link = f"[Interactive]({cfg.INTERACTIVE_URL}/cc_hist_{rand}.html)"

    return {
        "title":
        f"{ticker.upper()} {strike} {opt_type} expiring {expiry} Historical",
        "description": plt_link,
        "imagefile": imagefile,
    }
示例#19
0
def macd_command(ticker="",
                 fast="12",
                 slow="26",
                 signal="9",
                 start="",
                 end=""):
    """Displays chart with moving average convergence/divergence [Yahoo Finance]"""

    # Debug
    if cfg.DEBUG:
        # pylint: disable=logging-too-many-args
        logger.debug(
            "ta-macd %s %s %s %s %s %s",
            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 = 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(df_stock["Adj Close"], fast, slow, signal)
    trace_name = df_ta.columns[0].replace("_", " ")

    fig = make_subplots(
        rows=2,
        cols=1,
        shared_xaxes=True,
        vertical_spacing=0.07,
        row_width=[0.5, 0.6],
    )
    fig.add_trace(
        go.Scatter(
            name=ticker,
            x=df_stock.index,
            y=df_stock["Adj Close"].values,
            line=dict(color="#fdc708", width=2),
            opacity=1,
            showlegend=False,
        ),
        row=1,
        col=1,
    )
    fig.add_trace(
        go.Bar(
            name="MACD Histogram",
            x=df_ta.index,
            y=df_ta.iloc[:, 1].values,
            opacity=1,
        ),
        row=2,
        col=1,
    )
    fig.add_trace(
        go.Scatter(
            mode="lines",
            name="MACD Line",
            x=df_ta.index,
            y=df_ta.iloc[:, 0].values,
            opacity=1,
        ),
        row=2,
        col=1,
    )
    fig.add_trace(
        go.Scatter(
            mode="lines",
            name="Signal Line",
            x=df_ta.index,
            y=df_ta.iloc[:, 2].values,
            opacity=1,
        ),
        row=2,
        col=1,
    )
    fig.update_layout(
        margin=dict(l=0, r=20, t=30, b=20),
        template=cfg.PLT_TA_STYLE_TEMPLATE,
        colorway=cfg.PLT_TA_COLORWAY,
        title=f"{ticker} {trace_name}",
        title_x=0.3,
        yaxis_title="Stock Price ($)",
        yaxis=dict(fixedrange=False, ),
        xaxis=dict(
            rangeslider=dict(visible=False),
            type="date",
        ),
        dragmode="pan",
        legend=dict(orientation="h",
                    yanchor="bottom",
                    y=1.02,
                    xanchor="right",
                    x=1),
    )
    config = dict({"scrollZoom": True})
    imagefile = "ta_macd.png"

    # Check if interactive settings are enabled
    plt_link = ""
    if cfg.INTERACTIVE:
        html_ran = helpers.uuid_get()
        fig.write_html(f"in/macd_{html_ran}.html", config=config)
        plt_link = f"[Interactive]({cfg.INTERACTIVE_URL}/macd_{html_ran}.html)"

    fig.update_layout(
        width=800,
        height=500,
    )

    imagefile = helpers.image_border(imagefile, fig=fig)

    return {
        "title": f"Stocks: Moving-Average-Convergence-Divergence {ticker}",
        "description": plt_link,
        "imagefile": imagefile,
    }
示例#20
0
def rsi_command(ticker="",
                length="14",
                scalar="100",
                drift="1",
                start="",
                end=""):
    """Displays chart with relative strength index [Yahoo Finance]"""

    # Debug
    if cfg.DEBUG:
        # pylint: disable=logging-too-many-args
        logger.debug(
            "ta-rsi %s %s %s %s %s %s",
            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 = 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(df_stock["Adj Close"], length, scalar, drift)

    # Output Data
    fig = make_subplots(
        rows=2,
        cols=1,
        shared_xaxes=True,
        vertical_spacing=0.07,
        row_width=[0.5, 0.6],
    )
    fig.add_trace(
        go.Scatter(
            name=ticker,
            x=df_stock.index,
            y=df_stock["Adj Close"].values,
            line=dict(color="#fdc708", width=2),
            opacity=1,
            showlegend=False,
        ),
        row=1,
        col=1,
    )
    for i in range(0, df_ta.shape[1]):
        trace_name = df_ta.columns[i].replace("_", " ")
        fig.add_trace(
            go.Scatter(
                name=trace_name,
                x=df_ta.index,
                y=df_ta.iloc[:, i],
                opacity=1,
            ),
            row=2,
            col=1,
        )
    fig.add_hrect(
        y0=70,
        y1=100,
        fillcolor="red",
        opacity=0.2,
        layer="below",
        line_width=0,
        row=2,
        col=1,
    )
    fig.add_hrect(
        y0=0,
        y1=30,
        fillcolor="green",
        opacity=0.2,
        layer="below",
        line_width=0,
        row=2,
        col=1,
    )
    fig.add_hline(
        y=70,
        fillcolor="green",
        opacity=1,
        layer="below",
        line_width=3,
        line=dict(color="red", dash="dash"),
        row=2,
        col=1,
    )
    fig.add_hline(
        y=30,
        fillcolor="green",
        opacity=1,
        layer="below",
        line_width=3,
        line=dict(color="green", dash="dash"),
        row=2,
        col=1,
    )
    fig.update_layout(
        margin=dict(l=0, r=20, t=30, b=20),
        template=cfg.PLT_TA_STYLE_TEMPLATE,
        colorway=cfg.PLT_TA_COLORWAY,
        title=f"{ticker} {trace_name}",
        title_x=0.5,
        yaxis_title="Stock Price ($)",
        yaxis=dict(fixedrange=False, ),
        xaxis=dict(
            rangeslider=dict(visible=False),
            type="date",
        ),
        dragmode="pan",
        legend=dict(yanchor="top", y=0.99, xanchor="left", x=0.01),
    )
    config = dict({"scrollZoom": True})
    imagefile = "ta_rsi.png"

    # Check if interactive settings are enabled
    plt_link = ""
    if cfg.INTERACTIVE:
        html_ran = helpers.uuid_get()
        fig.write_html(f"in/rsi_{html_ran}.html", config=config)
        plt_link = f"[Interactive]({cfg.INTERACTIVE_URL}/rsi_{html_ran}.html)"

    fig.update_layout(
        width=800,
        height=500,
    )

    imagefile = helpers.image_border(imagefile, fig=fig)

    return {
        "title": f"Stocks: Relative-Strength-Index {ticker}",
        "description": plt_link,
        "imagefile": imagefile,
    }
示例#21
0
def ftd_command(ticker: str = "", start="", end=""):
    """Fails-to-deliver data [SEC]"""

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

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

    ticker = ticker.upper()

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

    stock = helpers.load(ticker, start)
    stock_ftd = stock[stock.index > start]
    stock_ftd = stock_ftd[stock_ftd.index < end]

    # Output data
    fig = make_subplots(shared_xaxes=True, specs=[[{"secondary_y": True}]])

    fig.add_trace(
        go.Scatter(
            name=ticker,
            x=stock_ftd.index,
            y=stock_ftd["Adj Close"],
            line=dict(color="#fdc708", width=2),
            opacity=1,
            showlegend=False,
        ),
        secondary_y=False,
    )
    fig.add_trace(
        go.Bar(
            name="FTDs",
            x=ftds_data["SETTLEMENT DATE"],
            y=ftds_data["QUANTITY (FAILS)"] / 1000,
            opacity=1,
        ),
        secondary_y=True,
    )
    # Set y-axes titles
    fig.update_yaxes(title_text="<b>Shares</b> [K]", secondary_y=True)
    fig.update_layout(
        margin=dict(l=0, r=20, t=30, b=20),
        template=cfg.PLT_TA_STYLE_TEMPLATE,
        colorway=cfg.PLT_TA_COLORWAY,
        title=f"{ticker}",
        title_x=0.5,
        yaxis_title="<b>Stock Price</b> ($)",
        yaxis=dict(
            side="right",
            fixedrange=False,
        ),
        xaxis=dict(
            rangeslider=dict(visible=False),
            type="date",
            fixedrange=False,
        ),
        xaxis2=dict(
            rangeslider=dict(visible=False),
            type="date",
            fixedrange=False,
        ),
        dragmode="pan",
        legend=dict(orientation="h",
                    yanchor="bottom",
                    y=1.02,
                    xanchor="right",
                    x=1),
        yaxis2=dict(
            side="left",
            position=0.15,
            fixedrange=False,
        ),
        hovermode="x unified",
    )
    config = dict({"scrollZoom": True})
    imagefile = "dps_ftd.png"

    # Check if interactive settings are enabled
    plt_link = ""
    if cfg.INTERACTIVE:
        html_ran = helpers.uuid_get()
        fig.write_html(f"in/ftds_{html_ran}.html", config=config)
        plt_link = f"[Interactive]({cfg.INTERACTIVE_URL}/ftds_{html_ran}.html)"

    fig.update_layout(
        width=800,
        height=500,
    )

    imagefile = helpers.image_border(imagefile, fig=fig)

    return {
        "title": f"Stocks: [SEC] Failure-to-deliver {ticker}",
        "description": plt_link,
        "imagefile": imagefile,
    }
示例#22
0
def cci_command(ticker="", length="14", scalar="0.015", start="", end=""):
    """Displays chart with commodity channel index [Yahoo Finance]"""

    # Debug
    if cfg.DEBUG:
        logger.debug(
            "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 = 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
    )

    dmin = df_ta.values.min()
    dmax = df_ta.values.max()
    # Output Data

    fig = make_subplots(
        rows=2,
        cols=1,
        shared_xaxes=True,
        vertical_spacing=0.07,
        row_width=[0.5, 0.6],
    )
    fig.add_trace(
        go.Scatter(
            name=ticker,
            x=df_stock.index,
            y=df_stock["Adj Close"].values,
            line=dict(color="#fdc708", width=2),
            opacity=1,
            showlegend=False,
        ),
        row=1,
        col=1,
    )
    fig.add_trace(
        go.Scatter(
            showlegend=False,
            x=df_ta.index,
            y=df_ta.iloc[:, 0].values,
            opacity=1,
        ),
        row=2,
        col=1,
    )
    fig.add_hrect(
        y0=100,
        y1=dmax,
        fillcolor="red",
        opacity=0.2,
        layer="below",
        line_width=0,
        row=2,
        col=1,
    )
    fig.add_hrect(
        y0=-100,
        y1=dmin,
        fillcolor="green",
        opacity=0.2,
        layer="below",
        line_width=0,
        row=2,
        col=1,
    )
    fig.add_hline(
        y=-100,
        fillcolor="green",
        opacity=1,
        layer="below",
        line_width=3,
        line=dict(color="green", dash="dash"),
        row=2,
        col=1,
    )
    fig.add_hline(
        y=100,
        fillcolor="red",
        opacity=1,
        layer="below",
        line_width=3,
        line=dict(color="red", dash="dash"),
        row=2,
        col=1,
    )
    fig.update_layout(
        margin=dict(l=0, r=20, t=30, b=20),
        template=cfg.PLT_TA_STYLE_TEMPLATE,
        colorway=cfg.PLT_TA_COLORWAY,
        title=f"{ticker} CCI",
        title_x=0.5,
        yaxis_title="Stock Price ($)",
        yaxis=dict(
            fixedrange=False,
        ),
        xaxis=dict(
            rangeslider=dict(visible=False),
            type="date",
        ),
        dragmode="pan",
        legend=dict(yanchor="top", y=0.99, xanchor="left", x=0.01),
    )
    config = dict({"scrollZoom": True})
    imagefile = "ta_cci.png"

    # Check if interactive settings are enabled
    plt_link = ""
    if cfg.INTERACTIVE:
        html_ran = helpers.uuid_get()
        fig.write_html(f"in/cci_{html_ran}.html", config=config)
        plt_link = f"[Interactive]({cfg.INTERACTIVE_URL}/cci_{html_ran}.html)"

    fig.update_layout(
        width=800,
        height=500,
    )
    imagefile = helpers.image_border(imagefile, fig=fig)

    return {
        "title": f"Stocks: Commodity-Channel-Index {ticker}",
        "description": plt_link,
        "imagefile": imagefile,
    }
示例#23
0
def topsells_command(
    gov_type="",
    past_transactions_months: int = 5,
    num: int = 10,
    raw: bool = False,
):
    """Displays most sold stocks by the congress/senate/house [quiverquant.com]"""
    # Debug user input
    if cfg.DEBUG:
        logger.debug(
            "gov-topsells %s %s %s %s",
            gov_type,
            past_transactions_months,
            num,
            raw,
        )

    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)

    # Output Data
    if df_gov.empty:
        raise Exception(f"No {gov_type} trading data found\n")

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

    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().replace(">$", "").strip())
    df_gov["max"] = df_gov["Range"].apply(
        lambda x: x.split("-")[1].replace(",", "").strip().strip("$").replace(
            ">$", "").strip() if "-" in x else x.strip("$").replace(
                ",", "").replace(">$", "").strip())

    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,
    )
    description = None
    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=True).abs().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().abs().head(
        n=num).plot(kind="bar", rot=0, ax=ax)
    ax.set_ylabel("Amount ($1k)")
    ax.set_title(
        f"{num} most sold stocks over last {past_transactions_months} months"
        f" (upper bound) for {gov_type}")
    plt.gcf().axes[0].yaxis.get_major_formatter().set_scientific(False)
    fig.tight_layout()

    plt.savefig("gov_topsells.png")
    imagefile = "gov_topsells.png"

    imagefile = image_border(imagefile)
    return {
        "title": f"Stocks: [quiverquant.com] Top sells for {gov_type.upper()}",
        "imagefile": imagefile,
        "description": description,
    }
示例#24
0
def aroon_command(ticker="", length="25", scalar="100", start="", end=""):
    """Displays chart with aroon indicator [Yahoo Finance]"""

    # Debug
    if cfg.DEBUG:
        logger.debug(
            "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 = 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
    )

    # Output Data
    aadown = df_ta.columns[0].replace("_", " ")
    aaup = df_ta.columns[1].replace("_", " ")
    aaosc = df_ta.columns[2].replace("_", " ")

    fig = make_subplots(
        rows=3,
        cols=1,
        shared_xaxes=True,
        vertical_spacing=0.07,
        row_width=[0.2, 0.2, 0.2],
    )
    fig.add_trace(
        go.Scatter(
            name=ticker,
            x=df_stock.index,
            y=df_stock["Adj Close"].values,
            line=dict(color="#fdc708", width=2),
            opacity=1,
            showlegend=False,
        ),
        row=1,
        col=1,
    )
    fig.add_trace(
        go.Scatter(
            name=f"Aroon DOWN ({aadown})",
            x=df_ta.index,
            y=df_ta.iloc[:, 0].values,
            opacity=1,
        ),
        row=2,
        col=1,
    )
    fig.add_trace(
        go.Scatter(
            name=f"Aroon UP ({aaup})",
            x=df_ta.index,
            y=df_ta.iloc[:, 1].values,
            opacity=1,
        ),
        row=2,
        col=1,
    )
    fig.add_trace(
        go.Scatter(
            name=f"Aroon OSC ({aaosc})",
            x=df_ta.index,
            y=df_ta.iloc[:, 2].values,
            opacity=1,
        ),
        row=3,
        col=1,
    )
    fig.add_hline(
        y=50,
        fillcolor="grey",
        opacity=1,
        layer="below",
        line_width=3,
        line=dict(color="grey", dash="dash"),
        row=2,
        col=1,
    )
    fig.update_layout(
        margin=dict(l=0, r=20, t=30, b=20),
        template=cfg.PLT_TA_STYLE_TEMPLATE,
        colorway=cfg.PLT_TA_COLORWAY,
        title=f"Aroon on {ticker}",
        title_x=0.5,
        yaxis_title="Stock Price ($)",
        yaxis=dict(
            fixedrange=False,
        ),
        xaxis=dict(
            rangeslider=dict(visible=False),
            type="date",
        ),
        dragmode="pan",
        legend=dict(yanchor="top", y=0.99, xanchor="left", x=0.01),
    )
    config = dict({"scrollZoom": True})
    imagefile = "ta_aroon.png"

    # Check if interactive settings are enabled
    plt_link = ""
    if cfg.INTERACTIVE:
        html_ran = helpers.uuid_get()
        fig.write_html(f"in/aroon_{html_ran}.html", config=config)
        plt_link = f"[Interactive]({cfg.INTERACTIVE_URL}/aroon_{html_ran}.html)"

    fig.update_layout(
        width=800,
        height=500,
    )
    imagefile = helpers.image_border(imagefile, fig=fig)

    return {
        "title": f"Stocks: Aroon-Indicator {ticker}",
        "description": plt_link,
        "imagefile": imagefile,
    }
示例#25
0
def fib_command(ticker="", start="", end=""):
    """Displays chart with fibonacci retracement [Yahoo Finance]"""

    # Debug
    if cfg.DEBUG:
        logger.debug(
            "ta-fib %s %s %s",
            ticker,
            start,
            end,
        )

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

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

    if end == "":
        end = datetime.now()
        f_end = None
    else:
        end = datetime.strptime(end, cfg.DATE_FORMAT)
        f_end = None

    ticker = ticker.upper()
    df_stock = bots.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, f_start, f_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)
    imagefile = "ta_fib.png"
    plt.savefig(imagefile)

    imagefile = image_border(imagefile)

    return {
        "title": f"Stocks: Fibonacci-Retracement-Levels {ticker}",
        "imagefile": imagefile,
    }
示例#26
0
def bbands_command(ticker="",
                   length="5",
                   n_std="2",
                   mamode="sma",
                   start="",
                   end=""):
    """Displays chart with bollinger bands [Yahoo Finance]"""

    # Debug
    if cfg.DEBUG:
        # pylint: disable=logging-too-many-args
        logger.debug(
            "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 = 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
    bbu = df_ta.columns[2].replace("_", " ")
    bbm = df_ta.columns[1].replace("_", " ")
    bbl = df_ta.columns[0].replace("_", " ")

    fig = go.Figure()
    fig.add_trace(
        go.Scatter(
            name=f"{bbu}",
            x=df_ta.index,
            y=df_ta.iloc[:, 2].values,
            opacity=1,
            mode="lines",
            line_color="indigo",
        ), )
    fig.add_trace(
        go.Scatter(
            name=f"{bbl}",
            x=df_ta.index,
            y=df_ta.iloc[:, 0].values,
            opacity=1,
            mode="lines",
            line_color="indigo",
            fill="tonexty",
            fillcolor="rgba(74, 0, 128, 0.2)",
        ), )
    fig.add_trace(
        go.Scatter(
            name=f"{bbm}",
            x=df_ta.index,
            y=df_ta.iloc[:, 1].values,
            opacity=1,
            line=dict(
                width=1.5,
                dash="dash",
            ),
        ), )
    fig.add_trace(
        go.Scatter(
            name=f"{ticker}",
            x=df_stock.index,
            y=df_stock["Adj Close"],
            line=dict(color="#fdc708", width=2),
            opacity=1,
        ), )
    fig.update_layout(
        margin=dict(l=0, r=0, t=50, b=20),
        template=cfg.PLT_TA_STYLE_TEMPLATE,
        colorway=cfg.PLT_TA_COLORWAY,
        title=f"{ticker} Bollinger Bands ({mamode.upper()})",
        title_x=0.5,
        yaxis_title="Stock Price ($)",
        xaxis_title="Time",
        yaxis=dict(fixedrange=False, ),
        xaxis=dict(
            rangeslider=dict(visible=False),
            type="date",
        ),
        dragmode="pan",
        legend=dict(yanchor="top", y=0.99, xanchor="left", x=0.01),
    )
    config = dict({"scrollZoom": True})
    imagefile = "ta_bbands.png"

    # Check if interactive settings are enabled
    plt_link = ""
    if cfg.INTERACTIVE:
        html_ran = helpers.uuid_get()
        fig.write_html(f"in/bbands_{html_ran}.html", config=config)
        plt_link = f"[Interactive]({cfg.INTERACTIVE_URL}/bbands_{html_ran}.html)"

    fig.update_layout(
        width=800,
        height=500,
    )

    imagefile = helpers.image_border(imagefile, fig=fig)

    return {
        "title": f"Stocks: Bollinger-Bands {ticker}",
        "description": plt_link,
        "imagefile": imagefile,
    }
示例#27
0
def sma_command(ticker="", window="", offset="", start="", end=""):
    """Displays chart with simple moving average [Yahoo Finance]"""

    # Debug
    if cfg.DEBUG:
        logger.debug(
            "ta-sma %s %s %s %s %s",
            ticker,
            window,
            offset,
            start,
            end,
        )

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

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

    if end == "":
        end = datetime.now()
    else:
        end = datetime.strptime(end, cfg.DATE_FORMAT)

    l_legend = [ticker]

    if window == "":
        window = [20, 50]
    else:
        window_temp = list()
        for wind in window.split(","):
            try:
                window_temp.append(float(wind))
            except Exception as e:
                raise Exception("Window needs to be a float") from e
        window = window_temp

    ticker = ticker.upper()
    stock = helpers.load(ticker, start)
    if stock.empty:
        raise Exception("Stock ticker is invalid")

    # Retrieve Data
    price_df = pd.DataFrame(stock["Adj Close"].values,
                            columns=["Price"],
                            index=stock.index)
    i = 1
    for win in window:
        sma_data = overlap_model.sma(values=stock["Adj Close"],
                                     length=win,
                                     offset=offset)
        price_df = price_df.join(sma_data)
        l_legend.append(f"SMA {win}")
        i += 1

    # Output Data
    start = start.strftime("%Y-%m-%d")
    end = end.strftime("%Y-%m-%d")
    price_df = price_df.loc[(price_df.index >= start) & (price_df.index < end)]

    fig = go.Figure()
    fig.add_trace(
        go.Scatter(
            name=f"{ticker}",
            x=price_df.index,
            y=price_df["Price"],
            line=dict(color="#fdc708", width=2),
            opacity=1,
        ), )
    for i in range(1, price_df.shape[1]):
        trace_name = price_df.columns[i].replace("_", " ")
        fig.add_trace(
            go.Scatter(
                name=trace_name,
                x=price_df.index,
                y=price_df.iloc[:, i],
                opacity=1,
            ), )
    fig.update_layout(
        margin=dict(l=0, r=0, t=50, b=20),
        template=cfg.PLT_TA_STYLE_TEMPLATE,
        colorway=cfg.PLT_TA_COLORWAY,
        title=f"{ticker} SMA",
        title_x=0.5,
        yaxis_title="Stock Price ($)",
        xaxis_title="Time",
        yaxis=dict(fixedrange=False, ),
        xaxis=dict(
            rangeslider=dict(visible=False),
            type="date",
        ),
        dragmode="pan",
        legend=dict(yanchor="top", y=0.99, xanchor="left", x=0.01),
    )
    config = dict({"scrollZoom": True})
    imagefile = "ta_sma.png"

    # Check if interactive settings are enabled
    plt_link = ""
    if cfg.INTERACTIVE:
        html_ran = helpers.uuid_get()
        fig.write_html(f"in/sma_{html_ran}.html", config=config)
        plt_link = f"[Interactive]({cfg.INTERACTIVE_URL}/sma_{html_ran}.html)"

    fig.update_layout(
        width=800,
        height=500,
    )

    imagefile = helpers.image_border(imagefile, fig=fig)

    return {
        "title": f"Stocks: Simple-Moving-Average {ticker}",
        "description": plt_link,
        "imagefile": imagefile,
    }
示例#28
0
def stoch_command(ticker="", fast_k="14", slow_d="3", slow_k="3", start="", end=""):
    """Displays chart with stochastic relative strength average [Yahoo Finance]"""

    # Debug
    if cfg.DEBUG:
        logger.debug(
            "ta-stoch %s %s %s %s %s %s",
            ticker,
            fast_k,
            slow_k,
            slow_d,
            start,
            end,
        )

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

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

    if end == "":
        end = datetime.now()
    else:
        end = datetime.strptime(end, cfg.DATE_FORMAT)

    if not fast_k.lstrip("-").isnumeric():
        raise Exception("Number has to be an integer")
    fast_k = int(fast_k)
    if not slow_k.lstrip("-").isnumeric():
        raise Exception("Number has to be an integer")
    slow_k = int(slow_k)
    if not slow_d.lstrip("-").isnumeric():
        raise Exception("Number has to be an integer")
    slow_d = int(slow_d)

    ticker = ticker.upper()
    df_stock = helpers.load(ticker, start)
    if df_stock.empty:
        raise Exception("Stock ticker is invalid")

    # Retrieve Data
    df_stock = df_stock.loc[(df_stock.index >= start) & (df_stock.index < end)]

    df_ta = momentum_model.stoch(
        df_stock["High"],
        df_stock["Low"],
        df_stock["Adj Close"],
        fast_k,
        slow_d,
        slow_k,
    )

    fig = make_subplots(
        rows=2,
        cols=1,
        shared_xaxes=True,
        vertical_spacing=0.07,
        row_width=[0.5, 0.7],
    )
    fig.add_trace(
        go.Scatter(
            x=df_stock.index,
            y=df_stock["Adj Close"].values,
            line=dict(color="#fdc708", width=2),
            opacity=1,
            showlegend=False,
        ),
        row=1,
        col=1,
    )
    K = df_ta.columns[0].replace("_", " ")
    D = df_ta.columns[1].replace("_", " ")
    fig.add_trace(
        go.Scatter(
            name=f"%K {K}",
            x=df_stock.index,
            y=df_ta.iloc[:, 0].values,
            line=dict(width=1.8),
            opacity=1,
        ),
        row=2,
        col=1,
    )
    fig.add_trace(
        go.Scatter(
            name=f"%D {D}",
            x=df_stock.index,
            y=df_ta.iloc[:, 1].values,
            line=dict(width=1.8, dash="dash"),
            opacity=1,
        ),
        row=2,
        col=1,
    )
    fig.add_hrect(
        y0=80,
        y1=100,
        fillcolor="red",
        opacity=0.2,
        layer="below",
        line_width=0,
        row=2,
        col=1,
    )
    fig.add_hrect(
        y0=0,
        y1=20,
        fillcolor="green",
        opacity=0.2,
        layer="below",
        line_width=0,
        row=2,
        col=1,
    )
    fig.add_hline(
        y=80,
        fillcolor="green",
        opacity=1,
        layer="below",
        line_width=3,
        line=dict(color="red", dash="dash"),
        row=2,
        col=1,
    )
    fig.add_hline(
        y=20,
        fillcolor="green",
        opacity=1,
        layer="below",
        line_width=3,
        line=dict(color="green", dash="dash"),
        row=2,
        col=1,
    )
    fig.update_layout(
        margin=dict(l=0, r=0, t=40, b=20),
        template=cfg.PLT_TA_STYLE_TEMPLATE,
        colorway=cfg.PLT_TA_COLORWAY,
        title=f"Stochastic Relative Strength Index (STOCH RSI) on {ticker}",
        title_x=0.5,
        yaxis_title="Stock Price ($)",
        yaxis=dict(
            fixedrange=False,
        ),
        xaxis=dict(
            rangeslider=dict(visible=False),
            type="date",
        ),
        dragmode="pan",
        legend=dict(yanchor="top", y=0.99, xanchor="left", x=0.01),
    )
    config = dict({"scrollZoom": True})
    imagefile = "ta_stoch.png"

    # Check if interactive settings are enabled
    plt_link = ""
    if cfg.INTERACTIVE:
        html_ran = helpers.uuid_get()
        fig.write_html(f"in/stoch_{html_ran}.html", config=config)
        plt_link = f"[Interactive]({cfg.INTERACTIVE_URL}/stoch_{html_ran}.html)"

    fig.update_layout(
        width=800,
        height=500,
    )

    imagefile = helpers.image_border(imagefile, fig=fig)

    return {
        "title": f"Stocks: Stochastic-Relative-Strength-Index {ticker}",
        "description": plt_link,
        "imagefile": imagefile,
    }
示例#29
0
def hist_command(
    ticker: str = None,
    expiry: str = "",
    strike: float = 10,
    opt_type: str = "",
    greek: str = "",
):
    """Plot historical option prices

    Parameters
    ----------
    ticker: str
        Stock ticker
    expiry: str
        expiration date
    strike: float
        Option strike price
    put: bool
        Calls for call
        Puts for put
    """

    # Debug
    if cfg.DEBUG:
        print(f"opt-hist {ticker} {strike} {opt_type} {expiry} {greek}")

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

    if opt_type == "Puts":
        put = bool(True)
    if opt_type == "Calls":
        put = bool(False)
    chain_id = ""

    df_hist = syncretism_model.get_historical_greeks(ticker, expiry, chain_id,
                                                     strike, put)
    title = f"\n{ticker.upper()} {strike} {opt_type} expiring {expiry} Historical {greek.upper()}"
    # Output data
    fig = make_subplots(shared_xaxes=True, specs=[[{"secondary_y": True}]])

    fig.add_trace(
        go.Scatter(
            name=ticker.upper(),
            x=df_hist.index,
            y=df_hist.price,
            line=dict(color="#fdc708", width=2),
            opacity=1,
        ), )
    fig.add_trace(
        go.Scatter(
            name="Premium",
            x=df_hist.index,
            y=df_hist["premium"],
            opacity=1,
            yaxis="y2",
        ), )
    if greek:
        fig.add_trace(
            go.Scatter(
                name=f"{greek.upper()}",
                x=df_hist.index,
                y=df_hist[greek],
                opacity=1,
                yaxis="y3",
            ), )
    fig.update_layout(
        margin=dict(l=10, r=10, t=30, b=20),
        template=cfg.PLT_TA_STYLE_TEMPLATE,
        colorway=cfg.PLT_TA_COLORWAY,
        title=title,
        title_x=0.03,
        yaxis_title="<b>Stock Price</b> ($)",
        yaxis=dict(
            side="right",
            fixedrange=False,
            titlefont=dict(color="#fdc708"),
            tickfont=dict(color="#fdc708"),
            position=0.02,
            nticks=20,
        ),
        xaxis=dict(
            rangeslider=dict(visible=False),
            type="date",
            fixedrange=False,
            domain=[0.037, 1],
        ),
        xaxis2=dict(
            rangeslider=dict(visible=False),
            type="date",
            fixedrange=False,
        ),
        xaxis3=dict(
            rangeslider=dict(visible=False),
            type="date",
            fixedrange=False,
        ),
        dragmode="pan",
        legend=dict(orientation="h",
                    yanchor="bottom",
                    y=1.02,
                    xanchor="right",
                    x=1),
        yaxis2=dict(
            side="left",
            fixedrange=False,
            anchor="x",
            overlaying="y",
            titlefont=dict(color="#d81aea"),
            tickfont=dict(color="#d81aea"),
            nticks=20,
        ),
        yaxis3=dict(
            side="left",
            position=0,
            fixedrange=False,
            overlaying="y",
            titlefont=dict(color="#00e6c3"),
            tickfont=dict(color="#00e6c3"),
            nticks=20,
        ),
        hovermode="x unified",
    )
    config = dict({"scrollZoom": True})
    imagefile = "opt_hist.png"

    # Check if interactive settings are enabled
    plt_link = ""
    if cfg.INTERACTIVE:
        html_ran = helpers.uuid_get()
        fig.write_html(f"in/hist_{html_ran}.html", config=config)
        plt_link = f"[Interactive]({cfg.INTERACTIVE_URL}/hist_{html_ran}.html)"

    fig.update_layout(
        width=800,
        height=500,
    )

    imagefile = helpers.image_border(imagefile, fig=fig)

    return {
        "title":
        f"{ticker.upper()} {strike} {opt_type} expiring {expiry} Historical",
        "description": plt_link,
        "imagefile": imagefile,
    }
示例#30
0
def overview_command(
    ticker: str = None,
    expiry: str = None,
    min_sp: float = None,
    max_sp: float = None,
):
    """Options Overview"""

    # Debug
    if cfg.DEBUG:
        logger.debug("opt-overview %s %s %s %s", ticker, expiry, min_sp, max_sp)

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

    # Get options info/dates, Look for logo_url
    df = get_options_info(ticker)  # Barchart Options IV Overview

    dates = yfinance_model.option_expirations(ticker)  # Expiration dates
    tup = f"{ticker.upper()}"
    url = yf.Ticker(tup).info["logo_url"]
    url += "?raw=true" if url else ""

    if not dates:
        raise Exception("Stock ticker is invalid")

    options = yfinance_model.get_option_chain(ticker, str(expiry))
    calls = options.calls.fillna(0)
    puts = options.puts.fillna(0)
    current_price = yfinance_model.get_price(ticker)

    min_strike2 = np.percentile(calls["strike"], 1)
    max_strike2 = np.percentile(calls["strike"], 100)
    min_strike = 0.75 * current_price
    max_strike = 1.95 * current_price

    if len(calls) > 40:
        min_strike = 0.75 * current_price
        max_strike = 1.25 * current_price

    if min_sp:
        min_strike = min_sp
        min_strike2 = min_sp
    if max_sp:
        max_strike = max_sp
        max_strike2 = max_sp
        if min_sp > max_sp:  # type: ignore
            min_sp, max_sp = max_strike2, min_strike2

    call_oi = calls.set_index("strike")["openInterest"] / 1000
    put_oi = puts.set_index("strike")["openInterest"] / 1000

    df_opt = pd.merge(call_oi, put_oi, left_index=True, right_index=True)
    df_opt = df_opt.rename(
        columns={"openInterest_x": "OI_call", "openInterest_y": "OI_put"}
    )

    max_pain = op_helpers.calculate_max_pain(df_opt)
    fig = go.Figure()

    dmax = df_opt[["OI_call", "OI_put"]].values.max()
    dmin = df_opt[["OI_call", "OI_put"]].values.min()
    fig.add_trace(
        go.Scatter(
            x=df_opt.index,
            y=df_opt["OI_call"],
            name="Calls",
            mode="lines+markers",
            line=dict(color="green", width=3),
        )
    )

    fig.add_trace(
        go.Scatter(
            x=df_opt.index,
            y=df_opt["OI_put"],
            name="Puts",
            mode="lines+markers",
            line=dict(color="red", width=3),
        )
    )
    fig.add_trace(
        go.Scatter(
            x=[current_price, current_price],
            y=[dmin, dmax],
            mode="lines",
            line=dict(color="gold", width=2),
            name="Current Price",
        )
    )
    fig.add_trace(
        go.Scatter(
            x=[max_pain, max_pain],
            y=[dmin, dmax],
            mode="lines",
            line=dict(color="grey", width=3, dash="dash"),
            name=f"Max Pain: {max_pain}",
        )
    )
    fig.update_xaxes(
        range=[min_strike, max_strike],
        constrain="domain",
    )
    fig.update_layout(
        margin=dict(l=0, r=0, t=60, b=20),
        template=cfg.PLT_SCAT_STYLE_TEMPLATE,
        title=f"Open Interest for {ticker.upper()} expiring {expiry}",
        title_x=0.5,
        legend_title="",
        xaxis_title="Strike",
        yaxis_title="Open Interest (1k)",
        xaxis=dict(
            rangeslider=dict(visible=False),
        ),
        legend=dict(yanchor="top", y=0.99, xanchor="left", x=0.01),
        dragmode="pan",
    )
    config = dict({"scrollZoom": True})
    imagefile = "opt_oi.png"

    plt_link = ""
    if cfg.INTERACTIVE:
        html_ran = helpers.uuid_get()
        fig.write_html(f"in/oi_{html_ran}.html", config=config)
        plt_link = f"[Interactive]({cfg.INTERACTIVE_URL}/oi_{html_ran}.html)"

    fig.update_layout(
        width=800,
        height=500,
    )

    imagefile = helpers.image_border(imagefile, fig=fig)

    uploaded_image_oi = gst_imgur.upload_image(imagefile, title="something")
    image_link_oi = uploaded_image_oi.link
    os.remove(imagefile)

    column_map = {"openInterest": "oi", "volume": "vol", "impliedVolatility": "iv"}
    columns = [
        "strike",
        "bid",
        "ask",
        "volume",
        "openInterest",
        "impliedVolatility",
    ]

    calls_df = calls[columns].rename(columns=column_map)
    puts_df = puts[columns].rename(columns=column_map)

    calls_df = calls_df[calls_df["strike"] >= min_strike2]
    calls_df = calls_df[calls_df["strike"] <= max_strike2]
    puts_df = puts_df[puts_df["strike"] >= min_strike2]
    puts_df = puts_df[puts_df["strike"] <= max_strike2]

    calls_df["iv"] = pd.to_numeric(calls_df["iv"].astype(float))
    puts_df["iv"] = pd.to_numeric(puts_df["iv"].astype(float))

    formats = {"iv": "{:.2f}"}
    for col, f in formats.items():
        calls_df[col] = calls_df[col].map(
            lambda x: f.format(x)  # pylint: disable=W0640
        )
        puts_df[col] = puts_df[col].map(lambda x: f.format(x))  # pylint: disable=W0640

    calls_df.set_index("strike", inplace=True)
    puts_df.set_index("strike", inplace=True)

    if "-" in df.iloc[0, 1]:
        iv = f"```diff\n-             {df.iloc[0, 1]}\n```"
    else:
        iv = f"```yaml\n              {df.iloc[0, 1]}\n```"

    pfix, sfix = f"{ticker.upper()} ", f" expiring {expiry}"
    if expiry == dates[0]:
        pfix = f"{ticker.upper()} Weekly "
        sfix = ""

    titles = [f"{ticker.upper()} Overview", f"{pfix}Open Interest{sfix}"]
    embeds = [
        disnake.Embed(
            title=f"{ticker.upper()} Overview",
            color=cfg.COLOR,
        ),
        disnake.Embed(
            title=f"{pfix}Open Interest{sfix}",
            description=plt_link,
            colour=cfg.COLOR,
        ),
    ]
    choices = [
        disnake.SelectOption(label=f"{ticker.upper()} Overview", value="0", emoji="🟢"),
        disnake.SelectOption(label=f"{pfix}Open Interest{sfix}", value="1", emoji="🟢"),
    ]
    embeds_img = []

    i, i2, end = 0, 0, 20
    df_calls = []
    dindex = len(calls_df.index)
    while i <= dindex:
        df_calls = calls_df.iloc[i:end]
        df_calls.append(df_calls)
        figc = df2img.plot_dataframe(
            df_calls,
            fig_size=(1000, (40 + (40 * 20))),
            col_width=[3, 3, 3, 3],
            tbl_cells=cfg.PLT_TBL_CELLS,
            font=cfg.PLT_TBL_FONT,
            template=cfg.PLT_TBL_STYLE_TEMPLATE,
            paper_bgcolor="rgba(0, 0, 0, 0)",
        )
        imagefile = helpers.save_image("opt-calls.png", figc)
        uploaded_image = gst_imgur.upload_image(imagefile, title="something")
        image_link = uploaded_image.link
        embeds_img.append(
            f"{image_link}",
        )
        titles.append(f"{pfix}Calls{sfix}")
        embeds.append(
            disnake.Embed(
                title=f"{pfix}Calls{sfix}",
                colour=cfg.COLOR,
            ),
        )
        i2 += 1
        i += 20
        end += 20
        os.remove(imagefile)

    # Add Calls page field
    i, page, puts_page = 2, 0, 3
    i3 = i2 + 2
    choices.append(
        disnake.SelectOption(label="Calls Page 1", value="2", emoji="🟢"),
    )
    for i in range(2, i3):
        page += 1
        puts_page += 1

        embeds[i].add_field(name=f"Calls Page {page}", value="_ _", inline=True)

    # Puts Pages
    i, end = 0, 20
    df_puts = []

    dindex = len(puts_df.index)
    while i <= dindex:
        df_puts = puts_df.iloc[i:end]
        df_puts.append(df_puts)
        figp = df2img.plot_dataframe(
            df_puts,
            fig_size=(1000, (40 + (40 * 20))),
            col_width=[3, 3, 3, 3],
            tbl_cells=cfg.PLT_TBL_CELLS,
            font=cfg.PLT_TBL_FONT,
            template=cfg.PLT_TBL_STYLE_TEMPLATE,
            paper_bgcolor="rgba(0, 0, 0, 0)",
        )
        imagefile = helpers.save_image("opt-puts.png", figp)
        uploaded_image = gst_imgur.upload_image(imagefile, title="something")
        image_link = uploaded_image.link
        embeds_img.append(
            f"{image_link}",
        )
        titles.append(f"{pfix}Puts{sfix}")
        embeds.append(
            disnake.Embed(
                title=f"{pfix}Puts{sfix}",
                colour=cfg.COLOR,
            ),
        )
        i2 += 1
        i += 20
        end += 20
        os.remove(imagefile)

    # Add Puts page field
    i, page = 0, 0
    puts_page -= 1
    i2 += 2
    choices.append(
        disnake.SelectOption(label="Puts Page 1", value=f"{puts_page}", emoji="🟢"),
    )
    for i in range(puts_page, i2):
        page += 1
        embeds[i].add_field(name=f"Puts Page {page}", value="_ _", inline=True)

    # Author/Footer
    for i in range(0, i2):
        embeds[i].set_author(
            name=cfg.AUTHOR_NAME,
            url=cfg.AUTHOR_URL,
            icon_url=cfg.AUTHOR_ICON_URL,
        )
        embeds[i].set_footer(
            text=cfg.AUTHOR_NAME,
            icon_url=cfg.AUTHOR_ICON_URL,
        )

    # Set images to Pages
    i = 0
    img_i = 0
    embeds[1].set_image(url=image_link_oi)
    for i in range(2, i2):
        embeds[i].set_image(url=embeds_img[img_i])
        img_i += 1
        i += 1

    if url:
        embeds[0].set_thumbnail(url=f"{url}")
    else:
        embeds[0].set_thumbnail(url=cfg.AUTHOR_ICON_URL)

    # Overview Section
    embeds[0].add_field(name=f"{df.iloc[0, 0]}", value=iv, inline=False)

    embeds[0].add_field(
        name=f"•{df.iloc[1, 0]}", value=f"```css\n{df.iloc[1, 1]}\n```", inline=True
    )
    for N in range(2, 6):
        embeds[0].add_field(
            name=f"_ _ _ _ _ _ _ _ _ _ •{df.iloc[N, 0]}",
            value=f"```css\n{df.iloc[N, 1]}\n```",
            inline=True,
        )

    embeds[0].add_field(name="_ _", value="_ _", inline=False)
    for N in range(6, 8):
        embeds[0].add_field(
            name=f"_ _ _ _ _ _ _ _ _ _ •{df.iloc[N, 0]}",
            value=f"```css\n{df.iloc[N, 1]}\n```",
            inline=True,
        )

    embeds[0].add_field(name="_ _", value="_ _", inline=False)
    for N in range(8, 10):
        embeds[0].add_field(
            name=f"_ _ _ _ _ _ _ _ _ _ •{df.iloc[N, 0]}",
            value=f"```css\n{df.iloc[N, 1]}\n```",
            inline=True,
        )

    embeds[0].add_field(name="_ _", value="_ _", inline=False)
    for N in range(10, 12):
        embeds[0].add_field(
            name=f"_ _ _ _ _ _ _ _ _ _ •{df.iloc[N, 0]}",
            value=f"```css\n{df.iloc[N, 1]}\n```",
            inline=True,
        )

    embeds[0].set_footer(text=f"Page 1 of {len(embeds)}")
    os.remove(imagefile)

    return {
        "view": Menu,
        "titles": titles,
        "embed": embeds,
        "choices": choices,
        "embeds_img": embeds_img,
    }