コード例 #1
0
def _plot_current_prices(plot_prices: plt.Subplot,
                         ticker: models.Ticker) -> int:
    current_period = -1
    prices: List[Optional[int]] = [
        None for _ in range(0, PRICE_PERIOD_COUNT + 2)
    ]
    if ticker.purchase_price != 0:
        prices[0] = ticker.purchase_price

    for i in range(0, PRICE_PERIOD_COUNT):
        try:
            this_price = ticker.prices[i]
        except IndexError:
            continue

        if this_price != 0:
            prices[i + 1] = this_price

            current_period = i

    if ticker.current_period > current_period:
        current_period = ticker.current_period

    plot_prices.step(
        [i for i in range(-1, PRICE_PERIOD_COUNT + 1)],
        prices,
        where="mid",
        linestyle="--",
        linewidth=4,
        dash_capstyle="projecting",
        color=colors.CURRENT_PRICE_COLOR,
    )

    # Annotate the prices
    for i, this_price in enumerate(ticker.prices):
        # Zero means unknown, skip it.
        if this_price == 0:
            continue

        plot_prices.annotate(
            str(this_price),
            (i, this_price),
            textcoords="offset points",
            xytext=(0, 10),
            ha="center",
            va="bottom",
            fontsize=LABEL_SIZE * 1.2,
            color=colors.CURRENT_PRICE_COLOR,
        )

    return current_period
コード例 #2
0
def _create_price_watermark(
    plot: plt.Subplot,
    name: str,
    price: int,
    va_top: bool,
    pattern: Optional["models.PricePatterns"],
) -> None:
    y_text_offset = 5

    if va_top:
        vertical_alignment = "top"
        y_text_offset *= -1
    else:
        vertical_alignment = "bottom"

    if pattern is None:
        pattern_color = colors.CURRENT_PRICE_COLOR
    else:
        pattern_color = colors.PATTERN_COLORS[pattern]

    # Create a dotted line line at the break-even point that matches the price
    # progression
    price_line = mlines.Line2D(
        [0, 4],
        [price, price],
        color=pattern_color,
        linewidth=2,
        linestyle="--",
    )
    plot.add_line(price_line)

    plot.annotate(
        f"{name}: {price}",
        (2, price),
        textcoords="offset points",
        xytext=(0, y_text_offset),
        horizontalalignment="center",
        verticalalignment=vertical_alignment,
        color=pattern_color,
        fontsize=LABEL_SIZE,
        bbox={
            "boxstyle": "Square,pad=0.3",
            "facecolor": colors.color(0, 0, 0, alpha=0.08),
            "edgecolor": "none",
            "linewidth": 0,
        },
    )
コード例 #3
0
def _create_pattern_line(
    price_plot: plt.Subplot,
    spike_breakdown: List[float],
    spike_pattern: models.PotentialPattern,
    spike_color: List[float],
) -> None:
    """Create a dashed line on the max price for periods with a potential spike"""
    # get highest possible price for each period

    first_period = spike_pattern.spike.start
    last_period = spike_pattern.spike.end
    high_price = spike_pattern.prices_summary.max

    period_highs: List[Optional[int]] = [
        high_price for _ in range(first_period, last_period + 1)
    ]
    price_periods: List[float] = [
        p for p in range(first_period, last_period + 1)
    ]

    # Instead of using a plot, we are just going to draw the line directly.
    # Create a line at the head of the current price period
    current_period_line = mlines.Line2D(
        [first_period - 0.5, last_period + 0.5],
        [high_price, high_price],
        color=spike_color,
        linestyle="--",
        linewidth=4,
        # We want this line to be always visible so our alpha floor is going to be .1
        alpha=max(utils.chance_alpha(spike_pattern.chance), 0.1),
    )
    price_plot.add_line(current_period_line)

    y_annotation_distance = 10

    for period in price_periods:
        if period == 11.5:
            continue

        try:
            chance = spike_breakdown[int(period)]
        except TypeError:
            # If this is period '11.5', then we don't need to annotate it, that value
            # is just here for line continuation
            continue

        # We need to render the numbers ABOVE the spike patter so that they don't
        # get illegible as the spike placement becomes more certain.
        price_plot.annotate(
            utils.format_chance(chance),
            (period, high_price),
            textcoords="offset points",
            xytext=(0, y_annotation_distance),
            ha="center",
            va="bottom",
            fontsize=LABEL_SIZE,
            color=spike_color,
        )

    # Annotate the total chance of this spike
    price_plot.annotate(
        utils.format_chance(spike_pattern.chance),
        (first_period - 0.5 - 0.1, high_price),
        ha="right",
        va="center",
        fontsize=LABEL_SIZE,
        color="white",
        alpha=0.75,
        bbox={
            "boxstyle": "Circle,pad=0.6",
            "facecolor": colors.color(*spike_color),
            "edgecolor": spike_color,
            "linewidth": 0,
        },
    )

    # Add a label to the daily chances for clarity
    middle = first_period + (last_period - first_period) / 2
    middle_price = next(p for p in period_highs if p)

    price_plot.annotate(
        "daily:",
        (middle, middle_price + y_annotation_distance * 2.5),
        textcoords="offset points",
        xytext=(0, y_annotation_distance),
        ha="center",
        va="bottom",
        fontsize=LABEL_SIZE * 1.1,
        color=spike_color,
    )
コード例 #4
0
def plot_pattern_chances(plot: plt.Subplot, forecast: models.Forecast) -> None:
    total = 0.0

    valid_patterns = sorted(
        (x for x in forecast.patterns if x.chance != 0),
        key=lambda x: x.chance,
        reverse=True,
    )

    for i, potential_pattern in enumerate(valid_patterns):
        if i > 0:
            # Add a little bit of space between sections
            total += 0.01

        chance = potential_pattern.chance
        # If the chance gets below 2.5%, the bar disappears, so we need to have a
        # minimum visual value for it.
        adjusted_chance = max(potential_pattern.chance, 0.015)

        pattern_color = colors.PATTERN_COLORS[potential_pattern.pattern]

        plot.barh(
            0.5,
            height=0.8,
            width=adjusted_chance,
            left=total,
            color=colors.color(*pattern_color, alpha=chance),
            linewidth=0,
        )

        patten_name = PATTERN_NAMES[potential_pattern.pattern]
        plot.annotate(
            f"{patten_name}: {utils.format_chance(chance)}",
            (total + (adjusted_chance / 2), 0.5),
            color="white",
            alpha=0.75,
            fontsize=LABEL_SIZE * chance**0.9 + LABEL_SIZE / 2,
            fontweight="bold",
            ha="center",
            va="center",
        )
        total += adjusted_chance

    plot.set_xlim((0, total))
    plot.set_ylim((0, 1))

    # 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 spine in plot.spines.values():
        spine.set_visible(False)