{"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":"![JGFU](data:image/jpeg;base64,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)","metadata":{}},{"cell_type":"markdown","source":" <a id=\"1\"></a>\n# <p style=\"background-color:#627D78;font-family:newtimeroman;color:#D5CABD;font-size:150%;text-align:center;border-radius:20px 60px;\">Importing Libraries</p>","metadata":{}},{"cell_type":"code","source":"import pandas as pd \nimport numpy as np\nimport random\nimport plotly.express as px\nimport plotly.offline as py\nimport gc\nfrom sklearn.preprocessing import RobustScaler,StandardScaler\nfrom sklearn.model_selection import StratifiedKFold\nfrom sklearn import metrics\nfrom lightgbm import LGBMClassifier\nfrom sklearn.linear_model import LogisticRegression\nfrom sklearn.metrics import roc_curve,RocCurveDisplay,ConfusionMatrixDisplay,confusion_matrix,roc_auc_score,accuracy_score\n\nimport plotly.express as px\nimport plotly.graph_objects as go\nfrom plotly.subplots import make_subplots\nfrom sklearn import preprocessing\nimport seaborn as sns\n\nimport matplotlib.pyplot as plt\n%matplotlib inline","metadata":{"execution":{"iopub.status.busy":"2021-11-10T05:41:37.665674Z","iopub.execute_input":"2021-11-10T05:41:37.666048Z","iopub.status.idle":"2021-11-10T05:41:40.373621Z","shell.execute_reply.started":"2021-11-10T05:41:37.665959Z","shell.execute_reply":"2021-11-10T05:41:40.372654Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":" <a id=\"1\"></a>\n# <p style=\"background-color:#627D78;font-family:newtimeroman;color:#D5CABD;font-size:150%;text-align:center;border-radius:20px 60px;\">Reading Data </p>","metadata":{}},{"cell_type":"code","source":"train = pd.read_csv('../input/g-research-crypto-forecasting/train.csv') \ntest = pd.read_csv('../input/g-research-crypto-forecasting/example_test.csv') \nsub = pd.read_csv('../input/g-research-crypto-forecasting/example_sample_submission.csv') \nasset_details = pd.read_csv('../input/g-research-crypto-forecasting/asset_details.csv')  ","metadata":{"execution":{"iopub.status.busy":"2021-11-10T05:41:40.375095Z","iopub.execute_input":"2021-11-10T05:41:40.375314Z","iopub.status.idle":"2021-11-10T05:41:41.330399Z","shell.execute_reply.started":"2021-11-10T05:41:40.375287Z","shell.execute_reply":"2021-11-10T05:41:41.326903Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id=\"1\"></a>\n# <p style=\"background-color:#627D78;font-family:newtimeroman;color:#D5CABD;font-size:150%;text-align:center;border-radius:20px 60px;\">Data Exploration</p>","metadata":{}},{"cell_type":"code","source":"train.head(10)","metadata":{"execution":{"iopub.status.busy":"2021-11-10T05:41:41.331174Z","iopub.status.idle":"2021-11-10T05:41:41.331516Z","shell.execute_reply.started":"2021-11-10T05:41:41.331342Z","shell.execute_reply":"2021-11-10T05:41:41.331359Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train.info()","metadata":{"execution":{"iopub.status.busy":"2021-11-10T05:41:41.333187Z","iopub.status.idle":"2021-11-10T05:41:41.333661Z","shell.execute_reply.started":"2021-11-10T05:41:41.333461Z","shell.execute_reply":"2021-11-10T05:41:41.333481Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train.shape","metadata":{"execution":{"iopub.status.busy":"2021-11-10T05:41:41.334877Z","iopub.status.idle":"2021-11-10T05:41:41.335205Z","shell.execute_reply.started":"2021-11-10T05:41:41.335031Z","shell.execute_reply":"2021-11-10T05:41:41.335047Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train.isna().sum()","metadata":{"execution":{"iopub.status.busy":"2021-11-10T05:41:41.336227Z","iopub.status.idle":"2021-11-10T05:41:41.33653Z","shell.execute_reply.started":"2021-11-10T05:41:41.336365Z","shell.execute_reply":"2021-11-10T05:41:41.336381Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train['Target'] = train['Target'].fillna(0)","metadata":{"execution":{"iopub.status.busy":"2021-11-10T05:41:41.337612Z","iopub.status.idle":"2021-11-10T05:41:41.337966Z","shell.execute_reply.started":"2021-11-10T05:41:41.337792Z","shell.execute_reply":"2021-11-10T05:41:41.337815Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train['VWAP'] = train['VWAP'].fillna(0)","metadata":{"execution":{"iopub.status.busy":"2021-11-10T05:41:41.338957Z","iopub.status.idle":"2021-11-10T05:41:41.339275Z","shell.execute_reply.started":"2021-11-10T05:41:41.339104Z","shell.execute_reply":"2021-11-10T05:41:41.339127Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train.isna().sum()","metadata":{"execution":{"iopub.status.busy":"2021-11-10T05:41:41.340567Z","iopub.status.idle":"2021-11-10T05:41:41.340924Z","shell.execute_reply.started":"2021-11-10T05:41:41.340753Z","shell.execute_reply":"2021-11-10T05:41:41.340775Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train.describe()","metadata":{"execution":{"iopub.status.busy":"2021-11-10T05:41:41.343205Z","iopub.status.idle":"2021-11-10T05:41:41.343737Z","shell.execute_reply.started":"2021-11-10T05:41:41.343485Z","shell.execute_reply":"2021-11-10T05:41:41.343516Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Finding correlation\nplt.figure(figsize=(10,5))\nax=sns.heatmap(train.corr(),cmap=\"Set1\",cbar=True,yticklabels=True,annot=True)\nbottom,top=ax.get_ylim()\nax.set_ylim(bottom + 0.5,top -0.5)","metadata":{"execution":{"iopub.status.busy":"2021-11-10T05:41:41.344555Z","iopub.status.idle":"2021-11-10T05:41:41.345455Z","shell.execute_reply.started":"2021-11-10T05:41:41.345237Z","shell.execute_reply":"2021-11-10T05:41:41.345265Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sns.barplot(\"High\",\"Low\",data=train.head(10),orient=\"v\")","metadata":{"execution":{"iopub.status.busy":"2021-11-10T05:41:41.346426Z","iopub.status.idle":"2021-11-10T05:41:41.346796Z","shell.execute_reply.started":"2021-11-10T05:41:41.346597Z","shell.execute_reply":"2021-11-10T05:41:41.346618Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for my_id in range(0,14):\n    df_select =train[train.Asset_ID==my_id]\n    plt.figure(figsize=(14,4))\n    plt.scatter(df_select.timestamp, df_select.VWAP, s=1)\n    my_title='Asset ID: ' + str(my_id) + ' - ' + asset_details[asset_details.Asset_ID==my_id].reset_index().Asset_Name[0]\n    plt.title(my_title)\n    plt.grid()\n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2021-11-10T05:41:41.348478Z","iopub.status.idle":"2021-11-10T05:41:41.349006Z","shell.execute_reply.started":"2021-11-10T05:41:41.348803Z","shell.execute_reply":"2021-11-10T05:41:41.348829Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_asset_details = asset_details.sort_values(\"Asset_ID\")\ndf_asset_details","metadata":{"execution":{"iopub.status.busy":"2021-11-10T05:41:41.349997Z","iopub.status.idle":"2021-11-10T05:41:41.350795Z","shell.execute_reply.started":"2021-11-10T05:41:41.350544Z","shell.execute_reply":"2021-11-10T05:41:41.350572Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sns.scatterplot(df_asset_details['Asset_ID'], df_asset_details['Weight'], hue = df_asset_details['Asset_Name'])","metadata":{"execution":{"iopub.status.busy":"2021-11-10T05:41:41.352089Z","iopub.status.idle":"2021-11-10T05:41:41.352419Z","shell.execute_reply.started":"2021-11-10T05:41:41.352246Z","shell.execute_reply":"2021-11-10T05:41:41.352268Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"px.scatter(df_asset_details, x=\"Weight\", y=\"Asset_ID\", color=\"Asset_Name\")","metadata":{"execution":{"iopub.status.busy":"2021-11-10T05:41:41.354178Z","iopub.status.idle":"2021-11-10T05:41:41.354536Z","shell.execute_reply.started":"2021-11-10T05:41:41.354342Z","shell.execute_reply":"2021-11-10T05:41:41.354367Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"px.sunburst(df_asset_details, path=['Weight','Asset_Name'], values='Asset_ID')\n","metadata":{"execution":{"iopub.status.busy":"2021-11-10T05:41:41.355754Z","iopub.status.idle":"2021-11-10T05:41:41.356107Z","shell.execute_reply.started":"2021-11-10T05:41:41.355926Z","shell.execute_reply":"2021-11-10T05:41:41.355951Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"px.histogram(df_asset_details, x=\"Weight\", y=\"Asset_ID\", color=\"Asset_Name\")","metadata":{"execution":{"iopub.status.busy":"2021-11-10T05:41:41.357328Z","iopub.status.idle":"2021-11-10T05:41:41.357705Z","shell.execute_reply.started":"2021-11-10T05:41:41.357495Z","shell.execute_reply":"2021-11-10T05:41:41.35752Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import pandas as pd\nimport plotly.graph_objects as go\ncrypto_df = pd.read_csv(\"../input/g-research-crypto-forecasting/\" + 'train.csv')\nbtc = crypto_df[crypto_df[\"Asset_ID\"]==1].set_index(\"timestamp\")\nbtc_mini = btc.iloc[-200:]\nfig = go.Figure(data=[go.Candlestick(x=btc_mini.index, open=btc_mini['Open'], high=btc_mini['High'], low=btc_mini['Low'], close=btc_mini['Close'])])\nfig.show()","metadata":{"execution":{"iopub.status.busy":"2021-11-10T05:41:41.358942Z","iopub.status.idle":"2021-11-10T05:41:41.359289Z","shell.execute_reply.started":"2021-11-10T05:41:41.359109Z","shell.execute_reply":"2021-11-10T05:41:41.359133Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"DEVICE = \"TPU\" #or \"GPU\"\n\n# USE DIFFERENT SEED FOR DIFFERENT STRATIFIED KFOLD\nSEED = 42\n\n# NUMBER OF FOLDS. \nFOLDS = 5\n# GAP FROM SPLIT TO SPLIT [SEE DETAILS ABOUT THE CV]\nGROUP_GAP = 31\n\n# INCLUDE OLD COMP DATA? YES=1 NO=0\nINC2021 = 0\nINC2020 = 1\nINC2019 = 0\nINC2018 = 0\nINC2017 = 0\nINCCOMP = 1\nINCSUPP = 0\n\n# BATCH SIZE AND EPOCHS\nBATCH_SIZES = [2048] * FOLDS\nEPOCHS = [1] * FOLDS\n\n# WHICH NETWORK ARCHITECTURE TO USE?\nDEPTH_NETS = [2, 2, 2, 2, 2] \nWIDTH_NETS = [64, 64, 64, 64, 64]\n\n# WEIGHTS FOR FOLD MODELS WHEN PREDICTING TEST\nWGTS = [1 / FOLDS] * FOLDS","metadata":{"execution":{"iopub.status.busy":"2021-11-10T05:41:41.360453Z","iopub.status.idle":"2021-11-10T05:41:41.360831Z","shell.execute_reply.started":"2021-11-10T05:41:41.360616Z","shell.execute_reply":"2021-11-10T05:41:41.360662Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\nimport traceback\nimport gresearch_crypto\nimport tensorflow as tf\nimport pandas as pd, numpy as np\nimport tensorflow.keras.backend as K\nfrom sklearn.model_selection import KFold\nfrom sklearn.metrics import mean_squared_error","metadata":{"execution":{"iopub.status.busy":"2021-11-10T05:41:41.362002Z","iopub.status.idle":"2021-11-10T05:41:41.362346Z","shell.execute_reply.started":"2021-11-10T05:41:41.362162Z","shell.execute_reply":"2021-11-10T05:41:41.362187Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"if DEVICE == \"TPU\":\n    print(\"connecting to TPU...\")\n    try:\n        tpu = tf.distribute.cluster_resolver.TPUClusterResolver()\n        print('Running on TPU ', tpu.master())\n    except ValueError:\n        tpu = None\n    if tpu:\n        try:\n            print(\"initializing  TPU ...\")\n            tf.config.experimental_connect_to_cluster(tpu)\n            tf.tpu.experimental.initialize_tpu_system(tpu)\n            strategy = tf.distribute.experimental.TPUStrategy(tpu)\n            print(\"TPU initialized\")\n        except: print(\"failed to initialize TPU\")\n    else: DEVICE = \"GPU\"\n\nif DEVICE != \"TPU\": strategy = tf.distribute.get_strategy()\nif DEVICE == \"GPU\": print(\"Num GPUs Available: \", len(tf.config.experimental.list_physical_devices('GPU')))\nAUTO     = tf.data.experimental.AUTOTUNE\nREPLICAS = strategy.num_replicas_in_sync","metadata":{"execution":{"iopub.status.busy":"2021-11-10T05:41:41.363633Z","iopub.status.idle":"2021-11-10T05:41:41.364003Z","shell.execute_reply.started":"2021-11-10T05:41:41.363819Z","shell.execute_reply":"2021-11-10T05:41:41.363842Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"orig_df_train = pd.read_csv('/kaggle/input/g-research-crypto-forecasting/train.csv')\nsupp_df_train = pd.read_csv('../input/g-research-crypto-forecasting/supplemental_train.csv')\ndf_asset_details = pd.read_csv('/kaggle/input/g-research-crypto-forecasting/asset_details.csv').sort_values(\"Asset_ID\")\n\nextra_data_files = {\n                        0: '../input/cryptocurrency-extra-data-binance-coin',\n                        2: '../input/cryptocurrency-extra-data-bitcoin-cash',\n                        1: '../input/cryptocurrency-extra-data-bitcoin',\n                        3: '../input/cryptocurrency-extra-data-cardano',\n                        4: '../input/cryptocurrency-extra-data-dogecoin',                        \n                        5: '../input/cryptocurrency-extra-data-eos-io',\n                        6: '../input/cryptocurrency-extra-data-ethereum',\n                        7: '../input/cryptocurrency-extra-data-ethereum-classic', \n                        8: '../input/cryptocurrency-extra-data-iota',\n                        9: '../input/cryptocurrency-extra-data-litecoin',\n                        11: '../input/cryptocurrency-extra-data-monero',\n                        10: '../input/cryptocurrency-extra-data-maker',\n                        12: '../input/cryptocurrency-extra-data-stellar',\n                        13: '../input/cryptocurrency-extra-data-tron'\n                   }\n\ndef load_training_data_for_asset(asset_id):\n    dfs = []        \n    if INCCOMP: dfs.append(orig_df_train[orig_df_train[\"Asset_ID\"] == asset_id].copy())\n    if INCSUPP: dfs.append(supp_df_train[supp_df_train[\"Asset_ID\"] == asset_id].copy())    \n    if INC2017 and os.path.exists(extra_data_files[asset_id] + '/full_data__' + str(asset_id) + '__' + str(2017) + '.csv'): dfs.append(pd.read_csv(extra_data_files[asset_id] + '/full_data__' + str(asset_id) + '__' + str(2017) + '.csv'))\n    if INC2018 and os.path.exists(extra_data_files[asset_id] + '/full_data__' + str(asset_id) + '__' + str(2018) + '.csv'): dfs.append(pd.read_csv(extra_data_files[asset_id] + '/full_data__' + str(asset_id) + '__' + str(2018) + '.csv'))\n    if INC2019 and os.path.exists(extra_data_files[asset_id] + '/full_data__' + str(asset_id) + '__' + str(2019) + '.csv'): dfs.append(pd.read_csv(extra_data_files[asset_id] + '/full_data__' + str(asset_id) + '__' + str(2019) + '.csv'))\n    if INC2020 and os.path.exists(extra_data_files[asset_id] + '/full_data__' + str(asset_id) + '__' + str(2020) + '.csv'): dfs.append(pd.read_csv(extra_data_files[asset_id] + '/full_data__' + str(asset_id) + '__' + str(2020) + '.csv'))\n    if INC2021 and os.path.exists(extra_data_files[asset_id] + '/full_data__' + str(asset_id) + '__' + str(2021) + '.csv'): dfs.append(pd.read_csv(extra_data_files[asset_id] + '/full_data__' + str(asset_id) + '__' + str(2021) + '.csv'))\n    df = pd.concat(dfs, axis = 0) if len(dfs) > 1 else dfs[0]\n    df['date'] = pd.to_datetime(df['timestamp'], unit = 's')        \n    df = df.sort_values('date')\n    return df","metadata":{"execution":{"iopub.status.busy":"2021-11-10T05:41:41.365469Z","iopub.status.idle":"2021-11-10T05:41:41.365841Z","shell.execute_reply.started":"2021-11-10T05:41:41.365657Z","shell.execute_reply":"2021-11-10T05:41:41.365681Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Two features from the competition tutorial\ndef upper_shadow(df): return df['High'] - np.maximum(df['Close'], df['Open'])\ndef lower_shadow(df): return np.minimum(df['Close'], df['Open']) - df['Low']\n\n# A utility function to build features from the original df\ndef get_features(df):\n    df_feat = df[['Count', 'Open', 'High', 'Low', 'Close', 'Volume', 'VWAP']].copy()\n    df_feat['upper_Shadow'] = upper_shadow(df_feat)\n    df_feat['lower_Shadow'] = lower_shadow(df_feat)\n    df_feat[\"high_div_low\"] = df_feat[\"High\"] / df_feat[\"Low\"]\n    df_feat[\"open_sub_close\"] = df_feat[\"Open\"] - df_feat[\"Close\"]\n    return df_feat","metadata":{"execution":{"iopub.status.busy":"2021-11-10T05:41:41.366989Z","iopub.status.idle":"2021-11-10T05:41:41.367341Z","shell.execute_reply.started":"2021-11-10T05:41:41.367158Z","shell.execute_reply":"2021-11-10T05:41:41.367181Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def build_model(fold, dim = 128):\n    inp = tf.keras.layers.Input(shape=(dim))\n    x = inp\n    \n    for i in range(DEPTH_NETS[fold]):\n        x = tf.keras.layers.Dense(WIDTH_NETS[fold])(x)\n        x = tf.keras.layers.BatchNormalization()(x)\n        x = tf.keras.layers.Activation('swish')(x)\n\n    x = tf.keras.layers.Dense(1, activation='linear')(x)\n    model = tf.keras.Model(inputs = inp, outputs = x)\n    opt = tf.keras.optimizers.Adam(learning_rate = 0.001)\n    model.compile(optimizer=opt, loss='mse')\n    return model","metadata":{"execution":{"iopub.status.busy":"2021-11-10T05:41:41.368756Z","iopub.status.idle":"2021-11-10T05:41:41.36911Z","shell.execute_reply.started":"2021-11-10T05:41:41.368933Z","shell.execute_reply":"2021-11-10T05:41:41.368952Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_lr_callback(batch_size = 8):\n    lr_start   = 0.000005\n    lr_max     = 0.00000125 * REPLICAS * batch_size\n    lr_min     = 0.000001\n    lr_ramp_ep = 5\n    lr_sus_ep  = 0\n    lr_decay   = 0.8\n    def lrfn(epoch):\n        if epoch < lr_ramp_ep: lr = (lr_max - lr_start) / lr_ramp_ep * epoch + lr_start\n        elif epoch < lr_ramp_ep + lr_sus_ep: lr = lr_max\n        else: lr = (lr_max - lr_min) * lr_decay**(epoch - lr_ramp_ep - lr_sus_ep) + lr_min\n        return lr\n    lr_callback = tf.keras.callbacks.LearningRateScheduler(lrfn, verbose=False)\n    return lr_callback","metadata":{"execution":{"iopub.status.busy":"2021-11-10T05:41:41.370425Z","iopub.status.idle":"2021-11-10T05:41:41.370798Z","shell.execute_reply.started":"2021-11-10T05:41:41.370583Z","shell.execute_reply":"2021-11-10T05:41:41.370604Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from sklearn.model_selection._split import _BaseKFold, indexable, _num_samples\nfrom sklearn.utils.validation import _deprecate_positional_args\n\n# https://github.com/getgaurav2/scikit-learn/blob/d4a3af5cc9da3a76f0266932644b884c99724c57/sklearn/model_selection/_split.py#L2243\nclass GroupTimeSeriesSplit(_BaseKFold):\n    \"\"\"Time Series cross-validator variant with non-overlapping groups.\n    Provides train/test indices to split time series data samples\n    that are observed at fixed time intervals according to a\n    third-party provided group.\n    In each split, test indices must be higher than before, and thus shuffling\n    in cross validator is inappropriate.\n    This cross-validation object is a variation of :class:`KFold`.\n    In the kth split, it returns first k folds as train set and the\n    (k+1)th fold as test set.\n    The same group will not appear in two different folds (the number of\n    distinct groups has to be at least equal to the number of folds).\n    Note that unlike standard cross-validation methods, successive\n    training sets are supersets of those that come before them.\n    Read more in the :ref:`User Guide <cross_validation>`.\n    Parameters\n    ----------\n    n_splits : int, default=5\n        Number of splits. Must be at least 2.\n    max_train_size : int, default=None\n        Maximum size for a single training set.\n    Examples\n    --------\n    >>> import numpy as np\n    >>> from sklearn.model_selection import GroupTimeSeriesSplit\n    >>> groups = np.array(['a', 'a', 'a', 'a', 'a', 'a',\\\n                           'b', 'b', 'b', 'b', 'b',\\\n                           'c', 'c', 'c', 'c',\\\n                           'd', 'd', 'd'])\n    >>> gtss = GroupTimeSeriesSplit(n_splits=3)\n    >>> for train_idx, test_idx in gtss.split(groups, groups=groups):\n    ...     print(\"TRAIN:\", train_idx, \"TEST:\", test_idx)\n    ...     print(\"TRAIN GROUP:\", groups[train_idx],\\\n                  \"TEST GROUP:\", groups[test_idx])\n    TRAIN: [0, 1, 2, 3, 4, 5] TEST: [6, 7, 8, 9, 10]\n    TRAIN GROUP: ['a' 'a' 'a' 'a' 'a' 'a']\\\n    TEST GROUP: ['b' 'b' 'b' 'b' 'b']\n    TRAIN: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] TEST: [11, 12, 13, 14]\n    TRAIN GROUP: ['a' 'a' 'a' 'a' 'a' 'a' 'b' 'b' 'b' 'b' 'b']\\\n    TEST GROUP: ['c' 'c' 'c' 'c']\n    TRAIN: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]\\\n    TEST: [15, 16, 17]\n    TRAIN GROUP: ['a' 'a' 'a' 'a' 'a' 'a' 'b' 'b' 'b' 'b' 'b' 'c' 'c' 'c' 'c']\\\n    TEST GROUP: ['d' 'd' 'd']\n    \"\"\"\n    @_deprecate_positional_args\n    def __init__(self,\n                 n_splits=5,\n                 *,\n                 max_train_size=None\n                 ):\n        super().__init__(n_splits, shuffle=False, random_state=None)\n        self.max_train_size = max_train_size\n\n    def split(self, X, y=None, groups=None):\n        \"\"\"Generate indices to split data into training and test set.\n        Parameters\n        ----------\n        X : array-like of shape (n_samples, n_features)\n            Training data, where n_samples is the number of samples\n            and n_features is the number of features.\n        y : array-like of shape (n_samples,)\n            Always ignored, exists for compatibility.\n        groups : array-like of shape (n_samples,)\n            Group labels for the samples used while splitting the dataset into\n            train/test set.\n        Yields\n        ------\n        train : ndarray\n            The training set indices for that split.\n        test : ndarray\n            The testing set indices for that split.\n        \"\"\"\n        if groups is None:\n            raise ValueError(\n                \"The 'groups' parameter should not be None\")\n        X, y, groups = indexable(X, y, groups)\n        n_samples = _num_samples(X)\n        n_splits = self.n_splits\n        n_folds = n_splits + 1\n        group_dict = {}\n        u, ind = np.unique(groups, return_index=True)\n        unique_groups = u[np.argsort(ind)]\n        n_samples = _num_samples(X)\n        n_groups = _num_samples(unique_groups)\n        for idx in np.arange(n_samples):\n            if (groups[idx] in group_dict):\n                group_dict[groups[idx]].append(idx)\n            else:\n                group_dict[groups[idx]] = [idx]\n        if n_folds > n_groups:\n            raise ValueError(\n                (\"Cannot have number of folds={0} greater than\"\n                 \" the number of groups={1}\").format(n_folds,\n                                                     n_groups))\n        group_test_size = n_groups // n_folds\n        group_test_starts = range(n_groups - n_splits * group_test_size,\n                                  n_groups, group_test_size)\n        for group_test_start in group_test_starts:\n            train_array = []\n            test_array = []\n            for train_group_idx in unique_groups[:group_test_start]:\n                train_array_tmp = group_dict[train_group_idx]\n                train_array = np.sort(np.unique(\n                                      np.concatenate((train_array,\n                                                      train_array_tmp)),\n                                      axis=None), axis=None)\n            train_end = train_array.size\n            if self.max_train_size and self.max_train_size < train_end:\n                train_array = train_array[train_end -\n                                          self.max_train_size:train_end]\n            for test_group_idx in unique_groups[group_test_start:\n                                                group_test_start +\n                                                group_test_size]:\n                test_array_tmp = group_dict[test_group_idx]\n                test_array = np.sort(np.unique(\n                                              np.concatenate((test_array,\n                                                              test_array_tmp)),\n                                     axis=None), axis=None)\n            yield [int(i) for i in train_array], [int(i) for i in test_array]\nimport numpy as np\nfrom sklearn.model_selection import KFold\nfrom sklearn.model_selection._split import _BaseKFold, indexable, _num_samples\nfrom sklearn.utils.validation import _deprecate_positional_args\n\n# modified code for group gaps; source\n# https://github.com/getgaurav2/scikit-learn/blob/d4a3af5cc9da3a76f0266932644b884c99724c57/sklearn/model_selection/_split.py#L2243\nclass PurgedGroupTimeSeriesSplit(_BaseKFold):\n    \"\"\"Time Series cross-validator variant with non-overlapping groups.\n    Allows for a gap in groups to avoid potentially leaking info from\n    train into test if the model has windowed or lag features.\n    Provides train/test indices to split time series data samples\n    that are observed at fixed time intervals according to a\n    third-party provided group.\n    In each split, test indices must be higher than before, and thus shuffling\n    in cross validator is inappropriate.\n    This cross-validation object is a variation of :class:`KFold`.\n    In the kth split, it returns first k folds as train set and the\n    (k+1)th fold as test set.\n    The same group will not appear in two different folds (the number of\n    distinct groups has to be at least equal to the number of folds).\n    Note that unlike standard cross-validation methods, successive\n    training sets are supersets of those that come before them.\n    Read more in the :ref:`User Guide <cross_validation>`.\n    Parameters\n    ----------\n    n_splits : int, default=5\n        Number of splits. Must be at least 2.\n    max_train_group_size : int, default=Inf\n        Maximum group size for a single training set.\n    group_gap : int, default=None\n        Gap between train and test\n    max_test_group_size : int, default=Inf\n        We discard this number of groups from the end of each train split\n    \"\"\"\n\n    @_deprecate_positional_args\n    def __init__(self,\n                 n_splits=5,\n                 *,\n                 max_train_group_size=np.inf,\n                 max_test_group_size=np.inf,\n                 group_gap=None,\n                 verbose=False\n                 ):\n        super().__init__(n_splits, shuffle=False, random_state=None)\n        self.max_train_group_size = max_train_group_size\n        self.group_gap = group_gap\n        self.max_test_group_size = max_test_group_size\n        self.verbose = verbose\n\n    def split(self, X, y=None, groups=None):\n        \"\"\"Generate indices to split data into training and test set.\n        Parameters\n        ----------\n        X : array-like of shape (n_samples, n_features)\n            Training data, where n_samples is the number of samples\n            and n_features is the number of features.\n        y : array-like of shape (n_samples,)\n            Always ignored, exists for compatibility.\n        groups : array-like of shape (n_samples,)\n            Group labels for the samples used while splitting the dataset into\n            train/test set.\n        Yields\n        ------\n        train : ndarray\n            The training set indices for that split.\n        test : ndarray\n            The testing set indices for that split.\n        \"\"\"\n        if groups is None:\n            raise ValueError(\n                \"The 'groups' parameter should not be None\")\n        X, y, groups = indexable(X, y, groups)\n        n_samples = _num_samples(X)\n        n_splits = self.n_splits\n        group_gap = self.group_gap\n        max_test_group_size = self.max_test_group_size\n        max_train_group_size = self.max_train_group_size\n        n_folds = n_splits + 1\n        group_dict = {}\n        u, ind = np.unique(groups, return_index=True)\n        unique_groups = u[np.argsort(ind)]\n        n_samples = _num_samples(X)\n        n_groups = _num_samples(unique_groups)\n        for idx in np.arange(n_samples):\n            if (groups[idx] in group_dict):\n                group_dict[groups[idx]].append(idx)\n            else:\n                group_dict[groups[idx]] = [idx]\n        if n_folds > n_groups:\n            raise ValueError(\n                (\"Cannot have number of folds={0} greater than\"\n                 \" the number of groups={1}\").format(n_folds,\n                                                     n_groups))\n\n        group_test_size = min(n_groups // n_folds, max_test_group_size)\n        group_test_starts = range(n_groups - n_splits * group_test_size,\n                                  n_groups, group_test_size)\n        for group_test_start in group_test_starts:\n            train_array = []\n            test_array = []\n\n            group_st = max(0, group_test_start - group_gap - max_train_group_size)\n            for train_group_idx in unique_groups[group_st:(group_test_start - group_gap)]:\n                train_array_tmp = group_dict[train_group_idx]\n\n                train_array = np.sort(np.unique(\n                                      np.concatenate((train_array,\n                                                      train_array_tmp)),\n                                      axis=None), axis=None)\n\n            train_end = train_array.size\n\n            for test_group_idx in unique_groups[group_test_start:\n                                                group_test_start +\n                                                group_test_size]:\n                test_array_tmp = group_dict[test_group_idx]\n                test_array = np.sort(np.unique(\n                                              np.concatenate((test_array,\n                                                              test_array_tmp)),\n                                     axis=None), axis=None)\n\n            test_array  = test_array[group_gap:]\n\n\n            if self.verbose > 0:\n                    pass\n\n            yield [int(i) for i in train_array], [int(i) for i in test_array]","metadata":{"execution":{"iopub.status.busy":"2021-11-10T05:41:41.372092Z","iopub.status.idle":"2021-11-10T05:41:41.372663Z","shell.execute_reply.started":"2021-11-10T05:41:41.37237Z","shell.execute_reply":"2021-11-10T05:41:41.3724Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# USE VERBOSE=0 for silent, VERBOSE=1 for interactive, VERBOSE=2 for commit\nVERBOSE = 1\n\ndef get_Xy_and_model_for_asset(asset_id):\n    df = load_training_data_for_asset(asset_id)\n    df_proc = get_features(df)\n    df_proc['date'] = df['date'].copy()\n    df_proc['y'] = df['Target']\n    df_proc = df_proc.dropna(how=\"any\")\n    X = df_proc.drop(\"y\", axis=1)\n    y = df_proc[\"y\"]\n    groups = pd.factorize(X['date'].dt.day.astype(str) + '_' + X['date'].dt.month.astype(str) + '_' + X['date'].dt.year.astype(str))[0]\n    X = X.drop(columns = 'date')\n    oof_preds = np.zeros(len(X))\n    scores, models = [], []\n    GROUP_GAP = 31\n    \n    for fold, (train_idx, val_idx) in enumerate(PurgedGroupTimeSeriesSplit(n_splits = FOLDS, group_gap = GROUP_GAP).split(X, y, groups)):\n        # GET TRAINING, VALIDATION SET\n        x_train, x_val = X.iloc[train_idx], X.iloc[val_idx]\n        y_train, y_val = y.iloc[train_idx], y.iloc[val_idx]\n\n        # DISPLAY FOLD INFO\n        if DEVICE == 'TPU':\n            if tpu: tf.tpu.experimental.initialize_tpu_system(tpu)\n        print('#'*25); print('#### FOLD',fold+1)\n        print('#### Training WIDTH %s DEPTH %s | batch_size %s' % (WIDTH_NETS[fold], DEPTH_NETS[fold], BATCH_SIZES[fold]*REPLICAS))\n\n        # BUILD MODEL\n        K.clear_session()\n        with strategy.scope(): model = build_model(fold, dim = x_train.shape[1])\n\n        # SAVE BEST MODEL EACH FOLD\n        sv = tf.keras.callbacks.ModelCheckpoint('fold-%i.h5' % fold, monitor = 'val_loss', verbose = 0, save_best_only = True, save_weights_only = True, mode = 'min', save_freq = 'epoch')\n\n        # TRAIN\n        print('Training...')\n        history = model.fit( x_train, y_train, epochs = EPOCHS[fold], callbacks = [sv,get_lr_callback(BATCH_SIZES[fold])], validation_data = (x_val, y_val), verbose=VERBOSE )\n        print('Loading best model...')\n        model.load_weights('fold-%i.h5' % fold)\n\n        # PREDICT OOF\n        print('Predicting OOF...')\n        pred = model.predict(x_val, verbose = VERBOSE)\n        models.append(model)\n\n        # REPORT RESULTS\n        try: mse = mean_squared_error(np.nan_to_num(y_val), np.nan_to_num(pred))\n        except: mse = 0.0\n        scores.append(mse)\n        oof_preds[val_idx] = pred[:,0]\n        print('#### FOLD %i OOF MSE %.3f' % (fold + 1, mse))\n\n    return scores, oof_preds, models\n\nmodels = {}\nscores = {}\noof_preds = {}\nfor asset_id, asset_name in zip(df_asset_details['Asset_ID'], df_asset_details['Asset_Name']):\n    print(f\"Training model for {asset_name:<16} (ID={asset_id:<2})\")\n    cur_scores, cur_oof_preds, cur_models = get_Xy_and_model_for_asset(asset_id)\n    scores[asset_id], oof_preds[asset_id], models[asset_id] = cur_scores, oof_preds, cur_models","metadata":{"execution":{"iopub.status.busy":"2021-11-10T05:41:41.374278Z","iopub.status.idle":"2021-11-10T05:41:41.37491Z","shell.execute_reply.started":"2021-11-10T05:41:41.374691Z","shell.execute_reply":"2021-11-10T05:41:41.374717Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# COMPUTE OVERALL OOF MSE\nprint('Overall MEAN OOF MSE %s' % np.mean(list(scores.values())))\n\n# SAVE OOF TO DISK \nfor asset in oof_preds:\n    df_oof = pd.DataFrame(dict(asset_id = asset, oof_preds=oof_preds))\n    df_oof.to_csv(str(asset) + '_oof.csv',index=False)\n    df_oof.head()","metadata":{"execution":{"iopub.status.busy":"2021-11-10T05:41:41.376004Z","iopub.status.idle":"2021-11-10T05:41:41.376889Z","shell.execute_reply.started":"2021-11-10T05:41:41.376669Z","shell.execute_reply":"2021-11-10T05:41:41.376699Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Make A Sub.","metadata":{}},{"cell_type":"code","source":"all_df_test = []\n\nenv = gresearch_crypto.make_env()\niter_test = env.iter_test()\n\nfor i, (df_test, df_pred) in enumerate(iter_test):\n    for j , row in df_test.iterrows():\n        try:\n            if row['Asset_ID'] in models:\n                models = models[row['Asset_ID']]\n                x_test = get_features(row)\n                y_pred = np.mean(np.concatenate([np.expand_dims(model.predict(x_test)[0], axis = 0) for model in models], axis = 0), axis = 0)\n            else: y_pred = 0.0\n        except: \n            y_pred = 0.0\n            traceback.print_exc()\n        df_pred.loc[df_pred['row_id'] == row['row_id'], 'Target'] = y_pred\n    all_df_test.append(df_test)\n    env.predict(df_pred)","metadata":{"execution":{"iopub.status.busy":"2021-11-10T05:41:41.378029Z","iopub.status.idle":"2021-11-10T05:41:41.378345Z","shell.execute_reply.started":"2021-11-10T05:41:41.378178Z","shell.execute_reply":"2021-11-10T05:41:41.378198Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}