{"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":"# 🪙Crypto 📈forecasting with Lightning⚡Flash\n\n[Flash](https://lightning-flash.readthedocs.io/en/stable) makes complex AI recipes for over 15 tasks across 7 data domains accessible to all.\n\nIn a nutshell, Flash is the production grade research framework you always dreamed of but didn't have time to build.","metadata":{}},{"cell_type":"code","source":"# ! pip install -q lightning-flash[tabular]\n! pip install -q 'https://github.com/PyTorchLightning/lightning-flash/archive/refs/heads/master.zip#egg=lightning-flash[tabular]'\n! pip install -q mplfinance\n! pip install -q --upgrade pandas --force-reinstall\n! pip list | grep -E \"lightning|torch|finance|crypto\"","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","_kg_hide-output":true,"execution":{"iopub.status.busy":"2021-11-14T12:38:29.879677Z","iopub.execute_input":"2021-11-14T12:38:29.879996Z","iopub.status.idle":"2021-11-14T12:39:45.666076Z","shell.execute_reply.started":"2021-11-14T12:38:29.879907Z","shell.execute_reply":"2021-11-14T12:39:45.665257Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Data exolorations & preparation\n\nChecking the input data and pairing with Crypto names","metadata":{}},{"cell_type":"code","source":"%reload_ext autoreload\n%autoreload 2\n\nimport pandas as pd\n\nTAB_COLUMN_TYPES = {\n    'Asset_ID': 'int8',\n    'Count': 'int32',\n    'row_id': 'int32',\n    'Count': 'int32',\n    'Open': 'float64',\n    'High': 'float64',\n    'Low': 'float64',\n    'Close': 'float64',\n    'Volume': 'float64',\n    'VWAP': 'float64',\n}\ndf_train = pd.read_csv(\"/kaggle/input/g-research-crypto-forecasting/train.csv\", low_memory=False, dtype=TAB_COLUMN_TYPES)\ndisplay(df_train.head())","metadata":{"execution":{"iopub.status.busy":"2021-11-14T12:39:45.667959Z","iopub.execute_input":"2021-11-14T12:39:45.668270Z","iopub.status.idle":"2021-11-14T12:40:43.122565Z","shell.execute_reply.started":"2021-11-14T12:39:45.668233Z","shell.execute_reply":"2021-11-14T12:40:43.121879Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Linking with coins\n\nShow how naby data points we heva pear crypto","metadata":{}},{"cell_type":"code","source":"df_counts = df_train.groupby(\"Asset_ID\").size()\ndf_counts.plot.bar(grid=True)","metadata":{"execution":{"iopub.status.busy":"2021-11-14T12:40:43.123668Z","iopub.execute_input":"2021-11-14T12:40:43.124137Z","iopub.status.idle":"2021-11-14T12:40:43.935989Z","shell.execute_reply.started":"2021-11-14T12:40:43.124100Z","shell.execute_reply":"2021-11-14T12:40:43.935285Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_asset_details = pd.read_csv(\"/kaggle/input/g-research-crypto-forecasting/asset_details.csv\")\ndisplay(df_asset_details.T)","metadata":{"execution":{"iopub.status.busy":"2021-11-14T12:40:43.938008Z","iopub.execute_input":"2021-11-14T12:40:43.938722Z","iopub.status.idle":"2021-11-14T12:40:44.009128Z","shell.execute_reply.started":"2021-11-14T12:40:43.938678Z","shell.execute_reply":"2021-11-14T12:40:44.008099Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"mapping = dict(df_asset_details[['Asset_ID', 'Asset_Name']].values)\ndf_train[\"Asset_Name\"] = df_train[\"Asset_ID\"].map(mapping)","metadata":{"execution":{"iopub.status.busy":"2021-11-14T12:40:44.013363Z","iopub.execute_input":"2021-11-14T12:40:44.015751Z","iopub.status.idle":"2021-11-14T12:40:44.977124Z","shell.execute_reply.started":"2021-11-14T12:40:44.015716Z","shell.execute_reply":"2021-11-14T12:40:44.976400Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Finantial timeseries\n\nshowing short tail of each coin with `mplfinance` package","metadata":{}},{"cell_type":"code","source":"import mplfinance as mpf\n\nfor n, dfg in df_train.groupby(\"Asset_Name\"):\n    dfg['timestamp'] = pd.to_datetime(dfg['timestamp'])\n    dfg.set_index(\"timestamp\", inplace=True)\n    mpf.plot(\n        dfg[-300:], # the dataframe containing the OHLC (Open, High, Low and Close) data\n        type='candle', # use candlesticks \n        volume=True, # also show the volume\n        mav=(3, 6, 9), # use three different moving averages\n        figsize=(14, 2), # set the ratio of the figure\n        style='yahoo',\n        title=n,\n    )","metadata":{"execution":{"iopub.status.busy":"2021-11-14T12:40:44.981750Z","iopub.execute_input":"2021-11-14T12:40:44.982561Z","iopub.status.idle":"2021-11-14T12:41:11.111355Z","shell.execute_reply.started":"2021-11-14T12:40:44.982507Z","shell.execute_reply":"2021-11-14T12:41:11.110635Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Prune\n\nlimit the amout dues to limited computing resources","metadata":{}},{"cell_type":"code","source":"# df_train_small = df_train[df_train[\"Asset_ID\"].isin([0, 1, 2])]\ndf_train_small = df_train[df_train[\"Asset_ID\"] == 0].interpolate()","metadata":{"execution":{"iopub.status.busy":"2021-11-14T12:41:11.112660Z","iopub.execute_input":"2021-11-14T12:41:11.113042Z","iopub.status.idle":"2021-11-14T12:41:11.608412Z","shell.execute_reply.started":"2021-11-14T12:41:11.113007Z","shell.execute_reply":"2021-11-14T12:41:11.607604Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Training with Flash Lightning\n\nSee the forecasting docs: https://lightning-flash.readthedocs.io/en/stable/reference/tabular_forecasting.html","metadata":{}},{"cell_type":"code","source":"import flash\nimport pandas as pd\nimport torch\nfrom flash.tabular.forecasting import TabularForecaster, TabularForecastingData\nfrom pytorch_forecasting.data import NaNLabelEncoder\nfrom pytorch_forecasting.data.examples import generate_ar_data","metadata":{"execution":{"iopub.status.busy":"2021-11-14T12:41:11.609732Z","iopub.execute_input":"2021-11-14T12:41:11.610014Z","iopub.status.idle":"2021-11-14T12:41:19.936618Z","shell.execute_reply.started":"2021-11-14T12:41:11.609975Z","shell.execute_reply":"2021-11-14T12:41:19.935842Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### 1. Create the DataModule\n\nExample based on this tutorial: https://pytorch-forecasting.readthedocs.io/en/latest/tutorials/ar.html","metadata":{}},{"cell_type":"code","source":"datamodule = TabularForecastingData.from_data_frame(\n    time_idx=\"timestamp\",\n    target=\"Target\",\n    # categorical_encoders={\"series\": NaNLabelEncoder().fit(data.series)},\n    group_ids=[\"Asset_ID\"],\n    time_varying_unknown_reals=[\"Target\"],\n    allow_missing_timesteps=True,\n    max_encoder_length=60,\n    max_prediction_length=1,\n    train_data_frame=df_train_small,\n    val_data_frame=df_train_small,\n    batch_size=512,\n    num_workers=4,\n)","metadata":{"execution":{"iopub.status.busy":"2021-11-14T12:41:19.938116Z","iopub.execute_input":"2021-11-14T12:41:19.938372Z","iopub.status.idle":"2021-11-14T12:41:36.030623Z","shell.execute_reply.started":"2021-11-14T12:41:19.938337Z","shell.execute_reply":"2021-11-14T12:41:36.029871Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### 2. Build the task","metadata":{}},{"cell_type":"code","source":"model = TabularForecaster(\n    datamodule.parameters,\n    backbone=\"deep_ar\",\n    # backbone_kwargs={\"widths\": [32, 512], \"backcast_loss_ratio\": 0.1},\n)","metadata":{"execution":{"iopub.status.busy":"2021-11-14T12:41:36.033272Z","iopub.execute_input":"2021-11-14T12:41:36.033546Z","iopub.status.idle":"2021-11-14T12:41:36.142137Z","shell.execute_reply.started":"2021-11-14T12:41:36.033509Z","shell.execute_reply":"2021-11-14T12:41:36.141493Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### 3. Create the trainer and train the model","metadata":{}},{"cell_type":"code","source":"import torch\nfrom pytorch_lightning.loggers import CSVLogger\nfrom pytorch_lightning.callbacks import StochasticWeightAveraging\n\nswa = StochasticWeightAveraging(swa_epoch_start=0.6)\nlogger = CSVLogger(save_dir='logs/')\ntrainer = flash.Trainer(\n    max_epochs=10,\n    logger=logger,\n    gpus=torch.cuda.device_count(),\n    gradient_clip_val=0.01,\n)\n\n# ==============================\n\ntrainer.tune(model, datamodule=datamodule, lr_find_kwargs=dict(min_lr=2e-5, max_lr=1, num_training=65),)\nprint(f\"Learning Rate: {model.learning_rate}\")\n\n# ==============================\n\ntrainer.fit(model, datamodule=datamodule)","metadata":{"_kg_hide-output":true,"execution":{"iopub.status.busy":"2021-11-14T12:41:36.143399Z","iopub.execute_input":"2021-11-14T12:41:36.144043Z","iopub.status.idle":"2021-11-14T13:07:34.123130Z","shell.execute_reply.started":"2021-11-14T12:41:36.144004Z","shell.execute_reply":"2021-11-14T13:07:34.122385Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nimport seaborn as sns\nsns.set()\n\nmetrics = pd.read_csv(f'{trainer.logger.log_dir}/metrics.csv')\nmetrics = metrics[[c for c in metrics.columns if \"_step\" not in c]]\ndel metrics[\"step\"]\nmetrics.set_index(\"epoch\", inplace=True)\ndisplay(metrics.dropna(axis=1, how=\"all\").head())\ng = sns.relplot(data=metrics, kind=\"line\")\ng.set(yscale=\"log\")\nplt.gcf().set_size_inches(15, 5)","metadata":{"execution":{"iopub.status.busy":"2021-11-14T13:07:34.124949Z","iopub.execute_input":"2021-11-14T13:07:34.125251Z","iopub.status.idle":"2021-11-14T13:07:35.162994Z","shell.execute_reply.started":"2021-11-14T13:07:34.125213Z","shell.execute_reply":"2021-11-14T13:07:35.162247Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### 4. Generate predictions","metadata":{}},{"cell_type":"code","source":"outputs = model.predict(df_train_small[-1000:])\nprint(outputs[0].keys())\npredictions = [o['prediction'] for o in outputs]\nprint(predictions)","metadata":{"execution":{"iopub.status.busy":"2021-11-14T13:07:35.164339Z","iopub.execute_input":"2021-11-14T13:07:35.164583Z","iopub.status.idle":"2021-11-14T13:07:35.354384Z","shell.execute_reply.started":"2021-11-14T13:07:35.164550Z","shell.execute_reply":"2021-11-14T13:07:35.353675Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import gresearch_crypto\nfrom pprint import pprint\nfrom tqdm.auto import tqdm\n\nenv = gresearch_crypto.make_env()   # initialize the environment\niter_test = env.iter_test()\n\nfor i, (df_test, df_pred) in tqdm(enumerate(iter_test)):\n    display(df_test.head())\n    df_test_small = df_test[df_test[\"Asset_ID\"] == 0]\n    df_test_small['Target'] = [None]\n    # TODO\n#     out = model.predict(df_test_small)\n#     preds = zip(df_test_small[row_id], out['prediction'])\n#     pprint(preds)\n    env.predict(df_pred)   # register your predictions\n    break","metadata":{"execution":{"iopub.status.busy":"2021-11-14T13:07:35.355682Z","iopub.execute_input":"2021-11-14T13:07:35.356446Z","iopub.status.idle":"2021-11-14T13:07:35.955679Z","shell.execute_reply.started":"2021-11-14T13:07:35.356407Z","shell.execute_reply":"2021-11-14T13:07:35.954196Z"},"trusted":true},"execution_count":null,"outputs":[]}]}