#! /usr/bin/python class Asset: def __init__(self, name, value, rate): self.value = value self.basis = value self.rate = rate self.name = name # self.value cannot go below 0 (since financial assets, w/o debt, cannot have negative values) # returns amount that cannot be applied. # examples: # A) # init values: # value = 1000 # basis = 1000 # adj_value = 500 # value = 1500 # basis = 1500 # return 0 # adj_value = -500 # value = 1000 # basis = 1000 # return 0 # adj_value = -2000 # value = 0 # basis = 0 # return 1000 -- (2000 - 1000) # B) # init values: # value = 1500 # basis = 1000 # # adj_value = -500 # value = 1000 # basis = 1000 + -500 * (1000/1500) # return 0 # adj_value = -1200 # value = 0 # basis = 0 # return 200 # def apply_return(self): self.value *= (1 + self.rate) class AssetTaxable(Asset): def adjust_value(self, adj_value): self.taxable_income = 0 diff = 0 if adj_value > 0: self.value += adj_value self.basis += adj_value else: # no need to calc anything and keeps us from div. by zero. if self.value == 0: return adj_value # calculate taxable income. diff = self.value + adj_value usable_amount = (diff < 0 and -self.value) or adj_value self.taxable_income = (1.0 - float(self.basis)/self.value) * usable_amount if diff < 0: self.value = 0 self.basis = 0 else: self.basis = self.basis + adj_value * (self.basis/self.value) self.value += adj_value diff = 0 return diff class AssetTaxDeferred(Asset): def adjust_value(self, adj_value): self.taxable_income = 0 diff = 0 if adj_value > 0: self.value += adj_value else: # no need to calc anything and keeps us from div. by zero. if self.value == 0: return adj_value # calculate taxable income. diff = self.value + adj_value usable_amount = (diff < 0 and -self.value) or adj_value self.taxable_income = usable_amount if diff < 0: self.value = 0 else: self.value += adj_value diff = 0 return diff class AssetTaxFree(Asset): def adjust_value(self, adj_value): self.taxable_income = 0 diff = 0 if adj_value > 0: self.value += adj_value else: # no need to calc anything and keeps us from div. by zero. if self.value == 0: return adj_value diff = self.value + adj_value if diff < 0: self.value = 0 else: self.value += adj_value diff = 0 return diff import inspect def lineno(): """Returns the current line number.""" return inspect.currentframe().f_back.f_lineno def unit_test(): asset = AssetTaxable("Test", 1000, 0.12) excess = 0 adj_value = 0 assert(asset.value == 1000, lineno()) assert(asset.basis == 1000, lineno()) adj_value = 500 excess = asset.adjust_value(adj_value) assert(excess == 0, lineno()) assert(asset.value == 1500, lineno()) assert(asset.basis == 1500, lineno()) adj_value = -500 excess = asset.adjust_value(adj_value) assert(excess == 0, lineno()) assert(asset.value == 1000, lineno()); assert(asset.basis == 1000, lineno()) adj_value = -2000 excess = asset.adjust_value(adj_value) assert(excess == -1000, lineno()) assert(asset.value == 0, lineno()) assert(asset.basis == 0, lineno()) asset.value = 1500 asset.basis = 1000 adj_value = -500 excess = asset.adjust_value(adj_value) assert(excess == 0, lineno()) assert(asset.value == 1000, lineno()) assert(asset.basis == 1000 + (1000/1500) * -500, lineno()) adj_value = -1200 excess = asset.adjust_value(adj_value) assert(excess == -200, lineno()) assert(asset.value == 0, lineno()) assert(asset.basis == 0, lineno()) # taxable income asset.value = 1000 asset.basis = 500 adj_value = -500 asset.adjust_value(adj_value) #print asset.taxable_income assert(asset.taxable_income == -250, lineno()) asset.value = 1000 asset.basis = 0 adj_value = -500 asset.adjust_value(adj_value) assert(asset.taxable_income == -500, lineno()) asset = AssetTaxDeferred("Test", 1000, 0.12) asset.value = 1000 asset.basis = 500 adj_value = -500 asset.adjust_value(adj_value) assert(asset.taxable_income == -500, lineno()) asset = AssetTaxable("Test", 1000, 0.12) #print "------------------" asset.value = 1000 asset.basis = 250 adj_value = -500 asset.adjust_value(adj_value) assert(asset.taxable_income == -375, lineno()) if __name__ == '__main__': unit_test()