feat: Add Monte Carlo stop loss calculation to trading system

This commit is contained in:
Bobby (aider) 2025-02-17 15:45:24 -08:00
parent 7910da0430
commit cd9b6f7969
2 changed files with 70 additions and 5 deletions

View File

@ -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]

View File

@ -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)}")