Space23 / app.py
QuantumLearner's picture
Update app.py
3d8dc02 verified
import yfinance as yf
import talib
import pandas as pd
import streamlit as st
import plotly.graph_objects as go
# Set page configuration
st.set_page_config(layout="wide")
# Define pattern functions
pattern_funcs = [
("Two Crows", talib.CDL2CROWS),
("Three Black Crows", talib.CDL3BLACKCROWS),
("Three Inside Up/Down", talib.CDL3INSIDE),
("Three-Line Strike", talib.CDL3LINESTRIKE),
("Three Outside Up/Down", talib.CDL3OUTSIDE),
("Three Stars In The South", talib.CDL3STARSINSOUTH),
("Three Advancing White Soldiers", talib.CDL3WHITESOLDIERS),
("Abandoned Baby", talib.CDLABANDONEDBABY),
("Advance Block", talib.CDLADVANCEBLOCK),
("Belt-hold", talib.CDLBELTHOLD),
("Breakaway", talib.CDLBREAKAWAY),
("Closing Marubozu", talib.CDLCLOSINGMARUBOZU),
("Concealing Baby Swallow", talib.CDLCONCEALBABYSWALL),
("Counterattack", talib.CDLCOUNTERATTACK),
("Dark Cloud Cover", talib.CDLDARKCLOUDCOVER),
("Doji", talib.CDLDOJI),
("Doji Star", talib.CDLDOJISTAR),
("Dragonfly Doji", talib.CDLDRAGONFLYDOJI),
("Engulfing Pattern", talib.CDLENGULFING),
("Evening Doji Star", talib.CDLEVENINGDOJISTAR),
("Evening Star", talib.CDLEVENINGSTAR),
("Up/Down-gap side-by-side white lines", talib.CDLGAPSIDESIDEWHITE),
("Gravestone Doji", talib.CDLGRAVESTONEDOJI),
("Hammer", talib.CDLHAMMER),
("Hanging Man", talib.CDLHANGINGMAN),
("Harami Pattern", talib.CDLHARAMI),
("Harami Cross Pattern", talib.CDLHARAMICROSS),
("High-Wave Candle", talib.CDLHIGHWAVE),
("Hikkake Pattern", talib.CDLHIKKAKE),
("Modified Hikkake Pattern", talib.CDLHIKKAKEMOD),
("Homing Pigeon", talib.CDLHOMINGPIGEON),
("Identical Three Crows", talib.CDLIDENTICAL3CROWS),
("In-Neck Pattern", talib.CDLINNECK),
("Inverted Hammer", talib.CDLINVERTEDHAMMER),
("Kicking", talib.CDLKICKING),
("Kicking - bull/bear determined by the longer marubozu", talib.CDLKICKINGBYLENGTH),
("Ladder Bottom", talib.CDLLADDERBOTTOM),
("Long Legged Doji", talib.CDLLONGLEGGEDDOJI),
("Long Line Candle", talib.CDLLONGLINE),
("Marubozu", talib.CDLMARUBOZU),
("Matching Low", talib.CDLMATCHINGLOW),
("Mat Hold", talib.CDLMATHOLD),
("Morning Doji Star", talib.CDLMORNINGDOJISTAR),
("Morning Star", talib.CDLMORNINGSTAR),
("On-Neck Pattern", talib.CDLONNECK),
("Piercing Pattern", talib.CDLPIERCING),
("Rickshaw Man", talib.CDLRICKSHAWMAN),
("Rising/Falling Three Methods", talib.CDLRISEFALL3METHODS),
("Separating Lines", talib.CDLSEPARATINGLINES),
("Shooting Star", talib.CDLSHOOTINGSTAR),
("Short Line Candle", talib.CDLSHORTLINE),
("Spinning Top", talib.CDLSPINNINGTOP),
("Stalled Pattern", talib.CDLSTALLEDPATTERN),
("Stick Sandwich", talib.CDLSTICKSANDWICH),
("Takuri (Dragonfly Doji with very long lower shadow)", talib.CDLTAKURI),
("Tasuki Gap", talib.CDLTASUKIGAP),
("Thrusting Pattern", talib.CDLTHRUSTING),
("Tristar Pattern", talib.CDLTRISTAR),
("Unique 3 River", talib.CDLUNIQUE3RIVER),
("Upside Gap Two Crows", talib.CDLUPSIDEGAP2CROWS),
("Upside/Downside Gap Three Methods", talib.CDLXSIDEGAP3METHODS)
]
# Streamlit app setup
st.title('Automatic Candlestick Pattern Detection')
st.write("""
This tool automatically detects 60+ candlestick patterns in stock or crypto price data.
* 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.
* The tool will fetch the historical data and highlight detected patterns on the charts.
* The charts display the asset price data along with vertical lines indicating where patterns were found.
* If no patterns are detected, the chart for that pattern will not be included.
""")
# Sidebar for input parameters
with st.sidebar.expander("Input Parameters", expanded=True):
symbol = st.text_input('Enter Asset Symbol', 'BTC-USD', help="Input the ticker symbol for the stock or crypto pair.")
start_date = st.date_input('Start Date', pd.to_datetime('2023-06-01'), help="Select the start date for the analysis.")
end_date = st.date_input('End Date', pd.to_datetime(pd.Timestamp.now().date() + pd.Timedelta(days=1)), help="Select the end date for the analysis.")
# Moving averages inside an expander, closed by default
with st.sidebar.expander("Moving Average Parameters", expanded=False):
ma_short_period = st.number_input('Short-term Moving Average Period', min_value=1, value=20, help="Set the period for the short-term moving average.")
ma_long_period = st.number_input('Long-term Moving Average Period', min_value=1, value=50, help="Set the period for the long-term moving average.")
# Place the Run Analysis button above the candlestick pattern checkboxes
if st.sidebar.button('Run Analysis'):
run_analysis = True
else:
run_analysis = False
# Candlestick patterns selection inside an expander, open by default
with st.sidebar.expander("Candlestick Patterns", expanded=True):
selected_patterns = {name: st.checkbox(name, value=True) for name, func in pattern_funcs}
if run_analysis:
# Fetch data with yfinance adjustments
data = yf.download(symbol, start=start_date, end=end_date, auto_adjust=False)
if isinstance(data.columns, pd.MultiIndex):
data.columns = data.columns.get_level_values(0)
if not data.empty:
# Calculate moving averages based on user input with NaN handling
data[f'MA{ma_short_period}'] = talib.SMA(data['Close'], timeperiod=ma_short_period)
data[f'MA{ma_long_period}'] = talib.SMA(data['Close'], timeperiod=ma_long_period)
for pattern_name, pattern_func in pattern_funcs:
if selected_patterns[pattern_name]:
# Calculate pattern with TALib and handle potential NaNs
data[pattern_name] = pattern_func(data['Open'], data['High'], data['Low'], data['Close'])
pattern_dates = data[data[pattern_name].notna() & (data[pattern_name] != 0)].index
if len(pattern_dates) == 0:
st.write(f"No {pattern_name} patterns detected for {symbol} in the selected date range.")
continue
# Create Plotly figure
fig = go.Figure()
# Candlestick chart
fig.add_trace(go.Candlestick(
x=data.index,
open=data['Open'],
high=data['High'],
low=data['Low'],
close=data['Close'],
name='Candlesticks',
yaxis='y2'
))
# Short-term moving average
fig.add_trace(go.Scatter(
x=data.index,
y=data[f'MA{ma_short_period}'],
mode='lines',
line=dict(color='blue', width=1.5),
name=f'{ma_short_period}-day MA',
yaxis='y2'
))
# Long-term moving average
fig.add_trace(go.Scatter(
x=data.index,
y=data[f'MA{ma_long_period}'],
mode='lines',
line=dict(color='orange', width=1.5),
name=f'{ma_long_period}-day MA',
yaxis='y2'
))
# Volume bars
fig.add_trace(go.Bar(
x=data.index,
y=data['Volume'],
name='Volume',
yaxis='y',
marker=dict(color='grey'),
opacity=0.5
))
# Add vertical lines for pattern detection
for date in pattern_dates:
fig.add_vline(x=date, line=dict(color='red', width=2, dash='dash'), name=pattern_name)
# Update layout
fig.update_layout(
title=f"{symbol} Price and {pattern_name} Pattern Detection",
xaxis_title="Date",
yaxis=dict(title='Volume'),
yaxis2=dict(title='Price', overlaying='y', side='right'),
legend_title="Legend",
xaxis_rangeslider_visible=False,
template='plotly_white',
height=600
)
st.plotly_chart(fig, use_container_width=True)
else:
st.error(f"No data found for {symbol} in the given date range ({start_date} to {end_date}).")
# Hide the Streamlit style
hide_streamlit_style = """
<style>
#MainMenu {visibility: hidden;}
footer {visibility: hidden;}
</style>
"""
st.markdown(hide_streamlit_style, unsafe_allow_html=True)