A comprehensive Python library for algorithmic trading with Alpaca API and Yahoo Finance integration. This repository provides utilities for portfolio analytics, data retrieval, order management, position handling, visualization, and automated notifications.
- Portfolio Analytics: Calculate performance metrics including Sharpe ratio, Sortino ratio, alpha, beta, and maximum drawdown
- Order Management: Place market, limit, and trailing stop orders with comprehensive error handling
- Position Management: Monitor positions, manage trailing stops, and close positions based on thresholds
- Data Management: Historical and real-time data from Alpaca and Yahoo Finance APIs
- News Scraping: Web scraping utilities with BeautifulSoup for financial news extraction
- Sentiment Analysis: AI-powered sentiment analysis using pre-trained financial news models
- Quantitative Tools: Correlation analysis and data preprocessing utilities
- Email Notifications: Automated alerts for trade execution and system events
- Yahoo Finance Integration: Access to market screeners and S&P 500 benchmark data
- Visualization Tools: Time series plotting and portfolio comparison charts
- Broker Integration: Seamless integration with Alpaca trading platform
- Strategy Snapshots: Export broker state (positions, orders, activities, balances, equity curve) to JSON
- Position Sizing: ATR-based volatility-adjusted position sizing with configurable risk limits
- Portfolio Constraints: Sector concentration and gross exposure checks before trade execution
- Adaptive Trailing Stops: Per-stock trailing stop percentages derived from ATR
- Targeted Order Cancellation: Cancel orders for specific symbols without removing protective stops on other positions
- Entry Order Cancellation: Cancel unfilled market/limit orders while preserving all stop orders
- Market Hours Detection: Check whether the current time is within NYSE regular trading session
- Performance Reports: One-call snapshot + metrics + multi-page PDF performance report with normalized benchmark
-
Clone the repository:
git clone https://github.com/your-username/algorithmic-trading-utilities.git cd algorithmic-trading-utilities -
Install dependencies:
pip install -r requirements.txt
pip install git+https://github.com/your-username/algorithmic-trading-utilities.gitAdd this line to your project's requirements.txt:
git+https://github.com/your-username/algorithmic-trading-utilities.gitThen install with:
pip install -r requirements.txtCreate a .env file in your project root:
PAPER_KEY="your_alpaca_paper_api_key"
PAPER_SECRET="your_alpaca_paper_secret_key"
web_app_email="your_sender_email@gmail.com"
web_app_email_password="your_gmail_app_password"
recipient_email="your_recipient_email@gmail.com"from algorithmic_trading_utilities.common.portfolio_ops import PerformanceMetrics
# Initialize PerformanceMetrics with portfolio and optional benchmark
pm = PerformanceMetrics(portfolio_equity=portfolio_series, benchmark_equity=benchmark_series)
# Get comprehensive performance metrics
metrics = pm.report()from algorithmic_trading_utilities.brokers.alpaca.orders import (
place_order,
get_orders,
cancel_orders,
place_trailing_stop_order,
cancel_order_by_symbol
)
# Place a market order
market_order = place_order(
symbol="AAPL",
quantity=10,
side="buy",
type="MarketOrderRequest",
time_in_force="gtc"
)
# Place a limit order
limit_order = place_order(
symbol="AAPL",
quantity=10,
side="buy",
type="LimitOrderRequest",
time_in_force="day",
limit_price=150.00
)
# Place a trailing stop order
trailing_stop = place_trailing_stop_order(
symbol="AAPL",
quantity=10,
side="buy",
trail_percent="5"
)
# Get all open orders
open_orders = get_orders()
print(f"Found {len(open_orders)} open orders")
# Cancel all orders
canceled_count = cancel_orders()
print(f"Canceled {canceled_count} orders")
# Cancel orders for specific symbol
cancel_order_by_symbol("AAPL")from algorithmic_trading_utilities.brokers.alpaca.positions import (
get_open_positions,
get_positions_without_trailing_stop_loss,
close_positions_below_threshold
)
from algorithmic_trading_utilities.common.config import loss_threshold
# Get all open positions
positions = get_open_positions()
for pos in positions:
print(f"Symbol: {pos['symbol']}, Qty: {pos['quantity']}, Side: {pos['side']}")
# Find positions without trailing stop protection
unprotected = get_positions_without_trailing_stop_loss()
print(f"Found {len(unprotected)} positions without trailing stops")
# Close losing positions (uses loss_threshold from config)
closed_count = close_positions_below_threshold(loss_threshold)
print(f"Closed {closed_count} positions below threshold")from algorithmic_trading_utilities.data.get_data import (
get_assets,
get_historical_data,
get_last_price,
get_asset_list
)
from algorithmic_trading_utilities.data.yfinance_ops import (
get_sp500_prices,
get_stock_gainers_table
)
from algorithmic_trading_utilities.common.config import trading_client
from alpaca.data.historical.stock import StockHistoricalDataClient
# Initialize data client
data_client = StockHistoricalDataClient("your_key", "your_secret")
# Get available assets
assets = get_assets(trading_client)
asset_symbols = get_asset_list(assets)
print(f"Found {len(asset_symbols)} tradeable assets")
# Get historical data for a specific stock
historical_data = get_historical_data("AAPL", data_client)
print(historical_data.head())
# Get current price
current_price = get_last_price("AAPL", data_client)
print(f"AAPL current price: ${current_price}")
# Get S&P 500 benchmark data
sp500_data = get_sp500_prices("2024-01-01")
print(sp500_data.tail())
# Get today's top gainers (with retry logic for rate limits)
gainers_df = get_stock_gainers_table()
print(f"Found {len(gainers_df)} large-cap gainers today")
print(gainers_df[['symbol', 'shortName', 'regularMarketChangePercent']].head())from algorithmic_trading_utilities.brokers.alpaca.account import get_balances
from algorithmic_trading_utilities.brokers.alpaca.activities import get_activities
balances = get_balances()
print(balances["cash"], balances["buying_power"], balances["equity"])
activities = get_activities(activity_types=["FILL", "DIV"], page_size=50)
print(f"Got {len(activities)} activities")from pathlib import Path
from algorithmic_trading_utilities.brokers.alpaca.performance_ops import save_strategy_snapshot
snapshot_path = save_strategy_snapshot(
strategy_name="mean_reversion_v1",
output_dir=Path("snapshots"),
timeframe="1D",
date_start="2025-01-01",
date_end="2025-01-31",
)
print(f"Saved snapshot to: {snapshot_path}")from algorithmic_trading_utilities.brokers.alpaca.performance_ops import (
generate_strategy_report,
load_strategy_snapshot,
generate_strategy_report_data,
)
# Generate a Markdown report from a saved snapshot
report_path = generate_strategy_report(snapshot_path, format="md")
print(f"Report saved to: {report_path}")
# Or get structured report data for programmatic use
snapshot = load_strategy_snapshot(snapshot_path)
report_data = generate_strategy_report_data(snapshot, include_benchmark=True)
print(f"Strategy: {report_data['strategy']}")
print(f"Open positions: {report_data['executive_summary']['open_positions_count']}")from pathlib import Path
from algorithmic_trading_utilities.brokers.alpaca.performance_ops import (
generate_performance_report,
)
# Save a snapshot, compute metrics, render plots, and write a PDF in one call
snapshot_path, pdf_path, metrics = generate_performance_report(
strategy_name="mean_reversion_v1",
output_dir=Path("strategy_snapshots"),
timeframe="1D",
date_start="2025-01-01",
include_benchmark=True,
)
print(f"Snapshot: {snapshot_path}")
print(f"PDF report: {pdf_path}")
print(f"Sharpe: {metrics['sharpe_ratio']}")from algorithmic_trading_utilities.common.portfolio_ops import (
PerformanceMetrics,
fetch_normalized_benchmark,
)
from algorithmic_trading_utilities.common.viz_ops import (
PerformanceViz,
build_performance_figures,
)
from algorithmic_trading_utilities.common.report_ops import write_performance_pdf
from algorithmic_trading_utilities.brokers.alpaca.performance_ops import (
get_portfolio_equity_series,
)
# Get portfolio equity as a date-indexed Series and align an S&P 500 benchmark
portfolio_equity = get_portfolio_equity_series()
portfolio_equity, benchmark_equity = fetch_normalized_benchmark(
portfolio_equity, "2025-01-01"
)
pm = PerformanceMetrics(portfolio_equity, benchmark_equity)
metrics = pm.calculate_all()
# Build all plots; benchmark line is hidden on dollar-scale plots by default
viz = PerformanceViz(pm=pm, benchmark_equity=benchmark_equity)
figs = build_performance_figures(viz, show=False)
# Write a multi-page PDF: cover page (title + metrics) + one figure per page
write_performance_pdf(
pdf_path="report.pdf",
title="Strategy - Performance Report",
metrics=metrics,
figs=figs,
period_text=f"Period: {portfolio_equity.index.min().date()} to {portfolio_equity.index.max().date()}",
)from algorithmic_trading_utilities.common.position_sizing import calculate_position_size
from alpaca.data.historical.stock import StockHistoricalDataClient
data_client = StockHistoricalDataClient("your_key", "your_secret")
# Size a position so that a 2x ATR move risks 1% of equity
result = calculate_position_size(
symbol="AAPL",
last_price=190.0,
equity=30000.0,
risk_per_trade=0.01,
client=data_client,
)
print(f"Shares: {result['quantity']}, Stop distance: ${result['stop_distance']}")
print(f"ATR: {result['atr']}, Notional: ${result['notional']}")from algorithmic_trading_utilities.common.portfolio_constraints import (
check_sector_exposure,
check_gross_exposure,
)
positions = [
{"symbol": "XOM", "market_value": "3000"},
{"symbol": "CVX", "market_value": "2500"},
]
# Check if adding another Energy stock would breach 30% sector limit
allowed, reason = check_sector_exposure(
positions, {"symbol": "COP", "notional": 2000}, equity=30000
)
print(f"Allowed: {allowed}, Reason: {reason}")
# Check gross exposure limit (default 80%)
allowed, reason = check_gross_exposure(positions, 3000, equity=30000)
print(f"Allowed: {allowed}, Reason: {reason}")from algorithmic_trading_utilities.common.trailing_stop_config import calculate_trailing_stop_pct
from algorithmic_trading_utilities.common.position_sizing import get_atr
atr = get_atr("AAPL", data_client)
stop_pct = calculate_trailing_stop_pct(atr=atr, last_price=190.0)
print(f"Trailing stop: {stop_pct:.1%}") # e.g., 6.6% instead of flat 10%from algorithmic_trading_utilities.brokers.alpaca.cancel_orders_targeted import cancel_orders_for_symbols
from algorithmic_trading_utilities.common.config import trading_client
# Cancel orders only for symbols about to receive new trades
cancelled = cancel_orders_for_symbols(["AAPL", "NVDA"], trading_client)
print(f"Cancelled {cancelled} orders")from algorithmic_trading_utilities.brokers.alpaca.orders import cancel_entry_orders
# Cancel all unfilled market/limit orders, preserving stop orders
cancelled = cancel_entry_orders()
print(f"Cancelled {cancelled} entry orders")from algorithmic_trading_utilities.common.market_hours import is_market_hours
# Check if NYSE is currently in regular session (09:25-16:05 ET)
if is_market_hours():
print("Market is open")
else:
print("Market is closed")from algorithmic_trading_utilities.common.quantitative_tools import (
remove_highly_correlated_columns
)
import pandas as pd
# Remove highly correlated features
data = {'A': [1, 2, 3, 4, 5], 'B': [2, 3, 4, 5, 6], 'C': [0, 5, 1, 3, 6]}
df = pd.DataFrame(data)
# Remove columns with correlation > 0.9
cleaned_df = remove_highly_correlated_columns(df, threshold=0.9)
print(f"Reduced from {len(df.columns)} to {len(cleaned_df.columns)} columns")from algorithmic_trading_utilities.common.viz_ops import (
plot_time_series,
compare_portfolio_and_benchmark,
plot_portfolio
)
# Plot portfolio vs benchmark comparison
comparison_df = get_portfolio_and_benchmark_values()
compare_portfolio_and_benchmark(comparison_df, "Portfolio vs S&P 500")
# Plot portfolio returns (handles both Series and DataFrame)
returns_df = get_portfolio_and_benchmark_returns()
plot_portfolio(returns_df["Portfolio"])
# Plot any time series data
plot_time_series(comparison_df)from algorithmic_trading_utilities.common.news_ops import (
scrape_with_beautifulsoup,
is_within_one_day,
calculate_time_ago
)
# Scrape financial news from a URL
url = "https://finance.yahoo.com/news/apple-earnings"
text_content = scrape_with_beautifulsoup(url)
# Calculate relative time from ISO timestamp
pub_date = "2025-10-11T19:27:39Z"
time_ago = calculate_time_ago(pub_date)
print(f"Posted: {time_ago}") # Output: "4h ago", "2d ago", etc.from algorithmic_trading_utilities.common.sentiment_ops import analyze_sentiment
# Analyze sentiment of financial news
text = "The company reported record profits and strong growth this quarter."
result = analyze_sentiment(text)
print(f"Sentiment: {result[0]['label']}") # positive/negative/neutral
print(f"Confidence: {result[0]['score']:.2%}") # 95%
# Example with negative sentiment
bearish_text = "The company faces bankruptcy and massive losses."
result = analyze_sentiment(bearish_text)
# Returns: [{'label': 'negative', 'score': 0.88}]from algorithmic_trading_utilities.common.email_ops import send_email_notification
# Send success notification
send_email_notification(
subject="Trade Execution",
notification="Successfully placed buy order for AAPL at $150.25",
type="SUCCESS"
)
# Send failure notification
send_email_notification(
subject="System Alert",
notification="Failed to connect to market data API",
type="FAILURE"
)import pandas as pd
from dotenv import load_dotenv
load_dotenv()
from algorithmic_trading_utilities.common.portfolio_ops import PerformanceMetrics
from algorithmic_trading_utilities.common.viz_ops import PerformanceViz
from algorithmic_trading_utilities.brokers.alpaca.alpaca_ops import get_portfolio_history
from algorithmic_trading_utilities.data.yfinance_ops import get_sp500_prices
# Get actual portfolio history
portfolio_history = get_portfolio_history()
portfolio_equity = pd.Series(
data=portfolio_history.equity,
index=pd.to_datetime(portfolio_history.timestamp, unit='s'),
name="portfolio_equity"
)
# Get S&P 500 benchmark data
benchmark_data = get_sp500_prices("2025-04-08")
benchmark_equity = pd.Series(
data=benchmark_data.iloc[:, 0].values,
index=pd.to_datetime(benchmark_data.index),
name="benchmark_equity"
)
# Align indices to common dates
common_dates = portfolio_equity.index.intersection(benchmark_equity.index)
portfolio_equity = portfolio_equity.loc[common_dates]
benchmark_equity = benchmark_equity.loc[common_dates]
# Normalize benchmark to start at same value as portfolio
benchmark_equity = benchmark_equity / benchmark_equity.iloc[0] * portfolio_equity.iloc[0]
pm = PerformanceMetrics(portfolio_equity, benchmark_equity)
metrics = pm.calculate_all()
viz = PerformanceViz(pm=pm, benchmark_equity=benchmark_equity)
fig_equity = viz.create_all_plots(True)
print("Performance Metrics:")
for key, value in metrics.items():
print(f"{key}: {value}")algorithmic_trading_utilities/
├── data/
│ ├── get_data.py # Alpaca data operations
│ └── yfinance_ops.py # Yahoo Finance integration
├── brokers/
│ └── alpaca/
│ ├── alpaca_ops.py # Portfolio history operations
│ ├── account.py # Account and balances
│ ├── activities.py # Account activities
│ ├── orders.py # Order management
│ ├── cancel_orders_targeted.py # Targeted order cancellation
│ ├── performance_ops.py # Strategy snapshot export
│ └── positions.py # Position management
├── common/
│ ├── portfolio_ops.py # Portfolio analytics + benchmark alignment
│ ├── portfolio_constraints.py # Sector/exposure risk checks
│ ├── position_sizing.py # ATR-based position sizing
│ ├── trailing_stop_config.py # Adaptive trailing stops
│ ├── market_hours.py # NYSE market hours detection
│ ├── quantitative_tools.py # Data analysis utilities
│ ├── news_ops.py # News scraping utilities
│ ├── sentiment_ops.py # Sentiment analysis with AI
│ ├── email_ops.py # Email notifications
│ ├── viz_ops.py # Visualization + figure orchestration
│ ├── report_ops.py # Multi-page PDF performance reports
│ └── config.py # Configuration and API setup
└── tests/ # Comprehensive test suitePerformance Metrics Methods:
average_return()– Daily average returntotal_return()– Total portfolio return from start to endstd_dev()– Standard deviation of returnsmax_drawdown()– Maximum drawdown (fraction)average_drawdown()– Average drawdown (fraction)drawdown_duration()– Longest duration of continuous drawdown
Risk-Adjusted Metrics:
sharpe_ratio()– Daily Sharpe ratioannualised_sharpe()– Annualized Sharpe ratiosortino_ratio()– Daily Sortino ratioannualised_sortino()– Annualized Sortino ratiocalmar_ratio()– Annual return divided by max drawdownalpha_beta()– CAPM alpha and beta vs benchmarkrolling_alpha_beta(window=252)– Rolling alpha and beta over a specified window
Return Distribution Metrics:
return_distribution_stats(alpha=0.05)– Skewness, kurtosis, VaR, and CVaR
Comprehensive Analysis:
calculate_all()– Returns all performance metrics as a dictionarycalculate_benchmark_metrics()– Returns benchmark metrics (alpha=0, beta=1 if benchmark provided)report()– Prints a formatted comparison of strategy vs benchmark metrics
Benchmark Alignment:
fetch_normalized_benchmark(portfolio_equity, date_start)– Fetches S&P 500, intersects dates with the portfolio, and rescales the benchmark so its first value equals the portfolio's first value
Order Placement:
place_order(symbol, quantity, side, type, time_in_force, **kwargs)- Place various order typesplace_trailing_stop_order(symbol, quantity, side, trail_percent)- Trailing stops
Order Retrieval:
get_orders()- Get all open ordersget_current_trailing_stop_orders()- Get active trailing stop ordersget_orders_symbol_list(orders)- Extract symbols from ordersget_orders_to_cancel()- Identify non-trailing stop orders
Order Cancellation:
cancel_orders()- Cancel all orders with retry logiccancel_order_by_symbol(symbol)- Cancel orders for specific symbolcancel_entry_orders()- Cancel unfilled market/limit orders, preserving stopscancel_orders_for_symbols(symbols, trading_client)- Cancel orders only for specified symbols (brokers.alpaca.cancel_orders_targeted)
Account and Strategy State (brokers.alpaca.account, brokers.alpaca.activities, brokers.alpaca.performance_ops)
get_balances()- Retrieve common account balance fieldsget_activities(...)- Retrieve account activitiessave_strategy_snapshot(strategy_name, ...)- Export positions/orders/activities/balances/equity performance to JSONgenerate_strategy_report(snapshot_path, ...)- Generate Markdown or JSON report from a snapshotgenerate_strategy_report_data(snapshot, ...)- Compute structured report aggregates from a snapshotnormalize_snapshot(snapshot)- Normalize raw snapshot data with data-quality warningsload_strategy_snapshot(path)- Load a saved snapshot JSON fileget_portfolio_equity_series()- Convert Alpaca portfolio history to a date-indexedpd.Seriesgenerate_performance_report(strategy_name, ...)- End-to-end: snapshot JSON + metrics + multi-page PDF report
get_atr(symbol, client, period=14)- Calculate Average True Rangecalculate_position_size(symbol, last_price, equity, risk_per_trade, client, ...)- ATR-adjusted position sizing with max notional cap
get_sector(symbol)- GICS sector lookup via yfinance with cachingcheck_sector_exposure(existing_positions, proposed_trade, equity, max_sector_pct=0.30)- Sector concentration checkcheck_gross_exposure(existing_positions, proposed_notional, equity, max_gross_pct=0.80)- Gross exposure limit check
is_market_hours()- ReturnsTrueif current UTC time is within NYSE regular session (09:25–16:05 ET / 13:25–20:05 UTC)
calculate_trailing_stop_pct(atr, last_price, min_pct=0.05, max_pct=0.20, atr_multiplier=2.5)- ATR-derived trailing stop percentage, clamped between bounds
Position Retrieval:
get_open_positions()- Get all open positions with formatted dataget_positions_without_trailing_stop_loss()- Find unprotected positionsget_positions_symbol_list(positions)- Extract symbols from positions
Position Management:
close_positions_below_threshold(threshold)- Close losing positions
get_assets(trading_client)- Retrieve tradeable assetsget_asset_list(assets)- Extract asset symbols from assetsget_historical_data(symbol, client)- Historical price data (365 days)get_last_price(symbol, client)- Most recent closing priceget_asset_df(assets)- Convert asset data to DataFrame
get_sp500_prices(start_date)- S&P 500 benchmark dataget_stock_gainers_table()- Daily large-cap gainers with retry logic
remove_highly_correlated_columns(df, threshold)- Remove correlated features
Web Scraping:
scrape_with_beautifulsoup(url)- Extract text content from financial news websites
Time Utilities:
is_within_one_day(post_time_list)- Check if post is within 24 hours (minutes, hours, or 1 day)calculate_time_ago(pub_date_str)- Convert ISO timestamp to relative time format (e.g., "4h ago", "2d ago")
AI-Powered Analysis:
analyze_sentiment(text)- Analyze sentiment using DistilRoBERTa model fine-tuned on financial news- Returns:
[{'label': 'positive'|'negative'|'neutral', 'score': float}] - Model:
mrm8488/distilroberta-finetuned-financial-news-sentiment-analysis - Optimized for financial market sentiment detection
- Returns:
plot_time_series(df)- General time series plottingcompare_portfolio_and_benchmark(df, title)- Portfolio vs benchmark chartsplot_portfolio(df)- Portfolio-specific plotting (handles Series/DataFrame)PerformanceViz(pm, benchmark_equity=...)- Per-plot rendering for aPerformanceMetricsinstancebuild_performance_figures(viz, show=False, mask_benchmark_on=("cumulative_returns", "equity_curve"))- Build all performance figures in one call; benchmark line is hidden on dollar-scale plots by default
write_performance_pdf(pdf_path, title, metrics, figs, period_text="")- Write a multi-page PDF with a cover page (title + monospace metrics block) followed by one figure per page
send_email_notification(subject, message, type)- Gmail SMTP notifications with timestamps
- Trading client setup with paper trading configuration
- Threshold settings (
loss_threshold,trailing_stop_loss_threshold) - API key management with environment variables
Default Thresholds (from config.py):
loss_threshold = 0.05 # 5% loss threshold for closing positions
trailing_stop_loss_threshold = 0.05 # 5% trailing stop loss thresholdEnvironment Variables Required:
# Alpaca API (Paper Trading)
PAPER_KEY="your_alpaca_paper_api_key"
PAPER_SECRET="your_alpaca_paper_secret_key"
# Email configuration
web_app_email="your_sender_email@gmail.com"
web_app_email_password="your_app_password"
recipient_email="your_recipient_email@gmail.com"calculate_all() returns:
{
'average_return': float, # Daily average return
'total_return': float, # Total return from start to end
'std_dev': float, # Standard deviation of returns
'sharpe_ratio': float, # Daily Sharpe ratio
'annualised_sharpe': float, # Annualized Sharpe ratio
'sortino_ratio': float, # Daily Sortino ratio
'annualised_sortino': float, # Annualized Sortino ratio
'max_drawdown': float, # Maximum drawdown (fraction)
'average_drawdown': float, # Average drawdown (fraction)
'drawdown_duration': int, # Longest duration of continuous drawdown
'skewness': float, # Skewness of daily returns
'kurtosis': float, # Kurtosis of daily returns
'VaR_5%': float, # Value at Risk (5% quantile)
'CVaR_5%': float, # Conditional Value at Risk (average of worst 5%)
'calmar_ratio': float, # Annual return / max drawdown
'alpha': float, # Alpha vs benchmark
'beta': float # Beta vs benchmark
}The library provides access to 200+ market screeners including popular ones like:
Momentum Screeners:
day_gainers- Daily top gainersday_losers- Daily top loserssmall_cap_gainers- Small cap momentummost_actives- Highest volume stocks
Value Screeners:
undervalued_large_caps- Value large capsfair_value_screener- Undervalued with strong growthundervalued_growth_stocks- Growth at reasonable prices
Sector Screeners:
growth_technology_stocks- Tech growth playsms_technology,ms_healthcare,ms_energy- Sector-specifictop_energy_us- Energy sector leaders
Investment Vehicles:
top_etfs- Top performing ETFshigh_yield_bond- High-yield bond funds
Note: get_stock_gainers_table() currently uses day_gainers filtered for large-cap stocks (market cap >= $10B) with exponential backoff retry logic for rate limiting.
Run the comprehensive test suite:
pytest tests/ -v -sTest Coverage:
test_portfolio_ops.py- Portfolio analytics and metrics (including alpha/beta)test_orders.py- Order management functionalitytest_positions.py- Position management operationstest_get_data.py- Alpaca data retrievaltest_yfinance_ops.py- Yahoo Finance operationstest_news_ops.py- News scraping and time utilitiestest_sentiment_ops.py- Sentiment analysis with AI modelstest_quantitative_tools.py- Quantitative analysis utilitiestest_viz_ops.py- Visualization functionstest_email_ops.py- Email notification systemtest_account.py- Alpaca account and balancestest_activities.py- Alpaca account activitiestest_performance_ops.py- Strategy snapshot export, equity-series helper, end-to-end PDF orchestrationtest_reporting.py- Strategy report generation and renderingtest_report_ops.py- Multi-page PDF performance report writertest_cancel_orders_targeted.py- Targeted order cancellationtest_portfolio_constraints.py- Sector and gross exposure constraintstest_position_sizing.py- ATR-based position sizingtest_trailing_stop_config.py- Adaptive trailing stop calculationtest_market_hours.py- NYSE market hours detection
The library includes robust error handling:
- Rate Limiting: Exponential backoff retry logic for Yahoo Finance API
- Empty Data: Graceful handling of empty DataFrames/Series
- API Failures: Defensive programming for network issues with APIError handling
- Data Type Flexibility: Functions handle both Series and DataFrame inputs
- Missing Data: Returns appropriate defaults (None, empty DataFrame)
- Order Management: Comprehensive error handling for trading operations
- Email Notifications: Built-in success/failure notification system
- Web Scraping: Exception handling for HTTP errors and request failures
- Sentiment Analysis: Model loading with error handling for missing dependencies
- Test strategies thoroughly with paper trading
- Never risk more than you can afford to lose
- Understand the risks of automated trading systems
- Consult with financial professionals before live trading
MIT License - see LICENSE file for details.
- Fork the repository
- Create a feature branch (
git checkout -b feature/new-feature) - Add comprehensive tests for new functionality
- Run the test suite:
pytest tests/ -v -s - Format code:
black . - Submit a pull request with detailed description
For issues and questions:
- GitHub Issues: Report bugs and request features
- Documentation: Check docstrings in each module
- Examples: Review usage patterns in this README
- Tests: Examine test files for implementation examples
- Current Version: Added order and position management, quantitative tools, comprehensive error handling
- Portfolio Analytics: Full suite including alpha/beta calculations vs S&P 500
- Yahoo Finance: Market screener integration with rate limiting and retry logic
- Email System: Gmail SMTP notifications with timestamps for trading events
- Testing: Comprehensive test suite with mocking for all modules
- Configuration: Centralized config with environment variable management