{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.13","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":11305158,"sourceType":"competition"},{"sourceId":13734500,"sourceType":"datasetVersion","datasetId":8738740}],"dockerImageVersionId":31193,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport os\n\ninput_dir = \"/kaggle/input\"\nfor root, _, files in os.walk(input_dir):\n    for file in files:\n        print(os.path.join(root, file))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-15T00:55:11.503402Z","iopub.execute_input":"2025-11-15T00:55:11.503731Z","iopub.status.idle":"2025-11-15T00:55:11.531553Z","shell.execute_reply.started":"2025-11-15T00:55:11.503708Z","shell.execute_reply":"2025-11-15T00:55:11.530711Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pickle\nimport lightgbm as lgb\nimport kaggle_evaluation.jane_street_inference_server\nimport warnings\nwarnings.filterwarnings('ignore')\n\n\n# CONFIGURATION\n\nTHRESHOLD = 0.0  # Trade if predicted return > 0\nFEATURE_COLS = [f'feature_{i:02d}' for i in range(79)]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-15T00:56:41.125649Z","iopub.execute_input":"2025-11-15T00:56:41.126334Z","iopub.status.idle":"2025-11-15T00:56:41.819291Z","shell.execute_reply.started":"2025-11-15T00:56:41.126309Z","shell.execute_reply":"2025-11-15T00:56:41.818565Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# LOAD MODEL\n\nprint(\"Loading LightGBM model\")\n\ntry:\n    model = lgb.Booster(model_file='/kaggle/input/jane-street-trading-model-v1/models/lgb_model.txt')\n    print(\"LightGBM model loaded successfully\")\nexcept Exception as e:\n    print(f\"ERROR: Could not load model: {e}\")\n    raise","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-15T00:58:04.877920Z","iopub.execute_input":"2025-11-15T00:58:04.879003Z","iopub.status.idle":"2025-11-15T00:58:04.933870Z","shell.execute_reply.started":"2025-11-15T00:58:04.878975Z","shell.execute_reply":"2025-11-15T00:58:04.933343Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# FEATURE ENGINEERING FOR INFERENCE\n\nclass InferenceFeatureEngineer:\n    \"\"\"\n    Lightweight feature engineering for real-time inference.\n    Recreates the same features used during training.\n    \"\"\"\n\n    def __init__(self):\n        self.feature_cols = FEATURE_COLS\n\n    def transform(self, df):\n        \"\"\"Apply feature engineering optimized for speed\"\"\"\n        df_processed = df.copy()\n\n        # Fill missing values with 0\n        for col in self.feature_cols:\n            if col in df_processed.columns:\n                if df_processed[col].isnull().any():\n                    df_processed[col].fillna(0, inplace=True)\n\n        # Basic statistical features\n        available_features = [col for col in self.feature_cols if col in df_processed.columns]\n        if len(available_features) > 0:\n            feature_data = df_processed[available_features]\n            df_processed['feature_mean'] = feature_data.mean(axis=1)\n            df_processed['feature_std'] = feature_data.std(axis=1).fillna(0)\n            df_processed['feature_max'] = feature_data.max(axis=1)\n            df_processed['feature_min'] = feature_data.min(axis=1)\n            df_processed['feature_range'] = df_processed['feature_max'] - df_processed['feature_min']\n            df_processed['feature_count'] = feature_data.notna().sum(axis=1)\n\n        # CRITICAL: Advanced interaction features\n\n        # Time interactions\n        if 'feature_06' in df_processed.columns and 'time_id' in df_processed.columns:\n            df_processed['f06_x_time'] = df_processed['feature_06'] * df_processed['time_id']\n\n        if 'feature_07' in df_processed.columns and 'time_id' in df_processed.columns:\n            df_processed['f07_x_time'] = df_processed['feature_07'] * df_processed['time_id']\n\n        # Polynomial features\n        if 'feature_06' in df_processed.columns:\n            df_processed['f06_squared'] = df_processed['feature_06'] ** 2\n            df_processed['f06_cubed'] = df_processed['feature_06'] ** 3\n\n        if 'feature_07' in df_processed.columns:\n            df_processed['f07_squared'] = df_processed['feature_07'] ** 2\n\n        # Cross-feature interactions\n        if 'feature_06' in df_processed.columns and 'feature_07' in df_processed.columns:\n            df_processed['f06_x_f07'] = df_processed['feature_06'] * df_processed['feature_07']\n            df_processed['f06_div_f07'] = df_processed['feature_06'] / (df_processed['feature_07'].abs() + 1e-5)\n\n        if 'feature_06' in df_processed.columns and 'feature_05' in df_processed.columns:\n            df_processed['f06_x_f05'] = df_processed['feature_06'] * df_processed['feature_05']\n\n        if 'feature_07' in df_processed.columns and 'feature_05' in df_processed.columns:\n            df_processed['f07_x_f05'] = df_processed['feature_07'] * df_processed['feature_05']\n\n        if 'feature_05' in df_processed.columns and 'feature_07' in df_processed.columns:\n            df_processed['f05_div_f07'] = df_processed['feature_05'] / (df_processed['feature_07'].abs() + 1e-5)\n\n        # Deviation features\n        if 'feature_06' in df_processed.columns and 'feature_mean' in df_processed.columns:\n            df_processed['f06_vs_mean'] = df_processed['feature_06'] / (df_processed['feature_mean'].abs() + 1e-5)\n\n        if 'feature_06' in df_processed.columns and 'feature_std' in df_processed.columns:\n            df_processed['f06_vs_std'] = df_processed['feature_06'] / (df_processed['feature_std'] + 1e-5)\n\n        # 4. Time features (cyclical encoding - captures daily patterns)\n        if 'time_id' in df_processed.columns:\n            time_max = 1000  # Approximate max time_id\n            df_processed['time_normalized'] = df_processed['time_id'] / time_max\n            df_processed['time_sin'] = np.sin(2 * np.pi * df_processed['time_normalized'])\n            df_processed['time_cos'] = np.cos(2 * np.pi * df_processed['time_normalized'])\n            df_processed['time_period'] = (df_processed['time_normalized'] * 3).astype(int).clip(0, 2).astype(float)\n\n        return df_processed\n\n    def prepare_features(self, df):\n        \"\"\"Prepare features for model prediction\"\"\"\n        \n        feature_columns = [col for col in df.columns if (\n            col.startswith('feature_') or\n            col.startswith('f0') or  # Engineered features like f06_x_time\n            col.startswith('time_') or\n            col in ['feature_mean', 'feature_std', 'feature_max', 'feature_min',\n                   'feature_range', 'feature_count', 'symbol_id', 'time_id', 'weight']\n        )]\n\n        # Remove duplicates while preserving order\n        feature_columns = list(dict.fromkeys(feature_columns))\n\n        # Extract features\n        X = df[feature_columns].copy()\n\n        # Handle infinite values\n        X = X.replace([np.inf, -np.inf], 0)\n\n        # Final missing value check\n        X = X.fillna(0)\n\n        return X\n\n# Initialize feature engineer\nengineer = InferenceFeatureEngineer()\nprint(\"Feature engineer initialized\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-15T01:00:16.526769Z","iopub.execute_input":"2025-11-15T01:00:16.527426Z","iopub.status.idle":"2025-11-15T01:00:16.540941Z","shell.execute_reply.started":"2025-11-15T01:00:16.527389Z","shell.execute_reply":"2025-11-15T01:00:16.540096Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# PREDICTION FUNCTION \n\n# Global counters for tracking\nprediction_count = 0\ntrade_count = 0\n\ndef predict(test_df, lags_df):\n    \"\"\"\n    Main prediction function called by Jane Street inference server.\n\n    Args:\n        test_df: DataFrame with current test features\n        lags_df: DataFrame with lagged features (optional, not used here)\n\n    Returns:\n        DataFrame with prediction (responder_6 column)\n    \"\"\"\n    global prediction_count, trade_count\n\n    try:\n        # feature engineering\n        df_transformed = engineer.transform(test_df)\n\n        # feature matrix\n        X = engineer.prepare_features(df_transformed)\n\n        # prediction using LightGBM model\n        prediction = model.predict(X.values)[0]\n\n        # trading decision\n        decision = 1 if prediction > THRESHOLD else 0\n\n        # track statistics\n        prediction_count += 1\n        if decision == 1:\n            trade_count += 1\n\n        # progress update (every 1000 predictions)\n        if prediction_count % 1000 == 0:\n            trade_rate = trade_count / prediction_count * 100\n            print(f\"Predictions: {prediction_count:,} | Trades: {trade_count:,} ({trade_rate:.1f}%)\")\n\n        # return prediction in required format\n        return pd.DataFrame({'responder_6': [decision]})\n\n    except Exception as e:\n        print(f\" Prediction error: {e}\")\n        import traceback\n        traceback.print_exc()\n        # Return safe default (no trade on error)\n        return pd.DataFrame({'responder_6': [0]})","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-15T01:01:55.454125Z","iopub.execute_input":"2025-11-15T01:01:55.454807Z","iopub.status.idle":"2025-11-15T01:01:55.460727Z","shell.execute_reply.started":"2025-11-15T01:01:55.454779Z","shell.execute_reply":"2025-11-15T01:01:55.459865Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# INITIALIZE AND RUN INFERENCE SERVER\n\nprint(\"=\"*80)\nprint(\"Starting Jane Street inference server\")\nprint(\"=\"*80)\n\n# Initialize the Jane Street inference server with our predict function\ninference_server = kaggle_evaluation.jane_street_inference_server.JSInferenceServer(predict)\n\n# Simply call serve() - it handles both test and competition modes automatically\ninference_server.serve()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-15T01:02:48.918887Z","iopub.execute_input":"2025-11-15T01:02:48.919676Z","iopub.status.idle":"2025-11-15T01:02:48.965446Z","shell.execute_reply.started":"2025-11-15T01:02:48.919648Z","shell.execute_reply":"2025-11-15T01:02:48.964830Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# SUMMARY\n\nprint(\"\\n\" + \"=\"*80)\nprint(\"SUBMISSION COMPLETE\")\nprint(\"=\"*80)\nprint(f\"Total predictions: {prediction_count:,}\")\nif prediction_count > 0:\n    trade_rate = trade_count / prediction_count * 100\n    print(f\"Trades executed: {trade_count:,} ({trade_rate:.1f}%)\")\n    print(f\"\\n Performance summary:\")\n    print(f\"   - Trade rate: {trade_rate:.1f}% (target: 45-50%)\")\n    if 40 <= trade_rate <= 60:\n        print(f\"   - Status:  GOOD - Conservative strategy\")\n    elif trade_rate > 60:\n        print(f\"   - Status:   WARNING - Too aggressive, consider increasing threshold\")\n    else:\n        print(f\"   - Status:   WARNING - Too conservative, consider decreasing threshold\")\nprint(\"=\"*80)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-15T01:03:40.927619Z","iopub.execute_input":"2025-11-15T01:03:40.928276Z","iopub.status.idle":"2025-11-15T01:03:40.933451Z","shell.execute_reply.started":"2025-11-15T01:03:40.928244Z","shell.execute_reply":"2025-11-15T01:03:40.932622Z"}},"outputs":[],"execution_count":null}]}