Beispiel #1
0
def histcont_command(ticker=""):
    """Displays historical quarterly-contracts [quiverquant.com]"""
    # Debug user input
    if imps.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()
    imagefile = "gov_histcont.png"

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

    imagefile = imps.image_border(imagefile, base64=dataBytesIO)

    return {
        "title": "Stocks: Historical Quarterly Government Contract ",
        "imagefile": imagefile,
    }
Beispiel #2
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 imps.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()

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

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

    return {
        "title": f"Stocks: [quiverquant.com] Contracts by {ticker}",
        "imagefile": imagefile,
    }
def toplobbying_command(num: int = 10, raw: bool = False):
    """Displays top lobbying firms [quiverquant.com]"""
    # Debug user input
    if imps.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()
    imagefile = "ta_toplobbying.png"

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

    imagefile = imps.image_border(imagefile, base64=dataBytesIO)

    return {
        "title": "Stocks: [quiverquant.com] Top Lobbying Firms",
        "imagefile": imagefile,
    }
Beispiel #4
0
def ma_command(
    ticker="",
    interval: int = 15,
    past_days: int = 0,
    ma_mode="ema",
    window="",
    offset: int = 0,
    start="",
    end="",
    extended_hours: bool = False,
    heikin_candles: bool = False,
    news: bool = False,
):
    """Displays chart with selected Moving Average  [Yahoo Finance]"""
    # Debug
    if imps.DEBUG:
        # pylint: disable=logging-too-many-args
        logger.debug(
            "ta ma %s %s %s %s %s %s %s %s %s %s %s",
            ticker,
            interval,
            past_days,
            ma_mode,
            window,
            offset,
            start,
            end,
            extended_hours,
            heikin_candles,
            news,
        )

    # Check for argument
    overlap_ma = {
        "ema": overlap_model.ema,
        "hma": overlap_model.hma,
        "sma": overlap_model.sma,
        "wma": overlap_model.wma,
        "zlma": overlap_model.zlma,
    }

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

    # Retrieve Data
    df_stock, start, end, bar_start = load_candle.stock_data(
        ticker=ticker,
        interval=interval,
        past_days=past_days,
        extended_hours=extended_hours,
        start=start,
        end=end,
        heikin_candles=heikin_candles,
    )

    if df_stock.empty:
        raise Exception("No Data Found")

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

    df_ta = df_stock.loc[(df_stock.index >= start) & (df_stock.index < end)]

    if df_ta.empty:
        raise Exception("No Data Found")

    for win in window:
        ema_data = overlap_ma[ma_mode](values=df_ta["Adj Close"],
                                       length=win,
                                       offset=offset)
        df_ta = df_ta.join(ema_data)

    # Output Data
    if interval != 1440:
        df_ta = df_ta.loc[(df_ta.index >= bar_start) & (df_ta.index < end)]
    df_ta = df_ta.fillna(0.0)

    plot = load_candle.candle_fig(
        df_ta,
        ticker,
        interval,
        extended_hours,
        news,
        bar=bar_start,
        int_bar=interval,
    )
    title = f"<b>{plot['plt_title']} Moving Average ({ma_mode.upper()})</b>"
    fig = plot["fig"]

    i2 = 6 if interval != 1440 else 11
    for i in range(i2, df_ta.shape[1]):
        fig.add_trace(
            go.Scatter(
                name=f"{df_ta.iloc[:, i].name}",
                mode="lines",
                x=df_ta.index,
                y=df_ta.iloc[:, i].values,
                opacity=1,
            ),
            secondary_y=True,
            row=1,
            col=1,
        )

    fig.update_layout(
        margin=dict(l=0, r=0, t=50, b=20),
        template=imps.PLT_TA_STYLE_TEMPLATE,
        colorway=imps.PLT_TA_COLORWAY,
        title=title,
        title_x=0.1,
        title_font_size=14,
        dragmode="pan",
    )
    imagefile = "ta_ma.png"

    # Check if interactive settings are enabled
    plt_link = ""
    if imps.INTERACTIVE:
        plt_link = imps.inter_chart(fig, imagefile, callback=False)

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

    return {
        "title": f"Stocks: Moving Average {ma_mode.upper()}",
        "description": plt_link,
        "imagefile": imagefile,
    }
Beispiel #5
0
def pt_command(ticker: str = "", raw: bool = False, start=""):
    """Displays price targets [Business Insider]"""

    # Debug
    if imps.DEBUG:
        logger.debug("dd pt %s", ticker)

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

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

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

    df_analyst_data = business_insider_model.get_price_target_from_analysts(ticker)
    stock = imps.load(ticker, start)
    title = f"Stocks: [Business Insider] Price Targets {ticker}"
    if df_analyst_data.empty or stock.empty:
        raise Exception("Enter valid ticker")

    # Output Data

    if raw:
        df_analyst_data.sort_index(ascending=False)
        report = "```" + df_analyst_data.to_string() + "```"

        output = {
            "title": title,
            "description": report,
        }
    else:
        plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI)
        if start:
            df_analyst_data = df_analyst_data[start:]

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

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

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

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

        plt.title(f"{ticker.upper()} (Time Series) and Price Target")
        plt.xlim(stock.index[0], stock.index[-1])
        plt.xlabel("Time")
        plt.ylabel("Share Price")
        plt.grid(b=True, which="major", color="#666666", linestyle="-")
        imagefile = "ta_pt.png"
        dataBytesIO = io.BytesIO()
        plt.savefig(dataBytesIO)
        plt.close("all")

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

        output = {
            "title": title,
            "imagefile": imagefile,
        }

    return output
Beispiel #6
0
def fib_command(
    ticker="",
    interval: int = 15,
    past_days: int = 0,
    start: str = "",
    end: str = "",
    extended_hours: bool = False,
    heikin_candles: bool = False,
    news: bool = False,
):
    """Displays chart with fibonacci retracement [Yahoo Finance]"""

    # Debug
    if imps.DEBUG:
        # pylint: disable=logging-too-many-args
        logger.debug(
            "ta fib %s %s %s %s %s %s %s %s",
            ticker,
            interval,
            past_days,
            start,
            end,
            extended_hours,
            heikin_candles,
            news,
        )

    past_days = (past_days + 1) if (interval != 1440) or (start != "") else 365

    # Retrieve Data
    (
        df_stock,
        start,
        end,
        bar_start,
    ) = load_candle.stock_data(
        ticker=ticker,
        interval=interval,
        past_days=past_days,
        extended_hours=extended_hours,
        start=start,
        end=end,
        heikin_candles=heikin_candles,
    )

    if df_stock.empty:
        raise Exception(f"No data found for {ticker.upper()}.")

    df_ta = df_stock.loc[(df_stock.index >= start) & (df_stock.index < end)]

    # Output Data
    if interval != 1440:
        df_ta = df_ta.loc[(df_ta.index >= bar_start) & (df_ta.index < end)]

    (
        df_fib,
        min_date,
        max_date,
        min_pr,
        max_pr,
    ) = custom_indicators_model.calculate_fib_levels(df_ta, 12, bar_start,
                                                     None)

    levels = df_fib.Price

    # Output Data
    fibs = [
        "<b>0</b>",
        "<b>0.235</b>",
        "<b>0.382</b>",
        "<b>0.5</b>",
        "<b>0.618</b>",
        "<b>0.65</b>",
        "<b>1</b>",
    ]
    plot = load_candle.candle_fig(
        df_ta,
        ticker,
        interval,
        extended_hours,
        news,
        bar=bar_start,
        int_bar=interval,
        shared_xaxes=True,
        vertical_spacing=0.07,
    )
    title = f"<b>{plot['plt_title']} Fibonacci-Retracement-Levels</b>"
    lvl_text: str = "right" if min_date > max_date else "left"
    fig = plot["fig"]

    fig.add_trace(
        go.Scatter(
            x=[min_date, max_date],
            y=[min_pr, max_pr],
            opacity=1,
            mode="lines",
            line=imps.PLT_FIB_COLORWAY[8],
            showlegend=False,
        ),
        row=1,
        col=1,
        secondary_y=True,
    )

    for i in range(6):
        fig.add_trace(
            go.Scatter(
                name=fibs[i],
                x=[min_date, max_date],
                y=[levels[i], levels[i]],
                opacity=0.2,
                mode="lines",
                line_color=imps.PLT_FIB_COLORWAY[i],
                showlegend=False,
            ),
            row=1,
            col=1,
            secondary_y=True,
        )
        fig.add_trace(
            go.Scatter(
                name=fibs[i + 1],
                x=[min_date, max_date],
                y=[levels[i + 1], levels[i + 1]],
                opacity=0.2,
                mode="lines",
                fill="tonexty",
                line_color=imps.PLT_FIB_COLORWAY[i + 1],
                showlegend=False,
            ),
            row=1,
            col=1,
            secondary_y=True,
        )

    for i in range(7):
        fig.add_trace(
            go.Scatter(
                name=fibs[i],
                x=[min_date],
                y=[levels[i]],
                opacity=0.9,
                mode="text",
                text=fibs[i],
                textposition=f"middle {lvl_text}"
                if i != 5 else f"bottom {lvl_text}",
                textfont=dict(imps.PLT_FIB_COLORWAY[7],
                              color=imps.PLT_FIB_COLORWAY[i]),
                showlegend=False,
            ),
            row=1,
            col=1,
            secondary_y=True,
        )
    fig.update_layout(
        margin=dict(l=0, r=0, t=50, b=20),
        template=imps.PLT_TA_STYLE_TEMPLATE,
        title=title,
        title_x=0.02,
        title_font_size=14,
        dragmode="pan",
    )
    imagefile = "ta_fib.png"

    # Check if interactive settings are enabled
    plt_link = ""
    if imps.INTERACTIVE:
        plt_link = imps.inter_chart(fig, imagefile, callback=False)

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

    return {
        "title": f"Stocks: Fibonacci-Retracement-Levels {ticker.upper()}",
        "description": plt_link,
        "imagefile": imagefile,
    }
Beispiel #7
0
def macd_command(
    ticker="",
    interval: int = 15,
    past_days: int = 0,
    fast="12",
    slow="26",
    signal="9",
    start="",
    end="",
    extended_hours: bool = False,
    heikin_candles: bool = False,
    news: bool = False,
):
    """Displays chart with moving average convergence/divergence [Yahoo Finance]"""

    # Debug
    if imps.DEBUG:
        # pylint: disable=logging-too-many-args
        logger.debug(
            "ta macd %s %s %s %s %s %s %s %s %s %s %s",
            ticker,
            interval,
            past_days,
            fast,
            slow,
            signal,
            start,
            end,
            extended_hours,
            heikin_candles,
            news,
        )

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

    # Retrieve Data
    df_stock, start, end, bar_start = load_candle.stock_data(
        ticker=ticker,
        interval=interval,
        past_days=past_days,
        extended_hours=extended_hours,
        start=start,
        end=end,
        heikin_candles=heikin_candles,
    )

    if df_stock.empty:
        raise Exception("No Data Found")

    if not fast.lstrip("-").isnumeric():
        raise Exception("Number has to be an integer")
    fast = int(fast)
    if not slow.lstrip("-").isnumeric():
        raise Exception("Number has to be an integer")
    slow = int(slow)
    if not signal.lstrip("-").isnumeric():
        raise Exception("Number has to be an integer")
    signal = int(signal)

    df_ta = df_stock.loc[(df_stock.index >= start) & (df_stock.index < end)]

    if df_ta.empty:
        raise Exception("No Data Found")

    ta_data = momentum_model.macd(df_stock["Adj Close"], fast, slow, signal)
    df_ta = df_ta.join(ta_data)

    # Output Data
    if interval != 1440:
        df_ta = df_ta.loc[(df_ta.index >= bar_start) & (df_ta.index < end)]
    df_ta = df_ta.fillna(0.0)

    plot = load_candle.candle_fig(
        df_ta,
        ticker,
        interval,
        extended_hours,
        news,
        bar=bar_start,
        int_bar=interval,
        rows=2,
        cols=1,
        shared_xaxes=True,
        vertical_spacing=0.07,
        row_width=[0.4, 0.6],
        specs=[[{"secondary_y": True}], [{"secondary_y": False}]],
    )
    title = f"<b>{plot['plt_title']} MACD {fast} {slow} {signal}</b>"
    fig = plot["fig"]
    idx = 6 if interval != 1440 else 11

    fig.add_trace(
        go.Bar(
            name="MACD Histogram",
            x=df_ta.index,
            y=df_ta.iloc[:, (idx + 1)].values,
            opacity=(plot["bar_opacity"] + 0.3),
            marker_color="#d81aea",
        ),
        row=2,
        col=1,
        secondary_y=False,
    )
    fig.add_trace(
        go.Scatter(
            name="MACD Line",
            mode="lines",
            x=df_ta.index,
            y=df_ta.iloc[:, idx].values,
            opacity=0.8,
            line=dict(color="#00e6c3"),
        ),
        row=2,
        col=1,
        secondary_y=False,
    )
    fig.add_trace(
        go.Scatter(
            name="Signal Line",
            mode="lines",
            x=df_ta.index,
            y=df_ta.iloc[:, (idx + 2)].values,
            opacity=1,
            line=dict(color="#9467bd"),
        ),
        row=2,
        col=1,
        secondary_y=False,
    )
    fig.update_layout(
        margin=dict(l=0, r=0, t=50, b=20),
        template=imps.PLT_TA_STYLE_TEMPLATE,
        colorway=imps.PLT_TA_COLORWAY,
        title=title,
        title_x=0.02,
        title_font_size=14,
        dragmode="pan",
    )
    imagefile = "ta_macd.png"

    # Check if interactive settings are enabled
    plt_link = ""
    if imps.INTERACTIVE:
        plt_link = imps.inter_chart(fig, imagefile, callback=False)

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

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

    return {
        "title": f"Stocks: Moving-Average-Convergence-Divergence {ticker.upper()}",
        "description": plt_link,
        "imagefile": imagefile,
    }
Beispiel #8
0
def vol_command(
    ticker: str = None,
    expiry: str = "",
    min_sp: float = None,
    max_sp: float = None,
):
    """Options VOL"""

    # Debug
    if imps.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
    call_v = call_v.fillna(0.0)
    put_v = put_v.fillna(0.0)

    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="#00ACFF", width=3),
        )
    )
    fig.add_trace(
        go.Scatter(
            x=put_v.index,
            y=put_v.values,
            name="Puts",
            mode="lines+markers",
            line=dict(color="#e4003a", 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",
        )
    )
    if imps.PLT_WATERMARK:
        fig.add_layout_image(imps.PLT_WATERMARK)
    fig.update_xaxes(
        range=[min_strike, max_strike],
        constrain="domain",
    )
    fig.update_layout(
        margin=dict(l=0, r=0, t=60, b=20),
        template=imps.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)",
        yaxis=dict(
            fixedrange=False,
            nticks=20,
        ),
        xaxis=dict(
            rangeslider=dict(visible=False),
        ),
        legend=dict(yanchor="top", y=0.99, xanchor="left", x=0.01),
        dragmode="pan",
    )

    imagefile = "opt_vol.png"

    # Check if interactive settings are enabled
    plt_link = ""
    if imps.INTERACTIVE:
        plt_link = imps.inter_chart(fig, imagefile, callback=False)

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

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

    return {
        "title": f"Volume for {ticker.upper()} expiring {expiry}",
        "description": plt_link,
        "imagefile": imagefile,
    }
Beispiel #9
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 imps.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()
    imagefile = "gov_topsells.png"

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

    imagefile = imps.image_border(imagefile, base64=dataBytesIO)

    return {
        "title": f"Stocks: [quiverquant.com] Top sells for {gov_type.upper()}",
        "imagefile": imagefile,
        "description": description,
    }
Beispiel #10
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 imps.DEBUG:
        logger.debug("opt vsurf %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=imps.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,
            )
        ]
    )
    if imps.PLT_WATERMARK:
        fig.add_layout_image(imps.PLT_WATERMARK)
    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=imps.PLT_3DMESH_STYLE_TEMPLATE,
        title=f"{label} Surface for {ticker.upper()}",
        title_x=0.5,
        hoverlabel=imps.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=imps.PLT_3DMESH_SCENE,
    )

    imagefile = "opt-vsurf.png"

    # Check if interactive settings are enabled
    plt_link = ""
    if imps.INTERACTIVE:
        plt_link = imps.inter_chart(fig, imagefile, callback=False)

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

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

    return {
        "title": f"{label} Surface for {ticker.upper()}",
        "description": plt_link,
        "imagefile": imagefile,
    }
Beispiel #11
0
def spos_command(ticker: str = ""):
    """Net short vs position [Stockgrid]"""

    # Debug user input
    if imps.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 imps.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,
    )
    if imps.PLT_WATERMARK:
        fig.add_layout_image(imps.PLT_WATERMARK)

    # 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=imps.PLT_TA_STYLE_TEMPLATE,
        colorway=imps.PLT_TA_COLORWAY,
        title=f"Net Short Vol. vs Position for {ticker}",
        title_x=0.5,
        yaxis_title="<b>Net Short Vol.</b> ($)",
        font=imps.PLT_FONT,
        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",
    )

    imagefile = "dps_spos.png"

    # Check if interactive settings are enabled
    plt_link = ""
    if imps.INTERACTIVE:
        plt_link = imps.inter_chart(fig, imagefile, callback=False)

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

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

    return {
        "title": title,
        "description": plt_link,
        "imagefile": imagefile,
    }
Beispiel #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 imps.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()
    imagefile = "gov_gtrades.png"

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

    imagefile = imps.image_border(imagefile, base64=dataBytesIO)

    return {
        "title": "Stocks: [quiverquant.com] Government Trades",
        "imagefile": imagefile,
    }
Beispiel #13
0
def metric_command(
    finance_key: str,
    finance_metric: str,
    ticker: str = "",
):
    """Display financials bars comparing sectors, industry, analysis, countries, market cap and excluding exchanges.

    Parameters
    ----------
    finance_key: str
        Select finance key from Yahoo Finance(e.g. financialData, defaultKeyStatistics, summaryProfile)
    finance_metric: str
        Select finance metric from Yahoo Finance (e.g. operatingCashflow, revenueGrowth, ebitda, freeCashflow)
    ticker: str
        Company ticker to use as the basis.
    """
    logger.info("metrics")
    exclude_exchanges: bool = True
    limit: int = 10
    ticker = ticker.lower()
    if ticker:
        data = yfinance.utils.get_json(f"https://finance.yahoo.com/quote/{ticker}")

        if "summaryProfile" in data:
            country = data["summaryProfile"]["country"]
            if country not in financedatabase_model.get_countries():
                similar_cmd = difflib.get_close_matches(
                    country,
                    financedatabase_model.get_countries(),
                    n=1,
                    cutoff=0.7,
                )
                if similar_cmd:
                    country = similar_cmd[0]
            sector = data["summaryProfile"]["sector"]
            if sector not in financedatabase_model.get_sectors():
                similar_cmd = difflib.get_close_matches(
                    sector,
                    financedatabase_model.get_sectors(),
                    n=1,
                    cutoff=0.7,
                )
                if similar_cmd:
                    sector = similar_cmd[0]
            industry = data["summaryProfile"]["industry"]
            if industry not in financedatabase_model.get_industries():
                similar_cmd = difflib.get_close_matches(
                    industry,
                    financedatabase_model.get_industries(),
                    n=1,
                    cutoff=0.7,
                )
                if similar_cmd:
                    industry = similar_cmd[0]
            if "price" in data:
                mktcap = data["price"]["marketCap"]
                if mktcap < 2_000_000_000:
                    mktcap = "Small"
                elif mktcap > 10_000_000_000:
                    mktcap = "Large"
                else:
                    mktcap = "Mid"

    stocks_data = financedatabase_model.get_stocks_data(
        country, sector, industry, mktcap, exclude_exchanges
    )

    metric_data = {}
    for symbol in list(stocks_data.keys()):
        if finance_key in stocks_data[symbol] and "quoteType" in stocks_data[symbol]:
            stock_name = stocks_data[symbol]["quoteType"]["longName"]
            metric = (
                stocks_data[symbol][finance_key][finance_metric]
                if stocks_data[symbol][finance_key] is not None
                and finance_metric in stocks_data[symbol][finance_key]
                else None
            )
            if metric and stock_name:
                metric_data[stock_name] = (metric, symbol)

    if len(metric_data) > 1:

        metric_data = dict(
            OrderedDict(
                sorted(metric_data.items(), key=lambda t: t[1][0], reverse=True)
            )
        )

        company_names = list()
        company_metrics = list()
        company_tickers = list()
        for name, metric in metric_data.items():
            company_names.append(name)
            company_metrics.append(metric[0])
            company_tickers.append(metric[1])

        company_name = np.array(company_names)[:limit]
        company_metric = np.array(company_metrics)[:limit]
        company_ticker = np.array(company_tickers)[:limit]

        magnitude = 0
        while max(company_metric) > 1_000 or abs(min(company_metric)) > 1_000:
            company_metric = np.divide(company_metric, 1_000)
            magnitude += 1

        # check if the value is a percentage
        if (magnitude == 0) and all(company_metric >= 0) and all(company_metric <= 1):
            unit = "%"
            company_metric = company_metric * 100

        else:
            unit = " KMBTP"[magnitude]

        colors = [
            "#ffed00",
            "#ef7d00",
            "#e4003a",
            "#c13246",
            "#822661",
            "#48277c",
            "#005ca9",
            "#00aaff",
            "#9b30d9",
            "#af005f",
            "#5f00af",
            "#af87ff",
        ]

        fig = go.Figure()

        i = 0
        for name, metric, tickers in zip(
            company_name[::-1], company_metric[::-1], company_ticker[::-1]
        ):
            if len(name.split(" ")) > 6 and len(name) > 40:
                name = (
                    f'{" ".join(name.split(" ")[:4])}\n{" ".join(name.split(" ")[4:])}'
                )
            df_name = []
            df_metric = []
            df_tickers = []
            df_name.append(name)
            df_metric.append(metric)
            df_tickers.append(tickers)
            fig.add_trace(
                go.Bar(
                    name=tickers,
                    y=[name],
                    x=[metric],
                    orientation="h",
                    marker=dict(
                        color=colors[i],
                        line=dict(color="rgb(248, 248, 249)", width=1),
                    ),
                ),
            )
            i += 1

        metric_title = (
            "".join(
                " " + char if char.isupper() else char.strip()
                for char in finance_metric
            )
            .strip()
            .capitalize()
        )

        benchmark = np.median(company_metric)
        if unit != " ":
            units = f" [{unit}] "
        else:
            units = " "

        title = f"{metric_title.capitalize()}{units}with benchmark of {benchmark:.2f} {unit}<br>"
        title += mktcap + " cap companies " if mktcap else "Companies "
        if industry:
            title += f"in {industry} industry<br>"
        elif sector:
            title += f"in {sector} sector<br>"

        if country:
            title += f"in {country}"
            title += " " if (industry or sector) else "<br>"

        title += (
            "(excl. data from international exchanges)"
            if exclude_exchanges
            else "(incl. data from international exchanges)"
        )
        fig.add_vline(
            x=benchmark,
            fillcolor="grey",
            opacity=1,
            layer="below",
            line_width=3,
            line=dict(color="grey", dash="dash"),
        )
        if imps.PLT_WATERMARK:
            fig.add_layout_image(imps.PLT_WATERMARK)
        fig.update_layout(
            margin=dict(l=40, r=0, t=100, b=20),
            template=imps.PLT_CANDLE_STYLE_TEMPLATE,
            title=title,
            colorway=colors,
            font=imps.PLT_FONT,
            legend={"traceorder": "reversed"},
        )
        imagefile = "sia_metrics.png"

        # Check if interactive settings are enabled
        plt_link = ""
        if imps.INTERACTIVE:
            plt_link = imps.inter_chart(fig, imagefile, callback=False)

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

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

        return {
            "title": "Stocks - Sector and Industry Analysis",
            "description": plt_link,
            "imagefile": imagefile,
        }
Beispiel #14
0
def smile_command(
    ticker: str = None,
    expiry: str = "",
    min_sp: float = None,
    max_sp: float = None,
):
    """Options Smile"""

    # Debug
    if imps.DEBUG:
        logger.debug("opt smile %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)
    calls = options.calls.fillna(0.0)
    puts = options.puts.fillna(0.0)
    current_price = yfinance_model.get_price(ticker)

    min_strike = 0.60 * current_price
    max_strike = 1.95 * current_price

    if len(calls) > 40:
        min_strike = 0.60 * current_price
        max_strike = 1.50 * current_price

    if min_sp:
        min_strike = min_sp
    if max_sp:
        max_strike = max_sp

    fig = go.Figure()

    fig.add_trace(
        go.Scatter(
            x=calls["strike"],
            y=calls["impliedVolatility"].interpolate(method="nearest"),
            name="Calls",
            mode="lines+markers",
            marker=dict(
                color="#00ACFF",
                size=4.5,
            ),
            line=dict(color="#00ACFF", width=2, dash="dash"),
        ))

    fig.add_trace(
        go.Scatter(
            x=puts["strike"],
            y=puts["impliedVolatility"].interpolate(method="nearest"),
            name="Puts",
            mode="lines+markers",
            marker=dict(
                color="#e4003a",
                size=4.5,
            ),
            line=dict(color="#e4003a", width=2, dash="dash"),
        ))

    if imps.PLT_WATERMARK:
        fig.add_layout_image(imps.PLT_WATERMARK)
    fig.update_xaxes(
        range=[min_strike, max_strike],
        constrain="domain",
    )
    fig.update_layout(
        margin=dict(l=20, r=0, t=60, b=20),
        template=imps.PLT_SCAT_STYLE_TEMPLATE,
        font=imps.PLT_FONT,
        title=
        f"<b>Implied Volatility vs. Strike for {ticker.upper()} expiring {expiry}</b>",
        title_x=0.5,
        legend_title="",
        xaxis_title="Strike",
        yaxis_title="Implied Volatility",
        yaxis=dict(
            side="right",
            fixedrange=False,
            nticks=20,
        ),
        xaxis=dict(
            rangeslider=dict(visible=False),
            nticks=20,
        ),
        legend=dict(yanchor="top", y=0.99, xanchor="left", x=0.01),
        dragmode="pan",
    )

    imagefile = "opt_smile.png"

    # Check if interactive settings are enabled
    plt_link = ""
    if imps.INTERACTIVE:
        plt_link = imps.inter_chart(fig, imagefile, callback=False)

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

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

    return {
        "title":
        f"Implied Volatility vs. Stirke for {ticker.upper()} expiring {expiry}",
        "description": plt_link,
        "imagefile": imagefile,
    }
Beispiel #15
0
def qtrcontracts_command(num: int = 20, analysis=""):
    """Displays a look at government contracts [quiverquant.com]"""
    # Debug user input
    if imps.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()
        imagefile = "gov_qtrcontracts.png"

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

        imagefile = imps.image_border(imagefile, base64=dataBytesIO)
        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
Beispiel #16
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 imps.DEBUG:
        logger.info("opt hist %s, %s, %s, %s", 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"

    title = f"{ticker.upper()} {strike} {opt_type} expiring {expiry} Historical"

    fig = make_subplots(
        shared_xaxes=True,
        specs=[[{
            "secondary_y": True
        }]],
    )
    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",
            increasing_line_color="#00ACFF",
            decreasing_line_color="#e4003a",
            showlegend=False,
        ),
        secondary_y=True,
    )
    fig.add_trace(
        go.Bar(
            x=df_hist.index,
            y=df_hist.Volume,
            name="Volume",
            yaxis="y2",
            marker_color="#fdc708",
            opacity=0.3,
            showlegend=False,
        ),
        secondary_y=False,
    )
    if imps.PLT_WATERMARK:
        fig.add_layout_image(imps.PLT_WATERMARK)
    fig.update_layout(
        margin=dict(l=0, r=0, t=25, b=5),
        template=imps.PLT_CANDLE_STYLE_TEMPLATE,
        showlegend=False,
        title=title,
        title_x=0.1,
        title_font_size=14,
        yaxis2_title="Premium",
        yaxis_title="Volume",
        font=imps.PLT_FONT,
        yaxis=dict(
            showgrid=False,
            fixedrange=False,
            side="left",
            titlefont=dict(color="#fdc708", size=12),
            tickfont=dict(
                color="#fdc708",
                size=14,
            ),
            nticks=20,
        ),
        yaxis2=dict(
            side="right",
            fixedrange=False,
            anchor="x",
            layer="above traces",
            overlaying="y",
            nticks=20,
            tickfont=dict(size=14, ),
            showline=False,
        ),
        xaxis=dict(
            rangeslider=dict(visible=False),
            type="date",
        ),
        dragmode="pan",
    )
    fig.update_xaxes(rangebreaks=[
        dict(bounds=["sat", "mon"]),
    ], )

    imagefile = "opt_hist.png"

    # Check if interactive settings are enabled
    plt_link = ""
    if imps.INTERACTIVE:
        plt_link = imps.inter_chart(fig, imagefile, callback=False)

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

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

    return {
        "title": title,
        "description": plt_link,
        "imagefile": imagefile,
    }
Beispiel #17
0
def adx_command(
    ticker="",
    interval: int = 15,
    past_days: int = 0,
    length="14",
    scalar="100",
    drift="1",
    start="",
    end="",
    extended_hours: bool = False,
    heikin_candles: bool = False,
    news: bool = False,
):
    """Displays chart with average directional movement index [Yahoo Finance]"""

    # Debug
    if imps.DEBUG:
        # pylint: disable=logging-too-many-args
        logger.debug(
            "ta adx %s %s %s %s %s %s %s %s %s %s %s",
            ticker,
            interval,
            past_days,
            length,
            scalar,
            drift,
            start,
            end,
            extended_hours,
            heikin_candles,
            news,
        )

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

    # Retrieve Data
    df_stock, start, end, bar_start = load_candle.stock_data(
        ticker=ticker,
        interval=interval,
        past_days=past_days,
        extended_hours=extended_hours,
        start=start,
        end=end,
        heikin_candles=heikin_candles,
    )

    if df_stock.empty:
        raise Exception("No Data Found")

    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)

    df_ta = df_stock.loc[(df_stock.index >= start) & (df_stock.index < end)]

    if df_ta.empty:
        raise Exception("No Data Found")

    ta_data = trend_indicators_model.adx(
        df_stock["High"],
        df_stock["Low"],
        df_stock["Adj Close"],
        length,
        scalar,
        drift,
    )
    df_ta = df_ta.join(ta_data)

    # Output Data
    if interval != 1440:
        df_ta = df_ta.loc[(df_ta.index >= bar_start) & (df_ta.index < end)]
    df_ta = df_ta.fillna(0.0)

    plot = load_candle.candle_fig(
        df_ta,
        ticker,
        interval,
        extended_hours,
        news,
        bar=bar_start,
        int_bar=interval,
        rows=2,
        cols=1,
        shared_xaxes=True,
        vertical_spacing=0.07,
        row_width=[0.4, 0.6],
        specs=[[{
            "secondary_y": True
        }], [{
            "secondary_y": False
        }]],
    )
    title = f"<b>{plot['plt_title']} Average Directional Movement Index</b>"
    fig = plot["fig"]
    idx = 6 if interval != 1440 else 11

    fig.add_trace(
        go.Scatter(
            name=f"ADX ({length})",
            mode="lines",
            x=df_ta.index,
            y=df_ta.iloc[:, idx].values,
            opacity=1,
            line=dict(width=2),
        ),
        secondary_y=False,
        row=2,
        col=1,
    )
    fig.add_trace(
        go.Scatter(
            name=f"+DI ({length})",
            mode="lines",
            x=df_ta.index,
            y=df_ta.iloc[:, (idx + 1)].values,
            opacity=1,
            line=dict(width=1),
        ),
        secondary_y=False,
        row=2,
        col=1,
    )
    fig.add_trace(
        go.Scatter(
            name=f"-DI ({length})",
            mode="lines",
            x=df_ta.index,
            y=df_ta.iloc[:, (idx + 2)].values,
            opacity=1,
            line=dict(width=1),
        ),
        secondary_y=False,
        row=2,
        col=1,
    )
    fig.add_hline(
        y=25,
        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=0, t=50, b=20),
        template=imps.PLT_TA_STYLE_TEMPLATE,
        colorway=imps.PLT_TA_COLORWAY,
        title=title,
        title_x=0.01,
        title_font_size=12,
        dragmode="pan",
    )
    imagefile = "ta_adx.png"

    # Check if interactive settings are enabled
    plt_link = ""
    if imps.INTERACTIVE:
        plt_link = imps.inter_chart(fig, imagefile, callback=False)

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

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

    return {
        "title":
        f"Stocks: Average-Directional-Movement-Index {ticker.upper()}",
        "description": plt_link,
        "imagefile": imagefile,
    }
Beispiel #18
0
def ad_command(
    ticker="",
    interval: int = 15,
    past_days: int = 0,
    is_open: bool = False,
    start="",
    end="",
    extended_hours: bool = False,
    heikin_candles: bool = False,
    news: bool = False,
):
    """Displays chart with accumulation/distribution line [Yahoo Finance]"""

    # Debug
    if imps.DEBUG:
        # pylint: disable=logging-too-many-args
        logger.debug(
            "ta ad %s %s %s %s %s %s %s %s %s",
            ticker,
            interval,
            past_days,
            is_open,
            start,
            end,
            extended_hours,
            heikin_candles,
            news,
        )

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

    # Retrieve Data
    df_stock, start, end, bar_start = load_candle.stock_data(
        ticker=ticker,
        interval=interval,
        past_days=past_days,
        extended_hours=extended_hours,
        start=start,
        end=end,
        heikin_candles=heikin_candles,
    )

    if df_stock.empty:
        raise Exception("No Data Found")

    df_ta = df_stock.loc[(df_stock.index >= start) & (df_stock.index < end)]
    df_ta = df_ta.join(volume_model.ad(df_stock, is_open))

    # Output Data
    if interval != 1440:
        df_ta = df_ta.loc[(df_ta.index >= bar_start) & (df_ta.index < end)]
    df_ta = df_ta.fillna(0.0)

    plot = load_candle.candle_fig(
        df_ta,
        ticker,
        interval,
        extended_hours,
        news,
        bar=bar_start,
        int_bar=interval,
        rows=2,
        cols=1,
        shared_xaxes=True,
        vertical_spacing=0.07,
        row_width=[0.4, 0.6],
        specs=[
            [{
                "secondary_y": True
            }],
            [{
                "secondary_y": False
            }],
        ],
    )
    title = f"<b>{plot['plt_title']} A/D</b>"
    fig = plot["fig"]

    fig.add_trace(
        go.Scatter(
            name="A/D",
            x=df_ta.index,
            y=df_ta.iloc[:, 6].values
            if interval != 1440 else df_ta.iloc[:, 11].values,
            mode="lines",
            line=dict(width=2),
            opacity=1,
        ),
        row=2,
        col=1,
    )
    fig.add_hline(
        y=0,
        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=0, t=50, b=20),
        template=imps.PLT_TA_STYLE_TEMPLATE,
        colorway=imps.PLT_TA_COLORWAY,
        title=title,
        title_x=0.1,
        title_font_size=14,
        dragmode="pan",
    )
    imagefile = "ta_ad.png"

    # Check if interactive settings are enabled
    plt_link = ""
    if imps.INTERACTIVE:
        plt_link = imps.inter_chart(fig, imagefile, callback=False)

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

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

    return {
        "title": f"Stocks: Accumulation/Distribution Line {ticker.upper()}",
        "description": plt_link,
        "imagefile": imagefile,
    }
Beispiel #19
0
def aroon_command(
    ticker="",
    interval: int = 15,
    past_days: int = 0,
    length="25",
    scalar="100",
    start="",
    end="",
    extended_hours: bool = False,
    heikin_candles: bool = False,
    news: bool = False,
):
    """Displays chart with aroon indicator [Yahoo Finance]"""

    # Debug
    if imps.DEBUG:
        logger.debug(
            "ta aroon %s %s %s %s %s, %s, %s, %s, %s, %s",
            ticker,
            interval,
            past_days,
            length,
            scalar,
            start,
            end,
            extended_hours,
            heikin_candles,
            news,
        )

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

    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)

    # Retrieve Data
    df_stock, start, end, bar_start = load_candle.stock_data(
        ticker=ticker,
        interval=interval,
        past_days=past_days,
        extended_hours=extended_hours,
        start=start,
        end=end,
        heikin_candles=heikin_candles,
    )

    if df_stock.empty:
        raise Exception("No Data Found")

    df_ta = df_stock.loc[(df_stock.index >= start) & (df_stock.index < end)]
    df_ta = df_ta.join(
        trend_indicators_model.aroon(df_ta["High"], df_ta["Low"], length,
                                     scalar))

    # Output Data
    if interval != 1440:
        df_ta = df_ta.loc[(df_ta.index >= bar_start) & (df_ta.index < end)]
    df_ta = df_ta.fillna(0.0)

    plot = load_candle.candle_fig(
        df_ta,
        ticker,
        interval,
        extended_hours,
        news,
        bar=bar_start,
        int_bar=interval,
        rows=3,
        cols=1,
        shared_xaxes=True,
        vertical_spacing=0.02,
        row_width=[0.2, 0.2, 0.3],
        specs=[
            [{
                "secondary_y": True
            }],
            [{
                "secondary_y": False
            }],
            [{
                "secondary_y": False
            }],
        ],
    )
    title = f"<b>{plot['plt_title']} Aroon ({length})</b>"
    fig = plot["fig"]
    idx = 6 if interval != 1440 else 11

    fig.add_trace(
        go.Scatter(
            name="Aroon DOWN",
            x=df_ta.index,
            y=df_ta.iloc[:, idx].values,
            opacity=1,
        ),
        row=2,
        col=1,
        secondary_y=False,
    )
    fig.add_trace(
        go.Scatter(
            name="Aroon UP",
            x=df_ta.index,
            y=df_ta.iloc[:, (idx + 1)].values,
            opacity=1,
        ),
        row=2,
        col=1,
        secondary_y=False,
    )
    fig.add_trace(
        go.Scatter(
            name="Aroon OSC",
            x=df_ta.index,
            y=df_ta.iloc[:, (idx + 2)].values,
            opacity=1,
        ),
        row=3,
        col=1,
        secondary_y=False,
    )
    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=0, t=50, b=20),
        template=imps.PLT_TA_STYLE_TEMPLATE,
        colorway=imps.PLT_TA_COLORWAY,
        title=title,
        title_x=0.1,
        title_font_size=14,
        dragmode="pan",
        yaxis=dict(nticks=10),
        yaxis2=dict(nticks=10),
    )
    imagefile = "ta_aroon.png"

    # Check if interactive settings are enabled
    plt_link = ""
    if imps.INTERACTIVE:
        plt_link = imps.inter_chart(fig, imagefile, callback=False)

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

    return {
        "title": f"Stocks: Aroon-Indicator {ticker.upper()}",
        "description": plt_link,
        "imagefile": imagefile,
    }
Beispiel #20
0
def bbands_command(
    ticker="",
    interval: int = 15,
    past_days: int = 0,
    length="20",
    n_std: float = 2.0,
    ma_mode="sma",
    start="",
    end="",
    extended_hours: bool = False,
    heikin_candles: bool = False,
    news: bool = False,
):
    """Displays chart with bollinger bands [Yahoo Finance]"""

    # Debug
    if imps.DEBUG:
        # pylint: disable=logging-too-many-args
        logger.debug(
            "ta bbands %s %s %s %s %s %s %s %s %s %s",
            ticker,
            past_days,
            length,
            n_std,
            ma_mode,
            start,
            end,
            extended_hours,
            heikin_candles,
            news,
        )

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

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

    # Retrieve Data
    df_stock, start, end, bar_start = load_candle.stock_data(
        ticker=ticker,
        interval=interval,
        past_days=past_days,
        extended_hours=extended_hours,
        start=start,
        end=end,
        heikin_candles=heikin_candles,
    )

    if df_stock.empty:
        raise Exception("No Data Found")

    df_ta = df_stock.loc[(df_stock.index >= start) & (df_stock.index < end)]
    df_ta = df_ta.join(
        volatility_model.bbands(df_ta["Adj Close"], ta_length, n_std, ma_mode))

    # Output Data
    if interval != 1440:
        df_ta = df_ta.loc[(df_ta.index >= bar_start) & (df_ta.index < end)]
    df_ta = df_ta.fillna(0.0)

    plot = load_candle.candle_fig(df_ta, ticker, interval, extended_hours,
                                  news)
    title = f"<b>{plot['plt_title']} Bollinger Bands ({ma_mode.upper()})</b>"
    fig = plot["fig"]
    idx = 6 if interval != 1440 else 11

    fig.add_trace(
        go.Scatter(
            name=f"BBU_{length}_{n_std}",
            x=df_ta.index,
            y=df_ta.iloc[:, (idx + 2)].values,
            opacity=1,
            mode="lines",
            line_color="indigo",
        ),
        secondary_y=True,
        row=1,
        col=1,
    )
    fig.add_trace(
        go.Scatter(
            name=f"BBL_{length}_{n_std}",
            x=df_ta.index,
            y=df_ta.iloc[:, idx].values,
            opacity=1,
            mode="lines",
            line_color="indigo",
            fill="tonexty",
            fillcolor="rgba(74, 0, 128, 0.2)",
        ),
        secondary_y=True,
        row=1,
        col=1,
    )
    fig.add_trace(
        go.Scatter(
            name=f"BBM_{length}_{n_std}",
            x=df_ta.index,
            y=df_ta.iloc[:, (idx + 1)].values,
            opacity=1,
            line=dict(
                width=1.5,
                dash="dash",
            ),
        ),
        secondary_y=True,
        row=1,
        col=1,
    )
    fig.update_layout(
        margin=dict(l=0, r=0, t=50, b=20),
        template=imps.PLT_TA_STYLE_TEMPLATE,
        colorway=imps.PLT_TA_COLORWAY,
        title=title,
        title_x=0.1,
        title_font_size=14,
        dragmode="pan",
    )
    imagefile = "ta_bbands.png"

    # Check if interactive settings are enabled
    plt_link = ""
    if imps.INTERACTIVE:
        plt_link = imps.inter_chart(fig, imagefile, callback=False)

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

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

    return {
        "title": f"Stocks: Bollinger-Bands {ticker.upper()}",
        "description": plt_link,
        "imagefile": imagefile,
    }
Beispiel #21
0
def ftd_command(ticker: str = "", start="", end=""):
    """Fails-to-deliver data [SEC]"""

    # Debug user input
    if imps.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, imps.DATE_FORMAT)

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

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

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

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

    ftd_opacity = 0.4 if (start > (datetime.now() - timedelta(days=30))) else 0.6
    ftd_opacity = (
        ftd_opacity if (start > (datetime.now() - timedelta(days=120))) else 0.9
    )

    # 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=True,
    )
    fig.add_trace(
        go.Bar(
            name="FTDs",
            x=ftds_data["SETTLEMENT DATE"],
            y=ftds_data["QUANTITY (FAILS)"],
            yaxis="y2",
            opacity=ftd_opacity,
        ),
        secondary_y=False,
    )
    if imps.PLT_WATERMARK:
        fig.add_layout_image(imps.PLT_WATERMARK)
    fig.update_layout(
        margin=dict(l=0, r=20, t=30, b=20),
        template=imps.PLT_TA_STYLE_TEMPLATE,
        colorway=imps.PLT_TA_COLORWAY,
        title=f"{ticker} Failed-to-deliver",
        title_x=0.5,
        yaxis2_title="<b>Stock Price</b>",
        font=imps.PLT_FONT,
        yaxis2=dict(
            side="left",
            fixedrange=False,
            showgrid=False,
            layer="above traces",
            overlaying="y",
            titlefont=dict(color="#fdc708"),
            tickfont=dict(
                color="#fdc708",
                size=13,
            ),
            nticks=20,
        ),
        yaxis=dict(
            side="right",
            position=0.15,
            fixedrange=False,
            title_text="<b>Shares</b>",
            titlefont=dict(color="#d81aea"),
            tickfont=dict(
                color="#d81aea",
                size=13,
            ),
            nticks=20,
        ),
        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),
        hovermode="x unified",
    )

    imagefile = "dps_ftd.png"

    # Check if interactive settings are enabled
    plt_link = ""
    if imps.INTERACTIVE:
        plt_link = imps.inter_chart(fig, imagefile, callback=False)

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

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

    return {
        "title": f"Stocks: [SEC] Failure-to-deliver {ticker}",
        "description": plt_link,
        "imagefile": imagefile,
    }
Beispiel #22
0
def rsi_command(
    ticker="",
    interval: int = 15,
    past_days: int = 0,
    length="14",
    scalar="100",
    drift="1",
    start="",
    end="",
    extended_hours: bool = False,
    heikin_candles: bool = False,
    news: bool = False,
):
    """Displays chart with relative strength index [Yahoo Finance]"""

    # Debug
    if imps.DEBUG:
        # pylint: disable=logging-too-many-args
        logger.debug(
            "ta rsi %s %s %s %s %s %s",
            ticker,
            interval,
            past_days,
            length,
            scalar,
            drift,
            start,
            end,
            extended_hours,
            heikin_candles,
            news,
        )

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

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

    df_stock, start, end, bar_start = load_candle.stock_data(
        ticker=ticker,
        interval=interval,
        past_days=past_days,
        extended_hours=extended_hours,
        start=start,
        end=end,
        heikin_candles=heikin_candles,
    )

    if df_stock.empty:
        raise Exception("No Data Found")

    df_ta = df_stock.loc[(df_stock.index >= start) & (df_stock.index < end)]
    df_ta = df_ta.join(momentum_model.rsi(df_ta["Adj Close"], length, scalar, drift))

    # Output Data
    if interval != 1440:
        df_ta = df_ta.loc[(df_ta.index >= bar_start) & (df_ta.index < end)]
    df_ta = df_ta.fillna(0.0)

    plot = load_candle.candle_fig(
        df_ta,
        ticker,
        interval,
        extended_hours,
        news,
        bar=bar_start,
        int_bar=interval,
        rows=2,
        cols=1,
        shared_xaxes=True,
        vertical_spacing=0.07,
        row_width=[0.5, 0.6],
        specs=[
            [{"secondary_y": True}],
            [{"secondary_y": False}],
        ],
    )
    title = f"<b>{plot['plt_title']} RSI</b>"
    fig = plot["fig"]

    fig.add_trace(
        go.Scatter(
            name=f"RSI {length}",
            mode="lines",
            x=df_ta.index,
            y=df_ta.iloc[:, 6].values if interval != 1440 else df_ta.iloc[:, 11].values,
            opacity=1,
        ),
        row=2,
        col=1,
        secondary_y=False,
    )
    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=0, t=50, b=20),
        template=imps.PLT_TA_STYLE_TEMPLATE,
        colorway=imps.PLT_TA_COLORWAY,
        title=title,
        title_x=0.1,
        title_font_size=14,
        dragmode="pan",
        yaxis=dict(nticks=15),
        yaxis2=dict(nticks=10),
    )
    imagefile = "ta_rsi.png"

    # Check if interactive settings are enabled
    plt_link = ""
    if imps.INTERACTIVE:
        plt_link = imps.inter_chart(fig, imagefile, callback=False)

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

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

    return {
        "title": f"Stocks: Relative-Strength-Index {ticker.upper()}",
        "description": plt_link,
        "imagefile": imagefile,
    }
Beispiel #23
0
def stoch_command(
    ticker: str = "",
    interval: int = 15,
    past_days: int = 0,
    fast_k="14",
    slow_d="3",
    slow_k="4",
    start="",
    end="",
    extended_hours: bool = False,
    heikin_candles: bool = False,
    news: bool = False,
):
    """Displays chart with stochastic relative strength average [Yahoo Finance]"""

    # Debug
    if imps.DEBUG:
        logger.debug(
            "ta stoch %s %s %s %s %s %s %s %s %s %s %s",
            ticker,
            interval,
            past_days,
            fast_k,
            slow_k,
            slow_d,
            start,
            end,
            extended_hours,
            heikin_candles,
            news,
        )

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

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

    # Retrieve Data
    df_stock, start, end, bar_start = load_candle.stock_data(
        ticker=ticker,
        interval=interval,
        past_days=past_days,
        extended_hours=extended_hours,
        start=start,
        end=end,
        heikin_candles=heikin_candles,
    )

    df_ta = df_stock.loc[(df_stock.index >= start) & (df_stock.index < end)]

    if df_ta.empty:
        raise Exception("No Data Found")

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

    # Output Data
    if interval != 1440:
        df_ta = df_ta.loc[(df_ta.index >= bar_start) & (df_ta.index < end)]
    df_ta = df_ta.fillna(0.0)

    plot = load_candle.candle_fig(
        df_ta,
        ticker,
        interval,
        extended_hours,
        news,
        bar=bar_start,
        int_bar=interval,
        rows=2,
        cols=1,
        shared_xaxes=True,
        vertical_spacing=0.07,
        row_width=[0.4, 0.6],
        specs=[[{
            "secondary_y": True
        }], [{
            "secondary_y": False
        }]],
    )
    title = f"<b>{plot['plt_title']} STOCH RSI</b>"
    fig = plot["fig"]
    idx = 6 if interval != 1440 else 11

    fig.add_trace(
        go.Scatter(
            name=f"%K {fast_k}, {slow_d}, {slow_k}",
            x=df_ta.index,
            y=df_ta.iloc[:, idx].values,
            line=dict(width=1.8),
            mode="lines",
            opacity=1,
        ),
        row=2,
        col=1,
    )
    fig.add_trace(
        go.Scatter(
            name=f"%D {fast_k}, {slow_d}, {slow_k}",
            x=df_ta.index,
            y=df_ta.iloc[:, (idx + 1)].values,
            line=dict(width=1.8, dash="dash"),
            opacity=1,
        ),
        row=2,
        col=1,
    )
    fig.add_hrect(
        y0=80,
        y1=100,
        fillcolor="red",
        opacity=0.2,
        layer="below",
        line_width=0,
        row=2,
        col=1,
    )
    fig.add_hrect(
        y0=0,
        y1=20,
        fillcolor="green",
        opacity=0.2,
        layer="below",
        line_width=0,
        row=2,
        col=1,
    )
    fig.add_hline(
        y=80,
        fillcolor="green",
        opacity=1,
        layer="below",
        line_width=3,
        line=dict(color="red", dash="dash"),
        row=2,
        col=1,
    )
    fig.add_hline(
        y=20,
        fillcolor="green",
        opacity=1,
        layer="below",
        line_width=3,
        line=dict(color="green", dash="dash"),
        row=2,
        col=1,
    )
    fig.update_layout(
        margin=dict(l=0, r=0, t=50, b=20),
        template=imps.PLT_TA_STYLE_TEMPLATE,
        colorway=imps.PLT_TA_COLORWAY,
        title=title,
        title_x=0.01,
        title_font_size=14,
        dragmode="pan",
    )
    imagefile = "ta_stoch.png"

    # Check if interactive settings are enabled
    plt_link = ""
    if imps.INTERACTIVE:
        plt_link = imps.inter_chart(fig, imagefile, callback=False)

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

    return {
        "title":
        f"Stocks: Stochastic-Relative-Strength-Index {ticker.upper()}",
        "description": plt_link,
        "imagefile": imagefile,
    }
Beispiel #24
0
def kc_command(
    ticker="",
    interval: int = 15,
    past_days: int = 0,
    length="20",
    scalar="2",
    ma_mode="sma",
    offset="0",
    start="",
    end="",
    extended_hours: bool = False,
    heikin_candles: bool = False,
    news: bool = False,
):
    """Displays chart with keltner channel [Yahoo Finance]"""

    # Debug
    if imps.DEBUG:
        # pylint: disable=logging-too-many-args
        logger.debug(
            "ta kc %s %s %s %s %s %s %s %s %s %s %s %s",
            ticker,
            interval,
            past_days,
            length,
            scalar,
            ma_mode,
            offset,
            start,
            end,
            extended_hours,
            heikin_candles,
            news,
        )

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

    # Retrieve Data
    df_stock, start, end, bar_start = load_candle.stock_data(
        ticker=ticker,
        interval=interval,
        past_days=past_days,
        extended_hours=extended_hours,
        start=start,
        end=end,
        heikin_candles=heikin_candles,
    )

    if df_stock.empty:
        raise Exception("No Data Found")

    df_ta = df_stock.loc[(df_stock.index >= start) & (df_stock.index < end)]

    if df_ta.empty:
        raise Exception("No Data Found")

    ta_data = volatility_model.kc(
        df_stock["High"],
        df_stock["Low"],
        df_stock["Adj Close"],
        length,
        scalar,
        ma_mode,
        offset,
    )
    df_ta = df_ta.join(ta_data)

    # Output Data
    if interval != 1440:
        df_ta = df_ta.loc[(df_ta.index >= bar_start) & (df_ta.index < end)]
    df_ta = df_ta.fillna(0.0)

    plot = load_candle.candle_fig(
        df_ta,
        ticker,
        interval,
        extended_hours,
        news,
        bar=bar_start,
        int_bar=interval,
        shared_xaxes=True,
        vertical_spacing=0.07,
    )
    title = f"<b>{plot['plt_title']} Keltner Channels ({ma_mode.upper()})</b>"
    fig = plot["fig"]
    idx = 6 if interval != 1440 else 11

    fig.add_trace(
        go.Scatter(
            name="upper",
            x=df_ta.index,
            y=df_ta.iloc[:, (idx + 2)].values,
            opacity=1,
            mode="lines",
            line_color="indigo",
            showlegend=False,
        ),
        row=1,
        col=1,
        secondary_y=True,
    )
    fig.add_trace(
        go.Scatter(
            name="lower",
            x=df_ta.index,
            y=df_ta.iloc[:, idx].values,
            opacity=1,
            mode="lines",
            line_color="indigo",
            fill="tonexty",
            fillcolor="rgba(74, 0, 128, 0.2)",
            showlegend=False,
        ),
        row=1,
        col=1,
        secondary_y=True,
    )
    fig.add_trace(
        go.Scatter(
            name="mid",
            x=df_ta.index,
            y=df_ta.iloc[:, (idx + 1)].values,
            opacity=1,
            line=dict(
                width=1.5,
                dash="dash",
            ),
            showlegend=False,
        ),
        row=1,
        col=1,
        secondary_y=True,
    )
    fig.update_layout(
        margin=dict(l=0, r=0, t=50, b=20),
        template=imps.PLT_TA_STYLE_TEMPLATE,
        colorway=imps.PLT_TA_COLORWAY,
        title=title,
        title_x=0.02,
        title_font_size=14,
        dragmode="pan",
    )
    imagefile = "ta_kc.png"

    # Check if interactive settings are enabled
    plt_link = ""
    if imps.INTERACTIVE:
        plt_link = imps.inter_chart(fig, imagefile, callback=False)

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

    return {
        "title": f"Stocks: Keltner-Channel {ticker.upper()}",
        "description": plt_link,
        "imagefile": imagefile,
    }
Beispiel #25
0
def cps_command(
    country: str,
    mktcap: str = "",
    exclude_exchanges: bool = True,
    raw: bool = False,
    max_sectors_to_display: int = 15,
    min_pct_to_display_sector: float = 0.015,
):
    """Display number of companies per sector in a specific country (and market cap). [Source: Finance Database]

    Parameters
    ----------
    country: str
        Select country to get number of companies by each sector
    mktcap: str
        Select market cap of companies to consider from Small, Mid and Large
    exclude_exchanges : bool
        Exclude international exchanges
    raw: bool
        Output all raw data
    max_sectors_to_display: int
        Maximum number of sectors to display
    min_pct_to_display_sector: float
        Minimum percentage to display sector
    external_axes : Optional[List[plt.Axes]], optional
        External axes (1 axis is expected in the list), by default None
    """

    companies_per_sector = financedatabase_model.get_companies_per_sector_in_country(
        country, mktcap, exclude_exchanges
    )

    companies_per_sector = dict(
        OrderedDict(
            sorted(companies_per_sector.items(), key=lambda t: t[1], reverse=True)
        )
    )

    for key, value in companies_per_sector.copy().items():
        if value == 0:
            del companies_per_sector[key]

    if not companies_per_sector:
        raise Exception("No companies found with these parameters!\n")

    df = pd.DataFrame.from_dict(companies_per_sector, orient="index")

    df.index.name = "Sector"
    df.columns = ["Number of companies"]
    df["Number of companies"] = df["Number of companies"].astype(int)

    title = mktcap + " Cap Companies " if mktcap else "Companies "
    title += f"in {country}"
    title += " Excl. Exchanges" if exclude_exchanges else " incl. Exchanges"
    title = textwrap.fill(title, 40)
    title_plot = textwrap.indent(text=title, prefix="<br>")

    if raw:
        output = {
            "title": "Stocks - Sector and Industry Analysis",
            "description": f"{df}",
        }
    else:

        if len(companies_per_sector) > 1:
            total_num_companies = sum(companies_per_sector.values())
            min_companies_to_represent = round(
                min_pct_to_display_sector * total_num_companies
            )
            filter_sectors_to_display = (
                np.array(list(companies_per_sector.values()))
                > min_companies_to_represent
            )

            if any(filter_sectors_to_display):

                if not all(filter_sectors_to_display):
                    num_sectors_to_display = np.where(~filter_sectors_to_display)[0][0]

                    if num_sectors_to_display < max_sectors_to_display:
                        max_sectors_to_display = num_sectors_to_display

            else:
                raise Exception(
                    "The minimum threshold percentage specified is too high, thus it will be ignored."
                )

            if len(companies_per_sector) > max_sectors_to_display:
                companies_per_sector_sliced = dict(
                    list(companies_per_sector.items())[: max_sectors_to_display - 1]
                )
                companies_per_sector_sliced["Others"] = sum(
                    dict(
                        list(companies_per_sector.items())[max_sectors_to_display - 1 :]
                    ).values()
                )

                legend, values = zip(*companies_per_sector_sliced.items())

            else:
                legend, values = zip(*companies_per_sector.items())

            fig = go.Figure()
            colors = [
                "#ffed00",
                "#ef7d00",
                "#e4003a",
                "#c13246",
                "#822661",
                "#48277c",
                "#005ca9",
                "#00aaff",
                "#9b30d9",
                "#af005f",
                "#5f00af",
                "#af87ff",
            ]

            fig.add_trace(
                go.Pie(
                    labels=legend,
                    values=values,
                    textinfo="label+percent",
                    showlegend=False,
                )
            )
            fig.update_traces(
                textposition="outside",
                textfont_size=15,
                marker=dict(
                    colors=colors,
                    line=dict(color="#F5EFF3", width=0.8),
                ),
            )
            if imps.PLT_WATERMARK:
                fig.add_layout_image(imps.PLT_WATERMARK)
            fig.update_layout(
                margin=dict(l=40, r=0, t=80, b=40),
                title=dict(
                    text=title_plot,
                    y=1,
                    x=0.5,
                    xanchor="center",
                    yanchor="top",
                ),
                template=imps.PLT_CANDLE_STYLE_TEMPLATE,
                colorway=colors,
                font=imps.PLT_FONT,
            )

        elif len(companies_per_sector) == 1:
            raise Exception(
                f"Only 1 sector found '{list(companies_per_sector.keys())[0]}'. No pie chart will be depicted."
            )
        else:
            raise Exception("No sector found. No pie chart will be depicted.")

        imagefile = "sia_cps.png"

        # Check if interactive settings are enabled
        plt_link = ""
        if imps.INTERACTIVE:
            plt_link = imps.inter_chart(fig, imagefile, callback=False)

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

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

        output = {
            "title": "Stocks - Sector and Industry Analysis",
            "description": plt_link,
            "imagefile": imagefile,
        }

    return output
Beispiel #26
0
def dpotc_command(ticker: str = ""):
    """Dark pools (ATS) vs OTC data [FINRA]"""

    # Debug user input
    if imps.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 imps.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,
        )
    if imps.PLT_WATERMARK:
        fig.add_layout_image(imps.PLT_WATERMARK)
    fig.update_layout(
        margin=dict(l=20, r=0, t=10, b=20),
        template=imps.PLT_CANDLE_STYLE_TEMPLATE,
        colorway=imps.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",
        font=imps.PLT_FONT,
        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=1,
        hoverdistance=1,
    )

    imagefile = "dps_dpotc.png"

    # Check if interactive settings are enabled
    plt_link = ""
    if imps.INTERACTIVE:
        plt_link = imps.inter_chart(fig, imagefile, callback=False)

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

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

    return {
        "title": title,
        "description": plt_link,
        "imagefile": imagefile,
    }
Beispiel #27
0
def hist_command(
    ticker: str = "",
    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 imps.DEBUG:
        logger.info("opt grhist %s %s %s %s %s", 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",
            ), )
    if imps.PLT_WATERMARK:
        fig.add_layout_image(imps.PLT_WATERMARK)
    fig.update_layout(
        margin=dict(l=10, r=10, t=30, b=20),
        template=imps.PLT_TA_STYLE_TEMPLATE,
        colorway=imps.PLT_TA_COLORWAY,
        title=title,
        title_x=0.03,
        title_font_size=14,
        yaxis_title="<b>Stock Price</b>",
        font=imps.PLT_FONT,
        yaxis=dict(
            side="right",
            fixedrange=False,
            titlefont=dict(color="#fdc708"),
            tickfont=dict(color="#fdc708"),
            showgrid=False,
            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,
            showgrid=False,
            overlaying="y",
            titlefont=dict(color="#00e6c3"),
            tickfont=dict(color="#00e6c3"),
            nticks=20,
        ),
        hovermode="x unified",
    )

    imagefile = "opt_hist.png"

    # Check if interactive settings are enabled
    plt_link = ""
    if imps.INTERACTIVE:
        plt_link = imps.inter_chart(fig, imagefile, callback=False)

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

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

    return {
        "title":
        f"{ticker.upper()} {strike} {opt_type} expiring {expiry} Historical",
        "description": plt_link,
        "imagefile": imagefile,
    }
Beispiel #28
0
def candle_command(
    ticker: str = "",
    interval: int = 15,
    past_days: int = 0,
    extended_hours: bool = False,
    start="",
    end="",
    news: bool = False,
    heikin_candles: bool = False,
    vwap: bool = False,
):
    """Shows candle plot of loaded ticker or crypto. [Source: Yahoo Finance or Binance API]

    Parameters
    ----------
    ticker : Stock Ticker
    interval : Chart Minute Interval, 1440 for Daily
    past_days: Past Days to Display. Default: 0(Not for Daily)
    extended_hours: Display Pre/After Market Hours. Default: False
    start: YYYY-MM-DD format
    end: YYYY-MM-DD format
    news: Display clickable news markers on interactive chart. Default: False
    heikin_candles: Heikin Ashi candles. Default: False
    """

    logger.info(
        "candle %s %s %s %s %s %s %s %s",
        ticker,
        interval,
        past_days,
        extended_hours,
        start,
        end,
        news,
        heikin_candles,
    )

    # Retrieve Data
    df_stock, start, end, bar_start = load_candle.stock_data(
        ticker=ticker,
        interval=interval,
        past_days=past_days,
        extended_hours=extended_hours,
        start=start,
        end=end,
        news=news,
        heikin_candles=heikin_candles,
    )

    df_stock = df_stock.loc[(df_stock.index >= start) & (df_stock.index < end)]
    df_stock = df_stock.join(overlap_model.vwap(df_stock, 0))

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

    # Output Data
    if interval != 1440:
        df_stock = df_stock.loc[(df_stock.index >= bar_start) & (df_stock.index < end)]

    plot = load_candle.candle_fig(
        df_stock,
        ticker,
        interval,
        extended_hours,
        news,
        bar=bar_start,
        int_bar=interval,
    )
    title = f"{plot['plt_title']} Chart"
    fig = plot["fig"]

    if interval != 1440 and vwap:
        fig.add_trace(
            go.Scatter(
                name="VWAP",
                x=df_stock.index,
                y=df_stock["VWAP_D"],
                opacity=0.65,
                line=dict(color="#00e6c3", width=2),
                showlegend=True,
            ),
            secondary_y=True,
        )

    fig.update_layout(
        margin=dict(l=0, r=0, t=40, b=20),
        template=imps.PLT_CANDLE_STYLE_TEMPLATE,
        title=title,
        title_x=0.5,
        title_font_size=14,
    )
    imagefile = "candle.png"

    # Check if interactive settings are enabled
    plt_link = ""
    if imps.INTERACTIVE:
        plt_link = imps.inter_chart(fig, imagefile, callback=True)

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

    return {
        "title": title,
        "description": plt_link,
        "imagefile": imagefile,
    }
Beispiel #29
0
def options_run(
    ticker,
    url,
    expiry,
    dates,
    df_bcinfo,
    calls,
    puts,
    df_opt,
    current_price,
    min_strike,
    max_strike,
    min_strike2,
    max_strike2,
    max_pain,
):
    """Options Overview"""
    titles, reports, embeds, embeds_img, choices, images_list = [], [], [], [], [], []
    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="#00ACFF", width=3),
        ))

    fig.add_trace(
        go.Scatter(
            x=df_opt.index,
            y=df_opt["OI_put"],
            name="Puts",
            mode="lines+markers",
            line=dict(color="#e4003a", 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}",
        ))
    if imps.PLT_WATERMARK:
        fig.add_layout_image(imps.PLT_WATERMARK)
    fig.update_xaxes(
        range=[min_strike, max_strike],
        constrain="domain",
    )
    fig.update_layout(
        margin=dict(l=0, r=0, t=60, b=20),
        template=imps.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), ),
        font=imps.PLT_FONT,
        legend=dict(yanchor="top", y=0.99, xanchor="left", x=0.01),
        dragmode="pan",
    )

    imagefile = "opt-oi.png"

    plt_link = ""
    if imps.INTERACTIVE:
        plt_link = imps.inter_chart(fig, imagefile, callback=False)
        reports.append(plt_link)

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

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

    if imps.IMAGES_URL or not imps.IMG_HOST_ACTIVE:
        image_link_oi = imps.multi_image(imagefile)
        images_list.append(imagefile)
    else:
        image_link_oi = imps.multi_image(imagefile)

    calls_df = calls[columns].rename(columns=column_map)
    calls_df = calls_df[calls_df["strike"] >= min_strike2]
    calls_df = calls_df[calls_df["strike"] <= max_strike2]
    calls_df["iv"] = pd.to_numeric(calls_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))

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

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

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

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

    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 = imps.plot_df(
            df_calls,
            fig_size=(1000, (40 + (40 * 20))),
            col_width=[3, 3, 3, 3],
            tbl_header=imps.PLT_TBL_HEADER,
            tbl_cells=imps.PLT_TBL_CELLS,
            font=imps.PLT_TBL_FONT,
            row_fill_color=imps.PLT_TBL_ROW_COLORS,
            paper_bgcolor="rgba(0, 0, 0, 0)",
        )
        imagefile = "opt-calls.png"
        imagefile = imps.save_image(imagefile, figc)

        if imps.IMAGES_URL or not imps.IMG_HOST_ACTIVE:
            image_link = imps.multi_image(imagefile)
            images_list.append(imagefile)
        else:
            image_link = imps.multi_image(imagefile)

        embeds_img.append(f"{image_link}", )
        titles.append(f"{pfix}Calls{sfix}", )
        embeds.append(
            disnake.Embed(
                title=f"{pfix}Calls{sfix}",
                colour=imps.COLOR,
            ), )
        i2 += 1
        i += 20
        end += 20

    # 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_df = puts[columns].rename(columns=column_map)

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

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

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

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

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

    # 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 = imps.plot_df(
            df_puts,
            fig_size=(1000, (40 + (40 * 20))),
            col_width=[3, 3, 3, 3],
            tbl_header=imps.PLT_TBL_HEADER,
            tbl_cells=imps.PLT_TBL_CELLS,
            font=imps.PLT_TBL_FONT,
            row_fill_color=imps.PLT_TBL_ROW_COLORS,
            paper_bgcolor="rgba(0, 0, 0, 0)",
        )
        imagefile = "opt-puts.png"
        imagefile = imps.save_image(imagefile, figp)

        if imps.IMAGES_URL or not imps.IMG_HOST_ACTIVE:
            image_link = imps.multi_image(imagefile)
            images_list.append(imagefile)
        else:
            image_link = imps.multi_image(imagefile)

        embeds_img.append(f"{image_link}", )
        titles.append(f"{pfix}Puts{sfix}", )
        embeds.append(
            disnake.Embed(
                title=f"{pfix}Puts{sfix}",
                colour=imps.COLOR,
            ), )
        i2 += 1
        i += 20
        end += 20

    # 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=imps.AUTHOR_NAME,
            url=imps.AUTHOR_URL,
            icon_url=imps.AUTHOR_ICON_URL,
        )
        embeds[i].set_footer(
            text=imps.AUTHOR_NAME,
            icon_url=imps.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=imps.AUTHOR_ICON_URL)

    # Overview Section
    if "^" not in ticker:
        reports.append(
            f"{'':^5}*{df_bcinfo.iloc[0, 0]:^25}*{'':^5}*{df_bcinfo.iloc[1, 0]:^25}*{'':^5}\n"
        )
        reports.append(
            f"{'':^8}{df_bcinfo.iloc[0, 1]:^25}{'':^5}{df_bcinfo.iloc[1, 1]:^25}\n"
        )
        i, i2 = 2, 3
        while i < 11:
            text = (
                f"{'':^5}*{df_bcinfo.iloc[i, 0]:^25}*{'':^5}*{df_bcinfo.iloc[i2, 0]:^25}*{'':^5}\n"
                f"{'':^5}{df_bcinfo.iloc[i, 1]:^30}{'':^5}{df_bcinfo.iloc[i2, 1]:^25}{'':^10}\n"
            )
            reports.append(text)
            i += 1
            i2 += 1

        embeds[0].add_field(name=f"{df_bcinfo.iloc[0, 0]}",
                            value=iv,
                            inline=False)
        embeds[0].add_field(
            name=f"•{df_bcinfo.iloc[1, 0]}",
            value=f"```css\n{df_bcinfo.iloc[1, 1]}\n```",
            inline=True,
        )

        for N in range(2, 6):
            embeds[0].add_field(
                name=f"_ _ _ _ _ _ _ _ _ _ •{df_bcinfo.iloc[N, 0]}",
                value=f"```css\n{df_bcinfo.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_bcinfo.iloc[N, 0]}",
                value=f"```css\n{df_bcinfo.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_bcinfo.iloc[N, 0]}",
                value=f"```css\n{df_bcinfo.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_bcinfo.iloc[N, 0]}",
                value=f"```css\n{df_bcinfo.iloc[N, 1]}\n```",
                inline=True,
            )

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

    return titles, reports, embeds, choices, embeds_img, images_list
Beispiel #30
0
def cpi_command(start=""):
    """Displays Consumer Prices Index (CPI)"""

    # Debug
    if imps.DEBUG:
        logger.debug(
            "econ cpi %s",
            start,
        )

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

    # Retrieve data
    df_d = ("date", "CPI")
    series_ids = list(df_d)
    data = pd.DataFrame()

    for s_id in series_ids:
        data = pd.concat(
            [
                data,
                pd.DataFrame(fred_model.get_series_data("CPIAUCSL", start),
                             columns=[s_id]),
            ],
            axis=1,
        )

    df = data.dropna()

    # Check for argument
    if df.empty:
        raise Exception("No available data found")

    data["date"] = pd.to_datetime(data["date"])
    data["CPI"] = data["CPI"].astype(float)
    data = data.drop(columns=["CPI"])
    end = datetime.now() + timedelta(days=30)

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

    fig = go.Figure()

    fig.add_trace(go.Scatter(
        x=df.index,
        y=df["CPI"],
    ))

    if imps.PLT_WATERMARK:
        fig.add_layout_image(imps.PLT_WATERMARK)

    fig.update_xaxes(dtick="M2", tickformat="%b\n%Y")
    fig.update_layout(
        xaxis_range=[df.index[0], end],
        margin=dict(l=0, r=0, t=40, b=50),
        template=imps.PLT_SCAT_STYLE_TEMPLATE,
        colorway=imps.PLT_TA_COLORWAY,
        title="CPI Monthly",
        title_x=0.5,
        yaxis_title="Consumer Prices",
        legend_title="",
        font=imps.PLT_FONT,
        yaxis=dict(
            fixedrange=False,
            nticks=20,
        ),
        xaxis=dict(
            rangeslider=dict(visible=False),
            type="date",
        ),
        legend=dict(yanchor="top", y=0.99, xanchor="left", x=0.01),
        dragmode="pan",
    )

    imagefile = "econ-cpi.png"

    # Check if interactive settings are enabled
    plt_link = ""
    if imps.INTERACTIVE:
        plt_link = imps.inter_chart(fig, imagefile, callback=False)

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

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

    return {
        "title": "Consumer Prices Index",
        "description": plt_link,
        "imagefile": imagefile,
    }