{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 70,
   "metadata": {},
   "outputs": [
    {
     "ename": "FileNotFoundError",
     "evalue": "File downloaded_etf/VWCE-MI-IE00BK5BQT80-italy-vanguard_ftse_all_world_ucits_etf_usd_accumulation-2020_01_14-2022_12_30.csv.json does not exist",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mFileNotFoundError\u001b[0m                         Traceback (most recent call last)",
      "Cell \u001b[0;32mIn[70], line 9\u001b[0m\n\u001b[1;32m      7\u001b[0m file_name2 \u001b[39m=\u001b[39m \u001b[39m\"\u001b[39m\u001b[39mSEGA-MI-IE00B4WXJJ64-italy-ishares_core_€_govt_bond_ucits_etf_eur_(dist)-2010_01_18-2022_12_30.csv.json\u001b[39m\u001b[39m\"\u001b[39m\n\u001b[1;32m      8\u001b[0m filename3 \u001b[39m=\u001b[39m \u001b[39m\"\u001b[39m\u001b[39mCSSPX-MI-IE00B5BMR087-italy-ishares_core_s&p_500_ucits_etf_usd_(acc)-2010_05_27-2022_12_30.csv.json\u001b[39m\u001b[39m\"\u001b[39m\n\u001b[0;32m----> 9\u001b[0m df1 \u001b[39m=\u001b[39m po\u001b[39m.\u001b[39;49mfile_to_dataframe(\u001b[39mf\u001b[39;49m\u001b[39m\"\u001b[39;49m\u001b[39m{\u001b[39;49;00mdirectory\u001b[39m}\u001b[39;49;00m\u001b[39m/\u001b[39;49m\u001b[39m{\u001b[39;49;00mfile_name1\u001b[39m}\u001b[39;49;00m\u001b[39m\"\u001b[39;49m)\n\u001b[1;32m     10\u001b[0m df2 \u001b[39m=\u001b[39m po\u001b[39m.\u001b[39mfile_to_dataframe(\u001b[39mf\u001b[39m\u001b[39m\"\u001b[39m\u001b[39m{\u001b[39;00mdirectory\u001b[39m}\u001b[39;00m\u001b[39m/\u001b[39m\u001b[39m{\u001b[39;00mfile_name2\u001b[39m}\u001b[39;00m\u001b[39m\"\u001b[39m)\n\u001b[1;32m     11\u001b[0m df3 \u001b[39m=\u001b[39m po\u001b[39m.\u001b[39mfile_to_dataframe(\u001b[39mf\u001b[39m\u001b[39m\"\u001b[39m\u001b[39m{\u001b[39;00mdirectory\u001b[39m}\u001b[39;00m\u001b[39m/\u001b[39m\u001b[39m{\u001b[39;00mfilename3\u001b[39m}\u001b[39;00m\u001b[39m\"\u001b[39m)\n",
      "File \u001b[0;32m~/eodhistoricaldata/portfolio_optimizer.py:75\u001b[0m, in \u001b[0;36mfile_to_dataframe\u001b[0;34m(filename, date_column_name, price_column_name)\u001b[0m\n\u001b[1;32m     70\u001b[0m     df\u001b[39m.\u001b[39mset_index(date_column_name, inplace\u001b[39m=\u001b[39m\u001b[39mTrue\u001b[39;00m)\n\u001b[1;32m     72\u001b[0m     \u001b[39mreturn\u001b[39;00m df[[price_column_name]]\n\u001b[0;32m---> 75\u001b[0m \u001b[39mdef\u001b[39;00m \u001b[39mdistribute_money_by_ticker_weights\u001b[39m(tickers_weights: Dict[\u001b[39mstr\u001b[39m, \u001b[39mfloat\u001b[39m], money:\u001b[39mint\u001b[39m, tickers_prices: Dict[\u001b[39mstr\u001b[39m, \u001b[39mfloat\u001b[39m],):\n\u001b[1;32m     76\u001b[0m     \u001b[39m\"\"\"distribute money by weights\u001b[39;00m\n\u001b[1;32m     77\u001b[0m \u001b[39m    returning for every ticker the amount of money and the amount of shares\u001b[39;00m\n\u001b[1;32m     78\u001b[0m \u001b[39m    \"\"\"\u001b[39;00m\n\u001b[1;32m     79\u001b[0m     \u001b[39mreturn\u001b[39;00m {\n\u001b[1;32m     80\u001b[0m         ticker: (money\u001b[39m*\u001b[39mweight, money\u001b[39m*\u001b[39mweight\u001b[39m/\u001b[39mtickers_prices[ticker])\n\u001b[1;32m     81\u001b[0m         \u001b[39mfor\u001b[39;00m ticker, weight \u001b[39min\u001b[39;00m tickers_weights\u001b[39m.\u001b[39mitems()\n\u001b[1;32m     82\u001b[0m     }\n",
      "File \u001b[0;32m~/.local/lib/python3.10/site-packages/pandas/util/_decorators.py:211\u001b[0m, in \u001b[0;36mdeprecate_kwarg.<locals>._deprecate_kwarg.<locals>.wrapper\u001b[0;34m(*args, **kwargs)\u001b[0m\n\u001b[1;32m    209\u001b[0m     \u001b[39melse\u001b[39;00m:\n\u001b[1;32m    210\u001b[0m         kwargs[new_arg_name] \u001b[39m=\u001b[39m new_arg_value\n\u001b[0;32m--> 211\u001b[0m \u001b[39mreturn\u001b[39;00m func(\u001b[39m*\u001b[39;49margs, \u001b[39m*\u001b[39;49m\u001b[39m*\u001b[39;49mkwargs)\n",
      "File \u001b[0;32m~/.local/lib/python3.10/site-packages/pandas/util/_decorators.py:331\u001b[0m, in \u001b[0;36mdeprecate_nonkeyword_arguments.<locals>.decorate.<locals>.wrapper\u001b[0;34m(*args, **kwargs)\u001b[0m\n\u001b[1;32m    325\u001b[0m \u001b[39mif\u001b[39;00m \u001b[39mlen\u001b[39m(args) \u001b[39m>\u001b[39m num_allow_args:\n\u001b[1;32m    326\u001b[0m     warnings\u001b[39m.\u001b[39mwarn(\n\u001b[1;32m    327\u001b[0m         msg\u001b[39m.\u001b[39mformat(arguments\u001b[39m=\u001b[39m_format_argument_list(allow_args)),\n\u001b[1;32m    328\u001b[0m         \u001b[39mFutureWarning\u001b[39;00m,\n\u001b[1;32m    329\u001b[0m         stacklevel\u001b[39m=\u001b[39mfind_stack_level(),\n\u001b[1;32m    330\u001b[0m     )\n\u001b[0;32m--> 331\u001b[0m \u001b[39mreturn\u001b[39;00m func(\u001b[39m*\u001b[39;49margs, \u001b[39m*\u001b[39;49m\u001b[39m*\u001b[39;49mkwargs)\n",
      "File \u001b[0;32m~/.local/lib/python3.10/site-packages/pandas/io/json/_json.py:733\u001b[0m, in \u001b[0;36mread_json\u001b[0;34m(path_or_buf, orient, typ, dtype, convert_axes, convert_dates, keep_default_dates, numpy, precise_float, date_unit, encoding, encoding_errors, lines, chunksize, compression, nrows, storage_options)\u001b[0m\n\u001b[1;32m    730\u001b[0m \u001b[39mif\u001b[39;00m convert_axes \u001b[39mis\u001b[39;00m \u001b[39mNone\u001b[39;00m \u001b[39mand\u001b[39;00m orient \u001b[39m!=\u001b[39m \u001b[39m\"\u001b[39m\u001b[39mtable\u001b[39m\u001b[39m\"\u001b[39m:\n\u001b[1;32m    731\u001b[0m     convert_axes \u001b[39m=\u001b[39m \u001b[39mTrue\u001b[39;00m\n\u001b[0;32m--> 733\u001b[0m json_reader \u001b[39m=\u001b[39m JsonReader(\n\u001b[1;32m    734\u001b[0m     path_or_buf,\n\u001b[1;32m    735\u001b[0m     orient\u001b[39m=\u001b[39;49morient,\n\u001b[1;32m    736\u001b[0m     typ\u001b[39m=\u001b[39;49mtyp,\n\u001b[1;32m    737\u001b[0m     dtype\u001b[39m=\u001b[39;49mdtype,\n\u001b[1;32m    738\u001b[0m     convert_axes\u001b[39m=\u001b[39;49mconvert_axes,\n\u001b[1;32m    739\u001b[0m     convert_dates\u001b[39m=\u001b[39;49mconvert_dates,\n\u001b[1;32m    740\u001b[0m     keep_default_dates\u001b[39m=\u001b[39;49mkeep_default_dates,\n\u001b[1;32m    741\u001b[0m     numpy\u001b[39m=\u001b[39;49mnumpy,\n\u001b[1;32m    742\u001b[0m     precise_float\u001b[39m=\u001b[39;49mprecise_float,\n\u001b[1;32m    743\u001b[0m     date_unit\u001b[39m=\u001b[39;49mdate_unit,\n\u001b[1;32m    744\u001b[0m     encoding\u001b[39m=\u001b[39;49mencoding,\n\u001b[1;32m    745\u001b[0m     lines\u001b[39m=\u001b[39;49mlines,\n\u001b[1;32m    746\u001b[0m     chunksize\u001b[39m=\u001b[39;49mchunksize,\n\u001b[1;32m    747\u001b[0m     compression\u001b[39m=\u001b[39;49mcompression,\n\u001b[1;32m    748\u001b[0m     nrows\u001b[39m=\u001b[39;49mnrows,\n\u001b[1;32m    749\u001b[0m     storage_options\u001b[39m=\u001b[39;49mstorage_options,\n\u001b[1;32m    750\u001b[0m     encoding_errors\u001b[39m=\u001b[39;49mencoding_errors,\n\u001b[1;32m    751\u001b[0m )\n\u001b[1;32m    753\u001b[0m \u001b[39mif\u001b[39;00m chunksize:\n\u001b[1;32m    754\u001b[0m     \u001b[39mreturn\u001b[39;00m json_reader\n",
      "File \u001b[0;32m~/.local/lib/python3.10/site-packages/pandas/io/json/_json.py:818\u001b[0m, in \u001b[0;36mJsonReader.__init__\u001b[0;34m(self, filepath_or_buffer, orient, typ, dtype, convert_axes, convert_dates, keep_default_dates, numpy, precise_float, date_unit, encoding, lines, chunksize, compression, nrows, storage_options, encoding_errors)\u001b[0m\n\u001b[1;32m    815\u001b[0m     \u001b[39mif\u001b[39;00m \u001b[39mnot\u001b[39;00m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39mlines:\n\u001b[1;32m    816\u001b[0m         \u001b[39mraise\u001b[39;00m \u001b[39mValueError\u001b[39;00m(\u001b[39m\"\u001b[39m\u001b[39mnrows can only be passed if lines=True\u001b[39m\u001b[39m\"\u001b[39m)\n\u001b[0;32m--> 818\u001b[0m data \u001b[39m=\u001b[39m \u001b[39mself\u001b[39;49m\u001b[39m.\u001b[39;49m_get_data_from_filepath(filepath_or_buffer)\n\u001b[1;32m    819\u001b[0m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39mdata \u001b[39m=\u001b[39m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39m_preprocess_data(data)\n",
      "File \u001b[0;32m~/.local/lib/python3.10/site-packages/pandas/io/json/_json.py:874\u001b[0m, in \u001b[0;36mJsonReader._get_data_from_filepath\u001b[0;34m(self, filepath_or_buffer)\u001b[0m\n\u001b[1;32m    866\u001b[0m     filepath_or_buffer \u001b[39m=\u001b[39m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39mhandles\u001b[39m.\u001b[39mhandle\n\u001b[1;32m    867\u001b[0m \u001b[39melif\u001b[39;00m (\n\u001b[1;32m    868\u001b[0m     \u001b[39misinstance\u001b[39m(filepath_or_buffer, \u001b[39mstr\u001b[39m)\n\u001b[1;32m    869\u001b[0m     \u001b[39mand\u001b[39;00m filepath_or_buffer\u001b[39m.\u001b[39mlower()\u001b[39m.\u001b[39mendswith(\n\u001b[0;32m   (...)\u001b[0m\n\u001b[1;32m    872\u001b[0m     \u001b[39mand\u001b[39;00m \u001b[39mnot\u001b[39;00m file_exists(filepath_or_buffer)\n\u001b[1;32m    873\u001b[0m ):\n\u001b[0;32m--> 874\u001b[0m     \u001b[39mraise\u001b[39;00m \u001b[39mFileNotFoundError\u001b[39;00m(\u001b[39mf\u001b[39m\u001b[39m\"\u001b[39m\u001b[39mFile \u001b[39m\u001b[39m{\u001b[39;00mfilepath_or_buffer\u001b[39m}\u001b[39;00m\u001b[39m does not exist\u001b[39m\u001b[39m\"\u001b[39m)\n\u001b[1;32m    876\u001b[0m \u001b[39mreturn\u001b[39;00m filepath_or_buffer\n",
      "\u001b[0;31mFileNotFoundError\u001b[0m: File downloaded_etf/VWCE-MI-IE00BK5BQT80-italy-vanguard_ftse_all_world_ucits_etf_usd_accumulation-2020_01_14-2022_12_30.csv.json does not exist"
     ]
    }
   ],
   "source": [
    "import pandas as pd\n",
    "import portfolio_optimizer as po\n",
    "import requests\n",
    "\n",
    "directory = \"downloaded_etf\"\n",
    "file_name1 = \"VWCE-MI-IE00BK5BQT80-italy-vanguard_ftse_all_world_ucits_etf_usd_accumulation-2020_01_14-2022_12_30.csv.json\"\n",
    "file_name2 = \"SEGA-MI-IE00B4WXJJ64-italy-ishares_core_€_govt_bond_ucits_etf_eur_(dist)-2010_01_18-2022_12_30.csv.json\"\n",
    "filename3 = \"CSSPX-MI-IE00B5BMR087-italy-ishares_core_s&p_500_ucits_etf_usd_(acc)-2010_05_27-2022_12_30.csv.json\"\n",
    "df1 = po.file_to_dataframe(f\"{directory}/{file_name1}\")\n",
    "df2 = po.file_to_dataframe(f\"{directory}/{file_name2}\")\n",
    "df3 = po.file_to_dataframe(f\"{directory}/{filename3}\")\n",
    "\n",
    "# rename columns\n",
    "df1.rename(columns={\"adjusted_close\": \"VWCE\"}, inplace=True)\n",
    "df2.rename(columns={\"adjusted_close\": \"SEGA\"}, inplace=True)\n",
    "df3.rename(columns={\"adjusted_close\": \"CSSPX\"}, inplace=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(           VWCE      SEGA     CSSPX\n",
       " VWCE   0.024949  0.004248  0.027240\n",
       " SEGA   0.004248  0.008362  0.004645\n",
       " CSSPX  0.027240  0.004645  0.031857,\n",
       " VWCE    -0.013707\n",
       " SEGA    -0.117323\n",
       " CSSPX    0.007130\n",
       " Name: 2022-12-30 00:00:00, dtype: float64)"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data = pd.concat([df1, df2, df3], axis=1)\n",
    "optimizer = po.PortfolioOptimizer(\n",
    "    data, True\n",
    ")\n",
    "\n",
    "optimizer.sigma, optimizer.mu"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [],
   "source": [
    "maxdata = optimizer.maximum_return()\n",
    "mindata = optimizer.minimum_risk()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "min risk: 0.08763370433800144, max risk: 0.17848613699023425\n"
     ]
    }
   ],
   "source": [
    "minrisk = float(mindata[1]['risk'])\n",
    "maxrisk = float(maxdata[1]['risk'])\n",
    "\n",
    "print(f\"min risk: {minrisk}, max risk: {maxrisk}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [],
   "source": [
    "interval = (maxrisk - minrisk) / 6"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "OrderedDict([('VWCE', 0.3443), ('SEGA', 0.5182), ('CSSPX', 0.1376)])"
      ]
     },
     "execution_count": 31,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "interval1 = minrisk + interval\n",
    "interval2 = minrisk + interval * 2\n",
    "interval3 = minrisk + interval * 3\n",
    "interval4 = minrisk + interval * 4\n",
    "interval5 = minrisk + interval * 5\n",
    "interval6 = minrisk + interval * 6\n",
    "\n",
    "optimizer.efficient_risk(interval1)[0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "OrderedDict([('VWCE', 0.1447), ('SEGA', 0.1807), ('CSSPX', 0.6745)])"
      ]
     },
     "execution_count": 32,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "optimizer.efficient_risk(interval4)[0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [],
   "source": [
    "soldi = 5321\n",
    "\n",
    "def get_portfolio_value(weights, prices):\n",
    "    return  [weights[ticker] * prices[ticker] for ticker in weights] \n",
    "\n",
    "port = get_portfolio_value(optimizer.efficient_risk(interval1)[0], data.iloc[-1])\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "VWCE: 1832.0203 (20)\n",
      "SEGA: 2757.3422 (26)\n",
      "CSSPX: 732.1696 (2)\n"
     ]
    }
   ],
   "source": [
    "for w in optimizer.efficient_risk(interval1)[0]:\n",
    "    soldi_per_ticker = soldi * optimizer.efficient_risk(interval1)[0][w]\n",
    "    quote_per_ticker = int(round((soldi_per_ticker / data.iloc[-1][w]),0))\n",
    "    print(f\"{w}: {soldi_per_ticker} ({quote_per_ticker})\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 75,
   "metadata": {},
   "outputs": [],
   "source": [
    "indb = \"\"\"IE00B58HMN42 CCEUAS MI\n",
    "IE00B579F325 SGLD MI\n",
    "IE00BKM4GZ66 EIMI MI\n",
    "LU1781541179 LCWD MI\n",
    "IE00BP3QZB59 IWVL MI\n",
    "IE00B4L5Y983 SWDA MI\n",
    "IE00BP46NG52 EMH5 MI\n",
    "IE00BF3N7102 IHYE MI\n",
    "IE00B9M6RS56 EMBE MI\n",
    "LU0478205379 XBLC MI\n",
    "LU0290358224 XEIN MI\n",
    "LU1437016204 GGOV PA\n",
    "LU1048317025 CBUSE MI\n",
    "IE00BDZVH966 IBC5 XETRA\n",
    "LU1407890976 U10H MI\n",
    "LU1650487413 EM13 MI\n",
    "\"\"\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 77,
   "metadata": {},
   "outputs": [],
   "source": [
    "for row in indb.splitlines():\n",
    "    isin, ticker, market = row.split()\n",
    "    \n",
    "    resp = requests.get(f\"http://localhost:1323/download_etf?ticker={ticker}&exchange={market}\")\n",
    "    resp.text"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 80,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['CBUSE{}MI{}LU1048317025{}italy{}UBS Barclays US Liquid Corporates UCITS hedged to EUR A-acc{}2014-06-20{}2023-01-05.json',\n",
       " 'CCEUAS{}MI{}IE00B58HMN42{}italy{}UBS (Irl) Fund Solutions plc – CMCI Composite SF UCITS ETF (hedged to EUR) A-acc{}2013-05-28{}2023-01-05.json',\n",
       " 'EIMI{}MI{}IE00BKM4GZ66{}italy{}iShares Core MSCI Emerging Markets IMI UCITS{}2014-07-24{}2023-01-05.json',\n",
       " 'EM13{}MI{}LU1650487413{}italy{}Lyxor Euromts 1-3Y Inv Grd (DR) ETF CEUR{}2010-01-01{}2023-01-05.json',\n",
       " 'EMBE{}MI{}IE00B9M6RS56{}italy{}iShares J.P. Morgan Emerging Markets Bond EUR Hedged UCITS{}2015-08-05{}2023-01-05.json',\n",
       " 'EMH5{}MI{}IE00BP46NG52{}italy{}SPDR BofA Merrill Lynch 0-5 Emerging Markets Government Bond UCITS{}2016-02-23{}2023-01-05.json',\n",
       " 'GGOV{}PA{}LU1437016204{}france{}Amundi Index Solutions - Amundi Index J.P. Morgan GBI Global Govies{}2017-02-15{}2023-01-05.json',\n",
       " 'IBC5{}XETRA{}IE00BDZVH966{}germany{}iShares $ TIPS UCITS ETF EUR Hedged (Acc) EUR{}2018-03-29{}2023-01-05.json',\n",
       " 'IHYE{}MI{}IE00BF3N7102{}italy{}iShares $ High Yield Corp Bond UCITS ETF EUR Hedged (Dist){}2021-06-01{}2023-01-05.json',\n",
       " 'IWVL{}MI{}IE00BP3QZB59{}italy{}iShares MSCI World Value Factor UCITS{}2015-02-20{}2023-01-05.json',\n",
       " 'LCWD{}MI{}LU1781541179{}italy{}Lyxor Core MSCI World (DR) UCITS ETF{}2021-02-19{}2023-01-05.json',\n",
       " 'SGLD{}MI{}IE00B579F325{}italy{}Invesco Physical Gold ETC{}2014-11-28{}2023-01-05.json',\n",
       " 'SWDA{}MI{}IE00B4L5Y983{}italy{}iShares Core MSCI World UCITS ETF USD (Acc){}2010-02-01{}2023-01-05.json',\n",
       " 'U10H{}MI{}LU1407890976{}italy{}Lyxor iBoxx $ Treasuries 10+ DR UCITS Monthly Hedged D-EUR{}2017-05-15{}2023-01-05.json',\n",
       " 'XBLC{}MI{}LU0478205379{}italy{}Xtrackers II EUR Corporate Bond UCITS ETF 1C{}2010-06-25{}2023-01-05.json',\n",
       " 'XEIN{}MI{}LU0290358224{}italy{}Xtrackers II Eurozone Inflation-Linked Bond UCITS ETF 1C{}2010-01-04{}2023-01-05.json']"
      ]
     },
     "execution_count": 80,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "resp = requests.get(\"http://localhost:1323/available_etfs_as_filename\")\n",
    "resp.json()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "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.10.6 (main, Nov 14 2022, 16:10:14) [GCC 11.3.0]"
  },
  "orig_nbformat": 4,
  "vscode": {
   "interpreter": {
    "hash": "916dbcbb3f70747c44a77c7bcd40155683ae19c65e1c03b4aa3499c5328201f1"
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
