espp - C function to compute the taxable income from ESPP disposition
#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
);
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;
};
grant_date
exercise_date
sale_date if disposition was not a sale
exercise_date
sale_date
sale_date
sale_date.
However, no tax is normally withheld unless the account from which the stock
is sold is subject to backup withholding.
exercise_date.
exercise_date is the last trading day of the purchase period. A new
purchase period begins at the same time as the offering period, and
thereafter every 6 months, up to 4 purchase periods per offering
period.
purchase_price is sometimes called ``the option price.''
purchase_price is usually 85% of the lesser of grant_price and
exercise_price. Consult your plan for details.
exercise_date if exercise_price is less than grant_price,
unless you elect otherwise. Consult your plan for details.
purchase_price with your
outstanding contributions, and will carry the balance over.
However, US IRC section 423(b)8 sets a statutory limit of $25,000
on the total grant_price of all ESPP shares purchased on behalf
of an employee during any given calendar year.
If this limit is reached, then the balance will probably be refunded to
you.
Consult your plan for details.
sale_fmv_price if
certain criteria are met.
See IRS pub. 526 for details.
exercise_price is less than grant_price, then a disqualifying
disposition can receive better tax treatment than a qualifying
disposition.
This is not a bug, but rather a peculiarity of the tax code.
/*
* 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
time_compare function assumes that for tax purposes the date of an event
is the date in the local time zone when the event occurred.
In reality, I don't know if the appropriate time zone is that of the taxpayer's
primary residence, of his location at the time of the event, of the exchange
on which the stock is traded, or of something else.
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.