def range_volatility(ticker, components): # Parse and check: find components matching dates, ensure start and end are present, ensure dates are valid today, dates = current_date(), [] for each in components: if PATTERNS['valid_date'].match(each): dates.append(each) if len(dates)!=2: return {"message": Response.vol_required_dates(ticker)} for each in dates: if each > today: return {"message": Response.invalid_date(each)} try: date = datetime.datetime.strptime(each, '%Y-%m-%d') except ValueError: return {"message": Response.invalid_date(each)} # Volatility Calculation dates = sorted(dates) start, end = dates[0], dates[1] try: quotes = data.DataReader(ticker, 'google')['Close'].loc[start:end] if len(quotes) < 10: return {"message": Response.vol_range_size(ticker)} except Exception: return {"message": Response.data_notfound(ticker)} logreturns = np.log(quotes / quotes.shift(1)) vol = round(np.sqrt(252*logreturns.var()), 5) return {"message" : Response.range_vol(ticker, start, end, vol)}
def name_exchange(ticker, components): exchanges = {"NMS": "NASDAQ", "NGM": "NASDAQ", "NYQ":"NYSE"} try: info = data.get_components_yahoo(ticker) except Exception: return {"message": Response.data_notfound(ticker)} name, symbol = info['name'][0], info['exchange'][0] exchange = exchanges.get(symbol) if not exchange: exchange = symbol return {"message": Response.name_exchange_response(ticker, name, exchange)}
def trailing_volatility(ticker, components): days=None for each in components: if PATTERNS['tvol'].match(each): days = int(each) break if days==None: return {"message": Response.trailing_days(ticker)} try: quotes = data.DataReader(ticker, 'google')['Close'][-days:] except Exception: return {"message": Response.data_notfound(ticker)} logreturns = np.log(quotes / quotes.shift(1)) vol = round(np.sqrt(252*logreturns.var()), 5) return {"message" : Response.trailing_vol(days, ticker, vol)}
def historical_data(ticker, components): # Prices adjusted for splits today, dates = current_date(), [] for each in components: if PATTERNS['valid_date'].match(each): dates.append(each) if not dates: return {"message": Response.missing_dates(ticker)} # Validate dates for each in dates: if each > today: return {"message": Response.invalid_date(each)} try: date = datetime.datetime.strptime(each, '%Y-%m-%d') except ValueError: return {"message": Response.invalid_date(each)} # Validate ticker and fetch data try: quotes = data.get_data_google(ticker) except Exception: return {"message": Response.data_notfound(ticker)} # Return price data for one day if len(dates)==1: date = dates[0] try: quote = quotes.loc[date] except KeyError: return {"message": Response.no_data_for_date(date)} return {"message": Response.historical_price( ticker, date, quote['Open'], quote['High'], quote['Low'], quote['Close'], int(quote['Volume']))} # If 2 dates are entered, returned the range during the given period elif len(dates)==2: dates = sorted(dates) start, end = dates[0], dates[1] quotes = quotes.loc[start:end] high = round(quotes['High'].max(),2) low = round(quotes['Low'].min(),2) return {"message": Response.historical_range(ticker, start, end, high, low)} else: return {"message": Response.too_many_dates(ticker)}
def actions(ticker, components): # Splits are quoted as decimals - convert to fraction ('7 for 1' vs .142857) def split_ratio(dec): frac = Fraction.from_float(dec).limit_denominator(10) num, denom = frac.numerator, frac.denominator return "{} for {}".format(denom, num) try: actions = data.get_data_yahoo_actions(ticker) except Exception: return {"message": Response.data_notfound(ticker)} if len(actions)==0: return {"message": Response.no_actions(ticker)} actions.ix[actions.action=="SPLIT", 'value'] = actions.value.map(lambda x: split_ratio(x)) actions['action'] = actions.action.map(lambda x: x.lower()) actions.index = actions.index.map(lambda x: datetime.date(x.year, x.month, x.day).strftime('%Y-%m-%d')) actions.iloc[::-1] # Build message from DataFrame message = Response.list_actions(ticker) for date, action, value in zip(actions.index, actions.action, actions.value): message += ("\n{} - {} `{}`".format(date, action, value)) return {"message": message}