Frage zu yfinance und Prozentualer Veränderung zum Vortag

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
ColaOfficial
User
Beiträge: 1
Registriert: Montag 17. Juli 2023, 18:39

Hallo zusammen,

ich arbeite gerade an einem Python-Skript, das mir die prozentuale Veränderung einer Aktie zum Vortag berechnen soll. Dabei nutze ich das yfinance-Modul, um die benötigten Daten zu beziehen. Leider funktioniert mein aktueller Code noch nicht ganz wie gewünscht. Kann mir jemand bei der Behebung des Problems helfen?

Hier ist der Code, den ich bisher habe:

Code: Alles auswählen

import yfinance as yf
from datetime import datetime, timedelta
import pytz

def get_last_change_1d_Vtop(tickersymbol, interval, days):
    global change_1d_Vtop, date, current_time
    end = datetime.now()
    start = end - timedelta(days + 5)  # Extend the period by 5 days

    data = yf.download(tickersymbol, start=start, end=end, interval=interval)
    formatted_dates = [date.strftime("%H:%M:%S" "   " "%d/%m/%Y") for date in data.index]
    data.index = formatted_dates

    # Current date
    current_date = datetime.today().date()

    # Get current time in Berlin timezone
    berlin_timezone = pytz.timezone('Europe/Berlin')
    current_time = datetime.now(berlin_timezone).time()

    # Check if it's after 22:00
    if current_date.weekday() == 0:  # Monday
        if current_time.hour < 9 or (current_time.hour == 9 and current_time.minute < 30):
            date = -4  # Last Friday's close
        elif current_time.hour >= 22:
            date = -3  # Friday's close
        else:
            date = -2  # Yesterday's close
    elif current_date.weekday() == 6:  # Sunday
        if current_time.hour < 9 or (current_time.hour == 9 and current_time.minute < 30):
            date = -3  # Last Friday's close
        elif current_time.hour >= 22:
            date = -2  # Friday's close
        else:
            date = -1  # Yesterday's close
    else:
        if current_time.hour < 9 or (current_time.hour == 9 and current_time.minute < 30):
            date = -3  # Last Friday's close
        elif current_time.hour >= 22:
            date = -2  # Yesterday's close
        else:
            date = -1  # Yesterday's close

    if len(data) >= abs(date):
        last_price = data['Close'].iloc[date]

        # Query current price
        ticker = yf.Ticker(tickersymbol)
        info = ticker.info

        currentPrice = info['currentPrice']

        price_change = currentPrice - last_price
        change_1d_Vtop = (price_change / last_price) * 100
        change_1d_Vtop = round(change_1d_Vtop, 2)
        return change_1d_Vtop
    else:
        print("Not enough data available for the specified period.")
        return None
geraldfo
User
Beiträge: 73
Registriert: Samstag 28. Januar 2023, 20:19
Wohnort: Nähe Wien
Kontaktdaten:

Welches Problem hast du konkret?
Benutzeravatar
__blackjack__
User
Beiträge: 14053
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@ColaOfficial: Das ``global`` hat da nichts zu suchen. Ein Wert davon wird bereits als Rückgabewert an den Aufrufer übertragen. Fall er die anderen beiden auch benötigen sollte, dann sind das halt auch Rückgabewerte.

Wenn man einen Zeitpunkt ermitteln will dann muss man das genau *einmal* machen, denn sonst ermittelt man ja mehr als einen Zeitpunkt, da zwischen den Aufrufen Zeit vergeht. Wenn man dann von dem einen Aufruf nur das Datum und von dem anderen nur die Zeit verwendet, dann müssen die nicht mehr zusammenpassen. Denn es kann ja sein, dass zwischen beiden Aufrufen sich das Datum geändert hat. Dann wäre man fast 24 Stunden daneben was den Zeitpunkt angeht mit dem man dann rechnet.

Man muss das auch gar nicht erst auf zwei Objekte aufteilen, sondern kann das bei einem `datetime`-Objekt belassen.

Und das einmal ein Zeitpunkt mit Zeitzone und einmal ohne verwendet wird, ist auch schräg bis fehlerhaft.

Kommentare sollen dem Leser einen Mehrwert über den Code geben. Faustregel: Kommentare beschreiben nicht *was* der Code macht, denn das steht da bereits als Code, sondern warum er das macht. Sofern das nicht offensichtlich ist. Offensichtlich ist in aller Regel auch was in der Dokumentation von Python und den verwendeten Bibliotheken steht.

Die Formatzeichenkette bei `strftime()` wird extrem komisch und verwirrend angegeben, als drei Zeichenketten die vom Compiler automatisch zusammengefügt werden. Das macht man wenn man eine Zeichenkette auf mehrere Zeilen aufteilen will, aber nicht bei *so* kurzen Teilzeichenketten die direkt nebeneinander stehen.

Inhaltlich ist das auch komisch formatiert mit den "/" als Trennzeichen und der Uhrzeit vor dem Datum. Zudem wird das auch überhaupt gar nicht verwendet, ist also komplett überflüssig das zu machen.

Der ``else``-Zweig und der ``elif``-Zweig davor enthalten den gleichen Code, womit der ``elif``-Zweig überflüssig ist — oder die sollten vielleicht nicht den gleichen Code enthalten.

Wie kann sowohl -2 als auch -1 für „Yesterday's close“ stehen? Mindestens einer der beiden Kommentare muss falsch sein.

``if now.hour < 9 or (now.hour == 9 and now.minute < 30):`` ist unnötig umständlich. Das ist kürzer und leichter verständlich: ``if (now.hour, now.minute) < (9, 30):``

Mir erschliesst sich die Logik dort auch nicht so ganz. Wenn es vor 9:30 Uhr ist gehe drei Tage zurück, ab 22 Uhr gehe zwei Tage zurück, sonst gehe einen Tag zurück‽

`date` ist als Name falsch für eine relative Anzahl von Tagen.

Der Code geht auch stillschweigend davon aus, dass für jeden Tag genau ein Eintrag in dem Dataframe ist. Kann man das einfach so als gegeben nehmen? Kann es dort tatsächlich keine Ausfälle geben? Selbst wenn es das nie geben kann, würde ich da trotzdem drauf prüfen. Passiert gar nicht so selten, dass Eingabedaten von aussen, die es so nie geben kann, dann doch mal nicht dem erwarteten entsprechen. Der Code würde dann einfach mit einem falschen Wert weiterarbeiten.

Namen werden in Python klein_mit_unterstrichen geschrieben. Ausnahmen sind Konstanten (KOMPLETT_GROSS) und Klassen (PascalCase).

`round()` verwendet man nur wenn man mit dem gerundeten Wert tatsächlich weiterrechnen will. Das ist nicht Aufgabe dieser Funktion das zu entscheiden.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Antworten