swifty@fluke.UUCP (steve swift) (01/07/86)
Below is an awk program for keeping track of stock investments, although it can be used for others. The program was originally written by Gary Anderson. I modified it for 80 column output and added the code for reinvestment and cash distributions. To use it, strip off everything outside the dotted lines, make the file executable and roi < financial_record | more I would like to see a version written in C, so it would be more portable. The file financial_record is constructed as desribed in the comments include in the program. If you have any improvements or bug reports contact: Steven Swift (206) 356-5278 John Fluke Mfg. Co. P.O. Box C9090 Everett WA 98206 {uw-beaver,decvax!microsof,ucbvax!lbl-csam,allegra,ssc-vax}!fluke!swifty _______________________________________________________________ #! /bin/awk -f # # program: roi # # authors: gary s. anderson # steve swift mod 12/85 # steve swift mod 9/85 # # date: 14 february 1984 # # purpose: to analyze stock and mutual fund investments # This version shortens the output for 80 column # terminals and keeps track of distributions # of cash and reinvested distributions. # # description: tbc # # input file format: # the first record of the input must indicate today's date # in the form # # date mm dd yy # # where date is literally 'date' and mm, dd, and yy are as you # would expect. # # the second record is of the form # # price xxx.xx # # where price is literally 'price' and xxx.xx is today's market # value of the stock. # # a purchase transaction has the form # # buy mm dd yy bbb.bb ppp.pp nnn.nn # # where buy is literally 'buy', mm, dd, and yy are the date of # the purchase transaction, bbb.bb is the amount of dollars # invested, ppp.pp is the per share price, and nnn.nn is the # number of shares purchased. # # a stock dividend transaction has the form # # div mm dd yy ppp.pp # # where div is literally 'div' and ppp.pp is the percentage of # dividend awarded. # # A reinvested cash distribution has the form # # rein mm dd yy bbb.bb ppp.pp nnn.nn # # where rein is literally "rein' and the rest are treated # the same as a buy transaction. Any reinvested gain # must also be recorded in a buy record for basis to be # correctly calculated. # # A cash distribution (that is not reinvested) has the form # # cash mm dd yy bbb.bb # # where cash is literally 'cash' and bbb.bb is the amount of # cash received. # # # initialize the transaction array index BEGIN \ { printf ("Stock Investment Program "); printf ("\n"); purchase = 0; #set the processing flag to enable processing of buy transactions processing = 1; #clear the selling data flag to disable selling output data selling = 0; } #ignore commented lines /#/ \ { print "comment--- ", $0; next; } # process a purchase transaction /buy/ \ { if (processing == 1) { purchase = purchase +1; transactiontype [purchase] = "purchase"; date [purchase] = $4*12+$2; heldmonths [purchase] = currentdate - date[purchase]; if (heldmonths [purchase] == 0) heldmonths [purchase] = 1; basis [purchase] = $5; pricepershare [purchase] = $6; initshares [purchase] = $7; currentshares [purchase] = $7; month [purchase] = $2; year [purchase] = $4; } } # process a reinvested distribution transaction /rein/ \ { if (processing == 1) { dist = dist +1; disttranstype [dist] = "dist"; distbasis [dist] = $5; distinitshares [dist] = $7; distcurshares [dist] = $7; } } /cash/ \ { coin = coin +1; cointranstype [coin] = "coin"; coinbasis [coin] = $5; } # process a dividend transaction /div/ \ { dividendpercent = $5; for (i=1; i<=purchase; i=i+1) { currentshares [i] = currentshares[i] \ + currentshares[i]*dividendpercent/100; } } # process the sold start or end record /sold/ \ { print $0 print $2 if ($2 == "start") { # disable further processing of buy transactions processing = 0; } if ($2 == "end") { # enable processing of buy transactions processing = 1; } } # process the selling data output traction /selling/ \ { # enable the data output of selling data selling = 1; sharessold = $2; } # process the date record /date/ \ { currentdate = $4*12+$2; todaymonth = $2; todayday = $3; todayyear = $4;; } # process the price record /price/ \ { currentprice = $2; } # all the data is now collected, output the reports END \ { cumulativeshares = 0; cumulativebasis = 0; for (i=1; i<=purchase; i=i+1) { if ((i % 40) == 1) { printf (""); printf ("\n\n"); printf ("Investment Analysis Program\n"); printf ("Todays Date - %2d/%2d/%2d\n", todaymonth, todayday, \ todayyear); printf ("Today's Stock Price - %6.3f\n", currentprice); printf ("\n"); printf ("%5s", "date"); printf ("%10s", "#share"); printf ("%10s", "$pershare"); printf ("%10s", "$value"); printf ("%10s", "%compound"); printf ("%8s", "#months"); printf ("%12s", "cumulative"); printf ("%12s", "cumulative"); printf ("\n"); printf ("%5s", ""); printf ("%10s", "initial"); printf ("%10s", ""); printf ("%10s", "current"); printf ("%10s", "roi"); printf ("%8s", "held"); printf ("%12s", "basis"); printf ("%12s", "#shares"); printf ("\n"); printf ("\n"); } currentvalue [i] = currentshares[i] * currentprice; # the following uses the fact that x^y = exp(y*log(x)) roi [i] = (exp ((1.0 / heldmonths [i]) * \ log (currentvalue [i] / basis [i])) - 1) * 100 * 12; cumulativeshares = cumulativeshares + currentshares [i]; cumulativebasis = cumulativebasis + basis [i]; printf ("%2d/%2d ", month [i], year [i]); printf ("%10.4f", initshares [i]); printf ("%10.4f", pricepershare [i]); printf ("%10.2f", currentvalue [i]); printf ("%10.4f", roi [i]); printf ("%8d", heldmonths [i]); printf ("%12.2f", cumulativebasis); printf ("%12.4f", cumulativeshares); if (selling == 1) { printf ("(-%5d = %12.4f)", sharessold, cumulativeshares-sharessold); } printf ("\n"); } printf ("\n"); printf ("\n"); # all the cash dividend data is collected cumcoinbasis = 0; for (i=1; i<=coin; i=i+1) { cumcoinbasis = cumcoinbasis + coinbasis [i]; } # all the dist data is now collected, output the reports cumdistshares = 0; cumdistbasis = 0; for (i=1; i<=dist; i=i+1) { cumdistshares = cumdistshares + distcurshares [i]; cumdistbasis = cumdistbasis + distbasis [i]; } printf ("distribution dollars - %12.2f", cumdistbasis); printf ("\n"); printf ("distribution shares - %14.4f", cumdistshares); printf ("\n"); printf ("\n"); printf ("total investment dollars - %8.2f", cumulativebasis - \ cumdistbasis); printf ("\n"); printf ("total investment shares - %10.4f", cumulativeshares - \ cumdistshares); printf ("\n"); printf ("\n"); printf ("total value - %22.2f", currentprice * cumulativeshares); printf ("\n"); printf ("accumulated shares - %17.4f", cumulativeshares); printf ("\n"); printf ("\n"); printf ("total cash received - %12.2f", cumcoinbasis); printf ("\n"); printf ("Today's Total Return - %13.2f\n", 100*( currentprice * \ cumulativeshares + cumcoinbasis) / (cumulativebasis - cumdistbasis)); printf ("\n"); } _________________________________________________________________________ -- Steven Swift (206) 356-5278 John Fluke Mfg. Co. P.O. Box C9090 Everett WA 98206 {uw-beaver,decvax!microsof,ucbvax!lbl-csam,allegra,ssc-vax}!fluke!swifty