CoolFace
Apppublic

Quant0/options

sourceHugging Faceapache-2.0updated 1y agoView on Hugging Face
0likes
app.py317 linesDownload Raw Back to root
1# @title Web interactiva2import gradio as gr3import pandas as pd4import yfinance as yf5import matplotlib.pyplot as plt6import plotly.graph_objects as go7import numpy as np8import os9from datetime import date10 11from processes import *12# Función para obtener los datos y mostrarlos en el DataFrame de la UI13import pandas as pd14import yfinance as yf15from datetime import date16 17def generar_tabla(option_type, ticker_input, expiration_date, size_of_the_window):18    # Verificar si el ticker tiene opciones19    if not yf.Ticker(ticker_input).options:20        return pd.DataFrame()21 22    fechas_disponibles = pd.Series(yf.Ticker(ticker_input).options)23    all_tables = []24 25    # Caso 1: expiración nula o vacía, buscar la más cercana26    if expiration_date is None or expiration_date == "":27        fecha_cercana = date.today().strftime('%Y-%m-%d')28        timedeltas = fechas_disponibles.apply(lambda x: pd.to_datetime(x) - pd.to_datetime(fecha_cercana))29        expiration_date1 = fechas_disponibles[timedeltas.abs().idxmin()]30        df_final = data_option(ticker_input, expiration_date1, option_type, size_of_the_window)31        return df_final32    33    # Caso 2: todas las expiraciones34    elif expiration_date == "All":35        for fecha in fechas_disponibles:36            table = data_option(ticker_input, fecha, option_type, size_of_the_window)37            if not table.empty:38                table['dates'] = fecha39                all_tables.append(table)40        df_final = pd.concat(all_tables, ignore_index=True)41        return df_final42    43    # Caso 3: expiración específica44    else:45        timedeltas = fechas_disponibles.apply(lambda x: pd.to_datetime(x) - pd.to_datetime(expiration_date))46        expiration_date1 = fechas_disponibles[timedeltas.abs().idxmin()]47        df_final = data_option(ticker_input, expiration_date1, option_type, size_of_the_window)48        return df_final49 50def parse_opciones_table(df):51    """52    Limpia y convierte un DataFrame extraído de una tabla decorada de opciones.53    Filtra filas válidas, convierte tipos y normaliza valores booleanos.54    """55    # Filtrar filas que contienen símbolos válidos de opciones (ej. GOOGL251219P00165000)56    df_clean = df[df['contractSymbol'].str.contains(r'^[A-Z]{4,6}\d{6}[PC]\d{8}$', regex=True)].copy()57 58    # Convertir columnas relevantes a tipos numéricos59    df_clean['strike'] = pd.to_numeric(df_clean['strike'], errors='coerce')60    df_clean['volume'] = pd.to_numeric(df_clean['volume'], errors='coerce')61    df_clean['lastPrice'] = pd.to_numeric(df_clean['lastPrice'], errors='coerce')62    df_clean['impliedVolatility'] = df_clean['impliedVolatility'].astype(str).str.replace('%', '').astype(float) / 10063 64    # Normalizar columna inTheMoney65    #df_clean['inTheMoney'] = df_clean['inTheMoney'].astype(str).str.upper().map({'VERDADERO': True, 'FALSO': False})66 67    # Eliminar filas con valores nulos en columnas clave68    df_clean = df_clean.dropna(subset=['strike', 'volume', 'lastPrice', 'impliedVolatility'])69 70    return df_clean71 72def plot_opciones(df_put, df_call, ticker_input, expiration_date):73    74    spot_price =  yf.Ticker(ticker_input).info['regularMarketPrice']75    puts_itm = df_put[df_put['strike'] > spot_price]76    puts_otm = df_put[df_put['strike'] <= spot_price]77    calls_itm = df_call[df_call['strike'] < spot_price]78    calls_otm = df_call[df_call['strike'] >= spot_price]79 80    fig1 = go.Figure()81    fig1.add_trace(go.Bar(x=puts_itm['strike'], y=puts_itm['volume'], name='PUT ITM', marker_color='green', width=1))82    fig1.add_trace(go.Bar(x=puts_otm['strike'], y=puts_otm['volume'], name='PUT OTM', marker_color='red',width=1))83    fig1.add_trace(go.Bar(x=calls_itm['strike'], y=calls_itm['volume'], name='CALL ITM', marker_color='blue',width=1))84    fig1.add_trace(go.Bar(x=calls_otm['strike'], y=calls_otm['volume'], name='CALL OTM', marker_color='orange',width=1))85    fig1.add_trace(go.Scatter(x=[spot_price], y=[0], mode='markers+text',86                             marker=dict(color='black', size=10),87                             text=[f'Spot: {spot_price}'],88                             textposition='top center',89                             name='Spot Price'))90        # Agrega la línea vertical discontinua91    fig1.add_trace(go.Scatter(92        x=[spot_price, spot_price],93        y=[0, max(max(puts_itm['volume']), max(puts_otm['volume']), max(calls_itm['volume']), max(calls_otm['volume'])) * 1.1],94        mode='lines',95        name=f'Spot: {spot_price}',96        marker=dict(color='black', size=10),97        line=dict(dash='dash'),98        showlegend=False99    ))100 101 102    fig1.update_layout(title=f"Didtribución del Volumen {ticker_input}",103                      xaxis_title='Strike',104                      yaxis_title='Volumen',105                      barmode='stack',106                      template='plotly_white',107                      legend=dict(108                            orientation="h",109                            yanchor="top",110                            y=-0.2,111                            xanchor="center",112                            x=0.5)113    )114 115 116    fig2 = go.Figure()117 118    fig2.add_trace(go.Scatter(119        x=df_put['strike'],120        y=df_put['impliedVolatility'],121        mode='markers+lines',122        name='PUT',123        marker=dict(color='red')124 125    ))126 127    fig2.add_trace(go.Scatter(128        x=df_call['strike'],129        y=df_call['impliedVolatility'],130        mode='markers+lines',131        name='CALL',132        marker=dict(color='blue')133 134    ))135 136    # Agrega la línea vertical aquí137    fig2.add_vline(x=spot_price, line_width=2, line_dash="dot", line_color="black")138 139    fig2.update_layout(140        title=f"Volatilidad Implícita por Strike {ticker_input}",141        xaxis_title='Strike',142        yaxis_title='Volatilidad Implícita',143        template='plotly_white',144        legend=dict(145                orientation="h",146                yanchor="top",147                y=-0.2,148                xanchor="center",149                x=0.5)150 151    )152 153    return fig1, fig2154 155 156def generar_puts(ticker_input, expiration_date, size_of_the_window):157    ticker_input = ticker_input158    puts = generar_tabla("put", ticker_input, expiration_date, size_of_the_window)159    clean_puts = parse_opciones_table(puts)160    return puts, clean_puts161    162def generar_calls(ticker_input, expiration_date, size_of_the_window):163    ticker_input = ticker_input164    calls = generar_tabla("call", ticker_input, expiration_date, size_of_the_window)165    clean_calls = parse_opciones_table(calls)166    return  calls, clean_calls167 168def generar_todo(ticker_input, expiration_date, size_of_the_window):169    puts = generar_puts(ticker_input, expiration_date, size_of_the_window)[0]170    puts_clean = generar_puts(ticker_input, expiration_date, size_of_the_window)[1]171    calls = generar_calls(ticker_input, expiration_date, size_of_the_window)[0]172    calls_clean = generar_calls(ticker_input, expiration_date, size_of_the_window)[1]173    return puts, puts_clean, calls, calls_clean174    175# Función para generar y devolver el archivo Excel176def exportar_a_excel(option_type, ticker_input, expiration_date, size_of_the_window):177 178    df_final = generar_tabla(option_type, ticker_input, expiration_date, size_of_the_window)179    try:180        if not df_final.empty:181            nombre_archivo = f"{ticker_input}_opciones_{option_type}.xlsx"182            df_final.to_excel(nombre_archivo, index=False)183            return nombre_archivo, "Archivo Excel generado con éxito."184        else:185            return None, "No se pudieron generar los datos para exportar."186    except Exception as e:187        return None, f"Error al exportar: {e}"188 189 190 191 192 193 194def exportar_a_excel_con_hojas(ticker_input, expiration_date, size_of_the_window):195 196    df_puts = generar_puts(ticker_input, expiration_date, size_of_the_window)[0]197    df_calls = generar_calls(ticker_input, expiration_date, size_of_the_window)[0]198    ticker = ticker_input.upper()199    nombre_archivo = f"{ticker}_opciones.xlsx"200    try:201        with pd.ExcelWriter(nombre_archivo) as writer:202            # Escribe el DataFrame de 'puts' en la primera hoja203            if not df_puts.empty:204                df_puts.to_excel(writer, sheet_name='Puts', index=False)205            206            # Escribe el DataFrame de 'calls' en la segunda hoja207            if not df_calls.empty:208                df_calls.to_excel(writer, sheet_name='Calls', index=False)209        210        return nombre_archivo, "Archivo Excel generado con éxito."211    except Exception as e:212        return None, f"Error al exportar: {e}"213 214 215 216        217 218# -------------------------------219#    Configuración de Gradio220# -------------------------------221 222 223# --- Valores por defecto para inicializar la tabla ---224initial_df_put = generar_tabla("put", "MSTR", '', 16)225initial_df_call = generar_tabla("call", "MSTR", '', 16)226 227 228with gr.Blocks(title="Análisis de Opciones") as demo:229    230    df_put_state = gr.State(value=parse_opciones_table(initial_df_put))231    df_call_state = gr.State(value=parse_opciones_table(initial_df_call))232    233    # Añade esta línea con la URL de tu imagen234    gr.Image("https://cdn.prod.website-files.com/67174dcb1d43b06a0eae317e/672bbbc7a2b88045e5661994_logo-afi.svg", show_label=False)235 236    gr.Markdown("# Analizador de Opciones")237    gr.Markdown("#### Herramienta para visualizar y exportar datos de opciones.")238    gr.Markdown("Introduzca el tipo de opción que desea consultar, indicando el Ticker y la Fecha de vencimiento. Si no se especifica una fecha de vencimiento, se mostrarán todas las disponibles.")239    with gr.Row():240        ticker_input = gr.Textbox(label="Ticker (ej. GOOGL)", value="MSTR")241        expiration_date = gr.Textbox(label="Fecha de vencimiento (formato: aaaa-mm-dd)", value = "" )242        size_of_the_window = gr.Slider(minimum=1, maximum=30, value=16, step=1, label="Tamaño de la ventana")243    btn_mostrar = gr.Button('Cargar Datos')244    245    246    247    with gr.Tab("Puts"):248 249        with gr.Row():250            gr.Markdown("# Opciones Put")251        252        with gr.Row():253            254            output_df_put = gr.DataFrame(label="Datos de Opciones put", value=initial_df_put) 255            256        '''   257        ticker_input.change(258            fn = generar_puts,259            inputs=[ticker_input, expiration_date, size_of_the_window],260            outputs= [ output_df_put, df_put_state]261        )262        '''263        264    with gr.Tab("Calls"):265        266        with gr.Row():267            gr.Markdown("# Opciones Call")268            #btn_mostrar2 = gr.Button("Mostrar datos")269        270        with gr.Row():271             272            output_df_call = gr.DataFrame(label="Datos de Opciones call", value=initial_df_call)273            274        275        '''    276        ticker_input.change(277            fn = generar_calls,278            inputs=[ticker_input, expiration_date, size_of_the_window],279            outputs= [ output_df_call, df_call_state]280        )281        '''282    with gr.Tab("Plots"):283        284        btn_plot = gr.Button("Mostrar Plot")285        286        with gr.Row():287            output_plot1 = gr.Plot(label="Distribución de Volumen de las opciones")288            output_plot2 = gr.Plot(label = 'Volatilidad Implícita por strike')289               290        btn_plot.click(291            fn=plot_opciones,292            inputs=[df_put_state, df_call_state, ticker_input, expiration_date],293            outputs=[output_plot1, output_plot2]294        )      295            296    with gr.Tab("Exportar"):297        gr.Markdown("# Exportación:")298        gr.Markdown("### Se generará un archivo excel con dos hojas: Calls y Puts, con las correspondientes tablas según los datos seleccionados")299        btn_descargar = gr.Button("Descargar en Excel")300        output_file = gr.File(label="Archivo Excel")301        output_msg = gr.Label()        302    303    # Enlaza el botón "Mostrar datos" para actualizar los dataframes y luego para graficar.304 305        btn_descargar.click(306            fn=exportar_a_excel_con_hojas,307            inputs=[ticker_input, expiration_date, size_of_the_window],308            outputs=[output_file, output_msg]309        )    310    btn_mostrar.click(311        fn=generar_todo,312        inputs=[ticker_input, expiration_date, size_of_the_window],313        outputs= [ output_df_put, df_put_state, output_df_call, df_call_state]314    )        315 316# Inicia la aplicación317demo.launch(share=True)