This repository explores deep reinforcement learning for multi-asset crypto portfolio allocation. It trains a Proximal Policy Optimization (PPO) agent in a custom Gymnasium environment and evaluates it against classical baselines such as constrained mean-variance optimization (MVO) and BTC buy-and-hold.
The project is notebook-driven: notebooks/main_analysis.ipynb is the main entry point, while the drl_portfolio package contains the reusable environment, feature engineering, and plotting utilities.
At a high level, the pipeline is:
- Load 4-hour historical crypto prices from CSV or download them from Binance.
- Generate rolling market features such as log returns, volatility, trend distance, and cross-asset correlation.
- Feed those features into a custom portfolio environment with a cash position and transaction costs.
- Train PPO to output portfolio weights that maximize a differential Sharpe-style reward.
- Evaluate each trained model on unseen windows and compare against MVO and BTC buy-and-hold.
The current codebase reflects a more recent experiment setup than some older project notes:
- Frequency: 4-hour bars
- Data range used in the notebook: 2023-01-01 through 2026-04-01
- Asset universe in
crypto_data_v4.csv:BTCUSDT,ETHUSDT,BNBUSDT,SOLUSDT,NEARUSDT,AVAXUSDT,OPUSDT,LDOUSDT,FETUSDT,LINKUSDT,AAVEUSDT,UNIUSDT,DOGEUSDT - Action space: one cash weight plus one weight per crypto asset
- Transaction costs in the environment: 0.10% trading fee + 0.05% slippage
- Baselines: constrained MVO and BTC buy-and-hold
drl-crypto-portfolio/
├── data/
│ ├── crypto_data.csv
│ ├── crypto_data_v2.csv
│ ├── crypto_data_v3.csv
│ └── crypto_data_v4.csv
├── drl_portfolio/
│ ├── __init__.py
│ ├── env.py
│ ├── features.py
│ └── utils.py
├── notebooks/
│ ├── images/
│ └── main_analysis.ipynb
├── results/
│ ├── best_model_window_*.zip
│ ├── vec_norm_window_*.pkl
│ └── ppo_logs/
├── requirements.txt
└── README.md
Defines PortfolioEnv, the custom Gymnasium environment used for training and evaluation.
Key behaviors:
- Adds an explicit cash position at action index
0 - Converts raw PPO actions into normalized portfolio weights using softmax
- Applies turnover-based transaction costs
- Tracks drifting portfolio weights after market movement
- Uses a clipped differential Sharpe reward for online RL training
Builds the model inputs from price data.
Current engineered features include:
- asset log returns
- short and long rolling volatility
- volatility ratio
- cross-asset volatility proxy
- trend distance from a long moving average
- rolling mean cross-asset correlation
The function returns aligned prices and features so the environment can step through them without leakage from missing lookback periods.
Contains helper functions for:
- generating rolling train/test windows
- plotting PPO portfolio weights over time
- summarizing weight statistics
The notebook performs the full experiment loop:
- Prepare price history and clean missing columns.
- Generate features for the full dataset.
- Create expanding train, validation, and test windows.
- Train one PPO model per window using vectorized environments.
- Save the best checkpoint and normalization statistics for each window.
- Run out-of-sample evaluation on the corresponding test window.
- Compare PPO against:
- constrained MVO using PyPortfolioOpt
- BTC buy-and-hold
Important PPO settings used in the current notebook:
- Policy:
MlpPolicy - Vectorized training envs: 4
- Timesteps per window: 8,000,000
n_steps: 2048batch_size: 512n_epochs: 5gae_lambda: 0.95clip_range: 0.2- learning rate schedule starting at
5e-5
git clone https://github.com/yeonjaej/drl-crypto-portfolio.git
cd drl-crypto-portfolio
pip install -r requirements.txtjupyter notebook notebooks/main_analysis.ipynbThe notebook can either:
- use existing CSV data already stored in
data/ - or download fresh Binance history and save a new dataset
There are multiple CSV snapshots in data/, which reflect different iterations of the experiment. The latest dataset in this repository appears to be data/crypto_data_v4.csv, while the notebook currently defaults to loading data/crypto_data_v3.csv when the download flag is disabled.
If you switch datasets, make sure the asset universe and any saved models in results/ still match the environment dimensions.
The results/ directory contains prior experiment outputs, including:
- saved PPO checkpoints for multiple windows
VecNormalizestatistics used during evaluation- TensorBoard training logs
- older model/log folders from earlier experiment versions
These artifacts are useful for reproducing evaluation without retraining from scratch.
This is a research/backtesting project, not a live trading system.
Current limitations include:
- notebook-centric workflow rather than a packaged training CLI
- no automated test suite for the RL pipeline
- experiment versions and documentation have evolved over time
- backtest assumptions may still differ from real execution conditions
MIT License. See LICENSE.