A batteries-included pythonic library for AlgoGators members
Project description
๐ AlgoSystem
A batteries-included Python library for algorithmic trading backtesting and beautiful, interactive dashboard visualization.
Transform your trading strategy performance analysis with professional-grade dashboards that rivals institutional trading platforms.
โจ Features
- ๐ Simple Backtesting: Run backtests with just a price series - no complex strategy definitions required
- ๐ Interactive Dashboards: Generate beautiful HTML dashboards with 20+ metrics and charts
- ๐จ Visual Dashboard Editor: Drag-and-drop interface for customizing dashboard layouts
- ๐ Comprehensive Analytics: Performance metrics, risk analysis, rolling statistics, and more
- ๐ Benchmark Comparison: Compare strategies against market benchmarks with alpha/beta analysis
- โ๏ธ Flexible Configuration: JSON-based system for complete dashboard customization
- ๐ป CLI Tools: Command-line interface for quick dashboard generation
- ๐ Standalone Dashboards: Export self-contained HTML files that work offline
๐ฆ Installation
Quick Install (Recommended)
pip install algosystem
Development Installation
# Clone the repository
git clone https://github.com/yourusername/algosystem.git
cd algosystem
poetry install
Requirements
- Python 3.9+
- pandas >= 2.0.0
- numpy >= 1.24.0
- Works on Windows, macOS, and Linux
๐ Quick Start
1. Basic Backtesting
import pandas as pd
from algosystem import Engine
# Load your strategy data (price series)
data = pd.read_csv('strategy_prices.csv', index_col=0, parse_dates=True)
# Run backtest and generate dashboard
engine = Engine(data)
results = engine.run()
dashboard_path = engine.generate_dashboard()
print(f"Dashboard ready: {dashboard_path}")
2. Using the CLI
# Generate dashboard from CSV
algosystem dashboard strategy_data.csv
# Launch visual dashboard editor
algosystem launch
# Create standalone dashboard
algosystem dashboard strategy_data.csv --output-file my_dashboard.html
3. Compare with Benchmark
from algosystem import Engine
# Load strategy and benchmark data
strategy = pd.read_csv('strategy.csv', index_col=0, parse_dates=True)
benchmark = pd.read_csv('sp500.csv', index_col=0, parse_dates=True)
# Run comparison
engine = Engine(strategy, benchmark=benchmark)
results = engine.run()
# Results include alpha, beta, correlation, etc.
print(f"Alpha: {results['metrics']['alpha']:.4f}")
print(f"Beta: {results['metrics']['beta']:.4f}")
print(f"Sharpe Ratio: {results['metrics']['sharpe_ratio']:.4f}")
๐ Complete Usage Guide
Understanding Your Data
AlgoSystem works with price series (portfolio values over time), not individual trades or signals.
Data Format Requirements
Your CSV should look like this:
Date,Portfolio_Value
2020-01-01,100000.00
2020-01-02,100150.25
2020-01-03,99875.50
...
Loading Data
import pandas as pd
# From CSV
data = pd.read_csv('portfolio.csv', index_col=0, parse_dates=True)
# From pandas DataFrame
dates = pd.date_range('2020-01-01', periods=1000, freq='D')
prices = 100 * (1 + pd.Series(returns)).cumprod()
data = pd.Series(prices, index=dates)
# From multiple columns (use first column)
data = pd.read_csv('multi_column.csv', index_col=0, parse_dates=True)
strategy_data = data['Portfolio_Value'] # Select specific column
Core Engine Features
1. Basic Backtesting
from algosystem import Engine
# Initialize engine
engine = Engine(
data=portfolio_series,
start_date='2020-01-01', # Optional: filter date range
end_date='2023-12-31', # Optional: filter date range
initial_capital=100000 # Optional: set starting capital
)
# Run backtest
results = engine.run()
# Access results
print(f"Total Return: {results['metrics']['total_return']:.2%}")
print(f"Sharpe Ratio: {results['metrics']['sharpe_ratio']:.2f}")
print(f"Max Drawdown: {results['metrics']['max_drawdown']:.2%}")
2. Benchmark Analysis
# Compare against benchmark
engine = Engine(strategy_data, benchmark=benchmark_data)
results = engine.run()
# Benchmark-specific metrics
benchmark_metrics = {
'alpha': results['metrics']['alpha'],
'beta': results['metrics']['beta'],
'correlation': results['metrics']['correlation'],
'tracking_error': results['metrics']['tracking_error'],
'information_ratio': results['metrics']['information_ratio']
}
3. Dashboard Generation
# Generate full dashboard
dashboard_path = engine.generate_dashboard(
output_dir='./my_dashboard',
open_browser=True, # Auto-open in browser
config_path='custom_config.json' # Use custom layout
)
# Generate standalone dashboard
standalone_path = engine.generate_standalone_dashboard(
'portfolio_analysis.html'
)
Advanced Usage
Custom Dashboard Configuration
Create a dashboard_config.json:
{
"metrics": [
{
"id": "total_return",
"type": "Percentage",
"title": "Total Return",
"value_key": "total_return",
"position": {"row": 0, "col": 0}
},
{
"id": "sharpe_ratio",
"type": "Value",
"title": "Sharpe Ratio",
"value_key": "sharpe_ratio",
"position": {"row": 0, "col": 1}
}
],
"charts": [
{
"id": "equity_curve",
"type": "LineChart",
"title": "Portfolio Growth",
"data_key": "equity_curve",
"position": {"row": 1, "col": 0},
"config": {
"y_axis_label": "Portfolio Value ($)",
"percentage_format": false
}
},
{
"id": "monthly_returns",
"type": "HeatmapTable",
"title": "Monthly Returns",
"data_key": "monthly_returns",
"position": {"row": 1, "col": 1},
"config": {}
}
],
"layout": {
"max_cols": 2,
"title": "My Custom Dashboard"
}
}
Working with Returns vs Prices
# If you have returns instead of prices
returns_series = pd.read_csv('returns.csv', index_col=0, parse_dates=True)
# Convert to price series
initial_value = 100000
price_series = initial_value * (1 + returns_series).cumprod()
# Run backtest
engine = Engine(price_series)
results = engine.run()
Risk Analysis
# Access detailed risk metrics
risk_metrics = {
'volatility': results['metrics']['annualized_volatility'],
'var_95': results['metrics']['var_95'],
'cvar_95': results['metrics']['cvar_95'],
'max_drawdown': results['metrics']['max_drawdown'],
'sortino_ratio': results['metrics']['sortino_ratio'],
'calmar_ratio': results['metrics']['calmar_ratio']
}
# Rolling metrics for time series analysis
rolling_data = results['plots']
rolling_sharpe = rolling_data['rolling_sharpe']
rolling_volatility = rolling_data['rolling_volatility']
drawdown_series = rolling_data['drawdown_series']
CLI Reference
Dashboard Commands
# Basic dashboard generation
algosystem dashboard portfolio.csv
# With custom output location
algosystem dashboard portfolio.csv --output-dir ./results
# Standalone dashboard
algosystem dashboard portfolio.csv --output-file analysis.html
# Include benchmark comparison
algosystem dashboard portfolio.csv --benchmark sp500.csv
# Use custom configuration
algosystem dashboard portfolio.csv --config custom_layout.json
Dashboard Editor
# Launch web-based editor
algosystem launch
# Launch on specific port
algosystem launch --port 8080
# Load existing configuration
algosystem launch --config existing_config.json
# Save configuration to specific location
algosystem launch --save-config ./configs/my_layout.json
Configuration Management
# Create new configuration file
algosystem create-config my_config.json
# View configuration contents
algosystem show-config my_config.json
# List all configurations
algosystem list-configs
๐ ๏ธ Developer Tutorial
Understanding the Architecture
AlgoSystem follows a modular architecture designed for extensibility:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ AlgoSystem Architecture โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโ
โ Data Input โ โ Engine Core โ โ Dashboard โ
โ โ โ โ โ Generator โ
โ โข CSV Files โ โโ โ โข Backtesting โ โโ โ โข HTML Export โ
โ โข Pandas Series โ โ โข Metrics Calc โ โ โข Standalone โ
โ โข Price Data โ โ โข Risk Analysis โ โ โข Interactive โ
โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโ
โ โ โ
โ โโโโโโโโโโโโโโโโโโโ โ
โ โ Analysis โ โ
โ โ Modules โ โ
โ โ โ โ
โโโโโโโโโโโโโโถโ โข Performance โโโโโโโโโโโโโโโ
โ โข Risk โ
โ โข Portfolio โ
โโโโโโโโโโโโโโโโโโโ
โ
โโโโโโโโโโโโโโโโโโโ
โ Web Editor โ
โ โ
โ โข Flask App โ
โ โข Drag & Drop โ
โ โข Live Preview โ
โโโโโโโโโโโโโโโโโโโ
Core Components
1. Engine Class (algosystem.backtesting.Engine)
The main interface for backtesting:
class Engine:
def __init__(self, data, benchmark=None, start_date=None,
end_date=None, initial_capital=None):
"""
Initialize backtesting engine.
Parameters:
-----------
data : pd.Series or pd.DataFrame
Portfolio price series
benchmark : pd.Series, optional
Benchmark price series for comparison
start_date : str or datetime, optional
Start date for analysis
end_date : str or datetime, optional
End date for analysis
initial_capital : float, optional
Initial portfolio value
"""
def run(self) -> dict:
"""Run backtest and return results."""
def generate_dashboard(self, output_dir=None,
config_path=None) -> str:
"""Generate interactive HTML dashboard."""
2. Metrics Module (algosystem.analysis.metrics)
Comprehensive performance calculations:
# Key functions
def calculate_metrics(strategy, benchmark=None) -> dict:
"""Calculate static performance metrics."""
def calculate_time_series_data(strategy, benchmark=None) -> dict:
"""Calculate rolling metrics and time series."""
def rolling_sharpe(returns, window=30) -> pd.Series:
"""Calculate rolling Sharpe ratio."""
3. Dashboard Generator (algosystem.backtesting.dashboard)
Creates interactive visualizations:
def generate_dashboard(engine, output_dir=None,
config_path=None) -> str:
"""Generate complete dashboard with configuration."""
def generate_standalone_dashboard(engine, output_path=None) -> str:
"""Create self-contained HTML file."""
Creating Custom Metrics
Add your own performance metrics:
# In algosystem/analysis/custom_metrics.py
def calculate_custom_metric(returns):
"""Calculate a custom performance metric."""
# Your custom calculation here
return custom_value
# Register with the system
from algosystem.analysis.metrics import calculate_metrics
# Extend the metrics function
original_calculate_metrics = calculate_metrics
def enhanced_calculate_metrics(strategy, benchmark=None):
metrics = original_calculate_metrics(strategy, benchmark)
# Add custom metric
returns = strategy.pct_change().dropna()
metrics['custom_metric'] = calculate_custom_metric(returns)
return metrics
# Replace the original function
algosystem.analysis.metrics.calculate_metrics = enhanced_calculate_metrics
Extending Dashboard Components
Custom Chart Types
Create new visualization types:
# In algosystem/backtesting/dashboard/charts/custom_chart.py
def create_custom_chart(data, config):
"""Create a custom chart component."""
return {
'type': 'CustomChart',
'data': format_data_for_chart(data),
'config': config
}
# Register in available_components.py
AVAILABLE_CHARTS.append({
"id": "custom_chart",
"type": "CustomChart",
"title": "My Custom Chart",
"data_key": "custom_data",
"description": "Description of custom chart",
"category": "custom"
})
Custom Metrics
Add new metric types:
# In available_components.py
AVAILABLE_METRICS.append({
"id": "my_metric",
"type": "Percentage",
"title": "My Custom Metric",
"value_key": "my_custom_metric",
"description": "Description of my metric",
"category": "custom"
})
Plugin Architecture
Create plugins for AlgoSystem:
# Create a plugin file: algosystem_plugin_example.py
class AlgoSystemPlugin:
def __init__(self):
self.name = "Example Plugin"
self.version = "1.0.0"
def register_metrics(self):
"""Register custom metrics."""
return {
'plugin_metric': self.calculate_plugin_metric
}
def register_charts(self):
"""Register custom charts."""
return {
'plugin_chart': self.create_plugin_chart
}
def calculate_plugin_metric(self, data):
"""Custom metric calculation."""
return data.std() * 252 ** 0.5
def create_plugin_chart(self, data, config):
"""Custom chart creation."""
return {
'type': 'PluginChart',
'data': data.to_dict(),
'config': config
}
# Use the plugin
plugin = AlgoSystemPlugin()
# Register plugin with AlgoSystem...
Testing Your Extensions
Create tests for custom components:
# tests/test_custom_metrics.py
import pytest
import pandas as pd
import numpy as np
from algosystem.analysis.custom_metrics import calculate_custom_metric
def test_custom_metric():
# Create test data
dates = pd.date_range('2020-01-01', periods=100)
returns = pd.Series(np.random.normal(0.001, 0.02, 100), index=dates)
# Test metric calculation
result = calculate_custom_metric(returns)
# Assertions
assert isinstance(result, float)
assert not np.isnan(result)
assert result > 0 # or whatever makes sense for your metric
# Run tests
# pytest tests/test_custom_metrics.py
Performance Optimization
Efficient Data Processing
# Use vectorized operations
def efficient_rolling_calculation(data, window=252):
"""Efficient rolling calculation using pandas."""
return data.rolling(window).apply(
lambda x: x.std() * np.sqrt(252),
raw=True # Use raw numpy arrays for speed
)
# Cache expensive calculations
from functools import lru_cache
@lru_cache(maxsize=128)
def cached_complex_calculation(data_hash, window):
"""Cache expensive calculations."""
# Complex calculation here
pass
Memory Management
# Process large datasets in chunks
def process_large_dataset(data, chunk_size=10000):
"""Process large datasets efficiently."""
results = []
for i in range(0, len(data), chunk_size):
chunk = data.iloc[i:i+chunk_size]
result = process_chunk(chunk)
results.append(result)
# Clean up memory
del chunk
return pd.concat(results)
Best Practices
1. Error Handling
def robust_metric_calculation(data):
"""Calculate metric with proper error handling."""
try:
if data.empty:
return 0.0
if len(data) < 30:
logger.warning("Insufficient data for metric calculation")
return np.nan
result = calculate_metric(data)
if np.isnan(result) or np.isinf(result):
return 0.0
return result
except Exception as e:
logger.error(f"Error calculating metric: {e}")
return np.nan
2. Configuration Validation
def validate_dashboard_config(config):
"""Validate dashboard configuration."""
required_fields = ['metrics', 'charts', 'layout']
for field in required_fields:
if field not in config:
raise ValueError(f"Missing required field: {field}")
# Validate metrics
for metric in config['metrics']:
if 'id' not in metric:
raise ValueError("Metric missing required 'id' field")
if 'position' not in metric:
raise ValueError(f"Metric {metric['id']} missing position")
return True
3. Logging
import logging
# Set up logging
logger = logging.getLogger('algosystem')
handler = logging.StreamHandler()
formatter = logging.Formatter(
'%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
handler.setFormatter(formatter)
logger.addHandler(handler)
logger.setLevel(logging.INFO)
# Use throughout your code
logger.info("Starting backtest...")
logger.warning("Low data quality detected")
logger.error("Failed to calculate metric")
๐จ Visual System Overview
Data Flow Diagram
graph TD
A["Portfolio Data<br/>CSV/DataFrame"] --> B["Engine.run()"]
B --> C["Metrics Calculation"]
B --> D["Time Series Analysis"]
B --> E["Risk Assessment"]
C --> F["Performance Metrics<br/>โข Total Return<br/>โข Sharpe Ratio<br/>โข Max Drawdown"]
D --> G["Rolling Analytics<br/>โข Rolling Sharpe<br/>โข Rolling Volatility<br/>โข Drawdown Series"]
E --> H["Risk Metrics<br/>โข VaR/CVaR<br/>โข Skewness<br/>โข Sortino Ratio"]
F --> I["Dashboard Generator"]
G --> I
H --> I
I --> J["Configuration<br/>dashboard_config.json"]
J --> K["HTML Dashboard<br/>Interactive Charts<br/>& Metrics"]
L["Benchmark Data<br/>Optional"] --> B
M["Custom Config<br/>Optional"] --> J
Dashboard Component Architecture
graph LR
A[Dashboard Layout] --> B[Metrics Section]
A --> C[Charts Section]
B --> D[Metric Row 1<br/>4 columns max]
B --> E[Metric Row 2<br/>4 columns max]
C --> F[Chart Row 1<br/>2 columns max]
C --> G[Chart Row 2<br/>2 columns max]
D --> H[Performance<br/>Metrics]
D --> I[Risk<br/>Metrics]
D --> J[Ratio<br/>Metrics]
D --> K[Trade<br/>Statistics]
F --> L[Equity Curve<br/>Line Chart]
F --> M[Drawdown<br/>Area Chart]
G --> N[Rolling Metrics<br/>Line Chart]
G --> O[Monthly Returns<br/>Heatmap]
CLI Command Structure
graph TD
A[algosystem] --> B[dashboard]
A --> C[launch]
A --> D[create-config]
A --> E[show-config]
A --> F[list-configs]
B --> G[strategy.csv<br/>Input File]
B --> H[--output-dir<br/>Output Directory]
B --> I[--benchmark<br/>Benchmark File]
B --> J[--config<br/>Config File]
C --> K[--port<br/>Server Port]
C --> L[--host<br/>Server Host]
C --> M[--config<br/>Load Config]
C --> N[--save-config<br/>Save Location]
D --> O[output.json<br/>New Config]
D --> P[--based-on<br/>Template Config]
Metric Categories Visualization
mindmap
root((AlgoSystem<br/>Metrics))
Performance
Total Return
Annualized Return
Volatility
CAGR
Risk
Max Drawdown
VaR (95%, 99%)
CVaR/Expected Shortfall
Downside Deviation
Skewness
Kurtosis
Ratios
Sharpe Ratio
Sortino Ratio
Calmar Ratio
Information Ratio
Trade Statistics
Win Rate
Best/Worst Month
Positive/Negative Days
Average Returns
Benchmark Relative
Alpha
Beta
Correlation
Tracking Error
Capture Ratios
Chart Types Available
| Chart Type | Description | Use Case |
|---|---|---|
| ๐ Line Chart | Time series visualization | Equity curves, rolling metrics |
| ๐ฅ Heatmap Table | Color-coded data grid | Monthly/yearly returns |
| ๐ Bar Chart | Categorical comparisons | Annual performance |
| ๐ Area Chart | Filled line charts | Drawdown visualization |
| ๐ Candlestick | OHLC price data | Market analysis (future) |
Color Scheme & Styling
/* AlgoSystem Color Palette */
:root {
--primary-blue: #2E86AB;
--success-green: #2ECC71;
--warning-orange: #F39C12;
--danger-red: #E74C3C;
--dark-gray: #2C3E50;
--light-gray: #ECF0F1;
--purple: #9B59B6;
--teal: #1ABC9C;
}
/* Positive/Negative Indicators */
.positive { color: var(--success-green); }
.negative { color: var(--danger-red); }
/* Chart Colors */
.equity-curve { color: var(--primary-blue); }
.drawdown { color: var(--danger-red); }
.rolling-metrics { color: var(--purple); }
.benchmark { color: var(--teal); }
๐ค Contributing
We welcome contributions! Please see our Contributing Guide for details.
Quick Start for Contributors
# Fork and clone
git clone https://github.com/yourusername/algosystem.git
cd algosystem
# Set up development environment
poetry install --with dev
# Run tests
pytest
# Run linting
black algosystem tests
flake8 algosystem tests
# Start development server
poetry run algosystem launch --debug
๐ License
MIT License - see LICENSE file for details.
๐ Links & Resources
- ๐ฆ PyPI Package: pypi.org/project/algosystem
- ๐ Documentation: algosystem.readthedocs.io
- ๐ GitHub Repository: github.com/yourusername/algosystem
- ๐ Issue Tracker: github.com/yourusername/algosystem/issues
- ๐ฌ Discussions: github.com/yourusername/algosystem/discussions
๐ Acknowledgments
Built with โค๏ธ for the algorithmic trading community.
Special thanks to:
- QuantStats for inspiration on metrics
- Plotly for interactive charting capabilities
- Flask for the web-based editor
- The Python finance community for continuous feedback and contributions
Happy trading! ๐
Project details
Release history Release notifications | RSS feed
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 algosystem-0.1.2.tar.gz.
File metadata
- Download URL: algosystem-0.1.2.tar.gz
- Upload date:
- Size: 711.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/2.1.2 CPython/3.12.8 Windows/11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
134e1d8aeaec07a6ad17ab3221437b7f7abd149f6cfd4f9c2aef19a9a9ff0904
|
|
| MD5 |
09ea41d6087f29596c5097182d6e94dd
|
|
| BLAKE2b-256 |
3103549ae31429e4beada323cc2812b13bf35ef60ac165e6cb35c11e27ac0a05
|
File details
Details for the file algosystem-0.1.2-py3-none-any.whl.
File metadata
- Download URL: algosystem-0.1.2-py3-none-any.whl
- Upload date:
- Size: 724.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/2.1.2 CPython/3.12.8 Windows/11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c31f425ef0626f4b82ff6877c0c87ca236e76fdb71fdd7871eaefec55d769342
|
|
| MD5 |
affd81e109c65ce7b3943f6b1b94bebd
|
|
| BLAKE2b-256 |
02cad9d5916cf35127c2fa6ef391217439971fe243a745b0687eb848a3f15449
|