diff --git a/beancount_reds_importers/importers/tdameritrade/__init__.py b/beancount_reds_importers/importers/tdameritrade/__init__.py index fd19326..e69de29 100644 --- a/beancount_reds_importers/importers/tdameritrade/__init__.py +++ b/beancount_reds_importers/importers/tdameritrade/__init__.py @@ -1,17 +0,0 @@ - -from beancount_reds_importers.libreader import ofxreader -from beancount_reds_importers.libtransactionbuilder import investments - - -class Importer(investments.Importer, ofxreader.Importer): - IMPORTER_NAME = 'TDAmeritrade' - - def custom_init(self): - super(Importer, self).custom_init() - self.max_rounding_error = 0.07 - self.filename_pattern_def = '.*tdameritrade' - self.get_ticker_info = self.get_ticker_info_from_id - - def get_ticker_info(self, security): - ticker = self.config['fund_info']['cusip_map'][security] - return ticker, '' diff --git a/beancount_reds_importers/importers/tdameritrade/tdameritrade_csv.py b/beancount_reds_importers/importers/tdameritrade/tdameritrade_csv.py new file mode 100644 index 0000000..4e650c4 --- /dev/null +++ b/beancount_reds_importers/importers/tdameritrade/tdameritrade_csv.py @@ -0,0 +1,62 @@ +""" TD Ameritrade .csv importer.""" + +from beancount_reds_importers.libreader import csvreader +from beancount_reds_importers.libtransactionbuilder import investments + + +class Importer(csvreader.Importer, investments.Importer): + IMPORTER_NAME = 'TD Ameritrade CSV' + + def custom_init(self): + self.max_rounding_error = 0.04 + self.filename_pattern_def = 'transactions' + self.header_identifier = 'DATE,TRANSACTION ID,DESCRIPTION.*' + self.get_ticker_info = self.get_ticker_info_from_id + self.date_format = '%m/%d/%Y' + self.funds_db_txt = 'funds_by_ticker' + self.skip_head_rows = 0 + self.skip_tail_rows = 1 + self.header_map = { + "DATE": 'date', + "TRANSACTION ID": 'txid', + "DESCRIPTION": 'memo', + "SYMBOL": 'security', + "QUANTITY": 'units', + "PRICE": 'unit_price', + "AMOUNT": 'amount', + "SHORT-TERM RDM FEE": 'short_term_fee', + "FUND REDEMPTION FEE": 'fund_redmpt_fee', + " DEFERRED SALES CHARGE": 'deferred_sales_charge', + "REG FEE": 'fees', + } + self.transaction_type_map = {} + self.skip_transaction_types = [] + + def prepare_raw_columns(self, rdr): + def f(desc): + if desc.startswith('Bought'): + return 'buystock' + if desc.startswith('Sold'): + return 'sellstock' + if desc.startswith('QUALIFIED DIVIDEND'): + return 'dividends' + if desc.startswith('ADR FEE'): + return 'debit' + if desc.startswith('CLIENT REQUESTED ELECTRONIC FUNDING RECEIPT'): + return 'credit' + return 'Unknown type' + + rdr = rdr.addfield('type', lambda x: f(x['DESCRIPTION'])) + rdr = rdr.addfield('total', lambda x: x['AMOUNT']) + rdr = rdr.addfield('tradeDate', lambda x: x['DATE']) + + return rdr + + def get_balance_positions(self): + return [] + + def build_metadata(self, file, metatype=None, data={}): + """This method is for importers to override. The overridden method can + look at the metatype ('transaction', 'balance', 'account', 'commodity', etc.) + and the data dictionary to return additional metadata""" + return {'txid': data['transaction'].txid} diff --git a/beancount_reds_importers/importers/tdameritrade/tdameritrade_csv_examples/run_test.bash b/beancount_reds_importers/importers/tdameritrade/tdameritrade_csv_examples/run_test.bash new file mode 100755 index 0000000..8e5ddb1 --- /dev/null +++ b/beancount_reds_importers/importers/tdameritrade/tdameritrade_csv_examples/run_test.bash @@ -0,0 +1 @@ +bean-extract tdameritrade_csv.import transactions.csv diff --git a/beancount_reds_importers/importers/tdameritrade/tdameritrade_csv_examples/tdameritrade_csv.import b/beancount_reds_importers/importers/tdameritrade/tdameritrade_csv_examples/tdameritrade_csv.import new file mode 100644 index 0000000..ee50d89 --- /dev/null +++ b/beancount_reds_importers/importers/tdameritrade/tdameritrade_csv_examples/tdameritrade_csv.import @@ -0,0 +1,43 @@ +#!/usr/bin/env python3 +"""Import configuration.""" + +import sys +from os import path + +sys.path.insert(0, path.join(path.dirname(__file__))) + +from beancount_reds_importers import tdameritrade_csv + +fund_data = [ + ('BP', '055622104', 'BP p.l.c. ADR'), + ('LUV', '844741108', 'Southwest Airlines Co.'), + ('COST', '22160K105', 'Costco Wholesale Corp.'), + ('VLO', '91913Y100', 'Valero Energy Corp.'), + ('HCP', '418100103', 'HashiCorp, Inc.'), + ('NVDA', '67066G104', 'NVIDIA Corp.'), + ('ON', '682189105', 'ON Semiconductor Corp.'), +] + +money_market = ['VMFXX'] + +fund_info = { + 'fund_data': fund_data, + 'money_market': money_market, +} + +CONFIG = [ + tdameritrade_csv.Importer({ + 'main_account' : 'Assets:Ameritrade:{ticker}', + 'cash_account' : 'Assets:Ameritrade:{currency}', + 'account_number' : 'XXXXXXXXX', + 'transfer' : 'Assets:Zero-Sum-Accounts:Transfers:Bank-Account', + 'dividends' : 'Income:Dividends:Ameritrade:{ticker}', + 'interest' : 'Income:Interest:Ameritrade:{ticker}', + 'cg' : 'Income:Capital-Gains:Ameritrade:{ticker}', + 'capgainsd_lt' : 'Income:Capital-Gains-Distributions:Long:Ameritrade:{ticker}', + 'capgainsd_st' : 'Income:Capital-Gains-Distributions:Short:Ameritrade:{ticker}', + 'fees' : 'Expenses:Brokerage-Fees:Ameritrade', + 'rounding_error' : 'Equity:Rounding-Errors:Imports', + 'fund_info' : fund_info, + }), +] diff --git a/beancount_reds_importers/importers/tdameritrade/tdameritrade_csv_examples/transactions.csv b/beancount_reds_importers/importers/tdameritrade/tdameritrade_csv_examples/transactions.csv new file mode 100644 index 0000000..d13eac4 --- /dev/null +++ b/beancount_reds_importers/importers/tdameritrade/tdameritrade_csv_examples/transactions.csv @@ -0,0 +1,17 @@ +DATE,TRANSACTION ID,DESCRIPTION,QUANTITY,SYMBOL,PRICE,COMMISSION,AMOUNT,REG FEE,SHORT-TERM RDM FEE,FUND REDEMPTION FEE, DEFERRED SALES CHARGE +06/10/2021,35XXXXXXXXX,CLIENT REQUESTED ELECTRONIC FUNDING RECEIPT (FUNDS NOW),,,,,6000.00,,,, +06/11/2021,35XXXXXXXXX,Bought 30 BP @ 27.71,30,BP,27.71,0.00,-831.30,,,, +06/11/2021,35XXXXXXXXX,Bought 50 LUV @ 57.44,50,LUV,57.44,0.00,-2872.00,,,, +06/11/2021,35XXXXXXXXX,Bought 5 COST @ 383.86,5,COST,383.86,0.00,-1919.30,,,, +08/13/2021,36XXXXXXXXX,QUALIFIED DIVIDEND (COST),,COST,,,3.95,,,, +09/24/2021,37XXXXXXXXX,QUALIFIED DIVIDEND (BP),,BP,,,9.83,,,, +09/24/2021,37XXXXXXXXX,ADR FEE (BP),,BP,,,-0.15,,,, +09/27/2021,37XXXXXXXXX,Bought 7 ON @ 49.55,7,ON,49.55,0.00,-346.85,,,, +10/25/2021,38XXXXXXXXX,Sold 5 COST @ 490.045,5,COST,490.045,0.00,2450.22,0.01,,, +11/03/2021,38XXXXXXXXX,Sold 7 ON @ 57.85,7,ON,57.85,0.00,404.95,,,, +11/05/2021,38XXXXXXXXX,Bought 38 VLO @ 76.28,38,VLO,76.28,0.00,-2898.64,,,, +12/09/2021,39XXXXXXXXX,QUALIFIED DIVIDEND (VLO),,VLO,,,37.24,,,, +12/17/2021,39XXXXXXXXX,QUALIFIED DIVIDEND (BP),,BP,,,9.68,,,, +12/23/2021,39XXXXXXXXX,QUALIFIED DIVIDEND (BP),,BP,,,0.15,,,, +12/23/2021,39XXXXXXXXX,QUALIFIED DIVIDEND (BP),,BP,,,-0.15,,,, +***END OF FILE*** diff --git a/beancount_reds_importers/importers/tdameritrade/tdameritrade_ofx.py b/beancount_reds_importers/importers/tdameritrade/tdameritrade_ofx.py new file mode 100644 index 0000000..429a757 --- /dev/null +++ b/beancount_reds_importers/importers/tdameritrade/tdameritrade_ofx.py @@ -0,0 +1,18 @@ +""" TD Ameritrade ofx importer.""" + +from beancount_reds_importers.libreader import ofxreader +from beancount_reds_importers.libtransactionbuilder import investments + + +class Importer(investments.Importer, ofxreader.Importer): + IMPORTER_NAME = 'TDAmeritrade' + + def custom_init(self): + super(Importer, self).custom_init() + self.max_rounding_error = 0.07 + self.filename_pattern_def = '.*tdameritrade' + self.get_ticker_info = self.get_ticker_info_from_id + + def get_ticker_info(self, security): + ticker = self.config['fund_info']['cusip_map'][security] + return ticker, ''