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'])
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
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
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.') 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'])
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
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