Today I decided to create a library of “get” calls that would convert the json string from my previous post into individual Pandas Series. In each Series the index is the date and the data is the data specified in the name of the library function. I named the library alphavantage.py.
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Mon Apr 8 06:23:22 2019
@author: Tom
"""
import pandas as pd
#
# getValueDict( j, which_value )
# Arguments:
# j - json strong returned from alphavantage query as a price history
# which_value - specific value to return.
# Return:
# Pandas Series where the indexes are date strings and the elements
# are floating point values
def getValueDict( j, which_value ):
# Ignoring the Metadata contained in the json string for now
all_daily = j['Time Series (Daily)']
# each element in the all_daily dictionary contains a key and a dictionary
# values is the name of this particular dictionary. It has keys that
# represent open, close, high, low and volume
for date,values in all_daily.items():
# adding one element at a time to the final Series
for key,value in values.items():
# the argument passed in determines which Series to obtain
if key == which_value:
# the values are type string, we need float
data = float(value)
# if the Series already exists then append this value to it
try:
new_price = pd.Series( data, index=[date] )
prices = prices.append( new_price )
# if the Series does not exist create it
except NameError:
prices = pd.Series( data, index=[date] )
return prices
def getOpeningPrices( j ):
return getValueDict( j, '1. open' )
def getClosingPrices( j ):
return getValueDict( j, '4. close' )
def getHighPrices( j ):
return getValueDict( j, '2. high' )
def getLowPrices( j ):
return getValueDict( j, '3. low' )
def getVolume( j ):
return getValueDict( j, '5. volume' )
Rewriting the original script using the new library required scaling down to a Series from a DataFrame. I also decided to use the date as the index, which required some customization.
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Sun Apr 7 07:11:46 2019
@author: Tom
Obtain the last 100 days of stock market data on the ticker symbol SPY
and compute the change in price from close to close. Then eliminate the
days that are not options expiration days and build a 7 bin histogram
"""
import requests # Necessary to get information from the url
import pandas as pd # Sexy dataframe objects
import numpy as np # Numerical recipes
import seaborn as sns # Sweet plotting package
import alphavantage as av # My personal alphavantage library
from scipy.stats import norm # Just me drawing a superimposed normal curve
# A little warning here, this is just to prove that indeed the data is not
# normal. I do not expect it to behave as a normal distribution over the period
# in question. I only go back 100 days because that is what the compact size
# gets you but also anything before that is unlikely to mean much.
# Get your own API KEY from the website
API_KEY = 'GETYOUROWN'
ticker = 'SPY'
url = 'https://www.alphavantage.co/'
query = 'query?function=TIME_SERIES_DAILY'
symbol = 'symbol=' + ticker
outputsize = 'outputsize=compact'
# Compile the request string. I broke this apart because I believe in the
# future I will want to use other queries.
request = url + query + '&' + symbol + '&' + outputsize + '&' + 'apikey='
# Get 100 days of data
full = requests.get(request + API_KEY)
# Convert the json data into a pandas dataframe
s = av.getClosingPrices( full.json() )
# Compute the change in price from previous close to this close.
day_to_day = pd.Series( [s[n] - s[n-1] for n in range(1,len(s) )], s.index[1:len(s)] )
# Utility lists to make the logic below understandable
days_of_week = ['Monday','Tuesday','Wednesday','Thursday','Friday', 'Saturday','Sunday']
options_exp = ['Monday','Wednesday','Friday']
# Determine list of days that are not options expiration days to delete from the mix
for i in range(0,len(day_to_day)-1):
if days_of_week[pd.to_datetime( day_to_day.index[i] ).dayofweek] not in options_exp:
try:
deles.append(day_to_day.index[i])
except NameError:
deles = day_to_day.index[i]
# Obtain a Series of all changes that occurred from the previous close to the
# end of the next options expirations day
options_day_to_day = day_to_day.drop( index=deles )
# Get histogram data
bins = np.histogram( options_day_to_day, bins = 7 )
sns.set(color_codes=True)
# Plot the histogram
ax = sns.distplot( options_day_to_day, fit=norm, bins = 7, kde=False, color="g" )
# Print out the number of elements in each bin
print( bins[0] )
# Print out the edges of the bins
print( bins[1] )
Again running the program using the latest information as of today we can obtain the histogram and the edges of the bins as before.

3.08142857 6.06571429 9.05 ]
The left edge of bin 4 is -2.89 and the right edge of bin 5 is 3.08. The closing price today was 288.21. Let’s look at selling a call at 288.21+3.08 rounded to the nearest 50 cents which would be 291.50. Then we sell a put at 288.21 – 2.89 rounded to the nearest 50 cents which would be 285.50. Currently my Robinhood App is not reporting options prices for tomorrow so we will go with those reported on Yahoo Finance. Unfortunately they do not report prices broken down in 50 cent increments that far away from the current asking price of the underlying security. So we will use the put at 286 and the call at 291. This makes the sale price .08 and .02 for a total of .10. Since a contract is for a hundred shares the maximum we can make on this spread is $10.
