File size: 8,942 Bytes
955a169
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
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'<style>{f.read()}</style>', 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"""
                            <div class="pattern-container">
                                <h4>• {pattern.replace('_', ' ')}</h4>
                                <p>{PATTERN_DESCRIPTIONS.get(pattern, '')}</p>
                            </div>
                            """, 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"""
                        <div class="prediction-container">
                            <h3 class="{direction_class}">Predicted Movement: {direction}</h3>
                            <p>Confidence: {confidence:.2%}</p>
                            <p>(Next 15-minute prediction)</p>
                        </div>
                        """, 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"""
                    <div class="metric-container">
                        <h4>RSI</h4>
                        <p>{last_rsi:.2f}</p>
                        <p class="{delta_color}">({delta:+.2f})</p>
                    </div>
                    """, 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"""
                    <div class="metric-container">
                        <h4>MACD</h4>
                        <p>{last_macd:.2f}</p>
                        <p class="{delta_color}">({delta:+.2f})</p>
                    </div>
                    """, 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"""
                    <div class="metric-container">
                        <h4>15-min SMA</h4>
                        <p>{last_sma:.2f}</p>
                        <p class="{delta_color}">({delta:+.2f})</p>
                    </div>
                    """, 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.")