{"cells":[{"cell_type":"markdown","metadata":{},"source":"# DRW Crypto Market Prediction - Baseline\nLGBM + XGBoost ensemble with time decay weights"},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":"import numpy as np\nimport pandas as pd\nfrom sklearn.model_selection import KFold\nfrom sklearn.linear_model import Ridge\nfrom lightgbm import LGBMRegressor\nfrom xgboost import XGBRegressor\nfrom scipy.stats import pearsonr\nimport gc\n\n# ── Config ──\nFEATURES = [\n    'X863','X856','X344','X598','X862','X385','X852','X603',\n    'X860','X674','X415','X345','X137','X855','X174','X302',\n    'X178','X532','X168','X612',\n    'bid_qty','ask_qty','buy_qty','sell_qty','volume'\n]\nN_FOLDS = 5\nSEED = 42"},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":"# ── Load Data ──\ntrain = pd.read_parquet('/kaggle/input/drw-crypto-market-prediction/train.parquet',\n                         columns=FEATURES + ['label']).reset_index(drop=True)\ntest = pd.read_parquet('/kaggle/input/drw-crypto-market-prediction/test.parquet',\n                        columns=FEATURES).reset_index(drop=True)\nsub = pd.read_csv('/kaggle/input/drw-crypto-market-prediction/sample_submission.csv')\n\nX = train[FEATURES].astype(np.float32)\ny = train['label']\nX_test = test[FEATURES].astype(np.float32)\ndel train, test; gc.collect()\nprint(f'Train: {X.shape}, Test: {X_test.shape}')"},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":"# ── Time Decay Weights ──\ndef time_decay_weights(n, decay=0.95):\n    w = decay ** (1.0 - np.arange(n) / (n - 1))\n    return w * n / w.sum()\n\nweights = time_decay_weights(len(X))"},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":"# ── Model Params (from top public notebooks) ──\nlgbm_params = dict(\n    boosting_type='gbdt', device='gpu', n_jobs=-1, verbose=-1,\n    random_state=SEED, colsample_bytree=0.50, learning_rate=0.013,\n    min_child_samples=20, n_estimators=900, num_leaves=145,\n    reg_alpha=19.2, reg_lambda=55.5, subsample=0.97, max_depth=9\n)\n\nxgb_params = dict(\n    tree_method='hist', device='gpu', n_jobs=-1, verbosity=0,\n    random_state=SEED, colsample_bylevel=0.48, colsample_bynode=0.36,\n    colsample_bytree=0.71, gamma=1.71, learning_rate=0.022,\n    max_depth=20, max_leaves=12, min_child_weight=16,\n    n_estimators=1667, subsample=0.066, reg_alpha=39.4, reg_lambda=75.4\n)"},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":"# ── Cross Validation ──\nkf = KFold(n_splits=N_FOLDS, shuffle=False)\noof_lgbm = np.zeros(len(X))\noof_xgb = np.zeros(len(X))\ntest_lgbm = np.zeros(len(X_test))\ntest_xgb = np.zeros(len(X_test))\n\nfor fold, (tr_idx, va_idx) in enumerate(kf.split(X), 1):\n    print(f'\\n=== Fold {fold}/{N_FOLDS} ===')\n    X_tr, X_va = X.iloc[tr_idx], X.iloc[va_idx]\n    y_tr, y_va = y.iloc[tr_idx], y.iloc[va_idx]\n    sw = weights[tr_idx]\n\n    # LightGBM\n    lgbm = LGBMRegressor(**lgbm_params)\n    lgbm.fit(X_tr, y_tr, sample_weight=sw, eval_set=[(X_va, y_va)])\n    oof_lgbm[va_idx] = lgbm.predict(X_va)\n    test_lgbm += lgbm.predict(X_test) / N_FOLDS\n    score_lgbm = pearsonr(y_va, oof_lgbm[va_idx])[0]\n\n    # XGBoost\n    xgb = XGBRegressor(**xgb_params)\n    xgb.fit(X_tr, y_tr, sample_weight=sw, eval_set=[(X_va, y_va)])\n    oof_xgb[va_idx] = xgb.predict(X_va)\n    test_xgb += xgb.predict(X_test) / N_FOLDS\n    score_xgb = pearsonr(y_va, oof_xgb[va_idx])[0]\n\n    print(f'  LGBM: {score_lgbm:.6f}  |  XGB: {score_xgb:.6f}')\n    del lgbm, xgb; gc.collect()"},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":"# ── Overall Scores ──\ns_lgbm = pearsonr(y, oof_lgbm)[0]\ns_xgb = pearsonr(y, oof_xgb)[0]\nprint(f'LGBM OOF Pearson: {s_lgbm:.6f}')\nprint(f'XGB  OOF Pearson: {s_xgb:.6f}')"},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":"# ── Simple Ensemble (Ridge meta-learner) ──\nmeta_X = np.column_stack([oof_lgbm, oof_xgb])\nmeta_X_test = np.column_stack([test_lgbm, test_xgb])\n\nridge = Ridge(alpha=1.0)\nridge.fit(meta_X, y)\noof_final = ridge.predict(meta_X)\ntest_final = ridge.predict(meta_X_test)\n\ns_final = pearsonr(y, oof_final)[0]\nprint(f'\\nEnsemble OOF Pearson: {s_final:.6f}')\nprint(f'Ridge weights: LGBM={ridge.coef_[0]:.4f}, XGB={ridge.coef_[1]:.4f}')"},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":"# ── Submit ──\nsub['prediction'] = test_final\nsub.to_csv('submission.csv', index=False)\nprint('Saved submission.csv')\nsub.head()"}],"metadata":{"accelerator":"GPU","language_info":{"name":"python"},"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"}},"nbformat":4,"nbformat_minor":4}