Project_Carmignac/data_exploration/aum_analysis.ipynb

752 lines
495 KiB
Plaintext
Raw Normal View History

2026-02-22 15:02:41 +01:00
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# AUM Analysis\n",
"\n",
"This notebook sums the **Value - AUM €** by **Product - Asset Type** and by **Product - Fund** from the AUM sample data."
]
},
{
"cell_type": "code",
"execution_count": 11,
2026-02-22 15:02:41 +01:00
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Requirement already satisfied: openpyxl in /opt/python/lib/python3.13/site-packages (3.1.5)\n",
"Requirement already satisfied: et-xmlfile in /opt/python/lib/python3.13/site-packages (from openpyxl) (2.0.0)\n"
2026-02-22 15:02:41 +01:00
]
}
],
"source": [
"import pandas as pd\n",
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"!pip install openpyxl\n",
"import os\n",
"import s3fs\n",
"import seaborn as sns\n",
"import plotly.express as px\n",
"import re"
2026-02-22 15:02:41 +01:00
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"fs = s3fs.S3FileSystem(\n",
" client_kwargs={'endpoint_url': 'https://'+'minio-simple.lab.groupe-genes.fr'},\n",
" key = os.environ[\"AWS_ACCESS_KEY_ID\"], \n",
" secret = os.environ[\"AWS_SECRET_ACCESS_KEY\"], \n",
" token = os.environ[\"AWS_SESSION_TOKEN\"])"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"/tmp/ipykernel_4263/3768862044.py:5: DtypeWarning: Columns (0,1,2,3) have mixed types. Specify dtype option on import or set low_memory=False.\n",
2026-02-22 15:02:41 +01:00
" stocks = pd.read_csv(f, sep=\";\")\n"
]
}
],
"source": [
"#with fs.open('projet-bdc-data//carmignac/Flows ENSAE V2 -20251105.csv', 'rb') as f:\n",
" #flows = pd.read_csv(f, sep=\";\")\n",
"\n",
"with fs.open('projet-bdc-data//carmignac/AUM ENSAE V2 -20251105.csv', 'rb') as f:\n",
" stocks = pd.read_csv(f, sep=\";\")\n",
"\n",
"#with fs.open('projet-bdc-data/carmignac/Monthly AUM and NAV since 2010.xlsx', 'rb') as f:#\n",
" #nav_raw = pd.read_excel(f, header=None, engine=\"openpyxl\")\n",
"\n",
"#nav = nav_raw[0].str.split(\",\", expand=True)\n",
"#nav.columns = nav.iloc[0]\n",
"#nav = nav[1:].reset_index(drop=True)"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Date conversion done.\n"
]
}
],
"source": [
"stocks[\"Centralisation Date\"] = pd.to_datetime(stocks[\"Centralisation Date\"], errors=\"coerce\")\n",
"#flows[\"Centralisation Date\"] = pd.to_datetime(flows[\"Centralisation Date\"], errors=\"coerce\")\n",
"#nav[\"NavDate\"] = pd.to_datetime(nav[\"NavDate\"], format=\"%d/%m/%Y\", errors=\"coerce\")\n",
"\n",
"print(\"Date conversion done.\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Sum of AUM by Product - Asset Type"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"AUM (€) by Product - Asset Type:\n",
"Product - Asset Type\n",
"Diversified 2.249487e+12\n",
"Fixed Income 1.901982e+12\n",
"Equity 9.811712e+11\n",
"Alternative 1.208047e+11\n",
"NaN 1.786480e+10\n",
"Private Assets 2.205183e+09\n"
]
},
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>Product - Asset Type</th>\n",
" <th>Total AUM (€)</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>Diversified</td>\n",
" <td>2.249487e+12</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>Fixed Income</td>\n",
" <td>1.901982e+12</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>Equity</td>\n",
" <td>9.811712e+11</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>Alternative</td>\n",
" <td>1.208047e+11</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>NaN</td>\n",
" <td>1.786480e+10</td>\n",
" </tr>\n",
" <tr>\n",
" <th>5</th>\n",
" <td>Private Assets</td>\n",
" <td>2.205183e+09</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" Product - Asset Type Total AUM (€)\n",
"0 Diversified 2.249487e+12\n",
"1 Fixed Income 1.901982e+12\n",
"2 Equity 9.811712e+11\n",
"3 Alternative 1.208047e+11\n",
"4 NaN 1.786480e+10\n",
"5 Private Assets 2.205183e+09"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Sum Value - AUM € per Product - Asset Type\n",
"aum_by_asset_type = stocks.groupby('Product - Asset Type', dropna=False)['Value - AUM €'].sum().sort_values(ascending=False)\n",
"\n",
"print(\"AUM (€) by Product - Asset Type:\")\n",
"print(aum_by_asset_type.to_string())\n",
"\n",
"# Display as DataFrame for nicer formatting\n",
"aum_by_asset_type_df = aum_by_asset_type.reset_index()\n",
"aum_by_asset_type_df.columns = ['Product - Asset Type', 'Total AUM (€)']\n",
"aum_by_asset_type_df"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 1000x500 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"fig, ax = plt.subplots(figsize=(10, 5))\n",
"aum_by_asset_type.plot(kind='bar', ax=ax, color='steelblue', edgecolor='navy', alpha=0.8)\n",
"ax.set_title('AUM Distribution by Product - Asset Type')\n",
"ax.set_xlabel('Product - Asset Type')\n",
"ax.set_ylabel('Total AUM (€)')\n",
"ax.tick_params(axis='x', rotation=45)\n",
"plt.tight_layout()\n",
"plt.show()"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 1000x600 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"# For each asset type: AUM per account (sum across funds/dates)\n",
"aum_per_account = stocks.groupby(['Product - Asset Type', 'Registrar Account - ID'], dropna=False)['Value - AUM €'].sum().reset_index()\n",
"\n",
"# Build cumulative concentration curves per asset type\n",
"fig, ax = plt.subplots(figsize=(10, 6))\n",
"\n",
"for asset_type in aum_per_account['Product - Asset Type'].unique():\n",
" subset = aum_per_account[aum_per_account['Product - Asset Type'] == asset_type].copy()\n",
" subset = subset.sort_values('Value - AUM €', ascending=False).reset_index(drop=True)\n",
" \n",
" total_aum = subset['Value - AUM €'].sum()\n",
" if total_aum == 0:\n",
" continue\n",
" \n",
" subset['cumsum_aum'] = subset['Value - AUM €'].cumsum()\n",
" subset['cumsum_pct'] = 100 * subset['cumsum_aum'] / total_aum\n",
" subset['n_accounts'] = range(1, len(subset) + 1)\n",
" \n",
" ax.plot(subset['n_accounts'], subset['cumsum_pct'], label=asset_type if pd.notna(asset_type) else '(empty)', linewidth=2)\n",
"\n",
"ax.axhline(y=90, color='gray', linestyle='--', alpha=0.5, label='90% threshold')\n",
"ax.set_xlabel('Number of accounts (sorted by AUM, largest first)')\n",
"ax.set_ylabel('Cumulative % of total AUM')\n",
"ax.set_title('Account concentration: how many accounts hold X% of each asset type?')\n",
"ax.legend(loc='lower right')\n",
"ax.grid(True, alpha=0.3)\n",
"plt.tight_layout()\n",
"plt.show()"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>Product - Asset Type</th>\n",
" <th>50% of AUM</th>\n",
" <th>75% of AUM</th>\n",
" <th>90% of AUM</th>\n",
" <th>95% of AUM</th>\n",
" <th>99% of AUM</th>\n",
" <th>Total accounts</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>Alternative</td>\n",
" <td>19</td>\n",
" <td>80</td>\n",
" <td>193</td>\n",
" <td>309</td>\n",
" <td>667</td>\n",
" <td>2679</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>Diversified</td>\n",
" <td>36</td>\n",
" <td>113</td>\n",
" <td>289</td>\n",
" <td>480</td>\n",
" <td>1100</td>\n",
" <td>8846</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>Equity</td>\n",
" <td>35</td>\n",
" <td>125</td>\n",
" <td>331</td>\n",
" <td>556</td>\n",
" <td>1378</td>\n",
" <td>9123</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>Fixed Income</td>\n",
" <td>33</td>\n",
" <td>114</td>\n",
" <td>307</td>\n",
" <td>514</td>\n",
" <td>1132</td>\n",
" <td>7348</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>Private Assets</td>\n",
" <td>1</td>\n",
" <td>1</td>\n",
" <td>1</td>\n",
" <td>1</td>\n",
" <td>3</td>\n",
" <td>18</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" Product - Asset Type 50% of AUM 75% of AUM 90% of AUM 95% of AUM \\\n",
"0 Alternative 19 80 193 309 \n",
"1 Diversified 36 113 289 480 \n",
"2 Equity 35 125 331 556 \n",
"3 Fixed Income 33 114 307 514 \n",
"4 Private Assets 1 1 1 1 \n",
"\n",
" 99% of AUM Total accounts \n",
"0 667 2679 \n",
"1 1100 8846 \n",
"2 1378 9123 \n",
"3 1132 7348 \n",
"4 3 18 "
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Summary: number of accounts holding X% of each asset type\n",
"thresholds = [50, 75, 90, 95, 99]\n",
"results = []\n",
"\n",
"for asset_type in aum_per_account['Product - Asset Type'].unique():\n",
" subset = aum_per_account[aum_per_account['Product - Asset Type'] == asset_type].copy()\n",
" subset = subset.sort_values('Value - AUM €', ascending=False).reset_index(drop=True)\n",
" total_aum = subset['Value - AUM €'].sum()\n",
" if total_aum == 0:\n",
" continue\n",
" \n",
" cumsum_pct = 100 * subset['Value - AUM €'].cumsum() / total_aum\n",
" \n",
" row = {'Product - Asset Type': asset_type if pd.notna(asset_type) else '(empty)'}\n",
" for pct in thresholds:\n",
" n_accounts = (cumsum_pct >= pct).idxmax() + 1 if (cumsum_pct >= pct).any() else len(subset)\n",
" row[f'{pct}% of AUM'] = n_accounts\n",
" row['Total accounts'] = len(subset)\n",
" results.append(row)\n",
"\n",
"pd.DataFrame(results)"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Alternative: 309 accounts (95% AUM) → 50947 rows → aum_95pct_by_asset_type/aum_alternative_95pct.csv\n",
"Diversified: 480 accounts (95% AUM) → 354694 rows → aum_95pct_by_asset_type/aum_diversified_95pct.csv\n",
"Equity: 556 accounts (95% AUM) → 431011 rows → aum_95pct_by_asset_type/aum_equity_95pct.csv\n",
"Fixed Income: 514 accounts (95% AUM) → 345213 rows → aum_95pct_by_asset_type/aum_fixed_income_95pct.csv\n",
"Private Assets: 1 accounts (95% AUM) → 88 rows → aum_95pct_by_asset_type/aum_private_assets_95pct.csv\n",
"nan: 4 accounts (95% AUM) → 3076 rows → aum_95pct_by_asset_type/aum_empty_95pct.csv\n",
"\n",
"Done. Files saved in 'aum_95pct_by_asset_type/'\n"
]
}
],
"source": [
"OUTPUT_DIR = 'aum_95pct_by_asset_type'\n",
"os.makedirs(OUTPUT_DIR, exist_ok=True)\n",
"\n",
"def safe_filename(asset_type):\n",
" \"\"\"Convert asset type to a safe filename.\"\"\"\n",
" if pd.isna(asset_type) or str(asset_type).strip() == '':\n",
" return 'empty'\n",
" return re.sub(r'[^\\w\\-]', '_', str(asset_type).strip().lower().replace(' ', '_'))\n",
"\n",
"# For each asset type: get accounts holding 95% of AUM\n",
"for asset_type in aum_per_account['Product - Asset Type'].unique():\n",
" if pd.isna(asset_type):\n",
" subset = aum_per_account[aum_per_account['Product - Asset Type'].isna()].copy()\n",
" else:\n",
" subset = aum_per_account[aum_per_account['Product - Asset Type'] == asset_type].copy()\n",
" subset = subset.sort_values('Value - AUM €', ascending=False).reset_index(drop=True)\n",
" total_aum = subset['Value - AUM €'].sum()\n",
" \n",
" if total_aum == 0:\n",
" n_accounts_95 = 0\n",
" accounts_95 = set()\n",
" else:\n",
" cumsum_pct = 100 * subset['Value - AUM €'].cumsum() / total_aum\n",
" n_accounts_95 = (cumsum_pct >= 95).idxmax() + 1 if (cumsum_pct >= 95).any() else len(subset)\n",
" accounts_95 = set(subset.head(n_accounts_95)['Registrar Account - ID'])\n",
" \n",
" # Extract all rows from original df for these accounts AND this asset type\n",
" if pd.isna(asset_type):\n",
" type_mask = stocks['Product - Asset Type'].isna()\n",
" else:\n",
" type_mask = stocks['Product - Asset Type'] == asset_type\n",
" mask = type_mask & (stocks['Registrar Account - ID'].isin(accounts_95))\n",
" df_subset = stocks.loc[mask]\n",
" \n",
" filename = f\"aum_{safe_filename(asset_type)}_95pct.csv\"\n",
" filepath = os.path.join(OUTPUT_DIR, filename)\n",
" df_subset.to_csv(filepath, index=False)\n",
" \n",
" print(f\"{asset_type or '(empty)'}: {len(accounts_95)} accounts (95% AUM) → {len(df_subset)} rows → {filepath}\")\n",
"\n",
"print(f\"\\nDone. Files saved in '{OUTPUT_DIR}/'\")"
]
},
2026-02-22 15:02:41 +01:00
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Sum of AUM by Product - Fund"
]
},
{
"cell_type": "code",
"execution_count": 6,
2026-02-22 15:02:41 +01:00
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"AUM (€) by Product - Fund:\n",
"Product - Fund\n",
"Carmignac Patrimoine 1.838372e+12\n",
"Carmignac Sécurité 1.053010e+12\n",
"Carmignac Investissement 5.300035e+11\n",
"Carmignac Portfolio Sécurité 2.562135e+11\n",
"Carmignac Portfolio Flexible Bond 2.223185e+11\n",
"Carmignac Portfolio Patrimoine 2.035761e+11\n",
"Carmignac Emergents 1.218833e+11\n",
"Carmignac Portfolio Global Bond 1.119945e+11\n",
"Carmignac Portfolio Credit 8.413277e+10\n",
"Carmignac Court Terme 8.224046e+10\n",
"Carmignac Portfolio Emerging Patrimoine 7.216283e+10\n",
"Carmignac Portfolio Grande Europe 6.404670e+10\n",
"Carmignac Portfolio Long-Short European Equities 6.162365e+10\n",
"Carmignac Portfolio Climate Transition 5.125412e+10\n",
"Carmignac Absolute Return Europe 4.100414e+10\n",
"Carmignac Credit 2027 3.937522e+10\n",
"Carmignac Portfolio Patrimoine Europe 3.880186e+10\n",
"Carmignac Portfolio Investissement 3.643094e+10\n",
"Carmignac Investissement Latitude 3.474053e+10\n",
"Carmignac Portfolio Emergents 2.942745e+10\n",
"Carmignac Portfolio Asia Discovery 2.934378e+10\n",
"Carmignac Multi Expertise 2.633552e+10\n",
"Carmignac Euro-Entrepreneurs 2.522512e+10\n",
"Carmignac Credit 2029 1.738790e+10\n",
"Carmignac Portfolio Grandchildren 1.627555e+10\n",
"Carmignac Credit 2025 1.547217e+10\n",
"Fonditalia Carmignac Active Allocation 1.452571e+10\n",
"Carmignac Portfolio EM Debt 1.231814e+10\n",
"UFF Grande Europe 0-100 1.222263e+10\n",
"Carmignac Profil Réactif 75 1.178726e+10\n",
"Carmignac Global Active 1.079949e+10\n",
"Carmignac Profil Réactif 100 1.032957e+10\n",
"FP Carmignac European Leaders 8.759356e+09\n",
"Mapfre Carmignac F.P. 8.205244e+09\n",
"Carmignac Portfolio Flexible Allocation 2024 6.464648e+09\n",
"Carmignac China New Economy 5.961919e+09\n",
"Carmignac Portfolio Investissement Latitude 5.955304e+09\n",
"Carmignac Credit 2031 5.310328e+09\n",
"FP Carmignac Global Equity Compounders 4.482628e+09\n",
"Carmignac Portfolio Merger Arbitrage Plus 4.335203e+09\n",
"Credit Suisse Carmignac Emerging Markets Multi-Asset Fund 3.920236e+09\n",
"Carmignac Portfolio Euro-Entrepreneurs 3.670384e+09\n",
"Carmignac Portfolio Merger Arbitrage 3.643225e+09\n",
"Carmignac Portfolio Human Xperience 3.477910e+09\n",
"Carmignac Alts ICAV Carmignac Credit Opportunities 3.294673e+09\n",
"Carmignac Alts ICAV European Long Short 3.260443e+09\n",
"Carmignac Portfolio Capital Cube 2.773859e+09\n",
"Carmignac Portfolio China New Economy 2.757754e+09\n",
"FP Carmignac Emerging Markets 2.224219e+09\n",
"FP Carmignac Global Bond 2.208401e+09\n",
"Carmignac S.A. SICAV - PART II UCI Private Evergreen 2.205183e+09\n",
"Carmignac Portfolio Family Governed 2.104642e+09\n",
"Carmignac Portfolio Tech Solutions 1.812327e+09\n",
"FP Carmignac Emerging Patrimoine 1.486110e+09\n",
"Carmignac Portfolio Long-Short Global Equities 1.450546e+09\n",
"FP Carmignac Patrimoine 1.367843e+09\n",
"FP Carmignac Emerging Discovery 1.315189e+09\n",
"Carmignac Portfolio Global Market Neutral 8.912455e+08\n",
"Carmignac Portfolio China 8.898217e+08\n",
"Carmignac Portfolio Inflation Solution 8.063914e+08\n",
"Carmignac Portfolio Absolute Return Europe 7.929928e+08\n",
"Solys - Carmignac Equity Selection 6.677506e+08\n",
"LUX IM - Carmignac Emerging Flexible Bond 6.397498e+08\n",
"Carmignac Portfolio Evolution 5.464840e+08\n",
"Carmignac Portfolio Alpha Themes 5.085499e+08\n",
"Carmignac Portfolio Active Risk Allocation 3.816403e+08\n",
"Carmignac Portfolio Cross Asset Opportunities 2.291751e+08\n",
"Carmignac Portfolio Sustainable Bond 6.016398e+07\n",
"Carmignac Epargne Actions Monde ISR 1.858147e+07\n",
"CFP 1 2.300000e+02\n",
"Carmignac Innovation 0.000000e+00\n",
"Carmignac Euro-Investissement 0.000000e+00\n",
"Carmignac Portfolio Infotech 0.000000e+00\n",
"Carmignac Portfolio Market Neutral 0.000000e+00\n"
]
},
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>Product - Fund</th>\n",
" <th>Total AUM (€)</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>Carmignac Patrimoine</td>\n",
" <td>1.838372e+12</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>Carmignac Sécurité</td>\n",
" <td>1.053010e+12</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>Carmignac Investissement</td>\n",
" <td>5.300035e+11</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>Carmignac Portfolio Sécurité</td>\n",
" <td>2.562135e+11</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>Carmignac Portfolio Flexible Bond</td>\n",
" <td>2.223185e+11</td>\n",
" </tr>\n",
" <tr>\n",
" <th>...</th>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>69</th>\n",
" <td>CFP 1</td>\n",
" <td>2.300000e+02</td>\n",
" </tr>\n",
" <tr>\n",
" <th>70</th>\n",
" <td>Carmignac Innovation</td>\n",
" <td>0.000000e+00</td>\n",
" </tr>\n",
" <tr>\n",
" <th>71</th>\n",
" <td>Carmignac Euro-Investissement</td>\n",
" <td>0.000000e+00</td>\n",
" </tr>\n",
" <tr>\n",
" <th>72</th>\n",
" <td>Carmignac Portfolio Infotech</td>\n",
" <td>0.000000e+00</td>\n",
" </tr>\n",
" <tr>\n",
" <th>73</th>\n",
" <td>Carmignac Portfolio Market Neutral</td>\n",
" <td>0.000000e+00</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p>74 rows × 2 columns</p>\n",
"</div>"
],
"text/plain": [
" Product - Fund Total AUM (€)\n",
"0 Carmignac Patrimoine 1.838372e+12\n",
"1 Carmignac Sécurité 1.053010e+12\n",
"2 Carmignac Investissement 5.300035e+11\n",
"3 Carmignac Portfolio Sécurité 2.562135e+11\n",
"4 Carmignac Portfolio Flexible Bond 2.223185e+11\n",
".. ... ...\n",
"69 CFP 1 2.300000e+02\n",
"70 Carmignac Innovation 0.000000e+00\n",
"71 Carmignac Euro-Investissement 0.000000e+00\n",
"72 Carmignac Portfolio Infotech 0.000000e+00\n",
"73 Carmignac Portfolio Market Neutral 0.000000e+00\n",
"\n",
"[74 rows x 2 columns]"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
2026-02-22 15:02:41 +01:00
"source": [
"# Sum Value - AUM € per Product - Fund\n",
"aum_by_fund = stocks.groupby('Product - Fund', dropna=False)['Value - AUM €'].sum().sort_values(ascending=False)\n",
"\n",
"print(\"AUM (€) by Product - Fund:\")\n",
"print(aum_by_fund.to_string())\n",
"\n",
"# Display as DataFrame for nicer formatting\n",
"aum_by_fund_df = aum_by_fund.reset_index()\n",
"aum_by_fund_df.columns = ['Product - Fund', 'Total AUM (€)']\n",
"aum_by_fund_df"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 1000x800 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"fig, ax = plt.subplots(figsize=(10, 8))\n",
"aum_by_fund.plot(kind='barh', ax=ax, color='coral', edgecolor='darkred', alpha=0.8)\n",
"ax.set_title('AUM Distribution by Product - Fund')\n",
"ax.set_xlabel('Total AUM (€)')\n",
"ax.set_ylabel('Product - Fund')\n",
"plt.tight_layout()\n",
"plt.show()"
]
2026-02-22 15:02:41 +01:00
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.13.12"
}
},
"nbformat": 4,
"nbformat_minor": 4
}