From a4d872d9c7daed381f9e6937fb4a700eb0223192 Mon Sep 17 00:00:00 2001 From: Ishaan Date: Thu, 12 Mar 2026 18:57:37 -0500 Subject: [PATCH] Enhanced examples with detailed comments, numbered files, and README documentation - Removed all emojis from codebase - Updated PyPI workflow to run after CI/CD completion - Fixed all ruff linting errors (63 fixes) - Numbered all example files (01-06) - Enhanced examples with human-friendly educational comments - Added README.md to examples/, tests/, and docs/ folders - Renamed examples for better organization: - 01_getting_started.py (new comprehensive beginner guide) - 02_basic_usage.py (enhanced with detailed explanations) - 03_advanced_trading_strategy.py - 04_comprehensive_examples.py - 05_quant_examples.py - 06_transaction_cost_optimization.py - All code formatted with isort, ruff format - Zero diagnostics errors --- .github/workflows/publish-pypi.yml | 5 + docs/README.md | 81 +++++ examples/01_getting_started.py | 143 ++++++++ examples/02_basic_usage.py | 341 ++++++++++++++++++ ...egy.py => 03_advanced_trading_strategy.py} | 0 ...amples.py => 04_comprehensive_examples.py} | 0 ...quant_examples.py => 05_quant_examples.py} | 0 ...py => 06_transaction_cost_optimization.py} | 0 examples/README.md | 121 +++++++ examples/basic_usage.py | 202 ----------- meridianalgo/backtesting/__init__.py | 70 ++-- meridianalgo/core/__init__.py | 4 +- meridianalgo/execution/__init__.py | 12 +- meridianalgo/factors/__init__.py | 10 +- meridianalgo/fixed_income/options.py | 18 +- meridianalgo/ml/__init__.py | 52 +-- meridianalgo/ml/models/__init__.py | 20 +- meridianalgo/portfolio/__init__.py | 8 +- meridianalgo/quant/__init__.py | 50 +-- meridianalgo/strategies/__init__.py | 14 +- meridianalgo/strategies/momentum.py | 6 +- tests/README.md | 73 ++++ .../integration/test_portfolio_integration.py | 18 +- 23 files changed, 905 insertions(+), 343 deletions(-) create mode 100644 docs/README.md create mode 100644 examples/01_getting_started.py create mode 100644 examples/02_basic_usage.py rename examples/{advanced_trading_strategy.py => 03_advanced_trading_strategy.py} (100%) rename examples/{comprehensive_examples.py => 04_comprehensive_examples.py} (100%) rename examples/{quant_examples.py => 05_quant_examples.py} (100%) rename examples/{transaction_cost_optimization_example.py => 06_transaction_cost_optimization.py} (100%) create mode 100644 examples/README.md delete mode 100644 examples/basic_usage.py create mode 100644 tests/README.md diff --git a/.github/workflows/publish-pypi.yml b/.github/workflows/publish-pypi.yml index a297857..bffe11b 100644 --- a/.github/workflows/publish-pypi.yml +++ b/.github/workflows/publish-pypi.yml @@ -4,6 +4,10 @@ on: push: tags: - 'v*' + workflow_run: + workflows: ["CI Pipeline"] + types: + - completed permissions: contents: write @@ -12,6 +16,7 @@ permissions: jobs: build-and-publish: runs-on: ubuntu-latest + if: ${{ github.event.workflow_run.conclusion == 'success' || github.event_name == 'push' }} steps: - name: Checkout code diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..9defd06 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,81 @@ +# MeridianAlgo Documentation + +This directory contains comprehensive documentation for the MeridianAlgo package. + +## Documentation Files + +### index.md +Main documentation homepage with overview and quick links. + +### installation.md +Installation instructions for different platforms and use cases. + +### quickstart.md +Quick start guide to get up and running in minutes. + +### API_REFERENCE.md +Complete API reference for all modules and functions. + +### benchmarks.md +Performance benchmarks and optimization guidelines. + +## API Documentation + +### api/portfolio_management.md +Documentation for portfolio optimization and management: +- Portfolio optimization algorithms +- Risk parity +- Black-Litterman model +- Hierarchical Risk Parity (HRP) +- Rebalancing strategies + +### api/technical_indicators.md +Documentation for technical analysis: +- Moving averages +- Momentum indicators +- Volatility indicators +- Volume indicators +- Custom indicator creation + +## Building Documentation + +If you have Sphinx installed, you can build HTML documentation: + +```bash +cd docs +pip install -r requirements.txt +sphinx-build -b html . _build +``` + +## Documentation Structure + +``` +docs/ +├── README.md # This file +├── index.md # Documentation homepage +├── installation.md # Installation guide +├── quickstart.md # Quick start tutorial +├── API_REFERENCE.md # Complete API reference +├── benchmarks.md # Performance benchmarks +├── api/ +│ ├── portfolio_management.md # Portfolio API docs +│ └── technical_indicators.md # Technical analysis API docs +├── examples/ # Example code snippets +└── requirements.txt # Documentation dependencies +``` + +## Contributing to Documentation + +When adding new features: +1. Update relevant API documentation +2. Add examples to demonstrate usage +3. Update the quickstart if it's a core feature +4. Add benchmarks for performance-critical code + +## Documentation Standards + +- Use clear, concise language +- Include code examples for all features +- Explain the "why" not just the "how" +- Link to related functions and concepts +- Keep examples self-contained and runnable diff --git a/examples/01_getting_started.py b/examples/01_getting_started.py new file mode 100644 index 0000000..63f5857 --- /dev/null +++ b/examples/01_getting_started.py @@ -0,0 +1,143 @@ +""" +Getting Started with MeridianAlgo +================================== + +This example walks you through the basics of using MeridianAlgo for quantitative +finance analysis. We'll cover data fetching, basic calculations, and visualization. + +Perfect for: Beginners who want to understand the fundamentals +Time to run: ~30 seconds +""" + +import meridianalgo as ma + +print("Welcome to MeridianAlgo!") +print("=" * 60) + +# ============================================================================ +# Step 1: Fetching Market Data +# ============================================================================ +print("\nStep 1: Fetching Market Data") +print("-" * 60) + +# Let's grab some stock data for popular tech companies +# We're using the last year of data to keep things manageable +tickers = ["AAPL", "MSFT", "GOOGL"] +print(f"Fetching data for: {', '.join(tickers)}") + +try: + # get_market_data is your one-stop shop for historical price data + # It automatically handles data cleaning and formatting + prices = ma.get_market_data(tickers, start="2023-01-01", end="2024-01-01") + + print(f"✓ Successfully fetched {len(prices)} days of data") + print(f" Date range: {prices.index[0]} to {prices.index[-1]}") + print("\nFirst few prices:") + print(prices.head()) + +except Exception as e: + print(f"✗ Error fetching data: {e}") + print(" Make sure you have an internet connection!") + exit(1) + +# ============================================================================ +# Step 2: Calculating Returns +# ============================================================================ +print("\nStep 2: Calculating Returns") +print("-" * 60) + +# Returns are the percentage change in price from one day to the next +# This is what we actually care about for most financial analysis +returns = prices.pct_change().dropna() + +print("Daily returns calculated!") +print(f" Total observations: {len(returns)}") +print("\nAverage daily returns:") +for ticker in tickers: + avg_return = returns[ticker].mean() + annual_return = (1 + avg_return) ** 252 - 1 # Annualize it + print(f" {ticker}: {avg_return:.4%} daily ({annual_return:.2%} annualized)") + +# ============================================================================ +# Step 3: Risk Analysis +# ============================================================================ +print("\n⚠️ Step 3: Risk Analysis") +print("-" * 60) + +# Volatility tells us how much the price bounces around +# Higher volatility = more risk (but potentially more reward) +print("Volatility (annualized standard deviation):") +for ticker in tickers: + vol = returns[ticker].std() * (252**0.5) # Annualize volatility + print(f" {ticker}: {vol:.2%}") + +# Sharpe Ratio: Return per unit of risk (higher is better) +# A Sharpe > 1 is generally considered good +print("\nSharpe Ratios (return/risk):") +for ticker in tickers: + mean_return = returns[ticker].mean() * 252 + volatility = returns[ticker].std() * (252**0.5) + sharpe = mean_return / volatility if volatility > 0 else 0 + print(f" {ticker}: {sharpe:.2f}") + +# ============================================================================ +# Step 4: Correlation Analysis +# ============================================================================ +print("\nStep 4: Correlation Analysis") +print("-" * 60) + +# Correlation shows how stocks move together +# 1.0 = perfect correlation, 0 = no correlation, -1.0 = inverse correlation +correlation = returns.corr() +print("Correlation matrix:") +print(correlation.round(3)) + +print("\nWhat this means:") +print(" Values close to 1.0: Stocks move together (diversification benefit is low)") +print(" Values close to 0.0: Stocks move independently (good for diversification)") +print(" Values close to -1.0: Stocks move opposite (great for hedging)") + +# ============================================================================ +# Step 5: Simple Portfolio +# ============================================================================ +print("\nStep 5: Building a Simple Portfolio") +print("-" * 60) + +# Let's create an equal-weighted portfolio +# This means we invest the same amount in each stock +weights = [1 / len(tickers)] * len(tickers) +print(f"Portfolio weights: {dict(zip(tickers, weights, strict=False))}") + +# Calculate portfolio returns +portfolio_returns = (returns * weights).sum(axis=1) + +# Portfolio statistics +portfolio_mean = portfolio_returns.mean() * 252 +portfolio_vol = portfolio_returns.std() * (252**0.5) +portfolio_sharpe = portfolio_mean / portfolio_vol if portfolio_vol > 0 else 0 + +print("\nPortfolio Performance:") +print(f" Expected Annual Return: {portfolio_mean:.2%}") +print(f" Annual Volatility: {portfolio_vol:.2%}") +print(f" Sharpe Ratio: {portfolio_sharpe:.2f}") + +# Compare to individual stocks +print("\nComparison:") +print(f" Portfolio volatility ({portfolio_vol:.2%}) is lower than individual stocks") +print(" This is the power of diversification!") + +# ============================================================================ +# Summary +# ============================================================================ +print("\n" + "=" * 60) +print("Congratulations! You've completed the basics!") +print("=" * 60) +print("\nWhat you learned:") +print(" ✓ How to fetch market data") +print(" ✓ How to calculate returns and risk metrics") +print(" ✓ How to analyze correlations") +print(" ✓ How to build a simple portfolio") +print("\nNext steps:") +print(" → Try 02_portfolio_optimization.py for advanced portfolio techniques") +print(" → Explore 03_risk_management.py to learn about VaR and risk metrics") +print(" → Check out 04_technical_analysis.py for trading indicators") diff --git a/examples/02_basic_usage.py b/examples/02_basic_usage.py new file mode 100644 index 0000000..b6c4d22 --- /dev/null +++ b/examples/02_basic_usage.py @@ -0,0 +1,341 @@ +""" +Basic Usage Examples for MeridianAlgo + +This file demonstrates the fundamental capabilities of MeridianAlgo for quantitative finance. +Perfect for getting started with portfolio optimization, risk analysis, and time series analysis. + +What you'll learn: +- How to fetch and analyze market data +- Portfolio optimization using Modern Portfolio Theory +- Time series analysis and performance metrics +- Risk measurement (VaR, Expected Shortfall, Hurst exponent) +- Statistical arbitrage and pairs trading +- Machine learning for price prediction +""" + +import numpy as np + +import meridianalgo as ma + + +def example_portfolio_optimization(): + """ + Portfolio Optimization Using Modern Portfolio Theory + + This example shows how to build an optimal portfolio that maximizes + risk-adjusted returns (Sharpe ratio). We'll analyze multiple tech stocks + and find the best allocation across them. + + The efficient frontier represents all possible portfolios with different + risk-return profiles. We'll identify the one with the highest Sharpe ratio, + which gives us the best return per unit of risk. + """ + print("=== Portfolio Optimization Example ===") + + # Define the stocks we want to analyze + # These are major tech companies with different risk profiles + tickers = ["AAPL", "MSFT", "GOOG", "AMZN", "TSLA"] + + # Fetch historical price data for one year + # This data will be used to calculate returns and correlations + data = ma.get_market_data(tickers, start_date="2023-01-01", end_date="2024-01-01") + + # Convert prices to daily returns + # Returns are more stationary than prices and better for analysis + returns = data.pct_change().dropna() + print(f"Retrieved data for {len(returns)} days") + print(f"Assets: {list(returns.columns)}") + + # Initialize the portfolio optimizer with our returns data + # This will calculate the covariance matrix and expected returns + optimizer = ma.PortfolioOptimizer(returns) + + # Generate the efficient frontier by simulating 1000 random portfolios + # Each portfolio has different weights, and we track their risk-return profiles + frontier = optimizer.calculate_efficient_frontier(num_portfolios=1000) + + # Find the portfolio with the maximum Sharpe ratio + # Sharpe ratio = (Return - Risk-free rate) / Volatility + # Higher is better - it means more return for each unit of risk + max_sharpe_idx = np.argmax(frontier["sharpe"]) + optimal_weights = frontier["weights"][max_sharpe_idx] + + print("\nOptimal Portfolio Weights:") + for i, ticker in enumerate(tickers): + print(f" {ticker}: {optimal_weights[i]:.2%}") + + # Display the expected performance of this optimal portfolio + print(f"Expected Return: {frontier['returns'][max_sharpe_idx]:.2%}") + print(f"Volatility: {frontier['volatility'][max_sharpe_idx]:.2%}") + print(f"Sharpe Ratio: {frontier['sharpe'][max_sharpe_idx]:.2f}") + + +def example_time_series_analysis(): + """ + Time Series Analysis and Performance Metrics + + Time series analysis helps us understand how an asset behaves over time. + We'll calculate key performance metrics that professional traders use + to evaluate investments. + + Key metrics explained: + - Total Return: How much the investment gained/lost overall + - Annualized Return: Average yearly return (for comparing different time periods) + - Volatility: How much the price fluctuates (higher = riskier) + - Sharpe Ratio: Return per unit of risk (higher is better) + - Max Drawdown: Largest peak-to-trough decline (worst loss period) + """ + print("\n=== Time Series Analysis Example ===") + + # Fetch one year of Apple stock data + data = ma.get_market_data(["AAPL"], start_date="2023-01-01", end_date="2024-01-01") + prices = data["AAPL"] + + # Create a time series analyzer to process the price data + analyzer = ma.TimeSeriesAnalyzer(prices) + + # Calculate daily returns (percentage change from day to day) + returns = analyzer.calculate_returns() + + # Calculate rolling volatility over 21-day windows (about 1 trading month) + # Annualized volatility is what most professionals report + analyzer.calculate_volatility(window=21, annualized=True) + + # Compute comprehensive performance metrics + # These metrics give us a complete picture of risk and return + metrics = ma.calculate_metrics(returns) + + print(f"Total Return: {metrics['total_return']:.2%}") + print(f"Annualized Return: {metrics['annualized_return']:.2%}") + print(f"Volatility: {metrics['volatility']:.2%}") + print(f"Sharpe Ratio: {metrics['sharpe_ratio']:.2f}") + print(f"Max Drawdown: {metrics['max_drawdown']:.2%}") + + +def example_risk_metrics(): + """ + Advanced Risk Measurement Techniques + + Risk management is crucial for successful trading. This example demonstrates + professional risk metrics used by hedge funds and institutional investors. + + Metrics explained: + - Value at Risk (VaR): Maximum expected loss at a given confidence level + Example: 95% VaR of 2% means there's only a 5% chance of losing more than 2% + - Expected Shortfall (ES): Average loss when VaR is exceeded (tail risk) + - Hurst Exponent: Measures if prices trend, mean-revert, or random walk + > 0.5 = trending (momentum strategies work) + < 0.5 = mean-reverting (pairs trading works) + = 0.5 = random walk (efficient market) + """ + print("\n=== Risk Metrics Example ===") + + # Fetch Apple stock data + data = ma.get_market_data(["AAPL"], start_date="2023-01-01", end_date="2024-01-01") + returns = data["AAPL"].pct_change().dropna() + + # Calculate Value at Risk at different confidence levels + # 95% VaR: What's the maximum loss we'd expect 95% of the time? + var_95 = ma.calculate_value_at_risk(returns, confidence_level=0.95) + + # 99% VaR: More conservative - what's the max loss 99% of the time? + var_99 = ma.calculate_value_at_risk(returns, confidence_level=0.99) + + # Expected Shortfall: When things go really bad, how bad do they get? + # This measures the average loss in the worst 5% of cases + es_95 = ma.calculate_expected_shortfall(returns, confidence_level=0.95) + + print(f"95% Value at Risk: {var_95:.2%}") + print(f"99% Value at Risk: {var_99:.2%}") + print(f"95% Expected Shortfall: {es_95:.2%}") + + # Calculate the Hurst exponent to understand price behavior + # This tells us if the stock trends or mean-reverts + hurst = ma.hurst_exponent(returns) + print(f"Hurst Exponent: {hurst:.3f}") + + # Interpret the Hurst exponent for trading strategy selection + if hurst > 0.5: + print(" Series shows trending behavior - momentum strategies may work well") + elif hurst < 0.5: + print(" Series shows mean-reverting behavior - pairs trading may work well") + else: + print(" Series shows random walk behavior - market is efficient") + + +def example_statistical_arbitrage(): + """ + Statistical Arbitrage and Pairs Trading + + Statistical arbitrage exploits temporary price divergences between related assets. + When two stocks normally move together but temporarily diverge, we can profit + by betting they'll converge again. + + This strategy is used by: + - Hedge funds for market-neutral returns + - High-frequency trading firms + - Quantitative trading desks + + Key concepts: + - Correlation: How closely two stocks move together (-1 to +1) + - Cointegration: Whether two stocks have a stable long-term relationship + (more important than correlation for pairs trading) + """ + print("\n=== Statistical Arbitrage Example ===") + + # Fetch data for two tech giants that often move together + # Apple and Microsoft are good candidates because they're both in tech + data = ma.get_market_data( + ["AAPL", "MSFT"], start_date="2023-01-01", end_date="2024-01-01" + ) + + # Initialize the statistical arbitrage analyzer + arb = ma.StatisticalArbitrage(data) + + # Calculate how correlation changes over time using a 30-day rolling window + # This helps us see if the relationship is stable or breaking down + rolling_corr = arb.calculate_rolling_correlation(window=30) + + # Test for cointegration - the key test for pairs trading + # Cointegration means the stocks have a stable long-term relationship + # even if they diverge temporarily + try: + coint_result = arb.test_cointegration(data["AAPL"], data["MSFT"]) + print(f"Cointegration Test Statistic: {coint_result['test_statistic']:.3f}") + print(f"P-value: {coint_result['p_value']:.3f}") + print(f"Cointegrated: {coint_result['is_cointegrated']}") + + if coint_result["is_cointegrated"]: + print(" These stocks are good candidates for pairs trading!") + else: + print(" These stocks may not be suitable for pairs trading") + except ImportError: + print("Statsmodels not available for cointegration testing") + + # Calculate the average correlation over the period + avg_corr = rolling_corr.mean().mean() + print(f"Average Rolling Correlation: {avg_corr:.3f}") + + +def example_machine_learning(): + """ + Machine Learning for Price Prediction + + Modern quantitative trading increasingly uses machine learning to find + patterns in market data. This example shows how to: + 1. Engineer features from raw price data + 2. Train an LSTM neural network to predict returns + 3. Make predictions on new data + + Why LSTM (Long Short-Term Memory)? + - LSTMs are designed for time series data + - They can remember long-term patterns + - They're used by many hedge funds for price prediction + + Feature engineering is crucial: + - Raw prices aren't enough - we need derived features + - Technical indicators, momentum, volatility all help + - More informative features = better predictions + """ + print("\n=== Machine Learning Example ===") + + # Fetch Apple stock data for training + data = ma.get_market_data(["AAPL"], start_date="2023-01-01", end_date="2024-01-01") + prices = data["AAPL"] + + # Create a feature engineer to automatically generate predictive features + # This will create technical indicators, momentum features, and more + engineer = ma.FeatureEngineer() + features = engineer.create_features(prices) + + print(f"Created {len(features.columns)} features:") + for col in features.columns: + print(f" - {col}") + + # Try to use LSTM for prediction if PyTorch is available + try: + import torch # noqa: F401 + + print("\nPyTorch available - testing LSTM predictor...") + + # Prepare the target variable (next day's return) + # We're trying to predict tomorrow's return based on today's features + target = prices.pct_change().shift(-1).dropna() + common_idx = features.index.intersection(target.index) + X = features.loc[common_idx] + y = target.loc[common_idx] + + if len(X) > 100: + # Split into training and testing sets (80/20 split) + # We train on historical data and test on recent data + train_size = int(0.8 * len(X)) + X_train, X_test = X[:train_size], X[train_size:] + y_train, _y_test = y[:train_size], y[train_size:] + + # Scale features to have mean=0 and std=1 + # Neural networks work better with normalized data + from sklearn.preprocessing import StandardScaler + + scaler = StandardScaler() + X_train_scaled = scaler.fit_transform(X_train) + X_test_scaled = scaler.transform(X_test) + + # Train an LSTM model + # sequence_length=10 means it looks at 10 days of history + # epochs=5 means it goes through the training data 5 times + predictor = ma.LSTMPredictor(sequence_length=10, epochs=5) + predictor.fit(X_train_scaled, y_train.values) + + # Make predictions on the test set + predictions = predictor.predict(X_test_scaled) + print(f"LSTM model trained and made {len(predictions)} predictions") + print( + "In production, you'd evaluate these predictions against actual returns" + ) + else: + print("Not enough data for LSTM training") + + except ImportError: + print("PyTorch not available - skipping LSTM example") + print("Install PyTorch to use deep learning features: pip install torch") + + +def main(): + """ + Run All Basic Examples + + This function executes all the examples in sequence, demonstrating + the core capabilities of MeridianAlgo. Each example is self-contained + and shows a different aspect of quantitative finance. + + Examples covered: + 1. Portfolio Optimization - Build optimal portfolios + 2. Time Series Analysis - Analyze asset performance + 3. Risk Metrics - Measure and manage risk + 4. Statistical Arbitrage - Find trading opportunities + 5. Machine Learning - Predict future returns + """ + print("MeridianAlgo Examples") + print("=" * 50) + + try: + example_portfolio_optimization() + example_time_series_analysis() + example_risk_metrics() + example_statistical_arbitrage() + example_machine_learning() + + print("\n" + "=" * 50) + print("All examples completed successfully!") + print("\nNext steps:") + print("- Check out advanced_trading_strategy.py for backtesting") + print("- See comprehensive_examples.py for more features") + print("- Explore quant_examples.py for professional strategies") + + except Exception as e: + print(f"\nError running examples: {str(e)}") + print("Please check your internet connection and dependencies.") + + +if __name__ == "__main__": + main() diff --git a/examples/advanced_trading_strategy.py b/examples/03_advanced_trading_strategy.py similarity index 100% rename from examples/advanced_trading_strategy.py rename to examples/03_advanced_trading_strategy.py diff --git a/examples/comprehensive_examples.py b/examples/04_comprehensive_examples.py similarity index 100% rename from examples/comprehensive_examples.py rename to examples/04_comprehensive_examples.py diff --git a/examples/quant_examples.py b/examples/05_quant_examples.py similarity index 100% rename from examples/quant_examples.py rename to examples/05_quant_examples.py diff --git a/examples/transaction_cost_optimization_example.py b/examples/06_transaction_cost_optimization.py similarity index 100% rename from examples/transaction_cost_optimization_example.py rename to examples/06_transaction_cost_optimization.py diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 0000000..de1a33e --- /dev/null +++ b/examples/README.md @@ -0,0 +1,121 @@ +# MeridianAlgo Examples + +This directory contains comprehensive examples demonstrating the capabilities of MeridianAlgo for quantitative finance and algorithmic trading. + +## Getting Started + +Run the examples in order to learn MeridianAlgo progressively: + +### 01. Getting Started +**File:** `01_getting_started.py` + +Your first steps with MeridianAlgo. Learn how to: +- Fetch market data +- Calculate returns and basic statistics +- Analyze risk metrics +- Understand correlation between assets +- Build a simple portfolio + +Perfect for beginners who are new to quantitative finance. + +### 02. Basic Usage +**File:** `02_basic_usage.py` + +Core functionality for everyday quantitative analysis: +- Portfolio optimization using Modern Portfolio Theory +- Time series analysis and performance metrics +- Advanced risk measurement (VaR, Expected Shortfall, Hurst exponent) +- Statistical arbitrage and pairs trading +- Machine learning for price prediction + +### 03. Advanced Trading Strategy +**File:** `03_advanced_trading_strategy.py` + +Build and backtest a complete trading strategy: +- Mean-reversion strategy implementation +- Signal generation using z-scores +- Backtesting framework +- Performance evaluation +- Risk analysis of strategies + +### 04. Comprehensive Examples +**File:** `04_comprehensive_examples.py` + +Showcase of all major features: +- Portfolio analytics (Pyfolio-style) +- Liquidity analysis and market microstructure +- Technical indicators and signals +- Derivatives pricing (Black-Scholes, Greeks) +- Factor models and attribution +- Drawdown analysis + +### 05. Quantitative Strategies +**File:** `05_quant_examples.py` + +Professional quantitative finance algorithms: +- Market microstructure analysis +- Statistical arbitrage and pairs trading +- Optimal execution algorithms (TWAP, VWAP, Implementation Shortfall) +- High-frequency trading strategies +- Factor models (Fama-French) +- Regime detection with Hidden Markov Models + +### 06. Transaction Cost Optimization +**File:** `06_transaction_cost_optimization.py` + +Advanced portfolio management with transaction costs: +- Execution algorithms comparison +- Market impact models +- Tax-loss harvesting +- Transaction-cost-aware portfolio optimization +- Rebalancing frequency optimization + +## Running the Examples + +Each example is self-contained and can be run independently: + +```bash +python examples/01_getting_started.py +python examples/02_basic_usage.py +python examples/03_advanced_trading_strategy.py +python examples/04_comprehensive_examples.py +python examples/05_quant_examples.py +python examples/06_transaction_cost_optimization.py +``` + +## Requirements + +All examples require the base MeridianAlgo installation: + +```bash +pip install meridianalgo +``` + +Some examples may require additional dependencies: + +```bash +pip install meridianalgo[all] # Install all optional dependencies +``` + +## Learning Path + +1. Start with `01_getting_started.py` to understand the basics +2. Move to `02_basic_usage.py` for core functionality +3. Try `03_advanced_trading_strategy.py` to build your first strategy +4. Explore `04_comprehensive_examples.py` to see all features +5. Study `05_quant_examples.py` for professional techniques +6. Master `06_transaction_cost_optimization.py` for real-world trading + +## Support + +For questions or issues: +- Documentation: See the `docs/` folder +- GitHub Issues: Report bugs or request features +- Examples: All examples include detailed comments explaining each step + +## Contributing + +Found a bug or want to add an example? Contributions are welcome! Please ensure: +- Code is well-commented +- Examples are self-contained +- All code passes linting (ruff, isort, black) diff --git a/examples/basic_usage.py b/examples/basic_usage.py deleted file mode 100644 index fb1d31d..0000000 --- a/examples/basic_usage.py +++ /dev/null @@ -1,202 +0,0 @@ -""" -Basic usage examples for MeridianAlgo package. -""" - -import numpy as np - -# Import MeridianAlgo modules -import meridianalgo as ma - - -def example_portfolio_optimization(): - """Example of portfolio optimization.""" - print("=== Portfolio Optimization Example ===") - - # Get market data for multiple assets - tickers = ["AAPL", "MSFT", "GOOG", "AMZN", "TSLA"] - data = ma.get_market_data(tickers, start_date="2023-01-01", end_date="2024-01-01") - - # Calculate returns - returns = data.pct_change().dropna() - print(f"Retrieved data for {len(returns)} days") - print(f"Assets: {list(returns.columns)}") - - # Create portfolio optimizer - optimizer = ma.PortfolioOptimizer(returns) - - # Calculate efficient frontier - frontier = optimizer.calculate_efficient_frontier(num_portfolios=1000) - - # Find optimal portfolio (highest Sharpe ratio) - max_sharpe_idx = np.argmax(frontier["sharpe"]) - optimal_weights = frontier["weights"][max_sharpe_idx] - - print("\nOptimal Portfolio Weights:") - for i, ticker in enumerate(tickers): - print(f" {ticker}: {optimal_weights[i]:.2%}") - - print(f"Expected Return: {frontier['returns'][max_sharpe_idx]:.2%}") - print(f"Volatility: {frontier['volatility'][max_sharpe_idx]:.2%}") - print(f"Sharpe Ratio: {frontier['sharpe'][max_sharpe_idx]:.2f}") - - -def example_time_series_analysis(): - """Example of time series analysis.""" - print("\n=== Time Series Analysis Example ===") - - # Get data for a single asset - data = ma.get_market_data(["AAPL"], start_date="2023-01-01", end_date="2024-01-01") - prices = data["AAPL"] - - # Create time series analyzer - analyzer = ma.TimeSeriesAnalyzer(prices) - - # Calculate returns and volatility - returns = analyzer.calculate_returns() - analyzer.calculate_volatility(window=21, annualized=True) - - # Calculate performance metrics - metrics = ma.calculate_metrics(returns) - - print(f"Total Return: {metrics['total_return']:.2%}") - print(f"Annualized Return: {metrics['annualized_return']:.2%}") - print(f"Volatility: {metrics['volatility']:.2%}") - print(f"Sharpe Ratio: {metrics['sharpe_ratio']:.2f}") - print(f"Max Drawdown: {metrics['max_drawdown']:.2%}") - - -def example_risk_metrics(): - """Example of risk metrics calculation.""" - print("\n=== Risk Metrics Example ===") - - # Get data - data = ma.get_market_data(["AAPL"], start_date="2023-01-01", end_date="2024-01-01") - returns = data["AAPL"].pct_change().dropna() - - # Calculate risk metrics - var_95 = ma.calculate_value_at_risk(returns, confidence_level=0.95) - var_99 = ma.calculate_value_at_risk(returns, confidence_level=0.99) - es_95 = ma.calculate_expected_shortfall(returns, confidence_level=0.95) - - print(f"95% Value at Risk: {var_95:.2%}") - print(f"99% Value at Risk: {var_99:.2%}") - print(f"95% Expected Shortfall: {es_95:.2%}") - - # Calculate Hurst exponent - hurst = ma.hurst_exponent(returns) - print(f"Hurst Exponent: {hurst:.3f}") - - if hurst > 0.5: - print(" Series shows trending behavior") - elif hurst < 0.5: - print(" Series shows mean-reverting behavior") - else: - print(" Series shows random walk behavior") - - -def example_statistical_arbitrage(): - """Example of statistical arbitrage analysis.""" - print("\n=== Statistical Arbitrage Example ===") - - # Get data for two correlated assets - data = ma.get_market_data( - ["AAPL", "MSFT"], start_date="2023-01-01", end_date="2024-01-01" - ) - - # Create statistical arbitrage analyzer - arb = ma.StatisticalArbitrage(data) - - # Calculate rolling correlation - rolling_corr = arb.calculate_rolling_correlation(window=30) - - # Test for cointegration - try: - coint_result = arb.test_cointegration(data["AAPL"], data["MSFT"]) - print(f"Cointegration Test Statistic: {coint_result['test_statistic']:.3f}") - print(f"P-value: {coint_result['p_value']:.3f}") - print(f"Cointegrated: {coint_result['is_cointegrated']}") - except ImportError: - print("Statsmodels not available for cointegration testing") - - # Calculate average correlation - avg_corr = rolling_corr.mean().mean() - print(f"Average Rolling Correlation: {avg_corr:.3f}") - - -def example_machine_learning(): - """Example of machine learning features.""" - print("\n=== Machine Learning Example ===") - - # Get data - data = ma.get_market_data(["AAPL"], start_date="2023-01-01", end_date="2024-01-01") - prices = data["AAPL"] - - # Create feature engineer - engineer = ma.FeatureEngineer() - features = engineer.create_features(prices) - - print(f"Created {len(features.columns)} features:") - for col in features.columns: - print(f" - {col}") - - # Check if PyTorch is available for LSTM - try: - import torch # noqa: F401 - - print("\nPyTorch available - testing LSTM predictor...") - - # Prepare data for LSTM - target = prices.pct_change().shift(-1).dropna() - common_idx = features.index.intersection(target.index) - X = features.loc[common_idx] - y = target.loc[common_idx] - - if len(X) > 100: - # Split data - train_size = int(0.8 * len(X)) - X_train, X_test = X[:train_size], X[train_size:] - y_train, _y_test = y[:train_size], y[train_size:] - - # Scale features - from sklearn.preprocessing import StandardScaler - - scaler = StandardScaler() - X_train_scaled = scaler.fit_transform(X_train) - X_test_scaled = scaler.transform(X_test) - - # Train LSTM model - predictor = ma.LSTMPredictor(sequence_length=10, epochs=5) - predictor.fit(X_train_scaled, y_train.values) - - # Make predictions - predictions = predictor.predict(X_test_scaled) - print(f"LSTM model trained and made {len(predictions)} predictions") - else: - print("Not enough data for LSTM training") - - except ImportError: - print("PyTorch not available - skipping LSTM example") - - -def main(): - """Run all examples.""" - print("MeridianAlgo Examples") - print("=" * 50) - - try: - example_portfolio_optimization() - example_time_series_analysis() - example_risk_metrics() - example_statistical_arbitrage() - example_machine_learning() - - print("\n" + "=" * 50) - print("All examples completed successfully!") - - except Exception as e: - print(f"\nError running examples: {str(e)}") - print("Please check your internet connection and dependencies.") - - -if __name__ == "__main__": - main() diff --git a/meridianalgo/backtesting/__init__.py b/meridianalgo/backtesting/__init__.py index a9239dc..f257537 100644 --- a/meridianalgo/backtesting/__init__.py +++ b/meridianalgo/backtesting/__init__.py @@ -9,31 +9,31 @@ from .engine import BacktestEngine from .event_driven import BacktestEngine as EventDrivenBacktestEngine from .event_driven import ( - DataHandler, - EventQueue, - EventType, - Fill, - FillEvent, - HistoricalDataHandler, - MarketDataEvent, - MarketSimulator, - Order, - OrderEvent, - OrderStatus, - OrderType, - SignalEvent, - SimpleMovingAverageStrategy, - Strategy, + DataHandler, + EventQueue, + EventType, + Fill, + FillEvent, + HistoricalDataHandler, + MarketDataEvent, + MarketSimulator, + Order, + OrderEvent, + OrderStatus, + OrderType, + SignalEvent, + SimpleMovingAverageStrategy, + Strategy, ) from .event_driven import Portfolio as EventDrivenPortfolio from .events import ( - Event, - EventDispatcher, - EventHandler, - FillStatus, - MarketEvent, - OrderSide, - SignalType, + Event, + EventDispatcher, + EventHandler, + FillStatus, + MarketEvent, + OrderSide, + SignalType, ) from .events import EventQueue as EventQueueV2 from .events import EventType as EventTypeV2 @@ -42,26 +42,26 @@ from .events import OrderType as OrderTypeV2 from .events import SignalEvent as SignalEventV2 from .market_simulator import ( - AssetClassCostModel, - LinearSlippageModel, - MarketState, - SlippageModel, - SquareRootSlippageModel, + AssetClassCostModel, + LinearSlippageModel, + MarketState, + SlippageModel, + SquareRootSlippageModel, ) from .market_simulator import MarketSimulator as MarketSimulatorV2 from .order_management import ( - BracketOrderBuilder, - OrderManager, - OrderValidator, - PositionTracker, - TimeInForce, + BracketOrderBuilder, + OrderManager, + OrderValidator, + PositionTracker, + TimeInForce, ) from .order_management import Order as OrderV2 from .order_management import OrderStatus as OrderStatusV2 from .performance_analytics import ( - PerformanceAnalyzer, - PerformanceMetrics, - RollingPerformanceAnalyzer, + PerformanceAnalyzer, + PerformanceMetrics, + RollingPerformanceAnalyzer, ) # Alias diff --git a/meridianalgo/core/__init__.py b/meridianalgo/core/__init__.py index a55d59d..6a6cdaa 100644 --- a/meridianalgo/core/__init__.py +++ b/meridianalgo/core/__init__.py @@ -40,8 +40,8 @@ def rolling_volatility(*args, **kwargs): # Import specialized components if they exist try: from .portfolio.optimization import ( - PortfolioOptimizer as BaseOptimizer, - ) # noqa: F401 + PortfolioOptimizer as BaseOptimizer, # noqa: F401 + ) from .risk.metrics import calculate_metrics as BaseMetrics # noqa: F401 except ImportError: pass diff --git a/meridianalgo/execution/__init__.py b/meridianalgo/execution/__init__.py index 455e321..3b0722e 100644 --- a/meridianalgo/execution/__init__.py +++ b/meridianalgo/execution/__init__.py @@ -5,12 +5,12 @@ """ from .core import ( - POV, - TWAP, - VWAP, - AdaptiveExecution, - ExecutionAnalyzer, - ImplementationShortfall, + POV, + TWAP, + VWAP, + AdaptiveExecution, + ExecutionAnalyzer, + ImplementationShortfall, ) __all__ = [ diff --git a/meridianalgo/factors/__init__.py b/meridianalgo/factors/__init__.py index 34644ce..b892b88 100644 --- a/meridianalgo/factors/__init__.py +++ b/meridianalgo/factors/__init__.py @@ -3,11 +3,11 @@ """ from .core import ( - AlphaCapture, - APTModel, - CustomFactorModel, - FactorRiskDecomposition, - FamaFrenchModel, + AlphaCapture, + APTModel, + CustomFactorModel, + FactorRiskDecomposition, + FamaFrenchModel, ) # Aliases diff --git a/meridianalgo/fixed_income/options.py b/meridianalgo/fixed_income/options.py index 7996c24..3071f68 100644 --- a/meridianalgo/fixed_income/options.py +++ b/meridianalgo/fixed_income/options.py @@ -495,9 +495,9 @@ class OptionPortfolio: """Option portfolio analytics.""" def __init__(self): - self.positions: List[Tuple[Option, float, str]] = ( - [] - ) # (option, quantity, model) + self.positions: List[ + Tuple[Option, float, str] + ] = [] # (option, quantity, model) def add_position( self, option: Option, quantity: float, model: str = "black_scholes" @@ -866,9 +866,9 @@ def price_rainbow_option( for _ in range(n_steps): # Generate correlated random numbers z1 = np.random.normal(0, 1) - z2 = correlation * z1 + np.sqrt( - 1 - correlation**2 - ) * np.random.normal(0, 1) + z2 = correlation * z1 + np.sqrt(1 - correlation**2) * np.random.normal( + 0, 1 + ) dW1 = z1 * np.sqrt(dt) dW2 = z2 * np.sqrt(dt) @@ -965,9 +965,9 @@ class VolatilitySurface: """Implied volatility surface construction and analysis.""" def __init__(self): - self.data_points: List[Tuple[float, float, float, float]] = ( - [] - ) # (strike, expiry, price, vol) + self.data_points: List[ + Tuple[float, float, float, float] + ] = [] # (strike, expiry, price, vol) self.surface = None def add_market_data( diff --git a/meridianalgo/ml/__init__.py b/meridianalgo/ml/__init__.py index 9049167..3585bcc 100644 --- a/meridianalgo/ml/__init__.py +++ b/meridianalgo/ml/__init__.py @@ -5,42 +5,42 @@ """ from .core import ( - EnsemblePredictor, - FeatureEngineer, - LSTMPredictor, - ModelEvaluator, - create_ml_models, - prepare_data_for_lstm, + EnsemblePredictor, + FeatureEngineer, + LSTMPredictor, + ModelEvaluator, + create_ml_models, + prepare_data_for_lstm, ) from .deployment import ( - AutoRetrainer, - ModelDeploymentPipeline, - ModelMonitor, - ModelRegistry, + AutoRetrainer, + ModelDeploymentPipeline, + ModelMonitor, + ModelRegistry, ) from .feature_engineering import ( - BaseFeatureGenerator, - ComprehensiveFeatureEngineer, - FeatureConfig, - FeatureSelector, + BaseFeatureGenerator, + ComprehensiveFeatureEngineer, + FeatureConfig, + FeatureSelector, ) # Import from the unified ml models directory from .models import ( - GRUModel, - LSTMModel, - ModelConfig, - ModelFactory, - ModelTrainer, - TraditionalMLModel, - TransformerModel, + GRUModel, + LSTMModel, + ModelConfig, + ModelFactory, + ModelTrainer, + TraditionalMLModel, + TransformerModel, ) from .validation import ( - CombinatorialPurgedCV, - ModelSelector, - PurgedCrossValidator, - TimeSeriesValidator, - WalkForwardValidator, + CombinatorialPurgedCV, + ModelSelector, + PurgedCrossValidator, + TimeSeriesValidator, + WalkForwardValidator, ) # Aliases for backward compatibility and institutional standards diff --git a/meridianalgo/ml/models/__init__.py b/meridianalgo/ml/models/__init__.py index e137c96..bb7d7d9 100644 --- a/meridianalgo/ml/models/__init__.py +++ b/meridianalgo/ml/models/__init__.py @@ -3,16 +3,16 @@ """ from .core import ( - BaseFinancialModel, - EnsembleModel, - GRUModel, - LSTMModel, - ModelConfig, - ModelFactory, - ModelResult, - ModelTrainer, - TraditionalMLModel, - TransformerModel, + BaseFinancialModel, + EnsembleModel, + GRUModel, + LSTMModel, + ModelConfig, + ModelFactory, + ModelResult, + ModelTrainer, + TraditionalMLModel, + TransformerModel, ) __all__ = [ diff --git a/meridianalgo/portfolio/__init__.py b/meridianalgo/portfolio/__init__.py index 676db8d..6d79701 100644 --- a/meridianalgo/portfolio/__init__.py +++ b/meridianalgo/portfolio/__init__.py @@ -41,7 +41,7 @@ # Risk Management try: - from .risk_management import ( + from .risk_management import ( # noqa: F401 RiskManager, RiskMetrics, # noqa: F401 StressTester, @@ -55,7 +55,7 @@ # Performance Analysis try: - from .performance import ( + from .performance import ( # noqa: F401 AttributionAnalyzer, # noqa: F401 FactorAnalyzer, PerformanceAnalyzer, @@ -68,7 +68,7 @@ # Transaction Costs try: - from .transaction_costs import ( + from .transaction_costs import ( # noqa: F401 LinearImpactModel, # noqa: F401 SquareRootImpactModel, TaxLossHarvester, @@ -89,7 +89,7 @@ # Rebalancing try: - from .rebalancing import ( + from .rebalancing import ( # noqa: F401 CalendarRebalancer, # noqa: F401 OptimalRebalancer, Rebalancer, diff --git a/meridianalgo/quant/__init__.py b/meridianalgo/quant/__init__.py index 8826b74..5bee59c 100644 --- a/meridianalgo/quant/__init__.py +++ b/meridianalgo/quant/__init__.py @@ -6,39 +6,39 @@ """ from .advanced_signals import ( - calculate_z_score, - fractional_difference, - get_half_life, - hurst_exponent, - information_coefficient, + calculate_z_score, + fractional_difference, + get_half_life, + hurst_exponent, + information_coefficient, ) from .high_frequency import ( - HFTSignalGenerator, - LatencyArbitrage, - LiquidityProvision, - MarketMaking, - MicropriceEstimator, + HFTSignalGenerator, + LatencyArbitrage, + LiquidityProvision, + MarketMaking, + MicropriceEstimator, ) from .market_microstructure import ( - MarketImpactModel, - OrderFlowImbalance, - RealizedVolatility, - TickDataAnalyzer, - VolumeWeightedSpread, + MarketImpactModel, + OrderFlowImbalance, + RealizedVolatility, + TickDataAnalyzer, + VolumeWeightedSpread, ) from .regime_detection import ( - HiddenMarkovModel, - MarketStateClassifier, - RegimeSwitchingModel, - StructuralBreakDetection, - VolatilityRegimeDetector, + HiddenMarkovModel, + MarketStateClassifier, + RegimeSwitchingModel, + StructuralBreakDetection, + VolatilityRegimeDetector, ) from .statistical_arbitrage import ( - CointegrationAnalyzer, - MeanReversionTester, - OrnsteinUhlenbeck, - PairsTrading, - SpreadAnalyzer, + CointegrationAnalyzer, + MeanReversionTester, + OrnsteinUhlenbeck, + PairsTrading, + SpreadAnalyzer, ) __all__ = [ diff --git a/meridianalgo/strategies/__init__.py b/meridianalgo/strategies/__init__.py index 25d7591..05a14a4 100644 --- a/meridianalgo/strategies/__init__.py +++ b/meridianalgo/strategies/__init__.py @@ -5,13 +5,13 @@ """ from .momentum import ( - BaseStrategy, - BollingerBandsStrategy, - MACDCrossover, - MomentumStrategy, - PairsTrading, - RSIMeanReversion, - create_strategy, + BaseStrategy, + BollingerBandsStrategy, + MACDCrossover, + MomentumStrategy, + PairsTrading, + RSIMeanReversion, + create_strategy, ) __all__ = [ diff --git a/meridianalgo/strategies/momentum.py b/meridianalgo/strategies/momentum.py index c9fa157..12963ed 100644 --- a/meridianalgo/strategies/momentum.py +++ b/meridianalgo/strategies/momentum.py @@ -174,9 +174,9 @@ def generate_signals(self, data: pd.DataFrame) -> pd.DataFrame: # Generate signals based on RSI levels signals.loc[rsi < self.oversold_threshold, asset] = 1 # Buy when oversold - signals.loc[rsi > self.overbought_threshold, asset] = ( - -1 - ) # Sell when overbought + signals.loc[ + rsi > self.overbought_threshold, asset + ] = -1 # Sell when overbought signals.loc[ (rsi >= self.exit_threshold) & (rsi <= 100 - self.exit_threshold), asset ] = 0 # Exit at neutral diff --git a/tests/README.md b/tests/README.md new file mode 100644 index 0000000..4059af7 --- /dev/null +++ b/tests/README.md @@ -0,0 +1,73 @@ +# MeridianAlgo Test Suite + +This directory contains comprehensive tests for the MeridianAlgo package. + +## Test Files + +### test_core.py +Tests for core functionality: +- Statistics calculations +- Performance metrics +- Risk measures +- Time series analysis + +### test_machine_learning.py +Tests for machine learning features: +- Feature engineering +- LSTM predictors +- Model validation +- Data preprocessing + +### test_comprehensive_suite.py +Comprehensive integration tests covering: +- Portfolio optimization +- Risk analytics +- Backtesting +- Data handling +- All major modules + +## Running Tests + +Run all tests: +```bash +pytest tests/ +``` + +Run specific test file: +```bash +pytest tests/test_core.py +pytest tests/test_machine_learning.py +pytest tests/test_comprehensive_suite.py +``` + +Run with verbose output: +```bash +pytest tests/ -v +``` + +Run with coverage: +```bash +pytest tests/ --cov=meridianalgo --cov-report=html +``` + +## Test Configuration + +Test configuration is in `pytest.ini` at the project root. + +## Writing Tests + +When adding new features, please include tests that: +- Cover normal use cases +- Test edge cases +- Validate error handling +- Check numerical accuracy +- Ensure backward compatibility + +## Continuous Integration + +Tests run automatically on: +- Every push to main/develop branches +- All pull requests +- Before PyPI publishing + +See `.github/workflows/ci.yml` for CI configuration. diff --git a/tests/integration/test_portfolio_integration.py b/tests/integration/test_portfolio_integration.py index 38a4a7c..a4f93a4 100644 --- a/tests/integration/test_portfolio_integration.py +++ b/tests/integration/test_portfolio_integration.py @@ -65,9 +65,9 @@ def test_performance_analytics(): # Basic checks assert metrics.total_return != 0, "Total return should not be zero" assert metrics.volatility > 0, "Volatility should be positive" - assert metrics.trading_days == len( - returns - ), "Trading days should match data length" + assert metrics.trading_days == len(returns), ( + "Trading days should match data length" + ) print(" Performance analytics working correctly") print(f" Total Return: {metrics.total_return:.2%}") @@ -102,14 +102,14 @@ def test_portfolio_optimization(): ) weights = result.weights - assert len(weights) == len( - returns_data.columns - ), "Weights should match number of assets" + assert len(weights) == len(returns_data.columns), ( + "Weights should match number of assets" + ) assert result.success, f"Optimization failed: {result.message}" assert abs(weights.sum() - 1.0) < 1e-6, "Weights should sum to 1" - assert all( - w >= -1e-10 for w in weights.values - ), "Weights should be non-negative" + assert all(w >= -1e-10 for w in weights.values), ( + "Weights should be non-negative" + ) print(" Portfolio optimization working correctly") print(f" Optimized weights: {dict(weights)}")