def make_transactions(cls, parts): # 04/14/2016 VANGUARD 500 INDEX ADMIRAL SER Contribution N/A EMPLOYEE PRETAX 1.5475 $192.28 $297.56 parts = [part for part in parts if part] trans_type = parts[-7] date = datetime.strptime(parts[0], '%m/%d/%Y') unit_price = Decimal(parts[-2].lstrip('$')) total = Decimal(parts[-1].replace('$', '').replace(',', '')) if parts[-3] == 'NaN': quantity = (total / unit_price).quantize(Decimal('.0001')) else: quantity = Decimal(parts[-3]) total = quantity * unit_price raw_commodity = ' '.join(parts[1:-7]) commodity = funds.get(raw_commodity) if not commodity: raise Exception('Unknown fund: ' + raw_commodity) other_account = cls.other_accounts.get(trans_type) if not other_account: raise Exception('Unexpected transaction type: ' + trans_type) if trans_type == 'Termination': cash_desc = 'Terminate account' trans_desc = 'Sell {} as part of termination'.format(commodity) # BPAS doesn't display terminations as negative total = -total quantity = -quantity elif trans_type in ('Fees', 'OtherFees'): cash_desc = 'Pay fees' trans_desc = 'Sell {} for fees'.format(commodity) # BPAS doesn't display fees as negative total = -total quantity = -quantity else: cash_desc = 'Cash from {}'.format(trans_type) trans_desc = 'Buy {} with cash from {}'.format( commodity, trans_type) return [ Transaction(date, cash_desc, [ Posting(cls.account, total), Posting(other_account), ]), Transaction(date, trans_desc, [ Posting(cls.account, quantity, commodity, unit_price), Posting(cls.account), ]) ]
def make_transactions(cls, parts): desc = parts[2].strip('"') date = datetime.strptime(parts[0], '%m/%d/%Y') quantity = Decimal(cls.trunc(parts[4])) posting = Posting(account='Liabilities:Credit Cards:U.S. Bank', quantity=quantity) return [Transaction(date=date, desc=desc, postings=[posting])]
def make_transactions(cls, parts): desc = parts[3].strip('"') date = datetime.strptime(parts[1], '%m/%d/%y') quantity = Decimal(parts[4]) if parts[5] == 'DR': quantity *= -1 posting = Posting(account=cls.account, quantity=quantity) return [Transaction(date=date, desc=desc, postings=[posting])]
def make_transactions(cls, parts): desc = parts[6].strip('"') date = datetime.strptime(parts[5], '%m/%d/%Y') if parts[2]: quantity = -1 * Decimal(parts[2]) else: quantity = Decimal(parts[3]) posting = Posting(account=cls.account, quantity=quantity) return [Transaction(date=date, desc=desc, postings=[posting])]
def make_transactions(cls, parts): # 11/02/2016,VANG TARGET RET 2045,CONTRIBUTION,"980.00","52.887" date = datetime.strptime(parts[0], '%m/%d/%Y') trans_type = parts[2] if trans_type == 'REALIZED G/L': # useless; ignore return [] total = Decimal(parts[3].strip('"').replace(',', '')) quantity = Decimal(parts[4].strip('"').replace(',', '')) unit_price = total / quantity commodity = funds.get(parts[1]) if not commodity: raise Exception('Unknown fund: ' + raw_commodity) other_account = cls.other_accounts.get(trans_type) if not other_account: raise Exception('Unexpected transaction type: ' + trans_type) if trans_type in ('CONTRIBUTION', 'DIVIDEND'): cash_desc = 'Cash from {}'.format(trans_type) trans_desc = 'Buy {} with cash from {}'.format( commodity, trans_type) elif trans_type in ('ADMINISTRATIVE FEES', 'RECORDKEEPING FEE', 'ADVISOR FEE', 'ADVISOR / CONSULTANT FEE'): cash_desc = 'Pay fees' trans_desc = 'Sell {} for fees'.format(commodity) elif trans_type in ('Withdrawals', ): cash_desc = 'Withdraw funds' trans_desc = 'Sell {} for withdrawal'.format(commodity) else: raise Exception('Unknown trans_type: ' + trans_type) return [ Transaction(date, cash_desc, [ Posting(cls.account, total), Posting(other_account), ]), Transaction(date, trans_desc, [ Posting(cls.account, quantity, commodity, unit_price), Posting(cls.account), ]) ]
def make_transactions(cls, parts): # 4/8/2016,380737G1 GR1001 102136,Buy,CREF Equity Index R3,162.4489,2.4237,393.73,Contribution trans_type = parts[7] date = datetime.strptime(parts[0], '%m/%d/%Y') quantity = Decimal(parts[5]) unit_price = Decimal(parts[4]) total = quantity * unit_price commodity = funds.get(parts[3]) if not commodity: raise Exception('Unknown fund: ' + parts[3]) other_account = cls.other_accounts.get(trans_type) if not other_account: raise Exception('Unexpected transaction type: ' + trans_type) if trans_type == 'Transfer': cash_trans_index = None if quantity < 0: trans_desc = 'Transfer out of {}'.format(commodity) else: trans_desc = 'Transfer into {}'.format(commodity) else: cash_desc = 'Cash from {}'.format(trans_type) trans_desc = 'Buy {} with cash from {}'.format( commodity, trans_type) cash_trans_index = 0 transactions = [ Transaction(date, trans_desc, [ Posting(cls.account, quantity, commodity, unit_price), Posting(cls.account), ]) ] if cash_trans_index is not None: transactions.insert( cash_trans_index, Transaction(date, cash_desc, [ Posting(cls.account, total), Posting(other_account), ])) return transactions
def record_transaction(self, trans, acct): if acct: trans.postings.append(Posting(account=acct)) self.journal.accounts.add(acct) self.journal.add_desc_to_map(trans.desc, acct) # skip if mirror transaction if self.journal.is_mirror_trans(trans): print('###################') print('MIRROR TRANSACTION: \n{}'.format(trans)) print('###################') return self.journal.transactions.append(trans)
def make_transactions(cls, parts): # 34549708,10/11/2016,10/12/2016,Buy,Buy,VANGUARD TARGET RETIREMENT 2045 INVESTOR CL,VTIVX,1244.048,18.83,-23425.43,0.0,-23425.43,0.0,Cash, trans_type = parts[3] date = datetime.strptime(parts[2], '%m/%d/%Y') quantity = Decimal(parts[7]) if parts[7] else 0 #unit_price = Decimal(parts[8]) total = Decimal(parts[9]) unit_price = abs(total / quantity) if quantity else 0 # default to money market symbol because it is omitted from data commodity = parts[6] if parts[6] else 'VMFXX' if trans_type in ('Dividend', 'Capital gain (LT)', 'Capital gain (ST)'): desc = 'Cash from dividends' postings = [ Posting(cls.account, total), Posting('Income:Dividends') ] elif trans_type == 'Sweep out': desc = 'Cash out of sweep account' quantity = total # for MM acct, 1 share == $1 postings = [ Posting(cls.account, -quantity, commodity, unit_price), Posting(cls.account, total) ] elif trans_type == 'Sweep in': desc = 'Cash into sweep account' quantity = total # for MM acct, 1 share == $1 postings = [ Posting(cls.account, total), Posting(cls.account, -quantity, commodity, unit_price) ] elif trans_type in ('Buy', 'Reinvestment', 'Reinvestment (ST gain)', 'Reinvestment (LT gain)'): desc = 'Buy ' + commodity postings = [ Posting(cls.account, quantity, commodity, unit_price), Posting(cls.account, total) ] elif trans_type == 'Rollover (incoming)': # skip this, assuming source account will record it return [] else: raise Exception('Unexpected transaction type: ' + trans_type) return [Transaction(date, desc, postings)]
def make_transactions(cls, parts): # As of sometime in 2018, Vanguard *sometimes* now separates the # capital gain and dividend payment transactions from the reinvestment # transactions so we expect two lines like this: # # 62341669,12/28/2018,12/28/2018,Capital gain (LT),Long-Term Capital Gains Distribution,VANGUARD TARGET RETIREMENT 2045 INVESTOR CL,VTIVX,0.0,1.0,0.95,0.0,0.95,0.0,Cash, # 62341669,12/28/2018,12/28/2018,Reinvestment (LT gain),Reinvestment of a Long-Term Capital Gains Distribution,VANGUARD TARGET RETIREMENT 2045 INVESTOR CL,VTIVX,0.047,20.08,-0.95,0.0,-0.95,0.0,Cash, # # We're going to ignore the first transaction of every pair # and then *assume* that it exists when we process the second one. # What Could Go Wrong(tm)? trans_type = parts[3] if trans_type == 'Dividend' or trans_type.startswith('Capital gain'): return [] date = datetime.strptime(parts[2], '%m/%d/%Y') quantity = Decimal(parts[7]) unit_price = Decimal(parts[8]) total = quantity * unit_price commodity = funds.get(parts[5]) if not commodity: raise Exception('Unknown fund: ' + parts[5]) other_account = cls.other_accounts.get(trans_type) if trans_type in {'Exchange', 'Buy'}: # exchanging funds within same account if quantity > 0: desc = 'Buy ' + commodity else: desc = 'Sell ' + commodity postings = [ Posting(cls.account, quantity, commodity, unit_price), Posting(cls.account, -total) ] return [Transaction(date, desc, postings)] if not other_account: raise Exception('Unexpected transaction type: ' + trans_type) return [ Transaction(date, 'Cash from {}'.format(trans_type), [ Posting(cls.account, total), Posting(other_account), ]), Transaction( date, 'Buy {} with cash from {}'.format(commodity, trans_type), [ Posting(cls.account, quantity, commodity, unit_price), Posting(cls.account), ]) ]
def make_transactions(cls, parts): desc = parts[4].strip('"') date = datetime.strptime(parts[0], '%Y-%m-%d') quantity = Decimal(parts[2]) posting = Posting(account=cls.account, quantity=quantity) return [Transaction(date=date, desc=desc, postings=[posting])]
def make_transactions(cls, parts): trans_type = parts[2] date = datetime.strptime(parts[0], '%Y%m%d') quantity = Decimal(parts[4]) unit_price = Decimal(parts[5].lstrip('$')) total = quantity * unit_price commodity = funds.get(parts[1]) if not commodity: raise Exception('Unknown fund: ' + parts[1]) other_account = cls.other_accounts.get(trans_type) if not other_account: raise Exception('Unexpected transaction type: ' + trans_type) if trans_type in {'Earnings', 'Contributions'}: cash_desc = 'Cash from {}'.format(trans_type) trans_desc = 'Buy {} with cash from {}'.format( commodity, trans_type) cash_trans_index = 0 elif trans_type == 'Transfers': cash_trans_index = None if quantity < 0: trans_desc = 'Transfer out of {}'.format(commodity) else: trans_desc = 'Transfer into {}'.format(commodity) # assume that transfers come in pairs and make their totals # match up exactly by tweaking the unit price of the second one # (because Wells Fargo's math/rounding is not to be trusted) if cls.previous_transfer is None: cls.previous_transfer = total else: total = -cls.previous_transfer unit_price = total / quantity cls.previous_transfer = None elif trans_type == 'In-Service Payout': cash_desc = 'Close account' trans_desc = 'Sell {} to close account'.format(commodity) cash_trans_index = 1 else: cash_desc = 'Pay fees' trans_desc = 'Sell {} for fees'.format(commodity) cash_trans_index = 1 transactions = [ Transaction(date, trans_desc, [ Posting(cls.account, quantity, commodity, unit_price), Posting(cls.account), ]) ] if cash_trans_index is not None: transactions.insert( cash_trans_index, Transaction(date, cash_desc, [ Posting(cls.account, total), Posting(other_account), ])) return transactions