def openActivityFlexCSV(self, df): ''' This will process a flex activity statement with headers and with or without metadata. The metadata rows are itendified with BOF BOA BOS columns. Setting up to process multiple accounts but the table names are still messed up Raise error if multiple accounts are sent in for now ''' tables = dict() tablenames = dict() mcd = dict() accounts = [] ldf, filemetadata = self.getFrame(('BOF', 'EOF'), df) accountsmetadata = [] if ldf and isinstance(ldf[0], pd.DataFrame): accounts, accountsmetadata = self.getFrame(('BOA', 'EOA'), ldf[0]) if len(accounts) > 1: raise ValueError( 'Multiple accounts is not enabled for Ib Statement parsing' ) filemetadata = filemetadata[0] accountsmetadata = accountsmetadata[0] else: accounts.append(df) for dfa in accounts: if filemetadata: # self.account = filemetadata[1] self.statementname = filemetadata[2] beginDate = filemetadata[4] self.beginDate = pd.Timestamp(beginDate).date() endDate = filemetadata[5] self.endDate = pd.Timestamp(endDate).date() if accountsmetadata: self.account = accountsmetadata[1] tabids = dfa[1].unique() for tabid in tabids: t = dfa[dfa[1] == tabid] if 'BOS' in t[0].unique(): tab, tabmetadata = self.getFrame(('BOS', 'EOS'), t) assert len(tab) == 1 assert len(tabmetadata) == 1 t = tab[0] tabmetadata = tabmetadata[0] currentcols = list(t.columns) headers = list(t[t[0] == 'HEADER'].iloc[0]) t = t[t[0] == 'DATA'] assert len(currentcols) == len(headers) t.columns = headers ourcols = self.getColsByTabid(tabid) ourcols, missingcols = self.verifyAvailableCols( headers, ourcols, tabid) if not ourcols: continue t = t[ourcols] mcd[tabid] = missingcols # Assign to dict and return tables[tabid] = t.copy() tablenames[tabid] = tabid tables, msg = self.doctorFlexTables(tables, mcd) if not len(tables.keys()): # TODO When enabling multi accounts-- fix this to not return return tables, msg ibdb = StatementDB(db=self.db, source='IB') positions = None if 'POST' in tables.keys(): positions = tables['POST'] tables['TRNT'] = self.figureBAPL(tables['TRNT'], positions) ibdb.processStatementSA(tables['TRNT'], self.account, self.beginDate, self.endDate, openPos=positions) return tables, tablenames
def getTablesFromDefaultStatement(self, df): ''' From a default Activity statement csv, retrieve AccountInformation, OpenPositions, and Trades ''' # df = pd.read_csv(infile, header=range(0,15)) keys = df[0].unique() tables = dict() tablenames = dict() mcd = dict() for key in keys: if key not in [ 'Statement', 'Account Information', 'Open Positions', 'Short Open Positions', 'Long Open Positions', 'Trades' ]: continue t = df[df[0] == key] headers = t[t[1].str.lower() == 'header'] if len(headers) > 1: msg = f'This statement has {len(headers)} {key} tables.' msg = msg + '\nMulti account statment not supported.' return dict(), msg assert t.iloc[0][1].lower() == 'header' currentcols = list(t.columns) headers = headers.iloc[0] t = t[t[1].str.lower() == 'data'] assert len(currentcols) == len(headers) t.columns = headers ourcols = self.getColsByTabid(key) ourcols, missingcols = self.verifyAvailableCols( headers, ourcols, key) if not ourcols: continue t = t[ourcols] if key in ['Long Open Positions', 'Short Open Positions']: t = t[t['DataDiscriminator'].str.lower() == 'summary'] key = 'OpenPositions' ourcols = self.getColsByTabid(key) if ourcols: ourcols, missingcols = self.verifyAvailableCols( list(t.columns), ourcols, key) t = t[ourcols].copy() if 'OpenPositions' in tables.keys(): if not set(tables['OpenPositions'].columns) == set( t.columns): msg = 'A Programmer thing-- see it occur before I write code' raise ValueError(msg) tables['OpenPositions'] = tables['OpenPositions'].append(t) tablenames['OpenPositions'] = 'OpenPositions' continue else: key = 'OpenPositions' key = key.replace(' ', '') mcd[key] = missingcols tables[key] = t tablenames[key] = key tables = self.doctorDefaultCSVStatement(tables, mcd) if 'Trades' not in tables.keys(): # This should maybe be a dialog msg = 'The statment lacks a trades table' return dict(), msg if self.account is None: msg = '''This statement lacks an account number. Can't add it to the database''' return dict(), msg ibdb = StatementDB(self.db, source='IB') openpos = None if 'OpenPositions' in tables.keys(): openpos = tables['OpenPositions'] tables['Trades'] = self.figureBAPL(tables['Trades'], tables['OpenPositions']) # Here we need to combine with cheatForBAPL to accomodate statements with no # OpenPositions ibdb.processStatementSA(tables['Trades'], self.account, self.beginDate, self.endDate, openPos=openpos) return tables, tablenames