Skip to content

cash_calculator.py

Realiza a “quebra” do caixa (Tesouro Selic, Trade RV, taxas, etc.)
e calcula provisões de trades a liquidar.

CashCalculator

Source code in carteira_online/production/cash_calculator.py
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
class CashCalculator:

    def __init__(self, input_path, today=dt.date.today()):

        self.today=today
        self.base_path = input_path
        self.cash_base = self.load_base()


    def load_base(self):
        # por enquanto trata apenas os caixas offshore
        data = pd.read_excel(self.base_path, sheet_name="Caixa Offshore")

        return data


    def _calculate_trades_rv(self, fund_name, trades, start_date, source="offshore"):
        hoje = self.today
        n_days = (hoje - start_date).days

        trades_rv = ["trade rv d0", "trade rv d1", "trade rv d2", "trade rv d3",
                    "trade rv d4", "trade rv d5", "trade rv d6"]
        if n_days > 6:
            print(f"Possível erro no caixa do {fund_name}. Verificar!")

        # Acumulando trades rv
        trades_rv = trades_rv[:n_days]

        trade_rv_tot = 0
        for idx, row in trades.iterrows():
            if row["Asset"] in trades_rv:
                trade_rv_tot += row["Quantidade"]
        return trade_rv_tot


    def get_net_cash(self, fund_name, trades, data_extractor, query_mngr, source="offshore"):
        """
        Calcula o caixa líquido de um fundo, considerando trades e ajustes.

        Args:
            fund_name (str): Nome do fundo.
            trades (pd.DataFrame): DataFrame contendo os trades do fundo.
            data_extractor: Objeto para extrair dados específicos (e.g., BTG).
            query_mngr: Objeto para consultas ao banco de dados.
            source (str, optional): Fonte do caixa ('offshore' ou 'onshore'). Defaults to "offshore".

        Returns:
            dict: Dicionário contendo o caixa e outros componentes relevantes.
        """


        if source == "offshore":
            # TODO pegar caixa da offshore do book gerencial

            #df = self.cash_base.loc[ self.cash_base["Fundo"] == fund_name ].sort_values(by="Data")
            #last_date = df["Data"].iat[-1]
            #df = df.loc[ df["Data"] == last_date]
            #cash = df["Caixa"].sum() + df["Ajuste"].sum()
            #start_date = self.cash_base.loc[ self.cash_base["Fundo"] == fund_name, "Data"].iloc[0].date()
            #trade_rv = self._calculate_trades_rv(fund_name, trades, start_date, source=source)
            #cash += trade_rv
            # Obtendo a tabela de caixas para o fundo em questao
            df = self.cash_base.query("Fundo == @fund_name")[["Data", "Tipo_Conta", "Caixa"]].copy()
            print("-- - -- -- -- -- -- -- -- -- -- ")
            print(df)
            print("-- - -- -- -- -- -- -- -- -- -- ")

            # Agrupando o caixa por tipo de conta
            df = df.groupby("Tipo_Conta").agg({"Data":"last", "Caixa":"sum"}).reset_index()
            # Na data mais recente dos caixas informados, vamos calcular os trades rv
            last_date = df["Data"].iat[-1].date()

            trade_rv = self._calculate_trades_rv(fund_name, trades, last_date, source=source)
            # O trade rv será impactado no caixa na conta asset
            df["Caixa"] = np.where(df["Tipo_Conta"] == 'us asset account', df["Caixa"] + trade_rv, df["Caixa"])

            # Retornando finalmente um dicionario quebrando o caixa por tipo de conta
            cash = df.set_index("Tipo_Conta")["Caixa"].to_dict()

            return {"Caixa" : cash, "Trade RV" : trade_rv}

            #df = self.cash_base.loc[ self.cash_base["Fundo"] == fund_name ].sort_values(by="Data")
            #last_date = df["Data"].iat[-1]
            #df = df.loc[ df["Data"] == last_date]
            #cash = df["Caixa"].sum() + df["Ajuste"].sum()
            #start_date = self.cash_base.loc[ self.cash_base["Fundo"] == fund_name, "Data"].iloc[0].date()
            #trade_rv = self._calculate_trades_rv(fund_name, trades, start_date, source=source)
            #cash += trade_rv
            #
            #return {"Caixa" : cash, "Trade RV" : trade_rv}
            #

        elif source == "onshore":
            btg_extractor = data_extractor.btg_extractor
            fund_name = fund_name.title()
            # primeiro salva o caixa baseado na carteira do btg disponivel
            # (valido para manga, lipi e global)
            selic = btg_extractor.get_cx_tesouro(fund_name)
            outros = btg_extractor.get_cx_outros(fund_name)
            # destrinchando outros:
            a_pagar = btg_extractor.get_cx_a_pagar(fund_name)
            a_receber = btg_extractor.get_cx_a_receber(fund_name)
            despesa = btg_extractor.get_cx_despesa(fund_name)
            taxa_adm = btg_extractor.get_cx_taxa_adm(fund_name)

            cx_offshore = btg_extractor.get_cx_offshore(fund_name)
            acoes_offshore = btg_extractor.get_acoes_offshore(fund_name)
            ntnb = btg_extractor.get_ntnb(fund_name)


            termo = 0 if fund_name not in data_extractor.term_adj else data_extractor.term_adj[fund_name] # TODO Fazer pegar esse total direito btg_extractor.get_tot_termos()
            a_pagar = a_pagar - termo    # Tirando termos do a pagar
                            # PROBLEMA 1: acabando o termo, devera continuar sendo abatido ate carteira atualizar
                            # PROBLEMA 2: novos termos só deverao ser abatidos depois da carteira atualizar
            #SOLUCAO:
            #if fund_name == "Lipizzaner":
            #    ajuste_tecnico_termos = 0.0 #AJUSTAR DIRETO AQUI!!!
            #    a_pagar += ajuste_tecnico_termos

            outros = outros - a_pagar - termo - a_receber - despesa - taxa_adm - cx_offshore - acoes_offshore - ntnb


            fut_adj = 0 #TODO REIMPLEMENTAR data_extractor.get_fut_adj(fund_name)

            # corrigir caixa pelos trades realizados
            # verficar numero de dias a serem corrigidos
            data_btg = btg_extractor.get_date(fund_name)
            trade_rv = self._calculate_trades_rv(fund_name, trades, data_btg, source=source)

            caixa = selic + outros + a_pagar + a_receber + despesa + taxa_adm + fut_adj + trade_rv + cx_offshore

            cx_liquido = caixa - despesa
            return {"Caixa" : caixa, "Caixa Líquido" : caixa,
                    "Tesouro" : selic, "Trade RV" : trade_rv,
                    "A Pagar" : a_pagar, "A Receber" : a_receber,
                    "Despesa" : despesa, "Taxa Adm" : taxa_adm,
                    "Ajuste Futuro" : fut_adj, "Outros" : outros, "Cx Offshore" : cx_offshore}

get_net_cash(fund_name, trades, data_extractor, query_mngr, source='offshore')

Calcula o caixa líquido de um fundo, considerando trades e ajustes.

Parameters:

Name Type Description Default
fund_name str

Nome do fundo.

required
trades DataFrame

DataFrame contendo os trades do fundo.

required
data_extractor

Objeto para extrair dados específicos (e.g., BTG).

required
query_mngr

Objeto para consultas ao banco de dados.

required
source str

Fonte do caixa ('offshore' ou 'onshore'). Defaults to "offshore".

'offshore'

Returns:

Name Type Description
dict

Dicionário contendo o caixa e outros componentes relevantes.

Source code in carteira_online/production/cash_calculator.py
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
def get_net_cash(self, fund_name, trades, data_extractor, query_mngr, source="offshore"):
    """
    Calcula o caixa líquido de um fundo, considerando trades e ajustes.

    Args:
        fund_name (str): Nome do fundo.
        trades (pd.DataFrame): DataFrame contendo os trades do fundo.
        data_extractor: Objeto para extrair dados específicos (e.g., BTG).
        query_mngr: Objeto para consultas ao banco de dados.
        source (str, optional): Fonte do caixa ('offshore' ou 'onshore'). Defaults to "offshore".

    Returns:
        dict: Dicionário contendo o caixa e outros componentes relevantes.
    """


    if source == "offshore":
        # TODO pegar caixa da offshore do book gerencial

        #df = self.cash_base.loc[ self.cash_base["Fundo"] == fund_name ].sort_values(by="Data")
        #last_date = df["Data"].iat[-1]
        #df = df.loc[ df["Data"] == last_date]
        #cash = df["Caixa"].sum() + df["Ajuste"].sum()
        #start_date = self.cash_base.loc[ self.cash_base["Fundo"] == fund_name, "Data"].iloc[0].date()
        #trade_rv = self._calculate_trades_rv(fund_name, trades, start_date, source=source)
        #cash += trade_rv
        # Obtendo a tabela de caixas para o fundo em questao
        df = self.cash_base.query("Fundo == @fund_name")[["Data", "Tipo_Conta", "Caixa"]].copy()
        print("-- - -- -- -- -- -- -- -- -- -- ")
        print(df)
        print("-- - -- -- -- -- -- -- -- -- -- ")

        # Agrupando o caixa por tipo de conta
        df = df.groupby("Tipo_Conta").agg({"Data":"last", "Caixa":"sum"}).reset_index()
        # Na data mais recente dos caixas informados, vamos calcular os trades rv
        last_date = df["Data"].iat[-1].date()

        trade_rv = self._calculate_trades_rv(fund_name, trades, last_date, source=source)
        # O trade rv será impactado no caixa na conta asset
        df["Caixa"] = np.where(df["Tipo_Conta"] == 'us asset account', df["Caixa"] + trade_rv, df["Caixa"])

        # Retornando finalmente um dicionario quebrando o caixa por tipo de conta
        cash = df.set_index("Tipo_Conta")["Caixa"].to_dict()

        return {"Caixa" : cash, "Trade RV" : trade_rv}

        #df = self.cash_base.loc[ self.cash_base["Fundo"] == fund_name ].sort_values(by="Data")
        #last_date = df["Data"].iat[-1]
        #df = df.loc[ df["Data"] == last_date]
        #cash = df["Caixa"].sum() + df["Ajuste"].sum()
        #start_date = self.cash_base.loc[ self.cash_base["Fundo"] == fund_name, "Data"].iloc[0].date()
        #trade_rv = self._calculate_trades_rv(fund_name, trades, start_date, source=source)
        #cash += trade_rv
        #
        #return {"Caixa" : cash, "Trade RV" : trade_rv}
        #

    elif source == "onshore":
        btg_extractor = data_extractor.btg_extractor
        fund_name = fund_name.title()
        # primeiro salva o caixa baseado na carteira do btg disponivel
        # (valido para manga, lipi e global)
        selic = btg_extractor.get_cx_tesouro(fund_name)
        outros = btg_extractor.get_cx_outros(fund_name)
        # destrinchando outros:
        a_pagar = btg_extractor.get_cx_a_pagar(fund_name)
        a_receber = btg_extractor.get_cx_a_receber(fund_name)
        despesa = btg_extractor.get_cx_despesa(fund_name)
        taxa_adm = btg_extractor.get_cx_taxa_adm(fund_name)

        cx_offshore = btg_extractor.get_cx_offshore(fund_name)
        acoes_offshore = btg_extractor.get_acoes_offshore(fund_name)
        ntnb = btg_extractor.get_ntnb(fund_name)


        termo = 0 if fund_name not in data_extractor.term_adj else data_extractor.term_adj[fund_name] # TODO Fazer pegar esse total direito btg_extractor.get_tot_termos()
        a_pagar = a_pagar - termo    # Tirando termos do a pagar
                        # PROBLEMA 1: acabando o termo, devera continuar sendo abatido ate carteira atualizar
                        # PROBLEMA 2: novos termos só deverao ser abatidos depois da carteira atualizar
        #SOLUCAO:
        #if fund_name == "Lipizzaner":
        #    ajuste_tecnico_termos = 0.0 #AJUSTAR DIRETO AQUI!!!
        #    a_pagar += ajuste_tecnico_termos

        outros = outros - a_pagar - termo - a_receber - despesa - taxa_adm - cx_offshore - acoes_offshore - ntnb


        fut_adj = 0 #TODO REIMPLEMENTAR data_extractor.get_fut_adj(fund_name)

        # corrigir caixa pelos trades realizados
        # verficar numero de dias a serem corrigidos
        data_btg = btg_extractor.get_date(fund_name)
        trade_rv = self._calculate_trades_rv(fund_name, trades, data_btg, source=source)

        caixa = selic + outros + a_pagar + a_receber + despesa + taxa_adm + fut_adj + trade_rv + cx_offshore

        cx_liquido = caixa - despesa
        return {"Caixa" : caixa, "Caixa Líquido" : caixa,
                "Tesouro" : selic, "Trade RV" : trade_rv,
                "A Pagar" : a_pagar, "A Receber" : a_receber,
                "Despesa" : despesa, "Taxa Adm" : taxa_adm,
                "Ajuste Futuro" : fut_adj, "Outros" : outros, "Cx Offshore" : cx_offshore}