From 6c7c83e2bd176794bf7d4defe0d06c04ca1c61b0 Mon Sep 17 00:00:00 2001 From: Aleksey Kramer Date: Sat, 29 Nov 2014 18:20:36 -0800 Subject: [PATCH 1/6] updated --- Students/A.Kramer/session08/generator_solution.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Students/A.Kramer/session08/generator_solution.py b/Students/A.Kramer/session08/generator_solution.py index ae9aa2a4..0886b1de 100644 --- a/Students/A.Kramer/session08/generator_solution.py +++ b/Students/A.Kramer/session08/generator_solution.py @@ -38,10 +38,8 @@ def prime(): def __is_prime(n): if n < 2: return False - if n == 2: - return True # checking only odd numbers - for x in range(3, int(n**0.5)+1, 2): + for x in range(2, int(n**0.5)+1, 2): if n % x == 0: return False return True From a3ff46fa80da94e1f8c33ed08b05323ca6ed1dfb Mon Sep 17 00:00:00 2001 From: Aleksey Kramer Date: Wed, 3 Dec 2014 19:05:43 -0800 Subject: [PATCH 2/6] Added Final Project --- Students/A.Kramer/Final_Project/Chart.py | 176 ++++++++++++++++++ .../A.Kramer/Final_Project/DataFactory.py | 70 +++++++ Students/A.Kramer/Final_Project/README.txt | 26 +++ Students/A.Kramer/Final_Project/RunFinal.py | 29 +++ 4 files changed, 301 insertions(+) create mode 100644 Students/A.Kramer/Final_Project/Chart.py create mode 100644 Students/A.Kramer/Final_Project/DataFactory.py create mode 100644 Students/A.Kramer/Final_Project/README.txt create mode 100644 Students/A.Kramer/Final_Project/RunFinal.py diff --git a/Students/A.Kramer/Final_Project/Chart.py b/Students/A.Kramer/Final_Project/Chart.py new file mode 100644 index 00000000..4ee82ae6 --- /dev/null +++ b/Students/A.Kramer/Final_Project/Chart.py @@ -0,0 +1,176 @@ +''' +Created on Dec 3, 2014 + +@author: Aleksey Kramer +''' +import numpy as np +import matplotlib +import matplotlib.pyplot as plt +import matplotlib.ticker as mticker +import matplotlib.dates as mdates +from matplotlib.finance import candlestick +import pylab + +# adjusted font size for the plots +matplotlib.rcParams.update({"font.size": 10}) + + +# define RSI function +def rsiFunc(prices, n=14): + deltas = np.diff(prices) + seed = deltas[:n+1] + up = seed[seed >= 0].sum() / n + down = -seed[seed<0].sum() / n + rs = up/down + rsi = np.zeros_like(prices) + rsi[:n] = 100. - 100./(1. + rs) + for i in range(n, len(prices)): + delta = deltas[i-1] + if delta > 0: + upval = delta + downval = 0. + else: + upval = 0. + downval = -delta + up = (up * (n-1) +upval) / n + down = (down*(n-1) + downval) / n + rs = up/down + rsi[i] = 100. - 100. / (1. + rs) + return rsi + +# define moving average function +def movingaverage(values, window): + weights = np.repeat(1.0, window) / window + smas = np.convolve(values, weights, 'valid') + return smas # numpy array + +def graphData(stock, MA1=12, MA2=26): + try: + # define the data file + stockFile = "./data/" + stock + ".txt" + + # Load data into numpy arrays + date, closep, highp, lowp, openp, volume = np.loadtxt(stockFile, delimiter=",", + unpack=True, converters = {0: mdates.strpdate2num("%Y%m%d")}) + + #----------------------------------------------------------------------------------------------- + # building data for drawing plotting candlestick chart. Basically, a an array of comma separated + # values. The order of elements is very specific, so check the documentation for candlestick + x = 0 + y = len(date) + candleArray = [] + while x < y: + # order of elements matters!!! - used for candlestick charting + appendLine = date[x], openp[x], closep[x], highp[x], lowp[x], volume[x] + candleArray.append(appendLine) + x += 1 + + # moving averages for 12 and 26 days + Av1 = movingaverage(closep, MA1) + Av2 = movingaverage(closep, MA2) + # Starting point for graphs + SP = len(date[MA2-1:]) + # Creating Moving Average labels + label1=str(MA1) + " SMA" + label2=str(MA2) + " SMA" + + + # changing the face color of the graphics + fig = plt.figure(facecolor="#07000D") + + # create room and plot candlestick chart + ax1 = plt.subplot2grid((5,4), (1,0), rowspan=4, colspan=4, axisbg="#07000D") + candlestick(ax1, candleArray[-SP:], width=0.75, colorup="#9EFF15", colordown="#FF1717") + # plot moving averages + ax1.plot(date[-SP:], Av1[-SP:], "#5998FF", label=label1, linewidth=1.5) + ax1.plot(date[-SP:], Av2[-SP:], "#E1EDF9", label=label2, linewidth=1.5) + # Set grid color to white + ax1.grid(True, color="white") + # Set number of tickers on x-axis + ax1.xaxis.set_major_locator(mticker.MaxNLocator(10)) + # Format date for presentation + ax1.xaxis.set_major_formatter(mdates.DateFormatter("%Y-%m-%d")) + # Change label and border colors + ax1.yaxis.label.set_color("white") + ax1.spines["bottom"].set_color("#5998FF") + ax1.spines["top"].set_color("#5998FF") + ax1.spines["left"].set_color("#5998FF") + ax1.spines["right"].set_color("#5998FF") + # Change tick color to white + ax1.tick_params(axis="y", colors="white") + ax1.tick_params(axis="x", colors="white") + plt.ylabel("Stock Price and Volume") + # display legend and set size of font to 7 + maLeg = plt.legend(loc=9, ncol=2, prop={"size":7}, fancybox=True) + # update label transparency + maLeg.get_frame().set_alpha(0.4) + textEd = pylab.gca().get_legend().get_texts() + # set label color + pylab.setp(textEd[0:5], color = "white") + # Tilt the labels to 45 degrees + for label in ax1.xaxis.get_ticklabels(): + label.set_rotation(45) + + + # set up RSI area + ax0 = plt.subplot2grid((5,4), (0,0), sharex=ax1, rowspan=1, colspan=4, axisbg="#07000d") + #plot RSI + rsi = rsiFunc(closep) + rsiCol = "#00FFE8" + ax0.plot(date[-SP:],rsi[-SP:], rsiCol, linewidth=1.5) + ax0.axhline(70, color = rsiCol) + ax0.axhline(30, color = rsiCol) + # color the spaces between the horizontal lines and the RSI line + ax0.fill_between(date[-SP:],rsi[-SP:], 70, where=(rsi[-SP:] >= 70), facecolor=rsiCol, edgecolor=rsiCol) + ax0.fill_between(date[-SP:],rsi[-SP:], 30, where=(rsi[-SP:] <= 30), facecolor=rsiCol, edgecolor=rsiCol) + # Change label and border colors + ax0.spines["bottom"].set_color("#5998FF") + ax0.spines["top"].set_color("#5998FF") + ax0.spines["left"].set_color("#5998FF") + ax0.spines["right"].set_color("#5998FF") + # Change tick color to white + ax0.tick_params(axis="x", colors="white") + ax0.tick_params(axis="y", colors="white") + ax0.set_yticks([30,70]) + ax0.yaxis.label.set_color("white") + plt.ylabel("RSI") + + + # Plot volume on the same range as ax1 + volumeMin = 0 + ax1v = ax1.twinx() + # subtract moving average calculations + ax1v.fill_between(date[-SP:], volumeMin, volume[-SP:], facecolor="#00FFE8", alpha=.5) + ax1v.axes.yaxis.set_ticklabels([]) + # hide grid + ax1v.grid(False) + # Change label and border colors + ax1v.spines["bottom"].set_color("#5998FF") + ax1v.spines["top"].set_color("#5998FF") + ax1v.spines["left"].set_color("#5998FF") + ax1v.spines["right"].set_color("#5998FF") + # update the height of the volume part + ax1v.set_ylim(0,3*volume.max()) + # Change axis color + ax1v.tick_params(axis="x", colors="white") + ax1v.tick_params(axis="y", colors="white") + + + # Setting up the overall appearance of the plot + plt.subplots_adjust(left=.08, bottom=.14, right=.95, top=.95, wspace=.20, hspace=0) + plt.suptitle(stock, color="white") + plt.setp(ax0.get_xticklabels(), visible=False) + plt.show() + fig.savefig("./data/" + stock + ".png", facecolor=fig.get_facecolor()) + + except Exception, e: + print "main loop", str(e) + +if __name__ == "__main__": + # testing the calls + # a list of stocks to process (for testing) + stocksToPull = 'AAPL', 'GOOG', 'AMZN', 'EBAY', 'CMG', 'MSFT', 'C', 'BA', 'TSLA' + + graphData(stocksToPull[3]) + + diff --git a/Students/A.Kramer/Final_Project/DataFactory.py b/Students/A.Kramer/Final_Project/DataFactory.py new file mode 100644 index 00000000..d76ae7d2 --- /dev/null +++ b/Students/A.Kramer/Final_Project/DataFactory.py @@ -0,0 +1,70 @@ +''' +Created on Nov 28, 2014 + +@author: Aleksey Kramer +''' +import os +import time +import urllib2 +import datetime + +def pullStockData(stock): + # check if data directory exists, if not, create + if not os.path.exists("./data"): + os.makedirs("./data") + + # print out the pull time + print "Pulling stock", stock, "\t", + print str(datetime.datetime.fromtimestamp(time.time()).strftime("%Y-%m-%d %H:%M:%S")) + + # define url and file + urlToVisit="http://chartapi.finance.yahoo.com/instrument/1.0/" + stock + "/chartdata;type=quote;range=1y/csv" + saveFileLine = stock + ".txt" + + # Determine the time of the last entry in the file, if file exists + # set the last Unix time to 0, if file dies not exist + try: + existingData = open("./data/" + saveFileLine, "r") + allLines = existingData.read(); + splitExisting = allLines.split("\n") + lastLine = splitExisting[-2] + lastUnix = int(lastLine.split(",")[0]) + existingData.close() + except Exception, e: + print "Pulling data: Determining last date", e + lastUnix = 0 + + # Obtain data for the ticket from Yahoo finance and split the file by new line + sourceCode = urllib2.urlopen(urlToVisit).read() + splitSource = sourceCode.split("\n") + + # Open file for writing and filter out the data to ensure that + # each line contains 6 entries separated by comma + # no 'visited' in the line + # and the timing in the entries for each record is greater than the last one already + # stored in existing file + saveFile = open("./data/" + saveFileLine, "a") + for eachLine in splitSource: + if "values" not in eachLine: + splitLine = eachLine.split(",") + if len(splitLine) == 6: + # assure we are only getting new data in the file + if int(splitLine[0]) > lastUnix: + lineToWrite = eachLine + "\n" + saveFile.write(lineToWrite) + saveFile.close() + + # Print out logging info and make program sleep for 1 second + print "Pulled Stock", stock + print "Sleeping....." + print str(datetime.datetime.fromtimestamp(time.time()).strftime("%Y-%m-%d %H:%M:%S")) + time.sleep(3) + + +# Pull the data for selected stocks +if __name__ == "__main__": + # Testing data pull + stocksToPull = 'AAPL', 'GOOG', 'AMZN', 'EBAY', 'CMG', 'MSFT', 'C', 'BA', 'TSLA' + pullStockData(stocksToPull[3]) + + \ No newline at end of file diff --git a/Students/A.Kramer/Final_Project/README.txt b/Students/A.Kramer/Final_Project/README.txt new file mode 100644 index 00000000..cbf4b2e1 --- /dev/null +++ b/Students/A.Kramer/Final_Project/README.txt @@ -0,0 +1,26 @@ +1. Libraries used in the code: + os + time + datetime + urllib2 + matplotlib + numpy + pylab + +2. To run the code, run RunFinal.py from command line. + Once prompted for an input, input the valid stock on the + prompt and hit ENTER key. Wait for several seconds. The + code is getting data from Yahoo Finance web services, + creates a 'data' directory in the directory from which + the script is run, saves the data file with the name of the + stock in the 'data' directory. + + After the data is saved, the code is graphing the data + on the screen. + + After the code is done with plotting, it saves the image + of the plot in the data directory with the name of the + stock in .png format. + + The logs and warnings displayed are just for logging and + verification of the output. \ No newline at end of file diff --git a/Students/A.Kramer/Final_Project/RunFinal.py b/Students/A.Kramer/Final_Project/RunFinal.py new file mode 100644 index 00000000..2b27310e --- /dev/null +++ b/Students/A.Kramer/Final_Project/RunFinal.py @@ -0,0 +1,29 @@ +''' +Created on Dec 3, 2014 + + The code pulls one year worth of data for the stock of your choice + and graphs the data using matplotlib, displaying candlestick chart, + simple moving averages for 12 and 26 days (default), and a Relative + Strength Index (RSI) for selected stock. + + I found an excellent video tutorial on financial graphing with python + that shows how to use matplotlib, change parameters of the plots + and to do math calculation to derive moving averages and RSI indexes. + The tutorial can be found on this web site: http://sentdex.com/ + This is excellent source to learn charting with matplotlib + +@author: Aleksey Kramer +''' +from Chart import graphData +from DataFactory import pullStockData + +def runCode(): + ''' Execute code for final project ''' + answer = raw_input("Enter The stock to graph: ") + pullStockData(answer.upper().strip()) + graphData(answer.upper().strip()) + +# run main program +if __name__ == "__main__": + runCode() + \ No newline at end of file From 2d3cae56e0d2d11572ed4dbb3ce283640ff31fd6 Mon Sep 17 00:00:00 2001 From: voite1 Date: Wed, 3 Dec 2014 19:07:59 -0800 Subject: [PATCH 3/6] Updated content --- Students/A.Kramer/Final_Project/README.txt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Students/A.Kramer/Final_Project/README.txt b/Students/A.Kramer/Final_Project/README.txt index cbf4b2e1..f06dee89 100644 --- a/Students/A.Kramer/Final_Project/README.txt +++ b/Students/A.Kramer/Final_Project/README.txt @@ -1,7 +1,7 @@ 1. Libraries used in the code: os - time - datetime + time + datetime urllib2 matplotlib numpy @@ -15,12 +15,12 @@ the script is run, saves the data file with the name of the stock in the 'data' directory. - After the data is saved, the code is graphing the data - on the screen. + After the data is saved, the code is plotting the data + to the screen. After the code is done with plotting, it saves the image of the plot in the data directory with the name of the stock in .png format. The logs and warnings displayed are just for logging and - verification of the output. \ No newline at end of file + verification of the output. From de7ff16144b9527f3a528efe2b45bfb48ef8ba70 Mon Sep 17 00:00:00 2001 From: Aleksey Kramer Date: Mon, 8 Dec 2014 19:09:47 -0800 Subject: [PATCH 4/6] Added Week 9 notes --- ... Every About Unicode and Character Sets.pdf | Bin 0 -> 246714 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 Students/A.Kramer/session09/The Absolute Minimum Every About Unicode and Character Sets.pdf diff --git a/Students/A.Kramer/session09/The Absolute Minimum Every About Unicode and Character Sets.pdf b/Students/A.Kramer/session09/The Absolute Minimum Every About Unicode and Character Sets.pdf new file mode 100644 index 0000000000000000000000000000000000000000..8e24354b5e558e090bf1395a26609523c016357e GIT binary patch literal 246714 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