Spaces:
Sleeping
Sleeping
| 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) |