juanbenitez commited on
Commit
2c28cc7
·
verified ·
1 Parent(s): 6982784

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +118 -0
app.py ADDED
@@ -0,0 +1,118 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import dash
2
+ from dash import dcc, html
3
+ from dash.dependencies import Input, Output, State
4
+ import pandas as pd
5
+ import plotly.graph_objects as go
6
+ import numpy as np
7
+ from datetime import datetime, timedelta
8
+
9
+ # --- 1. Generación de Datos Simulados (Mock Data) ---
10
+ def generar_datos_precios(dias=30):
11
+ """Genera un DataFrame simulado de precios diarios."""
12
+
13
+ # Crear un rango de fechas
14
+ fechas = [datetime.now() - timedelta(days=i) for i in range(dias)][::-1]
15
+
16
+ # Simular una trayectoria de precios (ejemplo: un paseo aleatorio)
17
+ # Empezamos en 100 y añadimos ruido
18
+ precios = [100.0]
19
+ for _ in range(dias - 1):
20
+ # El cambio es un número aleatorio pequeño (-1 a 1)
21
+ cambio = np.random.uniform(-1, 1) * 0.5
22
+ nuevo_precio = precios[-1] + cambio
23
+ # Nos aseguramos de que el precio no baje de 90
24
+ precios.append(max(90, nuevo_precio))
25
+
26
+ df = pd.DataFrame({
27
+ 'Fecha': fechas,
28
+ 'Precio': [float(f'{p:.2f}') for p in precios] # Formato a 2 decimales
29
+ })
30
+ return df
31
+
32
+ df_precios = generar_datos_precios()
33
+ precio_actual = df_precios['Precio'].iloc[-1]
34
+
35
+
36
+ # --- 2. Inicialización de la Aplicación Dash ---
37
+ app = dash.Dash(__name__)
38
+
39
+ # --- 3. Diseño (Layout) de la Aplicación ---
40
+ app.layout = html.Div(style={'backgroundColor': '#1f2630', 'color': '#c7d0d9', 'padding': '20px'}, children=[
41
+ html.H1("Simulador de Trading con Dash/Plotly", style={'textAlign': 'center', 'color': '#00bcd4'}),
42
+ html.P(f"Precio Actual del Activo (CEJ): ${precio_actual:.2f}", id='precio-actual-display', style={'textAlign': 'center', 'fontSize': '1.5em'}),
43
+
44
+ # Gráfico interactivo (Candlestick o Línea)
45
+ dcc.Graph(id='grafico-precios', style={'height': '60vh'}),
46
+
47
+ html.Div([
48
+ dcc.Input(id='input-cantidad', type='number', value=1, min=1, style={'marginRight': '10px', 'padding': '10px', 'width': '100px'}),
49
+ html.Button('COMPRAR ACTIVO', id='boton-comprar', n_clicks=0, style={'padding': '10px 20px', 'backgroundColor': '#4CAF50', 'color': 'white', 'border': 'none', 'borderRadius': '5px', 'cursor': 'pointer'}),
50
+ ], style={'textAlign': 'center', 'marginTop': '20px'}),
51
+
52
+ html.Div(id='output-transaccion', style={'textAlign': 'center', 'marginTop': '15px', 'fontSize': '1.2em', 'minHeight': '30px'})
53
+ ])
54
+
55
+
56
+ # --- 4. Callbacks para la Interactividad ---
57
+
58
+ # Callback para actualizar el gráfico
59
+ @app.callback(
60
+ Output('grafico-precios', 'figure'),
61
+ [Input('grafico-precios', 'relayoutData')] # Esto es solo para que Dash sepa cuándo refrescar (en apps reales, usarías dcc.Interval)
62
+ )
63
+ def actualizar_grafico(relayout_data):
64
+ """Dibuja un gráfico de línea simple con los precios simulados."""
65
+
66
+ fig = go.Figure(data=[
67
+ go.Scatter(
68
+ x=df_precios['Fecha'],
69
+ y=df_precios['Precio'],
70
+ mode='lines+markers',
71
+ name='Precio',
72
+ line={'color': '#00bcd4'} # Color del gráfico
73
+ )
74
+ ])
75
+
76
+ fig.update_layout(
77
+ title='Histórico de Precios del Activo (CEJ)',
78
+ xaxis_title='Fecha',
79
+ yaxis_title='Precio (USD)',
80
+ plot_bgcolor='#273142', # Fondo del gráfico
81
+ paper_bgcolor='#1f2630', # Fondo general de la figura
82
+ font_color='#c7d0d9'
83
+ )
84
+ return fig
85
+
86
+
87
+ # Callback para manejar la compra
88
+ @app.callback(
89
+ [Output('output-transaccion', 'children'),
90
+ Output('precio-actual-display', 'children')],
91
+ [Input('boton-comprar', 'n_clicks')],
92
+ [State('input-cantidad', 'value')]
93
+ )
94
+ def manejar_transaccion(n_clicks, cantidad):
95
+ global precio_actual
96
+
97
+ # Esta función se dispara al inicio, ignoramos el primer click (n_clicks=0)
98
+ if n_clicks is None or n_clicks == 0:
99
+ # Esto solo asegura que el display del precio inicial sea correcto
100
+ return "", f"Precio Actual del Activo (CEJ): ${precio_actual:.2f}"
101
+
102
+ # Simulamos que el precio puede haber cambiado (idealmente, esto vendría de un dcc.Interval)
103
+ # Para este ejemplo, solo usaremos el precio final de los datos simulados
104
+
105
+ costo_total = precio_actual * cantidad
106
+
107
+ mensaje = f"✅ ¡COMPRA EXITOSA! {cantidad} unidades de CEJ a ${precio_actual:.2f} cada una. Costo total: ${costo_total:.2f}"
108
+
109
+ # La salida del precio actual se mantiene:
110
+ precio_display = f"Precio Actual del Activo (CEJ): ${precio_actual:.2f}"
111
+
112
+ return mensaje, precio_display
113
+
114
+
115
+ # --- 5. Ejecución del Servidor ---
116
+ if __name__ == '__main__':
117
+ # El debug=True permite que los cambios en el código se reflejen automáticamente
118
+ app.run_server(debug=True)