def _create_weekday_grid(weekday_labels: plt.Subplot, ) -> None:
    weekday_labels.grid(
        axis="x",
        linestyle="-",
        linewidth=2,
        color=colors.DAY_GRID_COLOR,
        alpha=colors.DAY_GRID_ALPHA,
        zorder=1,
    )
def plot_price_periods(
    plot_prices: plt.Subplot,
    options: ForecastOptions,
) -> None:

    # set bg color for all graphs
    for plot in [plot_prices]:
        plot.set_facecolor(options.bg_color)
        # Remove all spines
        for spine in plot.spines.values():
            spine.set_visible(False)

    plot_prices.set_facecolor(options.bg_color)
    plot_prices.set_ylim(PRICE_Y_LIM)
    plot_prices.set_xlim([-1, 12])
    plot_prices.axes.set_yticks(np.arange(0, 701, 100))

    plot_prices.grid(
        axis="y",
        linestyle="-",
        linewidth=0.5,
        color=colors.PRICE_GRID_COLOR,
        alpha=colors.PRICE_GRID_ALPHA,
    )

    forecast = options.forecast
    for pattern in forecast.patterns:
        for week in pattern.potential_weeks:
            _create_week_area(plot_prices, week, pattern.pattern)

    big_pattern = utils.get_pattern(forecast, models.PricePatterns.BIGSPIKE)
    if big_pattern.chance > 0:
        _create_pattern_line(
            plot_prices,
            spike_breakdown=[x for x in forecast.spikes.big.breakdown],
            spike_pattern=big_pattern,
            spike_color=colors.BIG_SPIKE_COLOR,
        )

    small_pattern = utils.get_pattern(forecast,
                                      models.PricePatterns.SMALLSPIKE)
    if small_pattern.chance > 0:
        _create_pattern_line(
            plot_prices,
            spike_breakdown=[x for x in forecast.spikes.small.breakdown],
            spike_pattern=small_pattern,
            spike_color=colors.SMALL_SPIKE_COLOR,
        )

    bottom_axis = plot_prices.axes
    # the x locations for the bars
    indTods = np.arange(PRICE_PERIOD_COUNT)
    # Add the time of day labels for each bar
    bottom_axis.axes.set_xlim(plot_prices.get_xlim())
    bottom_axis.axes.set_xticks(indTods)
    bottom_axis.axes.set_xticklabels(PRICE_TODS)
    bottom_axis.spines["bottom"].set_position(("axes", -0.01))

    # Create weekday labels
    weekday_labels = bottom_axis.twiny()
    # We need to make sure the limits match to line up with the bars
    weekday_labels.set_xlim(plot_prices.get_xlim())
    # Place the weekdays between the AM / PM values
    weekday_labels.set_xticks([0.5, 2.5, 4.5, 6.5, 8.5, 10.5])
    # Set the labels
    weekday_labels.set_xticklabels(PRICE_DAYS)
    # Move the weekday labels down a littls
    weekday_labels.spines["bottom"].set_position(("axes", -0.06))
    _create_weekday_grid(weekday_labels)

    # style price axes
    plot_prices.tick_params(
        axis="y",
        labelcolor=colors.PRICE_LABEL_COLOR,
        labelsize=LABEL_SIZE,
        labeltop=False,
        labelbottom=False,
        labelright=True,
        labelleft=True,
        bottom=False,
        top=False,
        left=False,
    )

    # style TOD labels
    bottom_axis.tick_params(
        axis="x",
        labelcolor=colors.DAY_LABEL_COLOR,
        labelsize=LABEL_SIZE,
        labeltop=False,
        labelbottom=True,
        labelright=False,
        labelleft=False,
        bottom=False,
        top=False,
        left=False,
    )

    # style weekday labels
    weekday_labels.tick_params(
        axis="both",
        labelcolor=colors.DAY_LABEL_COLOR,
        labelsize=LABEL_SIZE,
        labelbottom=True,
        labeltop=False,
        bottom=False,
        top=False,
        left=False,
    )

    # Style tod and day label for current price period
    current_period = _plot_current_prices(plot_prices, options.ticker)
    if current_period != -1:
        bbox = dict(
            boxstyle="round,pad=0.5",
            color=colors.DAY_LABEL_COLOR,
        )
        current_tod_label = bottom_axis.xaxis.get_ticklabels()[current_period]
        current_tod_label.set_color("white")
        current_tod_label.set_bbox(bbox)

    _add_cursor(plot_prices, current_period)

    all_spines = itertools.chain(
        plot_prices.spines.values(),
        weekday_labels.spines.values(),
    )
    for spine in all_spines:
        spine.set_visible(False)
Example #3
0
def plot_prices_range(
    plot: plt.Subplot,
    ticker: models.Ticker,
    forecast: models.Forecast,
) -> None:
    max_pattern = models.PricePatterns.UNKNOWN
    guaranteed_pattern = models.PricePatterns.UNKNOWN
    min_pattern = models.PricePatterns.UNKNOWN

    break_even = ticker.purchase_price

    plot.axes.set_ylim(PRICE_Y_LIM)
    plot.axes.set_xlim([0, 4])

    bar_anchors = np.arange(4)

    for i, potential_pattern in enumerate(forecast.patterns):
        bar_position = bar_anchors[i]

        if len(potential_pattern.potential_weeks) == 0:
            continue

        min_price = potential_pattern.prices_future.min
        max_price = potential_pattern.prices_future.max

        pattern_color = colors.PATTERN_COLORS[potential_pattern.pattern]
        bar_color = colors.color(*pattern_color,
                                 alpha=potential_pattern.chance)

        plot.bar(
            [bar_position],
            [max_price - min_price],
            bottom=min_price,
            width=0.4,
            align="edge",
            color=bar_color,
        )

        if potential_pattern.prices_future.max == forecast.prices_future.max:
            max_pattern = potential_pattern.pattern

        if (potential_pattern.prices_future.guaranteed ==
                forecast.prices_future.guaranteed):
            guaranteed_pattern = potential_pattern.pattern

        if potential_pattern.prices_future.min == forecast.prices_future.min:
            min_pattern = potential_pattern.pattern

    # Create a price grid that matches the price progression
    plot.grid(
        axis="y",
        linestyle="-",
        linewidth=0.5,
        color=colors.PRICE_GRID_COLOR,
        alpha=colors.PRICE_GRID_ALPHA,
    )

    # Create a dotted line line at the breakeven point that matches the price
    # progression
    if break_even != 0:
        _create_price_watermark(plot,
                                "break-even",
                                break_even,
                                va_top=False,
                                pattern=None)

    # Create a dotted line line at the max profit point
    _create_price_watermark(
        plot,
        "potential",
        forecast.prices_future.max,
        va_top=False,
        pattern=max_pattern,
    )

    # Create a dotted line line at the max guaranteed point
    _create_price_watermark(
        plot,
        "guaranteed",
        forecast.prices_future.guaranteed,
        va_top=True,
        pattern=guaranteed_pattern,
    )

    if forecast.prices_summary.min != forecast.prices_summary.guaranteed:
        # Create a dotted line line at the min price
        _create_price_watermark(
            plot,
            "minimum",
            forecast.prices_future.min,
            va_top=True,
            pattern=min_pattern,
        )

    # remove axis labels
    plot.tick_params(
        axis="both",
        labeltop=False,
        labelbottom=False,
        labelright=False,
        labelleft=False,
        top=False,
        bottom=False,
        left=False,
        right=False,
    )

    plot.patch.set_visible(False)
    for position, spine in plot.spines.items():
        spine.set_visible(False)