Download and analyze historical futures data from TradeStation API
Project description
TradeStation Historical Data Downloader
Automated download of 1-minute futures data from TradeStation API with incremental updates, rate limiting, and Parquet storage.
Features
- OAuth2 Authentication - Automatic token refresh
- Incremental Updates - Only downloads new bars since last run
- Rate Limiting - Respects API limits with configurable delays
- Parquet Storage - Fast, compressed columnar format
- Resume Capability - Interrupted downloads can be resumed
- All US Futures - Pre-configured list of ~50 continuous contracts
Quick Start
1. Install
# From PyPI (recommended)
pip install tradestation-downloader
# Or from source using uv
pip install uv
uv sync
# Or standard pip from source
pip install -e .
# For development (includes pytest, ruff)
pip install -e ".[dev]"
2. Get TradeStation API Credentials
- Go to TradeStation Developer Portal
- Create an application
- Get your
client_id,client_secret, andrefresh_token
3. Configure
Option A - Interactive setup (recommended):
tradestation-auth
Option B - Manual setup:
cp config.yaml.template config.yaml
# Edit config.yaml with your credentials
4. Run
After install, CLI commands are available:
# Download all configured symbols (incremental)
tradestation-download
# Download specific symbols only
tradestation-download -s "@ES" "@NQ" "@CL"
# Full download (ignore existing data)
tradestation-download --full
# Use daily or monthly partitioned storage
tradestation-download --storage-format daily
tradestation-download --storage-format monthly
# List all default symbols
tradestation-download --list-symbols
# List symbol categories
tradestation-download --list-categories
# Download specific category
tradestation-download --category index
Note: On Windows, the
@symbol has special meaning in CMD/PowerShell. Always quote symbols:"@ES"instead of@ES.
Or run directly with Python:
python tradestation_downloader.py
python tradestation_downloader.py -s "@ES" "@NQ" "@CL"
Configuration
Edit config.yaml:
tradestation:
client_id: "YOUR_CLIENT_ID"
client_secret: "YOUR_CLIENT_SECRET"
refresh_token: "YOUR_REFRESH_TOKEN"
data_dir: "./data"
start_date: "2007-01-01"
interval: 1
unit: "Minute"
symbols:
- "@ES" # E-mini S&P 500
- "@NQ" # E-mini Nasdaq 100
# ... add more symbols
Output Format
Data is saved as Parquet files in the data_dir:
data/
├── ES_1min.parquet
├── NQ_1min.parquet
├── CL_1min.parquet
└── ...
Each file contains:
| Column | Type | Description |
|---|---|---|
| datetime | datetime | Bar timestamp (UTC) |
| open | float | Opening price |
| high | float | High price |
| low | float | Low price |
| close | float | Closing price |
| volume | int | Total volume |
Loading Data
import pandas as pd
# Load single symbol
df = pd.read_parquet("data/ES_1min.parquet")
print(df.head())
# Load multiple symbols
symbols = ["ES", "NQ", "CL"]
data = {s: pd.read_parquet(f"data/{s}_1min.parquet") for s in symbols}
Python API
pip install tradestation-downloader
Use programmatically in your project:
from tradestation import TradeStationDownloader, DownloadConfig, StorageFormat
config = DownloadConfig(
client_id="your_client_id",
client_secret="your_client_secret",
refresh_token="your_refresh_token",
symbols=["@ES"],
data_dir="./data",
start_date="2020-01-01",
storage_format=StorageFormat.SINGLE,
)
downloader = TradeStationDownloader(config)
data = downloader.download_all()
# Access download statistics
stats = downloader.stats
print(f"Downloaded {stats.bars_downloaded} bars")
print(f"Processed {stats.symbols_processed} symbols")
print(f"Errors: {stats.errors}")
# Use the data
es_df = data["@ES"]
print(es_df.head())
Or load from config file:
from tradestation import TradeStationDownloader, load_config
config = load_config("config.yaml")
config.symbols = ["@ES", "@NQ"] # Override symbols
downloader = TradeStationDownloader(config)
downloader.download_all()
Scheduling Daily Updates
Linux/Mac (cron)
# Edit crontab
crontab -e
# Add line to run daily at 6 AM
0 6 * * * cd /path/to/tradestation_downloader && python tradestation_downloader.py >> logs/download.log 2>&1
Windows (Task Scheduler)
- Open Task Scheduler
- Create Basic Task
- Set trigger: Daily at 6:00 AM
- Action: Start a program
- Program:
python - Arguments:
C:\path\to\tradestation_downloader.py - Start in:
C:\path\to\tradestation_downloader
Data Validation
import pandas as pd
from pathlib import Path
data_dir = Path("./data")
for f in data_dir.glob("*_1min.parquet"):
df = pd.read_parquet(f)
symbol = f.stem.replace("_1min", "")
print(f"{symbol}:")
print(f" Date range: {df['datetime'].min()} to {df['datetime'].max()}")
print(f" Total bars: {len(df):,}")
print(f" Missing dates: {df['datetime'].diff().gt(pd.Timedelta(minutes=2)).sum()}")
print()
Troubleshooting
"401 Unauthorized" Error
Your refresh token may have expired. Run tradestation-auth to get a new one.
"429 Rate Limited" Error
The script handles this automatically, but if persistent:
- Increase
rate_limit_delayin config - Reduce number of symbols per run
Missing Data
Some symbols may not have data going back to 2007. Check TradeStation's data availability for specific contracts.
Large Download Size
1-minute data from 2007 is ~500MB-1GB per symbol. Total for all US futures: ~30-50GB.
Default Symbols
Run tradestation-download --list-symbols to see all default symbols:
- Equity Index: @ES, @NQ, @YM, @RTY, @MES, @MNQ, etc.
- Energy: @CL, @NG, @RB, @HO, @BRN
- Metals: @GC, @SI, @HG, @PL, @PA
- Treasury: @US, @TY, @FV, @TU, @UB, @TEN, @TWE
- Grains: @C, @S, @W, @KW, @BO, @SM
- Softs: @KC, @SB, @CT, @CC, @OJ, @LBR
- Meats: @LC, @LH, @FC
- Currency: @EC, @JY, @BP, @AD, @CD, @SF, @DX
- Volatility: @VX
- Crypto: @BTC, @ETH, @MBT, @MET
License
MIT License - Free to use and modify.
Support
For TradeStation API issues: TradeStation Developer Support
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file tradestation_downloader-1.0.0.tar.gz.
File metadata
- Download URL: tradestation_downloader-1.0.0.tar.gz
- Upload date:
- Size: 80.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
dff0fc782d95c02077c0b6e082b4abad98e490354c6676491782d3b2cca6023b
|
|
| MD5 |
44586ff971d59e100dc51827c20c0955
|
|
| BLAKE2b-256 |
a29c7e4a6f958d099a276600d89b5830b37e0a95d5a4ce8a7bc13b9358eb0e80
|
File details
Details for the file tradestation_downloader-1.0.0-py3-none-any.whl.
File metadata
- Download URL: tradestation_downloader-1.0.0-py3-none-any.whl
- Upload date:
- Size: 20.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ea1b2ead2c48eb1f32d338b74c833539e9a3883722faba83209693c76cf9874d
|
|
| MD5 |
9b7fa5d8efc3adb3ec59b6b2d2fb6b05
|
|
| BLAKE2b-256 |
940f0eaa31da91bbd8f3666a64958bff6b9f33eec1aab07bfde88b7717b86a4f
|