def calc_instrument_realized_vol(db_session,
                                  instrument_id,
                                  trade_date,
                                  windows,
                                  is_primary=False):
     if trade_date > date.today():
         raise CustomException('所选日期不能超过今天')
     # TODO: 如果不是交易日,当前默认使用上一个交易日
     holidays = TradingCalendarRepo.get_holiday_list(db_session)
     start_date = DateTimeUtils.get_trading_day(trade_date,
                                                holidays,
                                                special_dates=[],
                                                step=max(windows),
                                                direction=-1)
     quote_close_dto_dict, diagnostics = QuoteCloseService.get_instrument_quote_close_dict_by_period(
         db_session, instrument_id, start_date, trade_date, is_primary)
     realized_vol_dto_list = []
     for window in windows:
         return_rates = []
         # 判断是否为节假日, 非节假日start_date为: trade_date往前走window-1天, 节假日start_date为: trade_date往前走window天
         if DateTimeUtils.is_trading_day(trade_date, holidays):
             start_date = DateTimeUtils.get_trading_day(trade_date,
                                                        holidays,
                                                        special_dates=[],
                                                        step=window - 1,
                                                        direction=-1)
         else:
             start_date = DateTimeUtils.get_trading_day(trade_date,
                                                        holidays,
                                                        special_dates=[],
                                                        step=window,
                                                        direction=-1)
         # 只处理在窗口范围日期内的数据
         for key in quote_close_dto_dict:
             if start_date <= key <= trade_date:
                 quote_close = quote_close_dto_dict.get(key)
                 if quote_close is not None and quote_close.returnRate is not None:
                     return_rates.append(quote_close.returnRate)
         if len(return_rates) < window:
             logging.debug('窗口大小大于回报率个数,窗口大小:%d,回报率个数:%d' %
                           (window, len(return_rates)))
         realized_vol = HistoricalVolAlgo.calc_one_realized_vol(
             return_rates)
         if realized_vol is None:
             # 如果计算得到的结果为None,直接跳过处理
             logging.debug('计算得到的值为空,窗口:%d' % window)
             continue
         dto = RealizedVolDTO()
         dto.window = window
         dto.vol = realized_vol
         realized_vol_dto_list.append(dto)
     return realized_vol_dto_list, diagnostics
Example #2
0
    def expire_date_fun(term_list, db_session):
        """
        根据当前日期和特定步长天数列表,除去节假日和双休,计算到期交易日
        [1,3,5,10,22,44,66,123]: 特定步长天数列表
        使用business_calendar库的Calendar方法

        :param date: term_list(特定步长天数列表)
        :return: expire_date_dict
        """

        # 获取当前时间
        current_day = datetime.date.today()

        # 获取节假日
        holidays = TradingCalendarRepo.get_holiday_list(db_session)

        # # todo 获取特殊日
        # special_dates = load_special_dates(db_session, underlier)
        special_dates = []
        # 根据step获取交易日是哪天,并与步长天数组成字典
        # 将到期日与天数组成一个字典
        expire_date_dict = {}
        for step_date in term_list:
            expire_date = DateTimeUtils.get_trading_day(
                current_day, holidays, special_dates, step_date)
            expire_date = expire_date.strftime('%Y-%m-%d')
            expire_date_dict[expire_date] = step_date

        return expire_date_dict
Example #3
0
 def go_trading_day(db_session, current_date, step, direction=1):
     special_dates = []
     holidays = TradingCalendarRepo.get_holiday_list(db_session)
     return DateTimeUtils.get_trading_day(current_date,
                                          holidays,
                                          special_dates,
                                          step,
                                          direction=direction)
 async def get_heat_map(self, trade_date=None):
     with self.make_session() as db_session:
         if trade_date is None:
             trade_date = datetime.now().date()
         # 求上一个交易日
         holidays = TradingDayService.get_holiday_list(db_session)
         trade_date = DateTimeUtils.get_trading_day(trade_date, holidays, special_dates=[], step=2, direction=-1)
         heat_map_dto_list, diagnostics = OtcAtmQuoteService.get_heat_map(db_session, trade_date)
     heat_map_schema = HeatMapSchema(many=True, exclude=[])
     return DiagnosticResponse(heat_map_schema.dump(heat_map_dto_list).data, diagnostics)
    def calc_all_instrument_quote_vol_surface(observed_date):
        """
        从otc_option_quote表里取华泰的数据,格式化写入到vol_surface表中
        :return:
        """
        db_session = create_db_session()
        try:
            # 取所有instrument_id
            instrument_ids = OTCOptionQuoteRepo.get_instrument_ids_by_observe_date(
                db_session, observed_date)
            vol_surface_dbo_dict = {}
            for index, instrument_id in enumerate(instrument_ids):
                # 计算一个标的的vol_surface
                logger.info('准备加载的标的为: %s, 进度为: %d of %d' %
                            (instrument_id, index + 1, len(instrument_ids)))
                vol_surface_dbo = VolSurfaceSpiderService.calc_one_instrument_quote_vol_surface(
                    db_session, instrument_id, observed_date)
                if vol_surface_dbo is None:
                    continue
                vol_surface_dbo_dict[instrument_id] = vol_surface_dbo
                logger.info('成功计算了标的: %s的vol_surface, 进度为: %d of %d' %
                            (instrument_id, index + 1, len(instrument_ids)))

            # 获取所有的合约种类及其对应的主力合约
            holidays = TradingCalendarRepo.get_holiday_list(db_session)
            special_dates = []
            # 取上一个交易日
            last_trade_date = DateTimeUtils.get_trading_day(
                observed_date, holidays, special_dates, 1, -1)
            # 获取所有的主力合约
            contract_list = db_session.query(FutureContractInfo).filter(
                FutureContractInfo.tradeDate == last_trade_date).all()
            # 获取当天所有活跃的大宗期货合约
            active_instrument_list = db_session.query(Instrument).filter(
                and_(
                    Instrument.status ==
                    enum_dto.InstrumentStatusType.ACTIVE.name,
                    Instrument.assetClass ==
                    enum_dto.AssetClassType.COMMODITY.name,
                    Instrument.instrumentType ==
                    enum_dto.InstrumentType.FUTURE.name,
                    or_(Instrument.delistedDate is None,
                        Instrument.delistedDate > observed_date))).all()
            active_instrument_dict = {}
            for instrument in active_instrument_list:
                if instrument.contractType not in active_instrument_dict:
                    active_instrument_dict[instrument.contractType] = []
                active_instrument_dict[instrument.contractType].append(
                    instrument.instrumentId)
            # 所有标的都使用主力合约对应的波动率曲面
            vol_surface_dbos = []
            for contract in contract_list:
                primary_contract_id = contract.primaryContractId
                if primary_contract_id not in vol_surface_dbo_dict:
                    logger.warning('标的没有主力合约对应的波动率曲面:%s' % primary_contract_id)
                    continue
                variety_type = contract.contractType
                if variety_type not in active_instrument_dict:
                    logger.warning('主力合约没有活跃的合约:%s' % variety_type)
                    continue
                active_future_list = active_instrument_dict[variety_type]
                for instrument_id in active_future_list:
                    vol_surface_dbo = copy.deepcopy(
                        vol_surface_dbo_dict[primary_contract_id])
                    vol_surface_dbo.uuid = uuid.uuid1()
                    vol_surface_dbo.instrumentId = instrument_id
                    vol_surface_dbos.append(vol_surface_dbo)
            # 将波动率曲面写入数据库
            VolSurfaceRepo.insert_vol_surfaces(db_session, vol_surface_dbos)
            logger.info('爬虫vol surface计算完成')
        except Exception as e:
            logger.error(e)
def update_all_instrument_vol_surface_to_terminal(observed_date):
    db_session = create_db_session()
    holidays = TradingCalendarRepo.get_holiday_list(db_session)
    special_dates = []
    if not DateTimeUtils.is_trading_day(observed_date, holidays,
                                        special_dates):
        observed_date = DateTimeUtils.get_trading_day(observed_date, holidays,
                                                      special_dates, 1, -1)

    # 登陆
    logging.info('update all instrument vol surface to bct观察日为: %s' %
                 DateTimeUtils.date2str(observed_date))
    header = server_utils.login_terminal()

    # 从终端加载需要的标的物
    terminal_instrument_ids = [
        instrument['instrumentId']
        for instrument in server_utils.get_instrument_list(header)
    ]
    logging.info(
        '从终端加载到的标的物为:%s, 长度为: %d' %
        (','.join(terminal_instrument_ids), len(terminal_instrument_ids)))

    # 获取数据库中标的物
    vol_surface_list = VolSurfaceRepo.get_vol_surface_by_observed_date(
        db_session, observed_date)

    if not vol_surface_list:
        logging.info('observed_date为: %s没有可以导入到终端的vol surface' % observed_date)

    # 将instruments去重
    unique_vol_surface_list = unique_instruments(vol_surface_list)
    logging.info('在trading_date为: %s时,vol surface 表获取到的标的数量为: %d' %
                 (observed_date, len(unique_vol_surface_list)))

    # 写入vol surface 到 bct
    failed_instrument_ids = []
    # hacky here, 由于bct接收的tenor是自然日,需要将vol surface中工作日转为自然日
    for index, unique_vol_surface in enumerate(unique_vol_surface_list):
        # try:
        instrument_id = unique_vol_surface.instrumentId
        a = unique_vol_surface.modelInfo
        model_info = unique_vol_surface.modelInfo
        if model_info is None:
            continue
        # 获取到当前的vol surface的实时行情spot价格
        market_data = get_real_time_market_data_by_instrument_id(instrument_id)
        if market_data is not None and market_data.get(
                'lastPrice') is not None:
            now_price = market_data.get('lastPrice')
        else:
            logging.error('标的物%s当前行情为空' % instrument_id)
            continue
        if unique_vol_surface.instrumentId not in terminal_instrument_ids:
            logging.info('当前标的: %s的vol surface不在终端需要的列表里' %
                         unique_vol_surface.instrumentId)
            continue

        logging.info('当前准备写入到bct的标的为: %s, 进度为: %d of %d' %
                     (unique_vol_surface.instrumentId, index + 1,
                      len(unique_vol_surface_list)))

        result = update_one_instrument_to_terminal(unique_vol_surface, header,
                                                   now_price, observed_date)
        if not result:
            failed_instrument_ids.append(instrument_id)
        time.sleep(0.3)
    # except Exception as e:
    #     logging.error('更新标的物%s波动率曲面失败, 异常:%s' % (instrument_id, str(e)))
    logging.error(
        '处理失败的标的物为:%d %s' %
        (len(failed_instrument_ids), ','.join(failed_instrument_ids)))
    db_session.close()