User Tools

Site Tools


echo_stock_price

This is an old revision of the document!


Alexa Custom Skill - Stock Prices

—————————————————————————————————————————–

Author: Tristan Brodeur Email: [email protected] Date: Last modified on 01/16/17 Keywords: Alexa, Amazon Skills Kit

—————————————————————————————————————————–

Overview

—————————————————————————————————————————–

1. Create a Lambda Function

To create a lambda function, follow this tutorial: Creating a lambda function

—————————————————————————————————————————–

2. Add the code

The code below is commented out in order to provide you with a better understanding

index.py
import requests
from bs4 import BeautifulSoup
'''
Amazon alexa skill to grab stock data from yahoo finance and present data to user
Currently has database of ~10 companies
Future updates to include database of all S&P 500 companies if data size allows
'''
##################################################################
def lambda_handler(event, context):
	#Checks to make sure application id is same as alexa skill (links)
	if (event['session']['application']['applicationId'] !=
		#Change to application id listed under your alexa skill in the developer portal
		"amzn1.ask.skill.XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"):
		raise ValueError("Invalid Application ID")
 
	if event["session"]["new"]:
		on_session_started({"requestId": event["request"]["requestId"]}, event["session"])
		#check event types and call appropriate response
		if event["request"]["type"] == "LaunchRequest":
			return on_launch(event["request"], event["session"])
		elif event["request"]["type"] == "IntentRequest":
			return on_intent(event["request"], event["session"])
		elif event["request"]["type"] == "SessionEndedRequest":
			return on_session_ended(event["request"], event["session"])
##################################################################
def on_session_started(session_started_request, session):
	print "Starting new."
##################################################################
def on_launch(launch_request, session):
	return get_welcome_response()
##################################################################
def on_intent(intent_request, session):
	intent = intent_request["intent"]
	intent_name = intent_request["intent"]["name"]
 
	if intent_name == "GetCurrentPrice":
		return get_current_price(intent)
	elif intent_name == "GetHigh":
		return get_high(intent)
	elif intent_name == "GetLow":
		return get_low(intent)
	elif intent_name == "AMAZON.HelpIntent":
		return get_welcome_response()
	elif intent_name == "AMAZON.CancelIntent" or intent_name == "AMAZON.StopIntent":
		return handle_session_end_request()
	else:
		raise ValueError("Invalid intent")
##################################################################
def on_session_ended(session_ended_request, session):
	print "Ending session."
##################################################################
def handle_session_end_request():
	card_title = "Stocker"
	speech_output = "Im sorry dave. Im afraid I cant do that."
	should_end_session = True
	return build_response({}, build_speechlet_response(card_title, speech_output, None, should_end_session))
##################################################################
def get_welcome_response():
	#Response to user invoking stock app without parameters/intents
	session_attributes = {}
	card_title = "Stocker"
	speech_output = "Welcome to the Stocker skill. " \
	 	"You can ask me for current stock prices, or " \
	 	"ask me about stock highs and lows."
	reprompt_text = "Please ask me for stock prices, " \
		"for example Apple stock price."
	should_end_session = False
	return build_response(session_attributes, build_speechlet_response(
        card_title, speech_output, reprompt_text, should_end_session))
 
##################################################################
def find_availability(to_find, restaurant):
	page = requests.get("")
	page_data = BeautifulSoup(page.content, "html.parser")
 
 
##################################################################
def grab_data(to_find, ticker_code):
 
	if ticker_code != "EVRGRN":
		#send http response fro yahoo finance to grab data based on passed in ticker code
		page = requests.get("https://finance.yahoo.com/quote/" + ticker_code + "?p=" + ticker_code)
		#resolves the page content into its component parts
		data = BeautifulSoup(page.content, "html.parser")
 
		if to_find == "get_current_price":
			#grab text from appropriate class and return to current object
			current = data.find(class_ = "Fw(b) Fz(36px) Mb(-4px)").get_text()
			#find index of decimal point to seperate dollars from cents
			index = current.index('.')
			dollars = current[:index]
			cents =  current[index+1:]
			#map each component in list to a string object, and join via str operator (in this case nothing, so it joins together)
			dollars = ''.join(map(str, dollars))
			cents = ''.join(map(str, cents))
			return dollars + " dollars and " + cents + " cents"
 
		elif to_find == "get_high" or to_find =="get_low":
			classes= data.find_all(class_ = "Ta(end) Fw(b)")
			#several stock values are listed under the class with the given value, so
			#we grab fourth object in list of classes, returning stock range
			stock_range = list(classes[4].get_text())
			#since text we grab is not in unicode, we grab each str object and encode it with UTF8
			stock_range = [x.encode('UTF8') for x in stock_range]
			if to_find == "get_high":
				high = ""
				for letter in stock_range:
					#since returned list of str objects are a range from low to high (e.g. $$ - $$), we grab second half of data for high value
					if letter == '-':
						high = stock_range[stock_range.index(letter)+2:]
						index = high.index('.')
						dollars = high[:index]
						cents =  high[index+1:]
						#map each component in list to a string object, and join via str operator (in this case nothing, so it joins together)
						dollars = ''.join(map(str, dollars))
						cents = ''.join(map(str, cents))
						return dollars + " dollars and" + cents + " cents"
			elif to_find == "get_low":
				low = ""
				for letter in stock_range:
					#since returned list of str objects are a range from high to low (e.g. $$-$$), we grab first half of data for low value
					if letter == '-':
						low = stock_range[:stock_range.index(letter)-1]
						index = low.index('.')
						dollars = low[:index]
						cents =  low[index+1:]
						#map each component in list to a string object, and join via str operator (in this case nothing, so it joins together)
						dollars = ''.join(map(str, dollars))
						cents = ''.join(map(str, cents))
						return dollars + " dollars and " + cents + " cents"
	#cor is on its way
	else:
		if to_find == "get_current_price":
			return "over 9000"
		elif to_find == "get_high" or to_find =="get_low":
			return "not yet available. Please ask Tristan"
##################################################################
def get_current_price(intent):
	session_attributes = {}
	card_title = "Current Stock Price"
	speech_output = "I'm not sure which company you wanted stock prices for. " \
                    "Please try again."
	reprompt_text = "I'm not sure which company you wanted stock prices for. " \
                    "Please try again."
	should_end_session = False
 
	if "Ticker" in intent["slots"]:
    		ticker_name = intent["slots"]["Ticker"]["value"]
    		#grab appropriate value based on name from ticke code dict
        	ticker_code = get_ticker_code(ticker_name.lower())
 
      	if (ticker_code != "unkn"):
      		card_title = "Current price for  " + ticker_name.title()
      		price = grab_data(get_current_price.__name__, ticker_code)
      		speech_output = "Current price for  " + ticker_name + " is: " + price
      		reprompt_text = ""
      		should_end_session = True
 
	return build_response(session_attributes, build_speechlet_response(
        	card_title, speech_output, reprompt_text, should_end_session))
##################################################################
def get_high(intent):
	session_attributes = {}
	card_title = "Stock High"
	speech_output = "I'm not sure which company you wanted stock prices for. " \
                    "Please try again."
	reprompt_text = "I'm not sure which company you wanted stock prices for. " \
                    "Please try again."
	should_end_session = False
 
	if "Ticker" in intent["slots"]:
    		ticker_name = intent["slots"]["Ticker"]["value"]
    		#grab appropriate value based on name from ticke code dict
        	ticker_code = get_ticker_code(ticker_name.lower())
 
      	if (ticker_code != "unkn"):
      		card_title = "High price for  " + ticker_name.title()
      		price = grab_data(get_high.__name__, ticker_code)
      		speech_output = "Stock high for " + ticker_name +  " is: " + price
      		reprompt_text = ""
      		should_end_session = True
 
	return build_response(session_attributes, build_speechlet_response(
        	card_title, speech_output, reprompt_text, should_end_session))			
##################################################################
def get_low(intent):
	session_attributes = {}
	card_title = "Stock Low"
	speech_output = "I'm not sure which company you wanted stock prices for. " \
			"Please try again."
	reprompt_text = "I'm not sure which company you wanted stock prices for. " \
			"Please try again."
	should_end_session = False
 
	if "Ticker" in intent["slots"]:
		ticker_name = intent["slots"]["Ticker"]["value"]
		#grab appropriate value based on name from ticke code dict
		ticker_code = get_ticker_code(ticker_name.lower())
 
		if (ticker_code != "unkn"):
			card_title = "Low price for  " + ticker_name.title()
      		price = grab_data(get_low.__name__, ticker_code)
      		speech_output = "Stock low for " + ticker_name + " is: " + price
      		reprompt_text = ""
      		should_end_session = True
 
	return build_response(session_attributes, build_speechlet_response(
      	card_title, speech_output, reprompt_text, should_end_session))
##################################################################
def build_speechlet_response(title, output, reprompt_text, should_end_session):
	#return data in json format to alexa skills kit
	return {
		"outputSpeech": {
     			"type": "PlainText",
     			"text": output
     		},
     		"card": {
     			"type": "Simple",
     			"title": title,
     			"content": output
     		},
     		"reprompt": {
     			"outputSpeech": {
     				"type": "PlainText",
     				"text": reprompt_text
     			}
     		},
     		"shouldEndSession": should_end_session
     	}
##################################################################
def get_ticker_code(ticker_name):
	#function to grab associated value based on ticker_name parameter
	return{
		'alphabet': 'GOOGL', 
		'apple': 'AAPL',
		'amazon':'AMZN', 
		'tesla':'TSLA', 
		'oracle':'ORCL', 
		'irobot':'IRBT',
		'microsoft':'MSFT', 
		'facebook':'FB',
		'intel':'INTC',
		'ibm':'IBM', 
		'evergreen robotics': 'EVRGRN',
		'netflix':'NFLX'
	}.get(ticker_name, "unkn")
##################################################################
def build_response(session_attributes, speechlet_response):
	return {
		"version": "1.0",
		"sessionAttributes": session_attributes,
		"response": speechlet_response
}		

Make sure to change the application id listed in lambda_handler() to your own id once you create the Alexa Skill with Alexa Skills Kit

—————————————————————————————————————————–

After the code is added, configure your lambda function with the Alexa Skills Kit.

echo_stock_price.1496188030.txt.gz · Last modified: 2017/05/30 16:47 by tbrodeur