HP Forums

Full Version: Leasing: advance payments
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
hi all,
this program calculates leasing with advanced payments (i.e duration: 60 months, 3 advanced payments (or at the end)...), giving monthly payment (less the advanced...) and calculating the monthly and annual yield (rate).
The program calculate also the payment of a Leasing with residual value (for payment and yield, with the IRR method).
Theese functions are similar to those in the HP 12C calculator.

Menu: Leasing_advpmt() - Leasing_yield() - Leasing_residual() - Leasing_res_yield()

Enjoy!

Salvo Micciché

EDIT: new version with a choose menu

Code:

Menu();

Leasing()
BEGIN
// by Salvo Micciché 2015
Menu();
END;

EXPORT Leasing_advpmt()
// solve for monthly payment
BEGIN
LOCAL r, n, fpmt, val;
INPUT ({r, n, fpmt, val},"Leasing: advance payments", {"yield%", "n lease", "n pmt advance", "value"}, 
{"Yield (rate)%", "Duration of lease", "Num of advance payments", "Value of Leasing"}, {0,0, 0, 0},{0,12, 3,0});
LOCAL npmt, pv;
npmt:= n - fpmt;
pv:= Finance.CalcPV(npmt, r, -1, 0, 12, 12, 1);
PRINT;
PRINT(
"Leasing with advanced payments

Value of lease: " + EVAL(val) + "
Duration of lease: " + EVAL(n) + "
Advanced payments n.: " + EVAL(fpmt) + "
Periodic payments n.: " + EVAL(npmt) + "
Yield (rate): " + EVAL(r) + "% 
Monthly payment: " + EVAL(val/(pv+fpmt))
);
WAIT (0);
Menu();
RETURN val/(pv+fpmt);
END;

EXPORT Leasing_yield()
// solve for yield
BEGIN
LOCAL n, fpmt, val, pmt, yield, npmt, pv;
INPUT ({n, fpmt, val, pmt},"Leasing: calc yield", {"n lease", "n pmt advance", "value", "payment"}, 
{"Duration of lease", "Num of advance payments", "Value of Leasing", "Monthly payment"}, {0,0, 0, 0},{12,3, 0, 0});
npmt:= n - fpmt;
pv:= fpmt*pmt-val;
yield:= Finance.CalcIPYR(npmt, pv, pmt, 0, 12, 12, 1);
PRINT;
PRINT ("Leasing: solving for Yield

Value of lease (loan): " + EVAL(val) + "
Duration of lease: " + EVAL(n) + "
Advanced payments n.: " + EVAL(fpmt) + "
Periodic payments n.: " + EVAL(npmt) + "
Monthly Payment: " + EVAL(pmt) + "
Monthly yield: " + EVAL(yield/12) + "% 
Yearly yield: " + EVAL(yield) + "%"
);
WAIT (0);
Menu();
RETURN yield;
END;

EXPORT Leasing_residual()
// Leasing with residual value, solve for monthly payment
BEGIN
LOCAL n, r, val, resval, fpmt, att, pv;
LOCAL npmt, pv2;
INPUT ({n, fpmt, r, val, resval},"Leasing with residual", {"n lease", "n adv pmt", "yield%", "value", "res value"}, 
{"Duration of lease", "Num advanced payments", "Yield (rate)%", "Value of Leasing (loan)", "Residual value"}, 
{0,0, 0, 0, 0},{12, 3, 0, 0, 0});
pv:= Finance.CalcPV(n, r,0, resval, 12, 12, 1);
att:= pv + val;
npmt:= n - fpmt;
pv2:= Finance.CalcPV(npmt, r, -1, 0, 12, 12, 1);
pv2:= pv2 + fpmt;
PRINT;
PRINT ("Leasing with residual 

Value of lease (loan): " + EVAL(val) + "
Residual value: " + EVAL(resval) + "
Duration of lease: " + EVAL(n) + "
Advanced payments n.: " + EVAL(fpmt) + "
Periodic payments n.: " + EVAL(npmt) + "
Yield (rate): " + EVAL(r) + "% 
Monthly payment: " + EVAL(att/pv2)
);
WAIT (0);
Menu();
RETURN att/pv2;
END;

EXPORT Leasing_res_yield()
// Leasing with residual value, solve for yield (rate)
BEGIN
LOCAL n, fpmt, val, pmt, resval, j, irr;
LOCAL flows:={}, yield, npmt, netamt;
INPUT ({n, fpmt, val, resval, pmt},"Leasing: calc yield", {"n lease", "n pmt advance", "value", "res val", "payment"}, 
{"Duration of lease", "Num of advance payments", "Value of Leasing", "REsidual value", "Monthly payment"},
{0,0, 0, 0, 0},{36,2, 0, 0, 0});
npmt:= n - fpmt;
netamt:= -val+pmt*fpmt; // net amount (-value + payment*advanced num pmt)
flows:= append(flows, netamt); // create list, append net amount
FOR j FROM 1 TO npmt DO
flows:= append (flows, pmt); // append payment, (num pmt - advanced pmt) times
END; // for
FOR j  FROM 1 TO (fpmt-1) DO
flows:= append (flows, 0);  // append 0, (mum advanced pmt minus 1)
END; // for
flows:= append(flows, resval); // append residual value
L1:= flows;
irr:= Solve.SOLVE(ΣLIST(MAKELIST((L1(I)/X^(I-1)),I,1,SIZE(L1))),X)-1;
// Solve.SOLVE() could not always work, but give only a secure value, solve() works better, butr gives more values
PRINT;
PRINT ("Leasing with advanced payments and residual value: yield 
Solved for IRR

Value of lease (loan): " + EVAL(val) + "
Residual value: " + EVAL(resval) + "
Duration of lease: " + EVAL(n) + "
Advanced payments n.: " + EVAL(fpmt) + "
Periodic payments n.: " + EVAL(npmt) + "
Monthly Payment: " + EVAL(pmt) + "
Net amount of cash advanced: " + EVAL(netamt) + "
Monthly yield: " + EVAL(irr*100) + "% 
Yearly yield: " + EVAL(12*irr*100) + "%"

);
WAIT (0);
Menu();
RETURN 12*irr; // yearly yield (IRR) in decimal
END;

EXPORT Menu()
BEGIN
LOCAL ch;
CHOOSE(ch, "Leasing", "Leasing with advanced payments", "Leasing: solving for Yield", 
"Leasing with residual", "Leasing residual: yield", "Quit");

CASE
IF ch==1 THEN Leasing_advpmt(); END;
IF ch==2 THEN Leasing_yield(); END;
IF ch==3 THEN Leasing_residual(); END;
IF ch==4 THEN Leasing_res_yield(); END;
IF ch==5 THEN RETURN; END;
DEFAULT 
KILL;
END; // case
END;
This is really good - the prompts are informative and information returned is excellent. Well done!
(05-21-2015 01:57 PM)Eddie W. Shore Wrote: [ -> ]This is really good - the prompts are informative and information returned is excellent. Well done!

thanks a lot, Eddie!

Here there is also a "graphic" version with a "Drawmenu".
This export two variables (LS_PMT, LS_yield) in Vars->User->Leasing
Now it should run better, with some hints by the user and friend khapster!

Code:

export LS_PMT:=0;
export LS_yield:={0,0};

// Initialize procedures used in project
EVENTHANDLER();
PUTMENU();
GETMENU();

Leasing_advpmt();
Leasing_yield();
Leasing_residual();
Leasing_res_yield();

// Initialize variables used globally in project
mSEL;
eTYP;
kP;
m;
m1;

EXPORT Leasing()
BEGIN
// Initialize local variables used within this procedure
 LOCAL mx,my,mTXT,EXITPGM;

 // Set the menu text (this is softcoded and determines if a menu item is valid)
 mTXT := {"AdvPmt","Yield","Resid","ResYld","","Quit"};

 // MAIN CODE - Loop until ESC is pressed, then exit the program
 EXITPGM := 0;
 WHILE EXITPGM == 0 DO

   // Clear the screen and draw the menu
   RECT_P();
TEXTOUT_P("Leasing with advanced payments", 30, 10, 5, RGB(255,0,0));
TEXTOUT_P("Advanced payments: calc payment", 25, 50);
TEXTOUT_P("Advanced payments: calc yield", 25, 70);
TEXTOUT_P("Leasing with residual: payment", 25, 90);
TEXTOUT_P("Leasing with residual: yield", 25, 110);
TEXTOUT_P("by Salvo Micciché 2015", 25, 140);
TEXTOUT_P("Credits: Dale (DrD), Eddie W. Shore", 25, 170);
TEXTOUT_P("Cyrille, akmon, kharpster", 25, 190);
   PUTMENU(mTXT);

   // Flush the mouse buffer
   WHILE MOUSE(1) ≥ 0 DO END;

   // Loop until we have a keyboard or mouse event
   REPEAT
     EVENTHANDLER();
   UNTIL eTYP <> "";

    CASE

     // If the event type was a keyboard action then process it
     IF eTYP == "K" THEN
       // If the ESC key was pressed set the program to end
       IF kP == 4 THEN
         EXITPGM := 1;  
       ELSE
         // ESC was not pressed do what you want with the keypress, we are just going to do a TEXTOUT        
       END;        
     END;

     // If the event type was mouse action then process it
     IF eTYP == "M" THEN
       // Convert mouse coordinates to decimal
       mx := B→R(m1(1));  
       my := B→R(m1(2));
       // Determine if mouse coordinates are inside of a valid menu item otherwise return a zero
       GETMENU(mx,my,mTXT);
       // If a valid menu item was selected, do something, we are just going to do a TEXTOUT
       IF mSEL > 0 THEN
         CASE 
          // If menu item 1 was selected display a choose box for the user to select from
           IF mSEL == 1 THEN
             Leasing_advpmt();
           END;
           IF mSEL == 2 THEN
             Leasing_yield(); 
           END;
           IF mSEL == 3 THEN
             Leasing_residual();  

           END;
           IF mSEL == 4 THEN

Leasing_res_yield();
           END;
           IF mSEL == 6 THEN
             EXITPGM := 1;         
           END;
         DEFAULT
           // This is the default action for the menu selection and will only run if no case statement is satisfied

         END;
       ELSE
       // Mouse not in menu, do something if needed
       END;
     END;
   END;  
 END;
END;

// -------------------------------------------------------------------
// Detect keyboard or mouse input (keyboard has priority)
// -------------------------------------------------------------------
EVENTHANDLER()
BEGIN
 eTYP := "";
 kP := GETKEY;
 IF kP <> -1 THEN
   eTYP := "K";
 ELSE
   m := MOUSE;
   m1 := m(1);
   IF  SIZE(m1) > 0 THEN
     eTYP := "M";
   END;
 END;
END;

// ----------------------------------------------
// Draw the menu using the list passed in
// ----------------------------------------------
PUTMENU(mTXT)
BEGIN
 DRAWMENU(mTXT(1),mTXT(2),mTXT(3),mTXT(4),mTXT(5),mTXT(6));
END;

// ------------------------------------------------------------------------------------------
// Get the number of the menu item selected (1-6) by checking mouse position
// Menu items with empty/blank text will return a zero
// ------------------------------------------------------------------------------------------
GETMENU(mx,my,mTXT)
BEGIN
 mSEL := 0;
 IF my≥220 AND my≤239 THEN
   CASE
     IF mx≥0 AND mx≤51 AND mTXT(1)>"" THEN
       mSEL := 1;
     END;
     IF mx≥53 AND mx≤104 AND mTXT(2)>"" THEN
       mSEL := 2;
     END;
     IF mx≥106 AND mx≤157 AND mTXT(3)>"" THEN
       mSEL := 3;
     END;
     IF mx≥159 AND mx≤210AND mTXT(4)>""  THEN
       mSEL := 4;
     END;
     IF mx≥212 AND mx≤263 AND mTXT(5)>"" THEN
       mSEL := 5;
     END;
     IF mx≥265 AND mx≤319 AND mTXT(6)>"" THEN
       mSEL := 6;
     END;
   END;
 END;
END;

// ------------------------------------------------------------------------------------------
// LEASING APPLICATION CODE
// ------------------------------------------------------------------------------------------

Leasing_advpmt()
// solve for monthly payment
// by Salvo Micciché 2015 - Credits: kharpster
BEGIN
LOCAL r, n, fpmt, val;
INPUT ({r, n, fpmt, val},"Leasing: advance payments", {"yield%", "n lease", "n pmt advance", "value"}, 
{"Yield (rate)%", "Duration of lease", "Num of advance payments", "Value of Leasing"}, {0,0, 0, 0},{0,12, 3,0});
LOCAL npmt, pv;
npmt:= n - fpmt;
pv:= Finance.CalcPV(npmt, r, -1, 0, 12, 12, 1);
sto(val/(pv+fpmt), LS_PMT);
RECT_P(0,0,319,219);
TEXTOUT_P("Leasing with advanced payments", 0, 10, 5, RGB(255,0,0));
TEXTOUT_P("Value of lease: " + EVAL(val), 0, 40);
TEXTOUT_P("Duration of lease: " + EVAL(n), 0, 60);
TEXTOUT_P("Advanced payments n.: " + EVAL(fpmt), 0, 80);
TEXTOUT_P("Periodic payments n.: " + EVAL(npmt), 0, 100);
TEXTOUT_P("Yield (rate): " + EVAL(ROUND(r,3)) + "%", 0, 120);
TEXTOUT_P("Monthly payment: " + EVAL(ROUND(val/(pv+fpmt),3)), 0, 140);
WAIT;
RETURN val/(pv+fpmt);
END;


Leasing_yield()
// solve for yield
BEGIN
LOCAL n, fpmt, val, pmt, yield, npmt, pv;
INPUT ({n, fpmt, val, pmt},"Leasing: calc yield", {"n lease", "n pmt advance", "value", "payment"}, 
{"Duration of lease", "Num of advance payments", "Value of Leasing", "Monthly payment"}, {0,0, 0, 0},{12,3, 0, 0});
npmt:= n - fpmt;
pv:= fpmt*pmt-val;
yield:= Finance.CalcIPYR(npmt, pv, pmt, 0, 12, 12, 1);
sto({yield/12, yield},LS_yield);
RECT_P(0,0,319,219);
TEXTOUT_P("Leasing: solving for Yield", 0, 10, 5, RGB(255,0,0));
TEXTOUT_P("Value of lease (loan): " + EVAL(val), 0, 40);
TEXTOUT_P("Duration of lease: " + EVAL(n), 0, 60);
TEXTOUT_P("Advanced payments n.: " + EVAL(fpmt), 0, 80);
TEXTOUT_P("Periodic payments n.: " + EVAL(npmt), 0, 100);
TEXTOUT_P("Monthly Payment: " + EVAL(ROUND(pmt,3)), 0, 120);
TEXTOUT_P("Monthly yield: " + EVAL(ROUND(yield/12,3)) +"%", 0, 140);
TEXTOUT_P("Yearly yield: " + EVAL(ROUND(yield,3)) +"%", 0, 160);
WAIT;
RETURN yield;
END;


Leasing_residual()
// Leasing with residual value, solve for monthly payment
BEGIN
LOCAL n, r, val, resval, fpmt, att, pv;
LOCAL npmt, pv2;
INPUT ({n, fpmt, r, val, resval},"Leasing with residual", {"n lease", "n adv pmt", "yield%", "value", "res value"}, 
{"Duration of lease", "Num advanced payments", "Yield (rate)%", "Value of Leasing (loan)", "Residual value"}, 
{0,0, 0, 0, 0},{12, 3, 0, 0, 0});
pv:= Finance.CalcPV(n, r,0, resval, 12, 12, 1);
att:= pv + val;
npmt:= n - fpmt;
pv2:= Finance.CalcPV(npmt, r, -1, 0, 12, 12, 1);
pv2:= pv2 + fpmt;
sto(att/pv2, LS_PMT);
RECT_P(0,0,319,219);
TEXTOUT_P("Leasing with residual", 0, 10, 5, RGB(255,0,0));
TEXTOUT_P("Value of lease (loan): " + EVAL(val), 0, 40);
TEXTOUT_P("Residual value: " + EVAL(resval), 0, 60);
TEXTOUT_P("Duration of lease: " + EVAL(n), 0, 80);
TEXTOUT_P("Advanced payments n.: " + EVAL(fpmt), 0, 100);
TEXTOUT_P("Periodic payments n.: " + EVAL(npmt), 0, 120);
TEXTOUT_P("Yield (rate): " + EVAL(ROUND(r,3)) + "%", 0, 140);
TEXTOUT_P("Monthly payment: " + EVAL(ROUND(att/pv2,3)), 0, 160);

WAIT;
RETURN att/pv2;
END;

Leasing_res_yield()
// Leasing with residual value, solve for yield (rate)
BEGIN
LOCAL n, fpmt, val, pmt, resval, j, irr;
LOCAL flows:={}, yield, npmt, netamt;
INPUT ({n, fpmt, val, resval, pmt},"Leasing: calc yield", {"n lease", "n pmt advance", "value", "res val", "payment"}, 
{"Duration of lease", "Num of advance payments", "Value of Leasing", "REsidual value", "Monthly payment"},
{0,0, 0, 0, 0},{36,2, 0, 0, 0});
npmt:= n - fpmt;
netamt:= -val+pmt*fpmt; // net amount (-value + payment*advanced num pmt)
flows:= append(flows, netamt); // create list, append net amount
FOR j FROM 1 TO npmt DO
flows:= append (flows, pmt); // append payment, (num pmt - advanced pmt) times
END; // for
FOR j  FROM 1 TO (fpmt-1) DO
flows:= append (flows, 0);  // append 0, (mum advanced pmt minus 1)
END; // for
flows:= append(flows, resval); // append residual value
L1:= flows;
irr:= Solve.SOLVE(ΣLIST(MAKELIST((L1(I)/X^(I-1)),I,1,SIZE(L1))),X)-1;
// Solve.SOLVE() could not always work, but give only a secure value, solve() works better, bur gives more values
sto({irr*100,12*irr*100}, LS_yield);
RECT_P(0,0,319,219);
TEXTOUT_P("Leasing with advanced payments and residual value", 0,10, 3, RGB(255,0,0));
TEXTOUT_P("Solved for yield (rate)", 0,40, 3);
TEXTOUT_P("Value of lease (loan): " + EVAL(val), 0,60);
TEXTOUT_P("Residual value: " + EVAL(resval), 0,80);
TEXTOUT_P("Duration of lease: " + EVAL(n), 0,100);
TEXTOUT_P("Advanced payments n.: " + EVAL(fpmt) + "Periodic pmt n.: " + EVAL(npmt), 0,120);
TEXTOUT_P("Monthly Payment: " + EVAL(ROUND(pmt,3)), 0,140);
TEXTOUT_P("Net amount of cash advanced: " + EVAL(ROUND(netamt,3)), 0,160);
TEXTOUT_P("Monthly yield: " + EVAL(ROUND(irr*100,3)) + "%", 0,180);
TEXTOUT_P("Yearly yield: " + EVAL(ROUND(12*irr*100,3)) + "%", 0,200);
WAIT;
RETURN 12*irr; // yearly yield (IRR) in decimal
END;
New version 2.0 after firmware 10077.
This version (with graphic menu as above) doesn't run with firmwares < 10077.

Code:

// Leasing v 2.0 by Salvo Micciché
// this version runs only with firmware > 10077

export LS_PMT:=0;
export LS_yield:={0,0};

// Initialize procedures used in project
EVENTHANDLER();
PUTMENU();
GETMENU();

Leasing_advpmt();
Leasing_yield();
Leasing_residual();
Leasing_res_yield();

// Initialize variables used globally in project
mSEL;
eTYP;
kP;
m;
m1;

EXPORT Leasing()
BEGIN
// Initialize local variables used within this procedure
 LOCAL mx,my,mTXT,EXITPGM;

 // Set the menu text (this is softcoded and determines if a menu item is valid)
 mTXT := {"AdvPmt","Yield","Resid","ResYld","","Quit"};

 // MAIN CODE - Loop until ESC is pressed, then exit the program
 EXITPGM := 0;
 WHILE EXITPGM == 0 DO

   // Clear the screen and draw the menu
   RECT_P();
TEXTOUT_P("Leasing with advanced payments", 30, 10, 5, RGB(255,0,0));
TEXTOUT_P("Advanced payments: calc payment", 25, 50);
TEXTOUT_P("Advanced payments: calc yield", 25, 70);
TEXTOUT_P("Leasing with residual: payment", 25, 90);
TEXTOUT_P("Leasing with residual: yield", 25, 110);
TEXTOUT_P("by Salvo Micciché 2015", 25, 140);
TEXTOUT_P("Credits: Dale (DrD), Eddie W. Shore", 25, 170);
TEXTOUT_P("Cyrille, akmon, kharpster", 25, 190);
   PUTMENU(mTXT);

   // Flush the mouse buffer
   WHILE MOUSE(1) ≥ 0 DO END;

   // Loop until we have a keyboard or mouse event
   REPEAT
     EVENTHANDLER();
   UNTIL eTYP <> "";

    CASE

     // If the event type was a keyboard action then process it
     IF eTYP == "K" THEN
       // If the ESC key was pressed set the program to end
       IF kP == 4 THEN
         EXITPGM := 1;  
       ELSE
         // ESC was not pressed do what you want with the keypress, we are just going to do a TEXTOUT        
       END;        
     END;

     // If the event type was mouse action then process it
     IF eTYP == "M" THEN
       // Convert mouse coordinates to decimal
       mx := B→R(m1(1));  
       my := B→R(m1(2));
       // Determine if mouse coordinates are inside of a valid menu item otherwise return a zero
       GETMENU(mx,my,mTXT);
       // If a valid menu item was selected, do something, we are just going to do a TEXTOUT
       IF mSEL > 0 THEN
         CASE 
          // If menu item 1 was selected display a choose box for the user to select from
           IF mSEL == 1 THEN
             Leasing_advpmt();
           END;
           IF mSEL == 2 THEN
             Leasing_yield(); 
           END;
           IF mSEL == 3 THEN
             Leasing_residual();  

           END;
           IF mSEL == 4 THEN

Leasing_res_yield();
           END;
           IF mSEL == 6 THEN
             EXITPGM := 1;         
           END;
         DEFAULT
           // This is the default action for the menu selection and will only run if no case statement is satisfied

         END;
       ELSE
       // Mouse not in menu, do something if needed
       END;
     END;
   END;  
 END;
END;

// -------------------------------------------------------------------
// Detect keyboard or mouse input (keyboard has priority)
// -------------------------------------------------------------------
EVENTHANDLER()
BEGIN
 eTYP := "";
 kP := GETKEY;
 IF kP <> -1 THEN
   eTYP := "K";
 ELSE
   m := MOUSE;
   m1 := m(1);
   IF  SIZE(m1) > 0 THEN
     eTYP := "M";
   END;
 END;
END;

// ----------------------------------------------
// Draw the menu using the list passed in
// ----------------------------------------------
PUTMENU(mTXT)
BEGIN
 DRAWMENU(mTXT(1),mTXT(2),mTXT(3),mTXT(4),mTXT(5),mTXT(6));
END;

// ------------------------------------------------------------------------------------------
// Get the number of the menu item selected (1-6) by checking mouse position
// Menu items with empty/blank text will return a zero
// ------------------------------------------------------------------------------------------
GETMENU(mx,my,mTXT)
BEGIN
 mSEL := 0;
 IF my≥220 AND my≤239 THEN
   CASE
     IF mx≥0 AND mx≤51 AND mTXT(1)>"" THEN
       mSEL := 1;
     END;
     IF mx≥53 AND mx≤104 AND mTXT(2)>"" THEN
       mSEL := 2;
     END;
     IF mx≥106 AND mx≤157 AND mTXT(3)>"" THEN
       mSEL := 3;
     END;
     IF mx≥159 AND mx≤210AND mTXT(4)>""  THEN
       mSEL := 4;
     END;
     IF mx≥212 AND mx≤263 AND mTXT(5)>"" THEN
       mSEL := 5;
     END;
     IF mx≥265 AND mx≤319 AND mTXT(6)>"" THEN
       mSEL := 6;
     END;
   END;
 END;
END;

// ------------------------------------------------------------------------------------------
// LEASING APPLICATION CODE
// ------------------------------------------------------------------------------------------

Leasing_advpmt()
// solve for monthly payment
// by Salvo Micciché 2015 - Credits: kharpster
BEGIN
LOCAL r, n, fpmt, val;
INPUT ({r, n, fpmt, val},"Leasing: advance payments", {"yield%", "n lease", "n pmt advance", "value"}, 
{"Yield (rate)%", "Duration of lease", "Num of advance payments", "Value of Leasing"}, {0,0, 0, 0},{0,12, 3,0});
LOCAL npmt, pv;
npmt:= n - fpmt;
pv:= Finance.TvmPV(npmt, r, -1, 0, 12, 12, 1);
sto(val/(pv+fpmt), LS_PMT);
RECT_P(0,0,319,219);
TEXTOUT_P("Leasing with advanced payments", 0, 10, 5, RGB(255,0,0));
TEXTOUT_P("Value of lease: " + EVAL(val), 0, 40);
TEXTOUT_P("Duration of lease: " + EVAL(n), 0, 60);
TEXTOUT_P("Advanced payments n.: " + EVAL(fpmt), 0, 80);
TEXTOUT_P("Periodic payments n.: " + EVAL(npmt), 0, 100);
TEXTOUT_P("Yield (rate): " + EVAL(ROUND(r,3)) + "%", 0, 120);
TEXTOUT_P("Monthly payment: " + EVAL(ROUND(val/(pv+fpmt),3)), 0, 140);
WAIT;
RETURN val/(pv+fpmt);
END;


Leasing_yield()
// solve for yield
BEGIN
LOCAL n, fpmt, val, pmt, yield, npmt, pv;
INPUT ({n, fpmt, val, pmt},"Leasing: calc yield", {"n lease", "n pmt advance", "value", "payment"}, 
{"Duration of lease", "Num of advance payments", "Value of Leasing", "Monthly payment"}, {0,0, 0, 0},{12,3, 0, 0});
npmt:= n - fpmt;
pv:= fpmt*pmt-val;
yield:= Finance.TvmIPYR(npmt, pv, pmt, 0, 12, 12, 1);
sto({yield/12, yield},LS_yield);
RECT_P(0,0,319,219);
TEXTOUT_P("Leasing: solving for Yield", 0, 10, 5, RGB(255,0,0));
TEXTOUT_P("Value of lease (loan): " + EVAL(val), 0, 40);
TEXTOUT_P("Duration of lease: " + EVAL(n), 0, 60);
TEXTOUT_P("Advanced payments n.: " + EVAL(fpmt), 0, 80);
TEXTOUT_P("Periodic payments n.: " + EVAL(npmt), 0, 100);
TEXTOUT_P("Monthly Payment: " + EVAL(ROUND(pmt,3)), 0, 120);
TEXTOUT_P("Monthly yield: " + EVAL(ROUND(yield/12,3)) +"%", 0, 140);
TEXTOUT_P("Yearly yield: " + EVAL(ROUND(yield,3)) +"%", 0, 160);
WAIT;
RETURN yield;
END;


Leasing_residual()
// Leasing with residual value, solve for monthly payment
BEGIN
LOCAL n, r, val, resval, fpmt, att, pv;
LOCAL npmt, pv2;
INPUT ({n, fpmt, r, val, resval},"Leasing with residual", {"n lease", "n adv pmt", "yield%", "value", "res value"}, 
{"Duration of lease", "Num advanced payments", "Yield (rate)%", "Value of Leasing (loan)", "Residual value"}, 
{0,0, 0, 0, 0},{12, 3, 0, 0, 0});
pv:= Finance.TvmPV(n, r,0, resval, 12, 12, 1);
att:= pv + val;
npmt:= n - fpmt;
pv2:= Finance.TvmPV(npmt, r, -1, 0, 12, 12, 1);
pv2:= pv2 + fpmt;
sto(att/pv2, LS_PMT);
RECT_P(0,0,319,219);
TEXTOUT_P("Leasing with residual", 0, 10, 5, RGB(255,0,0));
TEXTOUT_P("Value of lease (loan): " + EVAL(val), 0, 40);
TEXTOUT_P("Residual value: " + EVAL(resval), 0, 60);
TEXTOUT_P("Duration of lease: " + EVAL(n), 0, 80);
TEXTOUT_P("Advanced payments n.: " + EVAL(fpmt), 0, 100);
TEXTOUT_P("Periodic payments n.: " + EVAL(npmt), 0, 120);
TEXTOUT_P("Yield (rate): " + EVAL(ROUND(r,3)) + "%", 0, 140);
TEXTOUT_P("Monthly payment: " + EVAL(ROUND(att/pv2,3)), 0, 160);

WAIT;
RETURN att/pv2;
END;

Leasing_res_yield()
// Leasing with residual value, solve for yield (rate)
BEGIN
LOCAL n, fpmt, val, pmt, resval, j, irr;
LOCAL flows:={}, yield, npmt, netamt;
INPUT ({n, fpmt, val, resval, pmt},"Leasing: calc yield", {"n lease", "n pmt advance", "value", "res val", "payment"}, 
{"Duration of lease", "Num of advance payments", "Value of Leasing", "REsidual value", "Monthly payment"},
{0,0, 0, 0, 0},{36,2, 0, 0, 0});
npmt:= n - fpmt;
netamt:= -val+pmt*fpmt; // net amount (-value + payment*advanced num pmt)
flows:= append(flows, netamt); // create list, append net amount
FOR j FROM 1 TO npmt DO
flows:= append (flows, pmt); // append payment, (num pmt - advanced pmt) times
END; // for
FOR j  FROM 1 TO (fpmt-1) DO
flows:= append (flows, 0);  // append 0, (mum advanced pmt minus 1)
END; // for
flows:= append(flows, resval); // append residual value
L1:= flows;
irr:= Solve.SOLVE(ΣLIST(MAKELIST((L1(I)/X^(I-1)),I,1,SIZE(L1))),X)-1;
// Solve.SOLVE() could not always work, but give only a secure value, solve() works better, bur gives more values
sto({irr*100,12*irr*100}, LS_yield);
RECT_P(0,0,319,219);
TEXTOUT_P("Leasing with advanced payments and residual value", 0,10, 3, RGB(255,0,0));
TEXTOUT_P("Solved for yield (rate)", 0,40, 3);
TEXTOUT_P("Value of lease (loan): " + EVAL(val), 0,60);
TEXTOUT_P("Residual value: " + EVAL(resval), 0,80);
TEXTOUT_P("Duration of lease: " + EVAL(n), 0,100);
TEXTOUT_P("Advanced payments n.: " + EVAL(fpmt) + "Periodic pmt n.: " + EVAL(npmt), 0,120);
TEXTOUT_P("Monthly Payment: " + EVAL(ROUND(pmt,3)), 0,140);
TEXTOUT_P("Net amount of cash advanced: " + EVAL(ROUND(netamt,3)), 0,160);
TEXTOUT_P("Monthly yield: " + EVAL(ROUND(irr*100,3)) + "%", 0,180);
TEXTOUT_P("Yearly yield: " + EVAL(ROUND(12*irr*100,3)) + "%", 0,200);
WAIT;
RETURN 12*irr; // yearly yield (IRR) in decimal
END;
Reference URL's