Python Integration Guide
Leverage the speed of Rust with the flexibility of Python. VectorAlpha's Python bindings provide native performance for your quantitative finance workflows while maintaining the familiar Python API.
Performance First
Our Python bindings use PyO3 for zero-overhead integration. You get the full performance of Rust's SIMD-optimized calculations with Python's ease of use.
Learn more: PyO3 Documentation
Installation
Using pip (Recommended)
# Install from PyPI
pip install vectoralpha-ta
# For GPU acceleration support
pip install vectoralpha-ta[cuda]
# For development features
pip install vectoralpha-ta[dev]
Building from Source
For latest features or custom builds, compile from source using maturin:
Learn more: Maturin Documentation
# Clone the repository
git clone https://github.com/VectorAlpha/ta-library.git
cd ta-library/python
# Create virtual environment
python -m venv venv
source venv/bin/activate # On Windows: venvScriptsactivate
# Install maturin
pip install maturin
# Build and install in development mode
maturin develop --release
# Or build wheel for distribution
maturin build --release
Quick Start
Basic Usage
import vectoralpha as va
import numpy as np
import pandas as pd
# Generate sample data
dates = pd.date_range('2023-01-01', periods=1000, freq='1h')
prices = 100 + np.cumsum(np.random.randn(1000) * 0.5)
df = pd.DataFrame({'close': prices}, index=dates)
# Calculate indicators
sma_20 = va.indicators.sma(df['close'], period=20) # <span class="tooltip" data-tooltip="Simple Moving Average - average of last N periods">SMA</span>
rsi_14 = va.indicators.rsi(df['close'], period=14) # <span class="tooltip" data-tooltip="Relative Strength Index - momentum oscillator measuring speed and magnitude of price changes">RSI</span>
bb_upper, bb_middle, bb_lower = va.indicators.bollinger_bands(
df['close'], period=20, std_dev=2
) # <span class="tooltip" data-tooltip="Volatility bands placed above and below a moving average">Bollinger Bands</span>
# Add to DataFrame
df['SMA_20'] = sma_20
df['RSI_14'] = rsi_14
df['BB_Upper'] = bb_upper
df['BB_Lower'] = bb_lower
print(df.tail())
Working with NumPy Arrays
# VectorAlpha works seamlessly with NumPy arrays
prices_array = np.random.randn(10000).cumsum() + 100
# All indicators accept NumPy arrays
ema = va.indicators.ema(prices_array, period=12)
macd, signal, histogram = va.indicators.macd(
prices_array,
fast_period=12,
slow_period=26,
signal_period=9
) # <span class="tooltip" data-tooltip="Moving Average Convergence Divergence - trend following momentum indicator">MACD</span>
# Batch calculation for multiple indicators
indicators = va.batch_calculate({
'sma_10': ('sma', {'period': 10}),
'sma_20': ('sma', {'period': 20}),
'rsi_14': ('rsi', {'period': 14}),
'atr_14': ('atr', {'period': 14}) # <span class="tooltip" data-tooltip="Average True Range - volatility indicator">ATR</span>
}, prices_array)
for name, values in indicators.items():
print(f"{name}: {values[-5:]}")
Advanced Features
Streaming Calculations
Process real-time data efficiently with streaming indicators:
# Create streaming indicator instance
sma_stream = va.streaming.SMA(period=20)
rsi_stream = va.streaming.RSI(period=14)
# Simulate real-time data
for price in real_time_price_feed():
sma_value = sma_stream.update(price)
rsi_value = rsi_stream.update(price)
if rsi_value < 30 and price < sma_value:
print(f"Buy signal: RSI={rsi_value:.2f}, Price below SMA")
# Get current state without updating
current_sma = sma_stream.current()
# Reset if needed
if some_condition:
sma_stream.reset()
GPU Acceleration
Enable GPU acceleration for massive datasets:
# Check GPU availability
if va.cuda.is_available():
print(f"CUDA available: {va.cuda.device_name()}")
# Enable GPU acceleration globally
va.set_backend('cuda')
# Process large dataset on GPU
large_prices = np.random.randn(10_000_000).cumsum() + 100
# These calculations run on GPU
with va.cuda.stream():
sma = va.indicators.sma(large_prices, period=50)
ema = va.indicators.ema(large_prices, period=50)
rsi = va.indicators.rsi(large_prices, period=14)
# Benchmark CPU vs GPU
import time
# CPU timing
va.set_backend('cpu')
start = time.time()
cpu_result = va.indicators.sma(large_prices, period=50)
cpu_time = time.time() - start
# GPU timing
va.set_backend('cuda')
start = time.time()
gpu_result = va.indicators.sma(large_prices, period=50)
gpu_time = time.time() - start
print(f"CPU time: {cpu_time:.3f}s")
print(f"GPU time: {gpu_time:.3f}s")
print(f"Speedup: {cpu_time/gpu_time:.1f}x")
Custom Indicators
Create custom indicators by combining existing ones or writing Rust extensions:
# Python-based custom indicator
def custom_momentum_indicator(prices, short_period=10, long_period=30):
"""
Custom momentum indicator combining multiple signals
"""
# Use VectorAlpha's optimized calculations
sma_short = va.indicators.sma(prices, short_period)
sma_long = va.indicators.sma(prices, long_period)
rsi = va.indicators.rsi(prices, 14)
# Calculate momentum score
momentum = np.zeros_like(prices)
momentum[long_period:] = (
(sma_short[long_period:] - sma_long[long_period:]) / sma_long[long_period:] * 100
)
# Adjust by RSI
momentum *= (rsi / 50) # Scale by RSI strength
return momentum
# For maximum performance, implement in Rust
# See our Rust extension guide for details
Integration Examples
Pandas Integration
# Efficient pandas integration
def add_technical_indicators(df):
"""Add multiple technical indicators to a DataFrame"""
# Use vectorized operations
high = df['high'].values
low = df['low'].values
close = df['close'].values
volume = df['volume'].values
# Calculate all indicators
indicators = va.calculate_all({
'high': high,
'low': low,
'close': close,
'volume': volume
}, indicators=[
'sma_20',
'ema_12',
'rsi_14',
'macd',
'bollinger_bands',
'atr_14',
'obv', # <span class="tooltip" data-tooltip="On-Balance Volume - momentum indicator using volume flow">OBV</span>
'vwap' # <span class="tooltip" data-tooltip="Volume Weighted Average Price - average price weighted by volume">VWAP</span>
])
# Add to DataFrame
for name, values in indicators.items():
if isinstance(values, tuple): # Handle multi-output indicators
for i, sub_name in enumerate(['_upper', '_middle', '_lower']):
df[f'{name}{sub_name}'] = values[i]
else:
df[name] = values
return df
# Apply to your data
df = pd.read_csv('historical_data.csv', parse_dates=['timestamp'])
df = add_technical_indicators(df)
Real-time Strategy
class MomentumStrategy:
def __init__(self, symbol):
self.symbol = symbol
self.sma_fast = va.streaming.SMA(10)
self.sma_slow = va.streaming.SMA(30)
self.rsi = va.streaming.RSI(14)
self.position = 0
def on_tick(self, price, volume):
# Update indicators
fast_ma = self.sma_fast.update(price)
slow_ma = self.sma_slow.update(price)
rsi_value = self.rsi.update(price)
# Skip if not enough data
if slow_ma is None:
return
# Generate signals
if self.position == 0: # No position
if fast_ma > slow_ma and rsi_value > 50:
self.buy(price)
elif fast_ma < slow_ma and rsi_value < 50:
self.sell(price)
elif self.position > 0: # Long position
if fast_ma < slow_ma or rsi_value > 70:
self.close_position(price)
else: # Short position
if fast_ma > slow_ma or rsi_value < 30:
self.close_position(price)
def buy(self, price):
print(f"BUY {self.symbol} at {price}")
self.position = 1
def sell(self, price):
print(f"SELL {self.symbol} at {price}")
self.position = -1
def close_position(self, price):
action = "CLOSE LONG" if self.position > 0 else "CLOSE SHORT"
print(f"{action} {self.symbol} at {price}")
self.position = 0
Performance Tips
Best Practices for Maximum Performance
- ✓ Use NumPy arrays: Pass NumPy arrays instead of lists for 10x faster processing
- ✓ Batch operations: Calculate multiple indicators in one call to minimize overhead
- ✓ Reuse instances: For streaming data, reuse indicator instances instead of creating new ones
- ✓ GPU for large data: Use GPU acceleration for datasets with >1M data points
Error Handling
import vectoralpha as va
from vectoralpha.exceptions import (
InvalidPeriodError,
InsufficientDataError,
CudaNotAvailableError # <span class="tooltip" data-tooltip="Exception raised when CUDA GPU acceleration is not available">CUDA availability error</span>
)
try:
# Validate inputs
if len(prices) < 20:
raise InsufficientDataError("Need at least 20 data points")
# Calculate with error handling
result = va.indicators.sma(prices, period=20)
except InvalidPeriodError as e:
print(f"Invalid period specified: {e}")
except InsufficientDataError as e:
print(f"Not enough data: {e}")
except CudaNotAvailableError:
print("CUDA not available, falling back to CPU")
va.set_backend('cpu')
result = va.indicators.sma(prices, period=20)