TraderApp / app.py
VicGerardoPR's picture
Upload 4 files
275417a verified
import streamlit as st
import cv2
import numpy as np
import matplotlib.pyplot as plt
from PIL import Image
import io
import os
from datetime import datetime
import pandas as pd
from sklearn.linear_model import LinearRegression
# Configuración de la página
st.set_page_config(
page_title="Análisis Técnico de Trading",
page_icon="📈",
layout="wide"
)
# Título y descripción
st.title("Análisis Técnico de Trading")
st.markdown("""
Esta aplicación analiza gráficos de activos financieros y proporciona recomendaciones de trading.
Sube una imagen de un gráfico y obtén un análisis técnico junto con recomendaciones a corto y largo plazo.
""")
# Función para cargar y procesar la imagen
def load_and_process_image(uploaded_file):
if uploaded_file is not None:
# Leer la imagen
image = Image.open(uploaded_file)
img_array = np.array(image)
# Convertir a escala de grises para procesamiento
gray = cv2.cvtColor(img_array, cv2.COLOR_RGB2GRAY) if len(img_array.shape) > 2 else img_array
return image, img_array, gray
return None, None, None
# Función para detectar tendencias en el gráfico
def detect_trend(img_array, gray):
# Detectar bordes
edges = cv2.Canny(gray, 50, 150, apertureSize=3)
# Detectar líneas usando la transformada de Hough
lines = cv2.HoughLinesP(edges, 1, np.pi/180, threshold=100, minLineLength=100, maxLineGap=10)
# Analizar pendientes de las líneas para determinar tendencia
slopes = []
if lines is not None:
for line in lines:
x1, y1, x2, y2 = line[0]
if x2 != x1: # Evitar división por cero
slope = (y2 - y1) / (x2 - x1)
slopes.append(slope)
# Determinar tendencia basada en pendientes
if not slopes:
return "Neutral", 0
avg_slope = np.mean(slopes)
# En gráficos, y aumenta hacia abajo, por lo que pendiente negativa = tendencia alcista
if avg_slope < -0.1:
strength = min(abs(avg_slope) * 10, 10)
return "Alcista", strength
elif avg_slope > 0.1:
strength = min(abs(avg_slope) * 10, 10)
return "Bajista", strength
else:
return "Neutral", min(abs(avg_slope) * 20, 5)
# Función para detectar patrones de velas
def detect_candlestick_patterns(img_array):
# Simulación de detección de patrones
# En una implementación real, se utilizaría un modelo entrenado para reconocer patrones
# Detectar colores predominantes (verde/rojo)
hsv = cv2.cvtColor(img_array, cv2.COLOR_RGB2HSV)
# Máscara para color verde (velas alcistas)
lower_green = np.array([40, 40, 40])
upper_green = np.array([80, 255, 255])
green_mask = cv2.inRange(hsv, lower_green, upper_green)
green_count = np.sum(green_mask > 0)
# Máscara para color rojo (velas bajistas)
lower_red1 = np.array([0, 50, 50])
upper_red1 = np.array([10, 255, 255])
lower_red2 = np.array([170, 50, 50])
upper_red2 = np.array([180, 255, 255])
red_mask1 = cv2.inRange(hsv, lower_red1, upper_red1)
red_mask2 = cv2.inRange(hsv, lower_red2, upper_red2)
red_mask = red_mask1 + red_mask2
red_count = np.sum(red_mask > 0)
patterns = []
# Determinar patrones basados en colores predominantes
if green_count > red_count * 1.5:
patterns.append("Posible patrón de velas alcistas")
if np.random.random() > 0.5: # Simulación
patterns.append("Posible Martillo Alcista")
elif red_count > green_count * 1.5:
patterns.append("Posible patrón de velas bajistas")
if np.random.random() > 0.5: # Simulación
patterns.append("Posible Estrella Fugaz")
else:
patterns.append("Patrón de velas mixto o indeciso")
if np.random.random() > 0.7: # Simulación
patterns.append("Posible Doji")
return patterns
# Función para detectar soportes y resistencias
def detect_support_resistance(gray):
# Simulación de detección de soportes y resistencias
# En una implementación real, se utilizaría análisis de histograma o detección de líneas horizontales
# Proyección horizontal (suma de píxeles por fila)
h_projection = np.sum(gray, axis=1)
# Normalizar
h_projection = h_projection / np.max(h_projection)
# Encontrar picos (posibles soportes/resistencias)
peaks = []
for i in range(1, len(h_projection) - 1):
if h_projection[i] > h_projection[i-1] and h_projection[i] > h_projection[i+1] and h_projection[i] > 0.7:
peaks.append((i, h_projection[i]))
# Ordenar por intensidad
peaks.sort(key=lambda x: x[1], reverse=True)
# Tomar los 3 picos más fuertes
top_peaks = peaks[:min(3, len(peaks))]
# Convertir a niveles de soporte/resistencia
levels = []
height = gray.shape[0]
for peak in top_peaks:
y_pos = peak[0]
# En gráficos, la parte superior es resistencia, la parte inferior es soporte
if y_pos < height / 2:
levels.append(("Resistencia", y_pos / height))
else:
levels.append(("Soporte", y_pos / height))
return levels
# Función para generar recomendaciones
def generate_recommendations(trend, trend_strength, patterns, support_resistance):
recommendations = {
"corto_plazo": "",
"largo_plazo": "",
"niveles_clave": [],
"confianza_corto": 0,
"confianza_largo": 0
}
# Recomendación a corto plazo basada en tendencia y patrones
if trend == "Alcista":
if trend_strength > 7:
recommendations["corto_plazo"] = "Comprar con stop loss ajustado"
recommendations["confianza_corto"] = min(trend_strength * 0.9, 9)
elif trend_strength > 4:
recommendations["corto_plazo"] = "Comprar en retrocesos"
recommendations["confianza_corto"] = trend_strength * 0.8
else:
recommendations["corto_plazo"] = "Comprar con precaución"
recommendations["confianza_corto"] = trend_strength * 0.7
elif trend == "Bajista":
if trend_strength > 7:
recommendations["corto_plazo"] = "Vender o abrir cortos"
recommendations["confianza_corto"] = min(trend_strength * 0.9, 9)
elif trend_strength > 4:
recommendations["corto_plazo"] = "Vender rebotes"
recommendations["confianza_corto"] = trend_strength * 0.8
else:
recommendations["corto_plazo"] = "Mantener posiciones cortas existentes"
recommendations["confianza_corto"] = trend_strength * 0.7
else:
recommendations["corto_plazo"] = "Mantenerse al margen, mercado sin dirección clara"
recommendations["confianza_corto"] = trend_strength * 0.5
# Ajustar recomendación basada en patrones de velas
for pattern in patterns:
if "alcista" in pattern.lower() and trend != "Bajista":
recommendations["corto_plazo"] += ". " + pattern + " refuerza señal de compra"
recommendations["confianza_corto"] = min(recommendations["confianza_corto"] + 1, 10)
elif "bajista" in pattern.lower() and trend != "Alcista":
recommendations["corto_plazo"] += ". " + pattern + " refuerza señal de venta"
recommendations["confianza_corto"] = min(recommendations["confianza_corto"] + 1, 10)
elif "doji" in pattern.lower():
recommendations["corto_plazo"] += ". " + pattern + " indica indecisión, considerar reducir exposición"
recommendations["confianza_corto"] = max(recommendations["confianza_corto"] - 1, 1)
# Recomendación a largo plazo
if trend == "Alcista":
recommendations["largo_plazo"] = "Mantener posiciones largas con visión de medio/largo plazo"
recommendations["confianza_largo"] = min(trend_strength * 0.7, 8)
elif trend == "Bajista":
recommendations["largo_plazo"] = "Considerar estrategias de cobertura para el largo plazo"
recommendations["confianza_largo"] = min(trend_strength * 0.7, 8)
else:
recommendations["largo_plazo"] = "Acumular gradualmente en niveles de soporte clave"
recommendations["confianza_largo"] = 5
# Añadir información de soportes y resistencias
for level_type, level_value in support_resistance:
if level_type == "Soporte":
recommendations["niveles_clave"].append(f"Soporte en nivel {level_value:.2f}")
if trend == "Alcista":
recommendations["largo_plazo"] += f". Considerar aumentar posición en soporte {level_value:.2f}"
else: # Resistencia
recommendations["niveles_clave"].append(f"Resistencia en nivel {level_value:.2f}")
if trend == "Bajista":
recommendations["largo_plazo"] += f". Considerar reducir exposición en resistencia {level_value:.2f}"
return recommendations
# Función para visualizar el análisis
def visualize_analysis(image, trend, patterns, support_resistance):
fig, ax = plt.subplots(figsize=(10, 6))
ax.imshow(image)
# Añadir anotaciones
height, width = image.size[1], image.size[0]
# Anotar tendencia
ax.text(width * 0.05, height * 0.1, f"Tendencia: {trend}",
color='white', fontsize=12, bbox=dict(facecolor='black', alpha=0.7))
# Anotar patrones
for i, pattern in enumerate(patterns):
ax.text(width * 0.05, height * (0.2 + i * 0.05), pattern,
color='white', fontsize=10, bbox=dict(facecolor='blue', alpha=0.7))
# Anotar soportes y resistencias
for level_type, level_value in support_resistance:
y_pos = int(level_value * height)
color = 'green' if level_type == "Soporte" else 'red'
ax.axhline(y=y_pos, color=color, linestyle='--', alpha=0.7)
ax.text(width * 0.8, y_pos, level_type,
color='white', fontsize=10, bbox=dict(facecolor=color, alpha=0.7))
plt.axis('off')
return fig
# Interfaz principal
uploaded_file = st.file_uploader("Sube una imagen de un gráfico", type=["jpg", "jpeg", "png"])
if uploaded_file is not None:
# Mostrar imagen original
image, img_array, gray = load_and_process_image(uploaded_file)
if image is not None:
st.image(image, caption="Gráfico subido", use_column_width=True)
with st.spinner('Analizando gráfico...'):
# Detectar tendencia
trend, trend_strength = detect_trend(img_array, gray)
# Detectar patrones de velas
patterns = detect_candlestick_patterns(img_array)
# Detectar soportes y resistencias
support_resistance = detect_support_resistance(gray)
# Generar recomendaciones
recommendations = generate_recommendations(trend, trend_strength, patterns, support_resistance)
# Mostrar análisis
st.subheader("Análisis Técnico")
col1, col2 = st.columns(2)
with col1:
st.markdown(f"**Tendencia detectada:** {trend}")
st.markdown(f"**Fuerza de la tendencia:** {trend_strength:.1f}/10")
st.markdown("**Patrones identificados:**")
for pattern in patterns:
st.markdown(f"- {pattern}")
st.markdown("**Niveles clave:**")
for level in recommendations["niveles_clave"]:
st.markdown(f"- {level}")
with col2:
# Visualizar análisis
fig = visualize_analysis(image, trend, patterns, support_resistance)
st.pyplot(fig)
# Mostrar recomendaciones
st.subheader("Recomendaciones de Trading")
rec_col1, rec_col2 = st.columns(2)
with rec_col1:
st.markdown("### Operación a Corto Plazo")
st.markdown(recommendations["corto_plazo"])
st.progress(float(recommendations["confianza_corto"]/10))
st.markdown(f"*Nivel de confianza: {recommendations['confianza_corto']:.1f}/10*")
with rec_col2:
st.markdown("### Estrategia a Largo Plazo")
st.markdown(recommendations["largo_plazo"])
st.progress(float(recommendations["confianza_largo"]/10))
st.markdown(f"*Nivel de confianza: {recommendations['confianza_largo']:.1f}/10*")
# Disclaimer
st.markdown("---")
st.markdown("""
**Disclaimer:** Este análisis es generado automáticamente y tiene fines educativos.
No constituye asesoramiento financiero. Realice su propia investigación antes de tomar decisiones de inversión.
""")
else:
# Mostrar ejemplo cuando no hay archivo subido
st.info("👆 Sube una imagen de un gráfico para comenzar el análisis")
# Mostrar información de ejemplo
st.subheader("¿Cómo funciona?")
st.markdown("""
1. **Sube una imagen** de un gráfico de cualquier activo financiero
2. La aplicación **analiza automáticamente** la tendencia, patrones y niveles clave
3. Recibe **recomendaciones de trading** a corto y largo plazo
La aplicación utiliza técnicas de procesamiento de imágenes y análisis técnico para identificar:
- Tendencias alcistas, bajistas o laterales
- Patrones de velas japonesas
- Niveles de soporte y resistencia
- Señales de compra o venta
""")
# Información del pie de página
st.markdown("---")
st.markdown("Desarrollado con ❤️ usando Streamlit y técnicas de análisis de imágenes")