Spaces:
Sleeping
Sleeping
Create app.py
Browse files
app.py
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 matplotlib.pyplot as plt
|
| 7 |
+
import matplotlib.gridspec as gridspec
|
| 8 |
+
|
| 9 |
+
# Define pattern functions
|
| 10 |
+
pattern_funcs = [
|
| 11 |
+
("Two Crows", talib.CDL2CROWS),
|
| 12 |
+
("Three Black Crows", talib.CDL3BLACKCROWS),
|
| 13 |
+
("Three Inside Up/Down", talib.CDL3INSIDE),
|
| 14 |
+
("Three-Line Strike", talib.CDL3LINESTRIKE),
|
| 15 |
+
("Three Outside Up/Down", talib.CDL3OUTSIDE),
|
| 16 |
+
("Three Stars In The South", talib.CDL3STARSINSOUTH),
|
| 17 |
+
("Three Advancing White Soldiers", talib.CDL3WHITESOLDIERS),
|
| 18 |
+
("Abandoned Baby", talib.CDLABANDONEDBABY),
|
| 19 |
+
("Advance Block", talib.CDLADVANCEBLOCK),
|
| 20 |
+
("Belt-hold", talib.CDLBELTHOLD),
|
| 21 |
+
("Breakaway", talib.CDLBREAKAWAY),
|
| 22 |
+
("Closing Marubozu", talib.CDLCLOSINGMARUBOZU),
|
| 23 |
+
("Concealing Baby Swallow", talib.CDLCONCEALBABYSWALL),
|
| 24 |
+
("Counterattack", talib.CDLCOUNTERATTACK),
|
| 25 |
+
("Dark Cloud Cover", talib.CDLDARKCLOUDCOVER),
|
| 26 |
+
("Doji", talib.CDLDOJI),
|
| 27 |
+
("Doji Star", talib.CDLDOJISTAR),
|
| 28 |
+
("Dragonfly Doji", talib.CDLDRAGONFLYDOJI),
|
| 29 |
+
("Engulfing Pattern", talib.CDLENGULFING),
|
| 30 |
+
("Evening Doji Star", talib.CDLEVENINGDOJISTAR),
|
| 31 |
+
("Evening Star", talib.CDLEVENINGSTAR),
|
| 32 |
+
("Up/Down-gap side-by-side white lines", talib.CDLGAPSIDESIDEWHITE),
|
| 33 |
+
("Gravestone Doji", talib.CDLGRAVESTONEDOJI),
|
| 34 |
+
("Hammer", talib.CDLHAMMER),
|
| 35 |
+
("Hanging Man", talib.CDLHANGINGMAN),
|
| 36 |
+
("Harami Pattern", talib.CDLHARAMI),
|
| 37 |
+
("Harami Cross Pattern", talib.CDLHARAMICROSS),
|
| 38 |
+
("High-Wave Candle", talib.CDLHIGHWAVE),
|
| 39 |
+
("Hikkake Pattern", talib.CDLHIKKAKE),
|
| 40 |
+
("Modified Hikkake Pattern", talib.CDLHIKKAKEMOD),
|
| 41 |
+
("Homing Pigeon", talib.CDLHOMINGPIGEON),
|
| 42 |
+
("Identical Three Crows", talib.CDLIDENTICAL3CROWS),
|
| 43 |
+
("In-Neck Pattern", talib.CDLINNECK),
|
| 44 |
+
("Inverted Hammer", talib.CDLINVERTEDHAMMER),
|
| 45 |
+
("Kicking", talib.CDLKICKING),
|
| 46 |
+
("Kicking - bull/bear determined by the longer marubozu", talib.CDLKICKINGBYLENGTH),
|
| 47 |
+
("Ladder Bottom", talib.CDLLADDERBOTTOM),
|
| 48 |
+
("Long Legged Doji", talib.CDLLONGLEGGEDDOJI),
|
| 49 |
+
("Long Line Candle", talib.CDLLONGLINE),
|
| 50 |
+
("Marubozu", talib.CDLMARUBOZU),
|
| 51 |
+
("Matching Low", talib.CDLMATCHINGLOW),
|
| 52 |
+
("Mat Hold", talib.CDLMATHOLD),
|
| 53 |
+
("Morning Doji Star", talib.CDLMORNINGDOJISTAR),
|
| 54 |
+
("Morning Star", talib.CDLMORNINGSTAR),
|
| 55 |
+
("On-Neck Pattern", talib.CDLONNECK),
|
| 56 |
+
("Piercing Pattern", talib.CDLPIERCING),
|
| 57 |
+
("Rickshaw Man", talib.CDLRICKSHAWMAN),
|
| 58 |
+
("Rising/Falling Three Methods", talib.CDLRISEFALL3METHODS),
|
| 59 |
+
("Separating Lines", talib.CDLSEPARATINGLINES),
|
| 60 |
+
("Shooting Star", talib.CDLSHOOTINGSTAR),
|
| 61 |
+
("Short Line Candle", talib.CDLSHORTLINE),
|
| 62 |
+
("Spinning Top", talib.CDLSPINNINGTOP),
|
| 63 |
+
("Stalled Pattern", talib.CDLSTALLEDPATTERN),
|
| 64 |
+
("Stick Sandwich", talib.CDLSTICKSANDWICH),
|
| 65 |
+
("Takuri (Dragonfly Doji with very long lower shadow)", talib.CDLTAKURI),
|
| 66 |
+
("Tasuki Gap", talib.CDLTASUKIGAP),
|
| 67 |
+
("Thrusting Pattern", talib.CDLTHRUSTING),
|
| 68 |
+
("Tristar Pattern", talib.CDLTRISTAR),
|
| 69 |
+
("Unique 3 River", talib.CDLUNIQUE3RIVER),
|
| 70 |
+
("Upside Gap Two Crows", talib.CDLUPSIDEGAP2CROWS),
|
| 71 |
+
("Upside/Downside Gap Three Methods", talib.CDLXSIDEGAP3METHODS)
|
| 72 |
+
]
|
| 73 |
+
|
| 74 |
+
# Streamlit app setup
|
| 75 |
+
st.title('Candlestick Pattern Detection')
|
| 76 |
+
|
| 77 |
+
# Sidebar inputs
|
| 78 |
+
st.sidebar.header('Input Parameters')
|
| 79 |
+
symbol = st.sidebar.text_input('Enter Stock Ticker', 'SIE.DE')
|
| 80 |
+
start_date = st.sidebar.date_input('Start Date', pd.to_datetime('2020-01-01'))
|
| 81 |
+
end_date = st.sidebar.date_input('End Date', pd.to_datetime('2024-01-01'))
|
| 82 |
+
|
| 83 |
+
if st.sidebar.button('Run'):
|
| 84 |
+
data = yf.download(symbol, start=start_date, end=end_date)
|
| 85 |
+
|
| 86 |
+
if not data.empty:
|
| 87 |
+
for pattern_name, pattern_func in pattern_funcs:
|
| 88 |
+
data[pattern_name] = pattern_func(data['Open'], data['High'], data['Low'], data['Close'])
|
| 89 |
+
pattern_dates = data[data[pattern_name] != 0].index
|
| 90 |
+
|
| 91 |
+
if len(pattern_dates) == 0:
|
| 92 |
+
continue
|
| 93 |
+
|
| 94 |
+
fig = plt.figure(figsize=(20, 10))
|
| 95 |
+
gs = gridspec.GridSpec(2, 4)
|
| 96 |
+
|
| 97 |
+
mc = mpf.make_marketcolors(up='g', down='r', inherit=True)
|
| 98 |
+
custom_style = mpf.make_mpf_style(marketcolors=mc)
|
| 99 |
+
|
| 100 |
+
ax1 = plt.subplot(gs[0, :3])
|
| 101 |
+
data[['Close']].plot(ax=ax1, color='blue')
|
| 102 |
+
for date in pattern_dates:
|
| 103 |
+
ax1.axvline(date, color='red', linestyle='--', label=pattern_name if pattern_name not in [l.get_label() for l in ax1.lines] else "")
|
| 104 |
+
ax1.annotate(date.strftime('%Y-%m-%d'), (date, data['Close'].loc[date]), xytext=(-15, 10 + 20),
|
| 105 |
+
textcoords='offset points', color='red', fontsize=12, rotation=90)
|
| 106 |
+
|
| 107 |
+
window = 5 # Days before and after the pattern
|
| 108 |
+
for i in range(5):
|
| 109 |
+
if len(pattern_dates) > i:
|
| 110 |
+
pattern_date = pattern_dates[-(i + 1)]
|
| 111 |
+
|
| 112 |
+
start_date_window = pattern_date - pd.Timedelta(days=window)
|
| 113 |
+
end_date_window = min(data.index[-1], pattern_date + pd.Timedelta(days=window))
|
| 114 |
+
valid_dates = pd.date_range(start=start_date_window, end=end_date_window).intersection(data.index)
|
| 115 |
+
|
| 116 |
+
subset = data.loc[valid_dates]
|
| 117 |
+
|
| 118 |
+
if i == 0:
|
| 119 |
+
ax = plt.subplot(gs[0, 3])
|
| 120 |
+
else:
|
| 121 |
+
ax = plt.subplot(gs[1, i - 1])
|
| 122 |
+
|
| 123 |
+
mpf.plot(subset, type='candle', ax=ax, volume=False, show_nontrading=False, style=custom_style)
|
| 124 |
+
ax.set_title(f'{pattern_name} Pattern {i + 1} for {symbol}')
|
| 125 |
+
|
| 126 |
+
x_ticks = list(range(0, len(valid_dates), 1))
|
| 127 |
+
x_labels = [date.strftime('%Y-%m-%d') for date in valid_dates]
|
| 128 |
+
ax.set_xticks(x_ticks)
|
| 129 |
+
ax.set_xticklabels(x_labels, rotation=90)
|
| 130 |
+
|
| 131 |
+
ax1.set_title(f"{symbol} Stock Price and {pattern_name} Pattern Detection")
|
| 132 |
+
ax1.legend(loc='best')
|
| 133 |
+
ax1.grid(True)
|
| 134 |
+
ax1.set_xlabel("Date")
|
| 135 |
+
ax1.set_ylabel("Price")
|
| 136 |
+
plt.tight_layout()
|
| 137 |
+
|
| 138 |
+
st.pyplot(fig)
|
| 139 |
+
else:
|
| 140 |
+
st.write("No data found for the given ticker and date range.")
|