Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -1,10 +1,8 @@
|
|
| 1 |
import yfinance as yf
|
| 2 |
import talib
|
| 3 |
import pandas as pd
|
| 4 |
-
import mplfinance as mpf
|
| 5 |
import streamlit as st
|
| 6 |
-
import
|
| 7 |
-
import matplotlib.gridspec as gridspec
|
| 8 |
|
| 9 |
# Set page configuration
|
| 10 |
st.set_page_config(layout="wide")
|
|
@@ -79,26 +77,22 @@ st.title('Automatic Candlestick Pattern Detection')
|
|
| 79 |
|
| 80 |
st.write("""
|
| 81 |
This tool automatically detects 60+ candlestick patterns in stock price data.
|
| 82 |
-
You can input the stock ticker (e.g 'AAPL') or crypto pair (e.g.'BTC-USD'), start date, and end date in the sidebar menu to analyze.
|
| 83 |
-
The tool will fetch the historical data and highlight detected patterns on the charts.
|
| 84 |
-
The charts display the stock price data along with vertical lines indicating where patterns were found.
|
| 85 |
-
|
| 86 |
""")
|
| 87 |
|
| 88 |
-
# Sidebar inputs
|
| 89 |
-
st.sidebar.header('How to Use')
|
| 90 |
-
st.sidebar.write("""
|
| 91 |
-
1. Enter the stock ticker or crypto pair symbol.
|
| 92 |
-
2. Select the start and end dates.
|
| 93 |
-
3. Select the patterns you want to detect.
|
| 94 |
-
4. Click the "Run" button to generate the analysis.
|
| 95 |
-
""")
|
| 96 |
|
| 97 |
st.sidebar.header('Input Parameters')
|
| 98 |
-
symbol = st.sidebar.text_input('Enter
|
| 99 |
-
start_date = st.sidebar.date_input('Start Date', pd.to_datetime('
|
| 100 |
end_date = st.sidebar.date_input('End Date', pd.to_datetime('2025-01-01'))
|
| 101 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 102 |
if st.sidebar.button('Run Analysis'):
|
| 103 |
run_analysis = True
|
| 104 |
else:
|
|
@@ -111,6 +105,10 @@ if run_analysis:
|
|
| 111 |
data = yf.download(symbol, start=start_date, end=end_date)
|
| 112 |
|
| 113 |
if not data.empty:
|
|
|
|
|
|
|
|
|
|
|
|
|
| 114 |
for pattern_name, pattern_func in pattern_funcs:
|
| 115 |
if selected_patterns[pattern_name]:
|
| 116 |
data[pattern_name] = pattern_func(data['Open'], data['High'], data['Low'], data['Close'])
|
|
@@ -119,55 +117,62 @@ if run_analysis:
|
|
| 119 |
if len(pattern_dates) == 0:
|
| 120 |
continue
|
| 121 |
|
| 122 |
-
fig =
|
| 123 |
-
|
| 124 |
-
|
| 125 |
-
|
| 126 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 127 |
|
| 128 |
-
ax1 = plt.subplot(gs[0, :3])
|
| 129 |
-
data[['Close']].plot(ax=ax1, color='blue')
|
| 130 |
for date in pattern_dates:
|
| 131 |
-
|
| 132 |
-
|
| 133 |
-
|
| 134 |
-
|
| 135 |
-
|
| 136 |
-
|
| 137 |
-
|
| 138 |
-
|
| 139 |
-
|
| 140 |
-
|
| 141 |
-
|
| 142 |
-
valid_dates = pd.date_range(start=start_date_window, end=end_date_window).intersection(data.index)
|
| 143 |
-
|
| 144 |
-
subset = data.loc[valid_dates]
|
| 145 |
-
|
| 146 |
-
if i == 0:
|
| 147 |
-
ax = plt.subplot(gs[0, 3])
|
| 148 |
-
else:
|
| 149 |
-
ax = plt.subplot(gs[1, i - 1])
|
| 150 |
-
|
| 151 |
-
mpf.plot(subset, type='candle', ax=ax, volume=False, show_nontrading=False, style=custom_style)
|
| 152 |
-
ax.set_title(f'{pattern_name} Pattern {i + 1} for {symbol}')
|
| 153 |
-
|
| 154 |
-
x_ticks = list(range(0, len(valid_dates), 1))
|
| 155 |
-
x_labels = [date.strftime('%Y-%m-%d') for date in valid_dates]
|
| 156 |
-
ax.set_xticks(x_ticks)
|
| 157 |
-
ax.set_xticklabels(x_labels, rotation=90)
|
| 158 |
-
|
| 159 |
-
ax1.set_title(f"{symbol} Stock Price and {pattern_name} Pattern Detection")
|
| 160 |
-
ax1.legend(loc='best')
|
| 161 |
-
ax1.grid(True)
|
| 162 |
-
ax1.set_xlabel("Date")
|
| 163 |
-
ax1.set_ylabel("Price")
|
| 164 |
-
plt.tight_layout()
|
| 165 |
|
| 166 |
-
st.
|
| 167 |
else:
|
| 168 |
st.write("No data found for the given ticker and date range.")
|
| 169 |
|
| 170 |
-
|
| 171 |
hide_streamlit_style = """
|
| 172 |
<style>
|
| 173 |
#MainMenu {visibility: hidden;}
|
|
|
|
| 1 |
import yfinance as yf
|
| 2 |
import talib
|
| 3 |
import pandas as pd
|
|
|
|
| 4 |
import streamlit as st
|
| 5 |
+
import plotly.graph_objects as go
|
|
|
|
| 6 |
|
| 7 |
# Set page configuration
|
| 8 |
st.set_page_config(layout="wide")
|
|
|
|
| 77 |
|
| 78 |
st.write("""
|
| 79 |
This tool automatically detects 60+ candlestick patterns in stock price data.
|
| 80 |
+
* You can input the stock ticker (e.g. 'AAPL') or crypto pair (e.g. 'BTC-USD'), start date, and end date in the sidebar menu to analyze.
|
| 81 |
+
* The tool will fetch the historical data and highlight detected patterns on the charts.
|
| 82 |
+
* The charts display the stock price data along with vertical lines indicating where patterns were found.
|
| 83 |
+
* If no patterns are detected, the chart for that pattern will not be included.
|
| 84 |
""")
|
| 85 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 86 |
|
| 87 |
st.sidebar.header('Input Parameters')
|
| 88 |
+
symbol = st.sidebar.text_input('Enter Asset Symbol', 'AAPL')
|
| 89 |
+
start_date = st.sidebar.date_input('Start Date', pd.to_datetime('2023-06-01'))
|
| 90 |
end_date = st.sidebar.date_input('End Date', pd.to_datetime('2025-01-01'))
|
| 91 |
|
| 92 |
+
# Dynamic input for moving averages
|
| 93 |
+
ma_short_period = st.sidebar.number_input('Short-term Moving Average Period', min_value=1, value=20)
|
| 94 |
+
ma_long_period = st.sidebar.number_input('Long-term Moving Average Period', min_value=1, value=50)
|
| 95 |
+
|
| 96 |
if st.sidebar.button('Run Analysis'):
|
| 97 |
run_analysis = True
|
| 98 |
else:
|
|
|
|
| 105 |
data = yf.download(symbol, start=start_date, end=end_date)
|
| 106 |
|
| 107 |
if not data.empty:
|
| 108 |
+
# Calculate moving averages based on user input
|
| 109 |
+
data[f'MA{ma_short_period}'] = talib.SMA(data['Close'], timeperiod=ma_short_period)
|
| 110 |
+
data[f'MA{ma_long_period}'] = talib.SMA(data['Close'], timeperiod=ma_long_period)
|
| 111 |
+
|
| 112 |
for pattern_name, pattern_func in pattern_funcs:
|
| 113 |
if selected_patterns[pattern_name]:
|
| 114 |
data[pattern_name] = pattern_func(data['Open'], data['High'], data['Low'], data['Close'])
|
|
|
|
| 117 |
if len(pattern_dates) == 0:
|
| 118 |
continue
|
| 119 |
|
| 120 |
+
fig = go.Figure()
|
| 121 |
+
|
| 122 |
+
fig.add_trace(go.Candlestick(
|
| 123 |
+
x=data.index,
|
| 124 |
+
open=data['Open'],
|
| 125 |
+
high=data['High'],
|
| 126 |
+
low=data['Low'],
|
| 127 |
+
close=data['Close'],
|
| 128 |
+
name='Candlesticks',
|
| 129 |
+
yaxis='y2'
|
| 130 |
+
))
|
| 131 |
+
|
| 132 |
+
fig.add_trace(go.Scatter(
|
| 133 |
+
x=data.index,
|
| 134 |
+
y=data[f'MA{ma_short_period}'],
|
| 135 |
+
mode='lines',
|
| 136 |
+
line=dict(color='blue', width=1.5),
|
| 137 |
+
name=f'{ma_short_period}-day MA',
|
| 138 |
+
yaxis='y2'
|
| 139 |
+
))
|
| 140 |
+
|
| 141 |
+
fig.add_trace(go.Scatter(
|
| 142 |
+
x=data.index,
|
| 143 |
+
y=data[f'MA{ma_long_period}'],
|
| 144 |
+
mode='lines',
|
| 145 |
+
line=dict(color='orange', width=1.5),
|
| 146 |
+
name=f'{ma_long_period}-day MA',
|
| 147 |
+
yaxis='y2'
|
| 148 |
+
))
|
| 149 |
+
|
| 150 |
+
fig.add_trace(go.Bar(
|
| 151 |
+
x=data.index,
|
| 152 |
+
y=data['Volume'],
|
| 153 |
+
name='Volume',
|
| 154 |
+
yaxis='y',
|
| 155 |
+
marker=dict(color='grey'),
|
| 156 |
+
opacity=0.5
|
| 157 |
+
))
|
| 158 |
|
|
|
|
|
|
|
| 159 |
for date in pattern_dates:
|
| 160 |
+
fig.add_vline(x=date, line=dict(color='red', width=2, dash='dash'), name=pattern_name)
|
| 161 |
+
|
| 162 |
+
fig.update_layout(
|
| 163 |
+
title=f"{symbol} Stock Price and {pattern_name} Pattern Detection",
|
| 164 |
+
xaxis_title="Date",
|
| 165 |
+
yaxis=dict(title='Volume'),
|
| 166 |
+
yaxis2=dict(title='Price', overlaying='y', side='right'),
|
| 167 |
+
legend_title="Legend",
|
| 168 |
+
xaxis_rangeslider_visible=False,
|
| 169 |
+
template='plotly_white'
|
| 170 |
+
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 171 |
|
| 172 |
+
st.plotly_chart(fig)
|
| 173 |
else:
|
| 174 |
st.write("No data found for the given ticker and date range.")
|
| 175 |
|
|
|
|
| 176 |
hide_streamlit_style = """
|
| 177 |
<style>
|
| 178 |
#MainMenu {visibility: hidden;}
|