├── .gitignore ├── LICENSE ├── README.txt └── Stocks.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | 5 | # C extensions 6 | *.so 7 | 8 | # Distribution / packaging 9 | .Python 10 | env/ 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | *.egg-info/ 23 | .installed.cfg 24 | *.egg 25 | 26 | # PyInstaller 27 | # Usually these files are written by a python script from a template 28 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 29 | *.manifest 30 | *.spec 31 | 32 | # Installer logs 33 | pip-log.txt 34 | pip-delete-this-directory.txt 35 | 36 | # Unit test / coverage reports 37 | htmlcov/ 38 | .tox/ 39 | .coverage 40 | .coverage.* 41 | .cache 42 | nosetests.xml 43 | coverage.xml 44 | *,cover 45 | 46 | # Translations 47 | *.mo 48 | *.pot 49 | 50 | # Django stuff: 51 | *.log 52 | 53 | # Sphinx documentation 54 | docs/_build/ 55 | 56 | # PyBuilder 57 | target/ 58 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Robbie Barrat 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.txt: -------------------------------------------------------------------------------- 1 | # Stock_advisor 2 | Written in python 2.7, this program uses the Yahoo_finance api for python to get stock-related info about a company the user inputs, and then looks at how the company's stock has been doing to give the user advice on whether they should buy some of that company or not. 3 | This program requires the following modules: 4 | yahoo_finance (https://pypi.python.org/pypi/yahoo-finance/1.2.1) 5 | arrow (https://pypi.python.org/pypi/arrow) 6 | datetime (included with python) 7 | 8 | The input/output is pretty self explanatory: 9 | ------------------------------- 10 | Enter the abbreviation of the company you'd like to look into, for example, 'Google' would be 'GOOGL' 11 | Company Abbreviation: GOOGL 12 | Thank you, please wait a minute while the data for your company is being retrieved... 13 | This morning, it opened for $560.01, and right now is at $571.73. 14 | Since this morning, the price has risen by $11.72 15 | 16 | Would you like some info about what the stock has been like in the past few days? Yes/No: yes 17 | Okay, please wait a moment 18 | Analyzing data from the past few days... 19 | Today's price: 571.73 20 | Yesterday's price: None 21 | Two days ago's price: None 22 | Three days ago's price: 556.109985 23 | Five days ago's price: 541.700012 24 | One week ago's price: 545.619995 25 | Fifty day moving average: 550.05 26 | Two hundred day moving average: 545.31 27 | 28 | In the past week, the stock has been moving upwards in price. 29 | The fifty day average is greater than the two hundred day average, which signifies a longer term upwards trend. 30 | This stock looks like it is doing very well right now! I would invest in it! 31 | 32 | Alright, goodbye! 33 | Press the 'return' or 'enter' key to exit... 34 | ------------------------------- 35 | The 'Yesterday's price' and 'Two days ago's price' say "None" because I did this on a Monday, and the stock market is closed over the weekend. 36 | 37 | Also, by using this program you agree to take full responsibility if you lose any money by following this program's advice. I never said that the advice it gives would be accurate, so don't sue me if you invest all your money in the stocks it recomends and then lose your house. 38 | -------------------------------------------------------------------------------- /Stocks.py: -------------------------------------------------------------------------------- 1 | __author__ = 'Robbie Barrat' 2 | # I need the datetime module for telling the current date when I compare todays stock values to 5 days ago and such. 3 | import datetime 4 | # Yahoo Finance V. 1.1.4 5 | from yahoo_finance import Share 6 | # Arrow -- replaced the old date module 7 | import arrow 8 | 9 | 10 | # Checks to see if it is currently the weekend, and displays a message if so (since the stock market only operates on weekdays) 11 | def weekend(): 12 | if datetime.datetime.today().weekday() == 6: 13 | print "Hey, according to your computer it is Sunday, so the stock market is closed today." 14 | print "The data you see will be from the last time the stock market was opened." 15 | elif datetime.datetime.today().weekday() == 5: 16 | print "Hey, according to your computer it is Saturday, so the stock market is closed today." 17 | print "The data you see will be from the last time the stock market was opened." 18 | 19 | 20 | # Just a nice greeting message# 21 | def greeting(): 22 | print "Enter the abbreviation of the company you'd like to look into, for example, 'Google' would be 'GOOGL'" 23 | takeinput() 24 | 25 | 26 | # Here is the function that actually takes input # 27 | def takeinput(): 28 | company = raw_input("Company Abbreviation: ") 29 | if company == "": 30 | print "You need to enter a company name, buddy." 31 | takeinput() 32 | elif company.isalpha() == False: 33 | print "Try to keep it all letters, no numbers, spaces or symbols allowed." 34 | takeinput() 35 | elif not Share(str(company)).get_price(): 36 | print "That isn't a valid company, pal." 37 | takeinput() 38 | else: 39 | print "Thank you, please wait a minute while the data for your company is being retrieved..." 40 | # the reason there are two variables for this (companyname and company) is because there were some issues with the program 41 | # using a bad input, so companyname is defined only if the input is correct and accepted. 42 | companyname = company 43 | recentdata(companyname) 44 | 45 | 46 | # This function just gives some quick data about how the stock has been doing today. # 47 | def recentdata(companyname): 48 | try: 49 | companydata = Share(companyname) 50 | print "This morning, it opened for $" + companydata.get_open() + ", and right now is at $" + companydata.get_price() + "." 51 | if companydata.get_open() > companydata.get_price(): 52 | difference = float(companydata.get_open()) - float(companydata.get_price()) 53 | if len(str(difference)) < 3: 54 | print "Since this morning, the price has fallen by $" + str(difference) + "0" 55 | else: 56 | print "Since this morning, the price has fallen by $" + str(difference) 57 | elif companydata.get_open() < companydata.get_price(): 58 | difference = float(companydata.get_price()) - float(companydata.get_open()) 59 | if len(str(difference)) < 3: 60 | print "Since this morning, the price has risen by $" + str(difference) + "0" 61 | else: 62 | print "Since this morning, the price has risen by $" + str(difference) 63 | print "" 64 | selection = raw_input( 65 | "Would you like some info about what the stock has been like in the past few days? Yes/No: ") 66 | if str.lower(selection) == "no": 67 | end() 68 | elif str.lower(selection) == "yes": 69 | print "Okay, please wait a moment" 70 | except (RuntimeError, TypeError, NameError): 71 | print "Whoops, something went wrong there. Are you sure you entered a valid company abbreviation?" 72 | 73 | finally: 74 | longterm(companyname) 75 | 76 | 77 | def longterm(companyname): 78 | currentdate = arrow.utcnow() 79 | onedayago = currentdate.replace(days=-1).format('YYYY-MM-DD') 80 | twodaysago = currentdate.replace(days=-2).format('YYYY-MM-DD') 81 | threedaysago = currentdate.replace(days=-3).format('YYYY-MM-DD') 82 | fivedaysago = currentdate.replace(days=-5).format('YYYY-MM-DD') 83 | oneweekago = currentdate.replace(days=-7).format('YYYY-MM-DD') 84 | combine(onedayago, twodaysago, threedaysago, fivedaysago, oneweekago, companyname) 85 | 86 | 87 | # All this function does is put the data into a format that the yahoo_finance module can easily read. 88 | def combine(onedayago, twodaysago, threedaysago, fivedaysago, oneweekago, companyname): 89 | print "Analyzing data from the past few days..." 90 | dates = [onedayago, twodaysago, threedaysago, fivedaysago, oneweekago] 91 | for i in dates: 92 | i == i.format('YYYY-MM-DD') 93 | 94 | 95 | # Just gets the info and puts it into programmer friendly names 96 | def getclosing(date, company): 97 | # Thanks to stackoverflow user 'TessellatingHeckler' for helping me out with this next function! At the time dictionaries were a foreign concept to me. 98 | readings = company.get_historical(date, date) 99 | for reading in readings: 100 | close = reading['Close'] 101 | return close 102 | 103 | company = Share(companyname) 104 | closingonedayago = getclosing(str(dates[0]), company) 105 | closingtwodaysago = getclosing(str(dates[1]), company) 106 | closingthreedaysago = getclosing(str(dates[2]), company) 107 | closingfivedaysago = getclosing(str(dates[3]), company) 108 | closingoneweekago = getclosing(str(dates[4]), company) 109 | twohundredavg = company.get_200day_moving_avg() 110 | fiftyavg = company.get_50day_moving_avg() 111 | today = company.get_price() 112 | decision(today, closingonedayago, closingtwodaysago, closingthreedaysago, closingfivedaysago, closingoneweekago, twohundredavg, fiftyavg) 113 | 114 | 115 | # All this does is get information, display it in a readable fasion, and then determine based on short term and long term 116 | # data if the stock is worth investing in. It uses a system of points (titled positive and negative), which it ads up 117 | # and uses to determine if the stock is overall 'good' or 'bad'. If you don't understand just look at the code. 118 | def decision(today, oneday, twoday, threeday, fiveday, oneweek, twohundredavg, fiftyavg): 119 | # The 'negative' and 'positive' values will act like a score, and in the end will be used to determine an 'overall' score of good or bad. 120 | negative = 0 121 | positive = 0 122 | print "Today's price: " + str(today) 123 | print "Yesterday's price: " + str(oneday) 124 | print "Two days ago's price: " + str(twoday) 125 | print "Three days ago's price: " + str(threeday) 126 | print "Five days ago's price: " + str(fiveday) 127 | print "One week ago's price: " + str(oneweek) 128 | print "Fifty day moving average: " + str(fiftyavg) 129 | print "Two hundred day moving average: " + str(twohundredavg) 130 | print "" 131 | 132 | # These are just for doing short term stuff. Longer term stuff (50 and 200 day moving averages) comes 20 lines later 133 | prices = filter(None, [oneweek, fiveday, threeday]) 134 | recentprices = filter(None, [twoday, oneday, today]) 135 | 136 | pricenumber = 0 137 | recentpricenumber = 0 138 | 139 | for i in prices: 140 | pricenumber += float(i) 141 | 142 | for i in recentprices: 143 | recentpricenumber += float(i) 144 | 145 | # pricenumber is just the average of oneweek, fiveday, and threeday. 146 | # recentpricenumber is the average of twoday, oneday, and today. 147 | # These variables give a pretty good average for different time periods. 148 | pricenumber = pricenumber / len(prices) 149 | recentpricenumber = recentpricenumber / len(recentprices) 150 | 151 | if recentpricenumber > pricenumber: 152 | print "In the past week, the stock has been moving upwards in price." 153 | positive += 1 154 | else: 155 | print "In the past week, the stock has been decreasing in price." 156 | negative += 1 157 | 158 | # Now these are the longer term things 159 | if fiftyavg > twohundredavg: 160 | print "The fifty day average is greater than the two hundred day average, which signifies a longer term upwards trend." 161 | positive += 2 162 | elif fiftyavg < twohundredavg: 163 | print "The two hundred day average is greater than the fifty day average, which signifies a longer term downwards trend." 164 | negative += 2 165 | elif fiftyavg == twohundredavg: 166 | print "You probably didn't enter a valid company. Restart the program and try again." 167 | end() 168 | 169 | if negative > positive: 170 | if negative == 3: 171 | print "This stock looks like it is doing VERY poor! I wouldn't invest in it." 172 | end() 173 | if negative - positive == 1: 174 | print "This stock is doing pretty bad. It might recover in the near future, but for now I wouldn't buy it." 175 | end() 176 | print "This stock looks like it isn't doing well... I wouldn't invest in it." 177 | end() 178 | elif negative < positive: 179 | if positive == 3: 180 | print "This stock looks like it is doing very well right now! I would invest in it!" 181 | end() 182 | if positive - negative == 1: 183 | print "This stock is doing slightly good. It isn't making any serious growth at the moment." 184 | print "If you buy it you probably won't lose any money, but you probably won't make much either." 185 | end() 186 | print "This stock looks like it is doing pretty well. I suggest investing in it." 187 | end() 188 | elif positive == negative: 189 | print "This stock is doing mediocre. I would look for another stock to buy unless you are very confident in this one." 190 | end() 191 | 192 | 193 | # Very simple function, just exits the program. and says goodbye to the user. 194 | def end(): 195 | print "" 196 | print "Alright, goodbye!" 197 | print "Press the 'return' or 'enter' key to exit..." 198 | pause = raw_input("") 199 | raise SystemExit("Bye") 200 | 201 | ### ---------------------------------------------------------------------------------------------------------------- ### 202 | # This is just the part where it runs all the functions after they've been defined # 203 | 204 | weekend() 205 | greeting() 206 | --------------------------------------------------------------------------------