From cd9b6f7969b104f16d5fb8808646e2b6988ff833 Mon Sep 17 00:00:00 2001 From: "Bobby (aider)" Date: Mon, 17 Feb 2025 15:45:24 -0800 Subject: [PATCH] feat: Add Monte Carlo stop loss calculation to trading system --- src/pages/analysis/monte_carlo_page.py | 25 ++++++++++++ src/pages/trading/trading_system_page.py | 50 +++++++++++++++++++++--- 2 files changed, 70 insertions(+), 5 deletions(-) diff --git a/src/pages/analysis/monte_carlo_page.py b/src/pages/analysis/monte_carlo_page.py index 8cff8b5..d0fa34d 100644 --- a/src/pages/analysis/monte_carlo_page.py +++ b/src/pages/analysis/monte_carlo_page.py @@ -47,6 +47,31 @@ class MonteCarloSimulator: return price_paths + def calculate_stop_loss(self, risk_percentage: float) -> float: + """ + Calculate stop loss price based on Monte Carlo simulation and desired risk percentage + + Args: + risk_percentage (float): Maximum risk percentage willing to take + + Returns: + float: Recommended stop loss price + """ + # Run a quick simulation + paths = self.run_simulation() + + # Get the first day's simulated prices + first_day_prices = paths[1] # Using day 1 instead of day 0 to see immediate movement + + # Calculate the price that represents the risk percentage loss + potential_losses = (first_day_prices - self.last_price) / self.last_price * 100 + + # Find the price level that corresponds to our risk percentage + stop_loss_percentile = np.percentile(potential_losses, risk_percentage) + stop_loss_price = self.last_price * (1 + stop_loss_percentile / 100) + + return stop_loss_price + def calculate_metrics(self, paths: np.ndarray) -> Dict: """Calculate key metrics from simulation results""" final_prices = paths[-1] diff --git a/src/pages/trading/trading_system_page.py b/src/pages/trading/trading_system_page.py index af79d0d..83832c8 100644 --- a/src/pages/trading/trading_system_page.py +++ b/src/pages/trading/trading_system_page.py @@ -2,6 +2,9 @@ import streamlit as st from trading.journal import get_latest_portfolio_value, get_open_trades_summary from trading.position_calculator import PositionCalculator from utils.data_utils import get_current_prices +from pages.analysis.monte_carlo_page import MonteCarloSimulator +from datetime import datetime, timedelta +from utils.common_utils import get_stock_data def trading_system_page(): st.header("Trading System") @@ -54,18 +57,44 @@ def trading_system_page(): max_value=100.0, value=1.0, step=0.1) - stop_loss_percentage = st.number_input("Stop Loss Percentage (%)", - min_value=0.1, - max_value=100.0, - value=7.0, - step=0.1) + use_monte_carlo = st.checkbox("Use Monte Carlo for Stop Loss", value=True) with col2: + ticker = st.text_input("Ticker Symbol", value="").upper() entry_price = st.number_input("Entry Price ($)", min_value=0.01, step=0.01) target_price = st.number_input("Target Price ($)", min_value=0.01, step=0.01) if st.button("Calculate Position"): try: + if not ticker: + st.error("Please enter a ticker symbol") + return + + # Get historical data for Monte Carlo simulation + if use_monte_carlo: + with st.spinner("Calculating optimal stop loss..."): + df = get_stock_data( + ticker, + datetime.now() - timedelta(days=30), # Last 30 days of data + datetime.now(), + '1m' # Minute data for more accurate simulation + ) + + if df.empty: + st.error("No data available for the selected ticker") + return + + # Initialize Monte Carlo simulator + simulator = MonteCarloSimulator(df, num_simulations=1000, time_horizon=5) + + # Calculate stop loss price + stop_loss_price = simulator.calculate_stop_loss(risk_percentage) + + # Calculate stop loss percentage + stop_loss_percentage = abs((stop_loss_price - entry_price) / entry_price * 100) + else: + stop_loss_percentage = 7.0 # Default value if not using Monte Carlo + calculator = PositionCalculator( account_size=account_size, risk_percentage=risk_percentage, @@ -118,5 +147,16 @@ def trading_system_page(): f"- {portfolio_usage:.1f}% of total portfolio" ) + # Add Monte Carlo metrics if used + if use_monte_carlo: + st.subheader("Monte Carlo Analysis") + col1, col2 = st.columns(2) + with col1: + st.metric("Calculated Stop Loss Price", f"${stop_loss_price:.2f}") + st.metric("Stop Loss Percentage", f"{stop_loss_percentage:.2f}%") + with col2: + st.metric("Based on Simulations", "1,000") + st.metric("Simulation Timeframe", "5 days") + except Exception as e: st.error(f"Error calculating position: {str(e)}")