{"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":"gpu","dataSources":[{"sourceId":96164,"databundleVersionId":12993472,"sourceType":"competition"},{"sourceId":12462463,"sourceType":"datasetVersion","datasetId":7861436},{"sourceId":12503273,"sourceType":"datasetVersion","datasetId":7870836}],"dockerImageVersionId":31041,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimport sys\nimport pandas as pd\nimport numpy as np\nfrom sklearn.model_selection import KFold\nfrom xgboost import XGBRegressor\nfrom sklearn.cross_decomposition import PLSRegression\nfrom sklearn.preprocessing import StandardScaler, RobustScaler\nfrom sklearn.ensemble import RandomForestRegressor\nfrom scipy.stats import pearsonr\nimport warnings\nfrom lightgbm import LGBMRegressor\nfrom catboost import CatBoostRegressor\nwarnings.filterwarnings('ignore')","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# =========================\n# Configuration\n# =========================\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    # Use the actual feature names from the dataset (X1, X2, etc. instead of X863, X856, etc.)\n    FEATURES = [\n        \"bid_qty\", \"ask_qty\", \"buy_qty\", \"sell_qty\", \"volume\",\n        \"X1\", \"X2\", \"X3\", \"X4\", \"X5\", \"X6\", \"X7\", \"X8\", \"X9\", \"X10\",\n        \"X11\", \"X12\", \"X13\", \"X14\", \"X15\", \"X16\", \"X17\", \"X18\", \"X19\", \"X20\",\n        \"X21\", \"X22\", \"X23\", \"X24\", \"X25\", \"X26\", \"X27\"\n    ]\n    \n    LABEL_COLUMN     = \"label\"\n    N_FOLDS          = 5  # Increased from 3 for better cross-validation\n    RANDOM_STATE     = 42\n\n# Enhanced hyperparameters\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.015,  # Slightly reduced for better generalization\n    \"max_depth\": 18,  # Reduced to prevent overfitting\n    \"max_leaves\": 10,  # Reduced\n    \"min_child_weight\": 20,  # Increased for regularization\n    \"n_estimators\": 2000,  # Increased\n    \"subsample\": 0.08,  # Slightly increased\n    \"reg_alpha\": 45.0,  # Increased regularization\n    \"reg_lambda\": 85.0,  # Increased regularization\n    \"verbosity\": 0,\n    \"random_state\": Config.RANDOM_STATE,\n    \"n_jobs\": -1,\n    \"verbose\": False,\n}\n\nLGBM_PARAMS = {\n    \"boosting_type\": \"gbdt\",\n    \"device\": \"cpu\",\n    \"n_jobs\": -1,\n    \"verbose\": -1,\n    \"random_state\": Config.RANDOM_STATE,\n    \"colsample_bytree\": 0.55,  # Slightly increased\n    \"learning_rate\": 0.008,  # Reduced for more iterations\n    \"min_child_samples\": 25,  # Increased\n    \"min_child_weight\": 0.15,  # Increased\n    \"n_estimators\": 1500,  # Increased\n    \"num_leaves\": 120,  # Reduced\n    \"reg_alpha\": 25.0,  # Increased\n    \"reg_lambda\": 65.0,  # Increased\n    \"subsample\": 0.95,  # Slightly reduced\n    \"max_depth\": 8,  # Reduced\n    \"feature_fraction\": 0.8,  # Added for regularization\n    \"bagging_fraction\": 0.9,  # Added\n    \"bagging_freq\": 5  # Added\n}\n\n# Add CatBoost for diversity\nCATBOOST_PARAMS = {\n    \"iterations\": 1000,\n    \"learning_rate\": 0.02,\n    \"depth\": 8,\n    \"l2_leaf_reg\": 30,\n    \"random_strength\": 0.5,\n    \"bagging_temperature\": 0.2,\n    \"od_type\": \"Iter\",\n    \"od_wait\": 50,\n    \"random_seed\": Config.RANDOM_STATE,\n    \"verbose\": False,\n    \"allow_writing_files\": False\n}\n\n# Enhanced learners with CatBoost\nLEARNERS = [\n    {\"name\": \"xgb\", \"Estimator\": XGBRegressor, \"params\": XGB_PARAMS, \"need_scale\": False},\n    {\"name\": \"lgbm\", \"Estimator\": LGBMRegressor, \"params\": LGBM_PARAMS, \"need_scale\": False},\n    {\"name\": \"catboost\", \"Estimator\": CatBoostRegressor, \"params\": CATBOOST_PARAMS, \"need_scale\": False}\n]","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# =========================\n# Utility Functions\n# =========================\ndef create_time_decay_weights(n: int, decay: float = 0.98) -> np.ndarray:\n    \"\"\"Enhanced time decay with stronger emphasis on recent data\"\"\"\n    positions = np.arange(n)\n    normalized = positions / (n - 1)\n    weights = decay ** (1.0 - normalized)\n    return weights * n / weights.sum()\n\ndef feature_engineering(df: pd.DataFrame) -> pd.DataFrame:\n    \"\"\"Enhanced feature engineering with more sophisticated features\"\"\"\n    df = df.copy()\n\n    # Original features\n    df['volume_weighted_sell'] = df['sell_qty'] * df['volume']\n    df['buy_sell_ratio'] = df['buy_qty'] / (df['sell_qty'] + 1e-8)\n    df['selling_pressure'] = df['sell_qty'] / (df['volume'] + 1e-8)\n    df['effective_spread_proxy'] = np.abs(df['buy_qty'] - df['sell_qty']) / (df['volume'] + 1e-8)\n    df['log_volume'] = np.log1p(df['volume'])\n    df['bid_ask_imbalance'] = (df['bid_qty'] - df['ask_qty']) / (df['bid_qty'] + df['ask_qty'] + 1e-8)\n    df['order_flow_imbalance'] = (df['buy_qty'] - df['sell_qty']) / (df['buy_qty'] + df['sell_qty'] + 1e-8)\n    df['liquidity_ratio'] = (df['bid_qty'] + df['ask_qty']) / (df['volume'] + 1e-8)\n\n    # NEW ENHANCED FEATURES\n    # Market microstructure features\n    df['total_order_qty'] = df['bid_qty'] + df['ask_qty'] + df['buy_qty'] + df['sell_qty']\n    df['market_impact'] = df['volume'] / (df['total_order_qty'] + 1e-8)\n    df['price_pressure_indicator'] = df['buy_qty'] / (df['ask_qty'] + 1e-8)\n    df['liquidity_absorption'] = df['volume'] / (df['bid_qty'] + df['ask_qty'] + 1e-8)\n    \n    # Volume-based features\n    df['volume_intensity'] = df['volume'] / (df['total_order_qty'] + 1e-8)\n    df['aggressive_buy_ratio'] = df['buy_qty'] / (df['volume'] + 1e-8)\n    df['passive_order_ratio'] = (df['bid_qty'] + df['ask_qty']) / (df['total_order_qty'] + 1e-8)\n    \n    # Cross-feature interactions\n    df['volume_bid_interaction'] = df['volume'] * df['bid_qty']\n    df['volume_ask_interaction'] = df['volume'] * df['ask_qty']\n    df['buy_sell_volume_ratio'] = (df['buy_qty'] * df['volume']) / (df['sell_qty'] * df['volume'] + 1e-8)\n    \n    # Volatility proxies using X features (works with X1, X2, etc.)\n    x_features = [col for col in df.columns if col.startswith('X')]\n    if len(x_features) >= 5:\n        # Use first 10 X features for statistical measures\n        selected_x = x_features[:min(10, len(x_features))]\n        df['x_feature_mean'] = df[selected_x].mean(axis=1)\n        df['x_feature_std'] = df[selected_x].std(axis=1)\n        df['x_feature_skew'] = df[selected_x].skew(axis=1)\n        df['x_feature_range'] = df[selected_x].max(axis=1) - df[selected_x].min(axis=1)\n        \n        # Additional interactions with more X features if available\n        if len(x_features) >= 10:\n            df['x_feature_sum'] = df[selected_x].sum(axis=1)\n    \n    # Replace infinite values and extreme outliers\n    df = df.replace([np.inf, -np.inf], np.nan)\n    numeric_cols = df.select_dtypes(include=[np.number]).columns\n    \n    for col in numeric_cols:\n        if col != Config.LABEL_COLUMN:\n            if df[col].notna().sum() > 0:  # Only process if column has non-null values\n                q99 = df[col].quantile(0.99)\n                q01 = df[col].quantile(0.01)\n                if pd.notna(q99) and pd.notna(q01):\n                    df[col] = df[col].clip(lower=q01, upper=q99)\n    \n    return df\n\n\ndef load_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    print(f\"Loaded data - Train: {train_df.shape}, Test: {test_df.shape}, Submission: {submission_df.shape}\")\n\n    # Feature Engineering\n    train_df = feature_engineering(train_df)\n    test_df = feature_engineering(test_df)\n\n    # Handle missing values more carefully\n    train_df = train_df.fillna(train_df.median()).reset_index(drop=True)\n    test_df = test_df.fillna(train_df.median())\n\n    # Update features list after engineering\n    engineered_features = [col for col in train_df.columns if col != Config.LABEL_COLUMN]\n    setattr(Config, \"FEATURES\", engineered_features)\n\n    print(f\"Processed data - Train: {train_df.shape}, Test: {test_df.shape}\")\n    print(f\"Total features after engineering: {len(engineered_features)}\")\n\n    return train_df, test_df, submission_df\n\ndef get_model_slices(n_samples: int):\n    \"\"\"Enhanced model slices with more granular time-based splits\"\"\"\n    return [\n        {\"name\": \"full_data\", \"cutoff\": 0},\n        {\"name\": \"last_80pct\", \"cutoff\": int(0.20 * n_samples)},\n        {\"name\": \"last_60pct\", \"cutoff\": int(0.40 * n_samples)},\n        {\"name\": \"last_40pct\", \"cutoff\": int(0.60 * n_samples)},\n        {\"name\": \"last_20pct\", \"cutoff\": int(0.80 * n_samples)}\n    ]\n","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# =========================\n# Training and Evaluation\n# =========================\ndef train_single_model(X_train, y_train, X_valid, y_valid, X_test, learner, sample_weights=None):\n    \"\"\"Enhanced model training with early stopping and validation\"\"\"\n    if learner[\"need_scale\"]:\n        scaler = RobustScaler()\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    # Enhanced training with early stopping\n    if learner[\"name\"] == \"xgb\":\n        model.fit(\n            X_train_scaled, y_train, \n            sample_weight=sample_weights,\n            eval_set=[(X_valid_scaled, y_valid)], \n            early_stopping_rounds=50,\n            verbose=False\n        )\n    elif learner[\"name\"] == \"lgbm\":\n        model.fit(\n            X_train_scaled, y_train, \n            sample_weight=sample_weights,\n            eval_set=[(X_valid_scaled, y_valid)],\n            callbacks=[],\n            eval_metric='rmse'\n        )\n    elif learner[\"name\"] == \"catboost\":\n        model.fit(\n            X_train_scaled, y_train,\n            sample_weight=sample_weights,\n            eval_set=(X_valid_scaled, y_valid),\n            verbose=False\n        )\n    else:\n        model.fit(X_train_scaled, y_train, sample_weight=sample_weights)\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    \"\"\"Enhanced training with better OOF handling\"\"\"\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    # Use stronger time decay\n    full_weights = create_time_decay_weights(n_samples, decay=0.98)\n    \n    # Use TimeSeriesSplit-like approach for financial data\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            \n            # Enhanced sample weights\n            if cutoff > 0:\n                sw = create_time_decay_weights(len(subset), decay=0.98)[rel_idx]\n            else:\n                sw = full_weights[train_idx]\n\n            # --- ADD THIS CHECK ---\n            MIN_SAMPLES_FOR_TRAINING = 20 # A sensible minimum\n            if len(X_train) < MIN_SAMPLES_FOR_TRAINING:\n                print(f\"  Skipping slice: {slice_name}, not enough samples ({len(X_train)})\")\n                continue # Skips this slice and moves to the next one\n            # --- END OF CHECK ---\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                    # Better OOF prediction handling\n                    valid_mask = valid_idx >= cutoff\n                    if valid_mask.any():\n                        oof_preds[learner[\"name\"]][slice_name][valid_idx[valid_mask]] = valid_pred[valid_mask]\n                    \n                    # For samples before cutoff, use full_data predictions\n                    if cutoff > 0 and (~valid_mask).any():\n                        oof_preds[learner[\"name\"]][slice_name][valid_idx[~valid_mask]] = \\\n                            oof_preds[learner[\"name\"]][\"full_data\"][valid_idx[~valid_mask]]\n                    \n                    test_preds[learner[\"name\"]][slice_name] += test_pred / Config.N_FOLDS\n                    \n                except Exception as e:\n                    print(f\"    Error training {learner['name']}: {str(e)}\")\n                    continue\n    \n    return oof_preds, test_preds, model_slices\n","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# =========================\n# Enhanced Ensemble & Submission\n# =========================\ndef ensemble_and_submit(train_df, oof_preds, test_preds, submission_df):\n    \"\"\"Enhanced ensemble with better weighting strategy\"\"\"\n    learner_ensembles = {}\n    learner_weights = {}\n    \n    for learner_name in oof_preds:\n        # Calculate performance scores for each slice\n        scores = {}\n        for s in oof_preds[learner_name]:\n            mask = oof_preds[learner_name][s] != 0  # Only consider non-zero predictions\n            if mask.sum() > 0:\n                corr = pearsonr(\n                    train_df[Config.LABEL_COLUMN][mask], \n                    oof_preds[learner_name][s][mask]\n                )[0]\n                scores[s] = max(0, corr)  # Ensure non-negative weights\n            else:\n                scores[s] = 0\n        \n        total_score = sum(scores.values())\n        if total_score == 0:\n            # Fallback to equal weights\n            weights = {s: 1.0/len(scores) for s in scores}\n        else:\n            weights = {s: scores[s] / total_score for s in scores}\n        \n        # Create ensembles\n        oof_simple = np.mean([oof_preds[learner_name][s] for s in oof_preds[learner_name]], axis=0)\n        test_simple = np.mean([test_preds[learner_name][s] for s in test_preds[learner_name]], axis=0)\n        \n        oof_weighted = sum(weights[s] * oof_preds[learner_name][s] for s in weights)\n        test_weighted = sum(weights[s] * test_preds[learner_name][s] for s in weights)\n        \n        # Calculate final scores\n        mask_simple = oof_simple != 0\n        mask_weighted = oof_weighted != 0\n        \n        score_simple = pearsonr(train_df[Config.LABEL_COLUMN][mask_simple], oof_simple[mask_simple])[0] if mask_simple.sum() > 0 else 0\n        score_weighted = pearsonr(train_df[Config.LABEL_COLUMN][mask_weighted], oof_weighted[mask_weighted])[0] if mask_weighted.sum() > 0 else 0\n        \n        print(f\"\\n{learner_name.upper()} Simple Ensemble Pearson:   {score_simple:.4f}\")\n        print(f\"{learner_name.upper()} Weighted Ensemble Pearson: {score_weighted:.4f}\")\n        \n        # Choose better performing ensemble\n        if score_weighted > score_simple:\n            learner_ensembles[learner_name] = {\"oof\": oof_weighted, \"test\": test_weighted}\n            learner_weights[learner_name] = score_weighted\n        else:\n            learner_ensembles[learner_name] = {\"oof\": oof_simple, \"test\": test_simple}\n            learner_weights[learner_name] = score_simple\n    \n    # Final ensemble with learner-level weighting\n    total_weight = sum(learner_weights.values())\n    if total_weight == 0:\n        # Equal weights fallback\n        final_oof = np.mean([le[\"oof\"] for le in learner_ensembles.values()], axis=0)\n        final_test = np.mean([le[\"test\"] for le in learner_ensembles.values()], axis=0)\n    else:\n        normalized_weights = {k: v/total_weight for k, v in learner_weights.items()}\n        final_oof = sum(normalized_weights[name] * le[\"oof\"] for name, le in learner_ensembles.items())\n        final_test = sum(normalized_weights[name] * le[\"test\"] for name, le in learner_ensembles.items())\n    \n    final_score = pearsonr(train_df[Config.LABEL_COLUMN], final_oof)[0]\n    \n    print(f\"\\nFINAL ensemble across learners Pearson: {final_score:.4f}\")\n    print(f\"Learner weights: {learner_weights}\")\n\n    submission_df[\"prediction\"] = final_test\n    # submission_df.to_csv(\"submission.csv\", index=False)\n    # print(\"Saved: submission.csv\")\n    submission_df.to_csv(\"pipeline_ensemble_submission.csv\", index=False)\n    print(\"Saved: pipeline_ensemble_submission.csv\")\n","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# =========================\n# Main Execution\n# =========================\nif __name__ == \"__main__\":\n    train_df, test_df, submission_df = load_data()\n    oof_preds, test_preds, model_slices = train_and_evaluate(train_df, test_df)\n    ensemble_and_submit(train_df, oof_preds, test_preds, submission_df)","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pandas as pd\nfrom IPython.display import display\n\n# =======================================================\n# FINAL BLENDING FUNCTION (Based on your high-scoring code)\n# =======================================================\ndef iBlend_final(sls):\n    # This is your tida function with one minor change to read from multiple paths\n    def tida(sls):\n        def read_subm(sls, i):\n            subm_dict = sls[\"subm\"][i]\n            tnm = subm_dict[\"name\"]\n            # The ONLY change is here: building the path from the 'subm' dictionary\n            # This allows us to use '/kaggle/working/', '/kaggle/input/13-juli...', etc.\n            FiN = f\"{subm_dict['path']}/{tnm}.csv\"\n            # The 'ID' column in your external files is uppercase. We'll standardize to lowercase 'id'.\n            df = pd.read_csv(FiN).rename(columns={'ID': 'id'})\n            return df.rename(columns={'prediction': tnm, sls[\"target\"]: tnm})\n\n        dfs_subm = [read_subm(sls, i) for i in range(len(sls[\"subm\"]))]\n        df_subms = dfs_subm[0]\n        for i in range(1, len(dfs_subm)):\n            df_subms = pd.merge(df_subms, dfs_subm[i], on='id')\n\n        cols = [subm['name'] for subm in sls[\"subm\"]]\n        corrects = sls[\"subwts\"]\n        weights = [subm['weight'] for subm in sls[\"subm\"]]\n        corrects2 = sls[\"subwts2\"]\n        weights2 = [subm['weight'] for subm in sls[\"subm2\"]]\n\n        def alls(x, cs=cols):\n            tes = {c: x[c] for c in cs}.items()\n            subms_sorted = [t[0] for t in sorted(tes, key=lambda k: k[1], reverse=True if sls[\"sort\"] == 'desc' else False)]\n            return subms_sorted\n\n        def correct(x, cs=cols, w=weights, cw=corrects, w2=weights2, cw2=corrects2):\n            ic = [x['alls'].index(c) for c in cs]\n            # Your proven conditional logic is preserved\n            if x['abs(mx-m)'] > 0.74:\n                cS = [x[cols[j]] * (w[j] + cw[ic[j]]) for j in range(len(cols))]\n            else:\n                cS = [x[cols[j]] * (w2[j] + cw2[ic[j]]) for j in range(len(cols))]\n            return sum(cS)\n\n        def amxm(x, cs=cols):\n            return abs(max(x[cs].tolist()) - min(x[cs].tolist()))\n\n        df_subms['abs(mx-m)'] = df_subms.apply(amxm, axis=1)\n        df_subms['alls'] = df_subms.apply(alls, axis=1)\n        df_subms[sls[\"target\"]] = df_subms.apply(correct, axis=1)\n        return df_subms\n\n    # Your proven ensemble_tida function is preserved\n    def ensemble_tida(sls):\n        sample_subm = pd.read_csv(f\"{sls['subm'][0]['path']}/{sls['subm'][0]['name']}.csv\").rename(columns={'ID': 'id'})\n        sls['sort'] = 'desc'\n        dfD = tida(sls)[['id', sls['target']]]\n        sls['sort'] = 'asc'\n        dfA = tida(sls)[['id', sls['target']]]\n        target, d, a = sls['target'], sls['desc'], sls['asc']\n        submission = sample_subm[['id']].copy()\n        submission[target] = dfD[target] * d + a * dfA[target]\n        return submission\n\n    return ensemble_tida(sls)\n\n\n# =======================================================\n# CONFIGURATION (Based on your high-scoring template)\n# =======================================================\n# 1. Define file paths and names\npath_our_model = '/kaggle/working'\npath_ext1 = '/kaggle/input/13-juli-2025-drw'\npath_ext2 = '/kaggle/input/15-juli-2025-drw'\n\nour_model_name = 'pipeline_ensemble_submission'\n\n# All 11 external model names\nexternal_names = [\n    'submission 0.70871', 'submission 0.72837', 'submission 0.73799', 'submission 0.81760', 'submission 0.82968',\n    'submission 0.83975', 'submission 0.86767', 'submission 0.88377', 'submission 0.89178', 'submission 0.90038', 'submission 0.95002'\n]\n\n# 2. Set up the parameters dictionary\n# ⚠️ IMPORTANT: These weights are an educated guess based on your template. Fine-tuning these is the key to a top score.\nparams = {\n    'target': 'prediction',\n    'q_rows': 538150,\n    'desc'  : 0.30,\n    'asc'   : 0.70,\n\n    # Following your pattern: bonus for top models, penalty for bottom. Length must be 12.\n    'subwts':  [+0.20, +0.15, +0.10, +0.05, 0.0, -0.05, -0.10, -0.10, -0.15, -0.15, -0.20, -0.20],\n    'subwts2': [+0.18, +0.13, +0.09, +0.04, 0.0, -0.04, -0.09, -0.09, -0.13, -0.13, -0.18, -0.18],\n\n    # Base weights for all 12 models.\n    'subm': [\n        {'path': path_our_model, 'name': our_model_name,      'weight': 0.25}, # Our new model\n        {'path': path_ext2,    'name': external_names[10],    'weight': 0.20}, # 0.95002\n        {'path': path_ext2,    'name': external_names[9],     'weight': 0.10}, # 0.90038\n        {'path': path_ext2,    'name': external_names[8],     'weight': 0.10}, # 0.89178\n        {'path': path_ext2,    'name': external_names[7],     'weight': 0.08}, # 0.88377\n        {'path': path_ext2,    'name': external_names[6],     'weight': 0.05}, # 0.86767\n        {'path': path_ext2,    'name': external_names[5],     'weight': 0.05}, # 0.83975\n        {'path': path_ext1,    'name': external_names[4],     'weight': 0.05}, # 0.82968\n        {'path': path_ext1,    'name': external_names[3],     'weight': 0.04}, # 0.81760\n        {'path': path_ext1,    'name': external_names[2],     'weight': 0.03}, # 0.73799\n        {'path': path_ext1,    'name': external_names[1],     'weight': 0.03}, # 0.72837\n        {'path': path_ext1,    'name': external_names[0],     'weight': 0.02}, # 0.70871\n    ],\n}\n# The 'subm2' list is a slight variation for the second condition.\nparams['subm2'] = [\n        {'path': path_our_model, 'name': our_model_name,      'weight': 0.24}, # Our new model\n        {'path': path_ext2,    'name': external_names[10],    'weight': 0.21}, # 0.95002\n        {'path': path_ext2,    'name': external_names[9],     'weight': 0.11}, # 0.90038\n        {'path': path_ext2,    'name': external_names[8],     'weight': 0.11}, # 0.89178\n        {'path': path_ext2,    'name': external_names[7],     'weight': 0.08}, # 0.88377\n        {'path': path_ext2,    'name': external_names[6],     'weight': 0.05}, # 0.86767\n        {'path': path_ext2,    'name': external_names[5],     'weight': 0.05}, # 0.83975\n        {'path': path_ext1,    'name': external_names[4],     'weight': 0.04}, # 0.82968\n        {'path': path_ext1,    'name': external_names[3],     'weight': 0.03}, # 0.81760\n        {'path': path_ext1,    'name': external_names[2],     'weight': 0.02}, # 0.73799\n        {'path': path_ext1,    'name': external_names[1],     'weight': 0.02}, # 0.72837\n        {'path': path_ext1,    'name': external_names[0],     'weight': 0.02}, # 0.70871\n]\n\n\n# =======================================================\n# EXECUTION\n# =======================================================\nprint(\"Starting final high-performance blend...\")\nfinal_submission_df = iBlend_final(params)\n\n# The 'id' column might be named 'ID' in the final output, let's standardize it\nif 'ID' in final_submission_df.columns:\n    final_submission_df = final_submission_df.rename(columns={'ID': 'id'})\n    \nfinal_submission_df.to_csv('submission.csv', index=False)\nprint(\"Final submission.csv created successfully using your high-performance logic!\")\ndisplay(final_submission_df.head())","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}