Esempio n. 1
0
    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
Esempio n. 2
0
    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