Ejemplo n.º 1
0
    def evaluate_fitness(self, tickers: Tuple[str, ...], end: pd.Timestamp) -> float:
        """Вычисляет качество организма.

        Если осуществлялась оценка для указанных тикеров и даты - используется сохраненное значение. Если
        существует натренированная модель для указанных тикеров - осуществляется оценка без тренировки.
        В ином случае тренируется и оценивается с нуля.
        """
        tickers = list(tickers)
        data = self._data
        data.wins += 1

        if data.date == end and data.tickers == tickers:
            data.save()
            return data.llh

        pickled_model = data.model
        if data.tickers != tickers:
            pickled_model = None

        timer = time.monotonic_ns()
        model = Model(tuple(tickers), end, self.genotype.get_phenotype(), pickled_model)
        llh = model.llh
        timer = time.monotonic_ns() - timer

        data.llh = llh
        data.model = bytes(model)
        data.date = end
        data.tickers = tickers

        if pickled_model is None:
            data.timer = timer

        data.save()
        return llh
Ejemplo n.º 2
0
    def evaluate_fitness(self, tickers: tuple[str, ...],
                         end: pd.Timestamp) -> float:
        """Вычисляет качество организма.

        Если осуществлялась оценка для указанных тикеров и даты - используется сохраненное значение. Если
        существует натренированная модель для указанных тикеров - осуществляется оценка без тренировки.
        В ином случае тренируется и оценивается с нуля.
        """
        tickers = list(tickers)
        doc = self._doc
        doc.wins += 1

        timer = time.monotonic_ns()
        model = Model(tuple(tickers), end, self.genotype.get_phenotype())
        llh = model.llh
        timer = time.monotonic_ns() - timer

        doc.llh = llh
        doc.model = bytes(model)
        doc.date = end
        doc.tickers = tickers

        doc.timer = timer

        doc.save()
        return llh
Ejemplo n.º 3
0
    def evaluate_fitness(self, tickers: tuple[str, ...],
                         end: pd.Timestamp) -> list[float]:
        """Вычисляет качество организма.

        В первый вызов для нового дня используется метрика существующей натренированной модели.
        При последующих вызовах в течение дня выбрасывается ошибка.
        """
        if end == self.date:
            raise ReevaluationError

        tickers = list(tickers)
        doc = self._doc

        pickled_model = None
        if doc.date is not None and doc.date < end and tickers == doc.tickers:
            pickled_model = doc.model

        timer = time.monotonic_ns()
        model = Model(tuple(tickers), end, self.genotype.get_phenotype(),
                      pickled_model)
        llh, ir = model.quality_metrics

        if pickled_model is None:
            doc.timer = time.monotonic_ns() - timer

        doc.llh = [llh] + doc.llh
        doc.wins = len(doc.llh)
        doc.ir = [ir] + doc.ir

        doc.model = bytes(model)

        doc.date = end
        doc.tickers = tickers

        doc.save()

        return self.llh
Ejemplo n.º 4
0
class Organism:
    """Организм и основные операции с ним.

    Умеет рассчитывать качество организма для проведения естественного отбора, умирать, размножаться и
    отображать количество пройденных оценок качества.
    """

    def __init__(
            self, *, _id: Optional[bson.ObjectId] = None, genotype: Optional[Genotype] = None,
    ):
        self._data = store.Doc(id_=_id, genotype=genotype)

    def __str__(self) -> str:
        return str(self._data.genotype)

    @property
    def id(self) -> bson.ObjectId:
        """ID организма."""
        return self._data.id

    @property
    def genotype(self) -> Genotype:
        """Генотип организма."""
        return self._data.genotype

    @property
    def timer(self) -> float:
        """Генотип организма."""
        return self._data.timer

    @property
    def wins(self) -> int:
        """Количество побед."""
        return self._data.wins

    def evaluate_fitness(self, tickers: Tuple[str, ...], end: pd.Timestamp) -> float:
        """Вычисляет качество организма.

        Если осуществлялась оценка для указанных тикеров и даты - используется сохраненное значение. Если
        существует натренированная модель для указанных тикеров - осуществляется оценка без тренировки.
        В ином случае тренируется и оценивается с нуля.
        """
        tickers = list(tickers)
        data = self._data
        data.wins += 1

        if data.date == end and data.tickers == tickers:
            data.save()
            return data.llh

        pickled_model = data.model
        if data.tickers != tickers:
            pickled_model = None

        timer = time.monotonic_ns()
        model = Model(tuple(tickers), end, self.genotype.get_phenotype(), pickled_model)
        llh = model.llh
        timer = time.monotonic_ns() - timer

        data.llh = llh
        data.model = bytes(model)
        data.date = end
        data.tickers = tickers

        if pickled_model is None:
            data.timer = timer

        data.save()
        return llh

    def find_weaker(self) -> "Organism":
        """Находит организм с llh меньше или равное своему и максимальным временем обучения.

        Может найти самого себя.
        """
        data = self._data
        collection = store.get_collection()
        filter_ = dict(llh={"$lte": data.llh}, tickers=data.tickers)
        id_dict = collection.find_one(
            filter=filter_, projection=["_id"], sort=[("timer", pymongo.DESCENDING)]
        )
        return Organism(**id_dict)

    def die(self) -> NoReturn:
        """Организм удаляется из популяции."""
        self._data.delete()

    def make_child(self) -> "Organism":
        """Создает новый организм с помощью дифференциальной мутации."""
        genotypes = [organism.genotype for organism in _sample_organism(3)]
        child_genotype = self.genotype.make_child(*genotypes)
        return Organism(genotype=child_genotype)

    def forecast(self, tickers: Tuple[str, ...], end: pd.Timestamp) -> Forecast:
        """Выдает прогноз для текущего организма.

        При наличие натренированной модели, которая составлена на предыдущей статистике и для таких же
        тикеров, будет использованы сохраненные веса сети, или выбрасывается исключение.
        """
        data = self._data
        if (pickled_model := data.model) is None or tickers != tuple(data.tickers):
            raise ForecastError

        model = Model(tickers, end, self.genotype.get_phenotype(), pickled_model)
        return model.forecast()
Ejemplo n.º 5
0
class Organism:
    """Организм и основные операции с ним.

    Умеет рассчитывать качество организма для проведения естественного отбора, умирать, размножаться и
    отображать количество пройденных оценок качества.
    """
    def __init__(
        self,
        *,
        _id: Optional[bson.ObjectId] = None,
        genotype: Optional[Genotype] = None,
    ) -> None:
        """Загружает организм из базы данных."""
        self._doc = store.Doc(id_=_id, genotype=genotype)

    def __str__(self) -> str:
        """Текстовое представление генотипа организма."""
        return str(self._doc.genotype)

    @property
    def id(self) -> bson.ObjectId:
        """ID организма."""
        return self._doc.id

    @property
    def genotype(self) -> Genotype:
        """Генотип организма."""
        return self._doc.genotype

    @property
    def timer(self) -> float:
        """Генотип организма."""
        return self._doc.timer

    @property
    def wins(self) -> int:
        """Количество побед."""
        return self._doc.wins

    @property
    def llh(self) -> float:
        """Количество побед."""
        return self._doc.llh

    def evaluate_fitness(self, tickers: tuple[str, ...],
                         end: pd.Timestamp) -> float:
        """Вычисляет качество организма.

        Если осуществлялась оценка для указанных тикеров и даты - используется сохраненное значение. Если
        существует натренированная модель для указанных тикеров - осуществляется оценка без тренировки.
        В ином случае тренируется и оценивается с нуля.
        """
        tickers = list(tickers)
        doc = self._doc
        doc.wins += 1

        timer = time.monotonic_ns()
        model = Model(tuple(tickers), end, self.genotype.get_phenotype())
        llh = model.llh
        timer = time.monotonic_ns() - timer

        doc.llh = llh
        doc.model = bytes(model)
        doc.date = end
        doc.tickers = tickers

        doc.timer = timer

        doc.save()
        return llh

    def find_weaker(self) -> "Organism":
        """Находит организм с наименьшим llh.

        В оборе участвуют только организмы с таким же набором тикеров и датой обновления. Может найти
        самого себя.
        """
        doc = self._doc
        collection = store.get_collection()

        filter_ = {"timer": {"$gte": doc.timer}}
        id_dict = collection.find_one(
            filter=filter_,
            projection=["_id"],
            sort=[("llh", pymongo.ASCENDING)],
        )
        org = Organism(**id_dict)
        if self.id != org.id:
            return org

        filter_ = {}
        id_dict = collection.find_one(
            filter=filter_,
            projection=["_id"],
            sort=[("llh", pymongo.ASCENDING)],
        )
        return Organism(**id_dict)

    def die(self) -> None:
        """Организм удаляется из популяции."""
        self._doc.delete()

    def make_child(self, scale: float) -> "Organism":
        """Создает новый организм с помощью дифференциальной мутации."""
        parent, *_ = [organism.genotype for organism in _sample_organism(1)]
        child_genotype = self.genotype.make_child(parent, scale)
        return Organism(genotype=child_genotype)

    def forecast(self, tickers: tuple[str, ...],
                 end: pd.Timestamp) -> Forecast:
        """Выдает прогноз для текущего организма.

        При наличии натренированной модели, которая составлена на предыдущей статистике и для таких же
        тикеров, будет использованы сохраненные веса сети, или выбрасывается исключение.
        """
        doc = self._doc
        if (pickled_model := doc.model) is None or tickers != tuple(
                doc.tickers):
            raise ForecastError

        model = Model(tickers, end, self.genotype.get_phenotype(),
                      pickled_model)
        forecast = model.forecast()
        if np.any(np.isnan(forecast.cov)):
            self.die()
            raise ForecastError
        return forecast
Ejemplo n.º 6
0
class Organism:  # noqa: WPS214
    """Организм и основные операции с ним.

    Умеет рассчитывать качество организма для проведения естественного отбора, умирать, размножаться.
    """
    def __init__(
        self,
        *,
        _id: Optional[bson.ObjectId] = None,
        genotype: Optional[Genotype] = None,
    ) -> None:
        """Загружает организм из базы данных."""
        self._doc = store.Doc(id_=_id, genotype=genotype)

    def __str__(self) -> str:
        """Текстовое представление генотипа организма."""
        llh_block = _format_scores_list(self.llh)
        ir_block = _format_scores_list(self.ir)

        timer = datetime.timedelta(seconds=self.timer // TIME_TO_SEC)

        blocks = [
            f"LLH — {llh_block}",
            f"RET — {ir_block}",
            f"Timer — {timer} / Scores - {self.scores}",
            str(self._doc.genotype),
        ]

        return "\n".join(blocks)

    @property
    def id(self) -> bson.ObjectId:
        """ID организма."""
        return self._doc.id

    @property
    def genotype(self) -> Genotype:
        """Генотип организма."""
        return self._doc.genotype

    @property
    def date(self) -> pd.Timestamp:
        """Дата последнего расчета."""
        return self._doc.date

    @property
    def timer(self) -> float:
        """Генотип организма."""
        return self._doc.timer

    @property
    def scores(self) -> int:
        """Количество оценок LLH."""
        return self._doc.wins

    @property
    def llh(self) -> list[float]:
        """List of LLH OOS."""
        return self._doc.llh

    @property
    def ir(self) -> list[float]:
        """List of information ratios."""
        return self._doc.ir

    def clear(self) -> None:
        """Сбрасывает результаты обучения и оценки, но сохраняет информацию о количестве оценок."""
        doc = self._doc
        doc.model = None
        doc.llh = []
        doc.ir = []
        doc.date = None
        doc.tickers = None

    def evaluate_fitness(self, tickers: tuple[str, ...],
                         end: pd.Timestamp) -> list[float]:
        """Вычисляет качество организма.

        В первый вызов для нового дня используется метрика существующей натренированной модели.
        При последующих вызовах в течение дня выбрасывается ошибка.
        """
        if end == self.date:
            raise ReevaluationError

        tickers = list(tickers)
        doc = self._doc

        pickled_model = None
        if doc.date is not None and doc.date < end and tickers == doc.tickers:
            pickled_model = doc.model

        timer = time.monotonic_ns()
        model = Model(tuple(tickers), end, self.genotype.get_phenotype(),
                      pickled_model)
        llh, ir = model.quality_metrics

        if pickled_model is None:
            doc.timer = time.monotonic_ns() - timer

        doc.llh = [llh] + doc.llh
        doc.wins = len(doc.llh)
        doc.ir = [ir] + doc.ir

        doc.model = bytes(model)

        doc.date = end
        doc.tickers = tickers

        doc.save()

        return self.llh

    def die(self) -> None:
        """Организм удаляется из популяции."""
        self._doc.delete()

    def make_child(self, scale: float) -> "Organism":
        """Создает новый организм с помощью дифференциальной мутации."""
        parent1, parent2 = _get_parents()
        child_genotype = self.genotype.make_child(parent1.genotype,
                                                  parent2.genotype, scale)

        return Organism(genotype=child_genotype)

    def forecast(self, tickers: tuple[str, ...],
                 end: pd.Timestamp) -> Forecast:
        """Выдает прогноз для текущего организма.

        При наличии натренированной модели, которая составлена на предыдущей статистике и для таких же
        тикеров, будет использованы сохраненные веса сети, или выбрасывается исключение.
        """
        doc = self._doc
        if (pickled_model := doc.model) is None or tickers != tuple(
                doc.tickers):
            raise ForecastError

        model = Model(tickers, end, self.genotype.get_phenotype(),
                      pickled_model)
        forecast = model.forecast()
        if np.any(np.isnan(forecast.cov)) or np.any(np.isinf(forecast.cov)):
            self.die()
            raise ForecastError

        return forecast