Tag Archives: twitter

finance hacks

Python stock quote fetch

UPDATE

— 8< —

Nach den heldenhaften Ideen des ebenso heldenhaften Stefan twittert nun mein Portfolio wochentags um 15:00 die aktuelle Entwicklung: crashportfolio@twitter

— 8< —

Anfang der Woche habe ich mein fiktives Krisenportfolio gepostet – damit war’s plötzlich höchste Zeit, Kursentwicklungen aktuell zu halten. Zwei Stunden und ein paar Zeilen Python später ist nun alles automatisiert.

Natürlich ist die Verwaltung eines Portfolios etwas, was Yahoo!, Google und zig andere Dienste gratis anbieten. Außerdem sehe ich die Positionen ohnehin auf meinem Konto bei brokerjet, aber dennoch: Nichts macht so viel Spaß wie eine selbst gebastelte Lösung, nichts ist so flexibel verwendbar, und nichts geht abzüglich der anfänglichen Programmierzeit danach so schnell.

Erfassen

Zunächst war es wichtig, die fiktiven Investments strukturiert zu erfassen. Ich hasse zwar Tabellenkalkulation, aber CSV scheint dennoch ein brauchbares Austauschformat zu sein. Kurzum: Name, Einstiegskurs, Menge, Datum, sowie eine ID (=Symbol) und ein Pointer auf den jeweiligen data provider sind wichtig.

Commodity ETF,etf/RBS_Market_Access_Jim_Rogers_International_Commodity_Index_ETF,26.50,900,08.07.2012,finanzen.net
Altria,PHM7.F,28.51,300,08.07.2012,yahoo
BP,BPE5.DE,5.40,1400,08.07.2012,yahoo
Fuchs Petrolub,FPE.DE,40.80,180,08.07.2012,yahoo
Nestle,NESR.DE,48.64,150,08.07.2012,yahoo
Novo Nordisk,NOVA.DE,118.32,65,08.07.2012,yahoo
Pfizer,PFE.DE,18.21,400,08.07.2012,yahoo
Shoprite,HY7.F,15.64,480,08.07.2012,yahoo
Umicore,UMI.BR,35.32,200,08.07.2012,yahoo

Absaugen

Das CSV-File wird mittels Python eingelesen, die Klasse Paper wird pro Position instanziiert. Yahoo! bietet ein unerschöpfliches API für Aktienkurse, die Python-Library ystockquote macht das Ganze sehr einfach zu verwenden.

class Paper():
    """Any bond, etf or stock"""
    
    def __init__(self, data_provider, name, symbol, quant, purchase_price, date):
        
        self.data_provider = data_provider
            
        self.name = name
        self.symbol = symbol
        self.quant = int(quant)
        self.purchase_price = float(purchase_price)
        self.date = date
        
        self._price = None
    
    def __repr__(self):
        return "%20s %7.2f %7.2f %7.2f%% %5d" % (self.name, self.purchase_price, self.price, self.change, self.totalgain)
    
    @property
    def price(self):
        if not self._price:
            
            if self.data_provider == 'yahoo':
                self._price = float(ystockquote.get_price(self.symbol))
            elif self.data_provider == 'finanzen.net':
                self._price = FinanzenNetParser.get_price(self.symbol)
            else:
                raise NoDataProvider
        return self._price

    @property
    def change(self):
        return ((self.price / self.purchase_price ) - 1) * 100
    
    @property
    def totalgain(self):
        return self.change / 100.0 * (self.purchase_price * self.quant)

Für den Kurs des ETF benötige ich einen HTML-Parser, da Yahoo! dessen Kurs nicht anbietet. Mit BeautifulSoup habe ich einen neuen Lieblings-Parser ins Herz geschlossen – in Kürze war also der Kurs von finanzen.net eingebunden. (Python-Tipp: Webscraping with Python and beautifulsoup)

Natürlich muss ich das auch noch für die Goldmünzen und die Uhr machen, die sich ebenso in meinem Portfolio befinden.

class FinanzenNetParser():
         
    @classmethod
    def get_price(self, path):
        """Ok, tricky: price is the first th in a table.header_height"""
        
        url = 'http://www.finanzen.net/%s' % (path,)
        content = urllib2.urlopen(url).read()
        
        soup = BeautifulSoup(content)
        for table in  soup.find_all('table'):
        
            if table.get('class') == ['header_height']:
                return float(table.th.text.replace('EUR','').replace(',','.'))

Ausgeben

Der Output ist derzeit noch etwas mager, mit Jinja2 sind die Daten aber schnell in HTML gegossen und auf meinem Mobiltelefon verfügbar.

                name purchase current  change  total
       Commodity ETF   26.50   26.57    0.26%    62
              Altria   28.51   28.79    0.98%    84
                  BP    5.40    5.48    1.50%   113
      Fuchs Petrolub   40.80   40.65   -0.37%   -26
              Nestle   48.64   48.86    0.45%    32
        Novo Nordisk  118.32  120.15    1.55%   118
              Pfizer   18.21   18.52    1.67%   121
            Shoprite   15.64   15.89    1.62%   121
             Umicore   35.32   34.65   -1.91%  -134