返回某个日期点的付息现金

    技术2025-09-16  42

    create or replace function fn_getbondinterest(p_i_fund_id     number, --资产ID                                              p_vc_Stock_Code varchar2, --债券代码                                              p_i_Date        number, --日期                                              p_i_flag        number := 0, --是否计尾:0 不计算,1计算                                              p_en_year_rate  number := -1 --浮息债的年票面利率                                              ) return number is  /*****************************/  --功能:返回某个日期点的付息现金  --auther: lin 09.06.22  --edit :lin 09.07.30 解决 利息截止且没有兑付的情况下,返回0 的问题  --根据 计息方式(按平均值/实际天数)不同而配置不同的脚本  /*****************************/  ----------------临时参数---------------------  pvar_i_Result       number(22, 12) := 0; --临时结果  pvar_i_Date         number := 0; --对应:利息截止日过了,但又没有兑付的债券,输入日期取利息截止日  pvar_vc_SQL         varchar(500); --SQL  pvar_i_HasResult    number := 0; --历史数据  pvar_vc_Script      varchar2(200); --脚本计算公式  pvar_i_quoteway     number := 0; --报价方法(0-全价;1-净价)  pvar_InsStartDate   number := 0; --记息开始日  pvar_InsEndDate     number := 0; --加工后记息截止日  pvar_InsEndDate_old number := 0; --原始记息截止日  pvar_payInsDays     number := 0; --付息间隔天数  pvar_lastInsDays    number := 0; --上一次付息的日期  pvar_I_CASH_DATE    number := 0; --债券兑付日  pvar_i_Months       number := 0; --记息开始日距离当前日期的月份  pvar_InsMaybe       number := 0; --可能的  --  pvar_en_year_rate number := 0; --付息间隔(年)ok  -- pvar_interest_type number := 0; --计息方式(按平均值/实际天数)  ----------------公式参数-------------------  pvar_i_c  number := 0; --每百元面值年利息 ok  pvar_i_t  integer := 0; --起息日或上一付息日至估值日的实际天数 ok  pvar_i_tt integer := 0; --起息日至到期兑付日的实际天数 ok  pvar_i_TS integer := 0; --本付息周期的实际天数 ok  pvar_i_TY number := 0; --本付息周期所在计息年度的实际天数 ok  pvar_i_M  number := 0; --百元面值当前剩余本金值(资产支持证券)=取债券面值 ok  pvar_i_mm number := 0; --每百元面值到期兑付额(贴现债券)=取债券面值 ok  pvar_i_f  number := 0; --一年内付息次数 ok  pvar_i_K  number := 0; --债券起息日至估值日的整年数 ok  pvar_i_Pd number := 0; --债券发行价 ok

      pvar_i_redeem         integer := 0; --是否可赎回,0不可赎回 1可赎回  pvar_i_redemption     integer := 0; -- 是否可回售,0不可回售 1可回售  pvar_i_redemptiondate number := 0; --回售日期  pvar_i_redeemdate     number := 0; --赎回日期  pvar_vc_coupontype    varchar2(10);  pvar_vc_interesttype  varchar2(10);

      pvar_i_trade_date integer; --系统交易日begin  pvar_i_HasResult := 0;  Pvar_i_Date      := p_i_Date; ---add:lin 20090730  select a.i_trade_date into pvar_i_trade_date from systeminfo a;

      ----------------------获取参数数值-----证券不关联帐户--------------------  if pvar_i_HasResult = 0 then    begin      select t.i_start_date, --记息开始日             t.i_end_date, --记息截止日             t.i_end_date,             t.i_payamount, --付息间隔(年)             t.i_quoteway, --报价方法(0-全价;1-净价)             t.en_year_rate, --票面利率             t.en_price, --发行价格             t.I_CASH_DATE, --兑付日             t.en_facevalue, --每百元面值到期兑付额(贴现债券)=面值             t.i_redeem,             t.i_redemption,             t.i_redeemdate,             t.i_redemptiondate,             t.vc_coupontype,             t.vc_interesttype        into pvar_InsStartDate,             pvar_InsEndDate,             pvar_InsEndDate_old,             pvar_i_f,             pvar_i_quoteway,             pvar_i_c,             pvar_i_Pd,             pvar_I_CASH_DATE,             pvar_i_mm,             pvar_i_redeem, --是否可赎回,0不可赎回 1可赎回             pvar_i_redemption, -- 是否可回售,0不可回售 1可回售             pvar_i_redeemdate, --赎回日期             pvar_i_redemptiondate, --回售日期             pvar_vc_coupontype,             pvar_vc_interesttype        from (select a.i_start_date, --记息开始日                     a.i_end_date, --记息截止日                     a.i_payamount, --付息间隔(年)                     a.i_quoteway, --报价方法(0-全价;1-净价)                     a.en_year_rate, --票面利率                     a.en_price, --发行价格                     a.I_CASH_DATE, --兑付日                     a.en_facevalue, --每百元面值到期兑付额(贴现债券)=面值                     a.i_redeem,                     a.i_redemption,                     a.i_redeemdate,                     a.i_redemptiondate,                     a.vc_coupontype,                     a.vc_interesttype                from bondparams a               where (a.i_account_id = 0 or (p_i_fund_id = a.i_account_id))                 and a.vc_stock_code = p_vc_Stock_Code               order by a.i_account_id desc) t       where rownum < 2; --只取首记录;    exception      when no_data_found then        return 0;    end;  end if;

      --浮动利率  if pvar_vc_interesttype = '2' then    if p_en_year_rate <> -1 then      pvar_i_c := p_en_year_rate;    else      --从浮动利率表取票面利率      begin        select en_year_rate          into pvar_i_c          from (select a.en_year_rate                  from bondparams_floatrate a                 where (a.i_account_id = 0 or (p_i_fund_id = a.i_account_id))                   and a.vc_stock_code = p_vc_Stock_Code                   and a.i_change_date <= p_i_Date                 order by a.i_change_date desc)         where rownum = 1;      exception        when others then          pvar_i_c := 0;      end;    end if;  end if;

      ------如果输入的日期小于记息开始日,或者大于兑付日,返回0-----------------  if (Pvar_i_Date < pvar_InsStartDate) or (Pvar_i_Date > pvar_I_CASH_DATE) then    return 0;  end if;

      ------------------0:表示零息券----------------------  if pvar_i_f = 0 then    pvar_i_f := 1; ---xp 默认0息券的付息间隔为 1  end if;

      if pvar_vc_coupontype = '2' then    --息票品种 为 附息券的    begin      ----------------------------------------------------------      /*xp 20091128 增加赎回、回售日期 含权的判断,使得与中债数据对上                   pvar_i_redeem, --是否可赎回,0不可赎回 1可赎回                   pvar_i_redemption, -- 是否可回售,0不可回售 1可回售                   pvar_i_redeemdate, --赎回日期                   pvar_i_redemptiondate--回售日期      */      if (pvar_i_redeem = 1) then        begin          if (pvar_i_redeemdate < pvar_InsEndDate) and             (pvar_i_redeemdate > Pvar_i_Date) then            pvar_InsEndDate := pvar_i_redeemdate;          end if;

              if (pvar_i_redeemdate < pvar_InsEndDate) and             (pvar_i_redeemdate < Pvar_i_Date) then            pvar_InsStartDate := pvar_i_redeemdate;          end if;

            end;      end if;

          if (pvar_i_redemption = 1) then        begin          if (pvar_i_redeemdate < pvar_InsEndDate) and             (pvar_i_redemptiondate > Pvar_i_Date) then            pvar_InsEndDate := pvar_i_redemptiondate;          end if;

              if (pvar_i_redeemdate < pvar_InsEndDate) and             (pvar_i_redemptiondate < Pvar_i_Date) then            pvar_InsStartDate := pvar_i_redemptiondate;          end if;        end;      end if;

          ----------------------------------------------------------

          ----------------对于计息已经停止,且没有兑付的债券,日期取利息截止日期---add:2009.07.30---------------------------      if (Pvar_i_Date >= pvar_InsEndDate) and         (Pvar_i_Date <= pvar_I_CASH_DATE) then        Pvar_i_Date := pvar_InsEndDate;      end if;      -------通过计算得到的参数--------      pvar_payInsDays := 12 / pvar_i_f; --付息间隔月数      if pvar_payInsDays = 0 then        pvar_i_Result := 0;        return pvar_i_Result;      end if;

          --获取已经付息的次数      /*        如果计息开始日 与 付息日 的 日期号(dd)对不上。则开始计息日的月份+1      */      if (to_char(to_date(pvar_InsStartDate, 'yyyymmdd'), 'mm') <>         to_char(to_date(pvar_InsEndDate, 'yyyymmdd'), 'mm')) then        pvar_InsStartDate := to_number(to_char(add_months(to_date(pvar_InsStartDate,                                                                  'yyyymmdd'),                                                          1),                                               'yyyymm') ||                                       to_char(to_date(pvar_InsEndDate,                                                       'yyyymmdd'),                                               'dd'));      end if;      select floor(months_between(to_date(pvar_i_Date, 'yyyymmdd'),                                  to_date(pvar_InsStartDate, 'yyyymmdd')) /                   pvar_payInsDays)        into pvar_i_Months        FROM DUAL;      /*        --xp 20091128 解决起息日 与 付息截止日,日期不一样,导致利息计算出错        if ( to_char(to_date(pvar_InsStartDate, 'yyyymmdd'),'mm') <> to_char(to_date(pvar_InsEndDate, 'yyyymmdd'),'mm') ) then         if (pvar_InsEndDate = pvar_InsEndDate_old) then            pvar_i_Months := pvar_i_Months-1;         end if;        end if;      */      ------------------------------------------------------------------

          --xp 20091128 解决日期为2月28,加入月份后,日期非28,为31的情况,导致计算结果存在误差。      --pvar_lastInsDays := to_number(to_char(add_months(to_date(pvar_InsStartDate, 'yyyymmdd'),(pvar_payInsDays *pvar_i_Months)),'yyyymm')      --                              || to_char(to_date(pvar_InsEndDate,'yyyymmdd'),'dd')); --上一次付息的日期      ------------------------------------------------------------------      --暂时先不按照xp上面方法,上面构造出的日期会有问题      pvar_InsMaybe := to_number(to_char(add_months(to_date(pvar_InsStartDate,                                                            'yyyymmdd'),                                                    (pvar_payInsDays *                                                    pvar_i_Months)),                                         'yyyymmdd'));

          if to_number(to_char(to_date(pvar_InsMaybe, 'yyyymmdd'), 'dd')) <>         to_number(to_char(to_date(pvar_InsStartDate, 'yyyymmdd'), 'dd')) then        begin          if to_number(to_char(to_date(pvar_InsMaybe, 'yyyymmdd'), 'dd')) >             to_number(to_char(to_date(pvar_InsStartDate, 'yyyymmdd'), 'dd')) then            pvar_i_quoteway := to_number(to_char(to_date(pvar_InsStartDate,                                                         'yyyymmdd'),                                                 'dd'));          else            pvar_i_quoteway := to_number(to_char(to_date(pvar_InsMaybe,                                                         'yyyymmdd'),                                                 'dd'));          end if;          pvar_InsMaybe := to_number(to_char(add_months(to_date(pvar_InsStartDate,                                                                'yyyymmdd'),                                                        (pvar_payInsDays *                                                        pvar_i_Months)),                                             'yyyymm') ||                                     to_char(pvar_i_quoteway));        end;      end if;      pvar_lastInsDays := pvar_InsMaybe;

          --xp 20091128 本次付息日=传入交易日,那么当日不计息      if to_number(to_char(add_months(to_date(pvar_lastInsDays, 'yyyymmdd'),                                      pvar_payInsDays),                           'yyyymmdd')) = pvar_i_Date then        return 0;      end if;      pvar_i_t := to_date(pvar_i_Date, 'yyyymmdd') -                  to_date(pvar_lastInsDays, 'yyyymmdd') + p_i_flag; --起息日或上一付息日至估值日的实际天数      /*        if pvar_InsEndDate <> to_number(to_char(add_months(to_date(pvar_lastInsDays, 'yyyymmdd'),pvar_payInsDays),'yyyymmdd')) then          pvar_i_TS :=  to_date(pvar_InsEndDate, 'yyyymmdd')                      - to_date(pvar_lastInsDays, 'yyyymmdd'); ---本付息周期的实际天数        else          pvar_i_TS :=  add_months(to_date(pvar_lastInsDays, 'yyyymmdd'),pvar_payInsDays)                      - to_date(pvar_lastInsDays, 'yyyymmdd'); ---本付息周期的实际天数        end if;      */

          pvar_InsMaybe := to_number(to_char(add_months(to_date(pvar_lastInsDays,                                                            'yyyymmdd'),                                                    pvar_payInsDays),                                         'yyyymmdd'));      if to_number(to_char(to_date(pvar_InsMaybe, 'yyyymmdd'), 'dd')) <>         to_number(to_char(to_date(pvar_InsStartDate, 'yyyymmdd'), 'dd')) then        begin          if to_number(to_char(to_date(pvar_InsMaybe, 'yyyymmdd'), 'dd')) >             to_number(to_char(to_date(pvar_InsStartDate, 'yyyymmdd'), 'dd')) then            pvar_i_quoteway := to_number(to_char(to_date(pvar_InsStartDate,                                                         'yyyymmdd'),                                                 'dd'));          else            pvar_i_quoteway := to_number(to_char(to_date(pvar_InsMaybe,                                                         'yyyymmdd'),                                                 'dd'));          end if;          pvar_InsMaybe := to_number(to_char(add_months(to_date(pvar_lastInsDays,                                                                'yyyymmdd'),                                                        pvar_payInsDays),                                             'yyyymm') ||                                     to_char(pvar_i_quoteway));        end;      end if;      if pvar_i_f=2 then      --本付息周期的实际天数,根据兑息日在上半年还是下半年来计算        if pvar_lastInsDays<=substring(to_char(pvar_lastInsDays), 1, 4) || '0630' then          pvar_i_TS := to_date(substring(to_char(pvar_lastInsDays), 1, 4) || '0630','yyyymmdd')          -to_date(substring(to_char(pvar_lastInsDays), 1, 4) || '0101','yyyymmdd')+1;        else          pvar_i_TS := to_date(substring(to_char(pvar_lastInsDays), 1, 4) || '1231','yyyymmdd')          -to_date(substring(to_char(pvar_lastInsDays), 1, 4) || '0701','yyyymmdd')+1; ---本付息周期的实际天数        end if;       else      pvar_i_TS := to_date(pvar_InsMaybe, 'yyyymmdd') -                   to_date(pvar_lastInsDays, 'yyyymmdd'); ---本付息周期的实际天数       end if;    end;  else    begin      pvar_i_t := to_date(pvar_i_Date, 'yyyymmdd') -                  to_date(pvar_InsStartDate, 'yyyymmdd') + p_i_flag; --起息日至估值日的实际天数    end;  end if;  ------------------------------------------------------------------  pvar_i_tt := to_date(pvar_InsEndDate, 'yyyymmdd') -               to_date(pvar_InsStartDate, 'yyyymmdd'); --+ 1; --起息日至到期兑付日的实际天数

      select add_months(trunc(sysdate, 'year'), 12) - trunc(sysdate, 'year')    into pvar_i_TY    from dual; ----本付息周期所在计息年度的实际天数  -- pvar_i_f := 1 / pvar_en_year_rate; --一年内付息次数  pvar_i_K := floor((to_date(pvar_i_Date, 'yyyymmdd') -                    to_date(pvar_InsStartDate, 'yyyymmdd')) / 365); --债券起息日至估值日的整年数

      pvar_i_M := pvar_i_mm;  --------------获取脚本计算公式------------  begin    select VC_FORMULA      into pvar_vc_Script      from (select nvl(b.VC_FORMULA, ' ') as VC_FORMULA              from BONDPARAMS a              left join CALCINSMETIC b on a.Vc_Formulacode = b.vc_cim_code             where (a.i_account_id = 0 or (p_i_fund_id = a.i_account_id))               and a.vc_stock_code = p_vc_Stock_Code             order by a.i_account_id desc) t     where rownum < 2; --只取首记录;  exception    when no_data_found then      return pvar_i_Result;  end;  if pvar_vc_Script = ' ' then    return 0;  end if;  ------------------参数传入公式计算-------------------------  pvar_vc_Script := upper(pvar_vc_Script);  pvar_vc_Script := replace(pvar_vc_Script, upper('pvar_i_c'), pvar_i_c);  pvar_vc_Script := replace(pvar_vc_Script, upper('pvar_i_TS'), pvar_i_TS);  pvar_vc_Script := replace(pvar_vc_Script, upper('pvar_i_tt'), pvar_i_tt);  pvar_vc_Script := replace(pvar_vc_Script, upper('pvar_i_TY'), pvar_i_TY);  pvar_vc_Script := replace(pvar_vc_Script, upper('pvar_i_t'), pvar_i_t);

      pvar_vc_Script := replace(pvar_vc_Script, upper('pvar_i_mm'), pvar_i_mm);  pvar_vc_Script := replace(pvar_vc_Script, upper('pvar_i_M'), pvar_i_M);  pvar_vc_Script := replace(pvar_vc_Script, upper('pvar_i_f'), pvar_i_f);  pvar_vc_Script := replace(pvar_vc_Script, upper('pvar_i_K'), pvar_i_K);  pvar_vc_Script := replace(pvar_vc_Script, upper('pvar_i_Pd'), pvar_i_Pd);  pvar_vc_SQL    := replace('select pvar_vc_Script from dual',                            'pvar_vc_Script',                            pvar_vc_Script);  begin    execute immediate pvar_vc_SQL      into pvar_i_Result;  exception    when others then      pvar_i_Result := 0;  end;  return pvar_i_Result;end;

    最新回复(0)