{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# Baseline \nBaseline создается больше как шаблон, где можно посмотреть, как происходит обращение с входящими данными и что нужно получить на выходе. При этом ML начинка может быть достаточно простой. Это помогает быстрее приступить к самому ML, а не тратить ценное время на инженерные задачи. Также baseline является хорошей опорной точкой по метрике. Если наше решение хуже baseline - мы явно делаем что-то не так и стоит попробовать другой путь)\n\n### In baseline we will do the following:\nBuild a \"naive\"/baseline model (to which we will compare other models)\n\nSteps:\n- Install libs\n- Import\n- Load the data\n- EDA - Exploratory Data Analysis\n- Data preprocessing\n- Generate new features\n- Make the first model based on gradient bousting with CatBoost (CatBoostClassifier)\n- Generate submission file and send it to Kaggle","metadata":{}},{"cell_type":"markdown","source":"# Install libs","metadata":{}},{"cell_type":"code","source":"!pip install -q pandas_ta","metadata":{"execution":{"iopub.status.busy":"2023-11-01T10:14:27.373258Z","iopub.execute_input":"2023-11-01T10:14:27.374106Z","iopub.status.idle":"2023-11-01T10:14:45.404881Z","shell.execute_reply.started":"2023-11-01T10:14:27.374063Z","shell.execute_reply":"2023-11-01T10:14:45.403476Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# всегда фиксируйте RANDOM_SEED, чтобы ваши эксперименты были воспроизводимы!\nRANDOM_SEED = 42","metadata":{"execution":{"iopub.status.busy":"2023-11-01T10:15:00.567212Z","iopub.execute_input":"2023-11-01T10:15:00.567748Z","iopub.status.idle":"2023-11-01T10:15:00.574937Z","shell.execute_reply.started":"2023-11-01T10:15:00.567708Z","shell.execute_reply":"2023-11-01T10:15:00.573382Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# зафиксируем версию пакетов, чтобы эксперименты были воспроизводимы:\n!pip freeze > requirements.txt","metadata":{"execution":{"iopub.status.busy":"2023-11-01T10:15:00.996919Z","iopub.execute_input":"2023-11-01T10:15:00.997615Z","iopub.status.idle":"2023-11-01T10:15:03.899060Z","shell.execute_reply.started":"2023-11-01T10:15:00.997581Z","shell.execute_reply":"2023-11-01T10:15:03.897113Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Import","metadata":{}},{"cell_type":"code","source":"import os\nimport pandas as pd\nimport numpy as np\nfrom catboost import CatBoostClassifier\nimport pandas_ta as ta\nfrom tqdm import tqdm\n\nimport matplotlib.pyplot as plt\nimport seaborn as sns\n%matplotlib inline","metadata":{"execution":{"iopub.status.busy":"2023-11-01T10:15:03.901985Z","iopub.execute_input":"2023-11-01T10:15:03.902447Z","iopub.status.idle":"2023-11-01T10:15:04.151978Z","shell.execute_reply.started":"2023-11-01T10:15:03.902408Z","shell.execute_reply":"2023-11-01T10:15:04.150978Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Data loading","metadata":{}},{"cell_type":"code","source":"for dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n","metadata":{"execution":{"iopub.status.busy":"2023-11-01T10:15:11.227182Z","iopub.execute_input":"2023-11-01T10:15:11.227708Z","iopub.status.idle":"2023-11-01T10:15:11.239216Z","shell.execute_reply.started":"2023-11-01T10:15:11.227671Z","shell.execute_reply":"2023-11-01T10:15:11.237833Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"folder = '/kaggle/input/crypto-bull-prediction-challenge/'\n\ntrain = pd.read_csv(folder+'train.csv')\ntest = pd.read_csv(folder+'test.csv')\nsample_submission = pd.read_csv(folder+'sample_submission.csv')","metadata":{"execution":{"iopub.status.busy":"2023-11-01T10:15:51.177089Z","iopub.execute_input":"2023-11-01T10:15:51.177549Z","iopub.status.idle":"2023-11-01T10:16:01.052882Z","shell.execute_reply.started":"2023-11-01T10:15:51.177513Z","shell.execute_reply":"2023-11-01T10:16:01.051445Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# EDA\nExploratory Data Analysis","metadata":{}},{"cell_type":"code","source":"train","metadata":{"execution":{"iopub.status.busy":"2023-11-01T10:16:01.054843Z","iopub.execute_input":"2023-11-01T10:16:01.055209Z","iopub.status.idle":"2023-11-01T10:16:01.105780Z","shell.execute_reply.started":"2023-11-01T10:16:01.055179Z","shell.execute_reply":"2023-11-01T10:16:01.104357Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### date","metadata":{}},{"cell_type":"code","source":"train.groupby('symbol')['date'].min()","metadata":{"execution":{"iopub.status.busy":"2023-11-01T10:16:13.066326Z","iopub.execute_input":"2023-11-01T10:16:13.066731Z","iopub.status.idle":"2023-11-01T10:16:14.176061Z","shell.execute_reply.started":"2023-11-01T10:16:13.066701Z","shell.execute_reply":"2023-11-01T10:16:14.174862Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train.groupby('symbol')['date'].max()","metadata":{"execution":{"iopub.status.busy":"2023-11-01T10:16:14.178125Z","iopub.execute_input":"2023-11-01T10:16:14.178611Z","iopub.status.idle":"2023-11-01T10:16:15.273121Z","shell.execute_reply.started":"2023-11-01T10:16:14.178581Z","shell.execute_reply":"2023-11-01T10:16:15.271889Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train.groupby('symbol')['close'].count().sort_values()","metadata":{"execution":{"iopub.status.busy":"2023-11-01T10:16:15.275198Z","iopub.execute_input":"2023-11-01T10:16:15.275702Z","iopub.status.idle":"2023-11-01T10:16:15.649077Z","shell.execute_reply.started":"2023-11-01T10:16:15.275659Z","shell.execute_reply":"2023-11-01T10:16:15.647918Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test.groupby('symbol')['date'].min()","metadata":{"execution":{"iopub.status.busy":"2023-11-01T10:16:15.652373Z","iopub.execute_input":"2023-11-01T10:16:15.653412Z","iopub.status.idle":"2023-11-01T10:16:15.679791Z","shell.execute_reply.started":"2023-11-01T10:16:15.653366Z","shell.execute_reply":"2023-11-01T10:16:15.678632Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test.groupby('symbol')['date'].max()","metadata":{"execution":{"iopub.status.busy":"2023-11-01T10:16:15.681455Z","iopub.execute_input":"2023-11-01T10:16:15.681896Z","iopub.status.idle":"2023-11-01T10:16:15.709738Z","shell.execute_reply.started":"2023-11-01T10:16:15.681854Z","shell.execute_reply":"2023-11-01T10:16:15.708393Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test.groupby('symbol')['close'].count().sort_values()","metadata":{"execution":{"iopub.status.busy":"2023-11-01T10:16:15.711111Z","iopub.execute_input":"2023-11-01T10:16:15.711908Z","iopub.status.idle":"2023-11-01T10:16:15.727621Z","shell.execute_reply.started":"2023-11-01T10:16:15.711874Z","shell.execute_reply":"2023-11-01T10:16:15.726279Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## symbol","metadata":{}},{"cell_type":"code","source":"len(train['symbol'].unique())","metadata":{"execution":{"iopub.status.busy":"2023-11-01T10:16:15.729185Z","iopub.execute_input":"2023-11-01T10:16:15.729595Z","iopub.status.idle":"2023-11-01T10:16:16.037188Z","shell.execute_reply.started":"2023-11-01T10:16:15.729563Z","shell.execute_reply":"2023-11-01T10:16:16.036065Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"len(test['symbol'].unique())","metadata":{"execution":{"iopub.status.busy":"2023-11-01T10:16:16.038614Z","iopub.execute_input":"2023-11-01T10:16:16.038989Z","iopub.status.idle":"2023-11-01T10:16:16.050023Z","shell.execute_reply.started":"2023-11-01T10:16:16.038957Z","shell.execute_reply":"2023-11-01T10:16:16.048784Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Target","metadata":{}},{"cell_type":"code","source":"train.target.value_counts()","metadata":{"execution":{"iopub.status.busy":"2023-11-01T10:16:16.052705Z","iopub.execute_input":"2023-11-01T10:16:16.053076Z","iopub.status.idle":"2023-11-01T10:16:16.098190Z","shell.execute_reply.started":"2023-11-01T10:16:16.053045Z","shell.execute_reply":"2023-11-01T10:16:16.096818Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sample_submission","metadata":{"execution":{"iopub.status.busy":"2023-11-01T10:16:16.456865Z","iopub.execute_input":"2023-11-01T10:16:16.457317Z","iopub.status.idle":"2023-11-01T10:16:16.471639Z","shell.execute_reply.started":"2023-11-01T10:16:16.457263Z","shell.execute_reply":"2023-11-01T10:16:16.470316Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train.info()","metadata":{"execution":{"iopub.status.busy":"2023-11-01T10:16:17.026499Z","iopub.execute_input":"2023-11-01T10:16:17.027455Z","iopub.status.idle":"2023-11-01T10:16:17.047785Z","shell.execute_reply.started":"2023-11-01T10:16:17.027403Z","shell.execute_reply":"2023-11-01T10:16:17.046585Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test.info()","metadata":{"execution":{"iopub.status.busy":"2023-11-01T10:16:17.506729Z","iopub.execute_input":"2023-11-01T10:16:17.507183Z","iopub.status.idle":"2023-11-01T10:16:17.531089Z","shell.execute_reply.started":"2023-11-01T10:16:17.507147Z","shell.execute_reply":"2023-11-01T10:16:17.529521Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Data preprocessing","metadata":{}},{"cell_type":"code","source":"# IMPORTANT! for the correct processing of signs, we combine the train and the test into one dataset\ntrain['sample'] = 1 # note where we have train\ntest['sample'] = 0 # note where you have a test\n\ntrain['id'] = 0\ntest['target'] = 0 # in case you don't have the value \"target\", we will continue the display anyway, because it's just polar zeros\n\ndata = pd.concat([train, test]).reset_index(drop=True) # concat","metadata":{"execution":{"iopub.status.busy":"2023-11-01T10:16:18.926626Z","iopub.execute_input":"2023-11-01T10:16:18.927686Z","iopub.status.idle":"2023-11-01T10:16:19.695105Z","shell.execute_reply.started":"2023-11-01T10:16:18.927644Z","shell.execute_reply":"2023-11-01T10:16:19.693805Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"data","metadata":{"execution":{"iopub.status.busy":"2023-11-01T10:16:20.176424Z","iopub.execute_input":"2023-11-01T10:16:20.177700Z","iopub.status.idle":"2023-11-01T10:16:20.207875Z","shell.execute_reply.started":"2023-11-01T10:16:20.177647Z","shell.execute_reply":"2023-11-01T10:16:20.206549Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Generate new features\n> **Important Note on Time Series Data:**\n\n> Time series data has a natural temporal ordering, which makes it different from other types of data. When generating features or using libraries, it's paramount to ensure you don't inadvertently introduce future information into the past, a phenomenon known as \"data leakage\". Data leakage can result in overly optimistic performance metrics during model evaluation and can be a critical mistake in real-world scenarios.\n>\n> Always be meticulous about the indicators you incorporate and the libraries you leverage. Data leakage is a grave oversight in time series analysis and, if detected, will lead to disqualification from the competition.\n>\n> For a deeper understanding of data leakage in time series, refer to these articles:\n> - [How (not) to use Machine Learning for time series forecasting: Avoiding the pitfalls](https://towardsdatascience.com/how-not-to-use-machine-learning-for-time-series-forecasting-avoiding-the-pitfalls-19f9d7adf424)\n> - [Understanding Data Leakage in Machine Learning](https://machinelearningmastery.com/data-leakage-machine-learning/)\n","metadata":{}},{"cell_type":"code","source":"def gen_indicators(data, indicator_periods = [2, 3, 4, 6, 9, 12, 24, 48, 72, 96, 120, 168]):\n        stock_data_tech = data.copy()\n        stock_data_tech = stock_data_tech.sort_values(by='date')\n\n        fe_df = pd.DataFrame()\n\n        i=0\n\n        for symbol in tqdm(stock_data_tech.symbol.unique()):\n            data = stock_data_tech[stock_data_tech.symbol == symbol].copy()\n\n            data.reset_index(inplace=True, drop=True)\n            data.set_index('date', drop=False, inplace=True)\n\n            ################## Base pct ################################################################\n            for period in ([1,] + indicator_periods):\n                data[f'pct_close_{period}'] = data['close'].pct_change(period)\n            \n            ################### indicators ############################################################\n            # none period indicators\n            data.ta.pvol(append=True)\n            data.ta.bop(append=True)\n\n            for period in indicator_periods:\n\n                if period > 2:\n                    data.ta.willr(length=period, append=True)\n                    data.ta.stoch(length=period, append=True)\n                    data.ta.rsi(length=period, append=True)\n                    data.ta.roc(length=period, append=True)\n                    data.ta.mfi(length=period, append=True)\n                    # data.ta.massi(length=period, append=True)  # EMA data leak !!!\n\n            data.fillna(method=\"ffill\", inplace=True)\n            data.dropna(inplace=True)\n            #data.fillna(method=\"bfill\", inplace=True)\n            #data.fillna(0, inplace=True)\n            data.reset_index(inplace=True, drop=True)\n        \n            fe_df = pd.concat([fe_df, data], axis=0)\n        fe_df.reset_index(inplace=True, drop=True)\n        return fe_df","metadata":{"execution":{"iopub.status.busy":"2023-11-01T10:16:22.166551Z","iopub.execute_input":"2023-11-01T10:16:22.167004Z","iopub.status.idle":"2023-11-01T10:16:22.183975Z","shell.execute_reply.started":"2023-11-01T10:16:22.166969Z","shell.execute_reply":"2023-11-01T10:16:22.182603Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fe_data = gen_indicators(data)","metadata":{"execution":{"iopub.status.busy":"2023-11-01T10:16:22.666395Z","iopub.execute_input":"2023-11-01T10:16:22.666846Z","iopub.status.idle":"2023-11-01T10:24:06.152696Z","shell.execute_reply.started":"2023-11-01T10:16:22.666802Z","shell.execute_reply":"2023-11-01T10:24:06.151225Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Split","metadata":{}},{"cell_type":"code","source":"fe_train = fe_data.query('sample == 1').drop(['sample',], axis=1)\nfe_test = fe_data.query('sample == 0').drop(['sample',], axis=1)","metadata":{"execution":{"iopub.status.busy":"2023-11-01T10:24:06.155246Z","iopub.execute_input":"2023-11-01T10:24:06.155682Z","iopub.status.idle":"2023-11-01T10:24:11.996136Z","shell.execute_reply.started":"2023-11-01T10:24:06.155649Z","shell.execute_reply":"2023-11-01T10:24:11.994814Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fe_test = fe_test.sort_values(by=['id',])\n\nprint(fe_test[['date', 'symbol', 'trades', 'id', 'target',]])","metadata":{"execution":{"iopub.status.busy":"2023-11-01T10:24:11.997680Z","iopub.execute_input":"2023-11-01T10:24:11.998063Z","iopub.status.idle":"2023-11-01T10:24:12.060891Z","shell.execute_reply.started":"2023-11-01T10:24:11.998031Z","shell.execute_reply":"2023-11-01T10:24:12.059776Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"X_train = fe_train.drop(['open', 'high', 'low', 'close', 'volume', 'trades', 'symbol', 'date', 'id', 'target', 'close_unixtime'], axis=1)\ny_train = fe_train.target.values\n\nX_test = fe_test.drop(['open', 'high', 'low', 'close', 'volume', 'trades', 'symbol', 'date', 'id', 'target', 'close_unixtime'], axis=1)","metadata":{"execution":{"iopub.status.busy":"2023-11-01T10:24:12.063947Z","iopub.execute_input":"2023-11-01T10:24:12.064427Z","iopub.status.idle":"2023-11-01T10:24:13.730167Z","shell.execute_reply.started":"2023-11-01T10:24:12.064386Z","shell.execute_reply":"2023-11-01T10:24:13.728834Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"X_test","metadata":{"execution":{"iopub.status.busy":"2023-11-01T10:24:13.732225Z","iopub.execute_input":"2023-11-01T10:24:13.732818Z","iopub.status.idle":"2023-11-01T10:24:13.781005Z","shell.execute_reply.started":"2023-11-01T10:24:13.732785Z","shell.execute_reply":"2023-11-01T10:24:13.779666Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Model","metadata":{}},{"cell_type":"code","source":"model = CatBoostClassifier(verbose=100, random_seed=RANDOM_SEED,)\nmodel.fit(X_train, y_train,)","metadata":{"execution":{"iopub.status.busy":"2023-11-01T10:24:13.782878Z","iopub.execute_input":"2023-11-01T10:24:13.783235Z","iopub.status.idle":"2023-11-01T10:48:43.067926Z","shell.execute_reply.started":"2023-11-01T10:24:13.783205Z","shell.execute_reply":"2023-11-01T10:48:43.066748Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.save_model('catboost_baseline.model')","metadata":{"execution":{"iopub.status.busy":"2023-11-01T10:48:43.069652Z","iopub.execute_input":"2023-11-01T10:48:43.070103Z","iopub.status.idle":"2023-11-01T10:48:43.091476Z","shell.execute_reply.started":"2023-11-01T10:48:43.070058Z","shell.execute_reply":"2023-11-01T10:48:43.090081Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### feature importances","metadata":{}},{"cell_type":"code","source":"feature_importances = model.get_feature_importance()\n\n# Создаем DataFrame для удобства\nfeatures_df = pd.DataFrame({\n    'Feature': X_train.columns,\n    'Importance': feature_importances\n})\n\n# Сортируем по убыванию важности\nsorted_features_df = features_df.sort_values(by='Importance', ascending=False).head(25)\n\n# Рисуем график\nplt.figure(figsize=(12, 10))\nsns.barplot(data=sorted_features_df, x='Importance', y='Feature', palette='viridis')\nplt.title('Top 25 Feature Importances')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-11-01T10:48:43.093560Z","iopub.execute_input":"2023-11-01T10:48:43.094085Z","iopub.status.idle":"2023-11-01T10:48:43.165694Z","shell.execute_reply.started":"2023-11-01T10:48:43.094041Z","shell.execute_reply":"2023-11-01T10:48:43.163146Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## submission","metadata":{}},{"cell_type":"code","source":"predict_proba = model.predict_proba(X_test)[:, 1]","metadata":{"execution":{"iopub.status.busy":"2023-11-01T10:48:43.167412Z","iopub.status.idle":"2023-11-01T10:48:43.167892Z","shell.execute_reply.started":"2023-11-01T10:48:43.167662Z","shell.execute_reply":"2023-11-01T10:48:43.167681Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"len(predict_proba)","metadata":{"execution":{"iopub.status.busy":"2023-11-01T10:48:43.169189Z","iopub.status.idle":"2023-11-01T10:48:43.169632Z","shell.execute_reply.started":"2023-11-01T10:48:43.169414Z","shell.execute_reply":"2023-11-01T10:48:43.169433Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"len(sample_submission)","metadata":{"execution":{"iopub.status.busy":"2023-11-01T10:48:43.170556Z","iopub.status.idle":"2023-11-01T10:48:43.170950Z","shell.execute_reply.started":"2023-11-01T10:48:43.170763Z","shell.execute_reply":"2023-11-01T10:48:43.170781Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sample_submission['target'] = predict_proba","metadata":{"execution":{"iopub.status.busy":"2023-11-01T10:48:43.171898Z","iopub.status.idle":"2023-11-01T10:48:43.172277Z","shell.execute_reply.started":"2023-11-01T10:48:43.172085Z","shell.execute_reply":"2023-11-01T10:48:43.172103Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sample_submission.to_csv('submission.csv', index=False)","metadata":{"execution":{"iopub.status.busy":"2023-11-01T10:48:43.173166Z","iopub.status.idle":"2023-11-01T10:48:43.173548Z","shell.execute_reply.started":"2023-11-01T10:48:43.173361Z","shell.execute_reply":"2023-11-01T10:48:43.173379Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sample_submission['target'].hist(bins=250, edgecolor='black')","metadata":{"execution":{"iopub.status.busy":"2023-11-01T10:48:43.175078Z","iopub.status.idle":"2023-11-01T10:48:43.175499Z","shell.execute_reply.started":"2023-11-01T10:48:43.175285Z","shell.execute_reply":"2023-11-01T10:48:43.175320Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# What's next?\nЧто можно сделать, чтоб улучшить результат:\n\n- Добавить крассвалидацию (cross-validation)\n- Очистить данные\n- Сгенерировать новые признаки\n- Сделать отбор признаков\n- Перебрать различные модели\n- Посмотреть где модель ошибается и как ей можно помочь\n- Подобрать гиперпараметры\n\nВ общем, процесс творческий и весьма увлекательный! Удачи в соревновании!","metadata":{}},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}