yFinance: Wie viel wäre dein Investment heute wert

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Saiba
User
Beiträge: 1
Registriert: Donnerstag 30. Juni 2022, 22:08

Hi,

ich muss eine Uni Aufgabe lösen und habe einen code geschrieben. Komme aber gerade nicht weiter. Ich weiß, dass es hierfür wahrscheinlich eine einfache Lösung gibt aber mein Kopf ist gerade matsch. Vllt könnt ihr mir ausnahmsweise kurs aushelfen.

Ich würde gerne folgendes machen: Ich wähle eine AG aus. Gebe das Datum ein und wie viele Aktien ich gekauft hätte. Leider hab ich es nciht geschafft es mit einem Währungsbetrag zu machen..

Dann soll herauskommen: wie viel gewinn oder verlust ich mit dem Kauf der Aktie zum eingegebenen Datum gemacht hätte.


Mein Code:

Code: Alles auswählen

import sys
import requests
import json
import yfinance as yf
from datetime import date,datetime



def valid_stock(stock_name,api_key):
    base_url = "https://yfapi.net/v6/finance/quote"
    querystring = {"symbols": stock_name}
    headers = {
        'x-api-key': api_key
    }
    response = requests.request("GET", base_url, headers=headers, params=querystring)
    json_data = json.loads(response.text)
    if len(json_data['quoteResponse']['result']) == 0:
        return False
    else:
        return True

if __name__ == '__main__':
    api_key = "83esSjubXI6KUOuwEKncQXs4iR13Vsw8nhMdn0nf"

    if len(sys.argv) == 2:
        stock_name = sys.argv[1]
        if valid_stock(stock_name, api_key):
            date_of_buy = input(f"Enter the date (format: yyyy-mm-dd) you bought {stock_name}: ")
            quantity = int(input(f"Enter the quantity of {stock_name} you owns: "))
            end = str(str(date_of_buy.split("-")[0])+"-12-30")
            data_one = yf.download(stock_name, date_of_buy, end)
            today = date.today()
            start = str(str(today.year)+"-01-01")
            end = str(str(today.year)+"-"+str(today.month)+"-"+str(today.day))
            data_two = yf.download(stock_name, start, end)
            stock_previous_val = sum(data_one['Close'].tolist())/len(data_one['Close'].tolist())
            stock_current_val = sum(data_two['Close'].tolist()) / len(data_two['Close'].tolist())
            print(f"Stock {stock_name} Value in Year {date_of_buy.split('-')[0]} : ${round(stock_previous_val,2)}")
            print(f"Stock {stock_name} Value in Year {today.year} : ${round(stock_current_val,2)}")
            print(f"Expected Profit or Loss: ${round((stock_current_val - stock_previous_val)*quantity,2)}")
            
    else:

        print("Please Enter the Stock Name as: python single_stock.py stock_name")

Folgendes kommt raus:

Enter the date (format: yyyy-mm-dd) you bought AMZN: 2022-06-30
Enter the quantity of AMZN you owns: 1
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
a) Stock AMZN Value in Year 2022 : $107.56
b) Stock AMZN Value in Year 2022 : $140.31
Expected Profit or Loss: $32.75

C:\Users\Maximilian\Desktop\CodPy>

Was ich nicht verstehe. Eig müssten die Werte a & b gleich sein. Ich verstehe nicht wieso diese unterschiedlich sind. Kann mir jemand erklären wieso das der Fall ist?

Vielen Dank!!
LG
Saiba
Benutzeravatar
__blackjack__
User
Beiträge: 13077
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Saiba: Warum müssen die gleich sein? Die berechnen sich doch aus unterschiedlichen Werten. Die Textausgabe ist da auch ein bisschen zu ungenau, denn die Zeitangaben aus denen sich der Wert für a) und b) berechnet sind ja präziser als einfach nur das Jahr.

Dieses ganze Zeichenkettenbasteln mit Datumsangaben ist übrigens gruselig. Verwende dafür was das `datetime`-Modul bietet. `datetime.datetime` kann sowohl Zeichenketten mit Datumsangaben parsen als auch `datetime`-Objekte in Zeichenketten umwandeln. Letzteres kann man mit der Formatspezifikation bei `format()` und f-Zeichenketten machen. Da sollten Beispiele in der Dokumentation sein.

Und auch das runden auf zwei Nachkommastellen macht man für die Ausgabe mit einer Formatspezifizierung und nicht mit `round()`.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Max22
User
Beiträge: 6
Registriert: Donnerstag 26. Mai 2022, 14:36

Hi Blackjack,

sie müssten gleich sein, da ich den aktuellen wert der Aktie zur eingegebenen Zeit berechnen wollte.

Wenn ich am 02.07. 2022 eine Apple Aktie gekauft hätte, dann müsste es am 02.07.2022 den gleichen Wert haben.

Ich habs mit date time.datetime probiert, aber irgendwie krieg ich es nicht hin. ich weiß, dass es umständlich so ist aber es ist das beste was ich schaffte
Benutzeravatar
__blackjack__
User
Beiträge: 13077
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Max22: Warum müssten die gleich sein? Beide Werte werden ja mit der gleichen Formel über Werte berechnet die aus unterschiedlichen Zeiträumen kommen. Das wäre IMHO schon ein sehr grosser Zufall wenn die Ergebnisse gleich wären.

Warum wird da überhaupt etwas gerechnet? Ich hätte naiv gedacht man würde einfach den Wert vom Kauftag nehmen und den vom aktuellen Wert abziehen.

Du solltest Dich auch ganz grundsätzlich mal mit Datentypen beschäftigen und die benutzen. Es ist nicht nur das Du auf Zeichenketten operierst statt `date` und `datetime`-Objekte zu verwenden, sondern auch bei den Zeichenketten scheinst Du unsicher zu sein, denn da wird oft eine Zeichenkette mit `str()` in eine Zeichenkette umgewandelt, was keinen Sinn macht.

Der Datentyp der Rückgabe von der Web-API wird auch nicht sinnvoll verwendet. Das sieht mir nach Pandas-DataFrames aus. Statt die gleiche Spalte vier mal in eine Liste umzuwandeln und dann mit Python-Grundfunktionen den Mittelwert zu berechnen, würde man da einfach die entsprechende Methode aufrufen.

`round()` verwendet man wenn man mit einem gerundeten Wert weiterrechnen will. Also eher selten. Für die Anzahl von Nachkommastellen bei der Umwandlung beziehungsweise beim einsetzen in eine Zeichenkette regelt man das über die Formatspezifikation bei `format()` oder f-Zeichenketten.

Das Hauptprogramm gehört in eine Funktion. Es wird zwar durch das ``if __main__ == …`` vor Ausführen bei ``import`` geschützt, aber es werden da trotzdem noch ein Haufen modulglobale Variablen definiert die Probleme machen könnten.

Antworten vom Webserver bei `requests` sollte man auf Fehlercodes prüfen.

Die `response`-Objekte haben selber bereits eine `json()`-Methode.

Ein ``if``/``else`` bei dem in beiden Zweigen jeweils nur `True` oder `False` zurückgegeben werden, ist überflüssig. Das ``if`` hat eine Bedingung, und die liefert ja bereits einen Wahrheitswert. Den kann man dann auch gleich, ohne weitere Umwege zurückgeben.

Man muss nicht jeden Zwischenwert an einen eigenen Namen binden.

Braucht man diese Testfunktion denn überhaupt? Was passiert denn bei der API die Du da verwendest, wenn es die angegebene Aktie nicht gibt?

Wonach wurde eigentlich entschieden welche(r) der drei Benutzereingaben als Argument an der Kommandozeile übergeben werden muss und welche per `input()` abgefragt werden?

Ungetestet:

Code: Alles auswählen

#!/usr/bin/env python3
import sys
from datetime import date as Date, datetime as DateTime

import requests
import yfinance as yf


def is_valid_stock(stock_name, api_key):
    response = requests.get(
        "https://yfapi.net/v6/finance/quote",
        headers={"x-api-key": api_key},
        params={"symbols": stock_name},
    )
    response.raise_for_status()
    return len(response.json()["quoteResponse"]["result"]) > 0


def main():
    api_key = "..."

    if len(sys.argv) == 2:
        stock_name = sys.argv[1]
        if is_valid_stock(stock_name, api_key):
            date_of_buy = DateTime.strptime(
                input(
                    f"Enter the date (format: yyyy-mm-dd) you bought"
                    f" {stock_name}: "
                ),
                "%Y-%m-%d",
            ).date()
            quantity = int(
                input(f"Enter the quantity of {stock_name} you bought: ")
            )

            data_one = yf.download(
                stock_name,
                str(date_of_buy),
                str(date_of_buy.replace(month=12, day=30)),
            )

            today = Date.today()
            data_two = yf.download(
                stock_name, str(today.replace(month=1, day=1)), str(today)
            )

            stock_previous_value = data_one["Close"].mean()
            stock_current_value = data_two["Close"].mean()

            print(
                f"Stock {stock_name} value in Year {date_of_buy.year} :"
                f" ${stock_previous_value:.2f}"
            )
            print(
                f"Stock {stock_name} value in Year {today.year} :"
                f" ${stock_current_value:.2f}"
            )
            print(
                f"Expected profit or loss:"
                f" ${(stock_current_value-stock_previous_value)*quantity:.2f}"
            )

    else:
        print(
            "Please Enter the Stock Name as: python single_stock.py stock_name"
        )


if __name__ == "__main__":
    main()
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Antworten