Post Reply 
Bonds
06-01-2015, 09:20 AM (This post was last modified: 06-01-2015 04:22 PM by salvomic.)
Post: #1
Bonds
hi,
I would present a program useful to calculate price and yield of a Bond.
The program treat Bonds with coupons paid annually or semi-annually (or other ends) and also "Zero bonds", both for "actual year" and "financial year" (30/360).

For some examples see HP 12C User Guide or here.

Some examples may differ from the calculations made by HP 12C but always below 0.1, due to different rounding for the numbers...

Enjoy and let me know if you have further improvement.

Salvo M.

Code:

smenu();

EXPORT Bonds()
BEGIN
smenu();
END;

EXPORT Price()
// by Salvo Micciché 2015
// For Zero Coupon bonds input 0 in "Coupon" field
BEGIN
  local mesg, days1, days2, toReg, N, finAct;
  local sd, sm, sy, md, mm, my, ann, nextReg;
  local coupon, yi, years, price, inter, dayPer;
  local m1, d1;
  input ({ {sd,[0],{15,15,1}}, 
  {sm,{"1","2","3", "4", "5", "6", "7", "8", "9", "10", "11", "12"}, {40,15,1}}, 
  {sy,[0],{70,20,1}},
  {md,[0],{15,15,2}}, 
  {mm,{"1","2","3", "4", "5", "6", "7", "8", "9", "10", "11", "12"}, {40,15,2}}, 
  {my,[0],{70,20,2}},
  {coupon,[0],{40,15,4}}, {yi,[0], {75,15,4}},
  {ann,[0], {40,15,5}}, {finAct,2,{85,2, 5}}
  }, 
  "Price of Bond (maturity 100)", {"sd", "sm", "sy", "md", "mm", "my", 
  "Coupon", "y%", "ann", "Financial"}, 
  {"Settlement day", "Settlement month", "Settlement year (purchase)", 
  "Maturity day", "Maturity month", "Maturity year (regulation)", 
  "Coupon payment % (0 for zero coupon)", "yield %", "n. of annuality (i.e 2=semi)", "Financial year (360)"}, 
  {1, 0, 0, 1, 0, 0, 0, 0, 0, 0 }, {1, 0, 2015, 1, 0, 2015, 6.75, 4.75, 2, 0} );

  sd:=EVAL(sd); sm:=EVAL(sm);
  md:=EVAL(md); mm:=EVAL(mm);
  sy:=EVAL(sy); my:=EVAL(my);
  days1 := sy+sm/100+sd/10000;
  days2 := my+mm/100+md/10000;
  toReg := sy+mm/100+md/10000; // days to the regulation
  years := my-sy; // years to the maturity
  IF years<1 THEN years:= 1; END;
  IF (finAct==0) THEN
  N:= DDAYS(days1, days2);
  IF (days1>toReg) THEN nextReg:=DATEADD(toReg,IP(365/ann)); ELSE nextReg:=toReg; END;
  toReg := DDAYS(days1, nextReg);
  dayPer := IP(365/ann);
  ELSE
  N:= 30*12*years;
  IF (days1>toReg) THEN nextReg:=DATEADD(toReg,IP(360/ann)); ELSE nextReg:=toReg; END;
  m1:=IP(FP(nextReg)*100); d1:=FP(FP(nextReg)*100)*100;
  toReg:= 30*(m1-sm)+d1-sd;
  dayPer:= IP(360/ann);
  END; // if

  price := (coupon/ann)*( (1-1/(1+(yi/(ann*100)))^(ann*years)) / (yi/(ann*100)) ) + 100/(1+(yi/(ann*100)))^(ann*years);
  inter := (coupon/ann)*((dayPer - toReg)/dayPer);
  IF (coupon == 0) THEN // Zero Coupon
  RECT_P();
    TEXTOUT_P("Zero Coupon", 10, 50);
    TEXTOUT_P("from " + sd + "-" + sm + "-" + sy + " to " + md + "-" + mm + "-" + my , 10, 65 );
    TEXTOUT_P("Price of Bond: " + price, 10, 85);
    TEXTOUT_P("Paid " + ann + " times per year", 10, 105);
    TEXTOUT_P("Press ESC to continue", 10, 130);
  ELSE
  RECT_P();
    TEXTOUT_P("Days: " + N + " to the end (" + years + " years)", 10, 50);
   TEXTOUT_P("from " + sd + "-" + sm + "-" + sy + " to " + md + "-" + mm + "-" + my , 10, 65 );
    TEXTOUT_P("Days to next regulation " + toReg, 10, 85);
    TEXTOUT_P("Price of Bond: " + price, 10, 105);
    TEXTOUT_P("Paid " + ann + " times per year", 10, 125);
    TEXTOUT_P("Interest: " + inter, 10, 145);
    TEXTOUT_P("paid for " + EVAL(dayPer-toReg) + " days", 10, 165);
    TEXTOUT_P("Press ESC to continue", 10, 190);
  END; //if
  WAIT;
smenu();
  RETURN {ROUND(price, 3), ROUND(inter,3), ROUND(price+inter,3)};

END;

EXPORT Yield()
BEGIN
  local mesg, days1, days2, toReg, N, finAct;
  local sd, sm, sy, md, mm, my, years, yield;
  local coupon, price, ann, inter, dayPer, nextReg;
  local d1, m1;
  input ({ {sd,[0],{15,15,1}}, 
  {sm,{"1","2","3", "4", "5", "6", "7", "8", "9", "10", "11", "12"}, {40,15,1}}, 
  {sy,[0],{70,20,1}},
  {md,[0],{15,15,2}}, 
  {mm,{"1","2","3", "4", "5", "6", "7", "8", "9", "10", "11", "12"}, {40,15,2}}, 
  {my,[0],{70,20,2}},
  {coupon,[0],{40,15,4}}, {price,[0], {75,15,4}},
  {ann,[0], {40,15,5}}, {finAct,2,{85,2, 5}}
  }, 
  "Bond YTM: yield to maturity", {"sd", "sm", "sy", "md", "mm", "my", 
  "Coupon", "Price", "annu", "Financial"}, 
  {"Settlement day", "Settlement month", "Settlement year (purchase)", 
  "Maturity day", "Maturity month", "Maturity year (regulation)", 
  "Coupon payment % (0 for zero coupon)", "Price now", "n. of annuality (i.e 2=semi)", "Financial year (360)"}, 
  {1, 0, 0, 1, 0, 0, 0, 0, 0, 0 }, {1, 0, 2015, 1, 0, 2015, 6.75, 120, 2, 0} );

  sd:=EVAL(sd); sm:=EVAL(sm);
  md:=EVAL(md); mm:=EVAL(mm);
  sy:=EVAL(sy); my:=EVAL(my);
  days1 := sy+sm/100+sd/10000;
  days2 := my+mm/100+md/10000;
  toReg := sy+mm/100+md/10000; // days to the regulation
  years := my-sy; // years to the maturity
  IF years<1 THEN years:= 1; END;
  IF (finAct==0) THEN
  N:= DDAYS(days1, days2);
  IF (days1>toReg) THEN nextReg:=DATEADD(toReg,IP(365/ann)); ELSE nextReg:=toReg; END;
  toReg := DDAYS(days1, nextReg);
  dayPer := IP(365/ann);
  ELSE
  N:= 30*12*years;
  IF (days1>toReg) THEN nextReg:=DATEADD(toReg,IP(360/ann)); ELSE nextReg:=toReg; END;
  m1:=IP(FP(nextReg)*100); d1:=FP(FP(nextReg)*100)*100;
  toReg:= 30*(m1-sm)+d1-sd;
  dayPer:= IP(360/ann);
  END; // if

  C:= coupon; A:= ann; Y:= years; P:= price;
  // yield := Solve.SOLVE((C/A)*( (1-1/(1+(X/A))^(A*Y)) / (X/A) ) + 100/(1+(X/A))^(A*Y) = P, X);
  yield := FNROOT((C/A)*( (1-1/(1+(X/A))^(A*Y)) / (X/A) ) + 100/(1+(X/A))^(A*Y) = P, X);
  IF (coupon==0) THEN // Zero Coupon
RECT_P();
    TEXTOUT_P("Zero Coupon", 10, 50);
    TEXTOUT_P("from " + sd + "-" + sm + "-" + sy + " to " + md + "-" + mm + "-" + my , 10, 65 );
    TEXTOUT_P("Price of Bond: " + price, 10, 85);
    TEXTOUT_P("paid " + ann + " times per year", 10, 105);
    TEXTOUT_P("Yield to Maturity: " + ROUND(100*yield,3) + "%", 10, 125);
    TEXTOUT_P("Press ESC to continue", 10, 150);
  ELSE
RECT_P();
    TEXTOUT_P("Days: " + N + " to the end (" + years + " years)", 10, 50);
    TEXTOUT_P("from " + sd + "-" + sm + "-" + sy + " to " + md + "-" + mm + "-" + my , 10, 65 );
   TEXTOUT_P("Days to next regulation " + toReg, 10, 85);
    TEXTOUT_P("Price of Bond: " + price, 10, 105);
   TEXTOUT_P("paid " + ann + " times per year", 10, 125);
    TEXTOUT_P("Yield to Maturity: " + ROUND(100*yield,3) + "%", 10, 145);
    TEXTOUT_P("Press ESC to continue", 10, 170);
  END; //if
  WAIT;
  smenu();
  RETURN ROUND(100*yield,3);

END;

smenu()
BEGIN
  local ch;
  CHOOSE(ch, "Bonds: price, YTM, interest", "Price", "Yield", "Quit");
  CASE
   IF ch==1 THEN Price(); END;
   IF ch==2 THEN Yield(); END;
   IF ch==3 THEN RETURN; END;
  DEFAULT
  END; // case
END;

∫aL√0mic (IT9CLU) :: HP Prime 50g 41CX 71b 42s 39s 35s 12C 15C - DM42, DM41X - WP34s Prime Soft. Lib
Visit this user's website Find all posts by this user
Quote this message in a reply
Post Reply 


Messages In This Thread
Bonds - salvomic - 06-01-2015 09:20 AM
RE: Bonds - Randall - 08-20-2017, 09:40 PM
RE: Bonds - salvomic - 08-21-2017, 09:48 AM



User(s) browsing this thread: 1 Guest(s)