Spaces:
Runtime error
Runtime error
File size: 7,216 Bytes
0d45d74 5a4149f 0d45d74 c77be48 0d45d74 c77be48 382ea28 0d45d74 382ea28 0d45d74 382ea28 0d45d74 5a4149f 0d45d74 5a4149f 0d45d74 c1ca84f 5a4149f 0d45d74 928b15d 86fea3a 24b5931 86fea3a e2af605 5a4149f e2af605 382ea28 e2af605 5a4149f 382ea28 5a4149f 382ea28 5a4149f 928b15d 5a4149f 928b15d 5a4149f 928b15d 0d45d74 382ea28 0d45d74 382ea28 67bb0d5 5a4149f | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | import yfinance as yf
import pandas as pd
import numpy as np
import plotly.graph_objects as go
from plotly.subplots import make_subplots
import streamlit as st
from datetime import datetime, timedelta
# Helper function to fetch stock data
def fetch_stock_data(ticker: str, start_date: str, end_date: str) -> pd.DataFrame:
"""Fetch stock data from Yahoo Finance."""
data = yf.download(ticker, start=start_date, end=end_date, auto_adjust=False)
if isinstance(data.columns, pd.MultiIndex):
data.columns = data.columns.get_level_values(0)
return data
# Function to estimate probability and plot
def estimate_probability(data, n_days, initial_price, up_target, down_target):
# Calculate the thresholds for price change
up_threshold = round(abs((up_target - initial_price) / initial_price), 3)
down_threshold = round(abs((down_target - initial_price) / initial_price), 3)
# Calculate the n-day percentage change
data[f'{n_days}d_pct_change'] = data['Adj Close'].pct_change(n_days)
# Calculate the frequency of the threshold price change
total_periods = len(data.dropna(subset=[f'{n_days}d_pct_change']))
down_periods = len(data[data[f'{n_days}d_pct_change'] <= -down_threshold])
up_periods = len(data[data[f'{n_days}d_pct_change'] >= up_threshold])
down_frequency = down_periods / total_periods if total_periods > 0 else 0
up_frequency = up_periods / total_periods if total_periods > 0 else 0
# Plotting
fig = make_subplots(rows=2, cols=1, shared_xaxes=True, vertical_spacing=0.1,
subplot_titles=(f'Distribution of {n_days}-day percentage changes', f'Price for {ticker}'),
specs=[[{"secondary_y": False}], [{"secondary_y": False}]])
fig.add_trace(go.Histogram(x=data[f'{n_days}d_pct_change'], nbinsx=100, name='Percentage Change'), row=1, col=1)
fig.add_vline(x=-down_threshold, line=dict(color='red', dash='dash'), annotation_text=f"{down_threshold * 100:.2f}% decrease frequency: {down_frequency * 100:.2f}%", annotation_position="bottom left", row=1, col=1)
fig.add_vline(x=up_threshold, line=dict(color='blue', dash='dash'), annotation_text=f"{up_threshold * 100:.2f}% increase frequency: {up_frequency * 100:.2f}%", annotation_position="top right", row=1, col=1)
fig.add_trace(go.Scatter(x=data.index, y=data['Adj Close'], mode='lines', name='Adjusted Close Price'), row=2, col=1)
up_instances = data[data[f'{n_days}d_pct_change'] >= up_threshold]
down_instances = data[data[f'{n_days}d_pct_change'] <= -down_threshold]
fig.add_trace(go.Scatter(x=up_instances.index, y=up_instances['Adj Close'], mode='markers', marker=dict(color='blue', symbol='triangle-up', size=10), name=f"{up_threshold * 100:.2f}% increase"), row=2, col=1)
fig.add_trace(go.Scatter(x=down_instances.index, y=down_instances['Adj Close'], mode='markers', marker=dict(color='red', symbol='triangle-down', size=10), name=f"{down_threshold * 100:.2f}% decrease"), row=2, col=1)
fig.update_layout(title_text=f"Probability Estimation and Price for {ticker}", xaxis_title='Date', yaxis_title='Adjusted Close Price')
return fig, up_frequency, down_frequency
# Streamlit app
st.set_page_config(page_title="Price Movements Probability Analysis", layout="wide")
st.title('Price Probability Analysis')
# Sidebar for method selection
st.sidebar.title("Input Parameters")
with st.sidebar.expander("How to Use", expanded=False):
st.markdown("""
### How to Use
1. **Enter Ticker**: Input the stock symbol or crypto pair you want to analyze.
2. **Select Date Range**: Choose the start and end dates for the historical data.
3. **Set Parameters**:
- **Number of Days**: Define the period for percentage change calculation.
- **Initial Price**: The starting price for your analysis.
- **Up Target**: The target price for an upward move.
- **Down Target**: The target price for a downward move.
4. **Run Analysis**: Click the 'Run Analysis' button to generate the results.
""")
with st.sidebar.expander("Ticker and Date Settings", expanded=True):
ticker = st.text_input('Enter Ticker (Stock or Crypto Pair)', 'SAP.DE', help="Enter a stock ticker (e.g., AAPL) or a crypto pair (e.g., BTC-USD)")
start_date = st.date_input('Start Date', pd.to_datetime('2020-01-01'), help="Select the start date for the data")
end_date = st.date_input('End Date', datetime.now().date() + timedelta(days=1), help="Select the end date for the data")
with st.sidebar.expander("Parameter Settings", expanded=True):
# Fetch data to set default values only if Run Analysis is clicked
n_days = st.slider('Number of Days', min_value=1, max_value=100, value=30, step=1, help="Number of days for percentage change calculation")
initial_price = st.number_input('Initial Price', value=0.0, help="Starting price for analysis (defaults to latest price if 0)")
up_target = st.number_input('Up Target', value=0.0, help="Target price for upward move (defaults to 10% above initial if 0)")
down_target = st.number_input('Down Target', value=0.0, help="Target price for downward move (defaults to 10% below initial if 0)")
# Main content area
st.markdown("""
This app estimates the probability of a stock or cryptocurrency reaching certain price targets within a specified number of days based on historical data.
- **Distribution of Percentage Changes**: The histogram shows the distribution of percentage changes over the selected number of days.
- **Price Targets**: The vertical lines indicate the price targets for upward and downward moves. The frequencies of reaching these targets are annotated.
- **Price Plot**: The line chart shows the historical adjusted close prices with markers indicating instances where the price targets were met.
""")
# Run button
run_button = st.sidebar.button('Run Analysis')
# Fetch data and display results
if run_button:
data = fetch_stock_data(ticker, start_date, end_date)
if data.empty:
st.error(f"No data returned for {ticker} from {start_date} to {end_date}")
else:
st.session_state.data = data
data = st.session_state.data
if initial_price <= 0:
initial_price = data['Adj Close'].iloc[-1]
if up_target <= 0:
up_target = initial_price * 1.1
if down_target <= 0:
down_target = initial_price * 0.9
fig, up_frequency, down_frequency = estimate_probability(data, n_days, initial_price, up_target, down_target)
st.plotly_chart(fig)
st.markdown(f"""
### Results
**Probability of Reaching Targets:**
- Probability of reaching the up target ({up_target:.2f}) in {n_days} days: **{up_frequency * 100:.2f}%**
- Probability of reaching the down target ({down_target:.2f}) in {n_days} days: **{down_frequency * 100:.2f}%**
This analysis helps in understanding the historical likelihood of the price reaching certain targets within a specified number of days.
""")
hide_streamlit_style = """
<style>
#MainMenu {visibility: hidden;}
footer {visibility: hidden;}
</style>
"""
st.markdown(hide_streamlit_style, unsafe_allow_html=True) |