示例#1
0
 def get_instrument_quote_close_dict_by_period(db_session, instrument_id, start_date, end_date, is_primary=False):
     quote_close_dto_list = QuoteCloseService.get_instrument_quote_close_list_by_period(db_session, instrument_id,
                                                                                        start_date, end_date,
                                                                                        is_primary)
     # 转化为字典类型
     quote_close_dto_dict = {}
     for quote_close in quote_close_dto_list:
         quote_close_dto_dict[quote_close.tradeDate] = quote_close
     # 校验缺失的收盘价数据
     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 quote_close_dto_dict:
                 # 将缺失的日期添加到诊断中
                 missing_dates.append(trade_date)
                 # 是否需要将缺失的数据按None补齐
                 quote_close_dto_dict[trade_date] = None
         trade_date += timedelta(days=1)
     # 添加诊断信息
     diagnostics = []
     if len(missing_dates) != 0:
         message = '标的物%s在[%s, %s]时段内中缺失%d条收盘数据' % (
             instrument_id, DateTimeUtils.date2str(start_date), DateTimeUtils.date2str(end_date), len(missing_dates))
         diagnostics.append(DiagnosticDTO(DiagnosticType.WARNING, message, missing_dates))
         logging.debug(message)
     return quote_close_dto_dict, diagnostics
 def calc_instrument_vol_cone(db_session,
                              instrument_id,
                              start_date,
                              end_date,
                              windows,
                              percentiles,
                              is_primary=False):
     origin_start_date = start_date
     holidays = TradingDayService.get_holiday_list(db_session)
     # 判断是否时节假日
     if DateTimeUtils.is_trading_day(end_date, holidays):
         start_date = TradingDayService.go_trading_day(db_session,
                                                       start_date,
                                                       max(windows) - 1,
                                                       direction=-1)
     else:
         start_date = TradingDayService.go_trading_day(db_session,
                                                       start_date,
                                                       max(windows),
                                                       direction=-1)
     quote_close_dto_dict, diagnostics = QuoteCloseService.\
         get_instrument_quote_close_dict_by_period(db_session, instrument_id, start_date, end_date, is_primary)
     vol_cone_dto_list = HistoricalVolService.\
         calc_multiple_window_percentiles_by_quotes(origin_start_date, end_date, quote_close_dto_dict, windows,
                                                    percentiles)
     return vol_cone_dto_list, diagnostics
    def get_future_contract_order(db_session, contract_type, exist_dates,
                                  start_date, end_date):
        holidays = TradingCalendarRepo.get_holiday_list(db_session)
        special_dates = []
        if start_date > end_date:
            logging.error(
                "日期指定非法:%s 大于 %s" % DateTimeUtils.date2str(start_date),
                DateTimeUtils.date2str(end_date))
            return None
        else:
            all_dates = [
                DateTimeUtils.str2date(date.strftime("%Y-%m-%d"))
                for date in rrule(DAILY, dtstart=start_date, until=end_date)
            ]
            if exist_dates:
                missing_dates = list(set(all_dates) - set(exist_dates))
            else:
                missing_dates = all_dates
            listed_date, delisted_date = DateTimeUtils.offset_trade_date(
                start_date, end_date, holidays, special_dates)
            close_dict = CommodityFutureContractService.get_corresponding_close(
                db_session, contract_type, listed_date, delisted_date)
            instruments_list = db_session.query(Instrument).filter(
                Instrument.contractType == contract_type)

            fc_list = []
            if close_dict:
                for trade_date in missing_dates:
                    if DateTimeUtils.is_trading_day(trade_date, holidays,
                                                    special_dates):
                        logging.info("处理交易日%s" %
                                     DateTimeUtils.date2str(trade_date))
                        previous_trade_date, _ = DateTimeUtils.offset_trade_date(
                            trade_date, trade_date, holidays, special_dates)
                        pri, sec = FutureContractInfoAlgo.calc_one_future_contract_info(
                            instruments_list, close_dict, contract_type,
                            previous_trade_date)
                        if pri:
                            fc_info = FutureContractInfo(
                                contractType=contract_type,
                                tradeDate=trade_date,
                                primaryContractId=pri,
                                secondaryContractId=sec)
                            logging.info(
                                '合约的主力和次主力为:%s %s %s %s' %
                                (fc_info.contractType,
                                 DateTimeUtils.date2str(fc_info.tradeDate),
                                 fc_info.primaryContractId,
                                 fc_info.secondaryContractId))
                            fc_list.append(fc_info)
                    else:
                        logging.info("跳过非交易日%s" %
                                     DateTimeUtils.date2str(trade_date))
            else:
                fc_list = None
            return fc_list
 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
示例#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 calc_instrument_rolling_vol(db_session,
                                 instrument_id,
                                 start_date,
                                 end_date,
                                 window,
                                 is_primary=False):
     holidays = TradingDayService.get_holiday_list(db_session)
     # 判断是否时节假日
     if DateTimeUtils.is_trading_day(end_date, holidays):
         start_date = TradingDayService.go_trading_day(db_session,
                                                       start_date,
                                                       window - 1,
                                                       direction=-1)
     else:
         start_date = TradingDayService.go_trading_day(db_session,
                                                       start_date,
                                                       window,
                                                       direction=-1)
     quote_close_dto_dict, diagnostics = QuoteCloseService.get_instrument_quote_close_dict_by_period(
         db_session, instrument_id, start_date, end_date, is_primary)
     realized_vol_dto_list = HistoricalVolService.calc_one_rolling_vol_by_quotes(
         quote_close_dto_dict, window)
     return realized_vol_dto_list, diagnostics
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()
示例#8
0
 def is_trading_day(db_session, current_date):
     special_dates = []
     holidays = TradingCalendarRepo.get_holiday_list(db_session)
     return DateTimeUtils.is_trading_day(current_date, holidays,
                                         special_dates)