{"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":"none","dataSources":[{"sourceId":117097,"databundleVersionId":14080503,"sourceType":"competition"},{"sourceId":13280781,"sourceType":"datasetVersion","datasetId":8416714},{"sourceId":13491955,"sourceType":"datasetVersion","datasetId":8566279}],"dockerImageVersionId":31192,"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":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-11-09T14:20:34.938945Z","iopub.execute_input":"2025-11-09T14:20:34.939902Z","iopub.status.idle":"2025-11-09T14:20:34.954498Z","shell.execute_reply.started":"2025-11-09T14:20:34.939860Z","shell.execute_reply":"2025-11-09T14:20:34.952770Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# **Data Classification**","metadata":{}},{"cell_type":"markdown","source":"## **Importing Libraries**","metadata":{}},{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nimport seaborn as sns\nimport xgboost as xgb\nimport lightgbm as lgb\nimport category_encoders as ce\nimport matplotlib.pyplot as plt\nfrom xgboost import XGBClassifier\nfrom catboost import CatBoostClassifier\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.preprocessing import StandardScaler, LabelEncoder\nfrom sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score, confusion_matrix, classification_report, precision_recall_curve, roc_auc_score\n\nimport warnings\nwarnings.filterwarnings('ignore')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-15T12:16:02.744577Z","iopub.execute_input":"2025-11-15T12:16:02.744919Z","iopub.status.idle":"2025-11-15T12:16:02.751123Z","shell.execute_reply.started":"2025-11-15T12:16:02.744896Z","shell.execute_reply":"2025-11-15T12:16:02.750026Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## **Reading Train data**","metadata":{}},{"cell_type":"code","source":"# path of files\nbase_path = '/kaggle/input/pumpfun-30s-september-2025/'\n\n# list of files path\nfiles = [\n    base_path + 'september_2025_first30s_chunk_001.csv',\n    base_path + 'september_2025_first30s_chunk_002.csv',\n    base_path + 'september_2025_first30s_chunk_003.csv',\n    base_path + 'september_2025_first30s_chunk_004.csv',\n    base_path + 'september_2025_first30s_chunk_005.csv',\n    base_path + 'september_2025_first30s_chunk_006.csv',\n    base_path + 'september_2025_first30s_chunk_007.csv',\n    base_path + 'september_2025_first30s_chunk_008.csv',\n    base_path + 'september_2025_first30s_chunk_009.csv',\n    base_path + 'september_2025_first30s_chunk_010.csv',\n    base_path + 'september_2025_first30s_chunk_011.csv',\n    base_path + 'september_2025_first30s_chunk_012.csv',\n    base_path + 'september_2025_first30s_chunk_013.csv',\n    base_path + 'september_2025_first30s_chunk_014.csv',\n    base_path + 'september_2025_first30s_chunk_015.csv'\n]\n\n# to conact betwen all files at the same DataFrame\ntrain_df = pd.concat([pd.read_csv(f) for f in files], ignore_index=True)\nprint(f\"Shape: {train_df.shape}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-09T14:20:34.975894Z","iopub.execute_input":"2025-11-09T14:20:34.976351Z","iopub.status.idle":"2025-11-09T14:21:49.600957Z","shell.execute_reply.started":"2025-11-09T14:20:34.976305Z","shell.execute_reply":"2025-11-09T14:21:49.595778Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"To Merge with target tokens to add is_target column:","metadata":{}},{"cell_type":"code","source":"# Read Target Tokens (adjust path if needed)\ntarget_tokens = pd.read_csv('/kaggle/input/alpha-reader/Alpha Radar Target Tokens.csv')\n\n# Rename the column in target_tokens to match train_df\ntarget_tokens.rename(columns={'Target Token Addresses': 'mint_token_id'}, inplace=True)\n\n# Create 'is_target' column in the training data\ntrain_df['is_target'] = train_df['mint_token_id'].isin(target_tokens['mint_token_id']).astype(int)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-09T14:21:49.604760Z","iopub.execute_input":"2025-11-09T14:21:49.605161Z","iopub.status.idle":"2025-11-09T14:21:50.373181Z","shell.execute_reply.started":"2025-11-09T14:21:49.605136Z","shell.execute_reply":"2025-11-09T14:21:50.371784Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_df.shape","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-09T14:21:50.374154Z","iopub.execute_input":"2025-11-09T14:21:50.374484Z","iopub.status.idle":"2025-11-09T14:21:50.381997Z","shell.execute_reply.started":"2025-11-09T14:21:50.374463Z","shell.execute_reply":"2025-11-09T14:21:50.380568Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_df.info()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-09T14:21:50.383276Z","iopub.execute_input":"2025-11-09T14:21:50.383590Z","iopub.status.idle":"2025-11-09T14:21:50.416670Z","shell.execute_reply.started":"2025-11-09T14:21:50.383564Z","shell.execute_reply":"2025-11-09T14:21:50.415375Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_df.head(7)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-09T14:21:50.418335Z","iopub.execute_input":"2025-11-09T14:21:50.418761Z","iopub.status.idle":"2025-11-09T14:21:50.477554Z","shell.execute_reply.started":"2025-11-09T14:21:50.418737Z","shell.execute_reply":"2025-11-09T14:21:50.475248Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_df.describe()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-09T14:21:50.479533Z","iopub.execute_input":"2025-11-09T14:21:50.479862Z","iopub.status.idle":"2025-11-09T14:22:05.404629Z","shell.execute_reply.started":"2025-11-09T14:21:50.479839Z","shell.execute_reply":"2025-11-09T14:22:05.403275Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## **Data Cleaning**","metadata":{}},{"cell_type":"markdown","source":"### **Nulls**","metadata":{}},{"cell_type":"markdown","source":"To check if data has any **Nulls :**","metadata":{}},{"cell_type":"code","source":"train_df.isnull().sum()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-09T14:22:05.407977Z","iopub.execute_input":"2025-11-09T14:22:05.408615Z","iopub.status.idle":"2025-11-09T14:22:08.485729Z","shell.execute_reply.started":"2025-11-09T14:22:05.408590Z","shell.execute_reply":"2025-11-09T14:22:08.484288Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### **Outliers**","metadata":{}},{"cell_type":"markdown","source":"To calculate Percentage of Outliers we use this code:","metadata":{}},{"cell_type":"code","source":"def outlier_percentage(train_df):\n    numeric_cols = train_df.select_dtypes(include=['int64', 'float64']).columns\n    results = []\n\n    for col in numeric_cols:\n        Q1 = train_df[col].quantile(0.25)\n        Q3 = train_df[col].quantile(0.75)\n        IQR = Q3 - Q1\n        lower = Q1 - 1.5 * IQR\n        upper = Q3 + 1.5 * IQR\n        \n        # Outliers\n        outliers = train_df[(train_df[col] < lower) | (train_df[col] > upper)][col].count()\n        total = train_df[col].notnull().sum()\n        percent = (outliers / total) * 100\n        \n        results.append({\n            'Column': col,\n            'num of Outliers':outliers,\n            'Total': total,\n            'Percentage of Outliers (%)': round(percent, 2)})\n    \n    return pd.DataFrame(results)\n\n\noutlier_df = outlier_percentage(train_df)\nprint(outlier_df)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-09T14:22:08.487177Z","iopub.execute_input":"2025-11-09T14:22:08.487558Z","iopub.status.idle":"2025-11-09T14:22:29.234162Z","shell.execute_reply.started":"2025-11-09T14:22:08.487533Z","shell.execute_reply":"2025-11-09T14:22:29.232976Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"To extract only features which contain more than > 10% outliers:","metadata":{}},{"cell_type":"code","source":"# Filter columns with high outlier percentage (e.g., >10%)\nhigh_outlier_df = outlier_df[outlier_df['Percentage of Outliers (%)'] > 10]\n\n# Display them sorted by percentage (highest first)\nhigh_outlier_df = high_outlier_df.sort_values('Percentage of Outliers (%)', ascending=False)\n\n# Print result\nprint(\"Columns with a high percentage of outliers (>10%):\")\nprint(high_outlier_df[['Column', 'Percentage of Outliers (%)']])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-09T14:22:29.235437Z","iopub.execute_input":"2025-11-09T14:22:29.235786Z","iopub.status.idle":"2025-11-09T14:22:29.248162Z","shell.execute_reply.started":"2025-11-09T14:22:29.235758Z","shell.execute_reply":"2025-11-09T14:22:29.246932Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_df['rate_of_change'].min(),train_df['rate_of_change'].max()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-09T14:22:29.249103Z","iopub.execute_input":"2025-11-09T14:22:29.249414Z","iopub.status.idle":"2025-11-09T14:22:29.295012Z","shell.execute_reply.started":"2025-11-09T14:22:29.249390Z","shell.execute_reply":"2025-11-09T14:22:29.293803Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_df['volume_oscillator'].min(),train_df['volume_oscillator'].max()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-09T14:22:29.296034Z","iopub.execute_input":"2025-11-09T14:22:29.296397Z","iopub.status.idle":"2025-11-09T14:22:29.329488Z","shell.execute_reply.started":"2025-11-09T14:22:29.296372Z","shell.execute_reply":"2025-11-09T14:22:29.328296Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_df['token_quantity'].min(),train_df['token_quantity'].max()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-09T14:22:29.330939Z","iopub.execute_input":"2025-11-09T14:22:29.331392Z","iopub.status.idle":"2025-11-09T14:22:29.364526Z","shell.execute_reply.started":"2025-11-09T14:22:29.331366Z","shell.execute_reply":"2025-11-09T14:22:29.363472Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_df['token_delta'].min(),train_df['token_delta'].max()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-09T14:22:29.365947Z","iopub.execute_input":"2025-11-09T14:22:29.366257Z","iopub.status.idle":"2025-11-09T14:22:29.400524Z","shell.execute_reply.started":"2025-11-09T14:22:29.366234Z","shell.execute_reply":"2025-11-09T14:22:29.399369Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_df['relative_strength_index'].min(),train_df['relative_strength_index'].max()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-09T14:22:29.401924Z","iopub.execute_input":"2025-11-09T14:22:29.403166Z","iopub.status.idle":"2025-11-09T14:22:29.437094Z","shell.execute_reply.started":"2025-11-09T14:22:29.403129Z","shell.execute_reply":"2025-11-09T14:22:29.436114Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_df['sol_delta'].min(),train_df['sol_delta'].max()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-09T14:22:29.438269Z","iopub.execute_input":"2025-11-09T14:22:29.438579Z","iopub.status.idle":"2025-11-09T14:22:29.473250Z","shell.execute_reply.started":"2025-11-09T14:22:29.438558Z","shell.execute_reply":"2025-11-09T14:22:29.472220Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_df.columns","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-09T14:22:29.474484Z","iopub.execute_input":"2025-11-09T14:22:29.474806Z","iopub.status.idle":"2025-11-09T14:22:29.481777Z","shell.execute_reply.started":"2025-11-09T14:22:29.474783Z","shell.execute_reply":"2025-11-09T14:22:29.480793Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## **Feature Extraction**","metadata":{}},{"cell_type":"markdown","source":"**TimeStamp Feature**","metadata":{}},{"cell_type":"code","source":"train_df['timestamp']","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-09T14:22:29.482863Z","iopub.execute_input":"2025-11-09T14:22:29.483136Z","iopub.status.idle":"2025-11-09T14:22:29.504601Z","shell.execute_reply.started":"2025-11-09T14:22:29.483115Z","shell.execute_reply":"2025-11-09T14:22:29.503360Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Split the timestamp into minutes, seconds, and sub-seconds\ntimestamp_split = train_df['timestamp'].str.split(':', expand=True)\ntrain_df['minute'] = timestamp_split[0].astype(int)\n\nsec_split = timestamp_split[1].str.split('.', expand=True)\ntrain_df['second'] = sec_split[0].astype(int)\ntrain_df['sub_second'] = sec_split[1].astype(int)\n\n# Drop the original timestamp column\ntrain_df = train_df.drop(columns=['timestamp'])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-09T14:22:29.505500Z","iopub.execute_input":"2025-11-09T14:22:29.505824Z","iopub.status.idle":"2025-11-09T14:23:19.774539Z","shell.execute_reply.started":"2025-11-09T14:22:29.505801Z","shell.execute_reply":"2025-11-09T14:23:19.773322Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"**At Mint_token_id**","metadata":{}},{"cell_type":"code","source":"train_df['mint_token_id']","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-09T14:23:19.775645Z","iopub.execute_input":"2025-11-09T14:23:19.775994Z","iopub.status.idle":"2025-11-09T14:23:19.785161Z","shell.execute_reply.started":"2025-11-09T14:23:19.775965Z","shell.execute_reply":"2025-11-09T14:23:19.783991Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Length of the token ID\ntrain_df['token_id_length'] = train_df['mint_token_id'].str.len()\n\n# Prefix and suffix (last 4 characters)\ntrain_df['token_suffix'] = train_df['mint_token_id'].str[-4:]\n\n# Count of digits, uppercase letters, and lowercase letters\ntrain_df['num_digits'] = train_df['mint_token_id'].str.count(r'\\d')\ntrain_df['num_upper'] = train_df['mint_token_id'].str.count(r'[A-Z]')\ntrain_df['num_lower'] = train_df['mint_token_id'].str.count(r'[a-z]')\n\n# Frequency of each token ID in the dataset\ntoken_counts = train_df['mint_token_id'].value_counts()\ntrain_df['token_frequency'] = train_df['mint_token_id'].map(token_counts)\n\n\n# Token suffix\ntoken_suffix_encoder = ce.TargetEncoder(cols=['token_suffix'])\ntrain_df['token_suffix_encoded'] = token_suffix_encoder.fit_transform(train_df['token_suffix'], train_df['is_target'])\n\n# Drop the original column if desired\ntrain_df = train_df.drop(columns=['mint_token_id','token_suffix'])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-09T14:23:19.786525Z","iopub.execute_input":"2025-11-09T14:23:19.786894Z","iopub.status.idle":"2025-11-09T14:25:11.484631Z","shell.execute_reply.started":"2025-11-09T14:23:19.786864Z","shell.execute_reply":"2025-11-09T14:25:11.483286Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"**At holder**","metadata":{}},{"cell_type":"code","source":"# Length of the holder ID\ntrain_df['holder_length'] = train_df['holder'].str.len()\n\n# Last 4 characters (suffix)\ntrain_df['holder_suffix'] = train_df['holder'].str[-4:]\n\n# Count of digits, uppercase letters, and lowercase letters\ntrain_df['num_digits_holder'] = train_df['holder'].str.count(r'\\d')\ntrain_df['num_upper_holder'] = train_df['holder'].str.count(r'[A-Z]')\ntrain_df['num_lower_holder'] = train_df['holder'].str.count(r'[a-z]')\n\n# Frequency of each holder in the dataset\nholder_counts = train_df['holder'].value_counts()\ntrain_df['holder_frequency'] = train_df['holder'].map(holder_counts)\n\n\n# Holder suffix\nholder_suffix_encoder = ce.TargetEncoder(cols=['holder_suffix'])\ntrain_df['holder_suffix_encoded'] = holder_suffix_encoder.fit_transform(train_df['holder_suffix'], train_df['is_target'])\n\n# Drop the original columns\ntrain_df = train_df.drop(columns=['holder','holder_suffix'])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-09T14:25:11.485829Z","iopub.execute_input":"2025-11-09T14:25:11.486112Z","iopub.status.idle":"2025-11-09T14:27:16.757123Z","shell.execute_reply.started":"2025-11-09T14:25:11.486089Z","shell.execute_reply":"2025-11-09T14:27:16.755759Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"**At trade_mode**","metadata":{}},{"cell_type":"code","source":"train_df['trade_mode'].unique()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-09T14:27:16.763786Z","iopub.execute_input":"2025-11-09T14:27:16.764154Z","iopub.status.idle":"2025-11-09T14:27:17.268934Z","shell.execute_reply.started":"2025-11-09T14:27:16.764129Z","shell.execute_reply":"2025-11-09T14:27:17.267800Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Encode 'trade_mode' as numeric: buy = 1, sell = 0\ntrain_df['trade_mode_encoded'] = train_df['trade_mode'].map({'buy': 1, 'sell': 0})\n\n# Then drop the original column\ntrain_df = train_df.drop(columns=['trade_mode'])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-09T14:27:17.269992Z","iopub.execute_input":"2025-11-09T14:27:17.270273Z","iopub.status.idle":"2025-11-09T14:27:19.535866Z","shell.execute_reply.started":"2025-11-09T14:27:17.270253Z","shell.execute_reply":"2025-11-09T14:27:19.534545Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"**At Creator feature**","metadata":{}},{"cell_type":"code","source":"train_df['creator']","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-09T14:27:19.537626Z","iopub.execute_input":"2025-11-09T14:27:19.537913Z","iopub.status.idle":"2025-11-09T14:27:19.546556Z","shell.execute_reply.started":"2025-11-09T14:27:19.537893Z","shell.execute_reply":"2025-11-09T14:27:19.544984Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Create a Target Encoder\ntarget_encoder = ce.TargetEncoder(cols=['creator'])\n\n# Fit the encoder on the train data\ntrain_df['creator_encoded'] = target_encoder.fit_transform(train_df['creator'], train_df['is_target'])\n\n# Drop the original column\ntrain_data = train_df['creator'].copy()\ntrain_df = train_df.drop(columns=['creator'])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-09T14:27:19.547855Z","iopub.execute_input":"2025-11-09T14:27:19.548287Z","iopub.status.idle":"2025-11-09T14:27:30.095494Z","shell.execute_reply.started":"2025-11-09T14:27:19.548251Z","shell.execute_reply":"2025-11-09T14:27:30.094220Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"**Another features**","metadata":{}},{"cell_type":"code","source":"# Max\nMAX_VAL = 1e10\n\n# calculate percentage and avoid devided on zero\ntrain_df['delta_ratio'] = train_df['token_delta'] / np.maximum(train_df['sol_delta'], 1e-6)\ntrain_df['volume_ratio'] = train_df['token_volume'] / np.maximum(train_df['sol_volume'], 1e-6)\ntrain_df['cap_to_fee'] = train_df['market_cap_usd'] / np.maximum(train_df['creator_fee'], 1e-6)\ntrain_df['activity_ratio'] = train_df['total_count'] / np.maximum(train_df['token_frequency'], 1)\ntrain_df['buy_rate'] = train_df['buy_count'] / np.maximum(train_df['total_count'], 1)\ntrain_df['sell_rate'] = train_df['sell_count'] / np.maximum(train_df['total_count'], 1)\ntrain_df['holder_to_token_ratio'] = train_df['holder_length'] / np.maximum(train_df['token_id_length'], 1)\ntrain_df['bollinger_rsi_ratio'] = train_df['bollinger_relative_position'] / np.maximum(train_df['relative_strength_index'], 1)\ntrain_df['creator_impact'] = (train_df['creator_balance'] - train_df['creator_fee_pump']) / np.maximum(train_df['market_cap_usd'], 1)\ntrain_df['top10_ratio'] = train_df['top10_percent_total'] / np.maximum(train_df['market_cap_usd'], 1)\n\n# safe processing (add and multiply)\ntrain_df['time_complexity'] = train_df['minute']*60 + train_df['second'] + train_df['sub_second']/1000\ntrain_df['is_fast_tx'] = (train_df['sub_second'] < 500).astype(int)\ntrain_df['id_complexity'] = train_df['num_digits'] + train_df['num_upper'] + train_df['num_lower']\ntrain_df['holder_complexity'] = train_df['num_digits_holder'] + train_df['num_upper_holder'] + train_df['num_lower_holder']\ntrain_df['rsi_mfi_interaction'] = train_df['relative_strength_index'] * train_df['money_flow_index']\ntrain_df['volatility_strength'] = abs(train_df['rate_of_change']) * train_df['volume_oscillator']\ntrain_df['holder_retention'] = train_df['current_holders'] / np.maximum(train_df['total_holders'], 1)\n\n# replace any huage value by maximum value\nfor col in ['delta_ratio', 'volume_ratio', 'cap_to_fee', 'holder_to_token_ratio', \n            'bollinger_rsi_ratio', 'creator_impact', 'top10_ratio']:\n    train_df[col] = np.clip(train_df[col], -MAX_VAL, MAX_VAL)\n\n# Remove any INF or NaN\ntrain_df.replace([np.inf, -np.inf], np.nan, inplace=True)\ntrain_df.fillna(0, inplace=True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-09T14:27:30.096795Z","iopub.execute_input":"2025-11-09T14:27:30.097126Z","iopub.status.idle":"2025-11-09T14:27:42.261652Z","shell.execute_reply.started":"2025-11-09T14:27:30.097104Z","shell.execute_reply":"2025-11-09T14:27:42.260337Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_df.shape","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-09T14:27:42.264095Z","iopub.execute_input":"2025-11-09T14:27:42.265017Z","iopub.status.idle":"2025-11-09T14:27:42.273826Z","shell.execute_reply.started":"2025-11-09T14:27:42.264979Z","shell.execute_reply":"2025-11-09T14:27:42.272485Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_df.info()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-09T14:27:42.275059Z","iopub.execute_input":"2025-11-09T14:27:42.275381Z","iopub.status.idle":"2025-11-09T14:27:42.351044Z","shell.execute_reply.started":"2025-11-09T14:27:42.275357Z","shell.execute_reply":"2025-11-09T14:27:42.349924Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# float64 -> float32\nfor col in train_df.select_dtypes(include=['float64']).columns:\n    train_df[col] = train_df[col].astype(np.float32)\n\n# int64 -> int32 or uint16 \nfor col in train_df.select_dtypes(include=['int64']).columns:\n    if train_df[col].min() >= 0:\n        if train_df[col].max() < 256:\n            train_df[col] = train_df[col].astype(np.uint8)\n        elif train_df[col].max() < 65536:\n            train_df[col] = train_df[col].astype(np.uint16)\n        else:\n            train_df[col] = train_df[col].astype(np.int32)\n    else:\n        train_df[col] = train_df[col].astype(np.int32)\n\n# ===== Feature Engineering =====\n# Interaction Features\ntrain_df['rsi_mfi_interaction'] = train_df['relative_strength_index'] * train_df['money_flow_index']\ntrain_df['cap_to_fee_ratio'] = train_df['market_cap_usd'] / (train_df['creator_fee'] + 1e-9)\ntrain_df['volume_liquidity_ratio'] = train_df['token_volume'] / (train_df['liquidity_ratio'] + 1e-9)\n\n# Log Transform \nlarge_cols = ['market_cap_usd', 'token_volume', 'sol_volume', 'creator_balance']\nfor col in large_cols:\n    train_df[col + '_log'] = np.log1p(train_df[col])\n\n# Cyclical Encoding \ntrain_df['minute_sin'] = np.sin(2 * np.pi * train_df['minute']/60)\ntrain_df['minute_cos'] = np.cos(2 * np.pi * train_df['minute']/60)\ntrain_df['second_sin'] = np.sin(2 * np.pi * train_df['second']/60)\ntrain_df['second_cos'] = np.cos(2 * np.pi * train_df['second']/60)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-09T14:27:42.352462Z","iopub.execute_input":"2025-11-09T14:27:42.352820Z","iopub.status.idle":"2025-11-09T14:27:46.203713Z","shell.execute_reply.started":"2025-11-09T14:27:42.352796Z","shell.execute_reply":"2025-11-09T14:27:46.202365Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"To Check if there is any NAN or INF at our data:","metadata":{}},{"cell_type":"code","source":"# Numerical columns\nnumeric_df = train_df.select_dtypes(include=[np.number])\n\n# check NaN and INF \nprint(\"Number of INF:\", np.isinf(numeric_df).sum().sum())\nprint(\"Number of NaN:\", np.isnan(numeric_df).sum().sum())","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-09T14:27:46.205169Z","iopub.execute_input":"2025-11-09T14:27:46.205618Z","iopub.status.idle":"2025-11-09T14:27:52.003340Z","shell.execute_reply.started":"2025-11-09T14:27:46.205584Z","shell.execute_reply":"2025-11-09T14:27:52.002286Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_df.columns","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-09T14:27:52.004568Z","iopub.execute_input":"2025-11-09T14:27:52.004866Z","iopub.status.idle":"2025-11-09T14:27:52.012847Z","shell.execute_reply.started":"2025-11-09T14:27:52.004842Z","shell.execute_reply":"2025-11-09T14:27:52.011622Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## **Splitting data**","metadata":{}},{"cell_type":"markdown","source":"To sheck if output feature has implance data or not:","metadata":{}},{"cell_type":"code","source":"train_df['is_target'].value_counts()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-09T14:27:52.013892Z","iopub.execute_input":"2025-11-09T14:27:52.014410Z","iopub.status.idle":"2025-11-09T14:27:52.086961Z","shell.execute_reply.started":"2025-11-09T14:27:52.014382Z","shell.execute_reply":"2025-11-09T14:27:52.085790Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#show pie plot\ntrain_df['is_target'].value_counts().plot.pie(autopct='%.2f')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-09T14:27:52.088413Z","iopub.execute_input":"2025-11-09T14:27:52.088953Z","iopub.status.idle":"2025-11-09T14:27:52.286845Z","shell.execute_reply.started":"2025-11-09T14:27:52.088919Z","shell.execute_reply":"2025-11-09T14:27:52.285629Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Output column appear data has impalanced data se we deal with data to make it palanced:","metadata":{}},{"cell_type":"code","source":"zeros = train_df[train_df.is_target==0]\nones = train_df[train_df.is_target==1]\nprint(zeros.shape)\nprint(ones.shape)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-09T14:27:52.288049Z","iopub.execute_input":"2025-11-09T14:27:52.288428Z","iopub.status.idle":"2025-11-09T14:27:55.701460Z","shell.execute_reply.started":"2025-11-09T14:27:52.288402Z","shell.execute_reply":"2025-11-09T14:27:55.699956Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"zeros_sample = zeros.sample(980000)\nprint(zeros_sample.shape)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-09T14:27:55.702542Z","iopub.execute_input":"2025-11-09T14:27:55.702838Z","iopub.status.idle":"2025-11-09T14:27:57.514287Z","shell.execute_reply.started":"2025-11-09T14:27:55.702817Z","shell.execute_reply":"2025-11-09T14:27:57.512897Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"new_data = pd.concat([zeros_sample,ones] ,axis=0)\nnew_data.head(7)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-09T14:27:57.515454Z","iopub.execute_input":"2025-11-09T14:27:57.515812Z","iopub.status.idle":"2025-11-09T14:27:57.694017Z","shell.execute_reply.started":"2025-11-09T14:27:57.515787Z","shell.execute_reply":"2025-11-09T14:27:57.692651Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"We check corroleation between data and check if there is any data leakage:","metadata":{}},{"cell_type":"code","source":"target = 'is_target'\n\nreport = []\n\nfor col in train_df.columns:\n    if col == target:\n        continue\n    \n    # correlation with target ( float)\n    if np.issubdtype(train_df[col].dtype, np.number):\n        corr = train_df[col].corr(train_df[target])\n    else:\n        corr = np.nan\n    \n    # uniqueness\n    n_unique = train_df[col].nunique()\n    n_total = len(train_df)\n    uniqueness = n_unique / n_total\n    \n    # if column is potential leak(corr or uniqueness very low/high)\n    potential_leak = False\n    if corr is not np.nan and abs(corr) > 0.8:\n        potential_leak = True\n    if uniqueness < 0.001 or uniqueness > 0.999:\n        potential_leak = True\n\n    # if time columns\n    time_col = any(x in col.lower() for x in ['time','minute','second','hour'])\n    \n    report.append({\n        'feature': col,\n        'dtype': train_df[col].dtype,\n        'corr_with_target': corr,\n        'abs_corr': abs(corr) if corr is not np.nan else np.nan,\n        'uniqueness': uniqueness,\n        'is_time_feature': time_col,\n        'potential_leak': potential_leak\n    })\n\nreport_df = pd.DataFrame(report).sort_values(by='abs_corr', ascending=False)\nprint(report_df.head(20))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-09T14:27:57.695142Z","iopub.execute_input":"2025-11-09T14:27:57.695524Z","iopub.status.idle":"2025-11-09T14:28:48.609179Z","shell.execute_reply.started":"2025-11-09T14:27:57.695499Z","shell.execute_reply":"2025-11-09T14:28:48.608171Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"We drop features which make data leakage:","metadata":{}},{"cell_type":"code","source":"# feature which make data leakage\nleak_cols = report_df.loc[report_df['potential_leak'] == True, 'feature'].tolist()\ntime_cols = report_df.loc[report_df['is_time_feature'] == True, 'feature'].tolist()\n\nextra_drop = ['index', 'is_target']\n\n# safe X\nX_safe = new_data.drop(columns=leak_cols + time_cols + extra_drop)\nfeature_cols_safe = X_safe.columns.tolist()\n\n# target\ny = new_data['is_target']\n\nprint(\"Number of safe features:\", len(feature_cols_safe))\nprint(\"Dropped leak/time features + extra:\", leak_cols + time_cols + extra_drop)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-09T14:28:48.610179Z","iopub.execute_input":"2025-11-09T14:28:48.610510Z","iopub.status.idle":"2025-11-09T14:28:48.827790Z","shell.execute_reply.started":"2025-11-09T14:28:48.610488Z","shell.execute_reply":"2025-11-09T14:28:48.826536Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"X_train, X_val, y_train, y_val = train_test_split(X_safe, y, test_size=0.2, random_state=42, stratify=y)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-09T14:28:48.828867Z","iopub.execute_input":"2025-11-09T14:28:48.829174Z","iopub.status.idle":"2025-11-09T14:28:49.994972Z","shell.execute_reply.started":"2025-11-09T14:28:48.829151Z","shell.execute_reply":"2025-11-09T14:28:49.993782Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## **Modeling**","metadata":{}},{"cell_type":"markdown","source":"**We use CatBoostClassifier Model**","metadata":{}},{"cell_type":"code","source":"scale_weight = 980000/397893\nmodel = CatBoostClassifier(\n    iterations=1000,\n    learning_rate=0.05,\n    depth=8,\n    eval_metric='AUC',\n    scale_pos_weight = scale_weight,\n    verbose=100\n)\neval_set = (X_val,y_val)\nmodel.fit(X_train,y_train,\n          eval_set = eval_set,\n          use_best_model=True)\n\ny_pred_proba = model.predict_proba(X_val)[: ,1]\nauc = roc_auc_score(y_val,y_pred_proba)\nprint(\"AUC :\" ,auc)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-09T14:28:49.995956Z","iopub.execute_input":"2025-11-09T14:28:49.996250Z","iopub.status.idle":"2025-11-09T14:33:53.371832Z","shell.execute_reply.started":"2025-11-09T14:28:49.996226Z","shell.execute_reply":"2025-11-09T14:33:53.370472Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### **Evaluation**","metadata":{}},{"cell_type":"code","source":"y_pred = model.predict(X_val)\nprecision = precision_score(y_val,y_pred)\nrecall = recall_score(y_val,y_pred)\nprint(\"precision :\" ,precision)\nprint(\"Recall :\" ,recall)\n\nf1 =f1_score(y_val,y_pred)\nprint(\"F1-score :\" ,f1)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-09T14:33:53.372976Z","iopub.execute_input":"2025-11-09T14:33:53.373285Z","iopub.status.idle":"2025-11-09T14:33:54.199414Z","shell.execute_reply.started":"2025-11-09T14:33:53.373261Z","shell.execute_reply":"2025-11-09T14:33:54.197619Z"},"collapsed":true,"jupyter":{"outputs_hidden":true}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"For saving Model:","metadata":{}},{"cell_type":"code","source":"model.save_model(\"catboost_model.cbm\")\n\nprint(\"Model is saving'catboost_model.cbm'\")","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"so you can use this model on your evaluation or test data","metadata":{}}]}