def get_neutral_vol(db_session, instrument_id, valuation_date, window): strike_type = VolSurfaceStrikeType.PERCENT.name instance = VolSurfaceInstanceType.CLOSE.name vol_surface_dbo = VolSurfaceRepo.\ get_instrument_vol_surface(db_session, instrument_id, valuation_date, strike_type, instance) if vol_surface_dbo is None: logging.error('标的: %s在%s时没有找到vol surface' % (instrument_id, valuation_date)) raise CustomException('标的: %s在%s时没有找到波动率曲面' % (instrument_id, valuation_date)) instruments = vol_surface_dbo.modelInfo['instruments'] # 获取公允波动率 neutral_vol = None for instrument in instruments: if instrument['tenor'] == str(window) + 'D': for vol in instrument['vols']: if vol['percent'] == 1: neutral_vol = vol['quote'] break break if neutral_vol is None: logging.error('标的: %s在%s时找到波动率曲面, 但是无法计算公允波动率' % (instrument_id, valuation_date)) raise CustomException('标的: %s在%s时找到波动率曲面, 但是无法计算公允波动率' % (instrument_id, valuation_date)) return neutral_vol
def get_primary_instrument_id(db_session, instrument_id, trade_date, is_primary): if InstrumentService.is_commodity_variety_type(db_session, instrument_id): # 如果传入的是大宗合约类型, 则直接获取当天的主力合约代码 variety_type = instrument_id else: if is_primary is False: return instrument_id # 如果传入的是具体的大宗标的代码, 则直接获取当天的主力合约代码 variety_type = InstrumentService.get_commodity_variety_type( db_session, instrument_id) # 如果获取到的合约种类为空, 则说明该标的不是大宗商品, 直接返回标的代码 if variety_type is None: instrument = InstrumentRepo.get_instrument(db_session, instrument_id) if instrument is None: raise CustomException('不支持标的%s' % instrument_id) return instrument_id else: future_contract = CommodityFutureContractRepo.get_commodity_future_contract( db_session, variety_type, trade_date) if future_contract is None or future_contract.primaryContractId is None: raise CustomException( "合约类型%s在%s下无主力合约数据" % (variety_type, DateTimeUtils.date2str(trade_date))) return future_contract.primaryContractId
def check_date_params(db_session, start_date, end_date, window): if start_date > date.today() or end_date > date.today(): raise CustomException('所选日期不能超过今天') if TradingDayService.get_effective_days_num(db_session, start_date, end_date) < window: raise CustomException('所选日期范围[%s,%s]交易日个数小于窗口大小,无法进行计算' % (DateTimeUtils.date2str(start_date), DateTimeUtils.date2str(end_date)))
def get_otc_asset_tool_report(self, start_date=None, end_date=None, page=None, page_size=None, current_user=None): with self.make_session() as db_session: if start_date is None or end_date is None: raise CustomException('所选日期不能为空') if (page is None and page_size is not None) or (page is not None and page_size is None): raise CustomException('分页参数page和page_size必须同时存在或不存在') DateTimeUtils.validate(start_date, REPORT_DATE_PATTERN) DateTimeUtils.validate(end_date, REPORT_DATE_PATTERN) reports = OTCReportService.get_otc_asset_tool_report( db_session, start_date, end_date, page, page_size) return reports
async def get_implied_vol_report(self, instrument_id, report_date): with self.make_session() as db_session: report_date_obj = DateTimeUtils.str2date(report_date) if report_date_obj > date.today(): raise CustomException('所选日期不能超过今天') vol_report_dto_list = OTCPositionSnapshotService.get_implied_vol_report( db_session, instrument_id, report_date_obj) implied_vol_report_schema = ImpliedVolReportSchema(many=True, exclude=[]) return implied_vol_report_schema.dump(vol_report_dto_list).data
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
async def get_latest_vol_surface( self, instrument_id, valuation_date, strike_type=VolSurfaceStrikeType.PERCENT.name, instance=VolSurfaceInstanceType.CLOSE.name, is_primary=False): with self.make_session() as db_session: vol_surface_dto = ImpliedVolService.get_latest_vol_surface( db_session, instrument_id, DateTimeUtils.str2date(valuation_date), strike_type, instance, is_primary) if vol_surface_dto is None: raise CustomException('没有找到对应的波动率曲面') vol_surface_schema = VolSurfaceSchema(exclude=[]) return vol_surface_schema.dump(vol_surface_dto).data
async def get_instrument_realized_vol( self, instrument_id, trade_date, windows=[1, 3, 5, 10, 22, 44, 66, 132], is_primary=False): with self.make_session() as db_session: trade_date_obj = DateTimeUtils.str2date(trade_date) if trade_date_obj > date.today(): raise CustomException('所选日期不能超过今天') realized_vol_dto_list, diagnostics = HistoricalVolService.calc_instrument_realized_vol( db_session, instrument_id, DateTimeUtils.str2date(trade_date), windows, is_primary) realized_vol_schema = RealizedVolSchema( many=True, exclude=['tradeDate', 'instrumentId', 'percentile']) return DiagnosticResponse( realized_vol_schema.dump(realized_vol_dto_list).data, diagnostics)
def get_instrument_quote_close_list_by_period(db_session, instrument_id, start_date, end_date, is_primary=False): if not InstrumentService.is_commodity_variety_type(db_session, instrument_id): variety_type = None if is_primary: # 如果是大宗商品标的,则直接使用variety_type variety_type = InstrumentService.get_commodity_variety_type(db_session, instrument_id) if variety_type is None: instrument = InstrumentRepo.get_instrument(db_session, instrument_id) if instrument is None: raise CustomException('暂不支持标的物%s,请导入该标的物行情' % instrument_id) quote_close_dbo_list = QuoteCloseRepo.\ get_instrument_quote_close_list_by_period(db_session, instrument_id, start_date, end_date) else: quote_close_dbo_list = QuoteCloseService.\ get_commodity_future_quote_close_list_by_period(db_session, variety_type, start_date, end_date) else: quote_close_dbo_list = QuoteCloseService.\ get_commodity_future_quote_close_list_by_period(db_session, instrument_id, start_date, end_date) return QuoteCloseService.to_dtos(quote_close_dbo_list)
def get_instrument_atm_quote_list_by_period(db_session, underlyer, start_date, end_date, is_primary): if not InstrumentService.is_commodity_variety_type( db_session, underlyer): variety_type = None if is_primary: # 如果是大宗商品标的,则直接使用variety_type variety_type = InstrumentService.get_commodity_variety_type( db_session, underlyer) if variety_type is None: instrument = InstrumentRepo.get_instrument( db_session, underlyer) if instrument is None: raise CustomException('暂不支持标的物%s,请导入该标的物行情' % underlyer) atm_quote_dbo_list = OtcAtmQuoteRepo.\ get_instrument_atm_quote_list_by_period(db_session, underlyer, start_date, end_date) else: atm_quote_dbo_list = OtcAtmQuoteRepo.\ get_commodity_future_atm_quote_list_by_period(db_session, variety_type, start_date, end_date) else: atm_quote_dbo_list = OtcAtmQuoteRepo.\ get_commodity_future_atm_quote_list_by_period(db_session, underlyer, start_date, end_date) return OtcAtmQuoteService.to_dtos(atm_quote_dbo_list)