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 codeAny advice criticism would be really helpful.
- 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?
App:
Expand|Select|Wrap|Line Numbers
- """
- *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()