Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add function “get_crypto_visuals” to timeseries.py #70

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
173 changes: 170 additions & 3 deletions datasist/timeseries.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import random
import yfinance as yf
from plotly import graph_objs as go
import seaborn as sns
from IPython.display import display
from IPython.display import display, Image
from .structdata import get_cat_feats, get_num_feats, get_date_cols


Expand Down Expand Up @@ -226,7 +229,7 @@ def get_period_of_day(date_col=None):
raise ValueError("date_cols: Expect a date columns, got 'None'")


if date_col.dtype != np.int:
if date_col.dtype != np.int64:

date_col_hr = pd.to_datetime(date_col).dt.hour
return date_col_hr.map(_map_hours)
Expand Down Expand Up @@ -388,4 +391,168 @@ def _map_hours(x):
elif x in [13,14,15,16]:
return 'afternoon'
else:
return 'evening'
return 'evening'


def get_crypto_visuals(coin, period="5d", interval="15m", MA=False, days=[7,25,99], boll=False, boll_sma=25, save_fig=False, img_format="png"):




'''

Utilizing Plotly and yfinance to make a Stock Market Coin-USD timeseries plot using Candlesticks



Parameters
-----------------

coin: str

- Symbol of Crypto coin i.e 'BTC', 'ETH', 'DOGE', 'BNB', 'SXP'
- Must be currently listed on https://finance.yahoo.com/cryptocurrencies/


period: str, Default "5d"

- Answers the question - How far back from realtime should data be sourced?
- Valid periods: '1d','5d','1mo','3mo','6mo','1y','2y','5y','10y','ytd','max'


interval: str, Default "15m"

- References intra-period intervals of data
- Valid intervals: '1m','2m','5m','15m','30m','60m','90m','1h','1d','5d','1wk','1mo','3mo'
- Intraday data cannot extend last 60 days


MA: bool, Default False

- References the plotting of the Moving Average (MA) data



days: list, tuple, 1D array, Pandas Series, Set, Default = [7, 25, 99]

- Must be an iterable containing integer values only
- The integers represent, day subsets for the Moving Average data


boll: bool, Default False

- References the plotting of the bollinger band
- Important: • When both MA and boll are True, MA takes preference
• The above algorithm is in place to avoid a rowdy chart

boll_sma: Integer, Default 25

- Indicates the SMA value used as a reference point for plotting the bollinger band


save_fig: bool, Default False

- Saves the plot to the current working directory


img_format: str, Default "png"
- The desired image format:'png', 'jpg' or 'jpeg', 'webp', 'svg', and 'pdf'




Returns
-----------------
None


Examples of valid use
-----------------
>>> get_crypto_visuals("BTC")
>>> get_crypto_visuals("BTC", MA=True)
>>> get_crypto_visuals("BTC", period="10d", interval="5m", MA=True, days=[10,30,100], save_fig=True, img_format='jpeg')
>>> get_crypto_visuals("BTC", period="10d", interval="5m", MA=False, days=[10,30,100], boll=True)

'''

#Error Handling
if coin is None: raise ValueError("coin: Symbol of Crypto coin i.e 'BTC', 'ETH', 'DOGE', 'BNB', 'SXP'\nMust be currently listed on https://finance.yahoo.com/cryptocurrencies/")
if not isinstance(period, str): raise TypeError('period: This parameter should be a string')
if not isinstance(interval, str): raise TypeError('interval: This parameter should be a string')
if not isinstance(img_format, str): raise TypeError('img_format: This parameter should be a string')
if not isinstance(coin, str): raise TypeError('coin: This parameter should be a string')
if not isinstance(MA, bool): raise TypeError('MA: This parameter should be boolean (True or False)')
if not isinstance(boll, bool): raise TypeError('boll: This parameter should be boolean (True or False)')
if not isinstance(save_fig, bool): raise TypeError('save_fig: This parameter should be boolean (True or False)')
if not isinstance(boll_sma, int): raise TypeError('boll_sma: This parameter should be an Integer')
if (not hasattr(days, '__iter__')) or isinstance(days, str): raise TypeError("days: This parameter should be iterable, strings aren't also allowed")





coin = coin.upper().strip()
data = yf.download(tickers=f'{coin}-USD',period = period, interval = interval)
header = f"{coin}-USD Price Analysis"


#Generate Moving Average
if MA==True:
for i in days: data[f'MA{i}'] = data['Close'].rolling(i).mean()


#Generate Bollinger
def get_bollinger_band(prices, rate=boll_sma):
sma = prices.rolling(rate).mean()
std = prices.rolling(rate).std()
bollinger_up = sma + std * 2
bollinger_down = sma - std * 2
return sma, bollinger_up, bollinger_down

if boll:
if not (MA or (boll and MA)): sma, u,d = get_bollinger_band(data['Close'])

#declare figure
fig = go.Figure()


#Candlestick
fig.add_trace(go.Candlestick(x=data.index,
open=data['Open'],
high=data['High'],
low=data['Low'],
close=data['Close'],
name = 'Market data'))
#Randomly pick from preferred colors
col_lst = ['pink','darkgray','orange','darkblue','darkcyan','darkgoldenrod','darkgray','darkgrey','darkkhaki','darkmagenta','darkorange','darkorchid','darksalmon','darkslateblue','darkslategray','darkslategrey','darkturquoise','darkviolet','deeppink']
try: col_sam = random.sample(col_lst, len(days))
except ValueError: col_sam = np.random.choice(col_lst, len(days))


#Add Moving average on the chart
co = 0
for col in data.columns:
if col.startswith('MA'):
fig.add_trace(go.Scatter(x=data.index, y= data[col],line={'color':col_sam[co],'width':1.5}, name = col))
co+=1

#Add Bollinger on the chart
if boll:
if not (MA or (boll and MA)):
fig.add_trace(go.Scatter(x=data.index, y= u,line={'color':'darkmagenta','width':1.5}, name = "BOLL (Up)"))
fig.add_trace(go.Scatter(x=data.index, y=sma, line={'color':'orange','width':1.5}, name="BOLL (Mid)"))
fig.add_trace(go.Scatter(x=data.index, y= d,line={'color':'darkblue','width':1.5}, name = "BOLL (Down)"))


#Updating axis and graph
fig.update_xaxes(title=f'Datetime', rangeslider_visible =True)

fig.update_yaxes(title='USD ($)')
fig.update_layout({"title": {"text": header}})

#Show
fig.show()


#Save
if save_fig: fig.write_image("fig_timeplot_{}-usd.{}".format(coin.lower(), img_format.lower()), engine='kaleido')
7 changes: 5 additions & 2 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ jupyter==1.0.0
jupyter-client==6.1.3
jupyter-console==6.1.0
jupyter-core==4.6.3
kaleido==0.2.1
kiwisolver==1.2.0
MarkupSafe==1.1.1
matplotlib==3.2.2
Expand All @@ -36,16 +37,17 @@ pandocfilters==1.4.2
parso==0.7.0
pexpect==4.8.0
pickleshare==0.7.5
plotly==0.5.0
pluggy==0.13.1
ppscore==0.0.3
ppscore==1.2.0
prometheus-client==0.8.0
prompt-toolkit==3.0.5
ptyprocess==0.6.0
py==1.10.0
Pygments==2.7.4
pyparsing==2.4.7
pyrsistent==0.16.0
pytest==5.4.3
pytest==6.2.4
python-dateutil==2.8.1
pytz==2020.1
pyzmq==19.0.1
Expand All @@ -66,4 +68,5 @@ traitlets==4.3.3
wcwidth==0.2.5
webencodings==0.5.1
widgetsnbextension==3.5.1
yfinance==0.1.63
zipp==3.1.0