├── Procfile ├── README.md ├── requirements.txt ├── setup.sh └── streamlit_crypto_forecaster.py /Procfile: -------------------------------------------------------------------------------- 1 | web: sh setup.sh && streamlit run streamlit_crypto_forecaster.py 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Read Me 2 | 3 | 4 | This repository contains a Streamlit web app which predicts the future price of a specified crypto ticker from Coinmarketcap 5 | 6 | Deployed a Crypto predictor model on heroku using Facebook Prophet library 7 | 8 | Link to the web app 9 | 10 | https://crypto-prediction-1.herokuapp.com/ 11 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | streamlit==0.82.0 2 | pystan==2.19.1.1 3 | plotly==4.14.3 4 | fbprophet==0.7.1 5 | yfinance==0.1.59 6 | cryptocmd==0.6.0 -------------------------------------------------------------------------------- /setup.sh: -------------------------------------------------------------------------------- 1 | mkdir -p ~/.streamlit/ 2 | 3 | echo "\ 4 | [server]\n\ 5 | port = $PORT\n\ 6 | enableCORS = false\n\ 7 | headless = true\n\ 8 | \n\ 9 | " > ~/.streamlit/config.toml 10 | -------------------------------------------------------------------------------- /streamlit_crypto_forecaster.py: -------------------------------------------------------------------------------- 1 | # pip install pandas numpy matplotlib streamlit pystan fbprophet cryptocmd plotly 2 | import streamlit as st 3 | import numpy as np 4 | import pandas as pd 5 | import matplotlib as plt 6 | from datetime import date, datetime 7 | 8 | from cryptocmd import CmcScraper 9 | from fbprophet import Prophet 10 | from fbprophet.plot import plot_plotly 11 | from plotly import graph_objs as go 12 | 13 | st.title('Crypto Predictor') 14 | 15 | st.markdown("This web app enables you to predict on the future value of any cryptocurrency. Built with Streamlit.") 16 | 17 | ### Change sidebar color 18 | st.markdown( 19 | """ 20 | 26 | """, 27 | unsafe_allow_html=True, 28 | ) 29 | 30 | ### Set bigger font style 31 | st.markdown( 32 | """ 33 | 39 | """, unsafe_allow_html=True) 40 | 41 | st.sidebar.markdown("
Forecaster Settings
", unsafe_allow_html=True) 42 | 43 | ### Select ticker & number of days to predict on 44 | selected_ticker = st.sidebar.text_input("Select a ticker for prediction (i.e. BTC, ETH, LINK, etc.)", "BTC") 45 | period = int(st.sidebar.number_input('Number of days to predict:', min_value=0, max_value=1000000, value=365, step=1)) 46 | training_size = int(st.sidebar.number_input('Training set (%) size:', min_value=10, max_value=100, value=100, step=5)) / 100 47 | 48 | ### Initialise scraper without time interval 49 | @st.cache 50 | def load_data(selected_ticker): 51 | init_scraper = CmcScraper(selected_ticker) 52 | df = init_scraper.get_dataframe() 53 | min_date = pd.to_datetime(min(df['Date'])) 54 | max_date = pd.to_datetime(max(df['Date'])) 55 | return min_date, max_date 56 | 57 | data_load_state = st.sidebar.text('Loading data...') 58 | min_date, max_date = load_data(selected_ticker) 59 | data_load_state.text('Loading data... done!') 60 | 61 | 62 | ### Select date range 63 | date_range = st.sidebar.selectbox("Select the timeframe to train the model on:", options=["All available data", "Specific date range"]) 64 | 65 | if date_range == "All available data": 66 | 67 | ### Initialise scraper without time interval 68 | scraper = CmcScraper(selected_ticker) 69 | 70 | elif date_range == "Specific date range": 71 | 72 | ### Initialise scraper with time interval 73 | start_date = st.sidebar.date_input('Select start date:', min_value=min_date, max_value=max_date, value=min_date) 74 | end_date = st.sidebar.date_input('Select end date:', min_value=min_date, max_value=max_date, value=max_date) 75 | scraper = CmcScraper(selected_ticker, str(start_date.strftime("%d-%m-%Y")), str(end_date.strftime("%d-%m-%Y"))) 76 | 77 | ### Pandas dataFrame for the same data 78 | data = scraper.get_dataframe() 79 | 80 | 81 | st.subheader('Raw data') 82 | st.write(data.head()) 83 | 84 | ### Plot functions 85 | def plot_raw_data(): 86 | fig = go.Figure() 87 | fig.add_trace(go.Scatter(x=data['Date'], y=data['Close'], name="Close")) 88 | fig.layout.update(title_text='Time Series data with Rangeslider', xaxis_rangeslider_visible=True) 89 | st.plotly_chart(fig) 90 | 91 | def plot_raw_data_log(): 92 | fig = go.Figure() 93 | fig.add_trace(go.Scatter(x=data['Date'], y=data['Close'], name="Close")) 94 | fig.update_yaxes(type="log") 95 | fig.layout.update(title_text='Use the Rangeslider to zoom', xaxis_rangeslider_visible=True) 96 | st.plotly_chart(fig) 97 | 98 | ### Plot (log) data 99 | plot_log = st.checkbox("Plot log scale") 100 | if plot_log: 101 | plot_raw_data_log() 102 | else: 103 | plot_raw_data() 104 | 105 | ### Predict forecast with Prophet 106 | if st.button("Predict"): 107 | 108 | df_train = data[['Date','Close']] 109 | df_train = df_train.rename(columns={"Date": "ds", "Close": "y"}) 110 | 111 | ### Create Prophet model 112 | m = Prophet( 113 | changepoint_range=training_size, # 0.8 114 | yearly_seasonality='auto', 115 | weekly_seasonality='auto', 116 | daily_seasonality=False, 117 | seasonality_mode='multiplicative', # multiplicative/additive 118 | changepoint_prior_scale=0.05 119 | ) 120 | 121 | ### Add (additive) regressor 122 | for col in df_train.columns: 123 | if col not in ["ds", "y"]: 124 | m.add_regressor(col, mode="additive") 125 | 126 | m.fit(df_train) 127 | 128 | ### Predict using the model 129 | future = m.make_future_dataframe(periods=period) 130 | forecast = m.predict(future) 131 | 132 | ### Show and plot forecast 133 | st.subheader('Forecast data') 134 | st.write(forecast.head()) 135 | 136 | st.subheader(f'Forecast plot for {period} days') 137 | fig1 = plot_plotly(m, forecast) 138 | if plot_log: 139 | fig1.update_yaxes(type="log") 140 | st.plotly_chart(fig1) 141 | 142 | st.subheader("Forecast components") 143 | fig2 = m.plot_components(forecast) 144 | st.write(fig2) --------------------------------------------------------------------------------