*
*  BONDS.PRG
*  Manual example 7.4
*
compute nbonds=20
all nbonds
open data bonds.xls
data(format=xls,org=cols)
*
*  The data set consists of US Treasury bonds, which have
*  semi-annual coupons, but with the coupon stated in annual terms.
*  The maturity series also provides annual information. The coupon
*  is divided by two and the maturity multiplied by 2 to give values
*  for the actual coupon period.
*
set coupon   = coupon / 2
set maturity = maturity * 2
*
nonlin a0 a1 a2
compute a0=.030,a1=a2=0.0
compute cusp=2.0
declare real totalerror
*
*   We're using method=genetic to probe the parameter space more fully.
*
*   FIND loops over the evaluation instructions.
*
find(trace,method=genetic,iters=1000) minimum totalerror
   compute totalerror=0
*
*     Loop over the bonds
*
   do bond=1,nbonds
*
*        pv will be the present value of the bond cash flow
*        using the current parameter settings.
*
      compute mdate=maturity(bond)
      compute pv   =100.0 * $
         exp(-mdate*(a0+mdate*a1+%max(mdate-cusp,0.0)*a2))
*
*        Walk backwards through the coupons.
*
      compute cdate=mdate
      while (cdate > 0.0) {
         compute pv=pv + coupon(bond) * $
           exp(-cdate*(a0+cdate*a1+%max(cdate-cusp,0.0)*a2))
         compute cdate=cdate-1
      }
*
*        Adjust for simple interest payable by the purchaser
*        for the initial coupon. cdate will be -(fraction of period).
*
      compute pv=pv+coupon(bond)*cdate
      compute totalerror=totalerror+(value(bond)-pv)**2
   end do bond
end find
*
*   Graph the estimated yield curve from maturities of 0->10 periods (5 years).
*   After the present value function is evaluated, the maturity is switched to
*   years and the annual yield computed.
*
set testm 1 50  = .20*t
set pvalue 1 50 = $
   exp(-testm*(a0+testm*a1+%max(testm-cusp,0.0)*a2))
set testm 1 50  = testm/2
set yield 1 50  = -log(pvalue)/testm
scatter(style=line,window='Yield Curve')
# testm yield


