DBN is an experimental, self-contained Python framework for training and evaluating reinforcement-learning agents locally on Apple Silicon. It is built on top of MLX and uses Stable-Baselines3-shaped APIs so existing configs, notebooks and muscle memory can be reused without any cloud inference, per-token fees or paid GPU subscriptions.
The codebase is intentionally split between:
- RL agents and environments (
scripts/,tests/) for rapid prototyping on classic control tasks. - Synthetic market data (
scripts/data.py,scripts/viz.py,configs/) for the trading-bot direction. - Native benchmarking tools (
utils/bench/) for measuring throughput, memory and time-to-solve on MLX.
- Native MLX training — PPO, SAC and TD3 written in pure MLX with batched, vectorized updates.
- SB3-style API — familiar constructor arguments (
learning_rate,gamma,buffer_size,batch_size,tensorboard_log, ...). - Vectorized environments — pure-MLX
CartPoleMLXandPendulumMLXthat scale to tens of thousands of parallel envs. - Throughput & TTS benchmarks —
utils/bench/scale.pyandutils/bench/solve.pywith auto-doubling and plateau detection. - Live thermal telemetry —
smctemp,powermetricsandosx-cpu-tempsupport via a best-effort fallback chain. - Synthetic market data — OHLC, volume, returns, volatility, funding and alpha channels generated as MLX tensors.
- Minimal footprint — see
requirements.txt.
- Python 3.11 (see
.python-version) - macOS with Apple Silicon (MLX targets Metal)
- Optional but recommended:
smctemp(brew install narugit/smctemp/smctemp) for live CPU temperature
python3.11 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt.
├── scripts/ # Agents, data generation and visualization
│ ├── agent.py # Common Agent / MLXAgent interface
│ ├── ppo.py # MLX PPO
│ ├── sac.py # MLX SAC
│ ├── td3.py # MLX TD3
│ ├── data.py # Synthetic market data
│ └── viz.py # Plotly candlestick charts
├── tests/ # Vectorized envs and pytest suite
│ ├── cartpole.py # CartPoleMLX
│ ├── pendulum.py # PendulumMLX
│ └── test_*.py
├── utils/bench/ # Benchmarking harness
│ ├── common.py # Shared MLX / telemetry helpers
│ ├── scale.py # Throughput scaling sweep
│ └── solve.py # Time-to-solve benchmark
├── configs/ # Market simulation config and Plotly themes
│ ├── config.yaml
│ └── themes/
└── README.md
.venv/bin/python utils/bench/scale.py normal \
--env cartpole --algo ppo --max-envs 100_000This auto-doubles n_envs until throughput plateaus and reports env/train FPS, RSS/peak memory and thermal state.
.venv/bin/python utils/bench/solve.py \
--target pendulum_sac --envs 32 128 256--target can be cartpole_ppo, pendulum_ppo, pendulum_sac, pendulum_td3 or all.
.venv/bin/python -m pytestOr use the built-in smoke flags:
.venv/bin/python utils/bench/scale.py normal --smoke
.venv/bin/python utils/bench/solve.py --smoke.venv/bin/python - <<'PY'
from scripts.data import generate_market_data, load_config
from scripts.viz import plot_market_data
config = load_config("configs/config.yaml")
tensor, symbols = generate_market_data(config)
plot_market_data(tensor, symbols, theme_name="synthwave", symbol="BTC")
PYOutput is written to outputs/market/{theme_name}.png.
All agents follow a minimal predict / learn / save / load interface:
from tests.cartpole import CartPoleMLX
from scripts.ppo import PPO
env = CartPoleMLX(n_envs=64, seed=0)
model = PPO("MlpPolicy", env, verbose=1, tensorboard_log="runs/cartpole")
model.learn(100_000)
model.save("checkpoints/cartpole_ppo.safetensors")SAC and TD3 work the same way and expect a continuous PendulumMLX environment:
from tests.pendulum import PendulumMLX
from scripts.sac import SAC
env = PendulumMLX(n_envs=64, seed=0)
model = SAC("MlpPolicy", env, verbose=1, tensorboard_log="runs/pendulum")
model.learn(100_000)utils/bench/common.py provides shared helpers for:
- RSS and peak memory tracking
- Best-effort thermal monitoring (
smctemp -c,sudo powermetrics --samplers thermal,osx-cpu-temp) - Stable-Baselines3-shaped model and environment construction
CartPole PPO on Apple Silicon, n_envs auto-doubling from 16 to 8192:
| env | algo | n_envs | env FPS | train FPS | RSS MB | peak MB | ΔRSS MB | thermal | wall s |
|---|---|---|---|---|---|---|---|---|---|
| cartpole | PPO | 16 | 50,291 | 84,208 | 313.6 | 313.6 | 257 | 66.4 | 4.75 |
| cartpole | PPO | 32 | 173,541 | 166,474 | 331.6 | 331.6 | 18 | 69.3 | 4.81 |
| cartpole | PPO | 64 | 357,939 | 306,718 | 340.3 | 340.3 | 8.6 | 70.8 | 3.26 |
| cartpole | PPO | 128 | 716,405 | 529,114 | 349.2 | 349.2 | 8.9 | 69.9 | 1.89 |
| cartpole | PPO | 256 | 1,426,155 | 1,101,501 | 366.6 | 366.6 | 17.4 | 71.2 | 0.91 |
| cartpole | PPO | 512 | 2,888,197 | 1,750,960 | 370.2 | 370.2 | 3.6 | 69.9 | 0.57 |
| cartpole | PPO | 1024 | 5,671,038 | 3,115,224 | 373.3 | 373.3 | 3.1 | 69.9 | 0.32 |
| cartpole | PPO | 2048 | 11,231,887 | 3,610,902 | 380.6 | 380.6 | 7.3 | 70 | 0.28 |
| cartpole | PPO | 4096 | 22,005,588 | 3,584,210 | 385.9 | 385.9 | 5.3 | 69.9 | 0.28 |
| cartpole | PPO | 8192 | 41,560,339 | 3,570,957 | 385.9 | 385.9 | 0 | 68.8 | 0.28 |
- MLX graph memory grows during the first compile; the RSS delta you see on small
n_envsis usually one-time compilation cost. - Thermal readings require
smctempor asudoersNOPASSWD rule for/usr/bin/powermetricsif you want thepowermetricsfallback to work passwordlessly. - Vectorization is the main lever for throughput:
CartPoleMLXandPendulumMLXare designed to step thousands of envs in a single MLX call.
MIT