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()
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保存用户操作失败')