| | 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 |
| |
|
| | |
| | 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_stock_chart(ticker, start_date, end_date, chart_type): |
| | 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." |
| |
|
| | if chart_type == "Log": |
| | return plot_logarithmic_chart(data, ticker) |
| | else: |
| | return plot_candlestick_chart(data, ticker) |
| |
|
| | except Exception as e: |
| | return f"An error occurred: {str(e)}" |
| |
|
| | def plot_logarithmic_chart(data, ticker): |
| | 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='blue'))) |
| | fig.add_trace(go.Scatter(x=extended_dates, y=log_trend, mode='lines', name='Log Trend', line=dict(color='red'))) |
| | 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': f'Stock Log Chart: {ticker}', |
| | '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 |
| |
|
| | def plot_candlestick_chart(data, ticker): |
| | fig = go.Figure(data=[go.Candlestick(x=data.index, |
| | open=data['Open'], |
| | high=data['High'], |
| | low=data['Low'], |
| | close=data['Close'])]) |
| |
|
| | fig.update_layout( |
| | title={ |
| | 'text': f'Stock Candlestick Chart: {ticker}', |
| | 'y': 0.95, |
| | 'x': 0.5, |
| | 'xanchor': 'center', |
| | 'yanchor': 'top' |
| | }, |
| | xaxis_title='Date', |
| | yaxis_title='Price', |
| | 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 |
| |
|
| | |
| | current_date = datetime.now().strftime("%Y-%m-%d") |
| |
|
| | |
| | custom_css = """ |
| | .center-text { |
| | text-align: center; |
| | } |
| | |
| | #generate-button:hover, #ticker-input input:hover, #start-date-input input:hover, #end-date-input input:hover { |
| | background-color: #FFB3BA !important; /* Pastel red */ |
| | } |
| | |
| | #header-image { |
| | display: block; |
| | margin: 0 auto; |
| | max-width: 100%; |
| | height: auto; |
| | } |
| | """ |
| |
|
| | |
| | with gr.Blocks(theme=seafoam, title="Log Stock Charts", css=custom_css) as iface: |
| | |
| | gr.Image("header.png", elem_id="header-image", show_label=False) |
| | |
| | gr.Markdown("Enter a stock ticker and date range to generate a chart.", elem_classes=["center-text"]) |
| | |
| | with gr.Row(): |
| | ticker = gr.Textbox(label="Stock Ticker", value="MSFT", elem_id="ticker-input") |
| | start_date = gr.Textbox(label="Start Date", value="2015-01-01", elem_id="start-date-input") |
| | end_date = gr.Textbox(label="End Date", value=current_date, elem_id="end-date-input") |
| | |
| | with gr.Accordion("Chart Options", open=False): |
| | chart_type = gr.Radio(["Log", "Candlestick"], label="Chart Type", value="Log") |
| | |
| | submit_button = gr.Button("Generate Chart", elem_id="generate-button") |
| | |
| | with gr.Row(): |
| | stock_chart = gr.Plot(label="Stock Chart") |
| | |
| | submit_button.click( |
| | plot_interactive_stock_chart, |
| | inputs=[ticker, start_date, end_date, chart_type], |
| | outputs=[stock_chart] |
| | ) |
| |
|
| | |
| | iface.launch(show_api=False, show_error=False) |