import streamlit as st import plotly.graph_objects as go from datetime import datetime, timedelta import pandas as pd import numpy as np from utils.patterns import identify_patterns, calculate_technical_indicators from utils.predictions import predict_movement from utils.trading import fetch_market_data, is_market_open # Page configuration st.set_page_config( page_title="Trading Pattern Analysis", page_icon="📈", layout="wide" ) # Load custom CSS with open('styles/custom.css') as f: st.markdown(f'', unsafe_allow_html=True) # Pattern descriptions from the uploaded file PATTERN_DESCRIPTIONS = { 'HAMMER': 'Small body near the top with long lower wick, indicating buying pressure overcoming selling pressure.', 'INVERTED_HAMMER': 'Small body with long upper wick after downtrend, indicating resistance but potential upward movement.', 'PIERCING_LINE': 'Two-candlestick pattern where second closes above midpoint of first, signaling bullish shift.', 'BULLISH_ENGULFING': 'Small bearish candle followed by larger bullish candle that engulfs previous one.', 'MORNING_STAR': 'Three-candlestick pattern with bearish, small-bodied, and bullish candle indicating reversal.', 'THREE_WHITE_SOLDIERS': 'Three consecutive long bullish candles with small/no wicks, showing strong buying pressure.', 'BULLISH_HARAMI': 'Small bullish candle within body of preceding large bearish candle.', 'HANGING_MAN': 'Small body at top with long lower wick, signaling potential reversal.', 'DARK_CLOUD_COVER': 'Two-candlestick pattern with bearish closing below midpoint of previous bullish.', 'BEARISH_ENGULFING': 'Small bullish candle followed by larger bearish candle that engulfs it.', 'EVENING_STAR': 'Three-candlestick pattern with bullish, small-bodied, and bearish candle.', 'THREE_BLACK_CROWS': 'Three consecutive bearish candles showing strong selling.', 'SHOOTING_STAR': 'Small body with long upper wick, signaling resistance.', 'DOJI': 'Small body with wicks, showing market indecision.', 'DRAGONFLY_DOJI': 'Doji with long lower wick, showing buying pressure at bottom.', 'GRAVESTONE_DOJI': 'Doji with long upper wick, showing selling pressure at top.' } # Sidebar st.sidebar.title("Trading Controls") # Market Status Indicator market_open = is_market_open() status_color = "🟢" if market_open else "🔴" market_status = "Market Open" if market_open else "Market Closed" st.sidebar.write(f"{status_color} {market_status}") symbol = st.sidebar.text_input("Symbol", value="AAPL", help="Enter a valid stock symbol (e.g., AAPL, MSFT)") timeframe = st.sidebar.selectbox( "Timeframe", ["30m", "1h", "2h", "4h"], index=0, help="Select analysis timeframe (each candle represents 15 minutes)" ) # Add auto-refresh option auto_refresh = st.sidebar.checkbox("Auto-refresh data", value=True) if auto_refresh: st.sidebar.write("Updates every minute") st.rerun() # Use st.rerun() instead of experimental_rerun() # Main content st.title("Trading Pattern Analysis") try: # Fetch and process data with st.spinner('Fetching market data...'): df = fetch_market_data(symbol, period='1d', interval='15m') if len(df) >= 2: df = calculate_technical_indicators(df) patterns = identify_patterns(df) # Create candlestick chart fig = go.Figure(data=[go.Candlestick( x=df.index, open=df['Open'], high=df['High'], low=df['Low'], close=df['Close'] )]) # Update layout for dark theme fig.update_layout( template="plotly_dark", plot_bgcolor="#252525", paper_bgcolor="#252525", xaxis_rangeslider_visible=False, height=600, title=f"{symbol} - Live Market Data ({timeframe} timeframe)" ) # Display chart st.plotly_chart(fig, use_container_width=True) # Pattern Analysis col1, col2 = st.columns(2) with col1: st.subheader("Pattern Analysis") if not patterns.empty and len(patterns) > 0: latest_patterns = patterns.iloc[-1] detected_patterns = latest_patterns[latest_patterns == 1].index.tolist() if detected_patterns: st.write("Detected Patterns:") for pattern in detected_patterns: st.markdown(f"""

• {pattern.replace('_', ' ')}

{PATTERN_DESCRIPTIONS.get(pattern, '')}

""", unsafe_allow_html=True) else: st.info("No patterns detected in current timeframe") else: st.write("No pattern data available") with col2: st.subheader("Prediction") if len(df) >= 30: prediction, probability = predict_movement(df) if prediction is not None and probability is not None: direction = "Upward" if prediction else "Downward" confidence = probability[1] if prediction else probability[0] direction_class = "profit" if direction == "Upward" else "loss" st.markdown(f"""

Predicted Movement: {direction}

Confidence: {confidence:.2%}

(Next 15-minute prediction)

""", unsafe_allow_html=True) else: st.write("Could not generate prediction") else: st.write("Insufficient data for prediction") # Technical Indicators st.subheader("Technical Indicators") col3, col4, col5 = st.columns(3) with col3: last_rsi = df['RSI'].iloc[-1] if 'RSI' in df else None prev_rsi = df['RSI'].iloc[-2] if 'RSI' in df and len(df) > 1 else None if last_rsi is not None and prev_rsi is not None: delta = last_rsi - prev_rsi delta_color = "profit" if delta > 0 else "loss" st.markdown(f"""

RSI

{last_rsi:.2f}

({delta:+.2f})

""", unsafe_allow_html=True) with col4: last_macd = df['MACD'].iloc[-1] if 'MACD' in df else None prev_macd = df['MACD'].iloc[-2] if 'MACD' in df and len(df) > 1 else None if last_macd is not None and prev_macd is not None: delta = last_macd - prev_macd delta_color = "profit" if delta > 0 else "loss" st.markdown(f"""

MACD

{last_macd:.2f}

({delta:+.2f})

""", unsafe_allow_html=True) with col5: last_sma = df['SMA_20'].iloc[-1] if 'SMA_20' in df else None last_close = df['Close'].iloc[-1] if len(df) > 0 else None if last_sma is not None and last_close is not None: delta = last_close - last_sma delta_color = "profit" if delta > 0 else "loss" st.markdown(f"""

15-min SMA

{last_sma:.2f}

({delta:+.2f})

""", unsafe_allow_html=True) else: st.warning("Insufficient data points. This could be because the market is closed or the selected timeframe is too short.") except Exception as e: st.error(f"Error: {str(e)}") if "Connection Error" in str(e): st.warning("Unable to connect to market data. Please check your internet connection and try again.") elif "not found" in str(e): st.warning("Invalid symbol. Please enter a valid stock symbol.") else: st.info("If the market is closed, you can still view the most recent trading data.")