{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.11","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":96164,"databundleVersionId":12993472,"sourceType":"competition"}],"dockerImageVersionId":31040,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"_uuid":"f0ec9f9c-5ed9-4e56-9677-9a58381202ab","_cell_guid":"f0e6f033-d6d8-441a-983d-6ca8d8c28e6d","trusted":true,"collapsed":false,"execution":{"iopub.status.busy":"2025-07-19T22:51:11.935730Z","iopub.execute_input":"2025-07-19T22:51:11.936358Z","iopub.status.idle":"2025-07-19T22:51:12.972552Z","shell.execute_reply.started":"2025-07-19T22:51:11.936323Z","shell.execute_reply":"2025-07-19T22:51:12.971707Z"},"jupyter":{"outputs_hidden":false}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def reduce_mem_usage(dataframe, dataset):    \n    print('Reducing memory usage for:', dataset)\n    initial_mem_usage = dataframe.memory_usage().sum() / 1024**2\n    \n    for col in dataframe.columns:\n        col_type = dataframe[col].dtype\n\n        c_min = dataframe[col].min()\n        c_max = dataframe[col].max()\n        if str(col_type)[:3] == 'int':\n            if c_min > np.iinfo(np.int8).min and c_max < np.iinfo(np.int8).max:\n                dataframe[col] = dataframe[col].astype(np.int8)\n            elif c_min > np.iinfo(np.int16).min and c_max < np.iinfo(np.int16).max:\n                dataframe[col] = dataframe[col].astype(np.int16)\n            elif c_min > np.iinfo(np.int32).min and c_max < np.iinfo(np.int32).max:\n                dataframe[col] = dataframe[col].astype(np.int32)\n            elif c_min > np.iinfo(np.int64).min and c_max < np.iinfo(np.int64).max:\n                dataframe[col] = dataframe[col].astype(np.int64)\n        else:\n            if c_min > np.finfo(np.float16).min and c_max < np.finfo(np.float16).max:\n                dataframe[col] = dataframe[col].astype(np.float16)\n            elif c_min > np.finfo(np.float32).min and c_max < np.finfo(np.float32).max:\n                dataframe[col] = dataframe[col].astype(np.float32)\n            else:\n                dataframe[col] = dataframe[col].astype(np.float64)\n\n    final_mem_usage = dataframe.memory_usage().sum() / 1024**2\n    print('--- Memory usage before: {:.2f} MB'.format(initial_mem_usage))\n    print('--- Memory usage after: {:.2f} MB'.format(final_mem_usage))\n    print('--- Decreased memory usage by {:.1f}%\\n'.format(100 * (initial_mem_usage - final_mem_usage) / initial_mem_usage))\n\n    return dataframe","metadata":{"_uuid":"4666dd4c-564d-49ef-b47b-18dd558aa636","_cell_guid":"9d34dc96-d47f-4544-a7fc-c48c88e4fe7b","trusted":true,"collapsed":false,"execution":{"iopub.status.busy":"2025-07-19T22:51:12.973844Z","iopub.execute_input":"2025-07-19T22:51:12.974228Z","iopub.status.idle":"2025-07-19T22:51:12.983895Z","shell.execute_reply.started":"2025-07-19T22:51:12.974204Z","shell.execute_reply":"2025-07-19T22:51:12.983059Z"},"jupyter":{"outputs_hidden":false}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import sys\nimport pandas as pd\nimport numpy as np\nfrom sklearn.model_selection import KFold\nfrom xgboost import XGBRegressor\nfrom lightgbm import LGBMRegressor\nfrom sklearn.linear_model import (\n    HuberRegressor, RANSACRegressor, TheilSenRegressor,\n    Lasso, ElasticNet, Ridge\n)\nfrom sklearn.cross_decomposition import PLSRegression\nfrom sklearn.preprocessing import StandardScaler, RobustScaler\nfrom sklearn.ensemble import RandomForestRegressor\nfrom scipy.stats import pearsonr\nimport warnings\nwarnings.filterwarnings('ignore')\n\n# ===== Feature Engineering =====\ndef feature_engineering(df):\n    # Original features\n    df['bid_ask_interaction'] = df['bid_qty'] * df['ask_qty']\n    df['bid_buy_interaction'] = df['bid_qty'] * df['buy_qty']\n    df['bid_sell_interaction'] = df['bid_qty'] * df['sell_qty']\n    df['ask_buy_interaction'] = df['ask_qty'] * df['buy_qty']\n    df['ask_sell_interaction'] = df['ask_qty'] * df['sell_qty']\n\n    df['volume_weighted_sell'] = df['sell_qty'] * df['volume']\n    df['buy_sell_ratio'] = df['buy_qty'] / (df['sell_qty'] + 1e-10)\n    df['selling_pressure'] = df['sell_qty'] / (df['volume'] + 1e-10)\n    df['log_volume'] = np.log1p(df['volume'])\n\n    df['effective_spread_proxy'] = np.abs(df['buy_qty'] - df['sell_qty']) / (df['volume'] + 1e-10)\n    df['bid_ask_imbalance'] = (df['bid_qty'] - df['ask_qty']) / (df['bid_qty'] + df['ask_qty'] + 1e-10)\n    df['order_flow_imbalance'] = (df['buy_qty'] - df['sell_qty']) / (df['buy_qty'] + df['sell_qty'] + 1e-10)\n    df['liquidity_ratio'] = (df['bid_qty'] + df['ask_qty']) / (df['volume'] + 1e-10)\n    \n    # === NEW MICROSTRUCTURE FEATURES ===\n    \n    # Price Pressure Indicators\n    df['net_order_flow'] = df['buy_qty'] - df['sell_qty']\n    df['normalized_net_flow'] = df['net_order_flow'] / (df['volume'] + 1e-10)\n    df['buying_pressure'] = df['buy_qty'] / (df['volume'] + 1e-10)\n    df['volume_weighted_buy'] = df['buy_qty'] * df['volume']\n    \n    # Liquidity Depth Measures\n    df['total_depth'] = df['bid_qty'] + df['ask_qty']\n    df['depth_imbalance'] = (df['bid_qty'] - df['ask_qty']) / (df['total_depth'] + 1e-10)\n    df['relative_spread'] = np.abs(df['bid_qty'] - df['ask_qty']) / (df['total_depth'] + 1e-10)\n    df['log_depth'] = np.log1p(df['total_depth'])\n    \n    # Order Flow Toxicity Proxies\n    df['kyle_lambda'] = np.abs(df['net_order_flow']) / (df['volume'] + 1e-10)\n    df['flow_toxicity'] = np.abs(df['order_flow_imbalance']) * df['volume']\n    df['aggressive_flow_ratio'] = (df['buy_qty'] + df['sell_qty']) / (df['total_depth'] + 1e-10)\n    \n    # Market Activity Indicators\n    df['volume_depth_ratio'] = df['volume'] / (df['total_depth'] + 1e-10)\n    df['activity_intensity'] = (df['buy_qty'] + df['sell_qty']) / (df['volume'] + 1e-10)\n    df['log_buy_qty'] = np.log1p(df['buy_qty'])\n    df['log_sell_qty'] = np.log1p(df['sell_qty'])\n    df['log_bid_qty'] = np.log1p(df['bid_qty'])\n    df['log_ask_qty'] = np.log1p(df['ask_qty'])\n    \n    # Microstructure Volatility Proxies\n    df['realized_spread_proxy'] = 2 * np.abs(df['net_order_flow']) / (df['volume'] + 1e-10)\n    df['price_impact_proxy'] = df['net_order_flow'] / (df['total_depth'] + 1e-10)\n    df['quote_volatility_proxy'] = np.abs(df['depth_imbalance'])\n    \n    # Complex Interaction Terms\n    df['flow_depth_interaction'] = df['net_order_flow'] * df['total_depth']\n    df['imbalance_volume_interaction'] = df['order_flow_imbalance'] * df['volume']\n    df['depth_volume_interaction'] = df['total_depth'] * df['volume']\n    df['buy_sell_spread'] = np.abs(df['buy_qty'] - df['sell_qty'])\n    df['bid_ask_spread'] = np.abs(df['bid_qty'] - df['ask_qty'])\n    \n    # Information Asymmetry Measures\n    df['trade_informativeness'] = df['net_order_flow'] / (df['bid_qty'] + df['ask_qty'] + 1e-10)\n    df['execution_shortfall_proxy'] = df['buy_sell_spread'] / (df['volume'] + 1e-10)\n    df['adverse_selection_proxy'] = df['net_order_flow'] / (df['total_depth'] + 1e-10) * df['volume']\n    \n    # Market Efficiency Indicators\n    df['fill_probability'] = df['volume'] / (df['buy_qty'] + df['sell_qty'] + 1e-10)\n    df['execution_rate'] = (df['buy_qty'] + df['sell_qty']) / (df['total_depth'] + 1e-10)\n    df['market_efficiency'] = df['volume'] / (df['bid_ask_spread'] + 1e-10)\n    \n    # Non-linear Transformations\n    df['sqrt_volume'] = np.sqrt(df['volume'])\n    df['sqrt_depth'] = np.sqrt(df['total_depth'])\n    df['volume_squared'] = df['volume'] ** 2\n    df['imbalance_squared'] = df['order_flow_imbalance'] ** 2\n    \n    # Relative Measures\n    df['bid_ratio'] = df['bid_qty'] / (df['total_depth'] + 1e-10)\n    df['ask_ratio'] = df['ask_qty'] / (df['total_depth'] + 1e-10)\n    df['buy_ratio'] = df['buy_qty'] / (df['buy_qty'] + df['sell_qty'] + 1e-10)\n    df['sell_ratio'] = df['sell_qty'] / (df['buy_qty'] + df['sell_qty'] + 1e-10)\n    \n    # Market Stress Indicators\n    df['liquidity_consumption'] = (df['buy_qty'] + df['sell_qty']) / (df['total_depth'] + 1e-10)\n    df['market_stress'] = df['volume'] / (df['total_depth'] + 1e-10) * np.abs(df['order_flow_imbalance'])\n    df['depth_depletion'] = df['volume'] / (df['bid_qty'] + df['ask_qty'] + 1e-10)\n    \n    # Directional Indicators\n    df['net_buying_ratio'] = df['net_order_flow'] / (df['volume'] + 1e-10)\n    df['directional_volume'] = df['net_order_flow'] * np.log1p(df['volume'])\n    df['signed_volume'] = np.sign(df['net_order_flow']) * df['volume']\n    # Handle infinities and NaN\n    df = df.replace([np.inf, -np.inf], np.nan)\n    \n    # For each column, replace NaN with median for robustness\n    for col in df.columns:\n        if df[col].isna().any():\n            median_val = df[col].median()\n            df[col] = df[col].fillna(median_val if not pd.isna(median_val) else 0)\n    \n    return df\n\n# ===== Configuration =====\nclass Config:\n    TRAIN_PATH = \"/kaggle/input/drw-crypto-market-prediction/train.parquet\"\n    TEST_PATH = \"/kaggle/input/drw-crypto-market-prediction/test.parquet\"\n    SUBMISSION_PATH = \"/kaggle/input/drw-crypto-market-prediction/sample_submission.csv\"\n    \n    # Original features plus additional market features\n    FEATURES = ['X363', 'X321', 'X405', 'X730', 'X523', 'X756', 'X589', 'X462', 'X779',\n                'X25', 'X532', 'X520', 'X329', 'X383', \n            \"X752\",\n    \"X287\",\n    \"X298\",\n    \"X759\",\n    \"X302\",\n    \"X55\",\n    \"X56\",\n    \"X52\",\n    \"X303\",\n    \"X51\",\n    \"X598\", \"X385\", \"X603\", \"X674\",\n    \"X415\", \"X345\", \"X174\", \"X178\", \"X168\", \"X612\", \"bid_qty\",\n        \"ask_qty\", \"buy_qty\", \"sell_qty\", \"volume\" \n    ]\n    \n    LABEL_COLUMN = \"label\"\n    N_FOLDS = 3\n    RANDOM_STATE = 1\n\n# ===== Model Parameters =====\n# Original XGBoost parameters\nXGB_PARAMS = {\n    \"tree_method\": \"hist\",\n    \"device\": \"gpu\",\n    \"colsample_bylevel\": 0.4778,\n    \"colsample_bynode\": 0.3628,\n    \"colsample_bytree\": 0.7107,\n    \"gamma\": 1.7095,\n    \"learning_rate\": 0.02213,\n    \"max_depth\": 20,\n    \"max_leaves\": 12,\n    \"min_child_weight\": 16,\n    \"n_estimators\": 1667,\n    \"subsample\": 0.06567,\n    \"reg_alpha\": 39.3524,\n    \"reg_lambda\": 75.4484,\n    \"verbosity\": 0,\n    \"random_state\": Config.RANDOM_STATE,\n    \"n_jobs\": -1\n}\n\n# LightGBM parameters (simpler model for noisy data)\nLGBM_PARAMS = {\n    \"n_estimators\": 500,\n    \"learning_rate\": 0.03,\n    \"num_leaves\": 31,\n    \"min_child_samples\": 50,\n    \"subsample\": 0.8,\n    \"colsample_bytree\": 0.8,\n    \"reg_alpha\": 10,\n    \"reg_lambda\": 10,\n    \"random_state\": Config.RANDOM_STATE,\n    \"device\": \"gpu\",\n    \"verbosity\": -1,\n    \"n_jobs\": -1\n}\n\n# Define all learners\nLEARNERS = [\n    {\"name\": \"xgb_baseline\", \"Estimator\": XGBRegressor, \"params\": XGB_PARAMS, \"need_scale\": False}]\n\n# ===== Data Loading =====\ndef create_time_decay_weights(n: int, decay: float = 0.9) -> np.ndarray:\n    \"\"\"Create time decay weights for more recent data importance\"\"\"\n    positions = np.arange(n)\n    normalized = positions / (n - 1)\n    weights = decay ** (1.0 - normalized)\n    return weights * n / weights.sum()\n\ndef load_data():\n    \"\"\"Load and preprocess data\"\"\"\n    train_df = pd.read_parquet(Config.TRAIN_PATH, columns=Config.FEATURES + [Config.LABEL_COLUMN])\n    test_df = pd.read_parquet(Config.TEST_PATH, columns=Config.FEATURES)\n    submission_df = pd.read_csv(Config.SUBMISSION_PATH)\n\n    # Apply feature engineering\n    train_df = feature_engineering(train_df)\n    test_df = feature_engineering(test_df)\n\n    \n    to_remove = [\"bid_qty\", \"ask_qty\", \"buy_qty\", \"sell_qty\", \"volume\"]\n\n    train_df = train_df.drop(columns=to_remove)\n    test_df = test_df.drop(columns=to_remove)\n\n\n    train_df = reduce_mem_usage(train_df, \"train\")\n    test_df = reduce_mem_usage(test_df, \"test\")\n\n    \n    # Update features list with engineered features\n    engineered_features = [\n        \"log_volume\", 'bid_ask_interaction', 'bid_buy_interaction', 'bid_sell_interaction', \n        'ask_buy_interaction', 'ask_sell_interaction', 'net_order_flow', 'normalized_net_flow',\n        'buying_pressure', 'volume_weighted_buy', 'total_depth', 'depth_imbalance',\n        'relative_spread', 'log_depth', 'kyle_lambda', 'flow_toxicity', 'aggressive_flow_ratio',\n        'volume_depth_ratio', 'activity_intensity', 'log_buy_qty', 'log_sell_qty',\n        'log_bid_qty', 'log_ask_qty', 'realized_spread_proxy', 'price_impact_proxy',\n        'quote_volatility_proxy', 'flow_depth_interaction', 'imbalance_volume_interaction',\n        'depth_volume_interaction', 'buy_sell_spread', 'bid_ask_spread', 'trade_informativeness',\n        'execution_shortfall_proxy', 'adverse_selection_proxy', 'fill_probability',\n        'execution_rate', 'market_efficiency', 'sqrt_volume', 'sqrt_depth', 'volume_squared',\n        'imbalance_squared', 'bid_ratio', 'ask_ratio', 'buy_ratio', 'sell_ratio',\n        'liquidity_consumption', 'market_stress', 'depth_depletion', 'net_buying_ratio',\n        'directional_volume', 'signed_volume'\n    ]\n    Config.FEATURES = sorted(set(Config.FEATURES + engineered_features) - set(to_remove))\n    \n    print(f\"Loaded data - Train: {train_df.shape}, Test: {test_df.shape}, Submission: {submission_df.shape}\")\n    print(f\"Total features: {len(Config.FEATURES)}\")\n    \n    return train_df.reset_index(drop=True), test_df.reset_index(drop=True), submission_df\n\n# ===== Model Training =====\ndef get_model_slices(n_samples: int):\n    \"\"\"Define different data slices for training\"\"\"\n    return [\n        {\"name\": \"full_data\", \"cutoff\": 0},\n        {\"name\": \"last_90pct\", \"cutoff\": int(0.10 * n_samples)},\n        {\"name\": \"last_85pct\", \"cutoff\": int(0.15 * n_samples)},\n        {\"name\": \"last_80pct\", \"cutoff\": int(0.20 * n_samples)},\n\n    ]\n\ndef train_single_model(X_train, y_train, X_valid, y_valid, X_test, learner, sample_weights=None):\n    \"\"\"Train a single model with appropriate scaling if needed\"\"\"\n    if learner[\"need_scale\"]:\n        scaler = RobustScaler()  # More robust to outliers than StandardScaler\n        X_train_scaled = scaler.fit_transform(X_train)\n        X_valid_scaled = scaler.transform(X_valid)\n        X_test_scaled = scaler.transform(X_test)\n    else:\n        X_train_scaled = X_train\n        X_valid_scaled = X_valid\n        X_test_scaled = X_test\n    \n    model = learner[\"Estimator\"](**learner[\"params\"])\n    \n    # Handle different model training approaches\n    if learner[\"name\"] in [\"xgb_baseline\", \"lgbm\"]:\n        if learner[\"name\"] == \"xgb_baseline\":\n            model.fit(X_train_scaled, y_train, sample_weight=sample_weights, \n                     eval_set=[(X_valid_scaled, y_valid)], verbose=False)\n        else:  # LightGBM\n            model.fit(X_train_scaled, y_train, sample_weight=sample_weights,\n                     eval_set=[(X_valid_scaled, y_valid)], callbacks=[])\n    elif learner[\"name\"] in [\"huber\", \"lasso\", \"elasticnet\"]:\n        model.fit(X_train_scaled, y_train, sample_weight=sample_weights)\n    else:\n        # RANSAC, TheilSen, PLS don't support sample weights\n        model.fit(X_train_scaled, y_train)\n    \n    valid_pred = model.predict(X_valid_scaled)\n    test_pred = model.predict(X_test_scaled)\n    \n    return valid_pred, test_pred\n\ndef train_and_evaluate(train_df, test_df):\n    \"\"\"Train all models with cross-validation\"\"\"\n    n_samples = len(train_df)\n    model_slices = get_model_slices(n_samples)\n    \n    # Initialize prediction dictionaries\n    oof_preds = {\n        learner[\"name\"]: {s[\"name\"]: np.zeros(n_samples) for s in model_slices}\n        for learner in LEARNERS\n    }\n    test_preds = {\n        learner[\"name\"]: {s[\"name\"]: np.zeros(len(test_df)) for s in model_slices}\n        for learner in LEARNERS\n    }\n    \n    full_weights = create_time_decay_weights(n_samples)\n    kf = KFold(n_splits=Config.N_FOLDS, shuffle=False)\n    \n    for fold, (train_idx, valid_idx) in enumerate(kf.split(train_df), start=1):\n        print(f\"\\n--- Fold {fold}/{Config.N_FOLDS} ---\")\n        X_valid = train_df.iloc[valid_idx][Config.FEATURES]\n        y_valid = train_df.iloc[valid_idx][Config.LABEL_COLUMN]\n        X_test = test_df[Config.FEATURES]\n        \n        for s in model_slices:\n            cutoff = s[\"cutoff\"]\n            slice_name = s[\"name\"]\n            subset = train_df.iloc[cutoff:].reset_index(drop=True)\n            rel_idx = train_idx[train_idx >= cutoff] - cutoff\n            \n            if len(rel_idx) == 0:\n                continue\n                \n            X_train = subset.iloc[rel_idx][Config.FEATURES]\n            y_train = subset.iloc[rel_idx][Config.LABEL_COLUMN]\n            sw = create_time_decay_weights(len(subset))[rel_idx] if cutoff > 0 else full_weights[train_idx]\n            \n            print(f\"  Training slice: {slice_name}, samples: {len(X_train)}\")\n            \n            for learner in LEARNERS:\n                try:\n                    valid_pred, test_pred = train_single_model(\n                        X_train, y_train, X_valid, y_valid, X_test, learner, sw\n                    )\n                    \n                    # Store OOF predictions\n                    mask = valid_idx >= cutoff\n                    if mask.any():\n                        idxs = valid_idx[mask]\n                        X_valid_subset = train_df.iloc[idxs][Config.FEATURES]\n                        if learner[\"need_scale\"]:\n                            scaler = RobustScaler()\n                            scaler.fit(X_train)\n                            valid_pred_subset = learner[\"Estimator\"](**learner[\"params\"]).fit(\n                                scaler.transform(X_train), y_train\n                            ).predict(scaler.transform(X_valid_subset))\n                            oof_preds[learner[\"name\"]][slice_name][idxs] = valid_pred_subset\n                        else:\n                            oof_preds[learner[\"name\"]][slice_name][idxs] = valid_pred[mask]\n                    \n                    if cutoff > 0 and (~mask).any():\n                        oof_preds[learner[\"name\"]][slice_name][valid_idx[~mask]] = \\\n                            oof_preds[learner[\"name\"]][\"full_data\"][valid_idx[~mask]]\n                    \n                    test_preds[learner[\"name\"]][slice_name] += test_pred\n                    \n                except Exception as e:\n                    print(f\"    Error training {learner['name']}: {str(e)}\")\n                    continue\n    \n    # Normalize test predictions\n    for learner_name in test_preds:\n        for slice_name in test_preds[learner_name]:\n            test_preds[learner_name][slice_name] /= Config.N_FOLDS\n    \n    return oof_preds, test_preds, model_slices\n\n# ===== Ensemble and Submission =====\ndef create_submissions(train_df, oof_preds, test_preds, submission_df):\n    \"\"\"Create multiple submission files for different strategies\"\"\"\n    all_submissions = {}\n    \n    # 1. Original baseline (XGBoost only)\n    if \"xgb_baseline\" in oof_preds:\n        xgb_oof = np.mean(list(oof_preds[\"xgb_baseline\"].values()), axis=0)\n        xgb_test = np.mean(list(test_preds[\"xgb_baseline\"].values()), axis=0)\n        xgb_score = pearsonr(train_df[Config.LABEL_COLUMN], xgb_oof)[0]\n        print(f\"\\nXGBoost Baseline Score: {xgb_score:.4f}\")\n        \n        submission_xgb = submission_df.copy()\n        submission_xgb[\"prediction\"] = xgb_test\n        submission_xgb.to_csv(f\"submission.csv\", index=False)\n        all_submissions[\"xgb_baseline\"] = xgb_score\n    \n    \n    # Print summary\n    print(\"\\n\" + \"=\"*50)\n    print(\"SUBMISSION SUMMARY:\")\n    print(\"=\"*50)\n    for name, score in sorted(all_submissions.items(), key=lambda x: x[1], reverse=True):\n        print(f\"{name:25s}: {score:.4f}\")\n    \n    return all_submissions\n\n# ===== Main Execution =====\nif __name__ == \"__main__\":\n    print(\"Loading data...\")\n    train_df, test_df, submission_df = load_data()\n    \n    print(\"\\nTraining models...\")\n    oof_preds, test_preds, model_slices = train_and_evaluate(train_df, test_df)\n    \n    print(\"\\nCreating submissions...\")\n    submission_scores = create_submissions(train_df, oof_preds, test_preds, submission_df)\n    \n    print(\"\\nAll submissions created successfully!\")\n    print(\"Files created:\")\n    print(\"- submission_xgb_baseline.csv (original baseline)\")","metadata":{"_uuid":"a7bde0a0-b189-4596-bf82-b1a5fbb241a3","_cell_guid":"24ce0cb6-5c92-44e4-8dfe-ed5dcc6ef214","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2025-07-19T22:51:17.027860Z","iopub.execute_input":"2025-07-19T22:51:17.028120Z","iopub.status.idle":"2025-07-19T22:54:36.889421Z","shell.execute_reply.started":"2025-07-19T22:51:17.028101Z","shell.execute_reply":"2025-07-19T22:54:36.888647Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}