luxorasap 0.1.9__py3-none-any.whl → 0.1.10__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
luxorasap/__init__.py CHANGED
@@ -13,7 +13,7 @@ from types import ModuleType
13
13
  try:
14
14
  __version__: str = metadata.version(__name__)
15
15
  except metadata.PackageNotFoundError: # editable install
16
- __version__ = "0.1.9"
16
+ __version__ = "0.1.10"
17
17
 
18
18
  # ─── Lazy loader ─────────────────────────────────────────────────
19
19
  def __getattr__(name: str) -> ModuleType:
@@ -572,7 +572,9 @@ class LuxorQuery:
572
572
  query_asset = asset
573
573
  if asset == 'bmfxclco curncy':
574
574
  query_asset = 'usdbrl curncy'
575
- variation = self.get_pct_change(query_asset, recent_date=today, previous_date=last_date)
575
+ variation = 0
576
+ if today > last_date:
577
+ variation = self.get_pct_change(query_asset, recent_date=today, previous_date=last_date)
576
578
  # vamos ajustar o preco com a variacao
577
579
  last_price = last_price * (1 + variation)
578
580
  # vamos colocar na base na data de hoje
@@ -977,9 +979,10 @@ class LuxorQuery:
977
979
 
978
980
  # A partir de uma data pegar o trimestre anterior
979
981
  elif period == 'qtr':
980
- start_date = ref_date - pd.DateOffset(months=3)
981
- start_date = start_date.date()
982
- start_date = self.get_month_end(start_date)
982
+ # Deve retornar sempre a ultima data do final do trimestre anterior
983
+ current_quarter = (ref_date.month - 1) // 3 + 1
984
+ start_of_current_quarter = dt.date(ref_date.year, (current_quarter - 1) * 3 + 1, 1)
985
+ start_date = start_of_current_quarter - dt.timedelta(days=1) # Last day of previous quarter
983
986
 
984
987
  if force_bday:
985
988
  start_date = self.get_bday_offset(start_date, offset=0, location=holiday_location)
@@ -1263,7 +1266,7 @@ class LuxorQuery:
1263
1266
  return self.get_price(price_key, px_date=date) * usdbrl/bdr_size
1264
1267
 
1265
1268
 
1266
- def normalize_trades(self, trades, currency, asset_id_columns="Asset_ID"):
1269
+ def normalize_trades(self, trades, currency, asset_id_columns="Asset_ID", usdbrl_ticker="bmfxclco curncy"):
1267
1270
  """ Para um dado dataframe de trades, converte para moeda indicada.
1268
1271
  Trades devem conter as colunas Asset, Ticker e Delta_Shares.
1269
1272
  BDR: Usa o peso do BDR e a quantidade de BDR operada para chegar na quantidade do ativo original.
@@ -1312,7 +1315,7 @@ class LuxorQuery:
1312
1315
  #trades["Delta_Shares"] = np.where(trades["Ticker"] == 'brk/a us equity', trades["Delta_Shares"] * brkA_brkB_ratio, trades["Delta_Shares"])
1313
1316
 
1314
1317
  # Adicionando coluna de usdbrl de fechamento em cada dia
1315
- hist_usdbrl = self.get_prices("bmfxclco curncy", previous_date=previous_date, recent_date=recent_date).rename(columns={"Last_Price": "USDBRL"})
1318
+ hist_usdbrl = self.get_prices(usdbrl_ticker, previous_date=previous_date, recent_date=recent_date).rename(columns={"Last_Price": "USDBRL"})
1316
1319
 
1317
1320
  trades = pd.merge(trades, hist_usdbrl[["Date", "USDBRL"]], on="Date")
1318
1321
 
@@ -1416,7 +1419,7 @@ class LuxorQuery:
1416
1419
 
1417
1420
  def __get_positions_and_movements(self, fund_name, tickers=None,
1418
1421
  recent_date=dt.date.today(), previous_date=dt.date.today()-dt.timedelta(days=1),
1419
- period=None, holiday_location="all", currency="usd"):
1422
+ period=None, holiday_location="all", currency="usd", usdbrl_ticker="bmfxclco curncy"):
1420
1423
  """
1421
1424
  Args:
1422
1425
  fund_name (str):
@@ -1501,7 +1504,7 @@ class LuxorQuery:
1501
1504
  #trades["Trade_Side"] = np.where(trades["Delta_Shares"] < 0, "sell", "buy")
1502
1505
 
1503
1506
  # Ordenando boletas, por padrao vamos sempre comprar antes de vender.
1504
- trades = self.normalize_trades(trades, currency=currency).sort_values(by=["Date"], kind="stable")
1507
+ trades = self.normalize_trades(trades, currency=currency, usdbrl_ticker=usdbrl_ticker).sort_values(by=["Date"], kind="stable")
1505
1508
  # Apos normalizar os trades, eh necessario recalcular o preco da boleta
1506
1509
 
1507
1510
  # Agrupando boletas de forma a ter apenas uma boleta por dia por codigo de ativo
@@ -1528,7 +1531,7 @@ class LuxorQuery:
1528
1531
 
1529
1532
  def get_positions_and_movements(self, fund_name, tickers=None,
1530
1533
  recent_date=dt.date.today(), previous_date=dt.date.today()-dt.timedelta(days=1),
1531
- period=None, holiday_location="all", currency="usd"):
1534
+ period=None, holiday_location="all", currency="usd", usdbrl_ticker="bmfxclco curncy"):
1532
1535
 
1533
1536
  """
1534
1537
  Args:
@@ -1546,7 +1549,7 @@ class LuxorQuery:
1546
1549
  df = self.__run_return_analysis(fund_name, tickers=tickers,
1547
1550
  recent_date=recent_date, previous_date=previous_date,
1548
1551
  period=period, holiday_location=holiday_location,
1549
- currency=currency, agregate_by_name=False
1552
+ currency=currency, agregate_by_name=False, usdbrl_ticker=usdbrl_ticker
1550
1553
  )
1551
1554
  # Vamos obter os precos de fechamento em cada dia
1552
1555
  # Preenchendo primeiro todo o historico
@@ -1554,9 +1557,9 @@ class LuxorQuery:
1554
1557
  price_keys = list(df["Price_Key"].unique())
1555
1558
  prices = self.get_prices(
1556
1559
  tickers=price_keys, previous_date=prices_previous_date, currency=currency,
1557
- get_intraday_prices=True
1560
+ get_intraday_prices=True, usdbrl_ticker=usdbrl_ticker
1558
1561
  ).rename(columns={"Asset":"Price_Key"})
1559
-
1562
+
1560
1563
  df = df.merge(prices, on=["Date", "Price_Key"], how="left")
1561
1564
  # Finalmente, vamos atualizar com o preco mais recente do ativo na data de hoje
1562
1565
  #df_prev = df.query("Date < @dt.date.today()").copy()
@@ -1585,17 +1588,20 @@ class LuxorQuery:
1585
1588
  return df
1586
1589
 
1587
1590
 
1588
- def run_return_analysis(self, fund_name, tickers=None, recent_date=dt.date.today(), previous_date=dt.date.today()-dt.timedelta(days=1), period=None, holiday_location="all"):
1591
+ def run_return_analysis(self, fund_name, tickers=None, recent_date=dt.date.today(), previous_date=dt.date.today()-dt.timedelta(days=1),
1592
+ period=None, holiday_location="all", usdbrl_ticker="bmfxclco curncy"):
1589
1593
 
1590
1594
  currency = "usd"
1591
1595
  positions_and_movements_usd = self.__run_return_analysis(fund_name, tickers=tickers, recent_date=recent_date,
1592
1596
  previous_date=previous_date, period=period,
1593
- holiday_location=holiday_location, currency=currency)
1597
+ holiday_location=holiday_location, currency=currency,
1598
+ usdbrl_ticker=usdbrl_ticker)
1594
1599
  currency = "brl"
1595
1600
 
1596
1601
  positions_and_movements_brl = self.__run_return_analysis(fund_name, tickers=tickers, recent_date=recent_date,
1597
1602
  previous_date=previous_date, period=period,
1598
- holiday_location=holiday_location, currency=currency)
1603
+ holiday_location=holiday_location, currency=currency,
1604
+ usdbrl_ticker=usdbrl_ticker)
1599
1605
  if (positions_and_movements_usd is None) and (positions_and_movements_brl is None): return None
1600
1606
 
1601
1607
  return pd.concat([positions_and_movements_usd, positions_and_movements_brl])
@@ -1623,11 +1629,12 @@ class LuxorQuery:
1623
1629
 
1624
1630
  def __run_return_analysis(self, fund_name, tickers=None, recent_date=dt.date.today(),
1625
1631
  previous_date=dt.date.today()-dt.timedelta(days=1), period=None, holiday_location="all",
1626
- currency="usd", agregate_by_name=True):
1632
+ currency="usd", agregate_by_name=True, usdbrl_ticker="bmfxclco curncy"):
1627
1633
 
1628
1634
  assert(currency in ["usd", "brl"])
1629
1635
 
1630
- positions_and_movements = self.__get_positions_and_movements(fund_name, tickers, recent_date, previous_date, period, holiday_location, currency=currency)
1636
+ positions_and_movements = self.__get_positions_and_movements(fund_name, tickers, recent_date, previous_date, period, holiday_location,
1637
+ currency=currency, usdbrl_ticker=usdbrl_ticker)
1631
1638
 
1632
1639
  # -> Shares_Bought : Delta_Shares > 0
1633
1640
  positions_and_movements["Shares_Bought"] = np.where(positions_and_movements["Delta_Shares"] > 0, positions_and_movements["Delta_Shares"], 0)
@@ -1688,7 +1695,8 @@ class LuxorQuery:
1688
1695
 
1689
1696
  # -> pegar precos e colocar no diario
1690
1697
  previous_date = positions_and_movements["Date"].min().date()
1691
- prices = self.get_prices(tickers = list(positions_and_movements["Price_Key"].unique()), previous_date=previous_date-dt.timedelta(days=100), currency=currency).rename(columns={"Asset":"Price_Key"})
1698
+ prices = self.get_prices(tickers = list(positions_and_movements["Price_Key"].unique()), previous_date=previous_date-dt.timedelta(days=100), currency=currency,
1699
+ usdbrl_ticker=usdbrl_ticker).rename(columns={"Asset":"Price_Key"})
1692
1700
 
1693
1701
  positions_and_movements = positions_and_movements.merge(prices, on=["Date", "Price_Key"])
1694
1702
 
@@ -1745,7 +1753,8 @@ class LuxorQuery:
1745
1753
  positions_and_movements = self.normalize_price_key(positions_and_movements)
1746
1754
  # A normalizacao pode acabar inserindo algum ticker generico que ainda nao estava calculado. Logo, temos que pegar os precos novamente.
1747
1755
  prices = self.get_prices(tickers = list(positions_and_movements["Price_Key"].unique()),
1748
- previous_date=previous_date-dt.timedelta(days=100), currency=currency).rename(columns={"Asset":"Price_Key"})
1756
+ previous_date=previous_date-dt.timedelta(days=100), currency=currency,
1757
+ usdbrl_ticker=usdbrl_ticker).rename(columns={"Asset":"Price_Key"})
1749
1758
 
1750
1759
  positions_and_movements = positions_and_movements.merge(prices[["Date", "Price_Key", "Last_Price"]], on=["Date","Price_Key"])
1751
1760
 
@@ -1777,7 +1786,8 @@ class LuxorQuery:
1777
1786
 
1778
1787
  positions_and_movements["Days_Since_Start"] = (positions_and_movements["Date"] - positions_and_movements["Start_Date"]).dt.days
1779
1788
 
1780
- spx_prices = self.get_prices("inx index", recent_date=recent_date, previous_date=previous_date, currency=currency)[["Date", "Last_Price"]].rename(columns={"Last_Price" : "spx_index"})
1789
+ spx_prices = self.get_prices("inx index", recent_date=recent_date, previous_date=previous_date, currency=currency,
1790
+ usdbrl_ticker=usdbrl_ticker)[["Date", "Last_Price"]].rename(columns={"Last_Price" : "spx_index"})
1781
1791
  positions_and_movements = positions_and_movements.merge(spx_prices, on="Date", how="left")
1782
1792
 
1783
1793
  #positions_and_movements["spx_index"] = (positions_and_movements["spx_index"].pct_change().fillna(0)+1).cumprod()-1
@@ -1838,21 +1848,21 @@ class LuxorQuery:
1838
1848
  cash = cash.drop(columns=["usdbrl"])
1839
1849
 
1840
1850
  # Vamos calcular o preco de fechamento com o rendimento do dia
1841
- bz_cash_index = self.get_prices("bzacselc index", period="60m", currency=currency)
1851
+ bz_cash_index = self.get_prices("bzacselc index", period="60m", currency=currency, usdbrl_ticker=usdbrl_ticker)
1842
1852
  bz_cash_index["Date"] = bz_cash_index["Date"].dt.date
1843
1853
  bz_cash_index = (bz_cash_index[["Date", "Last_Price"]]
1844
1854
  .rename(columns={"Last_Price":"bz_cash_index"})
1845
1855
  .set_index("Date").pct_change()
1846
1856
  .fillna(0)+1).reset_index()
1847
1857
 
1848
- us_cash_index = self.get_prices("sofrindx index", period="60m", currency=currency)
1858
+ us_cash_index = self.get_prices("sofrindx index", period="60m", currency=currency, usdbrl_ticker=usdbrl_ticker)
1849
1859
  us_cash_index["Date"] = us_cash_index["Date"].dt.date
1850
1860
  us_cash_index = (us_cash_index[["Date", "Last_Price"]]
1851
1861
  .rename(columns={"Last_Price":"us_cash_index"})
1852
1862
  .set_index("Date").pct_change()
1853
1863
  .fillna(0)+1).reset_index()
1854
1864
 
1855
- us_margin_cost = self.get_prices("sofr + 75bps", period="60m", currency=currency)
1865
+ us_margin_cost = self.get_prices("sofr + 75bps", period="60m", currency=currency, usdbrl_ticker=usdbrl_ticker)
1856
1866
  us_margin_cost["Date"] = us_margin_cost["Date"].dt.date
1857
1867
  us_margin_cost = (us_margin_cost[["Date", "Last_Price"]]
1858
1868
  .rename(columns={"Last_Price":"us_margin_cost"})
@@ -1885,7 +1895,7 @@ class LuxorQuery:
1885
1895
 
1886
1896
  cash["Type"] = cash["Group"]
1887
1897
  cash["Name"] = cash["Group"].str.replace("_", " ").str.title()
1888
- cash["Asset_ID"] = cash["Type"]+"_"+cash["Type"]
1898
+ cash["Asset_ID"] = cash["Type"].str.replace("_"," ")+"_"+cash["Type"].str.replace("_"," ")
1889
1899
  cash["Price_Key"] = cash["Type"]
1890
1900
 
1891
1901
  cash["Delta_Shares"] = cash.groupby(["Group"])["Close_Quantity"].diff().fillna(0)
@@ -1948,7 +1958,7 @@ class LuxorQuery:
1948
1958
  def calculate_daily_pnl(self, fund, ref_date, currency, holiday_location="all", bdays=10,
1949
1959
  group_filters=[], type_filters=[], classification_filters=[], location_filters=[], asset_filters=[],
1950
1960
  currency_exposure_filters=[], include_cash=True, include_cash_debt=False, ticker_filters=[], annual_adm_fee=0,
1951
- ignore_small_pnl=True): #test_op_fix=False):
1961
+ ignore_small_pnl=True, usdbrl_ticker="bmfxclco curncy"): #test_op_fix=False):
1952
1962
  """ Calcula o PnL do dia de cada ativo no fundo.
1953
1963
  (Nao inclui o PnL das taxas!).
1954
1964
  Args:
@@ -1964,7 +1974,7 @@ class LuxorQuery:
1964
1974
  previous_date = self.get_bday_offset(ref_date, -bdays,
1965
1975
  location=holiday_location)
1966
1976
  df = self.get_positions_and_movements(fund, previous_date=previous_date,
1967
- recent_date=ref_date, currency=currency)
1977
+ recent_date=ref_date, currency=currency, usdbrl_ticker=usdbrl_ticker)
1968
1978
  assets = self.get_table("assets").rename(columns={"Key":"Asset_ID",
1969
1979
  "Currency Exposure":"Currency_Exposure"})
1970
1980
 
@@ -2008,7 +2018,7 @@ class LuxorQuery:
2008
2018
  #if test_op_fix:
2009
2019
 
2010
2020
  df_op_fix = df.query("Type.isin(@types_to_fix_open_price)").copy()
2011
- df_op_fix = self.__fix_open_price(df_op_fix, currency, ref_date, previous_date)
2021
+ df_op_fix = self.__fix_open_price(df_op_fix, currency, ref_date, previous_date, usdbrl_ticker=usdbrl_ticker)
2012
2022
 
2013
2023
  df = df.query("~Type.isin(@types_to_fix_open_price)").copy()
2014
2024
 
@@ -2021,7 +2031,8 @@ class LuxorQuery:
2021
2031
 
2022
2032
  # Podemos puxar o caixa aqui e concatenar para as proximas operacoes
2023
2033
  if include_cash:
2024
- cash = self.get_hist_cash_movements(fund, ref_date, currency=currency, bdays=bdays, holiday_location=holiday_location)
2034
+ cash = self.get_hist_cash_movements(fund, ref_date, currency=currency, bdays=bdays, holiday_location=holiday_location,
2035
+ usdbrl_ticker=usdbrl_ticker)
2025
2036
  cash["Today"] = pd.to_datetime(cash["Today"])
2026
2037
  cash = cash.query("Close_Mkt_Value >= 0").copy()
2027
2038
  cash["Luxor_Classification"] = 'fixed income'
@@ -2035,7 +2046,8 @@ class LuxorQuery:
2035
2046
 
2036
2047
  # Vamos segregar como dívida o caixa virado.
2037
2048
  if include_cash_debt:
2038
- cash_debt = self.get_hist_cash_movements(fund, ref_date, currency=currency, bdays=bdays, holiday_location=holiday_location)
2049
+ cash_debt = self.get_hist_cash_movements(fund, ref_date, currency=currency, bdays=bdays, holiday_location=holiday_location,
2050
+ usdbrl_ticker=usdbrl_ticker)
2039
2051
  cash_debt["Today"] = pd.to_datetime(cash_debt["Today"])
2040
2052
  cash_debt = cash_debt.query("Close_Mkt_Value < 0").copy()
2041
2053
  cash_debt["Luxor_Classification"] = 'debt'
@@ -2115,7 +2127,7 @@ class LuxorQuery:
2115
2127
  df["Cash_Flow"] = abs(df["Shares_Bought_Cost"]) + -abs(df["Amount_Sold"])
2116
2128
 
2117
2129
  hist_dividends = self.get_dividends(fund, ref_date, previous_date, currency=currency,
2118
- holiday_location=holiday_location)
2130
+ holiday_location=holiday_location, usdbrl_ticker=usdbrl_ticker)
2119
2131
  hist_dividends = pd.merge(assets[["Asset_ID", "Ticker"]],
2120
2132
  hist_dividends, on="Ticker",how="left")[["Date", "Asset_ID", "Amount"]]
2121
2133
  hist_dividends = hist_dividends.rename(columns={"Date": "Today", "Amount":"Dividends"})
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: luxorasap
3
- Version: 0.1.9
3
+ Version: 0.1.10
4
4
  Summary: Toolbox da Luxor para ingestão, análise e automação de dados financeiros.
5
5
  Author-email: Luxor Group <backoffice@luxor.com.br>
6
6
  License: Proprietary – All rights reserved
@@ -1,10 +1,10 @@
1
- luxorasap/__init__.py,sha256=gChf0kJo8keSBj-o1REIFsc97DXoE3_-ynR8tzb3Pk0,1355
1
+ luxorasap/__init__.py,sha256=40Cplh9skQUZbSyL9SL8_HCi5C2Lzadr2iCHssWhKow,1356
2
2
  luxorasap/btgapi/__init__.py,sha256=QUlfb5oiBY6K1Q5x4-a-x2wECe1At5wc2962I5odOJk,620
3
3
  luxorasap/btgapi/auth.py,sha256=PvyCtbEyBO2B1CIeAlNXWugKW1OgiKfPcVzS6K5FBnQ,1872
4
4
  luxorasap/btgapi/reports.py,sha256=ZVEMLoJPXc0r3XjPJPMsKQN0zZd1Npd7umNpAj1bncs,8040
5
5
  luxorasap/btgapi/trades.py,sha256=956HZ9BvN9C_VQvKTyBLN0x6ZygwVqBZN11F7OnNbDI,5985
6
6
  luxorasap/datareader/__init__.py,sha256=41RAvbrQ4R6oj67S32CrKqolx0CJ2W8cbOF6g5Cqm2g,120
7
- luxorasap/datareader/core.py,sha256=LpXe5g4lZpfEqaz_gjjHizVA-vPEjBi5yJKg_7K0Nkw,153205
7
+ luxorasap/datareader/core.py,sha256=TWcqokzMgahZx5mxBhrkJ05EWSsibZIww6hJz7unuFc,154641
8
8
  luxorasap/ingest/__init__.py,sha256=XhxDTN2ar-u6UCPhnxNU_to-nWiit-SpQ6cA_N9eMSs,795
9
9
  luxorasap/ingest/cloud/__init__.py,sha256=Hm-43YkjRhu3UiFVt1Zx7DmQuNJnK2GVWfCx1T3gKNc,2052
10
10
  luxorasap/ingest/legacy_local/dataloader.py,sha256=zKPhuiBSFwkuWN6d8g2s60KkbVk1R_1cGMCtQM9j-0c,11908
@@ -14,8 +14,8 @@ luxorasap/utils/dataframe/reader.py,sha256=Vzjdw-AeS1lnWEHQ8RZNh0kK93NWTp0NWVi_B
14
14
  luxorasap/utils/dataframe/transforms.py,sha256=Bm_cv9L9923QIXH82Fa_M4pM94f2AJRPu62Vv_i7tto,1684
15
15
  luxorasap/utils/storage/__init__.py,sha256=U3XRq94yzRp3kgBSUcRzs2tQgJ4o8h8a1ZzwiscA5XM,67
16
16
  luxorasap/utils/storage/blob.py,sha256=pcEixGxwXM9y5iPPpkX__ySWq0milghJGketYZlRL-0,3171
17
- luxorasap-0.1.9.dist-info/METADATA,sha256=_RAaTxzxjeqxi3RzXnaK526ih1HAkuv5W-VnUave5Kk,3803
18
- luxorasap-0.1.9.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
19
- luxorasap-0.1.9.dist-info/entry_points.txt,sha256=XFh-dOwUhlya9DmGvgookMI0ezyUJjcOvTIHDEYS44g,52
20
- luxorasap-0.1.9.dist-info/top_level.txt,sha256=9YOL6bUIpzY06XFBRkUW1e4rgB32Ds91fQPGwUEjxzU,10
21
- luxorasap-0.1.9.dist-info/RECORD,,
17
+ luxorasap-0.1.10.dist-info/METADATA,sha256=Ey_ftFQQB3iRQmgesvVZ5qF0w8OTy0m0cyMKOj16krM,3804
18
+ luxorasap-0.1.10.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
19
+ luxorasap-0.1.10.dist-info/entry_points.txt,sha256=XFh-dOwUhlya9DmGvgookMI0ezyUJjcOvTIHDEYS44g,52
20
+ luxorasap-0.1.10.dist-info/top_level.txt,sha256=9YOL6bUIpzY06XFBRkUW1e4rgB32Ds91fQPGwUEjxzU,10
21
+ luxorasap-0.1.10.dist-info/RECORD,,