Wednesday, March 16, 2011

Yet Another Mortgage Estimator

The New York Times has a really slick rent-versus-buy calculator; that site has everything you need to compare renting versus taking on a mortgage. I can't recommend it it highly enough.

One thing that the New York Times' calculator confirms is that renting is always better than buying in Silicon Valley. You would need to stay in the same house for about 40 years before it became cheaper than renting for the same period of time.

But "wait!", you say, " you are just throwing your money away when you rent." That is true. But it turns out that housing prices are so high in Silicon Valley, that you actually throw away more money in interest when you take on a mortgage to buy a house (or condo even).

It is at this point someone helpfully adds, "but you can deduct interest from your taxes".

So the questions are:
  1. How much money do you "throw away" paying mortgage?
  2. And, how much of that do you "get back" from Uncle Sam via the federal mortgage interest deduction tax break?

The first is pretty easy to answer; any loan amortization table will tell you how much interest you pay given a loan amount, interest rate, and number of years you'll be borrowing the money. The second is a little more complicated. Let me explain:

The federal mortgage interest deduction is just that: it allows you to deduct the amount of money you paid in mortgage interest from your income for that year. In other words, it is as if you never made that money. So, if you earn $60,000 in gross income and pay $12,000 in mortgage interest, Uncle Sam will pretend you only earned $48,000 for the sake of calculating your federal income tax.

That wouldn't mean that you get $12,000 off your federal income tax, though; it just reduces the amount of income you have to pay tax on. Meanwhile, you only get to deduct the mortgage interest if you itemize your deductions. This means more work for you in preparing your taxes, but more importantly, it means that you have to give up the "standard deduction". The standard deduction is the amount that everyone is entitled to deduct from their gross income; but you can't take both the standard deduction and an itemized deduction at the same time. So you only want to take an itemized deduction if it would be greater than your standard deduction. For a married couple filing jointly the standard deduction in 2011 will be $11,600.

Going back to the previous example, if you paid $12,000 in mortgage interest you could itemize your deductions and reduce your taxable income by $12,000 or you could not itemize and take the standard deduction of $11,600. With a hypothetical $60,000 of gross income, itemizing would bring your taxable income down to just $48,000 versus $48,400 without itemizing. Obviously, in this case, the itemized deduction leaves less of your money subject to federal tax, so you would want to take that. But it should also be clear that the benefit of the federal mortgage interest deduction is not really $12,000 since, if you didn't have a mortgage, you could still deduct $11,600. So the tax break is really worth the difference between an itemized deduction and the standard deduction...or just $400. But it isn't worth $400 either because it just means that $400 less of your money is taxed; at $60,000 your marginal tax rate would be 15% so the difference in tax is just $400 x 15%, or $60.

That's right, the federal income tax break on $12,000 of mortgage interest is a whopping $60.

The value of the deduction depends on your taxable income and the amount of mortgage interest you pay each year. The amount of mortgage interest you pay goes down as you pay back principle so the value of the tax break also goes down each year.

Anyway, I think you get the idea...calculating the value of the federal mortgage interest deduction isn't trivial. Basically, you have to do your taxes twice, once itemizing to take the mortgage interest deduction and again with the standard deduction, each year, in order to calculate the total value of the tax break.

So I made my own mortgage estimator that approximates the value of the mortgage interest deduction and, factoring that number in, tells you how much money you actually "throw away" on mortgage interest. It also amortizes the after-tax-break interest over the number of months you plan to live in the house, which yields a number comparable to the amount you would "throw away" on rent.

My calculator is here: http://mortgage-estimator.appspot.com/.

The Loan Amount, Interest Rate, and Term fields are used to calculate the amortization table for the mortgage and hopefully are self-explanatory. You can also input the loan amount by entering the Home Price and Down Payment; in which case, how much equity you are putting down is displayed next to the Down Payment as a percentage.

The Gross Income, Filing Status, and Children (actually, dependents) fields are used to estimate your federal tax obligations. The tax estimator is pretty simple; it doesn't know anything about the more obscure deductions nor does it handle investment income, but I believe it is sufficient for its purpose in comparing your hypothetical tax obligation with and without the mortgage deduction.

Finally, the Expected Residency field is an acknowledgement that none of us are likely to live in the same house for the rest of our lives; here you can enter the number of years you expect to live in the home. This is important in the "how much money am I throwing away in interest" calculation because mortgage interest -- like all loan interest -- is front-end loaded. You pay more interest at the beginning of your loan and more principle towards the end. So the fewer years you live in the house before you sell it, the higher your paid interest-to-principle ratio will be.

And now for the minutia:
  • All numbers are rounded when they are displayed. So $31.586 will be displayed as $31.59 and $16.134 will be displayed as $16.13; their difference is $15.452 so will be displayed as $15.45 not $15.46. Not that you should expect this estimator to be accurate to the penny anyway.

  • The estimator does not currently take into account private mortgage insurance nor FHA loan assistance programs.

  • The estimator does not currently take into account state taxes and any possible state-specific home ownership incentives.

Monday, March 14, 2011

More TSA lunacy

As if the TSA's gratuitous strip-searches at the airport weren't enough, they've branched out into train travel too. You know, in case someone gets the bright idea of highjacking a train and running it into a skyscraper. But seriously, groping people as they get off the train? What could the logic possibly be? Certainly not safety: the trip had already concluded incident-free.

We are paying perverts to do nothing of value.

So this is what it has come to? The American taxpayer shells out 8.1 billion dollars a year to get felt up by strangers while our lawmakers fight to kill Big Bird to save 451 million dollars. I'd like to actually meet the people who think paying perverts to feel up law-abiding people after they demonstratively proved they are no threat is a better use of our tax dollars than, well, anything.

Thursday, February 3, 2011

Dear Amtrak

Dear Amtrak,

A bus is not a train. If I wanted to take a bus, I'd go to greyhound.com and plan my trip. But I didn't; I went to amtrak.com because I wanted to plan a train trip. To that end, I want:
  1. A list of actual train stations, not bus terminals
  2. A map of train routes and their transfer points
  3. An option on your trip planner to not include bus routes

Look, I'm not stupid; I realize you can't stop in every city. But I don't expect you to. If I'm planning a cruise, I can go to carnival.com, and they provide me a list of departure ports to choose from. They don't claim to service Omaha, Nebraska and, when I choose Omaha, offer a trip that includes a bus to New Orleans. But that is exactly what your retarded web site does when I try to plan a train trip.

So, please Amtrak, don't make it so damn hard to use your service. With the TSA intent on ogling and fondling our wives and children, you've got a great chance to win the business of concerned middle-class citizens. President Obama even threw you a bone in his State of the Union address. But here's a newsflash: while train travel can compensate for being slow by being nostalgic, bus travel is slow, uncomfortable, and generally un-cool.

So quit hiding behind the transport of last resort, the bus, and take a page from the cruise lines: some of us are as interested in the trip as we are in the destination.

Thursday, December 2, 2010

Personal income taxes and job creation

With elections over, the issue of whether to extend the Bush-era personal income tax cuts to families earning over $250,000 a year is back in the news. Currently, there is a 33% tax bracket that affects income in excess of $209,250 and a 35% tax bracket for income in excess of $372,950 (for joint filers). So, in effect, under the Democratic proposal, a new tax bracket will be created between the two existing brackets like so:

33%$209,250-$250,000
36%$250,000-$373,650
39.6%$373,650+


The exact numbers may still change as the details are worked out, but bear with me.

The Republicans are currently pushing to extend the Bush-era personal income tax cuts to families earning over $1,000,000 a year or extend them to everyone. If this were to come to pass, again an extra tax bracket would be created, but it would look something like:

33%$209,250-$373,650
35%$373,650-$1,000,000
39.6%$1,000,000+


Again, the exact numbers aren't all that important. For the sake of example, though, let's look at a scenario of a family making a cool half-a-million dollars a year in personal income. Currently, this family would be paying approximately $141,563 in federal income tax (assuming the standard deduction of $10,700 for 2010).

BracketRangeDollars Taxed
in this Bracket
Tax Amount
10%$0 – $16,750$16,750$1,675.00
15%$16,751 – $68,000$51,250$7,687.50
25%$68,001 – $137,300$69,300$17,325.00
28%$137,301 – $209,250$71,950$20,146.00
33%$209,251 – $373,650$164,400$54,252.00
35%$373,651 +$115,650$40,477.50
Total:$489,300$141,563.00

Wow, that's a big number. It is funny to think we're having all this argument over people earning so much money that their taxes are triple what the average American grosses in a year.

Anyway, our poor put-out example family is paying $141,563 out of their $500,000 annual income in federal income tax. That is an effective tax rate of 28.3%.

Under the Republicans' proposed plan, there would be no change in the amount of federal income tax paid by our hypothetical family since they earn less than 1 million dollars a year.

Under the Democrats' proposed plan, our hypothetical family would have to pay $150,592 in tax, which is 30.1% of their income.


BracketRangeDollars Taxed
in this Bracket
Tax Amount
10%$0 – $16,750$16,750$1,675.00
15%$16,751 – $68,000$51,250$7,687.50
25%$68,001 – $137,300$69,300$17,325.00
28%$137,301 – $209,250$71,950$20,146.00
33%$209,251 – $250,000$40,750$13,447.50
36%$250,001 – $373,650$123,650$44,514.00
39.6%$373,651 +$115,650$45,797.40
Total:$489,300$150,592.40


So the difference between the two proposals amounts to a 1.8% tax increase in this example. With a little hand-waving, let's just say the argument is over a 2% tax increase affecting families earning between $250,000 and $1,000,000 a year.

The Republicans claim that this tax will curb job creation. In response to the vote in the House of Representatives approving of the Democrat's proposal, Republican representative Gary Miller of California issued a statement saying
During these difficult economic times, raising taxes on any American family or small business will not help our economy recover nor foster the private-sector job growth needed to achieve economic recovery. The only thing that Democrats have accomplished by today's vote is yet more uncertainty for our nation's job creators.


Certainly, no one will argue that the U.S. could use more jobs. But is a 2% personal income tax increase going to materially affect job creation? Returning to the example above, a small business owner making $500,000 a year would see a difference of about $9000 in their take-home pay. That isn't enough to create even one job.

In any event, this ignores the elephant in the room: the issue being debated is a tax rate on personal income tax, not corporate tax. Why would a business owner pay out income from their business to themselves, incurring personal income tax, only to reinvest that money into their business? Wouldn't it make more sense to create those jobs using *before* tax dollars? And that is what any business owner can do -- and is doing -- right now, under the current tax law. And what they'll be able to continue doing no matter what happens with regards to personal income tax.

So it is patently silly to think that a decrease of any kind in the personal income tax is going to affect job creation. The money that creates jobs isn't taxed. You don't get lower than a zero percent tax rate. Businesses are not directly affected by the personal income tax rate.

No, the Republicans' cherished 2% tax cut on families making more than $250,000 a year only helps wealthy people put more money in their pockets. At best, businesses may benefit indirectly by virtue of the fact that wealthy people have more disposable income.

Sunday, November 21, 2010

Where are the protesters?

I'm waiting with baited breath to see whether there will be any protests over the airport nudey scanners and TSA groping this Thanksgiving holiday. I mean, we all remember the riots over universal health care, right?

If the government putting their nose in our personal business rankled people, surely the government putting their hands in our privates will unleash true rage.

Surely people will be up-in-arms over the TSA taking naked pictures of them and keeping the good ones for fun. Surely people will be angry that their wives and daughters are being felt up by convicted sex offenders. Surely people will be rabid over the loss of their 4th amendment rights.

Given the public shows of anger and disgust -- the public backlash -- in town hall meetings regarding something as mundane as health care, I expect the protests against the government's full assault of our privacy and dignity to be something to see. I can't wait.
Update 2010/11/24:
Well, the busiest travel day of the year has passed without any notable protests. I'm not quite sure what to make of that.

Sunday, November 14, 2010

New Chapter

Well, tomorrow is a big day for me: I'll be starting a new job. I'll be working for a super-secretive company in Cupertino which means that I won't be writing any more tech-related posts. I'm sure the next few weeks will be hectic, so I doubt I'll be up to writing much anyway. But I've got some ideas of what I'd like to write about once things settle down.

I'd say "stay tuned" but I'm pretty sure no one is tuned in to my blog as it is. :)

Friday, November 12, 2010

Python: Enumerating IP Addresses on FreeBSD

As promised in my earlier post on enumerating local interfaces and their IP addresses on MacOS X, this time I'll cover how to do the same on FreeBSD and other operating systems that implement the getifaddrs API. Basically, this is just a python wrapper around the getifaddrs interface using ctypes.

The code is a bit longer than I typically like to include in a blog post, but here it goes:
"""
Wrapper for getifaddrs(3).
"""

import socket
import sys

from collections import namedtuple
from ctypes import *

class sockaddr_in(Structure):
_fields_ = [
('sin_len', c_uint8),
('sin_family', c_uint8),
('sin_port', c_uint16),
('sin_addr', c_uint8 * 4),
('sin_zero', c_uint8 * 8)
]

def __str__(self):
assert self.sin_len >= sizeof(sockaddr_in)
data = ''.join(map(chr, self.sin_addr))
return socket.inet_ntop(socket.AF_INET, data)

class sockaddr_in6(Structure):
_fields_ = [
('sin6_len', c_uint8),
('sin6_family', c_uint8),
('sin6_port', c_uint16),
('sin6_flowinfo', c_uint32),
('sin6_addr', c_uint8 * 16),
('sin6_scope_id', c_uint32)
]

def __str__(self):
assert self.sin6_len >= sizeof(sockaddr_in6)
data = ''.join(map(chr, self.sin6_addr))
return socket.inet_ntop(socket.AF_INET6, data)

class sockaddr_dl(Structure):
_fields_ = [
('sdl_len', c_uint8),
('sdl_family', c_uint8),
('sdl_index', c_short),
('sdl_type', c_uint8),
('sdl_nlen', c_uint8),
('sdl_alen', c_uint8),
('sdl_slen', c_uint8),
('sdl_data', c_uint8 * 12)
]

def __str__(self):
assert self.sdl_len >= sizeof(sockaddr_dl)
addrdata = self.sdl_data[self.sdl_nlen:self.sdl_nlen+self.sdl_alen]
return ':'.join('%02x' % x for x in addrdata)

class sockaddr_storage(Structure):
_fields_ = [
('sa_len', c_uint8),
('sa_family', c_uint8),
('sa_data', c_uint8 * 254)
]

class sockaddr(Union):
_anonymous_ = ('sa_storage', )
_fields_ = [
('sa_storage', sockaddr_storage),
('sa_sin', sockaddr_in),
('sa_sin6', sockaddr_in6),
('sa_sdl', sockaddr_dl),
]

def family(self):
return self.sa_storage.sa_family

def __str__(self):
family = self.family()
if family == socket.AF_INET:
return str(self.sa_sin)
elif family == socket.AF_INET6:
return str(self.sa_sin6)
elif family == 18: # AF_LINK
return str(self.sa_sdl)
else:
print family
raise NotImplementedError, "address family %d not supported" % family


class ifaddrs(Structure):
pass
ifaddrs._fields_ = [
('ifa_next', POINTER(ifaddrs)),
('ifa_name', c_char_p),
('ifa_flags', c_uint),
('ifa_addr', POINTER(sockaddr)),
('ifa_netmask', POINTER(sockaddr)),
('ifa_dstaddr', POINTER(sockaddr)),
('ifa_data', c_void_p)
]

# Define constants for the most useful interface flags (from if.h).
IFF_UP = 0x0001
IFF_BROADCAST = 0x0002
IFF_LOOPBACK = 0x0008
IFF_POINTTOPOINT = 0x0010
IFF_RUNNING = 0x0040
if sys.platform == 'darwin' or 'bsd' in sys.platform:
IFF_MULTICAST = 0x8000
elif sys.platform == 'linux':
IFF_MULTICAST = 0x1000

# Load library implementing getifaddrs and freeifaddrs.
if sys.platform == 'darwin':
libc = cdll.LoadLibrary('libc.dylib')
else:
libc = cdll.LoadLibrary('libc.so')

# Tell ctypes the argument and return types for the getifaddrs and
# freeifaddrs functions so it can do marshalling for us.
libc.getifaddrs.argtypes = [POINTER(POINTER(ifaddrs))]
libc.getifaddrs.restype = c_int
libc.freeifaddrs.argtypes = [POINTER(ifaddrs)]


def getifaddrs():
"""
Get local interface addresses.

Returns generator of tuples consisting of interface name, interface flags,
address family (e.g. socket.AF_INET, socket.AF_INET6), address, and netmask.
The tuple members can also be accessed via the names 'name', 'flags',
'family', 'address', and 'netmask', respectively.
"""
# Get address information for each interface.
addrlist = POINTER(ifaddrs)()
if libc.getifaddrs(pointer(addrlist)) < 0:
raise OSError

X = namedtuple('ifaddrs', 'name flags family address netmask')

# Iterate through the address information.
ifaddr = addrlist
while ifaddr and ifaddr.contents:
# The following is a hack to workaround a bug in FreeBSD
# (PR kern/152036) and MacOSX wherein the netmask's sockaddr may be
# truncated. Specifically, AF_INET netmasks may have their sin_addr
# member truncated to the minimum number of bytes necessary to
# represent the netmask. For example, a sockaddr_in with the netmask
# 255.255.254.0 may be truncated to 7 bytes (rather than the normal
# 16) such that the sin_addr field only contains 0xff, 0xff, 0xfe.
# All bytes beyond sa_len bytes are assumed to be zero. Here we work
# around this truncation by copying the netmask's sockaddr into a
# zero-filled buffer.
if ifaddr.contents.ifa_netmask:
netmask = sockaddr()
memmove(byref(netmask), ifaddr.contents.ifa_netmask,
ifaddr.contents.ifa_netmask.contents.sa_len)
if netmask.sa_family == socket.AF_INET and netmask.sa_len < sizeof(sockaddr_in):
netmask.sa_len = sizeof(sockaddr_in)
else:
netmask = None

try:
yield X(ifaddr.contents.ifa_name,
ifaddr.contents.ifa_flags,
ifaddr.contents.ifa_addr.contents.family(),
str(ifaddr.contents.ifa_addr.contents),
str(netmask) if netmask else None)
except NotImplementedError:
# Unsupported address family.
yield X(ifaddr.contents.ifa_name,
ifaddr.contents.ifa_flags,
None,
None,
None)
ifaddr = ifaddr.contents.ifa_next

# When we are done with the address list, ask libc to free whatever memory
# it allocated for the list.
libc.freeifaddrs(addrlist)

__all__ = ['getifaddrs'] + [n for n in dir() if n.startswith('IFF_')]
As always, this code is released under a BSD-style license.