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

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;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值