HP Forums

Full Version: Solve: "bad guess(es)" error...
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
hi,
why this code
Code:

EXPORT provasol()
BEGIN
local yield, coupon, ann, years, price;
coupon:=6.75;
ann:=2;
years:=14;
price:=122.125;
yield := Solve.SOLVE((coupon/ann)*( (1-1/(1+(X/ann))^(ann*years)) / (X/ann) ) + 100/(1+(X/ann))^(ann*years) = price, X);
RETURN yield;
END;

gives error "Bad Guesses"?
If I try with the values in Home I get the correct answer: 0.0459035...
Code:

Solve.SOLVE((6.75/2)*( (1-1/(1+(X/2))^(2*14)) / (X/2) ) + 100/(1+(X/2))^(2*14) = 122.125, X);

Thank you
Salvo
Hi Salvo;

The program's local vars don't persist within the Solve app (out of scope). If you use Globals (see the reserved vars in the code below), the program works fine.

<<A subroutine *could* be used to pass locals to reserved vars, and return the results back to yield, if necessary.>>

Code:

EXPORT provasol()
BEGIN
  local yield, coupon, ann, years, price;

// Using reserved vars as globals
  C:=6.75;
  A:=2;
  Y:=14;
  P:=122.125;

//  Locals don't persist in Solve App
  //coupon:=6.75;
  //ann:=2;
  //years:=14;
  //price:=122.125;

  //yield := Solve.SOLVE((coupon/ann)*( (1-1/(1+(X/ann))^(ann*years)) / (X/ann) ) + 100/(1+(X/ann))^(ann*years) = price, X);
  
  yield := Solve.SOLVE((C/A)*( (1-1/(1+(X/A))^(A*Y)) / (X/A) ) + 100/(1+(X/A))^(A*Y) = P, X);

  RETURN yield;
END;
(05-31-2015 10:31 AM)DrD Wrote: [ -> ]Hi Salvo;

The program's local vars don't persist within the Solve app (out of scope). If you use Globals (see the reserved vars in the code below), the program works fine.

<<A subroutine *could* be used to pass locals to reserved vars, and return the results back to yield, if necessary.>>

thank you!
It works.

I'm using it in the first version for my program to calc Bonds (for now, however, this one, with the flag to calculate "financial year" -30/360- gives result for price a little different from the 12C, and sure my formulas aren't correct, and the Prime reset calculating yield for this option: please, try, advice...)

here there are the code:
Code:

EXPORT Bonds()
BEGIN

END;

EXPORT Price()
BEGIN
  local mesg, days1, days2, toReg, N, finAct;
  local sd, sm, sy, md, mm, my, ann;
  local coupon, yi, years, price, inter, dayPer;
  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 %", "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==0 THEN years:= 1; END;

  IF (finAct==0) THEN
  N:= DDAYS(days1, days2);
  toReg := DDAYS(days1, toReg);
  dayPer := IP(365/ann);
  ELSE
  N:= 30*(mm-sm)+md-sd;
  toReg:= 30*(mm-sm)+md-sd;
  dayPer:= 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);
  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("Price of Bond: " + price, 10, 85);
  TEXTOUT_P("Paid " + ann + " times per year", 10, 105);
  TEXTOUT_P("Interest: " + inter, 10, 125);
  TEXTOUT_P("Press ESC to continue", 10, 150);
  WAIT;
  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;
  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 %", "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==0 THEN years:= 1; END;

  IF (finAct==0) THEN
  N:= DDAYS(days1, days2);
  toReg := DDAYS(days1, toReg);
  dayPer := IP(365/ann);
  ELSE
  N:= 30*(mm-sm)+md-sd;
  toReg:= 30*(mm-sm)+md-sd;
  dayPer:= 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);
  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("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);
  WAIT;
  RETURN ROUND(100*yield,3);

END;
I'd also recommend using FNROOT instead. That is the normal root finder routine that is not an app function.
(06-01-2015 04:04 PM)Tim Wessman Wrote: [ -> ]I'd also recommend using FNROOT instead. That is the normal root finder routine that is not an app function.

Thank you Tim, I'll try it soon for my program!

Salvo
Reference URL's