Spaces:
Running
Running
| import pandas as pd | |
| import plotly.graph_objects as go | |
| import pygwalker as pyg | |
| import streamlit as st | |
| import streamlit.components.v1 as components | |
| import yfinance as yf | |
| from plotly.subplots import make_subplots | |
| from scipy.stats import norm | |
| from utils.helper import * | |
| # Streamlit app layout | |
| st.set_page_config(layout="wide") | |
| st.title("📊 Technical Trading Strategy Simulation 💹") | |
| # Sidebar inputs | |
| ticker = st.sidebar.text_input("Enter Stock Ticker", "AAPL").upper() | |
| start_date = st.sidebar.date_input("Start Date", pd.to_datetime("2020-01-01")) | |
| end_date = st.sidebar.date_input("End Date", pd.to_datetime("today")) | |
| # Add sidebar slider for selecting two integers | |
| st.sidebar.success("Please select your own parameters.") | |
| # Expander | |
| with st.expander("Expand to fine tune the windows:"): | |
| short_window = st.sidebar.slider( | |
| "Select short window size", min_value=2, max_value=200, value=20 | |
| ) | |
| long_window = st.sidebar.slider( | |
| "Select long window size", min_value=2, max_value=250, value=95 | |
| ) | |
| signal_window = st.sidebar.slider( | |
| "Select signal window size", min_value=2, max_value=250, value=9 | |
| ) | |
| values = st.sidebar.slider( | |
| "Select a range of values", min_value=-100, max_value=100, value=(-10, 10), step=1 | |
| ) | |
| option = st.sidebar.selectbox( | |
| "How would you like rescale data?", ("Original", "Normalization", "Percentile") | |
| ) | |
| st.sidebar.markdown( | |
| f""" | |
| ## URL of the app: [here](https://huggingface.co/spaces/eagle0504/technical-trader). | |
| """ | |
| ) | |
| # Add submit button in the sidebar | |
| submit_button = st.sidebar.button("Submit") | |
| # Update to execute changes only when the submit button is clicked | |
| if submit_button: | |
| with st.spinner("Wait for it..."): | |
| # Message | |
| if option == "Original": | |
| st.success( | |
| "We use the stock price (within the range selected) to create the MACD and Signal Line (which numerically vary based on price data)." | |
| ) | |
| elif option == "Normalization": | |
| st.success( | |
| "We use the stock price (within the range selected) to create the MACD and Signal Line (which numerically vary based on price data). Next, we normalize the MACD/Signal Line so that fall in a consistent range, i.e. approximately from -2 to 2." | |
| ) | |
| else: | |
| st.success( | |
| "We use the stock price (within the range selected) to create the MACD and Signal Line (which numerically vary based on price data). Next, we normalize the MACD/Signal Line so that fall in a consistent range, i.e. approximately from -2 to 2. Last, we use the normalized data to create probabilities from -100% to +100%. The probability means statistically what is believed to reverse the current direction." | |
| ) | |
| # Download stock data | |
| data = yf.download(ticker, start=start_date, end=end_date) | |
| if not data.empty: | |
| if option == "Normalization": | |
| data = calculate_normalized_macd( | |
| data, short_window, long_window, signal_window | |
| ) | |
| some_warning_message = "normalized data" | |
| elif option == "Percentile": | |
| data = calculate_percentile_macd( | |
| data, short_window, long_window, signal_window | |
| ) | |
| some_warning_message = "percentile data (numbers in %)" | |
| else: | |
| data = calculate_macd(data, short_window, long_window, signal_window) | |
| some_warning_message = "original data" | |
| data = find_crossovers(data, values[0], values[1]) | |
| # Plotting | |
| fig = create_fig(data, ticker) | |
| st.plotly_chart(fig, use_container_width=True) | |
| st.warning(f"In the above graph, we use {some_warning_message}.") | |
| else: | |
| st.write("No data available for the given ticker.") | |
| # New section to get and display fundamentals data under an expander | |
| with st.expander("View Fundamentals Data"): | |
| a, b, c = get_fundamentals(ticker) | |
| fundamentals_data = pd.concat([a, b, c], axis=0) | |
| fundamentals_data_t = fundamentals_data.transpose() | |
| fundamentals_data_t["date"] = fundamentals_data_t.index | |
| fundamentals_data_t.reset_index(drop=True, inplace=True) | |
| if not fundamentals_data.empty: | |
| # Generate a table (crude way) | |
| # st.table(fundamentals_data) | |
| # Generate the HTML using Pygwalker (user-friendly and flexible) | |
| pyg_html = pyg.walk(fundamentals_data_t, return_html=True) | |
| # Embed the HTML into the Streamlit app | |
| components.html(pyg_html, height=1000, scrolling=True) | |
| else: | |
| st.write("No fundamentals data available for the given ticker.") | |