TradingAgents/examples/portfolio_example.py

454 lines
16 KiB
Python

"""
Comprehensive Portfolio Management System Example
This example demonstrates all major features of the TradingAgents
portfolio management system.
"""
from decimal import Decimal
from datetime import datetime, timedelta
import logging
# Configure logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
from tradingagents.portfolio import (
Portfolio,
MarketOrder,
LimitOrder,
StopLossOrder,
TakeProfitOrder,
RiskLimits,
TradingAgentsPortfolioIntegration,
)
def example_basic_trading():
"""Example 1: Basic Trading Operations"""
print("\n" + "="*80)
print("Example 1: Basic Trading Operations")
print("="*80)
# Create a portfolio with $100,000 initial capital
portfolio = Portfolio(
initial_capital=Decimal('100000.00'),
commission_rate=Decimal('0.001') # 0.1% commission
)
print(f"Initial Portfolio:")
print(f" Cash: ${portfolio.cash:,.2f}")
print(f" Total Value: ${portfolio.total_value():,.2f}")
# Execute a buy order
print("\n--- Buying 100 shares of AAPL at $150.00 ---")
buy_order = MarketOrder('AAPL', Decimal('100'))
portfolio.execute_order(buy_order, current_price=Decimal('150.00'))
print(f"After Purchase:")
print(f" Cash: ${portfolio.cash:,.2f}")
print(f" Positions: {list(portfolio.positions.keys())}")
# Check position details
aapl_position = portfolio.get_position('AAPL')
print(f"\nAAPL Position:")
print(f" Quantity: {aapl_position.quantity}")
print(f" Cost Basis: ${aapl_position.cost_basis}")
print(f" Total Cost: ${aapl_position.total_cost():,.2f}")
# Price goes up
print("\n--- Price moves to $160.00 ---")
current_prices = {'AAPL': Decimal('160.00')}
unrealized_pnl = portfolio.unrealized_pnl(current_prices)
total_value = portfolio.total_value(current_prices)
print(f"Unrealized P&L: ${unrealized_pnl:,.2f}")
print(f"Total Value: ${total_value:,.2f}")
print(f"Return: {((total_value - portfolio.initial_capital) / portfolio.initial_capital):.2%}")
# Sell position
print("\n--- Selling 100 shares of AAPL at $160.00 ---")
sell_order = MarketOrder('AAPL', Decimal('-100'))
portfolio.execute_order(sell_order, current_price=Decimal('160.00'))
realized_pnl = portfolio.realized_pnl()
print(f"Realized P&L: ${realized_pnl:,.2f}")
print(f"Final Cash: ${portfolio.cash:,.2f}")
print(f"Trade History: {len(portfolio.trade_history)} completed trades")
return portfolio
def example_order_types():
"""Example 2: Different Order Types"""
print("\n" + "="*80)
print("Example 2: Different Order Types")
print("="*80)
portfolio = Portfolio(
initial_capital=Decimal('100000.00'),
commission_rate=Decimal('0.001')
)
# Market Order - executes immediately
print("\n--- Market Order ---")
market_order = MarketOrder('AAPL', Decimal('100'))
portfolio.execute_order(market_order, Decimal('150.00'))
print(f"Executed market order at $150.00")
# Limit Order - only executes at specified price or better
print("\n--- Limit Order ---")
limit_order = LimitOrder('GOOGL', Decimal('50'), limit_price=Decimal('2000.00'))
# Try at higher price - won't execute
print(f"Current price $2050.00 - can execute: {limit_order.can_execute(Decimal('2050.00'))}")
# Try at limit price - will execute
print(f"Current price $2000.00 - can execute: {limit_order.can_execute(Decimal('2000.00'))}")
portfolio.execute_order(limit_order, Decimal('2000.00'))
# Add stop-loss to AAPL position
print("\n--- Adding Stop-Loss Protection ---")
aapl_position = portfolio.get_position('AAPL')
aapl_position.stop_loss = Decimal('145.00') # 3.3% stop-loss
aapl_position.take_profit = Decimal('165.00') # 10% take-profit
print(f"AAPL Position protected with:")
print(f" Stop-Loss: ${aapl_position.stop_loss}")
print(f" Take-Profit: ${aapl_position.take_profit}")
# Check for triggers
print("\n--- Checking Triggers at $144.00 ---")
prices = {'AAPL': Decimal('144.00'), 'GOOGL': Decimal('2000.00')}
stop_loss_orders = portfolio.check_stop_loss_triggers(prices)
if stop_loss_orders:
print(f"Stop-loss triggered for {stop_loss_orders[0].ticker}!")
# In production, you would execute these orders
# portfolio.execute_order(stop_loss_orders[0], prices['AAPL'])
return portfolio
def example_risk_management():
"""Example 3: Risk Management"""
print("\n" + "="*80)
print("Example 3: Risk Management")
print("="*80)
# Create portfolio with strict risk limits
risk_limits = RiskLimits(
max_position_size=Decimal('0.15'), # 15% max per position
max_sector_concentration=Decimal('0.25'), # 25% max per sector
max_drawdown=Decimal('0.20'), # 20% max drawdown
min_cash_reserve=Decimal('0.10') # 10% minimum cash
)
portfolio = Portfolio(
initial_capital=Decimal('100000.00'),
commission_rate=Decimal('0.001'),
risk_limits=risk_limits
)
print("Risk Limits:")
print(f" Max Position Size: {portfolio.risk_manager.limits.max_position_size:.1%}")
print(f" Max Sector Concentration: {portfolio.risk_manager.limits.max_sector_concentration:.1%}")
print(f" Max Drawdown: {portfolio.risk_manager.limits.max_drawdown:.1%}")
print(f" Min Cash Reserve: {portfolio.risk_manager.limits.min_cash_reserve:.1%}")
# Calculate position size using risk management
print("\n--- Position Sizing ---")
entry_price = Decimal('150.00')
stop_loss_price = Decimal('145.00')
risk_per_trade = Decimal('0.02') # 2% risk per trade
position_size = portfolio.risk_manager.calculate_position_size(
portfolio.total_value(),
risk_per_trade,
entry_price,
stop_loss_price
)
print(f"Entry Price: ${entry_price}")
print(f"Stop-Loss Price: ${stop_loss_price}")
print(f"Risk Per Trade: {risk_per_trade:.1%}")
print(f"Calculated Position Size: {position_size} shares")
# Execute with calculated size
order = MarketOrder('AAPL', position_size)
portfolio.execute_order(order, entry_price)
position_value = position_size * entry_price
portfolio_value = portfolio.total_value()
position_pct = position_value / portfolio_value
print(f"\nPosition Value: ${position_value:,.2f}")
print(f"Portfolio Value: ${portfolio_value:,.2f}")
print(f"Position Size: {position_pct:.2%} of portfolio")
# Try to violate position size limit
print("\n--- Testing Position Size Limit ---")
try:
# This would create a position > 15% of portfolio
oversized_order = MarketOrder('GOOGL', Decimal('100'))
portfolio.execute_order(oversized_order, Decimal('2000.00'))
except Exception as e:
print(f"Order rejected: {e}")
return portfolio
def example_performance_analytics():
"""Example 4: Performance Analytics"""
print("\n" + "="*80)
print("Example 4: Performance Analytics")
print("="*80)
portfolio = Portfolio(
initial_capital=Decimal('100000.00'),
commission_rate=Decimal('0.001')
)
# Simulate a series of trades
trades = [
('AAPL', Decimal('100'), Decimal('150.00'), Decimal('160.00')),
('GOOGL', Decimal('50'), Decimal('2000.00'), Decimal('2100.00')),
('MSFT', Decimal('200'), Decimal('300.00'), Decimal('295.00')), # Loss
('TSLA', Decimal('75'), Decimal('200.00'), Decimal('220.00')),
]
print("Simulating trades...")
for ticker, quantity, buy_price, sell_price in trades:
# Buy
buy_order = MarketOrder(ticker, quantity)
portfolio.execute_order(buy_order, buy_price)
# Sell
sell_order = MarketOrder(ticker, -quantity)
portfolio.execute_order(sell_order, sell_price)
trade = portfolio.trade_history[-1]
print(f" {ticker}: {trade.pnl:+,.2f} ({trade.pnl_percent:+.2%})")
# Get performance metrics
print("\n--- Performance Metrics ---")
metrics = portfolio.get_performance_metrics()
print(f"Total Return: {metrics.total_return:+.2%}")
print(f"Annualized Return: {metrics.annualized_return:+.2%}")
print(f"Total Trades: {metrics.total_trades}")
print(f"Winning Trades: {metrics.winning_trades}")
print(f"Losing Trades: {metrics.losing_trades}")
print(f"Win Rate: {metrics.win_rate:.2%}")
print(f"Profit Factor: {metrics.profit_factor:.2f}")
print(f"Average Win: ${metrics.average_win:,.2f}")
print(f"Average Loss: ${metrics.average_loss:,.2f}")
print(f"Largest Win: ${metrics.largest_win:,.2f}")
print(f"Largest Loss: ${metrics.largest_loss:,.2f}")
print(f"Sharpe Ratio: {metrics.sharpe_ratio:.2f}")
print(f"Sortino Ratio: {metrics.sortino_ratio:.2f}")
print(f"Max Drawdown: {metrics.max_drawdown:.2%}")
print(f"Volatility: {metrics.volatility:.2%}")
# Show equity curve
print("\n--- Equity Curve (last 5 points) ---")
equity_curve = portfolio.get_equity_curve()
for date, value in equity_curve[-5:]:
print(f" {date.strftime('%Y-%m-%d %H:%M:%S')}: ${value:,.2f}")
return portfolio
def example_persistence():
"""Example 5: Saving and Loading Portfolio"""
print("\n" + "="*80)
print("Example 5: Persistence")
print("="*80)
# Create and trade
portfolio = Portfolio(
initial_capital=Decimal('100000.00'),
commission_rate=Decimal('0.001')
)
portfolio.execute_order(MarketOrder('AAPL', Decimal('100')), Decimal('150.00'))
portfolio.execute_order(MarketOrder('GOOGL', Decimal('50')), Decimal('2000.00'))
print(f"Original Portfolio:")
print(f" Cash: ${portfolio.cash:,.2f}")
print(f" Positions: {list(portfolio.positions.keys())}")
# Save to JSON
filename = 'example_portfolio.json'
portfolio.save(filename)
print(f"\nSaved portfolio to {filename}")
# Load from JSON
loaded_portfolio = Portfolio.load(filename)
print(f"\nLoaded Portfolio:")
print(f" Cash: ${loaded_portfolio.cash:,.2f}")
print(f" Positions: {list(loaded_portfolio.positions.keys())}")
# Verify they match
assert loaded_portfolio.cash == portfolio.cash
assert len(loaded_portfolio.positions) == len(portfolio.positions)
print("\n✓ Portfolio state successfully preserved")
# Save to SQLite
from tradingagents.portfolio import PortfolioPersistence
persistence = PortfolioPersistence('./portfolio_data')
portfolio_data = portfolio.to_dict()
persistence.save_to_sqlite(portfolio_data, 'example_portfolio.db')
print(f"\nSaved to SQLite database: example_portfolio.db")
# Export trades to CSV
if portfolio.trade_history:
persistence.export_to_csv(
[trade.to_dict() for trade in portfolio.trade_history],
'example_trades.csv'
)
print("Exported trade history to CSV: example_trades.csv")
return portfolio
def example_tradingagents_integration():
"""Example 6: TradingAgents Integration"""
print("\n" + "="*80)
print("Example 6: TradingAgents Integration")
print("="*80)
portfolio = Portfolio(
initial_capital=Decimal('100000.00'),
commission_rate=Decimal('0.001')
)
# Create integration layer
integration = TradingAgentsPortfolioIntegration(portfolio)
# Simulate agent decisions
current_prices = {
'AAPL': Decimal('150.00'),
'GOOGL': Decimal('2000.00'),
'MSFT': Decimal('300.00')
}
# Decision 1: Buy AAPL
print("\n--- Agent Decision 1: Buy AAPL ---")
decision1 = {
'action': 'buy',
'ticker': 'AAPL',
'quantity': 100,
'order_type': 'market',
'reasoning': 'Strong bullish sentiment from technical and fundamental analysis'
}
result = integration.execute_agent_decision(decision1, current_prices)
print(f"Status: {result['status']}")
print(f"Action: {result['action']} {result['ticker']}")
print(f"Quantity: {result['quantity']}")
print(f"Price: ${result['price']}")
# Decision 2: Buy GOOGL with limit order
print("\n--- Agent Decision 2: Buy GOOGL (Limit Order) ---")
decision2 = {
'action': 'buy',
'ticker': 'GOOGL',
'quantity': 50,
'order_type': 'limit',
'limit_price': Decimal('2000.00'),
'reasoning': 'Value opportunity identified'
}
result = integration.execute_agent_decision(decision2, current_prices)
print(f"Status: {result['status']}")
# Get portfolio context for agents
print("\n--- Portfolio Context for Agents ---")
context = integration.get_portfolio_context(current_prices)
print(f"Total Value: ${context['total_value']}")
print(f"Cash: ${context['cash']} ({context['cash_pct']})")
print(f"Invested: ${context['invested_value']}")
print(f"Unrealized P&L: ${context['unrealized_pnl']}")
print(f"Total Return: {context['total_return']}")
print(f"Number of Positions: {context['num_positions']}")
print("\nPositions:")
for pos in context['positions']:
print(f" {pos['ticker']}: {pos['quantity']} shares @ ${pos['cost_basis']}")
if 'unrealized_pnl' in pos:
print(f" P&L: ${pos['unrealized_pnl']} ({pos['unrealized_pnl_pct']})")
# Rebalance portfolio
print("\n--- Rebalancing Portfolio ---")
target_weights = {
'AAPL': Decimal('0.40'),
'GOOGL': Decimal('0.30'),
'MSFT': Decimal('0.30')
}
print("Target Weights:")
for ticker, weight in target_weights.items():
print(f" {ticker}: {weight:.1%}")
rebalance_results = integration.rebalance_portfolio(target_weights, current_prices)
print(f"\nRebalancing completed: {len(rebalance_results)} trades executed")
for result in rebalance_results:
if result['status'] == 'success':
print(f" {result['action']} {result['ticker']}: {result['quantity']} shares")
# Get execution history
print("\n--- Execution History ---")
history = integration.get_execution_history(limit=5)
print(f"Last {len(history)} executions recorded")
return portfolio, integration
def main():
"""Run all examples"""
print("\n" + "="*80)
print("TradingAgents Portfolio Management System - Comprehensive Examples")
print("="*80)
try:
# Run each example
portfolio1 = example_basic_trading()
portfolio2 = example_order_types()
portfolio3 = example_risk_management()
portfolio4 = example_performance_analytics()
portfolio5 = example_persistence()
portfolio6, integration = example_tradingagents_integration()
print("\n" + "="*80)
print("All Examples Completed Successfully!")
print("="*80)
print("\nKey Takeaways:")
print("1. Easy to use API for portfolio management")
print("2. Multiple order types with proper execution logic")
print("3. Comprehensive risk management and limits")
print("4. Detailed performance analytics and metrics")
print("5. Flexible persistence options (JSON, SQLite, CSV)")
print("6. Seamless integration with TradingAgents framework")
print("\nNext Steps:")
print("- Review the source code in tradingagents/portfolio/")
print("- Check out the test suite in tests/portfolio/")
print("- Read the README at tradingagents/portfolio/README.md")
print("- Integrate with your TradingAgents strategies")
except Exception as e:
print(f"\n❌ Error running examples: {e}")
import traceback
traceback.print_exc()
if __name__ == '__main__':
main()