{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Import Python packages\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "# ! uv pip install E:\\Work\\ruzt\\msyrs --upgrade"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "import macrosynergy\n",
    "import pandas as pd\n",
    "import numpy as np\n",
    "import polars as pl\n",
    "import time\n",
    "import os\n",
    "\n",
    "from macrosynergy.panel import view_timelines\n",
    "from macrosynergy.management.types import QuantamentalDataFrame"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Import Python bindings - `msyrs`\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "import msyrs"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "DATA_FOLDER_PATH = \"E:/Work/jpmaqs-data\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "cids_dm = \"AUD.CAD.CHF.EUR.GBP.JPY.NOK.NZD.SEK.USD\".split(\".\")\n",
    "cids_em = \"CLP.COP.CZK.HUF.IDR.ILS.INR.KRW.MXN.PLN.THB.TRY.TWD.ZAR\".split(\".\")\n",
    "cids = cids_dm + cids_em\n",
    "cids_dux = list(set(cids) - set([\"IDR\", \"NZD\"]))\n",
    "ecos = \"CPIC_SA_P1M1ML12.CPIC_SJA_P3M3ML3AR.CPIC_SJA_P6M6ML6AR.CPIH_SA_P1M1ML12.CPIH_SJA_P3M3ML3AR.CPIH_SJA_P6M6ML6AR.INFTEFF_NSA.INTRGDP_NSA_P1M1ML12_3MMA.INTRGDPv5Y_NSA_P1M1ML12_3MMA.PCREDITGDP_SJA_D1M1ML12.RGDP_SA_P1Q1QL4_20QMA.RYLDIRS02Y_NSA.RYLDIRS05Y_NSA.PCREDITBN_SJA_P1M1ML12\".split(\n",
    "    \".\"\n",
    ")\n",
    "\n",
    "\n",
    "mkts = \"DU02YXR_NSA.DU05YXR_NSA.DU02YXR_VT10.DU05YXR_VT10.EQXR_NSA.EQXR_VT10.FXXR_NSA.FXXR_VT10.FXCRR_NSA.FXTARGETED_NSA.FXUNTRADABLE_NSA\".split(\n",
    "    \".\"\n",
    ")\n",
    "xcats = ecos + mkts\n",
    "\n",
    "cpi_xcats = \"CPIC_SA_P1M1ML12.CPIC_SJA_P3M3ML3AR.CPIC_SJA_P6M6ML6AR.CPIH_SA_P1M1ML12.CPIH_SJA_P3M3ML3AR.CPIH_SJA_P6M6ML6AR\".split(\n",
    "    \".\"\n",
    ")\n",
    "\n",
    "tickers = [f\"{c}_{x}\" for c in cids for x in xcats]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Time taken to load qdf batch: 2.7522997856140137\n"
     ]
    }
   ],
   "source": [
    "starttime = time.time()\n",
    "\n",
    "big_df: pl.DataFrame = msyrs.qdf.load_qdf_from_download_bank(\n",
    "    folder_path=DATA_FOLDER_PATH,\n",
    "    xcats=xcats,\n",
    ")\n",
    "print(f\"Time taken to load qdf batch: {time.time() - starttime}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "286.69339656829834"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "big_df.estimated_size(\"mb\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "sel_cids = [\"USD\", \"EUR\", \"GBP\", \"AUD\", \"CAD\"]\n",
    "start = \"1990-01-01\"\n",
    "nb_start_time = time.time()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Running with uniform weights, 2 xcats, 5 cids\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Time taken to reduce qdf: 1.0994884967803955\n"
     ]
    }
   ],
   "source": [
    "fx_xcats = [xc for xc in xcats if xc.startswith(\"FX\")]\n",
    "eq_xcats = [xc for xc in xcats if xc.startswith(\"EQ\")]\n",
    "starttime = time.time()\n",
    "\n",
    "eq_df = msyrs.qdf.reduce_dataframe(\n",
    "    df=big_df,\n",
    "    cids=sel_cids,\n",
    "    xcats=fx_xcats + eq_xcats + cpi_xcats,\n",
    "    start=start,\n",
    ")\n",
    "\n",
    "fx_df = msyrs.qdf.reduce_dataframe(\n",
    "    df=big_df, cids=sel_cids, start=start, xcats=fx_xcats, intersect=True\n",
    ")\n",
    "new_df: pl.DataFrame = msyrs.qdf.update_dataframe(df=eq_df, df_add=fx_df)\n",
    "\n",
    "print(f\"Time taken to reduce qdf: {time.time() - starttime}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Time taken to run linear composite: 0.19902491569519043\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "e:\\Work\\ruzt\\msyrs\\.venv\\Lib\\site-packages\\macrosynergy\\panel\\linear_composite.py:437: UserWarning: USD does not have complete xcat data for ['FXXR_NSA']. These will be filled with NaNs for the calculation.\n",
      "  warnings.warn(wrn_msg.format(cidx=cidx, missing_xcats=missing_xcats))\n"
     ]
    }
   ],
   "source": [
    "_cids = [\"USD\", \"CAD\"]\n",
    "\n",
    "_df = new_df.to_pandas()\n",
    "starttime = time.time()\n",
    "\n",
    "\n",
    "mx = macrosynergy.panel.linear_composite(\n",
    "    df=_df,\n",
    "    xcats=[\"EQXR_NSA\", \"FXXR_NSA\"],\n",
    "    cids=_cids,\n",
    "    weights=None,\n",
    "    signs=None,\n",
    "    normalize_weights=False,\n",
    "    start=None,\n",
    "    end=None,\n",
    "    blacklist=None,\n",
    "    complete_xcats=False,\n",
    "    complete_cids=False,\n",
    "    new_xcat=\"COMPOSITE\",\n",
    "    new_cid=\"GLB\",\n",
    ")\n",
    "print(f\"Time taken to run linear composite: {time.time() - starttime}\")\n",
    "\n",
    "\n",
    "# view_timelines(QuantamentalDataFrame(mx), cids=_cids)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Time taken to run linear composite rs: 0.047815799713134766\n"
     ]
    }
   ],
   "source": [
    "_cids = [\"USD\", \"CAD\"]\n",
    "starttime = time.time()\n",
    "\n",
    "x = msyrs.panel.linear_composite(\n",
    "    df=new_df,\n",
    "    xcats=[\"EQXR_NSA\", \"FXXR_NSA\"],\n",
    "    cids=_cids,\n",
    "    weights=None,\n",
    "    signs=None,\n",
    "    weight_xcats=None,\n",
    "    normalize_weights=False,\n",
    "    start=None,\n",
    "    end=None,\n",
    "    blacklist=None,\n",
    "    complete_xcats=False,\n",
    "    complete_cids=False,\n",
    "    new_xcat=\"COMPOSITE\",\n",
    "    new_cid=\"GLB\",\n",
    ")\n",
    "print(f\"Time taken to run linear composite rs: {time.time() - starttime}\")\n",
    "\n",
    "# view_timelines(QuantamentalDataFrame(x.to_pandas()), cids=_cids)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Running with variable weights\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "e:\\Work\\ruzt\\msyrs\\.venv\\Lib\\site-packages\\macrosynergy\\panel\\linear_composite.py:437: UserWarning: USD does not have complete xcat data for ['FXXR_NSA']. These will be filled with NaNs for the calculation.\n",
      "  warnings.warn(wrn_msg.format(cidx=cidx, missing_xcats=missing_xcats))\n"
     ]
    },
    {
     "data": {
      "image/png": "[encoded data, 121580 characters]",
      "text/plain": [
       "<Figure size 2075.09x855 with 4 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "_cids = [\"USD\", \"CAD\", \"EUR\", \"AUD\"]\n",
    "_xcats = [\"EQXR_NSA\", \"FXXR_NSA\"]\n",
    "\n",
    "mx = macrosynergy.panel.linear_composite(\n",
    "    df=new_df.to_pandas(),\n",
    "    xcats=_xcats,\n",
    "    cids=_cids,\n",
    "    weights=[1, 9],\n",
    "    normalize_weights=False,\n",
    "    new_xcat=\"COMPOSITE\",\n",
    "    new_cid=\"GLB\",\n",
    ")\n",
    "x = msyrs.panel.linear_composite(\n",
    "    df=new_df,\n",
    "    xcats=_xcats,\n",
    "    cids=_cids,\n",
    "    weights=[1, 9],\n",
    "    normalize_weights=False,\n",
    "    new_xcat=\"COMPOSITE\",\n",
    "    new_cid=\"GLB\",\n",
    ")\n",
    "view_timelines(QuantamentalDataFrame(mx), cids=_cids)\n",
    "mwide = QuantamentalDataFrame(mx).to_wide().sort_index()\n",
    "rwide = QuantamentalDataFrame(x.to_pandas()).to_wide().sort_index()\n",
    "np.allclose((mwide - rwide).sum(axis=1), 0)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Running with variable weights, normalized\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "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>real_date</th>\n",
       "      <th>value</th>\n",
       "      <th>cid</th>\n",
       "      <th>xcat</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>22</th>\n",
       "      <td>1990-02-20</td>\n",
       "      <td>3.592367</td>\n",
       "      <td>CAD</td>\n",
       "      <td>COMPOSITE</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>23</th>\n",
       "      <td>1990-02-21</td>\n",
       "      <td>3.592367</td>\n",
       "      <td>CAD</td>\n",
       "      <td>COMPOSITE</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>24</th>\n",
       "      <td>1990-02-22</td>\n",
       "      <td>3.592367</td>\n",
       "      <td>CAD</td>\n",
       "      <td>COMPOSITE</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>25</th>\n",
       "      <td>1990-02-23</td>\n",
       "      <td>3.592367</td>\n",
       "      <td>CAD</td>\n",
       "      <td>COMPOSITE</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>26</th>\n",
       "      <td>1990-02-26</td>\n",
       "      <td>3.592367</td>\n",
       "      <td>CAD</td>\n",
       "      <td>COMPOSITE</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>...</th>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>35319</th>\n",
       "      <td>2025-03-31</td>\n",
       "      <td>2.721470</td>\n",
       "      <td>AUD</td>\n",
       "      <td>COMPOSITE</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>35320</th>\n",
       "      <td>2025-04-01</td>\n",
       "      <td>2.721470</td>\n",
       "      <td>AUD</td>\n",
       "      <td>COMPOSITE</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>35321</th>\n",
       "      <td>2025-04-02</td>\n",
       "      <td>2.721470</td>\n",
       "      <td>AUD</td>\n",
       "      <td>COMPOSITE</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>35322</th>\n",
       "      <td>2025-04-03</td>\n",
       "      <td>2.721470</td>\n",
       "      <td>AUD</td>\n",
       "      <td>COMPOSITE</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>35323</th>\n",
       "      <td>2025-04-04</td>\n",
       "      <td>2.721470</td>\n",
       "      <td>AUD</td>\n",
       "      <td>COMPOSITE</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>33163 rows × 4 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "       real_date     value  cid       xcat\n",
       "22    1990-02-20  3.592367  CAD  COMPOSITE\n",
       "23    1990-02-21  3.592367  CAD  COMPOSITE\n",
       "24    1990-02-22  3.592367  CAD  COMPOSITE\n",
       "25    1990-02-23  3.592367  CAD  COMPOSITE\n",
       "26    1990-02-26  3.592367  CAD  COMPOSITE\n",
       "...          ...       ...  ...        ...\n",
       "35319 2025-03-31  2.721470  AUD  COMPOSITE\n",
       "35320 2025-04-01  2.721470  AUD  COMPOSITE\n",
       "35321 2025-04-02  2.721470  AUD  COMPOSITE\n",
       "35322 2025-04-03  2.721470  AUD  COMPOSITE\n",
       "35323 2025-04-04  2.721470  AUD  COMPOSITE\n",
       "\n",
       "[33163 rows x 4 columns]"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x = msyrs.panel.linear_composite(\n",
    "    df=new_df,\n",
    "    xcats=cpi_xcats,\n",
    "    cids=_cids,\n",
    "    weights=list(range(1, len(cpi_xcats) + 1)),\n",
    "    normalize_weights=True,\n",
    "    new_xcat=\"COMPOSITE\",\n",
    "    new_cid=\"GLB\",\n",
    ")\n",
    "x.to_pandas().dropna(how=\"any\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 125276 characters]",
      "text/plain": [
       "<Figure size 2075.09x855 with 4 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "view_timelines(x.to_pandas().dropna(how=\"any\"), cids=_cids)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 125276 characters]",
      "text/plain": [
       "<Figure size 2075.09x855 with 4 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "mx = macrosynergy.panel.linear_composite(\n",
    "    df=new_df.to_pandas(),\n",
    "    xcats=cpi_xcats,\n",
    "    cids=_cids,\n",
    "    weights=list(range(1, len(cpi_xcats) + 1)),\n",
    "    normalize_weights=True,\n",
    "    new_xcat=\"COMPOSITE\",\n",
    "    new_cid=\"GLB\",\n",
    ")\n",
    "view_timelines(mx.dropna(how=\"any\"), cids=_cids)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "mwide = QuantamentalDataFrame(mx).to_wide().sort_index()\n",
    "rwide = QuantamentalDataFrame(x.to_pandas()).to_wide().sort_index()\n",
    "np.allclose((mwide - rwide).sum(axis=1), 0)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Running with categorical weights, normalized\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "ename": "NotImplementedError",
     "evalue": "Not implemented yet",
     "output_type": "error",
     "traceback": [
      "\u001b[31m---------------------------------------------------------------------------\u001b[39m",
      "\u001b[31mNotImplementedError\u001b[39m                       Traceback (most recent call last)",
      "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[17]\u001b[39m\u001b[32m, line 1\u001b[39m\n\u001b[32m----> \u001b[39m\u001b[32m1\u001b[39m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mNotImplementedError\u001b[39;00m(\u001b[33m\"\u001b[39m\u001b[33mNot implemented yet\u001b[39m\u001b[33m\"\u001b[39m)\n",
      "\u001b[31mNotImplementedError\u001b[39m: Not implemented yet"
     ]
    }
   ],
   "source": [
    "raise NotImplementedError(\"Not implemented yet\")"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": ".venv",
   "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.12.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
