示例#1
0
    def calculate_ma(self):
        """
        stockpriceテーブルに登録されている全ての企業に対して、単純移動平均・指数平滑移動平均・加重移動平均
        の3通りの方法で日次の値を計算し、stockprice_maテーブルに格納する。

        暫定で短期(5日)・中期(25日)・長期(75日)の3パターンを計算するが、MACalculatorクラスのインタフェースとしては
        任意の日数で計算できるようにしておき、日数変更が用意なようにしておく。

        TODO: 一度全体を計算した後は最新日を計算するだけで十分なので、実行時間が長くなってきたら判定ロジックを追加する。
        """
        self.logger.info('Start calculate_ma Job.')
        dao = CommonDao(session, StockPriceMA, logger)
        ma_dtos = []
        company_ids = self.get_calc_companies()
        calculators = [
            SMACalculator(self.session, self.logger, company_ids),
            EMACalculator(self.session, self.logger, company_ids),
            WMACalculator(self.session, self.logger, company_ids),
        ]
        spans = [5, 25, 75]  # 計算期間

        for calculator in calculators:
            for span in spans:
                ma_dtos.extend(calculator.get_ma_values(span))
        # DELSERTにより更新(TODO対応後はUPSERTに変更)
        dao.delsert(ma_dtos, ['company_id', 'date', 'ma_type'])
示例#2
0
    def test_delsert_is_correct_data(
        self,
        session_001,
        test_common_dao_delsert_data,
        application_logger,
        company_id,
        date,
    ):
        """
        全DELETE全INSERT処理を実施した後のレコードが、正しくDBに保持されているか

        delsertメソッド内ではdtoに手を加えていないので保持されていることのみを確認する
        """
        stock_price_dao = CommonDao(session_001, StockPrice,
                                    application_logger)
        stock_price_dao.delsert(test_common_dao_delsert_data,
                                ['company_id', 'date'])

        record = \
            session_001.query(
                StockPrice
            ).filter(
                StockPrice.company_id == company_id,
                StockPrice.date == date,
            ).first()

        assert record is not None
示例#3
0
    def test_upsert_record_count(
        self,
        session_001,
        test_common_dao_upsert_data,
        application_logger,
    ):
        """
        UPSERT処理を実施した後のレコード数が、想定通りであるか
        """
        stock_price_dao = CommonDao(session_001, StockPrice,
                                    application_logger)
        stock_price_dao.upsert(test_common_dao_upsert_data,
                               ['company_id', 'date'])
        record_count = session_001.query(func.count(
            StockPrice.company_id)).scalar()

        assert len(test_common_dao_upsert_data) == record_count
示例#4
0
    def __init__(
        self,
        session: Session,
        logger: Logger,
    ):
        """
        SQL AlchemyでDBを操作するためのセッションとアプリケーションログ出力用のロガーを受け取る

        Parameters
        ----------
        session: sqlalchemy.Session
            SQL AlchemyでDBを操作するためのSessionクラス
        logger: logging.Logger
            アプリケーションログ出力用のロガー
        """
        self.session = session
        self.dao = CommonDao(session, StockPrice, logger)
        self.logger = logger
示例#5
0
 def update_jp_stock_prices(self):
     """
     Companyテーブルに登録されている企業の中でcountry_codeが"JP"の企業について、
     StockManagerクラスにより株価データを取得し、DBにUPSERTで格納する。
     """
     self.logger.info('Start update_jp_stock_prices Job.')
     dao = CommonDao(session, StockPrice, logger)
     stock_factory = JpStockFactory()
     stock_codes = stock_factory.get_target_stock_codes(self.session)
     stock_manager = StockManager(
         self.session,
         stock_factory.get_stock_api(),
         stock_factory.get_stock_crawler(),
     )
     for stock_code in stock_codes:
         self.logger.info(f'Fetch StockCode:{stock_code} prices')
         company_id = self.get_company_id(stock_code, 'JP')
         stock_price_dtos = stock_manager.get_incremental_stock_price(
             stock_code,
             company_id,
         )
         # UPSERTによりDB更新
         if (stock_price_dtos is not None) and (len(stock_price_dtos) >= 1):
             dao.upsert(stock_price_dtos, ['company_id', 'date'])
示例#6
0
    def test_upsert_is_correct_update_data(
        self,
        session_001,
        test_common_dao_upsert_data,
        application_logger,
        company_id,
        date,
    ):
        """
        UPSERT処理を実施した後のUPDATE対象のレコードが、正しくDBに保持されているか

        「ins_tsを書き換えていないこと」という観点が加わる
        """
        old_record = \
            session_001.query(
                StockPrice
            ).filter(
                StockPrice.company_id == company_id,
                StockPrice.date == date,
            ).first()

        stock_price_dao = CommonDao(session_001, StockPrice,
                                    application_logger)
        stock_price_dao.upsert(test_common_dao_upsert_data,
                               ['company_id', 'date'])

        record = \
            session_001.query(
                StockPrice
            ).filter(
                StockPrice.company_id == company_id,
                StockPrice.date == date,
            ).first()

        assert record is not None
        assert old_record.ins_ts == record.ins_ts
示例#7
0
class StockClient(object):
    """
    各種クラスを使用して、最新の株価データを取得しDB格納するクラス
    """
    def __init__(
        self,
        session: Session,
        logger: Logger,
    ):
        """
        SQL AlchemyでDBを操作するためのセッションとアプリケーションログ出力用のロガーを受け取る

        Parameters
        ----------
        session: sqlalchemy.Session
            SQL AlchemyでDBを操作するためのSessionクラス
        logger: logging.Logger
            アプリケーションログ出力用のロガー
        """
        self.session = session
        self.dao = CommonDao(session, StockPrice, logger)
        self.logger = logger

    def update_jp_stock_prices(self):
        """
        Companyテーブルに登録されている企業の中でcountry_codeが"JP"の企業について、
        StockManagerクラスにより株価データを取得し、DBにUPSERTで格納する。
        """
        self.logger.info('Start update_jp_stock_prices Job.')
        stock_factory = JpStockFactory()
        stock_codes = stock_factory.get_target_stock_codes(self.session)
        stock_manager = StockManager(
            self.session,
            stock_factory.get_stock_api(),
            stock_factory.get_stock_crawler(),
        )
        for stock_code in stock_codes:
            self.logger.info(f'Fetch StockCode:{stock_code} prices')
            company_id = self.get_company_id(stock_code, 'JP')
            stock_price_dtos = stock_manager.get_incremental_stock_price(
                stock_code,
                company_id,
            )
            # UPSERTによりDB更新
            if (stock_price_dtos is not None) and (len(stock_price_dtos) >= 1):
                self.dao.upsert(stock_price_dtos, ['company_id', 'date'])

    def get_company_id(
        self,
        stock_code: str,
        country_code: str,
    ):
        """
        Companyテーブルに対して、銘柄コードと国コードから企業コードを返す。

        Parameters
        ----------
        stock_code: str
            検索対象となる銘柄コード
        country_code: str
            検索対象となる国コード
        """
        company_id = self.session.query(Company.company_id).filter(
            Company.stock_code == stock_code,
            Company.country_code == "JP").one().company_id
        return company_id