import gradio as gr from gradio.themes import Base from gradio.themes.utils import colors, sizes, fonts from typing import Iterable import yfinance as yf import numpy as np import pandas as pd import plotly.graph_objects as go from datetime import datetime # Custom Seafoam theme definition class Seafoam(Base): def __init__( self, *, primary_hue: colors.Color | str = colors.emerald, secondary_hue: colors.Color | str = colors.blue, neutral_hue: colors.Color | str = colors.blue, spacing_size: sizes.Size | str = sizes.spacing_md, radius_size: sizes.Size | str = sizes.radius_md, text_size: sizes.Size | str = sizes.text_lg, font: fonts.Font | str | Iterable[fonts.Font | str] = ( fonts.GoogleFont("Quicksand"), "ui-sans-serif", "sans-serif", ), font_mono: fonts.Font | str | Iterable[fonts.Font | str] = ( fonts.GoogleFont("IBM Plex Mono"), "ui-monospace", "monospace", ), ): super().__init__( primary_hue=primary_hue, secondary_hue=secondary_hue, neutral_hue=neutral_hue, spacing_size=spacing_size, radius_size=radius_size, text_size=text_size, font=font, font_mono=font_mono, ) super().set( body_background_fill="linear-gradient(to bottom right, *primary_50, *primary_100, *primary_200)", body_background_fill_dark="linear-gradient(to bottom right, *primary_900, *primary_800, *primary_700)", button_primary_background_fill="linear-gradient(90deg, *primary_300, *secondary_400)", button_primary_background_fill_hover="linear-gradient(90deg, *primary_200, *secondary_300)", button_primary_text_color="white", button_primary_background_fill_dark="linear-gradient(90deg, *primary_600, *secondary_800)", slider_color="*secondary_300", slider_color_dark="*secondary_600", block_title_text_weight="600", block_border_width="3px", block_shadow="*shadow_drop_lg", button_shadow="*shadow_drop_lg", button_large_padding="32px", ) seafoam = Seafoam() def download_stock_data(ticker, start_date, end_date): stock = yf.Ticker(ticker) df = stock.history(start=start_date, end=end_date) return df def plot_interactive_logarithmic_stock_chart(ticker, start_date, end_date): try: stock = yf.Ticker(ticker) data = stock.history(start=start_date, end=end_date) if data.empty: return "No data available for the specified date range." x = (data.index - data.index[0]).days y = np.log(data['Close']) slope, intercept = np.polyfit(x, y, 1) future_days = 365 * 10 all_days = np.arange(len(x) + future_days) log_trend = np.exp(intercept + slope * all_days) inner_upper_band = log_trend * 2 inner_lower_band = log_trend / 2 outer_upper_band = log_trend * 4 outer_lower_band = log_trend / 4 extended_dates = pd.date_range(start=data.index[0], periods=len(all_days), freq='D') fig = go.Figure() fig.add_trace(go.Scatter(x=data.index, y=data['Close'], mode='lines', name='Close Price', line=dict(color='#3A9184'))) fig.add_trace(go.Scatter(x=extended_dates, y=log_trend, mode='lines', name='Log Trend', line=dict(color='#FF8C61'))) fig.add_trace(go.Scatter(x=extended_dates, y=inner_upper_band, mode='lines', name='Inner Upper Band', line=dict(color='#6FB1A7'))) fig.add_trace(go.Scatter(x=extended_dates, y=inner_lower_band, mode='lines', name='Inner Lower Band', line=dict(color='#6FB1A7'))) fig.add_trace(go.Scatter(x=extended_dates, y=outer_upper_band, mode='lines', name='Outer Upper Band', line=dict(color='#FFC2A5'))) fig.add_trace(go.Scatter(x=extended_dates, y=outer_lower_band, mode='lines', name='Outer Lower Band', line=dict(color='#FFC2A5'))) fig.update_layout( title={ 'text': 'Stock Log Charts', 'y': 0.95, 'x': 0.5, 'xanchor': 'center', 'yanchor': 'top' }, xaxis_title='Date', yaxis_title='Price (Log Scale)', yaxis_type="log", height=800, legend=dict(x=0.01, y=0.99, bgcolor='rgba(255, 255, 255, 0.8)'), hovermode='x unified', plot_bgcolor='#F5F9F8', paper_bgcolor='#F5F9F8', font=dict(family="Quicksand, sans-serif", size=12, color="#313D38") ) fig.update_xaxes( rangeslider_visible=True, rangeselector=dict( buttons=list([ dict(count=1, label="1m", step="month", stepmode="backward"), dict(count=6, label="6m", step="month", stepmode="backward"), dict(count=1, label="YTD", step="year", stepmode="todate"), dict(count=1, label="1y", step="year", stepmode="backward"), dict(step="all") ]) ) ) return fig except Exception as e: return f"An error occurred: {str(e)}" # Get the current date current_date = datetime.now().strftime("%Y-%m-%d") # Create Gradio interface with custom Seafoam theme with gr.Blocks(theme=seafoam, title="Stock Log Charts") as iface: gr.Markdown("# Stock Log Charts") gr.Markdown("Enter a stock ticker and date range to generate a logarithmic chart.") with gr.Row(): ticker = gr.Textbox(label="Stock Ticker", value="MSFT") start_date = gr.Textbox(label="Start Date", value="2015-01-01") end_date = gr.Textbox(label="End Date", value=current_date) submit_button = gr.Button("Generate Chart") with gr.Row(): log_plot = gr.Plot(label="Logarithmic Stock Chart") submit_button.click( plot_interactive_logarithmic_stock_chart, inputs=[ticker, start_date, end_date], outputs=[log_plot] ) # Launch the app iface.launch()