{"metadata":{"kernelspec":{"name":"python3","display_name":"Python 3","language":"python"},"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":"nvidiaTeslaT4","dataSources":[{"sourceId":117097,"databundleVersionId":14080503,"sourceType":"competition"},{"sourceId":13280781,"sourceType":"datasetVersion","datasetId":8416714},{"sourceId":277803131,"sourceType":"kernelVersion"},{"sourceId":277885183,"sourceType":"kernelVersion"},{"sourceId":280446094,"sourceType":"kernelVersion"}],"dockerImageVersionId":31154,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# Alpha Radar: Solana Sprint Competition","metadata":{}},{"cell_type":"markdown","source":"## Import dependencies","metadata":{}},{"cell_type":"code","source":"import os\nimport logging\nimport pandas as pd\nimport plotly.express as px\nimport plotly.io as pio\nimport torch\n\nfrom data_utils import load_data, create_feature_dataframe, merge_target\nfrom train_catboost import train_model, make_predictions, get_feature_importance, plot_feature_importance, get_topk_features, save_models\nfrom generate_smart_money_list_leak_free import generate_smart_money_list_strict_past\n\n# Set up logging\nlogging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s', force=True)\n\n# Set up plotly to display plots properly when the notebook is viewed\npio.renderers.default = 'iframe'","metadata":{"execution":{"iopub.status.busy":"2025-11-20T23:38:39.124823Z","iopub.execute_input":"2025-11-20T23:38:39.125296Z","iopub.status.idle":"2025-11-20T23:38:46.147088Z","shell.execute_reply.started":"2025-11-20T23:38:39.125269Z","shell.execute_reply":"2025-11-20T23:38:46.146520Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## EDA & Data Preprocessing","metadata":{}},{"cell_type":"code","source":"TRANSACTIONS_CSV_PATH = \"/kaggle/input/pumpfun-30s-september-2025\"\n\nTARGETS_CSV_PATH = 'https://drive.usercontent.google.com/u/0/uc?id=1EsqpZXPBU-6m0djDmccCrtUX07jV2fHA'\n\nEVAL_CSV_PATH = '/kaggle/input/alpha-radar-solana-sprint'\n\n# Load and Preprocess Data\ntransactions_df, targets_df, eval_df = load_data(TRANSACTIONS_CSV_PATH, TARGETS_CSV_PATH, EVAL_CSV_PATH)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-14T14:23:41.996220Z","iopub.execute_input":"2025-11-14T14:23:41.997083Z","iopub.status.idle":"2025-11-14T14:23:43.647251Z","shell.execute_reply.started":"2025-11-14T14:23:41.997059Z","shell.execute_reply":"2025-11-14T14:23:43.646507Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### Understanding single token transaction data","metadata":{}},{"cell_type":"code","source":"# Taking a look at how a single token's info change from first to last transaction timestamp\n\nrand_mint_token_id = transactions_df.sample(n=1).mint_token_id.iloc[0]\n\ntoken_data = transactions_df.loc[transactions_df['mint_token_id']==rand_mint_token_id].sort_values(by='timestamp', ascending=True)\ntoken_data['is_target'] = token_data.iloc[0].mint_token_id in targets_df['Target Token Addresses'].values\n\ntoken_data[['timestamp','mint_token_id', 'market_cap_usd', 'sol_volume', 'trade_mode', 'is_target']].head()\n","metadata":{"execution":{"iopub.status.busy":"2025-11-14T14:23:53.121706Z","iopub.execute_input":"2025-11-14T14:23:53.121959Z","iopub.status.idle":"2025-11-14T14:23:53.136213Z","shell.execute_reply.started":"2025-11-14T14:23:53.121938Z","shell.execute_reply":"2025-11-14T14:23:53.135250Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"fig = px.line(token_data, x='timestamp', y='market_cap_usd', title='Market cap (USD) vs Timestamp', color='is_target')\nfig.show()","metadata":{"execution":{"iopub.status.busy":"2025-11-14T14:28:48.270409Z","iopub.execute_input":"2025-11-14T14:28:48.270990Z","iopub.status.idle":"2025-11-14T14:28:48.390940Z","shell.execute_reply.started":"2025-11-14T14:28:48.270966Z","shell.execute_reply":"2025-11-14T14:28:48.390194Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### Feature engineering (Aggregating same-token transactions and creating new features)","metadata":{}},{"cell_type":"code","source":"# create smart money features helper files\n\nif not (os.path.isfile(\"./smart_money_list_strict_past.csv\") and os.path.isfile(\"./token_order.csv\")):\n    logging.info('Creating smart money and target tokens CSVs')\n    generate_smart_money_list_strict_past(TRANSACTIONS_CSV_PATH, TARGETS_CSV_PATH)\nelse:\n    logging.info('Smart money and token order CSV files already exist. Skipping creation...')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-14T13:00:02.692614Z","iopub.execute_input":"2025-11-14T13:00:02.693719Z","iopub.status.idle":"2025-11-14T13:00:02.698775Z","shell.execute_reply.started":"2025-11-14T13:00:02.693685Z","shell.execute_reply":"2025-11-14T13:00:02.698142Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Path for the final output file\nOUTPUT_FEATURES_PATH_TRAIN = './processed_token_features_train.csv'\nOUTPUT_FEATURES_PATH_EVAL = './processed_token_features_eval.csv'\n\ncreate_features = True # Recreate new training and evaluation features dataframes\n\nif create_features:\n    logging.info('create_features is enabled. Creating train and eval features dataframes. This may take a while...\\n')\n    features_df = create_feature_dataframe(transactions_df)\n    eval_df = create_feature_dataframe(eval_df, save_path=OUTPUT_FEATURES_PATH_EVAL)\n    \n    # Merge Target Variable\n    train_df = merge_target(features_df, targets_df)\n    \n    # Save to CSV\n    try:\n        logging.info(f\"Saving train data to {OUTPUT_FEATURES_PATH_TRAIN}...\")\n        train_df.to_csv(OUTPUT_FEATURES_PATH_TRAIN, index=False)\n        logging.info(\"--- Process Complete ---\")\n    except Exception as e:\n        logging.error(f\"Error during saving to {OUTPUT_FEATURES_PATH_TRAIN}: {e}\", exc_info=True)\n        \n    logging.info(\"\\nPositive class distribution:\")\n    logging.info(train_df['is_target'].value_counts(normalize=True))\n    \nelif os.path.isdir(OUTPUT_FEATURES_PATH_TRAIN) and os.path.exists(OUTPUT_FEATURES_PATH_EVAL):\n    logging.info('create_features is False and train and eval features CSV files already exist. Skipping their creation...')","metadata":{"execution":{"iopub.status.busy":"2025-11-11T02:53:06.607404Z","iopub.execute_input":"2025-11-11T02:53:06.608077Z","iopub.status.idle":"2025-11-11T02:56:50.069442Z","shell.execute_reply.started":"2025-11-11T02:53:06.608056Z","shell.execute_reply":"2025-11-11T02:56:50.068546Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Model Creation & Training","metadata":{}},{"cell_type":"code","source":"device = 'GPU' if torch.cuda.is_available() else 'CPU'\ndevice","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-20T23:38:47.467435Z","iopub.execute_input":"2025-11-20T23:38:47.467998Z","iopub.status.idle":"2025-11-20T23:38:47.561707Z","shell.execute_reply.started":"2025-11-20T23:38:47.467975Z","shell.execute_reply":"2025-11-20T23:38:47.560916Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"models, best_threshold = train_model(task_type=device)","metadata":{"execution":{"iopub.status.busy":"2025-11-11T03:06:52.022218Z","iopub.execute_input":"2025-11-11T03:06:52.022924Z","iopub.status.idle":"2025-11-11T03:09:39.380381Z","shell.execute_reply.started":"2025-11-11T03:06:52.022898Z","shell.execute_reply":"2025-11-11T03:09:39.379671Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Analyzing Feature Importance data","metadata":{}},{"cell_type":"code","source":"feature_importance = get_feature_importance(models)\n\nfeature_importance.head()","metadata":{"execution":{"iopub.status.busy":"2025-11-11T03:10:27.391087Z","iopub.execute_input":"2025-11-11T03:10:27.391741Z","iopub.status.idle":"2025-11-11T03:10:27.421809Z","shell.execute_reply.started":"2025-11-11T03:10:27.391716Z","shell.execute_reply":"2025-11-11T03:10:27.421107Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"plot_feature_importance(feature_importance)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-11T03:10:32.127363Z","iopub.execute_input":"2025-11-11T03:10:32.128007Z","iopub.status.idle":"2025-11-11T03:10:32.194993Z","shell.execute_reply.started":"2025-11-11T03:10:32.127982Z","shell.execute_reply":"2025-11-11T03:10:32.194400Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"top10_features = get_topk_features(feature_importance, 10)\ntop10_features","metadata":{"execution":{"iopub.status.busy":"2025-11-11T03:10:41.852074Z","iopub.execute_input":"2025-11-11T03:10:41.852440Z","iopub.status.idle":"2025-11-11T03:10:41.857479Z","shell.execute_reply.started":"2025-11-11T03:10:41.852413Z","shell.execute_reply":"2025-11-11T03:10:41.856855Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Make model predictions on Eval data","metadata":{}},{"cell_type":"code","source":"make_predictions(models, eval_df, optimal_threshold=best_threshold)\n","metadata":{"execution":{"iopub.status.busy":"2025-11-11T03:55:21.510587Z","iopub.execute_input":"2025-11-11T03:55:21.510833Z","iopub.status.idle":"2025-11-11T03:55:21.781919Z","shell.execute_reply.started":"2025-11-11T03:55:21.510815Z","shell.execute_reply":"2025-11-11T03:55:21.781144Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Save models","metadata":{}},{"cell_type":"code","source":"save_models(models, best_threshold, './models')","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}