def buy(self, date, in_quantity, from_quantity, from_units="USD", lot_number = None): lot_number = self.check_and_make_buy_lot_number(lot_number) self.transactions.append( Transaction( date, Transaction.float2decimal(in_quantity, self.sigfigs), Transaction.float2decimal(from_quantity, 2), self.units, from_units, lot_number ) )
def sell(self, date, out_quantity, to_quantity, to_units="USD", lot_number=None): gains = self.realized_gains(out_quantity, to_quantity, to_units, lot_number, date) #print(sell_cost) self.transactions.append( Transaction( date, -1*Transaction.float2decimal(out_quantity, self.sigfigs), -1*Transaction.float2decimal(to_quantity, self.sigfigs), self.units, to_units, lot_number ) ) return gains
def filter_transactions_by_date(self, date): if date is None: return self.transactions else: d = Transaction.parse_date(date) # This is a generator, so be sure to make a list if you need to iterate more than once. transactions_filtered = (x for x in self.transactions if x.date <= d) return transactions_filtered
def unrealized_capital_gains(self, price, date=None): transactions_filtered = list(self.filter_transactions_by_date(date)) # The unrealized capital gains are the shares remaining (i.e. not sold) in each lot, # times the price gain, summed over each lot lot_numbers = {x.lot_number for x in transactions_filtered} running_total = 0 for lot_number in lot_numbers: # DRY this up; I copy/pasted this from a different function! lot_volume = sum(x.buy_quantity for x in transactions_filtered if x.lot_number == lot_number) [lot_cost] = [ Transaction.float2decimal(x.sell_quantity / x.buy_quantity, 2) for x in transactions_filtered if x.lot_number == lot_number and x.buy_quantity > 0 ] lot_gains = lot_volume * (Transaction.float2decimal(price, 2) - lot_cost) running_total += lot_gains return running_total
def sell_all(self, date, to_quantity): sell_price = Transaction.float2decimal(to_quantity, 2)/self.volume(date) # DRY this up too, probably transactions_filtered = list(self.filter_transactions_by_date(date)) lot_numbers = {x.lot_number for x in transactions_filtered} output = list() for lot in lot_numbers: lot_volume = sum(x.buy_quantity for x in transactions_filtered if x.lot_number==lot) if lot_volume > 0: output.append(self.sell(date, lot_volume, lot_volume*sell_price, lot_number=lot)) return output
def realized_gains(self, out_quantity, to_quantity, to_units, lot_number, date=None): if lot_number is None: raise Exception("You must specify a lot number when selling!") transactions_filtered = list(self.filter_transactions_by_date(date)) lot_volume = sum(x.buy_quantity for x in transactions_filtered if x.lot_number == lot_number) out_quantity = Transaction.float2decimal(out_quantity, self.sigfigs) to_quantity = Transaction.float2decimal(to_quantity, 2) if lot_volume < out_quantity: raise Exception( "Can't sell more shares ({}) than are in the lot ({})!".format( out_quantity, lot_volume)) [lot_cost] = [ x.sell_quantity / x.buy_quantity for x in transactions_filtered if x.lot_number == lot_number and x.buy_quantity > 0 ] sell_cost = to_quantity / out_quantity return (float(sell_cost) - float(lot_cost)) * float(out_quantity)
def cost_basis(self, date=None): # DRY this up (somehow, hm.) transactions_filtered = list(self.filter_transactions_by_date(date)) lot_numbers = {x.lot_number for x in transactions_filtered} running_total = 0 for lot_number in lot_numers: lot_volume = sum(x.buy_quantity for x in transactions_filtered if x.lot_number == lot_number) [lot_cost] = [ Transaction.float2decimal(x.sell_quantity / x.buy_quantity, 2) for x in transactions_filtered if x.lot_number == lot_number and x.buy_quantity > 0 ] running_total += lot_cost return running_total
def unrealized_capital_gains(self, price, date=None): transactions_filtered = self.filter_transactions_by_date(date) cost_basis = self.__cost_basis_avg_method(date) price = Transaction.float2decimal(price,2) return price*self.volume()-cost_basis