NAME

espp - C function to compute the taxable income from ESPP disposition


SYNOPSIS

        #include "tax/espp.h"
        time_t grant_date, exercise_date, sale_date;
        double grant_price, exercise_price, sale_price,
          purchase_price, sale_fmv_price;
        int deceased;
        struct EsppResult result = espp(
          grant_date, exercise_date, sale_date,
          grant_price, exercise_price, sale_price,
          purchase_price, sale_fmv_price, deceased
        );


DESCRIPTION

espp is a C function to compute the taxable income from the sale or other disposition of stock purchased through a qualifying ESPP program.

The EsppResult structure is defined in tax/espp.h as follows:

        struct EsppResult {
                double stcg;
                double ltcg;
                double ordinc;
                int disq;
        };


INPUTS

grant_date
the first trading day of the offering period, or the first trading day of the first purchase period after enrollment if a new offering period does not begin

grant_price
closing price on grant_date

exercise_date
the trading day that the stock was purchased

exercise_price
closing price on exercise_date

sale_date
date of sale or other disposition

sale_price
price at which stock was sold, less commission, or closing price on sale_date if disposition was not a sale

purchase_price
price actually paid for stock on exercise_date

sale_fmv_price
closing price on sale_date

deceased
nonzero if and only if the enrollee was deceased by the end of the tax year containing sale_date


OUTPUTS

stcg
short term capital gains (or loss if negative)

ltcg
long term capital gains (or loss if negative)

ordinc
ordinary income

disq
nonzero if and only if the sale is a disqualifying disposition


NOTES


IMPLEMENTATION

        /*
         * LEGAL NOTICE:
         * (c)2004-2006 Anders Johnson
         * The author is not qualified to give tax advice, and he
         * categorically disclaims any and all liability for this program.
         * This program may be distributed according to the terms of the
         * GNU Public License, version 2.
         */

        #include "tax/espp.h"

        #ifdef __cplusplus
        namespace tax {
        #endif

        struct EsppResult espp(
          time_t grant_date, time_t exercise_date, time_t sale_date,
          double grant_price, double exercise_price, double sale_price,
          double purchase_price, double sale_fmv_price, int deceased
        ) {
                struct EsppResult result;
                double cg, oi;
                int lt = time_compare(&sale_date, &exercise_date, 1);
                int q = deceased ||
                  (lt && time_compare(&sale_date, &grant_date, 2));
                if(q) {
                        if(sale_fmv_price < purchase_price) {
                                cg = sale_price - purchase_price;
                                oi = 0.0;
                        }
                        else if(sale_fmv_price < grant_price) {
                                cg = sale_price - sale_fmv_price;
                                oi = sale_fmv_price - purchase_price;
                        }
                        else {
                                cg = sale_price - grant_price;
                                oi = grant_price - purchase_price;
                        }
                }
                else {
                        cg = sale_price - exercise_price;
                        oi = exercise_price - purchase_price;
                }
                result.stcg = lt ? 0.0 : cg;
                result.ltcg = lt ? cg : 0.0;
                result.ordinc = oi;
                result.disq = !q;
                return result;
        }

        /*
         * Returns nonzero iff t1 exceeds t0 by more than yrs years
         * according to US tax rules.
         */
        int time_compare(
          const time_t *t1, const time_t *t0, int yrs
        ) {
                /* NOTE: If you buy on Feb 28, need to wait until Mar 1.
                   http://www.fairmark.com/news/oldblog.htm (Feb 2004) */
                struct tm tm1 = *localtime(t1);
                time_t t0a = *t0 + 24 * 60 * 60;
                /* We shouldn't relly need to worry abount DST, because
                   t0 isn't likely to be near midnight nor on a weekend,
                   but to be safe... */
                struct tm tm0 = *localtime(t0);
                if(tm0.tm_hour < 12) {
                        t0a += 6 * 60 * 60;
                } else {
                        t0a -= 6 * 60 * 60;
                }
                tm0 = *localtime(&t0a);
                return (
                  tm1.tm_year > tm0.tm_year + yrs ||
                  (tm1.tm_year == tm0.tm_year + yrs &&
                   (tm1.tm_mon > tm0.tm_mon ||
                    (tm1.tm_mon == tm0.tm_mon &&
                     tm1.tm_mday >= tm0.tm_mday
                    )
                   )
                  )
                );
        }

        #ifdef __cplusplus
        }; // namespace tax
        #endif


BUGS


SEE ALSO

Suggested strategies for managing your ESPP can be found at http://www.andersjohnson.com/prog/espp/strategies.html, a copy of which is included in the distribution.