Buckets:

|
download
raw
10.9 kB
# FinRL Environment
A wrapper around [FinRL](https://github.com/AI4Finance-Foundation/FinRL) stock trading environments that conforms to the OpenEnv specification.
## Overview
This environment enables reinforcement learning for stock trading tasks using FinRL's powerful StockTradingEnv, exposed through OpenEnv's simple HTTP API. It supports:
- **Stock Trading**: Buy/sell actions across multiple stocks
- **Portfolio Management**: Track balance, holdings, and portfolio value
- **Technical Indicators**: MACD, RSI, CCI, DX, and more
- **Flexible Configuration**: Custom data sources and trading parameters
## Quick Start
### 1. Build the Docker Image
First, build the base image (from OpenEnv root):
```bash
cd OpenEnv
docker build -t envtorch-base:latest -f src/openenv/core/containers/images/Dockerfile .
```
Then build the FinRL environment image:
```bash
docker build -t finrl-env:latest -f envs/finrl_env/server/Dockerfile .
```
### 2. Run the Server
#### Option A: With Default Sample Data
```bash
docker run -p 8000:8000 finrl-env:latest
```
This starts the server with synthetic sample data for testing.
#### Option B: With Custom Configuration
Create a configuration file `config.json`:
```json
{
"data_path": "/data/stock_data.csv",
"stock_dim": 3,
"hmax": 100,
"initial_amount": 100000,
"num_stock_shares": [0, 0, 0],
"buy_cost_pct": [0.001, 0.001, 0.001],
"sell_cost_pct": [0.001, 0.001, 0.001],
"reward_scaling": 0.0001,
"state_space": 25,
"action_space": 3,
"tech_indicator_list": ["macd", "rsi_30", "cci_30", "dx_30"]
}
```
Run with configuration:
```bash
docker run -p 8000:8000 \
-v $(pwd)/config.json:/config/config.json \
-v $(pwd)/data:/data \
-e FINRL_CONFIG_PATH=/config/config.json \
finrl-env:latest
```
### 3. Use the Client
```python
from envs.finrl_env import FinRLEnv, FinRLAction
import numpy as np
# Connect to server
client = FinRLEnv(base_url="http://localhost:8000")
# Get configuration
config = client.get_config()
print(f"Trading {config['stock_dim']} stocks")
print(f"Initial capital: ${config['initial_amount']:,.0f}")
# Reset environment
result = client.reset()
print(f"Initial portfolio value: ${result.observation.portfolio_value:,.2f}")
# Trading loop
for step in range(100):
# Get current state
state = result.observation.state
# Your RL policy here (example: random actions)
num_stocks = config['stock_dim']
actions = np.random.uniform(-1, 1, size=num_stocks).tolist()
# Execute action
result = client.step(FinRLAction(actions=actions))
print(f"Step {step}: Portfolio=${result.observation.portfolio_value:,.2f}, "
f"Reward={result.reward:.2f}")
if result.done:
print("Episode finished!")
break
client.close()
```
## Architecture
```
┌─────────────────────────────────────────────────────────────┐
│ RL Training Framework │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Policy Net │ │ Value Net │ │ Replay │ │
│ │ (PyTorch) │ │ (PyTorch) │ │ Buffer │ │
│ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ │
│ └──────────────────┴──────────────────┘ │
│ │ │
│ ┌────────▼────────┐ │
│ │ FinRLEnv │ ← HTTP Client │
│ │ (HTTPEnvClient) │ │
│ └────────┬────────┘ │
└────────────────────────────┼─────────────────────────────────┘
│ HTTP (JSON)
┌────────▼────────┐
│ Docker Container│
│ Port: 8000 │
│ │
│ ┌─────────────┐ │
│ │FastAPI │ │
│ │Server │ │
│ └──────┬──────┘ │
│ │ │
│ ┌──────▼──────┐ │
│ │ FinRL │ │
│ │ Environment │ │
│ └──────┬──────┘ │
│ │ │
│ ┌──────▼──────┐ │
│ │ FinRL │ │
│ │ StockTrading│ │
│ │ Env │ │
│ └─────────────┘ │
└─────────────────┘
```
## API Reference
### FinRLAction
Trading action for the environment.
**Attributes:**
- `actions: list[float]` - Array of normalized action values (-1 to 1) for each stock
- Positive values: Buy
- Negative values: Sell
- Magnitude: Relative trade size
**Example:**
```python
# Buy stock 0, sell stock 1, hold stock 2
action = FinRLAction(actions=[0.5, -0.3, 0.0])
```
### FinRLObservation
Observation returned by the environment.
**Attributes:**
- `state: list[float]` - Flattened state vector
- Structure: `[balance, prices..., holdings..., indicators...]`
- `portfolio_value: float` - Total portfolio value (cash + holdings)
- `date: str` - Current trading date
- `done: bool` - Whether episode has ended
- `reward: float` - Reward for the last action
- `metadata: dict` - Additional information
**Example:**
```python
obs = result.observation
print(f"Portfolio: ${obs.portfolio_value:,.2f}")
print(f"Date: {obs.date}")
print(f"State dimension: {len(obs.state)}")
```
### Client Methods
#### `reset() -> StepResult[FinRLObservation]`
Reset the environment to start a new episode.
```python
result = client.reset()
```
#### `step(action: FinRLAction) -> StepResult[FinRLObservation]`
Execute a trading action.
```python
action = FinRLAction(actions=[0.5, -0.3])
result = client.step(action)
```
#### `state() -> State`
Get episode metadata (episode_id, step_count).
```python
state = client.state()
print(f"Episode: {state.episode_id}, Step: {state.step_count}")
```
#### `get_config() -> dict`
Get environment configuration.
```python
config = client.get_config()
print(config['stock_dim'])
print(config['initial_amount'])
```
## Data Format
The environment expects stock data in the following CSV format:
| date | tic | close | high | low | open | volume | macd | rsi_30 | cci_30 | dx_30 |
|------------|--------|--------|--------|--------|--------|---------|-------|--------|--------|-------|
| 2020-01-01 | AAPL | 100.0 | 102.0 | 98.0 | 99.0 | 1000000 | 0.5 | 55.0 | 10.0 | 15.0 |
| 2020-01-01 | GOOGL | 1500.0 | 1520.0 | 1480.0 | 1490.0 | 500000 | -0.3 | 48.0 | -5.0 | 20.0 |
**Required columns:**
- `date`: Trading date
- `tic`: Stock ticker symbol
- `close`, `high`, `low`, `open`: Price data
- `volume`: Trading volume
- Technical indicators (as specified in `tech_indicator_list`)
## Configuration Parameters
| Parameter | Type | Description |
|-----------|------|-------------|
| `data_path` | str | Path to CSV file with stock data |
| `stock_dim` | int | Number of stocks to trade |
| `hmax` | int | Maximum shares per trade |
| `initial_amount` | int | Starting cash balance |
| `num_stock_shares` | list[int] | Initial holdings for each stock |
| `buy_cost_pct` | list[float] | Transaction cost for buying (per stock) |
| `sell_cost_pct` | list[float] | Transaction cost for selling (per stock) |
| `reward_scaling` | float | Scaling factor for rewards |
| `state_space` | int | Dimension of state vector |
| `action_space` | int | Dimension of action space |
| `tech_indicator_list` | list[str] | Technical indicators to include |
## Integration with RL Frameworks
### Stable Baselines 3
```python
from stable_baselines3 import PPO
from envs.finrl_env import FinRLEnv, FinRLAction
import numpy as np
# Create custom wrapper for SB3
class SB3FinRLWrapper:
def __init__(self, base_url):
self.env = FinRLEnv(base_url=base_url)
config = self.env.get_config()
self.action_space = spaces.Box(
low=-1, high=1,
shape=(config['action_space'],),
dtype=np.float32
)
self.observation_space = spaces.Box(
low=-np.inf, high=np.inf,
shape=(config['state_space'],),
dtype=np.float32
)
def reset(self):
result = self.env.reset()
return np.array(result.observation.state, dtype=np.float32)
def step(self, action):
result = self.env.step(FinRLAction(actions=action.tolist()))
return (
np.array(result.observation.state, dtype=np.float32),
result.reward or 0.0,
result.done,
result.observation.metadata
)
# Train
env = SB3FinRLWrapper("http://localhost:8000")
model = PPO("MlpPolicy", env, verbose=1)
model.learn(total_timesteps=10000)
```
## Troubleshooting
### Server won't start
1. Check if base image exists:
```bash
docker images | grep envtorch-base
```
2. Build base image if missing:
```bash
docker build -t envtorch-base:latest -f src/openenv/core/containers/images/Dockerfile .
```
### Import errors
Make sure you're in the `src` directory:
```bash
cd OpenEnv/src
python -c "from envs.finrl_env import FinRLEnv"
```
### Configuration errors
Verify your data file has all required columns:
```python
import pandas as pd
df = pd.read_csv('your_data.csv')
print(df.columns.tolist())
```
## Examples
See the `examples/` directory for complete examples:
- `examples/finrl_simple.py` - Basic usage
- `examples/finrl_training.py` - Full training loop with PPO
- `examples/finrl_backtesting.py` - Backtesting a trained agent
## License
BSD 3-Clause License (see LICENSE file in repository root)
## References
- [FinRL Paper](https://arxiv.org/abs/2011.09607)
- [FinRL GitHub](https://github.com/AI4Finance-Foundation/FinRL)
- [OpenEnv Documentation](README)

Xet Storage Details

Size:
10.9 kB
·
Xet hash:
0b6e6d1a646625be88e27cba0c03fc8a38535c94a4905acdbc0422d9f206213e

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.