From 203431f732e5b31276ef9ad88f232f210ceb45db Mon Sep 17 00:00:00 2001 From: fredmaloggia Date: Wed, 26 Nov 2025 16:02:45 +0100 Subject: [PATCH] Initial commit --- API UBS NEO.py | 130 ++++++++++++++++++++++++++++++++++++ Token.txt | 1 + Valuation_DE000UP32UU0.xlsx | Bin 0 -> 7544 bytes 3 files changed, 131 insertions(+) create mode 100644 API UBS NEO.py create mode 100644 Token.txt create mode 100644 Valuation_DE000UP32UU0.xlsx diff --git a/API UBS NEO.py b/API UBS NEO.py new file mode 100644 index 0000000..968c45f --- /dev/null +++ b/API UBS NEO.py @@ -0,0 +1,130 @@ +# -*- coding: utf-8 -*- +""" +Created on Wed Oct 22 15:15:02 2025 + +@author: Federico +""" + +import os +from datetime import date, timedelta + +import pandas as pd +import requests + +# === Lettura token da file === +with open("token.txt", "r") as f: + token = f.read().strip() + +# === Parametri === +isin = "DE000UP32UU0" +url = f"https://neo.ubs.com/api/ged-amc/external/report/v1/valuation/{isin}" +headers = {"Authorization": f"Bearer {token}"} + +# === Intervallo management fee === +management_from = date(2025, 11, 1) +management_to = date.today() - timedelta(days=1) +management_url = ( + "https://neo.ubs.com/api/ged-amc/external/fee/v1/management/" + f"{isin}?fromDate={management_from:%Y-%m-%d}&toDate={management_to:%Y-%m-%d}" +) +performance_url = ( + "https://neo.ubs.com/api/ged-amc/external/fee/v1/performance/" + f"{isin}?fromDate={management_from:%Y-%m-%d}&toDate={management_to:%Y-%m-%d}" +) + + +# Helper per trasformare il payload JSON in DataFrame pronti per Excel +def build_tables_from_payload(payload, base_name="MANAGEMENT_FEE"): + tables = {} + + def normalize(obj): + return pd.json_normalize(obj, sep=".") + + if isinstance(payload, list): + tables[base_name] = normalize(payload) + return tables + + if isinstance(payload, dict): + if "content" in payload and isinstance(payload["content"], list): + tables[base_name] = normalize(payload["content"]) + + for key, val in payload.items(): + if key == "content": + continue + if isinstance(val, list): + sheet_name = f"{base_name}_{key}".upper()[:31] + tables[sheet_name] = normalize(val) + + if not tables: + tables[base_name] = normalize(payload) + + return tables + + +# === Richiesta API valuation === +response = requests.get(url, headers=headers) +print("Status code:", response.status_code) + +if response.status_code == 200: + data = response.json() + + # === Info generali del certificato === + amc_info = data.get("amc", {}) + print("\n--- INFO CERTIFICATO ---") + print("ISIN:", amc_info.get("isin")) + print("Descrizione:", amc_info.get("description")) + print("AUM:", amc_info.get("aum")) + + # === Estraggo le varie asset class === + constituents = data.get("constituents", {}) + dfs = {k: pd.DataFrame(v) for k, v in constituents.items()} + + # === Richiesta management fee === + management_response = requests.get(management_url, headers=headers) + print("Management fee status code:", management_response.status_code) + management_tables = {} + + if management_response.status_code == 200: + management_payload = management_response.json() + management_tables = build_tables_from_payload(management_payload) + else: + print("Errore nella richiesta management fee:", management_response.status_code) + print(management_response.text) + + # === Richiesta performance fee === + performance_response = requests.get(performance_url, headers=headers) + print("Performance fee status code:", performance_response.status_code) + performance_tables = {} + + if performance_response.status_code == 200: + performance_payload = performance_response.json() + performance_tables = build_tables_from_payload(performance_payload, base_name="PERFORMANCE_FEE") + else: + print("Errore nella richiesta performance fee:", performance_response.status_code) + print(performance_response.text) + + # === Salvataggio in Excel === + output_file = f"Valuation_{isin}.xlsx" + with pd.ExcelWriter(output_file, engine="openpyxl") as writer: + # Salva anche info generali in un foglio + pd.DataFrame([amc_info]).to_excel(writer, sheet_name="AMC_INFO", index=False) + for name, df in dfs.items(): + if not df.empty: + df.to_excel(writer, sheet_name=name[:31], index=False) + for name, df in management_tables.items(): + if not df.empty: + df.to_excel(writer, sheet_name=name[:31], index=False) + for name, df in performance_tables.items(): + if not df.empty: + df.to_excel(writer, sheet_name=name[:31], index=False) + + print(f"\nFile salvato con successo: {os.path.abspath(output_file)}") + + # Esempio: mostra i primi record di EQUITY + if "EQUITY" in dfs and not dfs["EQUITY"].empty: + print("\n--- EQUITY ---") + print(dfs["EQUITY"].head()) + +else: + print("Errore nella richiesta:", response.status_code) + print(response.text) diff --git a/Token.txt b/Token.txt new file mode 100644 index 0000000..8bf4c1e --- /dev/null +++ b/Token.txt @@ -0,0 +1 @@ +eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJhdWQiOiIvZ2VkLWFtYy9leHRlcm5hbCIsInN1YiI6IlRDQ2JmZjU4MGYyZDE1MDQ2MDZiYzIwZTRkZDUzZWViYjY4IiwiaXNzIjoiTmVvIFBsYXRmb3JtIEpXVCBBdXRob3JpemF0aW9uIFNlcnZpY2UiLCJleHAiOjE3NjkwNDAwMDAsImlhdCI6MTc2MTEzNDU0NCwianRpIjoiMzYwN2NhNGItZjQzMi00NzI1LTliMDEtMDFkMzk3NmEzOTM1In0.l7XVhPvKvEeu7wM7EQTyiDKmQ9YcmgEzmtN0rW9d0G9waB8AE3hjOPq8xgWAdDkqcyEWuwqPEZoPEzx4mT6P4E8pXLZkTvfq7VzY3UZ_CdawHL7LmtwoXGeCpORHJe4m_6yDuxcr8FdOQsApVZDL_Dhq3uRCcIPe-zUcY440ZdND5oyGJQIELvomsIbNW7pgCW2P_MTW0ELWTKH4RWQkvc1DNC4XIlY8EJCWLU8Icn_iGav4J7mO2h8yLZTOIDywOd6s27GQMUAn4E46n9rVRVGrPwKbV1KjgI8Z3SsK8vMHorotZAaruaOT3lV3P5zrxwOpafJMrDFsXOGgd97VfA \ No newline at end of file diff --git a/Valuation_DE000UP32UU0.xlsx b/Valuation_DE000UP32UU0.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..550524cc000bb14a62fb085b3ec6783a199f5577 GIT binary patch literal 7544 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 literal 0 HcmV?d00001