J
Jimbo
I have made a Python App(really script) that will check a stocks
current values from a website & save that data to a SQLite 3 database.
I am looking for any suggestions & criticisms on what I should do
better or anything at all but mainly in these areas:
Any advice criticism would be really helpful.
App:
current values from a website & save that data to a SQLite 3 database.
I am looking for any suggestions & criticisms on what I should do
better or anything at all but mainly in these areas:
- Correct Python Layout of code
- Correct error checking: Am I catching all my errors or are my
exceptions not specific enough? Should I be using more try excepts
inside my functions?
- Are there any areas where huge errors, bugs etc could occur that I
have not compensated for?
- I am also looking for suggestions on how to write a function better,
so if you think that function is really bad & should be rewritten
completely or something I would really like to hear it.
- Anything else that you see
- Is python meant to be used in the way I have used it? To make a
'semi detailed' app?
Any advice criticism would be really helpful.
App:
Code:
"""
*Stock Data Builder*
Algorithm:
- Search website for stock
- Get website HTML source code
- Search code for target stock data(price,dividends,etc..)
- Add data to text file
"""
import sys
import os
import sqlite3
import datetime
import time
import urllib2
### Global Variables ###
menu = "***Stock Program*** \n\n1. Add a Stock to track \n2. Get
Todays Tracking Data \n3. Exit \nEnter decision: "
target = '<th scope="row" class="row"><a href="/asx/research/
companyInfo.do?by=asxCode&asxCode=%s">%s</a>'
ASXurl = 'http://www.asx.com.au/asx/markets/priceLookup.do?
by=asxCodes&asxCodes='
class stock:
code = ""
purchasePrice = 0
purchaseQuantity = 0
price = [] # list of recent prices
recentBid = [] # list of recent bids for stock
recentOffer = [] # list of recent offers for stock
stockVol = [] # list of stock quantity available on
market
def __init__(self):
""" Default Constructor """
self.code = ""
self.purchasePrice = 0
self.purchaseQuantity = 0
def constructor(self, stockCode, purPrice, purQuant):
""" Constructor """
self.code = stockCode
self.purchasePrice = purPrice
self.purchaseQuantity = purQuant
def setData(self, stockCode, purPrice, purQuant, priceList,
reBidList, reOffList, popList):
""" Defines & implements the objects' public variables """
self.code = stockCode
self.purchasePrice = purPrice
self.purchaseQuantity = purQuant
self.price = priceList
self.recentBid = reBidList
self.recentOffer = reOffList
self.stockVol = popList
self.printStats()
def updateData(self, priceEle, bidEle, offerEle, populEle):
""" Adds data to stock object's lists """
self.price.append(priceEle)
self.recentBid.append(bidEle)
self.recentOffer.append(offerEle)
self.stockVol.append(populEle)
def printStats(self):
""" Output Stock attributes """
print("Stock Code: "+self.code)
print("Stock Purchase Price: "+str(self.purchasePrice))
print("Stock Quantity Owned: "+str(self.purchaseQuantity))
print("***Initial Investment Value:
"+str(self.purchasePrice*self.purchaseQuantity))
if not(len(self.price) <= 0):
print("Stock Current Price: "+str(self.price[-1]))
print("Recent Bid: "+str(self.recentBid[-1]))
print("Recent Offer: "+str(self.recentOffer[-1]))
print("Total Stock Volume in market:
"+str(self.stockVol[-1]))
print("***Present Investment Value:
"+str(self.price[-1]*self.purchaseQuantity))
print("\n")
### Functions ###
def connectDatabase(dbLocation, dbName, tableName):
""" Establish & Return connection to SQLite Database """
try:
if not (os.path.exists(dbLocation)):
os.mkdir(dbLocation) # create folder/dir
os.chdir(dbLocation) # change directory focus to
dbLocation
conn = sqlite3.connect(dbLocation+dbName)
cur = conn.cursor()
try:
createTableQ = "CREATE TABLE IF NOT EXISTS "+tableName
+" (code varchar PRIMARY KEY, purchase_price float, purchase_quantity
float, purchase_date varchar);"
cur.execute(createTableQ)
conn.commit()
except:
pass
return conn
except IOError or OSError:
print "Connection to database failed"
return False
def retrieveStockDatabase(conn, tableName):
""" Read SQLite3 database & extract stock data into StockList """
stockList = []
stockQuery = "select recent_price, recent_offer, recent_bid,
stock_volume from ? ;"
cur = conn.cursor()
cur.execute("select code, purchase_price, purchase_quantity from
"+tableName+";")
for row in cur.fetchall():
newStock = stock()
newStock.code = row[0]
newStock.purchasePrice = row[1]
newStock.purchaseQuantity = row[2]
cur.execute(stockQuery,[newStock.code])
for rw in cur.fetchall():
newStock.price.append(rw[0])
newStock.recentOffer.append(rw[1])
newStock.recentBid.append(rw[2])
newStock.stockVol.append(rw[3])
stockList.append(newStock)
return stockList
def getDate():
""" Return todays date in format DD:MM:YYYY """
time = datetime.datetime.now()
date = time.strftime("%d:%m:%Y") # string format time (%y)
return date
def newStockDatabase(conn, stockTable, stock):
""" Add a new stock to SQLite database if not already there
We save the stocks code, purchase price, quantity purchased
& date of purchase. """
cur = conn.cursor()
try:
createTableQ = "create table "+stock.code+" (date varchar
PRIMARY KEY, recent_price float, recent_offer float, recent_bid float,
stock_volume double);"
stockQuery = "insert into "+stockTable+"
values(?, ?, ?, ?);"
cur.execute(createTableQ)
cur.execute(stockQuery,
[stock.code,stock.purchasePrice,stock.purchaseQuant,getDate()])
conn.commit()
except IOError or OSError:
print "Table may already exist or bad SQLite connection."
return False
def webFormat(URL):
if (URL.startswith("http://")==False):
URL = "http://"+URL
return URL
def getSource(URL):
""" Retrieve HTML source code from website URL &
save in sourceBuffer """
try:
URL = webFormat(URL) # make sure URL contains essential
"http://"
sourceBuffer = urllib2.urlopen(URL)
print '\nResponse code = ',sourceBuffer.code
print 'Response headers = ',sourceBuffer.info()
print 'Actual URL = ',sourceBuffer.geturl()
sourceCode = sourceBuffer.read()
sourceBuffer.close()
return sourceCode
except IOError: # URLError
print "Function Failed: Reasons could be invalid URL name \nOR
\nHTML protocol message transfer failure."
return False # function failed
def getTargetText(targetStrtData, targetEndData, dataBuffer):
""" Grabs target text that lies inside 'dataBuffer' string
between targetStrtData & targetEndData """
try:
result = dataBuffer.split(targetStrtData)
result.pop(0)
result = result[0].split(targetEndData)
result.pop(1)
print result
return result
except IOError:
print "Function Failed: Reasons could be targetStrtData and/or
targetEndData is not present in dataBuffer."
def getStockData(htmlText, selectedStock):
""" Extract stock data(stock code,price,etc) from htmlText """
try:
# Here I extract my number data from HTML text
tempList = []
for string in htmlText:
for i in string.split('>'):
for e in i.split():
if ('.' in e and e[0].isdigit()):
tempList.append(float(e))
elif (',' in e and e[0].isdigit() ):
# remove ',' chars
e = e.replace(',','')
tempList.append(float(e))
selectedStock.updateData(tempList[0],tempList[2],tempList[3],tempList[7])
except IOError: # is this the correct error I should be trying to
catch here??
print "Function Failed: Reasons could be: sites HTML data has
changed. Consult author of program."
return False
def createStockTracker(stockCode,stockPrice,stockQuant, stockList):
""" Add a new stock to the database to track """
newStock = stock()
newStock.constructor(stockCode,stockPrice,stockQuant)
stockList.append(newStock)
return stockList
def writeStockToDatabase(conn, stock):
""" Write ONLY this Stock's attributes to SQLite Database """
cur = conn.cursor()
date = getDate()
tableName = stock.code
stockquery = "insert into "+tableName+" values(?, ?, ?, ?, ?);"
cur.execute(query,[date,stock.price[-1], stock.recentOffer[-1],
stock.recentBid[-1], stock.stockVol[-1]])
conn.commit()
def writeAllToDatabase(conn, stockList):
""" Enter recent Stock attributes into SQLite Database """
cur = conn.cursor()
date = getDate()
for stock in stockList:
tableName = stock.code
stockquery = "insert into "+tableName+"
values(?, ?, ?, ?, ?);"
cur.execute(query,[date,stock.price[-1],
stock.recentOffer[-1], stock.recentBid[-1], stock.stockVol[-1]])
conn.commit()
### Input Functions ###
def inputNewStock():
""" """
print "*Please note only an Australian Securities Exchange(ASX)
listed stock can be tracked in Version 1.0."
badInput = True
while (badInput == True):
try:
code = raw_input("Please enter the ASX code for the
stock you wish to track: ")
price = input("Please enter the individual stock value
for "+code+": ")
quantity = input("Please enter the number/quantity of
stocks purchased: ")
if (len(code)>3):
badInput = True
else : badInput = False
return True
except IOError:
if (raw_input("Incorrect input. Note: ASX code cannot be
more than 3 chars. Press 'x' to exit or anything else to try
again")=='x'):
return False
badInput = True # this I am not sure if necessary to loop
correctly
### Main program loop ###
def main():
programEnd = False;
dbLocation = "C:\Users\Sam\Desktop\StockApp/"
dbName = "stockData.db"
stockTable = "stocks"
conn = connectDatabase(dbLocation,dbName,stockTable)
stockList = retrieveStockDatabase(conn,stockTable)
for s in stockList:
s.printStats()
while (programEnd == False):
decision = input(menu) # Print Menu
if (decision==1):
if not(inputNewStock()==False):
stockList =
createStockTracker(acode,price,quantity,stockList)
newStockDatabase(conn,stockTable,stockList[-1])
print("\n** New Stock **")
stockList[-1].printStats()
print "The stock "+code+" was successfully added to
our database. \nNow every time the program runs it will automatically
track this stock & obtain its stock attributes\n\n"
# TO DO:
# get new stock recent Data from internet etc.
# add stock data to data base;
elif (decision==2):
if (len(stockList)>0):
for Stock in stockList:
URL = ASXurl+Stock.code
sourceCode = getSource(URL)
targetData = getTargetText(target %
(Stock.code,Stock.code),"</tr>",sourceCode)
getStockData(targetData,Stock)
Stock.printStats()
#writeStockToDatabase(conn,Stock)
else:
print "You must first identify a stock to follow.
\nPlease select option 1."
elif (decision==3):
print "Thank you for using Stock Program. Goodbye.\n"
programEnd = True; # Exit program
conn.close()
return 0 # End program
main()