luxorasap 0.1.25__tar.gz → 0.1.27__tar.gz
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-0.1.25 → luxorasap-0.1.27}/PKG-INFO +1 -1
- {luxorasap-0.1.25 → luxorasap-0.1.27}/pyproject.toml +2 -2
- {luxorasap-0.1.25 → luxorasap-0.1.27}/src/luxorasap/__init__.py +1 -1
- {luxorasap-0.1.25 → luxorasap-0.1.27}/src/luxorasap/datareader/core.py +19 -18
- {luxorasap-0.1.25 → luxorasap-0.1.27}/src/luxorasap.egg-info/PKG-INFO +1 -1
- {luxorasap-0.1.25 → luxorasap-0.1.27}/README.md +0 -0
- {luxorasap-0.1.25 → luxorasap-0.1.27}/setup.cfg +0 -0
- {luxorasap-0.1.25 → luxorasap-0.1.27}/src/luxorasap/btgapi/__init__.py +0 -0
- {luxorasap-0.1.25 → luxorasap-0.1.27}/src/luxorasap/btgapi/auth.py +0 -0
- {luxorasap-0.1.25 → luxorasap-0.1.27}/src/luxorasap/btgapi/reports.py +0 -0
- {luxorasap-0.1.25 → luxorasap-0.1.27}/src/luxorasap/btgapi/trades.py +0 -0
- {luxorasap-0.1.25 → luxorasap-0.1.27}/src/luxorasap/datareader/__init__.py +0 -0
- {luxorasap-0.1.25 → luxorasap-0.1.27}/src/luxorasap/ingest/__init__.py +0 -0
- {luxorasap-0.1.25 → luxorasap-0.1.27}/src/luxorasap/ingest/cloud/__init__.py +0 -0
- {luxorasap-0.1.25 → luxorasap-0.1.27}/src/luxorasap/ingest/legacy_local/dataloader.py +0 -0
- {luxorasap-0.1.25 → luxorasap-0.1.27}/src/luxorasap/utils/__init__.py +0 -0
- {luxorasap-0.1.25 → luxorasap-0.1.27}/src/luxorasap/utils/dataframe/__init__.py +0 -0
- {luxorasap-0.1.25 → luxorasap-0.1.27}/src/luxorasap/utils/dataframe/reader.py +0 -0
- {luxorasap-0.1.25 → luxorasap-0.1.27}/src/luxorasap/utils/dataframe/transforms.py +0 -0
- {luxorasap-0.1.25 → luxorasap-0.1.27}/src/luxorasap/utils/storage/__init__.py +0 -0
- {luxorasap-0.1.25 → luxorasap-0.1.27}/src/luxorasap/utils/storage/blob.py +0 -0
- {luxorasap-0.1.25 → luxorasap-0.1.27}/src/luxorasap.egg-info/SOURCES.txt +0 -0
- {luxorasap-0.1.25 → luxorasap-0.1.27}/src/luxorasap.egg-info/dependency_links.txt +0 -0
- {luxorasap-0.1.25 → luxorasap-0.1.27}/src/luxorasap.egg-info/entry_points.txt +0 -0
- {luxorasap-0.1.25 → luxorasap-0.1.27}/src/luxorasap.egg-info/requires.txt +0 -0
- {luxorasap-0.1.25 → luxorasap-0.1.27}/src/luxorasap.egg-info/top_level.txt +0 -0
- {luxorasap-0.1.25 → luxorasap-0.1.27}/tests/test_btgapi_auth.py +0 -0
- {luxorasap-0.1.25 → luxorasap-0.1.27}/tests/test_btgapi_reports.py +0 -0
- {luxorasap-0.1.25 → luxorasap-0.1.27}/tests/test_btgapi_trades.py +0 -0
- {luxorasap-0.1.25 → luxorasap-0.1.27}/tests/test_datareader.py +0 -0
- {luxorasap-0.1.25 → luxorasap-0.1.27}/tests/test_ingest_cloud.py +0 -0
- {luxorasap-0.1.25 → luxorasap-0.1.27}/tests/test_ingest_legacy_local.py +0 -0
- {luxorasap-0.1.25 → luxorasap-0.1.27}/tests/test_utils_dataframe.py +0 -0
- {luxorasap-0.1.25 → luxorasap-0.1.27}/tests/test_utils_storage.py +0 -0
|
@@ -10,7 +10,7 @@ build-backend = "setuptools.build_meta"
|
|
|
10
10
|
#############################
|
|
11
11
|
[project]
|
|
12
12
|
name = "luxorasap"
|
|
13
|
-
version = "0.1.
|
|
13
|
+
version = "0.1.27"
|
|
14
14
|
description = "Toolbox da Luxor para ingestão, análise e automação de dados financeiros."
|
|
15
15
|
readme = "README.md"
|
|
16
16
|
requires-python = ">=3.9"
|
|
@@ -78,7 +78,7 @@ exclude = ["tests*"]
|
|
|
78
78
|
# bumpver (sem-ver)
|
|
79
79
|
#############################
|
|
80
80
|
[tool.bumpver]
|
|
81
|
-
current_version = "0.1.
|
|
81
|
+
current_version = "0.1.27"
|
|
82
82
|
version_pattern = "MAJOR.MINOR.PATCH"
|
|
83
83
|
|
|
84
84
|
# regex explícito – obrigatório no bumpver 2024+
|
|
@@ -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.
|
|
16
|
+
__version__ = "0.1.27"
|
|
17
17
|
|
|
18
18
|
# ─── Lazy loader ─────────────────────────────────────────────────
|
|
19
19
|
def __getattr__(name: str) -> ModuleType:
|
|
@@ -289,8 +289,8 @@ class LuxorQuery:
|
|
|
289
289
|
"Price" : "Last_Price"
|
|
290
290
|
})[["Date","Asset","Last_Price"]]
|
|
291
291
|
)
|
|
292
|
+
|
|
292
293
|
if table_key == 'hist_vc_px_last':
|
|
293
|
-
|
|
294
294
|
last_prices = table.groupby("Asset")["Last_Price"].last()
|
|
295
295
|
last_date_df = pd.DataFrame({"Date": [dt.datetime.now()] * len(last_prices)})
|
|
296
296
|
last_date_df["Asset"] = last_prices.index
|
|
@@ -299,8 +299,8 @@ class LuxorQuery:
|
|
|
299
299
|
table = (pd.concat([table, last_date_df]).sort_values(by="Date")
|
|
300
300
|
.set_index("Date").groupby("Asset")
|
|
301
301
|
.apply(lambda g: g[~g.index.duplicated(keep="first")].resample("D").ffill(),
|
|
302
|
-
include_groups=False).reset_index(
|
|
303
|
-
|
|
302
|
+
include_groups=False).reset_index()
|
|
303
|
+
)
|
|
304
304
|
|
|
305
305
|
self.price_tables_loaded[table_key] = table
|
|
306
306
|
|
|
@@ -637,7 +637,6 @@ class LuxorQuery:
|
|
|
637
637
|
tickers = [t.lower() for t in tickers] # padronizando tickers para lowercase
|
|
638
638
|
|
|
639
639
|
prices = self.hist_prices_table.copy()
|
|
640
|
-
|
|
641
640
|
|
|
642
641
|
surrogate_previous_date = previous_date - dt.timedelta(days=30)
|
|
643
642
|
surrogate_recent_date = recent_date + dt.timedelta(days=30)
|
|
@@ -658,7 +657,7 @@ class LuxorQuery:
|
|
|
658
657
|
|
|
659
658
|
if get_intraday_prices:
|
|
660
659
|
prices = self.__hist_prices_intraday_extensor(prices)
|
|
661
|
-
|
|
660
|
+
|
|
662
661
|
if currency != "local":
|
|
663
662
|
|
|
664
663
|
# TODO: Resolver problema de consistencia com ticker e ticker_bbg
|
|
@@ -667,25 +666,29 @@ class LuxorQuery:
|
|
|
667
666
|
|
|
668
667
|
ticker_map = assets.query("~Ticker_BBG.isna() and Ticker_BBG != Ticker")[["Ticker", "Ticker_BBG"]].set_index("Ticker").to_dict("index")
|
|
669
668
|
assets["Ticker"] = assets["Ticker"].apply(lambda x: ticker_map[x]["Ticker_BBG"] if x in ticker_map.keys() else x)
|
|
670
|
-
|
|
671
|
-
prices = pd.merge(
|
|
669
|
+
ticker_to_location = assets[["Ticker", "Location"]].drop_duplicates()
|
|
670
|
+
prices = pd.merge(prices, ticker_to_location, left_on="Asset", right_on="Ticker", how='left')[["Date", "Asset", "Last_Price", "Location"]]
|
|
671
|
+
|
|
672
672
|
currency_map = {"bz":"brl","br":"brl", "us":"usd", "cn":"cad", "eur":"eur"}
|
|
673
673
|
prices["Location"] = prices["Location"].apply(lambda x: currency_map.get(x, 'not found'))
|
|
674
674
|
|
|
675
675
|
prices_by_location = []
|
|
676
676
|
iter_prices = prices.groupby("Location")
|
|
677
|
-
|
|
677
|
+
|
|
678
678
|
for p in iter_prices:
|
|
679
|
+
|
|
679
680
|
if p[0] == 'not found':
|
|
680
681
|
assets_not_found = list(p[1]["Asset"].unique())
|
|
681
682
|
logger.warning(f"currency_map nao suporta Location dos ativos {assets_not_found}.")
|
|
682
683
|
continue
|
|
683
684
|
price_currency = p[0]
|
|
685
|
+
|
|
684
686
|
converted_prices = self.convert_currency(p[1][list(set(p[1].columns) - {"Location"})],
|
|
685
687
|
price_currency=price_currency, dest_currency=currency,
|
|
686
688
|
usdbrl_ticker=usdbrl_ticker, force_continuous_date_range=force_continuous_date_range,
|
|
687
689
|
holiday_location=holiday_location, get_intraday_prices=get_intraday_prices,
|
|
688
690
|
force_month_end=force_month_end)
|
|
691
|
+
|
|
689
692
|
if not converted_prices.empty:
|
|
690
693
|
prices_by_location.append(converted_prices)
|
|
691
694
|
|
|
@@ -697,7 +700,7 @@ class LuxorQuery:
|
|
|
697
700
|
|
|
698
701
|
# Finalmente, vamos seguir filtrando pelo periodo desejado.
|
|
699
702
|
prices = prices.query("Date <= @recent_date and Date >= @previous_date and Asset.isin(@tickers)")
|
|
700
|
-
|
|
703
|
+
|
|
701
704
|
#if adjust_bmfxlcoc and ('bmfxclco curncy' in tickers) and (recent_date == dt.date.today()):
|
|
702
705
|
# max_date = prices.query("Asset == 'bmfxclco curncy'")["Date"].max()
|
|
703
706
|
# if max_date < dt.date.today(): # vamos colocar mais um dia usando usdbrl curncy
|
|
@@ -1558,6 +1561,7 @@ class LuxorQuery:
|
|
|
1558
1561
|
period=period, holiday_location=holiday_location,
|
|
1559
1562
|
currency=currency, agregate_by_name=False, usdbrl_ticker=usdbrl_ticker
|
|
1560
1563
|
)
|
|
1564
|
+
|
|
1561
1565
|
# Vamos obter os precos de fechamento em cada dia
|
|
1562
1566
|
# Preenchendo primeiro todo o historico
|
|
1563
1567
|
prices_previous_date = (df["Date"].min() - dt.timedelta(days=100)).date()
|
|
@@ -1566,8 +1570,9 @@ class LuxorQuery:
|
|
|
1566
1570
|
tickers=price_keys, previous_date=prices_previous_date, currency=currency,
|
|
1567
1571
|
get_intraday_prices=True, usdbrl_ticker=usdbrl_ticker
|
|
1568
1572
|
).rename(columns={"Asset":"Price_Key"})
|
|
1569
|
-
|
|
1570
|
-
df = df.merge(prices, on=["Date", "Price_Key"], how="left")
|
|
1573
|
+
|
|
1574
|
+
#df = df.merge(prices, on=["Date", "Price_Key"], how="left")
|
|
1575
|
+
df = df.merge(prices, on=["Date", "Price_Key"]) #, how="left")
|
|
1571
1576
|
# Finalmente, vamos atualizar com o preco mais recente do ativo na data de hoje
|
|
1572
1577
|
#df_prev = df.query("Date < @dt.date.today()").copy()
|
|
1573
1578
|
#df_today = df.query("Date == @dt.date.today()").copy()
|
|
@@ -1591,7 +1596,7 @@ class LuxorQuery:
|
|
|
1591
1596
|
|
|
1592
1597
|
# preenchendo Last_Price nulos com o do dia anterior para os mesmos asset_id
|
|
1593
1598
|
df["Last_Price"] = df.groupby("Asset_ID")["Last_Price"].ffill()
|
|
1594
|
-
|
|
1599
|
+
|
|
1595
1600
|
return df
|
|
1596
1601
|
|
|
1597
1602
|
|
|
@@ -1764,7 +1769,7 @@ class LuxorQuery:
|
|
|
1764
1769
|
usdbrl_ticker=usdbrl_ticker).rename(columns={"Asset":"Price_Key"})
|
|
1765
1770
|
|
|
1766
1771
|
positions_and_movements = positions_and_movements.merge(prices[["Date", "Price_Key", "Last_Price"]], on=["Date","Price_Key"])
|
|
1767
|
-
|
|
1772
|
+
|
|
1768
1773
|
positions_and_movements["Period"] = period
|
|
1769
1774
|
positions_and_movements["Currency"] = currency
|
|
1770
1775
|
# Consideramos como ativos atuais aqueles que possuem posicao aberta ou que foram encerradas no dia
|
|
@@ -1798,7 +1803,7 @@ class LuxorQuery:
|
|
|
1798
1803
|
positions_and_movements = positions_and_movements.merge(spx_prices, on="Date", how="left")
|
|
1799
1804
|
|
|
1800
1805
|
#positions_and_movements["spx_index"] = (positions_and_movements["spx_index"].pct_change().fillna(0)+1).cumprod()-1
|
|
1801
|
-
|
|
1806
|
+
|
|
1802
1807
|
return positions_and_movements.rename(columns={"Price_Key":"Ticker"})
|
|
1803
1808
|
|
|
1804
1809
|
|
|
@@ -2038,8 +2043,6 @@ class LuxorQuery:
|
|
|
2038
2043
|
# Juntando dfs novamente
|
|
2039
2044
|
df = pd.concat([df, df_op_fix])
|
|
2040
2045
|
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
2046
|
# Precisamos consertar o open_price do FX. (Deve ser convertido pelo spot de fechamento sempre)
|
|
2044
2047
|
|
|
2045
2048
|
# Podemos puxar o caixa aqui e concatenar para as proximas operacoes
|
|
@@ -2192,7 +2195,6 @@ class LuxorQuery:
|
|
|
2192
2195
|
|
|
2193
2196
|
df = pd.concat([df, df_fees])
|
|
2194
2197
|
|
|
2195
|
-
|
|
2196
2198
|
df["Daily_Pnl"] = df["Pnl_Unchanged"] + df["Pnl_Bought"] + df["Pnl_Sold"] + df["Dividends"]
|
|
2197
2199
|
|
|
2198
2200
|
# Calculando PL Inicial Ajustado
|
|
@@ -2208,7 +2210,6 @@ class LuxorQuery:
|
|
|
2208
2210
|
|
|
2209
2211
|
df["Daily_Attribution"] = np.where(df["Open_AUM_Adjusted"] == 0,0, df["Daily_Pnl"] / df["Open_AUM_Adjusted"])
|
|
2210
2212
|
df["Daily_Return"] = df.reset_index().groupby("Today")["Daily_Attribution"].sum()
|
|
2211
|
-
|
|
2212
2213
|
|
|
2213
2214
|
# ao retornar, filtrar port Daily_Pnl != 0 e not Daily_Pnl.isna()
|
|
2214
2215
|
if ignore_small_pnl:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|