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

 

11 Comments

  • Stefan
    July 12, 2012 - 2012-07-12 8:59:15 | Permalink

    Passend dazu: Quick’n’dirty Script um den aktuellen Kurs einer Aktie via Yahoo Finance abzufragen und auf Twitter zu posten: https://bitbucket.org/stefanschleifer/twitstock/src, im Einsatz z.B. unter https://twitter.com/fbstock_ 😉

    • Mathias
      July 13, 2012 - 2012-07-13 8:45:00 | Permalink

      Stefan,

      sehr cool! Wo läuft das Skript? Vielleicht mach’ ich ja einen Krisenportfolio-Ticker daraus.

      Übrigens: Aus allererster Hand weiß ich, dass sich derzeit einige Banken den Kopf über neuartige Services zerbrechen. Ein Kerl wie du hätte in knapp vier Wochen wahrscheinlich ein Online-Banking mit zusätzlichen Features wie Kontobewegungen via SMS, usw. programmiert.

  • Stefan
    July 13, 2012 - 2012-07-13 12:23:20 | Permalink

    Läuft via cronjob auf meinem vServer. @Krisenticker: Ist nicht unbedingt auf Wiederverwendbarkeit ausgelegt, war/ist nur ein Hack. 😉

    Haha, wäre sicher cool jep, die Bank deiner Isabella hat eh gerade ihr Netbanking neu gelauncht. 😉

  • Pingback: Mathias' Blog » Mathias’ Krisenportfolio

  • Benny
    September 23, 2012 - 2012-09-23 4:01:27 | Permalink

    Vorsicht mit Yahoo-Daten 😉 Bin auf deinen Blog gestoßen weil ich nach einer Alternative und FinanzenNet-Parser gesucht habe, da die Yahoo-Daten immer mal wieder Fehler enthalten (entweder nur einzelne Werte was man automatisiert erkennen kann, oder aber völlig wilde Daten verursacht durch z.B. Splits. Also läuft man rückwärts in die Vergangenheit stimmen die Daten bis zu dem Punkt wo ein Split auftritt und dann gehts in die Hose). Ist allerdings mit dem Zufall verknüpft. Ich habe bei gleicher CSV-URL unterschiedliche (mal richtige, mal falsche) CSV-Files bekommen. Bestes Beispiel die Adidas-Aktie ADS.DE rund um den 5.6.2006.
    Probleme werden auch hier genannt: http://www.aktienboard.com/forum/f29/historische-kursdaten-yahoo-splits-dividenden-waehrungen-t97978/

    Also: Mit Vorsicht zu genießen 😉

    Code on…

    • Mathias
      September 23, 2012 - 2012-09-23 4:08:36 | Permalink

      Benny,

      Danke für den Hinweis.

      Spätestens als sich meine Shoprite-Aktien über Nacht verzehnfacht hatten, war mir leider bewusst, dass es Datenprobleme bei Yahoo! geben kann. (Die Alternative wär’ mir lieber gewesen…)

      Wie liest du Daten von Finanzen.net ein?

      • Benny
        October 6, 2012 - 2012-10-06 10:23:30 | Permalink

        Hi Mathias,
        zur Zeit lese ich noch keine Daten von Finanzen.net ein, ich komme zur Zeit zu wenig zu meinen Hobby-Programmier-Aufgaben. Ich habe lediglich einmal den Seitenquelltext in Augenschein genommen und darüber hinaus die Entscheidung getroffen selbst eine Datenbank aufzusetzen. Dann wird es die Hauptsache sein diese einmal mit validen Daten aufzusetzen (möglicherweise auch über grafischen Plot-Abgleich (denn Plots bekommt man ja wie Sand am Meer im Gegensatz zu den Werten) und anschließend täglich automatisiert zu aktualisieren. Aber im Gegensatz zu historischen Daten bekommt man die aktuellen ja von diversen Anbietern und kann diese dann entsprechend validieren. Und dann habe ich eine Datenbank mit der ich arbeiten kann ohne dass irgendjemand Mist bauen kann 😉 Naja, außer mir, aber dann bin ich wenigstens selbst schuld. Wer weiß, vlt hänge ich meine Datenbank ja dann eines Tages ans Netz und konkurriere mit Yahoo 😉

  • Smithf169
    March 28, 2014 - 2014-03-28 2:04:09 | Permalink

    Very nice! cakekbfefe

  • Cit
    November 26, 2015 - 2015-11-26 12:33:56 | Permalink

    Kann schon jemand von euch Daten aus der Vergangenheit von Finanzen.Net lesen? Wenn ja ,wie?

  • Steffen
    January 7, 2016 - 2016-01-07 12:22:56 | Permalink

    Hallo Mathias,
    sehr interessanter Artikel und Kommentare hier. Ich habe folgende Idee:

    Ich möchte über die Positionen auf meiner Watchlist per E-Mail über ein neues 52-Wochen-Hoch/Tief informiert werden, um ggf. einen Kauf oder Verkauf durchzuführen.

    Finanzen.net stellt u.a. unter http://www.finanzen.net/chartsignale/index/Alle/liste/week-52-high Chartsignale von 52-Wochen-Hochs zur Verfügung.

    Ich habe auf meiner Watchlist diverse Positionen bei denen ich informiert werden möchte, ob einer der Werte ein neues Hoch (oder Tief) erreicht hat.

    Hierfür muss ein Abgleich mit meinem Depot/Watchlist und der Webseite durchgeführt werden. Ist ein Match dabei, wird eine E-Mail an mich versendet.

    Meine Frage an dich: Wie müsste der Parser aussehen und wo laufen?

    Was hälst du von der Idee?

    • Mathias
      January 9, 2016 - 2016-01-09 12:28:24 | Permalink

      Hallo Steffen,

      die Idee klingt nach IFTTT (if this then that) – und wahrlich gibt’s dort schon etwas zum Loslegen: https://ifttt.com/stocks

      Viel Erfolg damit!

  • Leave a Reply

    Your email address will not be published. Required fields are marked *