Program to calculate bonds
hi,
I'm making a program to calculate price or yield for Bonds (with regulation annually, semiannually and so on, financial or actual year calculation).
Thanks to Dale (DrD) for som tips about "Solve"
I need help (Franz?) to test and improve it, as I think my formulas are "enough" correct, but perhaps not 100%...
I'm comparing it with some results given by HP 12C (see here the Guide), but they differs for 0.2 or less from results of my program; maybe there is only a problem or rounding (or not)...
For "zero coupon" bonds input 0 as "coupon", to calculate the price.
After the program will be enough robust I'll implement better menu and a formula for Options and Black Schole formula (but for that I need more help, hi)...
Thank you in advance for help!
Salvo
EDIT: the program is now in the Software Library of the Forum
The code:
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
|