Exemple #1
0
    def __init__(self, initial: Price):
        super().__init__(initial)
        mod: Modifier
        parent: Modifier

        # Slice 2: InitialDecay
        mod = InitialDecay(self.initial, None)
        self.timeline[TimePeriod(2)] = mod
        parent = mod

        # Slices 3-13: Decay
        for i in range(3, 14):
            time = TimePeriod(i)
            mod = SlowDecay(self.initial, parent)
            self.timeline[time] = mod
            parent = mod
Exemple #2
0
    def __init__(self,
                 initial: 'Price',
                 pattern_start: int):

        low = self._pattern_earliest
        high = self._pattern_latest
        if not low <= pattern_start <= high:
            raise ValueError(f"pattern_start must be between {low} and {high}, inclusive")

        super().__init__(initial)
        self._pattern_start = pattern_start
        self._pattern_peak = TimePeriod(pattern_start + self._peak_time)
        self._tail = 9 - pattern_start
Exemple #3
0
    def __init__(self,
                 initial: 'Price',
                 pattern_start: int):

        super().__init__(initial, pattern_start)

        chain: List[Modifier] = []
        decay_class: Type[Modifier]

        def _push_node(mod_cls: Type[Modifier],
                       parent_override: Optional[Modifier] = None) -> Modifier:
            if parent_override is None:
                my_parent = chain[-1] if chain else None
            else:
                my_parent = parent_override
            mod = mod_cls(self.initial, my_parent)
            chain.append(mod)
            return mod

        decay_class = WideLoss
        for _ in range(2, pattern_start):
            _push_node(decay_class)
            decay_class = SlowDecay

        # Pattern starts:
        _push_node(SmallProfit)
        _push_node(SmallProfit)

        # And then gets weird!
        # Create an unlisted parent that represents the peak shared across the next three prices.
        cap = MediumProfit(self.initial, chain[-1])
        _push_node(CappedPassthrough, cap).sub1 = True
        _push_node(Passthrough, cap)
        _push_node(CappedPassthrough, cap).sub1 = True

        # Alright, phew.
        decay_class = WideLoss
        for _ in range(0, self._tail):
            _push_node(decay_class)
            decay_class = SlowDecay

        # Build timeline
        assert len(chain) == 12
        for i, mod in enumerate(chain):
            time = TimePeriod(i + 2)
            self.timeline[time] = mod
Exemple #4
0
    def __init__(self,
                 initial: 'Price',
                 pattern_start: int):

        super().__init__(initial, pattern_start)

        def _get_pattern(value: int) -> Type[Modifier]:
            # The default:
            cls: Type[Modifier] = SlowDecay

            # Pattern takes priority:
            if value == pattern_start:
                cls = SmallProfit
            elif value == pattern_start + 1:
                cls = MediumProfit
            elif value == pattern_start + 2:
                cls = LargeProfit
            elif value == pattern_start + 3:
                cls = MediumProfit
            elif value == pattern_start + 4:
                cls = SmallProfit
            elif value >= pattern_start + 5:
                # Week finishes out with independent low prices
                cls = WideLoss
            elif value == 2:
                # Normal start-of-week pattern
                cls = InitialDecay

            return cls

        parent = None
        # Slices 2-13: Magic!
        for i in range(2, 14):
            time = TimePeriod(i)
            mod = _get_pattern(i)(self.initial, parent)
            self.timeline[time] = mod
            parent = mod
Exemple #5
0
def plot_models_range(name: str,
                      models: Sequence[Model],
                      previous: ModelEnum,
                      add_points: bool = False) -> None:
    '''
    Plot a fill_between for all models' low and high values using an
    alpha (transparency) equal to 1/num_models. Plot a regular line
    for all fixed prices.

    Shows ~probability of various prices based on your possible models.
    '''

    colors = {
        TRIPLE: 'orange',
        SPIKE:  'green',
        DECAY:  'red',
        BUMP:   'blue',
    }

    _fig, ax = plt.subplots()

    # cosmetics
    ax.set_title(f'Island {name}: current: !!ERROR!!; Last: {previous.name}')
    ax.set_ylabel('Turnip Price')
    ax.set_xticklabels(['Mon AM', 'Mon PM', 'Tue AM', 'Tue PM', 'Wed AM', 'Wed PM',
                        'Thu AM', 'Thu PM', 'Fri AM', 'Fri PM', 'Sat AM', 'Sat PM'])
    ax.xaxis.set_ticks(range(2, 14))
    plt.xticks(rotation=45)
    plt.grid(axis='both', which='both', ls='--')
    ax.set_ylim(0, 660)
    plt.tight_layout()

    if len(models) == 0:
        return

    a_model = models[0]

    continuous_priced_days = []
    continuous_priced_chunk = set()
    continuous_unpriced_days = []
    continuous_unpriced_chunk = set()
    for day in range(2, 14):
        # does this day have data?
        if a_model.timeline[TimePeriod(day)].price.is_atomic:
            # is tomorrow a valid day to have data?
            if day < 13:
                # does tomorrow have data?
                if a_model.timeline[TimePeriod(day + 1)].price.is_atomic:
                    # build onto the chunk
                    continuous_priced_chunk.update([day, day + 1])
                # chunk broken.
                else:
                    continuous_priced_chunk.update([day])
                    continuous_priced_days.append(list(continuous_priced_chunk))
                    continuous_priced_chunk = set()
            else:
                # end of the week, finish the priced_days
                continuous_priced_days.append(list(continuous_priced_chunk))
        # today does not have data
        else:
            # is tomorrow a valid day to have data?
            if day < 13:
                # does it?
                if not a_model.timeline[TimePeriod(day + 1)].price.is_atomic:
                    # build the chunk
                    if day != 2:
                        # add yesterday unless today is monday_am
                        continuous_unpriced_chunk.update([day - 1, day, day + 1])
                    else:
                        continuous_unpriced_chunk.update([day, day + 1])
                # chunk broken
                else:
                    if day != 2:
                        continuous_unpriced_chunk.update([day - 1, day, day + 1])
                    else:
                        continuous_unpriced_chunk.update([day, day + 1])
                    continuous_unpriced_days.append(list(sorted(continuous_unpriced_chunk, key=lambda x: x)))
                    continuous_unpriced_chunk = set()
            else:
                # end of the week, finish the unpriced_days
                continuous_unpriced_days.append(list(continuous_unpriced_chunk))

    for chunk in continuous_priced_days:
        vals = [a_model.timeline[TimePeriod(day)].price.value for day in chunk]
        plt.plot(chunk, vals, c='black')

    model_counts = Counter(x.model_type for x in models)
    remaining_model_types = model_counts.keys()
    remaining_probability = sum(MARKOV[previous][rem_mod]
                                for rem_mod in remaining_model_types)
    adjusted_priors = {model: MARKOV[previous][model] / remaining_probability
                       for model in model_counts.keys()}

    for chunk in continuous_unpriced_days:
        if len(chunk) == 1:
            # if this is one day of unpriced data, connect it to the neighbors.
            value = chunk[0]
            chunk = [value - 1, value, value + 1]
        for model in models:
            low_vals = [model.timeline[TimePeriod(day)].price.lower for day in chunk]
            high_vals = [model.timeline[TimePeriod(day)].price.upper for day in chunk]

            if previous != ModelEnum.unknown:
                alpha = adjusted_priors[model.model_type] / model_counts[model.model_type]
            else:
                alpha = 1 / len(models)

            plt.fill_between(chunk, low_vals, high_vals, alpha=alpha, color=colors[model.model_type])

            if add_points:
                plt.scatter(chunk, low_vals, c='black', s=2)
                plt.scatter(chunk, high_vals, c='black', s=2)

    # cosmetics
    msummary = '+'.join(['{}_{{{}}}^{{{:.2f}}}'.format(t, l.name, adjusted_priors[l])
                         for l, t in model_counts.items()])
    ax.set_title(f'Island {name}: ${len(models)}_{{total}}={msummary}$, Last: {previous.name}')
Exemple #6
0
    def __init__(self,
                 initial: Price,
                 length_phase1: int,
                 length_decay1: int,
                 length_phase2: int):

        super().__init__(initial)

        if not 0 <= length_phase1 <= 6:
            raise ValueError("Phase1 length must be between [0, 6]")
        self._length_phase1 = length_phase1

        if not 2 <= length_decay1 <= 3:
            raise ValueError("Decay1 length must be 2 or 3")
        self._length_decay1 = length_decay1
        self._length_decay2 = 5 - length_decay1

        remainder = 7 - length_phase1
        if not 1 <= length_phase2 <= remainder:
            raise ValueError(f"Phase2 must be between [1, {remainder}]")
        self._length_phase2 = length_phase2
        self._length_phase3 = remainder - length_phase2

        assert (self._length_phase1
                + self._length_phase2
                + self._length_phase3
                + self._length_decay1
                + self._length_decay2) == 12

        chain: List[Modifier] = []
        decay_class: Type[Modifier]

        def _push_node(mod_cls: Type[Modifier]) -> None:
            mod = mod_cls(self.initial, chain[-1] if chain else None)
            chain.append(mod)

        # Phase 1 [0, 6]
        for _ in range(0, self._length_phase1):
            _push_node(SmallProfit)

        # Decay 1 [2, 3]
        decay_class = MediumLoss
        for _ in range(0, self._length_decay1):
            _push_node(decay_class)
            decay_class = RapidDecay

        # Phase 2 [1, 6]
        for _ in range(0, self._length_phase2):
            _push_node(SmallProfit)

        # Decay 2 [2, 3]
        decay_class = MediumLoss
        for _ in range(0, self._length_decay2):
            _push_node(decay_class)
            decay_class = RapidDecay

        # Phase 3 [0, 6]
        for _ in range(0, self._length_phase3):
            _push_node(SmallProfit)

        # Build timeline
        assert len(chain) == 12
        for i, mod in enumerate(chain):
            time = TimePeriod(i + 2)
            self.timeline[time] = mod