{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.14","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":84493,"databundleVersionId":9871156,"sourceType":"competition"}],"dockerImageVersionId":30805,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nimport os","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2024-12-31T07:31:56.695349Z","iopub.execute_input":"2024-12-31T07:31:56.696111Z","iopub.status.idle":"2024-12-31T07:31:56.700454Z","shell.execute_reply.started":"2024-12-31T07:31:56.696055Z","shell.execute_reply":"2024-12-31T07:31:56.699474Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Dependencies and Libraries","metadata":{}},{"cell_type":"code","source":"%%capture\n!pip install fastparquet","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-31T07:31:56.701960Z","iopub.execute_input":"2024-12-31T07:31:56.702279Z","iopub.status.idle":"2024-12-31T07:32:04.961456Z","shell.execute_reply.started":"2024-12-31T07:31:56.702253Z","shell.execute_reply":"2024-12-31T07:32:04.960415Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from fastparquet import ParquetFile","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-31T07:32:04.963359Z","iopub.execute_input":"2024-12-31T07:32:04.963651Z","iopub.status.idle":"2024-12-31T07:32:04.968204Z","shell.execute_reply.started":"2024-12-31T07:32:04.963625Z","shell.execute_reply":"2024-12-31T07:32:04.967298Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pandas as pd\nimport matplotlib.pyplot as plt\nimport numpy as np\nimport seaborn as sns\nimport math\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.metrics import r2_score","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-31T07:32:04.969319Z","iopub.execute_input":"2024-12-31T07:32:04.969590Z","iopub.status.idle":"2024-12-31T07:32:04.980524Z","shell.execute_reply.started":"2024-12-31T07:32:04.969565Z","shell.execute_reply":"2024-12-31T07:32:04.979711Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Adjust pandas display options\npd.set_option('display.max_rows', None)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-31T07:32:04.982134Z","iopub.execute_input":"2024-12-31T07:32:04.982382Z","iopub.status.idle":"2024-12-31T07:32:04.992814Z","shell.execute_reply.started":"2024-12-31T07:32:04.982358Z","shell.execute_reply":"2024-12-31T07:32:04.992154Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Load Dataset","metadata":{}},{"cell_type":"code","source":"dataset_dir = \"/kaggle/input/jane-street-real-time-market-data-forecasting\"\n\ndef get_train_path(i : int = 0, root : str = dataset_dir) -> str :\n    return os.path.join(root, \"train.parquet\", f\"partition_id={i}\", \"part-0.parquet\")\ndef get_test_path(i : int = 0, root : str = dataset_dir) -> str :\n    return os.path.join(root, \"test.parquet\", f\"date_id={i}\", \"part-0.parquet\")\n\npf = ParquetFile(get_train_path(0))\ndf_train = pf.to_pandas()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-31T07:32:04.993657Z","iopub.execute_input":"2024-12-31T07:32:04.993874Z","iopub.status.idle":"2024-12-31T07:32:06.305640Z","shell.execute_reply.started":"2024-12-31T07:32:04.993852Z","shell.execute_reply":"2024-12-31T07:32:06.304924Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df_train.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-31T07:32:06.306681Z","iopub.execute_input":"2024-12-31T07:32:06.306925Z","iopub.status.idle":"2024-12-31T07:32:06.326208Z","shell.execute_reply.started":"2024-12-31T07:32:06.306901Z","shell.execute_reply":"2024-12-31T07:32:06.325294Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(np.unique(df_train['symbol_id']))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-31T07:32:06.327276Z","iopub.execute_input":"2024-12-31T07:32:06.327533Z","iopub.status.idle":"2024-12-31T07:32:06.381456Z","shell.execute_reply.started":"2024-12-31T07:32:06.327509Z","shell.execute_reply":"2024-12-31T07:32:06.380748Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"SYMBOL = 0","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-31T07:32:06.382621Z","iopub.execute_input":"2024-12-31T07:32:06.382964Z","iopub.status.idle":"2024-12-31T07:32:06.386945Z","shell.execute_reply.started":"2024-12-31T07:32:06.382927Z","shell.execute_reply":"2024-12-31T07:32:06.386057Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"dfs = []\nfor i in range(10) :\n    path = get_train_path(i)\n    pf = ParquetFile(path)\n    df = pf.to_pandas()\n    df = df[df['symbol_id'] == SYMBOL]\n    dfs.append(df)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-31T07:32:06.387904Z","iopub.execute_input":"2024-12-31T07:32:06.388256Z","iopub.status.idle":"2024-12-31T07:32:39.417681Z","shell.execute_reply.started":"2024-12-31T07:32:06.388210Z","shell.execute_reply":"2024-12-31T07:32:39.416716Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df = pd.concat(dfs, ignore_index = True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-31T07:32:39.420530Z","iopub.execute_input":"2024-12-31T07:32:39.420843Z","iopub.status.idle":"2024-12-31T07:32:39.612099Z","shell.execute_reply.started":"2024-12-31T07:32:39.420816Z","shell.execute_reply":"2024-12-31T07:32:39.611410Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Basic Exploration","metadata":{}},{"cell_type":"code","source":"df.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-31T07:32:39.613284Z","iopub.execute_input":"2024-12-31T07:32:39.613943Z","iopub.status.idle":"2024-12-31T07:32:39.633008Z","shell.execute_reply.started":"2024-12-31T07:32:39.613902Z","shell.execute_reply":"2024-12-31T07:32:39.632096Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"drops = ['weight','symbol_id'] + [f'responder_{i:01d}' for i in range(6)] + [f'responder_{i:01d}' for i in range(7,9)]\ndf.drop(drops, axis = 1, inplace = True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-31T07:32:39.634244Z","iopub.execute_input":"2024-12-31T07:32:39.634517Z","iopub.status.idle":"2024-12-31T07:32:39.785392Z","shell.execute_reply.started":"2024-12-31T07:32:39.634479Z","shell.execute_reply":"2024-12-31T07:32:39.784432Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Basic Preprocessing","metadata":{}},{"cell_type":"markdown","source":"Removing the column if percentage of null values is above threshold for even a single date_id","metadata":{}},{"cell_type":"code","source":"# Threshold for null percentage\nthreshold = 10\n\n# Calculate the percentage of null values for each feature, grouped by date_id\nnull_percentage = df.groupby('date_id').apply(lambda x: x.isnull().mean() * 100)\n\n# Identify columns where null percentage exceeds the threshold for any date_id\ncolumns_to_drop = null_percentage.columns[(null_percentage > threshold).any()]\nprint(\"Columns removed:\")\nprint(columns_to_drop.tolist())\n\ndf = df.drop(columns=columns_to_drop)\ndf.ffill(axis = 0)\ndf=df.dropna(axis=1)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-31T07:32:39.786481Z","iopub.execute_input":"2024-12-31T07:32:39.786788Z","iopub.status.idle":"2024-12-31T07:32:42.590844Z","shell.execute_reply.started":"2024-12-31T07:32:39.786761Z","shell.execute_reply":"2024-12-31T07:32:42.589812Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-31T07:32:42.592131Z","iopub.execute_input":"2024-12-31T07:32:42.592419Z","iopub.status.idle":"2024-12-31T07:32:42.610852Z","shell.execute_reply.started":"2024-12-31T07:32:42.592386Z","shell.execute_reply":"2024-12-31T07:32:42.609948Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Dropping unecesarry columns for training the model","metadata":{}},{"cell_type":"code","source":"df.drop(['feature_09', 'feature_10', 'feature_11'], axis = 1, inplace = True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-31T07:32:42.611840Z","iopub.execute_input":"2024-12-31T07:32:42.612079Z","iopub.status.idle":"2024-12-31T07:32:42.700060Z","shell.execute_reply.started":"2024-12-31T07:32:42.612054Z","shell.execute_reply":"2024-12-31T07:32:42.699357Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.compose import ColumnTransformer\nfrom sklearn.preprocessing import StandardScaler\n\nscaler = StandardScaler()\n\ncolumns_to_scale = df.columns[2:]\nall_columns = list(columns_to_scale) + ['date_id', 'time_id']\n\n# Use ColumnTransformer to apply the scaler\nct = ColumnTransformer(\n    transformers=[\n        (\"scale\", scaler, columns_to_scale)  # Apply scaler to specified columns\n    ],\n    remainder=\"passthrough\"  # Keep other columns as they are\n)\n\n# Transform the data\nscaled_data = ct.fit_transform(df)\nscaled_df = pd.DataFrame(scaled_data, columns=all_columns)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-31T07:32:42.701107Z","iopub.execute_input":"2024-12-31T07:32:42.701490Z","iopub.status.idle":"2024-12-31T07:32:43.613262Z","shell.execute_reply.started":"2024-12-31T07:32:42.701453Z","shell.execute_reply":"2024-12-31T07:32:43.612570Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Group by the first column (e.g., 'Group')\ngrouped = scaled_df.groupby(\"date_id\")\n\n# Convert each group into a NumPy array and stack them\ndfs_by_date = [group.iloc[:, :-2] for _, group in grouped]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-31T07:32:43.614223Z","iopub.execute_input":"2024-12-31T07:32:43.614504Z","iopub.status.idle":"2024-12-31T07:32:43.868481Z","shell.execute_reply.started":"2024-12-31T07:32:43.614478Z","shell.execute_reply":"2024-12-31T07:32:43.867592Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"X = []\ny = []\n\nfor frame in dfs_by_date:\n    if len(frame) == 849 :\n        X.append(frame.iloc[:,:-1])\n        y.append(frame.iloc[:,-1])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-31T07:32:43.870016Z","iopub.execute_input":"2024-12-31T07:32:43.870306Z","iopub.status.idle":"2024-12-31T07:32:43.941748Z","shell.execute_reply.started":"2024-12-31T07:32:43.870274Z","shell.execute_reply":"2024-12-31T07:32:43.941124Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import torch\nimport torch.nn as nn\n\nclass Seq2SeqModel(nn.Module):\n    def __init__(self, input_dim, hidden_dim, output_dim, num_layers=1, dropout = 0.3):\n        super(Seq2SeqModel, self).__init__()\n        # Encoder LSTM\n        self.encoder = nn.LSTM(input_dim, hidden_dim, num_layers, batch_first=True, dropout= dropout)\n        # Decoder LSTM\n        self.decoder = nn.LSTM(output_dim, hidden_dim, num_layers, batch_first=True, dropout = dropout)\n        # Fully connected layer to predict target\n    \n        # self.fc = nn.Linear(hidden_dim, output_dim\n        self.fc = nn.Sequential(\n            nn.Linear(hidden_dim, 64),  # More neurons\n            nn.ReLU(),\n            nn.Linear(64, 32),        # Additional layer\n            nn.ReLU(),\n            nn.Linear(32, output_dim)\n        )\n    \n    def forward(self, features, targets=None, teacher_forcing_ratio=0.5):\n        \"\"\"\n        Forward pass for training/inference.\n        Args:\n            features: Tensor of shape (batch_size, seq_len, input_dim)\n            targets: Tensor of shape (batch_size, seq_len, output_dim), optional during inference\n            teacher_forcing_ratio: Probability of using ground truth targets during training\n        Returns:\n            Outputs: Predicted targets of shape (batch_size, seq_len, output_dim)\n        \"\"\"\n        batch_size, seq_len, _ = features.size()\n        hidden_dim = self.fc[-1].out_features\n\n        # Encode the features\n        _, (hidden, cell) = self.encoder(features)  # (hidden, cell) are the encoder's final states\n\n        # Prepare outputs container\n        outputs = torch.zeros(batch_size, seq_len, hidden_dim).to(features.device)\n\n        # First input to the decoder is the first target value or a placeholder\n        decoder_input = torch.zeros(batch_size, hidden_dim).to(features.device)  # Start with zeros\n\n        # Decoder: Sequentially predict each time step\n        for t in range(seq_len):\n            output, (hidden, cell) = self.decoder(decoder_input.unsqueeze(1), (hidden, cell))\n            output = self.fc(output.squeeze(1))  # Predict target for this time step\n            outputs[:, t, :] = output\n\n            # Decide if we use teacher forcing or predicted value\n            if targets is not None and torch.rand(1).item() < teacher_forcing_ratio:\n                decoder_input = targets[:, t, :]  # Use ground truth\n            else:\n                decoder_input = output  # Use model's own prediction\n\n        return outputs","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-31T07:37:17.130465Z","iopub.execute_input":"2024-12-31T07:37:17.130858Z","iopub.status.idle":"2024-12-31T07:37:17.139675Z","shell.execute_reply.started":"2024-12-31T07:37:17.130826Z","shell.execute_reply":"2024-12-31T07:37:17.138818Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Convert to tensors\ndef convert_to_tensors(features_list, targets_list):\n    features_tensor = [torch.tensor(df.values, dtype=torch.float32) for df in features_list]\n    targets_tensor = [torch.tensor(series.values, dtype=torch.float32) for series in targets_list]\n    return features_tensor, targets_tensor","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-31T07:37:18.822421Z","iopub.execute_input":"2024-12-31T07:37:18.823041Z","iopub.status.idle":"2024-12-31T07:37:18.827686Z","shell.execute_reply.started":"2024-12-31T07:37:18.823007Z","shell.execute_reply":"2024-12-31T07:37:18.826826Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"features_tensor, targets_tensor = convert_to_tensors(X, y)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-31T07:37:19.086757Z","iopub.execute_input":"2024-12-31T07:37:19.087005Z","iopub.status.idle":"2024-12-31T07:37:19.147689Z","shell.execute_reply.started":"2024-12-31T07:37:19.086981Z","shell.execute_reply":"2024-12-31T07:37:19.146981Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Split into train and validation sets\ntrain_features, val_features, train_targets, val_targets = train_test_split(\n    features_tensor, targets_tensor, test_size=0.2, random_state=42\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-31T07:37:19.312482Z","iopub.execute_input":"2024-12-31T07:37:19.312855Z","iopub.status.idle":"2024-12-31T07:37:19.318536Z","shell.execute_reply.started":"2024-12-31T07:37:19.312826Z","shell.execute_reply":"2024-12-31T07:37:19.317615Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from torch.utils.data import DataLoader, Dataset\n\nclass TimeSeriesDataset(Dataset):\n    def __init__(self, features, targets):\n        self.features = features\n        self.targets = targets\n\n    def __len__(self):\n        return len(self.features)\n\n    def __getitem__(self, idx):\n        return self.features[idx], self.targets[idx]\n\n# Create dataset and dataloaders\ntrain_dataset = TimeSeriesDataset(train_features, train_targets)\nval_dataset = TimeSeriesDataset(val_features, val_targets)\n\ntrain_loader = DataLoader(train_dataset, batch_size=4, shuffle=True)\nval_loader = DataLoader(val_dataset, batch_size=4, shuffle=False)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-31T07:37:19.539785Z","iopub.execute_input":"2024-12-31T07:37:19.540078Z","iopub.status.idle":"2024-12-31T07:37:19.548879Z","shell.execute_reply.started":"2024-12-31T07:37:19.540052Z","shell.execute_reply":"2024-12-31T07:37:19.548121Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Example usage\nbatch_size = 32\nseq_len = X[0].shape[0]\ninput_dim = X[0].shape[1] \noutput_dim = 1\nlayers = 3\n\nmodel = Seq2SeqModel(input_dim=input_dim, hidden_dim=128, output_dim=output_dim, num_layers = layers)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-31T07:37:20.290685Z","iopub.execute_input":"2024-12-31T07:37:20.290991Z","iopub.status.idle":"2024-12-31T07:37:20.303129Z","shell.execute_reply.started":"2024-12-31T07:37:20.290966Z","shell.execute_reply":"2024-12-31T07:37:20.302446Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import torch.optim as optim\n\n# Loss function and optimizer\ncriterion = nn.MSELoss()\noptimizer = optim.Adam(model.parameters(), lr=0.001)\n\n# Training loop\nepochs = 10\nteacher_forcing_ratio = 1\n\nfor epoch in range(epochs):\n    model.train()\n    train_loss = 0.0\n    for features, targets in train_loader:\n        optimizer.zero_grad()\n        outputs = model(features, targets.unsqueeze(-1), teacher_forcing_ratio=teacher_forcing_ratio)\n        loss = criterion(outputs.squeeze(-1), targets)\n        loss.backward()\n        optimizer.step()\n        train_loss += loss.item()\n    print(f\"Epoch {epoch + 1}, Train Loss: {train_loss / len(train_loader)}\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-31T07:37:20.603705Z","iopub.execute_input":"2024-12-31T07:37:20.603968Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model.eval()\nval_predictions, val_targets_list = [], []\n\nwith torch.no_grad():\n    for features, targets in val_loader:\n        outputs = model(features)  # No teacher forcing during validation\n        val_predictions.append(outputs.squeeze(-1).cpu().numpy())\n        val_targets_list.append(targets.cpu().numpy())\n\n# Concatenate predictions and targets\nval_predictions = np.concatenate(val_predictions, axis=0)\nval_targets = np.concatenate(val_targets_list, axis=0)\n\n# Calculate R² score\nr2 = r2_score(val_targets, val_predictions)\nprint(f\"Validation R² Score: {r2}\")","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"for x,y in zip(val_targets, val_predictions) :\n    for val_x, val_y in zip(x,y) :\n        print(val_x,val_y)","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}