def update_implied_vol(start_date, end_date, force_update):
     """
     根据日期循环导入数到数据平台otc_position_snapshot表
     :param start_date:
     :param end_date:
     :param force_update:
     :return:
     """
     db_session = create_db_session()
     try:
         for index in range(0, (end_date - start_date).days + 1):
             report_date = (start_date + timedelta(index))
             logging.info('开始获取report_date: %s的数据' % report_date)
             clean_position_dict = ROTCPositionService.clean_one_day_implied_vol(
                 db_session, report_date)
             position_snapshots = ROTCPositionService.convert_data_to_position_snapshot(
                 clean_position_dict)
             exiting_trans_codes = OTCPositionSnapshotRepo.get_trans_codes_by_report_date(
                 db_session, report_date)
             ROTCPositionService.save_position_snapshot(
                 db_session, report_date, exiting_trans_codes,
                 position_snapshots, force_update)
     except Exception as e:
         logging.error('运行错误: %s' % e)
         db_session.close()
         raise Exception(e)
 def update_day_instrument_realized_vol(db_session, instrument_id_dict,
                                        instruments, valuation_date):
     """
     保存一天所有标的的历史波动率
     :param db_session:
     :param instrument_id_dict:
     :param instruments:
     :param valuation_date:
     :return:
     """
     logging.info('开始计算交易日: %s的历史波动率' % valuation_date)
     failed_instrument_id_dict = {}
     realized_vol_dict = {}
     for index, instrument in enumerate(instruments):
         instrument_id = instrument.instrumentId
         try:
             if instrument_id_dict[
                     instrument_id] in BCTSpecialConfig.instrument_types:
                 # 计算realized vol 时, 过滤掉基金, 期权
                 logging.debug('instrument_id: %s 不支持realized_vol计算' %
                               instrument_id)
                 continue
             logging.debug('开始计算: %s的历史波动率, 进度为: %d of %d' %
                           (instrument_id, index, len(instruments)))
             realized_vol_dto_list, diagnostics = HistoricalVolService. \
                 calc_instrument_realized_vol(db_session, instrument_id, valuation_date,
                                              windows=RealizedVolService.windows, is_primary=True)
             if len(realized_vol_dto_list) == 0:
                 failed_instrument_id_dict[
                     instrument_id] = instrument_id_dict[instrument_id]
             for realized_vol_dto in realized_vol_dto_list:
                 realized_vol = RealizedVol(uuid=str(uuid.uuid1()),
                                            instrumentId=instrument_id,
                                            valuationDate=valuation_date,
                                            vol=realized_vol_dto.vol,
                                            exfsid=instrument.contractType,
                                            windows=realized_vol_dto.window,
                                            updatedAt=datetime.now())
                 if realized_vol.instrumentId not in realized_vol_dict:
                     realized_vol_dict[realized_vol.instrumentId] = {}
                 realized_vol_dict[realized_vol.instrumentId][
                     realized_vol.windows] = realized_vol
         except Exception as e:
             logging.error('计算: %s的历史波动率失败, 错误: %s' % (instrument_id, e))
             failed_instrument_id_dict[instrument_id] = instrument_id_dict[
                 instrument_id]
     logging.info('完成计算交易日: %s的历史波动率,成功%s条,失败%s条' %
                  (valuation_date, len(realized_vol_dict),
                   len(failed_instrument_id_dict)))
     return realized_vol_dict, failed_instrument_id_dict
    def clean_one_day_implied_vol(db_session, report_date):
        """
        清洗一天的数据
        :param db_session:
        :param report_date:
        :return:
        """
        report_date = DateTimeUtils.date2str(report_date)
        trans_code_list = ROTCPositionRepo.get_trans_code_list_by_date(
            db_session, report_date)
        logging.info('正在获取持仓表数据长度为: %d' % (len(trans_code_list)))
        position_data_list = ROTCPositionRepo.get_otc_position_by_trans_codes(
            db_session, report_date, trans_code_list)

        trans_code_list = [
            position_data.TRANSCODE for position_data in position_data_list
        ]
        logging.info('正在获取成交表数据,长度为: %d' % (len(trans_code_list)))
        trade_data_dict = ROTCTradedataRepo.get_trade_data_by_trans_codes(
            db_session, report_date, trans_code_list)

        clean_position_dict = {}
        for index, position_data in enumerate(position_data_list):
            trans_code = position_data.TRANSCODE
            trade_data = trade_data_dict.get(trans_code)
            if trade_data is not None:
                try:
                    logging.debug('正在组合数据, 当前进度为: %d of %d' %
                                  (index, len(position_data_list)))
                    clean_position = ROTCPositionService.organize_trade_data(
                        position_data, trade_data)
                    implied_vol = clean_position.get('implied_vol')
                    if implied_vol is not None:
                        clean_position_dict[trans_code] = clean_position
                    else:
                        # TODO: 如果没有implied_vol,则直接根据价格反推隐含波动率,按以下规则进行
                        # 除了价格,利率 / 分红,还需要检查行权价,到期日和期权类型:
                        # 行权价可能需要注意是否为百分比,如果为百分比,需要继续检查是否有期初价格。
                        # 反推隐含波动率需要知道每份期权的价格,因此价格需要检查是否有对应的数量。没有数量,则需要名义本金,参与率,期限(如果年化),期初价格。
                        clean_position_dict[trans_code] = None
                except Exception as e:
                    logging.error('交易数据转化错误,trans_code: %s, 异常:%s' %
                                  (trans_code, str(e)))
        return clean_position_dict
 def update_days_instrument_realized_vol(start_date,
                                         end_date,
                                         force_update=False):
     """
     保存不同交易日的标的历史波动率
     :param start_date:
     :param end_date:
     :param force_update:
     :return:
     """
     db_session = create_db_session
     while start_date <= end_date:
         try:
             valuation_date = start_date
             # 获取全量instrument表数据
             instrument_id_dict = {}
             for instrument in InstrumentRepo.get_all_instrument(
                     db_session):
                 instrument_id_dict[
                     instrument.instrumentId] = instrument.instrumentType
             # 获取instrument id list
             instruments = InstrumentRepo.get_instruments_by_trade_date(
                 db_session, valuation_date)
             # 获取valuation_date的标的历史波动率
             realized_vol_dict, failed_instrument_id_dict = RealizedVolService. \
                 update_day_instrument_realized_vol(db_session, instrument_id_dict, instruments, valuation_date)
             # 获取valuation_date已经存在的标的历史波动率
             existed_realized_vol_dict = RealizedVolRepo. \
                 get_realized_vol_dict_by_valuation_date(db_session, valuation_date)
             # 保存历史波动率
             RealizedVolService. \
                 save_realized_vol(db_session, valuation_date, realized_vol_dict, existed_realized_vol_dict,
                                   force_update)
             start_date = start_date + timedelta(days=1)
             if len(failed_instrument_id_dict) != 0:
                 failed_length = len(failed_instrument_id_dict)
                 total_length = len(instruments)
                 logging.error('交易日为: %s, 计算历史波动率失败为 %d of %d, 标的id为: %s' %
                               (valuation_date, failed_length, total_length,
                                failed_instrument_id_dict))
         except Exception as e:
             db_session.close()
             raise e
     db_session.close()
Exemple #5
0
 def calc_instrument_atm_vol_list(db_session, underlyer, start_date,
                                  end_date, is_primary):
     atm_quote_list = OtcAtmQuoteService.get_instrument_atm_quote_list_by_period(
         db_session, underlyer, start_date, end_date, is_primary)
     # TODO:去掉重复数据,相同valuation date, underlyer, source, expire date的数据需要去重
     # 根据valuation date进行分类
     atm_quote_dict = {}
     for atm_quote in atm_quote_list:
         if atm_quote.valuationDate not in atm_quote_dict:
             atm_quote_dict[atm_quote.valuationDate] = []
         atm_quote_dict[atm_quote.valuationDate].append(atm_quote)
     # 取一个自然月后到期日的前后3天的ask_vol和bid_vol的平均值作为当天的atm_vol
     atm_vol_dict = {}
     for valuation_date in atm_quote_dict:
         quote_list = atm_quote_dict[valuation_date]
         atm_vol = OtcAtmQuoteService.calc_one_atm_vol(
             valuation_date, quote_list)
         if atm_vol is not None:
             atm_vol_dict[valuation_date] = atm_vol
     # 检测哪些日期缺失
     missing_dates = []
     holidays = TradingDayService.get_holiday_list(db_session, start_date,
                                                   end_date)
     trade_date = start_date
     while trade_date <= end_date:
         if DateTimeUtils.is_trading_day(trade_date, holidays):
             if trade_date not in atm_vol_dict:
                 # 将缺失的日期添加到诊断中
                 missing_dates.append(trade_date)
                 # TODO: 是否需要将缺失的数据按0补足
         trade_date += timedelta(days=1)
     # 添加诊断信息
     diagnostics = []
     if len(missing_dates) != 0:
         message = '标的物%s在[%s, %s]时段内中缺失%d条ATM Vol数据' % (
             underlyer, DateTimeUtils.date2str(start_date),
             DateTimeUtils.date2str(end_date), len(missing_dates))
         diagnostics.append(
             DiagnosticDTO(DiagnosticType.WARNING, message, missing_dates))
         logging.error(message)
     return atm_vol_dict.values(), diagnostics
 def auth_sys_log_save(auth_ret, body, token, ip):
     try:
         body = json.loads(body)
         method = body['method']
         operation = auth_sys_operation_type.get(method)
         if operation:
             params = {
                 "username": auth_ret['username'],
                 "operation": operation,
                 "service": Constant.SERVICE,
                 "method": method,
                 "params": body.get('params')
             }
             headers = {
                 'Authorization': 'Bearer ' + token,
                 'X-Forwarded-For': ip
             }
             ServerUtils.call_request_bct('auth-service', 'authSysLogSave',
                                          params, headers)
     except CustomException as e:
         logging.error('调用接口: authSysLogSave保存用户操作失败')