Exemple #1
0
    def loads(data: dict) -> "StockRecord":

        data_date = data.get("date")
        data_dt = data.get("dt")
        data_crawl_datetime = data.get("crawl_datetime")

        if data_date and data_dt and data_crawl_datetime:
            raise KabutobashiEntityError("日付のカラム[dt, date, crawl_datetime]のいずれかしか選べません")
        if data_date:
            dt = data_date
        elif data_dt:
            dt = data_dt
        elif data_crawl_datetime:
            dt = datetime.fromisoformat(data_crawl_datetime).strftime("%Y-%m-%d")
        else:
            raise KabutobashiEntityError("日付のカラム[dt, date, crawl_datetime]のいずれかが存在しません")

        return StockRecord(
            id=data.get("id"),
            code=str(data["code"]),
            open=_convert_float(data["open"]),
            high=_convert_float(data["high"]),
            low=_convert_float(data["low"]),
            close=_convert_float(data["close"]),
            psr=_convert_float(data["psr"]),
            per=_convert_float(data["per"]),
            pbr=_convert_float(data["pbr"]),
            volume=_convert_int(data["volume"]),
            dt=dt,
        )
Exemple #2
0
def _convert_float(input_value: Union[str, float, int]) -> float:
    if type(input_value) is float:
        return input_value
    elif type(input_value) is int:
        return float(input_value)
    elif type(input_value) is str:
        try:
            return float(_replace(input_value=input_value))
        except ValueError as e:
            raise KabutobashiEntityError(f"cannot convert {input_value} to float: {e}")
    raise KabutobashiEntityError(f"cannot convert {input_value} to float")
Exemple #3
0
 def _code_constraint_check(stock_recordset: StockRecordset):
     brands = stock_recordset.get_code_list()
     if len(brands) > 1:
         raise KabutobashiEntityError("multiple code")
     elif len(brands) == 0:
         raise KabutobashiEntityError("no code")
     code_records = list(set([v.code for v in stock_recordset.recordset]))
     if len(code_records) > 1:
         raise KabutobashiEntityError("multiple code")
     elif len(code_records) == 0:
         raise KabutobashiEntityError("no code")
Exemple #4
0
def _convert_int(input_value: Union[str, float, int]) -> int:
    if type(input_value) == int:
        return input_value
    elif type(input_value) == float:
        try:
            return int(input_value)
        except ValueError:
            return 0
    elif type(input_value) is str:
        try:
            return int(_replace(input_value=input_value))
        except ValueError as e:
            raise KabutobashiEntityError(f"cannot convert {input_value} to integer: {e}")
    raise KabutobashiEntityError(f"cannot convert {input_value} to int")
Exemple #5
0
 def of(
     entity: Union[pd.DataFrame, StockDataSingleCode, StockRecordset], *, code: Optional[str] = None
 ) -> "StockCodeSingleAggregate":
     if type(entity) is pd.DataFrame:
         single_code = StockDataSingleCode.of(df=entity)
     elif type(entity) is StockDataSingleCode:
         single_code = entity
     elif type(entity) is StockRecordset:
         if code is None:
             raise KabutobashiEntityError("code is required")
         df_ = entity.to_df(code=code)
         single_code = StockDataSingleCode.of(df=df_)
     else:
         raise KabutobashiEntityError("accept pd.DataFrame or StockDataSingleCode")
     return StockCodeSingleAggregate(code=single_code.code, single_code=single_code)
Exemple #6
0
    def sliding_split(
        self,
        *,
        buy_sell_term_days: int = 5,
        sliding_window: int = 60,
        step: int = 3
    ) -> Generator[Tuple[int, pd.DataFrame, pd.DataFrame], None, None]:
        """
        単一の銘柄に関してwindow幅を ``sliding_window`` 日として、
        保持しているデータの期間の間をslidingしていく関数。

        Args:
            buy_sell_term_days: この日数後までデータを切り出す。
            sliding_window: slidingしていくwindow幅
            step: windowsをずらしていく期間

        Returns:
            idx: 切り出された番号。
            df_for_x: 特徴量を計算するためのDataFrame。
            df_for_y: ``buy_sell_term_days`` 後のDataFrameを返す。値動きを追うため。
        """
        df = self.to_df()
        df_length = len(df.index)
        if df_length < buy_sell_term_days + sliding_window:
            raise KabutobashiEntityError("入力されたDataFrameの長さがwindow幅よりも小さいです")
        loop = df_length - (buy_sell_term_days + sliding_window)
        for idx, i in enumerate(range(0, loop, step)):
            offset = i + sliding_window
            end = offset + buy_sell_term_days
            yield idx, df[i:offset], df[offset:end]
Exemple #7
0
    def with_processed(self, methods: List[Method]) -> "StockCodeSingleAggregate":
        # check all methods
        for method in methods:
            if not isinstance(method, Method):
                raise KabutobashiEntityError()

        return StockCodeSingleAggregate(
            code=self.code, single_code=self.single_code, processed_list=[self._to_single_processed(m) for m in methods]
        )
Exemple #8
0
 def to_single_code(self, code: str) -> "StockRecordset":
     if type(code) is not str:
         raise KabutobashiEntityError(f"code must be type of `str`")
     return StockRecordset.of(df=self._to_df(code=code))
Exemple #9
0
 def __post_init__(self):
     if not self.recordset:
         raise KabutobashiEntityError(f"required stock_data")
 def _check_visualize_option(self, data: dict):
     validator = Validator(self.VISUALIZE_OPTION_SCHEMA)
     if not validator.validate(data):
         raise KabutobashiEntityError(validator)
 def _check_color_mapping(self, data: list):
     validator = Validator(self.COLOR_MAPPING_SCHEMA)
     for d in data:
         if not validator.validate(d):
             raise KabutobashiEntityError(validator)
Exemple #12
0
 def visualize(self, size_ratio: int = 2) -> StockDataVisualized:
     if not self.processed_list:
         raise KabutobashiEntityError("call with_processed() before.")
     return StockDataVisualized.of(processed=self.processed_list, size_ratio=size_ratio)
Exemple #13
0
    def _visualize(processed_list: List[StockDataProcessedBySingleMethod],
                   size_ratio: int):
        """
        Visualize Stock Data.

        Args:
            processed_list:
            size_ratio: determine the size of the graph, default 2.

        Returns:
            Figure
        """
        def _n_rows() -> int:
            lower_nums = len([
                p for p in processed_list
                if p.visualize_option["position"] == "lower"
            ])
            return 1 + lower_nums

        n_rows = _n_rows()

        def _gridspec_kw() -> dict:
            if n_rows == 1:
                return {"height_ratios": [3]}
            return {"height_ratios": [3] + [1] * (n_rows - 1)}

        gridspec_kw = _gridspec_kw()
        fig, axs = plt.subplots(nrows=n_rows,
                                ncols=1,
                                figsize=(6 * size_ratio, 5 * size_ratio),
                                gridspec_kw=gridspec_kw)
        # auto-formatting x-axis
        fig.autofmt_xdate()

        # set candlestick base
        base_df = processed_list[0].df[["dt", "open", "close", "high", "low"]]
        StockDataVisualized._add_ax_candlestick(axs[0], base_df)

        ax_idx = 1
        # plots
        for processed in processed_list:
            position = processed.visualize_option["position"]
            df = processed.df
            time_series = mdates.date2num(df["dt"])
            mapping = processed.color_mapping
            if position == "in":
                for m in mapping:
                    df_key = m["df_key"]
                    color = m["color"]
                    label = m["label"]
                    axs[0].plot(time_series, df[df_key], label=label)
                # display labels
                axs[0].legend(loc="best")
            elif position == "lower":
                for m in mapping:
                    df_key = m["df_key"]
                    color = m["color"]
                    label = m["label"]
                    plot = m.get("plot", "plot")
                    if plot == "plot":
                        # type FloatingArray is no accepted ...
                        # so `df[df_key].astype(float)`
                        axs[ax_idx].plot(time_series,
                                         df[df_key].astype(float),
                                         label=label)
                    elif plot == "bar":
                        axs[ax_idx].bar(time_series, df[df_key], label=label)
                # display labels
                axs[ax_idx].legend(loc="best")
                # lower
                ax_idx += 1
            elif position == "-":
                # technical_analysis以外のmethodが入っている場合
                pass
            else:
                raise KabutobashiEntityError()

        return fig