2
\$\begingroup\$

The code below is a good representation of my coding skills. I've been at it for about 6 months. What I am interested in is ways to make the following program faster. I currently have the urlrequests threaded to pull information for 500 stocks, but it is still too slow (around 30 seconds). What python techniques can I use to make this program more efficient?

Thanks!

from urllib.request import urlopen
from csv import reader
from threading import Thread


class StockQuote():
    """gets stock data from Yahoo Finance"""

    def __init__(self, quote):
        self.quote = quote

    def lastPrice(self):
        url = 'http://finance.yahoo.com/d/quotes.csv?s={ticker}&f=l1'.format(ticker=self.quote)
        return bytes.decode((urlopen(url).read().strip()))

    def volume(self):
        url = 'http://finance.yahoo.com/d/quotes.csv?s={ticker}&f=v0'.format(ticker=self.quote)
        return bytes.decode((urlopen(url).read().strip()))

    def yearrange(self):
        url = 'http://finance.yahoo.com/d/quotes.csv?s={ticker}&f=w0'.format(ticker=self.quote)
        return bytes.decode((urlopen(url).read().strip()))

    def PEratio(self):
        url = 'http://finance.yahoo.com/d/quotes.csv?s={ticker}&f=r0'.format(ticker=self.quote)
        return bytes.decode((urlopen(url).read().strip()))

    def bookValue(self):
        url = 'http://finance.yahoo.com/d/quotes.csv?s={ticker}&f=b4'.format(ticker=self.quote)
        return bytes.decode((urlopen(url).read().strip()))

    def EBITDA(self):
        url = 'http://finance.yahoo.com/d/quotes.csv?s={ticker}&f=j4'.format(ticker=self.quote)
        return bytes.decode((urlopen(url).read().strip()))

    def PEGRatio(self):
        url = 'http://finance.yahoo.com/d/quotes.csv?s={ticker}&f=r5'.format(ticker=self.quote)
        return bytes.decode((urlopen(url).read().strip()))

    def ticker(self):
        url = 'http://finance.yahoo.com/d/quotes.csv?s={ticker}&f=s0'.format(ticker=self.quote)
        return bytes.decode((urlopen(url).read().strip()))


class StockData(Thread):


    def __init__(self, stk, fileobj):
        Thread.__init__(self)
        self.stk = stk
        self.fileobj = fileobj

    def run(self):
        try:
            stkObj = StockQuote(self.stk)
            stkdata= {}
            stkdata['Ticker'] = stkObj.ticker()
            stkdata['Price'] = stkObj.lastPrice()
            stkdata['PE Ratio'] = stkObj.PEratio()
            stkdata['Volume'] = stkObj.volume()
            stkdata['Year Range'] = stkObj.yearrange()
            stkdata['Book Value per Share'] = stkObj.bookValue()
            stkdata['EBITDA'] = stkObj.EBITDA()
            stkdata['PEG Ratio'] = stkObj.PEGRatio()
        except Exception:
            pass
        self.fileobj.write(str(stkdata))

def openSP500file():
    SP500 = reader(open(r'C:\Users\test\Desktop\SP500.csv', 'r'), delimiter=',')
    printlist = open(r'C:\Users\test\Desktop\SP500prices.txt', 'w')
    for x in SP500:
        indStk = x[0]
        t1 = StockData(indStk, printlist)
        t1.start()


def main():
    openSP500file()


if __name__ == '__main__':
    main()
\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

It is difficult to make the program faster because time is mostly expended in IO and url connections. It would help for checking changes if you could provide the csv stock files.

On the other hand the code could be greatly simplified. The following code has not been tested (no csv files available) but gives you the idea:

from urllib.request import urlopen
from csv import reader
from threading import Thread


class StockQuote():
    """gets stock data from Yahoo Finance"""

    names = dict(lastPrice='l1', volume='v0', yearrange='w0', PEratio='r0',
                  bookValue='b4', EBITDA='j4', PEGRatio='r5', ticker='s0')

    def __init__(self, quote):
        self.quote = quote
        self.url = 'http://finance.yahoo.com/d/quotes.csv?s={ticker}&f={par}'

    def __getattr__(self, name):
        url = self.url.format(ticker=self.quote, par=StockQuote.names[name])
        return bytes.decode((urlopen(url).read().strip()))


class StockData(Thread):

    def __init__(self, stk, fileobj):
        Thread.__init__(self)
        self.stk = stk
        self.fileobj = fileobj

    def run(self):
        stkdata = {}
        stkObj = StockQuote(self.stk)
        for prprty in StockQuote.names:
            try:
                func = getattr(stkObj, prprty)
                stkdata[prprty] = func()
            except Exception:
                pass

        self.fileobj.write(str(stkdata))


def openSP500file():
    SP500 = reader(open(r'C:\Users\test\Desktop\SP500.csv', 'r'), delimiter=',')
    printlist = open(r'C:\Users\test\Desktop\SP500prices.txt', 'w')
    for x in SP500:
        indStk = x[0]
        t1 = StockData(indStk, printlist)
        t1.start()


def main():
    openSP500file()


if __name__ == '__main__':
    main()
\$\endgroup\$
1
  • \$\begingroup\$ Thank you very much. I'll have to study up on the getattr and the .names method that you added to the for prprty loop. I haven't seen those before. But this is really helpful and I love how compact you made the code. Thanks! \$\endgroup\$ Dec 19, 2011 at 2:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.