Post Reply 
Cash Flow (IRR, MIRR, NPV)
05-21-2015, 03:49 PM (This post was last modified: 05-27-2015 05:42 PM by salvomic.)
Post: #1
Cash Flow (IRR, MIRR, NPV)
hi all,
here a program to calculate Cash Flow operations with the Prime (IRR, MIRR, NPV).
The program is presented in two version: the first give three routines to calculate (Net Present Value, Internal Rate of Return and Modified Internal Rate of Return, like that in the HP 12C); the second will follow with a "Drawmenu" version with only a command, Cash_Flow that executes the same routines internally.
NPV included is the nice program by Eddie W. Shore (here in the Forum).
I would like to thank who has helped me to do this program: Dale (DRD), Cyrille de Brébisson, Akmon, Didier Lachiese, kharpster, who has transformed the program into "menu-ized" version...)

Warning: both version use list L1 or matrix M1 to store data, so, if you have important data in there, please, first save them otherwhere...
I advice to use the list for series of cash flow with few data to treat or edit {CF0, CF1, CF2, ... CFj...}, and a matrix when there are more data with frequency repeated (i.e [CF0, 1], [CF1, 2], [CF2, 1], [CF3, 8], ...,[CFj],... [CF last, 1]).

You can store data into list (or matrix) first of use the program, or inside the program, editing them.

Enjoy!

Salvo Micciché (salvomic)

Version with commands separately exported
Code:

EXPORT IRR()
// Credits: Cyrille de Brébisson, Akmon, Dale (DrD), salvomic (Salvo Micciché), 
// Eddie W. Shore, Didier Lachiese, kharpster
// Interal Rate of Return. Cash flows in {L1} list or M1 (matrix with frequencies)
// by Salvo Micciché
BEGIN
local ch, irr;
CHOOSE(ch,"Flows List or Matrix w/ freq","Cash Flows List","CF Matrix whit frequencies");
CASE
IF ch==1 THEN
EDITLIST(L1, "Internal Rate of Return");
END;
IF ch==2 THEN
EDITMAT(M1, "Internal Rate of Return");
 LOCAL flows:={}, j, k, s;
 s:=SIZE(M1);
 FOR j FROM 1 TO s(1) DO
 FOR k FROM 1 TO M1(j,2) DO
flows:= append(flows, M1(j,1));
 END; END; // for 1, 2
L1:= flows;
END;
DEFAULT
MSGBOX("IRR() with {list} or [matrix with frequencies]");
RETURN;
END; // case
irr:= solve(ΣLIST(MAKELIST((L1(I)/X^(I-1)),I,1,SIZE(L1))),X)-1;
IF (irr(1)>=1 OR irr(1)<=-1) THEN irr:=tail(irr); END;
// formula by akmon, Cyrille, Dale
PRINT;
PRINT("Internal Rate of Return

IRR = ");
PRINT(EVAL(ROUND(100*irr,4)) + "%");
RETURN irr;
END;

EXPORT MIRR()
// Calc Modified Internal Return Rate
// Salvo Micciché 2015
BEGIN
LOCAL sr, rr, flpos:={}, flneg:={}, sz ;
LOCAL sz1, sz2, npvp, npvn, n ;
LOCAL ch, fvp, ppyr, mirrvalue;
CHOOSE(ch,"Flows List or Matrix w/ freq","Cash Flows List","CF Matrix whit frequencies");
CASE
IF ch==1 THEN
EDITLIST(L1, "Modified Internal Rate of Return");
END;
IF ch==2 THEN
EDITMAT(M1, "Internal Rate of Return");
 LOCAL flows:={}, j, k, s;
 s:=SIZE(M1);
 FOR j FROM 1 TO s(1) DO
 FOR k FROM 1 TO M1(j,2) DO
flows:= append(flows, M1(j,1));
 END; END; // for 1, 2
L1:= flows;
END;
DEFAULT
MSGBOX("MIRR() with {list} or [matrix with frequencies]");
KILL;
END; // case

INPUT ({sr, rr, ppyr},"Safe and risk rate", {"sr", "rr", "ppyr"}, 
{"Safe rate CF-", "Risk (reinvestment) Rate CF+", "n Payments for year"}, {0,0, 12},{0,0, 12});
// sr and rr yearly rates (es. 6%, 10%), ppyr number of payments in a year
sz:= SIZE(L1);
sr:=sr/ppyr; rr:=rr/ppyr;
n:=sz-1;
flneg:=MIN(L1,0); flpos:=MAX(L1,0); // one list -> two list, tnx Didier
sz1:= SIZE(flpos); sz2:= SIZE(flneg);
npvp:= NPV(rr, flpos);
npvp:=-npvp;
fvp:=Finance.CalcFV(n,rr*ppyr,npvp,0,ppyr,12,0);
npvn:= NPV(sr, flneg);
// RETURN 100*((fvp/-npvn)^(1/n)-1 );  HP 12C formula (equal to the next)
mirrvalue:= Finance.CalcIPYR(n,npvn,0,fvp,ppyr,12,0)/ppyr;
PRINT;
PRINT ("Modified Internal Rate of Return

Safe rate " + EVAL(ROUND(sr*ppyr,3)) + "% - Risk (reinvestment) rate " + EVAL(ROUND(rr*ppyr,3)) + "% 
with " + STRING(ppyr) + " n. payments per year.

NPV negative flows " + STRING(ROUND(npvn,3)) + "
NPV positve flows " + STRING(ROUND(npvp,3)) + "
FV of posive flows NPV " + STRING(ROUND(fvp,3)) + "
MIRR monthly rate " + STRING(ROUND(mirrvalue,3)) + "%
MIRR yearly   rate " + EVAL(ROUND(mirrvalue*ppyr,3)) + "%"
);
RETURN {mirrvalue, ppyr*mirrvalue}; // return monthly and yearly MIRR
END;

EXPORT NPV(r, flows)
// routine by Eddie W. Shore
 BEGIN
 LOCAL t:=0, k, s;
 r:=1+0.01*r;
 CASE
 // list
 IF TYPE(flows)==6 THEN
 s:=SIZE(flows);
 FOR k FROM 1 TO s DO
 t:=t+flows(k)/(r^(k-1));
 END;
 END;
 // matrix
 IF TYPE(flows)==4 THEN

 LOCAL j, n;
 s:=SIZE(flows);
 k:=0;
 FOR j FROM 1 TO s(1) DO
 FOR n FROM 1 TO flows(j,2) DO
 t:=flows(j,1)/(r^k)+t;
 k:=k+1;
 END; // for
 END; // for 2
 END; // if
 DEFAULT
 MSGBOX("NPV(rate, list) or NPV(rate, [flow, freq])");
 KILL;
 END; // Case
 RETURN t;
 END;

recall_npv()
BEGIN
local ch, r;
INPUT (r, "Rate", "rate%", "Rate for Net Present Value", 0, 10);
CHOOSE(ch,"Flows List or Matrix w/ freq","Cash Flows List","CF Matrix whit frequencies");
CASE
IF ch==1 THEN
EDITLIST(L1, "Internal Rate of Return");
END;
IF ch==2 THEN
EDITMAT(M1, "Internal Rate of Return");
 LOCAL flows:={}, j, k, s;
 s:=SIZE(M1);
 FOR j FROM 1 TO s(1) DO
 FOR k FROM 1 TO M1(j,2) DO
flows:= append(flows, M1(j,1));
 END; END; // for 1, 2
L1:= flows;
END;
DEFAULT
MSGBOX("IRR() with {list} or [matrix with frequencies]");
KILL;
END; // case
NPV(r, L1);
END;

EXPORT about()
BEGIN
PRINT;
PRINT ("Program created by by Salvo Micciché (salvomic). 
Credits: Cyrille de Brébisson, Akmon, Dale (DrD), Eddie W. Shore, Didier Lachiese, kharpster");
RETURN;
END;

Here Cash_Flows, the version with Drawmenu, every functions inside the program...
This version exports variables in CF_IRR, CF_MIRR, CF_NPV inside Vars->User->Cash_Flow

Code:

export CF_IRR:=0;
export CF_MIRR:={0,0};
export CF_NPV:=0;

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

IRR();
MIRR();
NPV();
recall_npv();
about();

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

EXPORT Cash_Flow()
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 := {"NPV","IRR","MIRR","About","","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("Cash Flow Utility", 100, 10, 5, RGB(255,0,0));
TEXTOUT_P("NPV Net Present Value", 25, 50);
TEXTOUT_P("IRR Internal Rate of Return", 25, 70);
TEXTOUT_P("MIRR Modified Internal Rate of Return", 25, 90);
TEXTOUT_P("by Salvo Micciché, 2015", 25, 120);
TEXTOUT_P("Credits: Cyrille de Brébisson, Akmon", 25, 150);
TEXTOUT_P("Dale (DrD), Eddie W. Shore", 25, 170);
TEXTOUT_P("Didier Lachiese, 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
             recall_npv();  
           END;
           IF mSEL == 2 THEN
             IRR();
           END;
           IF mSEL == 3 THEN
             MIRR(); 
           END;
           IF mSEL == 4 THEN
       about();
           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;

// ------------------------------------------------------------------------------------------
// Cash Flow application Code
// ------------------------------------------------------------------------------------------

IRR()
// Credits: Cyrille de Brébisson, Akmon, Dale (DrD), salvomic (Salvo Micciché), 
// Eddie W. Shore, Didier Lachiese, kharpster
// Interal Rate of Return. Cash flows in {L1} list or M1 (matrix with frequencies)
// by Salvo Micciché
BEGIN
local ch, irr;
CHOOSE(ch,"Flows List or Matrix w/ freq","Cash Flows List","CF Matrix whit frequencies");
CASE
IF ch==1 THEN
EDITLIST(L1, "Internal Rate of Return");
END;
IF ch==2 THEN
EDITMAT(M1, "Internal Rate of Return");
 LOCAL flows:={}, j, k, s;
 s:=SIZE(M1);
 FOR j FROM 1 TO s(1) DO
 FOR k FROM 1 TO M1(j,2) DO
flows:= append(flows, M1(j,1));
 END; END; // for 1, 2
L1:= flows;
END;
DEFAULT
TEXTOUT_P("Use: IRR() with {list} or [matrix with frequencies]", 5, 30);
WAIT;
RETURN;
END; // case
irr:= solve(ΣLIST(MAKELIST((L1(I)/X^(I-1)),I,1,SIZE(L1))),X)-1;
IF (irr(1)>=1 OR irr(1)<=-1) THEN irr:=tail(irr); END;
// formula by akmon, Cyrille, Dale
sto(irr, CF_IRR);
RECT_P(0,0,319,219);
TEXTOUT_P("IRR Internal Rate of Return", 0, 10);
TEXTOUT_P(EVAL(ROUND(100*irr, 3))+ "%", 0, 30, 0, RGB(255,0,0));
WAIT;
RETURN irr;
END;

MIRR()
// Calc Modified Internal Return Rate
// Salvo Micciché 2015
BEGIN
LOCAL sr, rr, flpos:={}, flneg:={}, sz ;
LOCAL sz1, sz2, npvp, npvn, n ;
LOCAL ch, fvp, ppyr, mirrvalue;
CHOOSE(ch,"Flows List or Matrix w/ freq","Cash Flows List","CF Matrix whit frequencies");
CASE
IF ch==1 THEN
EDITLIST(L1, "Modified Internal Rate of Return");
END;
IF ch==2 THEN
EDITMAT(M1, "Internal Rate of Return");
 LOCAL flows:={}, j, k, s;
 s:=SIZE(M1);
 FOR j FROM 1 TO s(1) DO
 FOR k FROM 1 TO M1(j,2) DO
flows:= append(flows, M1(j,1));
 END; END; // for 1, 2
L1:= flows;
END;
DEFAULT
TEXTOUT_P("Use: MIRR() with {list} or [matrix with frequencies]", 0, 30);
END; // case
INPUT ({sr, rr, ppyr},"Safe and risk rate", {"sr", "rr", "ppyr"}, 
{"Safe rate -", "Risk Rate +", "n Pmt for year"}, {0,0, 12},{0,0, 12});
// sr and rr yearly rates (es. 6%, 10%), ppyr number of payments in a year
sz:= SIZE(L1);
sr:=sr/ppyr; rr:=rr/ppyr;
n:=sz-1;
flneg:=MIN(L1,0); flpos:=MAX(L1,0); // one list -> two list, tnx Didier
sz1:= SIZE(flpos); sz2:= SIZE(flneg);
npvp:= NPV(rr, flpos);
npvp:=-npvp;
fvp:=Finance.CalcFV(n,rr*ppyr,npvp,0,ppyr,12,0);
npvn:= NPV(sr, flneg);
// RETURN 100*((fvp/-npvn)^(1/n)-1 );  HP 12C formula (equal to the next)
mirrvalue:= Finance.CalcIPYR(n,npvn,0,fvp,ppyr,12,0)/ppyr;
sto({mirrvalue, ppyr*mirrvalue}, CF_MIRR);
RECT_P(0,0,319,219);
TEXTOUT_P("Modified Internal Rate of Return", 0, 10);
TEXTOUT_P("Safe rate " + EVAL(ROUND(sr*ppyr, 3)) + "%", 0, 30);
TEXTOUT_P("Risk rate " + EVAL(ROUND(rr*ppyr, 3)) + "%", 0, 50);
TEXTOUT_P("with " + STRING(ppyr) + " payments per year", 0, 70);
TEXTOUT_P("NPV negative flows " + STRING(ROUND(npvn,3)), 0, 90);
TEXTOUT_P("FV of posive flows NPV " + STRING(ROUND(fvp,3)), 0, 110);
TEXTOUT_P("MIRR monthly rate " + STRING(ROUND(mirrvalue,3)) + "%", 0, 130, 0, RGB(255,0,0));
TEXTOUT_P("MIRR yearly rate " + EVAL(ROUND(mirrvalue*ppyr, 3)) + "%", 0, 150, 0, RGB(255,0,0));
WAIT;
RETURN {mirrvalue, ppyr*mirrvalue}; // return monthly and yearly MIRR
END;


NPV(r, flows)
// routine by Eddie W. Shore
 BEGIN
 LOCAL t:=0, k, s;
 r:=1+0.01*r;
 CASE
 // list
 IF TYPE(flows)==6 THEN
 s:=SIZE(flows);
 FOR k FROM 1 TO s DO
 t:=t+flows(k)/(r^(k-1));
 END;
 END;
 // matrix
 IF TYPE(flows)==4 THEN

 LOCAL j, n;
 s:=SIZE(flows);
 k:=0;
 FOR j FROM 1 TO s(1) DO
 FOR n FROM 1 TO flows(j,2) DO
 t:=flows(j,1)/(r^k)+t;
 k:=k+1;
 END; // for
 END; // for 2
 END; // if
 DEFAULT
TEXTOUT_P("Use: NPV(rate, list) or NPV(rate, [flow, freq])", 0, 30);
 END; // Case
sto(t, CF_NPV);
RECT_P(0,0,319,219);
TEXTOUT_P("NPV Net Present Value: " + EVAL(t), 0, 50, 0, RGB(255,0,0) );
RETURN t;
 END;

recall_npv()
BEGIN
local ch, r;
INPUT (r, "Rate", "rate%", "Rate for Net Present Value", 0, 10);
CHOOSE(ch,"Flows List or Matrix w/ freq","Cash Flows List","CF Matrix whit frequencies");
CASE
IF ch==1 THEN
EDITLIST(L1, "Internal Rate of Return");
END;
IF ch==2 THEN
EDITMAT(M1, "Internal Rate of Return");
 LOCAL flows:={}, j, k, s;
 s:=SIZE(M1);
 FOR j FROM 1 TO s(1) DO
 FOR k FROM 1 TO M1(j,2) DO
flows:= append(flows, M1(j,1));
 END; END; // for 1, 2
L1:= flows;
END;
DEFAULT
TEXTOUT_P("IRR() with {list} or [matrix with frequencies]", 0, 30);
END; // case
NPV(r, L1);
WAIT;
END;

about()
BEGIN

RECT_P(0,0,319,219);
TEXTOUT_P("Program created by by Salvo Micciché (salvomic)", 5, 10);
TEXTOUT_P("Credits", 5, 40, 0, RGB(0,255,0));
TEXTOUT_P("Cyrille de Brébisson, Akmon, Dale (DrD)", 5, 60);
TEXTOUT_P("Eddie W. Shore, Didier Lachiese, kharpster", 5, 80);

WAIT;
RETURN;
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
Cash Flow (IRR, MIRR, NPV) - salvomic - 05-21-2015 03:49 PM
RE: Cash Flow (IRR, MIRR, NPV) - akmon - 05-21-2015, 10:27 PM
RE: Cash Flow (IRR, MIRR, NPV) - salvomic - 05-21-2015, 10:43 PM
RE: Cash Flow (IRR, MIRR, NPV) - salvomic - 05-27-2015, 05:45 PM
RE: Cash Flow (IRR, MIRR, NPV) - salvomic - 05-27-2015, 06:16 PM
RE: Cash Flow (IRR, MIRR, NPV) - salvomic - 05-27-2015, 06:32 PM
RE: Cash Flow (IRR, MIRR, NPV) - salvomic - 05-28-2015, 07:56 AM
RE: Cash Flow (IRR, MIRR, NPV) - fhub - 05-28-2015, 09:39 AM
RE: Cash Flow (IRR, MIRR, NPV) - salvomic - 05-28-2015, 09:47 AM
RE: Cash Flow (IRR, MIRR, NPV) - salvomic - 05-28-2015, 08:20 AM
RE: Cash Flow (IRR, MIRR, NPV) - salvomic - 04-23-2016, 03:07 PM
RE: Cash Flow (IRR, MIRR, NPV) - seb83 - 08-22-2017, 08:42 AM



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