예제 #1
0
    def get(self, request, *args, **kwargs):
        """ 
        Hier werden alle benötigten Daten für das Konfigurieren einer Simulation geholt. Dazu gehören alle verfügbaren Strategien 
        und alle verfügbaren finanziellen Instrumente, auf denen eine Simulation laufen kann. 
        Diese werden an das Template über den Context weitergegeben. Die getroffene Wahl wird über JavaScript in das entsprechende Formular Feld geschrieben
        """
        Simulation.objects.all().delete() # Alle erstellten Objekte löschen. Diese werden temporär erstellt um verlustfreies Anzeigen von Daten zu garantieren

        self.object  = None # CreateView braucht irgendein Object, None ist dabei ein valider Wert
        context      = super().get_context_data(**kwargs) 

        # Hier werden alle Strategie-Daten bezogen.
        serverAntwort = datenAnBackendSenden(
            hauptPfad = "strategie/", 
            unterPfad = "getalle", 
            daten = {
                "benutzer_id" : request.user.username,
            }
        )
        # Wenn Fehler enthalten, auf FehlerSeite weiterleiten, ansonsten Strategie Daten im Context speichern.
        if(allgemeineFehlerPruefung(serverAntwort,request)):
            return redirect(reverse('simulation:simulation-fehler'))  
        context['strategien'] = serverAntwort["strategien"]
        # ------------------------
        
        # Hier werden alle ISIN-Daten bezogen.
        serverAntwort = datenAnBackendSenden(
            hauptPfad = "isin/", 
            unterPfad = "getalle", 
            daten = {
                "benutzer_id": request.user.username,
            }
        )
        if(allgemeineFehlerPruefung(serverAntwort,self.request)):
            return redirect(reverse('simulation:simulation-fehler'))  
        
        alleIsins = []
        """ 
        Die ISINs können Indizes und Währungen enthalten. 
        Indices können anhand zwei verschiedener Attribute (ist_index == True und einheit == "Punkte") identifiziert werden
        Währungen können anhand der Einheit identifiziert werden (einheit == "undefiniert")
        Alle ISINs die nicht diese Attribute haben, werden in eine separate Liste gespeichert und schließlich im Context gespeichert
        """
        for isin in serverAntwort["isins"]:
            if(not isin["ist_index"] and isin["einheit"] != "Punkte" and isin["einheit"] != "undefiniert"):
                alleIsins.append(isin)
                
        serverAntwort["isins"] = alleIsins
        context['isins'] = serverAntwort["isins"]
        # ------------------------
        return self.render_to_response(context)
예제 #2
0
    def get(self, request, *args, **kwargs):
        """
            Holt alle verfügbaren Regeln für die Darstellung.

            Hier wird die get_context_data-Funktion der CreateView-Klasse überschrieben.
            Es wird mit datenAnBackendSenden versucht die Daten zu holen. 
            Auf die dabei potentiell entstandenen Fehler wird in allgemeineFehlerPruefung geprüft.
            Bei vorhandenen Fehlern wird von der Funktion ein True zurückgegeben
            was zu einem Redirect auf die FehlerView führt. Bei False wird die 
            serverAntwort im Context gespeichert, um eine Darstellung der Regeln zu ermöglichen"""
        serverAntwort = datenAnBackendSenden(hauptPfad="regel/",
                                             unterPfad="getalle",
                                             daten={
                                                 "benutzer_id":
                                                 self.request.user.username,
                                             })

        if (allgemeineFehlerPruefung(serverAntwort, self.request)):
            return redirect(reverse("strategie:strategie-fehler"))

        self.object = Strategie()
        context = self.get_context_data(object=self.object)
        context["regeln"] = serverAntwort["regeln"]
        context["appName"] = appName
        return self.render_to_response(context)
예제 #3
0
    def form_valid(self, form):
        """
        Hier werden die Eingabedaten des Nutzers an das Backend gesendet. 
        Wenn dabei Fehler entstanden sind, wird auf die Fehlerseite weitergeleitet. 
        Ansonsten wird mit dem return von super.form_valid automatisch ein Simulations-Objekt erstellt, get_absolute_url des Objekts aufgerufen und
        somit auf die Simulations-Ergebnis-Ansicht weitergeleitet.

        """
        simulationsDaten = datenAnBackendSenden(
            hauptPfad = globalerHauptPfad, 
            unterPfad = "", 
            daten     = {
                "benutzer_id"   : self.request.user.username,
                "strategie_id"  : int(form.cleaned_data["strategie"]),
                "isin"          : form.cleaned_data["isin"],
                "start_kapital" : int(form.cleaned_data["startkapital"]),
                "start_datum"   : str(form.cleaned_data["von_datum"]),
                "end_datum"     : str(form.cleaned_data["bis_datum"])
            }
        )

        if(allgemeineFehlerPruefung(simulationsDaten, self.request)):
            return redirect(reverse('simulation:simulation-fehler'))  
        else:
            self.request.session["simulationsDaten"] = simulationsDaten
            return super().form_valid(form) 
예제 #4
0
def pruefeObEigeneSkala(ID, callerSelf):
    """
        Funktion zum Prüfen ob ein Indikator mit der angegebenen ID eine eigene Skala hat. 
        Hierbei werden die Indikatordaten geholt und, wenn kein Fehler aufgetreten ist, der Wert für eigene_skala zurückgegeben
        """
    serverAntwort = datenAnBackendSenden(hauptPfad="indikator/",
                                         unterPfad="get",
                                         daten={
                                             "id":
                                             int(ID),
                                             "benutzer_id":
                                             callerSelf.request.user.username,
                                         })

    if (allgemeineFehlerPruefung(serverAntwort, callerSelf.request)):
        return redirect(reverse('simulation:simulation-fehler'))

    return serverAntwort["indikator"]["eigene_skala"]
예제 #5
0
    def get_context_data(self, *args, **kwargs):
        """
            Holt die Daten aller Regeln. Die Daten der verwendeten Regel werden in eine eigene Liste gespeichert.

        """

        context = super().get_context_data(**kwargs)

        # Daten an Backend senden.
        serverAntwort = datenAnBackendSenden(
            hauptPfad="regel/",
            unterPfad="getalle",
            daten={"benutzer_id": self.request.user.username})

        # ServerAntwort auf Fehler prüfen. Bei gefundenen Fehler auf FehlerSeite leiten.
        if (allgemeineFehlerPruefung(serverAntwort, self.request)):
            return redirect(reverse("strategie:strategie-fehler"))

        verwendeteRegelListe = []

        # Liste mit verwendeten Regeln erstellen.

        for verwendeteRegel in self.request.session["verwendete-regeln"]:

            for regel in serverAntwort["regeln"]:
                if (regel["id"] == verwendeteRegel):
                    verwendeteRegelListe.append(regel)

        for i in verwendeteRegelListe:
            print(i["id"])
        # Alle Regeln im Context speichern
        context["regeln"] = serverAntwort["regeln"]

        # Alle verwendeten Regeln im Context speichern
        context["verwendeteRegeln"] = verwendeteRegelListe
        # Den bearbeitbar-Wert in Context speichern. Wichtig für DetailAnsicht
        context["bearbeitbar"] = self.request.session["bearbeitbar"]
        return context
예제 #6
0
    def get(self, request):
        """
        Diese Funktion holt sich alle Daten die benötigt werden für das Darstellen der Simulations-Ergebnisse.
        Dazu gehören die Aktienkurs Daten der zum simulieren verwendeten ISIN und die Simulationsergebnisse.

        """
        if ("konfigDaten" not in request.session):
            request.session[
                "fehler"] = "Keine Simulationsdaten vorhanden. Versuchen Sie es nochmal..."
            return redirect(reverse('simulation:simulation-fehler'))

            # Zuletzt erstelltes Objekt holen

# Prüfen ob es existiert, wenn nicht, auf FehlerSeite weiterleiten und entsprechende Fehlermeldung in session speichern.

        konfigDaten = request.session["konfigDaten"]

        strategie_id = konfigDaten["strategie_id"]
        isin = konfigDaten["isin"]
        start_kapital = konfigDaten["start_kapital"]
        start_datum = konfigDaten["start_datum"]
        end_datum = konfigDaten["end_datum"]
        # Hier werden die Simulation-Konfigurations-Daten an das Backend geschickt.
        simulationsDaten = datenAnBackendSenden(hauptPfad=globalerHauptPfad,
                                                unterPfad="",
                                                daten={
                                                    "benutzer_id":
                                                    self.request.user.username,
                                                    "strategie_id":
                                                    strategie_id,
                                                    "isin":
                                                    isin,
                                                    "start_kapital":
                                                    start_kapital,
                                                    "start_datum":
                                                    start_datum,
                                                    "end_datum":
                                                    end_datum,
                                                })
        # Bei Fehlern auf Fehlerseite weiterleiten
        if (allgemeineFehlerPruefung(simulationsDaten, request)):
            return redirect(reverse('simulation:simulation-fehler'))
        #------------------

        self.request.session[
            "simulationsDaten"] = simulationsDaten  # Simulationsdaten in Session speichern um für die Funktion downloadCSV zugänglich zu machen

        #Von- und Bis-Datum in passendes Format TT.MM.JJJJ umwandeln
        vonDatumAnzeigeFormat = datetime.strptime(
            start_datum, '%Y-%m-%d').strftime('%d.%m.%Y')
        bisDatumAnzeigeFormat = datetime.strptime(
            end_datum, '%Y-%m-%d').strftime('%d.%m.%Y')

        # AnzeigeDaten Dict für Template zusammenbauen
        anzeigeDaten = {
            "strategie_id": strategie_id,
            "strategie_name": simulationsDaten["strategie"]["name"],
            "isin": simulationsDaten["wertpapier"]["isin"],
            "name": simulationsDaten["wertpapier"]["name"],
            "start_kapital": start_kapital,
            "start_datum": start_datum,
            "end_datum": end_datum,
            "statistik": simulationsDaten["strategie_statistik"],
        }

        # Statistischen Werte auf 3 Nachkommestellen kürzen
        anzeigeDaten["statistik"]["performance_gesamt"] = '%.3f' % (float(
            anzeigeDaten["statistik"]["performance_gesamt"]))
        anzeigeDaten["statistik"]["performance_pro_jahr"] = '%.3f' % (float(
            anzeigeDaten["statistik"]["performance_pro_jahr"]))
        anzeigeDaten["statistik"]["hoch_gesamt"] = '%.3f' % (float(
            anzeigeDaten["statistik"]["hoch_gesamt"]))
        anzeigeDaten["statistik"]["tief_gesamt"] = '%.3f' % (float(
            anzeigeDaten["statistik"]["tief_gesamt"]))
        anzeigeDaten["statistik"]["maximum_drawdown"] = '%.3f' % (float(
            anzeigeDaten["statistik"]["maximum_drawdown"]))

        # Alle Koordinatensysteme erstellen

        p1 = figure(  # p1 ist Koordinatensystem mit Aktienkurs als Candlesticks
            plot_width=1000,
            plot_height=700,
            x_axis_type="datetime",
            tools="pan, wheel_zoom, box_zoom, reset, save"  # verfügbaren Tools
        )
        p2 = figure(  # p2 ist Koordinatensystem mit Aktienkurs als Linie
            plot_width=1000,
            plot_height=700,
            x_axis_type="datetime",
            tools="pan, wheel_zoom, box_zoom, reset, save",
            x_range=p1.
            x_range,  # Verschiebungen entlang der X-Achse von p1 übernehmen
            y_range=p1.
            y_range  # Verschiebungen entlang der Y-Achse von p1 übernehmen
        )
        p3 = figure(  # p3 ist Koordinatensystem für Performance-Entwicklung
            plot_width=1000,
            plot_height=700,
            x_axis_type="datetime",
            tools="pan, wheel_zoom, box_zoom, reset, save",
            x_range=p1.
            x_range  # Verschiebungen entlang der X-Achse von p1 übernehmen
            # Verschiebung entlang der Y-Achse wird nicht übernommen, da es keinen Sinn ergibt.
        )
        plotListe = [p1, p2, p3]  # Alle Koordinatensyteme in eine Liste

        indikatoren = simulationsDaten[
            "indikator_zeitreihe"]  # Alle indikatordaten werden in einem eigenen Objekt gespeichert
        keyList = []
        listenDict = {}

        # Jeder einzelne Key wird in die Key-Liste gespeichert und für jeden Key wird im ListenDict eine leere Liste erstellt.
        # Der erste key ist immer der Zeitstempel, die darauf folgenden sind die keys der Indikatoren
        for key in indikatoren[0]:
            keyList.append(key)
            listenDict[key] = []

        # daten im indikatoren-Objekt werden aufgeteilt und abhängig vom key an die entsprechende Liste im listenDict angefügt.
        for daten in indikatoren:
            for key in keyList:
                listenDict[key].append(daten[key])

        # Farb-Palette für das Darstellen der Graphen in verschiedenen Farben
        colors = itertools.cycle(palette)

        # Alle benötigten DataFrames generieren und deren Zeitstempel entsprechend formatieren
        zeitstempelDataFrame = pd.DataFrame(listenDict["zeitstempel"],
                                            columns=['zeitstempel'])
        zeitstempelDataFrame["zeitstempel"] = pd.to_datetime(
            zeitstempelDataFrame["zeitstempel"])

        kursZeitreiheDF = pd.DataFrame(simulationsDaten["kurs_zeitreihe"])
        kursZeitreiheDF["zeitstempel"] = pd.to_datetime(
            kursZeitreiheDF["zeitstempel"])

        stratZeitreiheDF = pd.DataFrame(
            simulationsDaten["strategie_kurs_zeitreihe"])
        stratZeitreiheDF["zeitstempel"] = pd.to_datetime(
            stratZeitreiheDF["zeitstempel"])

        kaufVerkaufDF = pd.DataFrame(
            simulationsDaten["strategie_kaeufe_verkaeufe_zeitreihe"])

        inc = kursZeitreiheDF.close > kursZeitreiheDF.open  # inc ist ein boolean, welcher True zurückgibt wenn Close > Open
        dec = kursZeitreiheDF.open > kursZeitreiheDF.close  # dec ist ein boolean, welcher True zurückgibt wenn Open > Close
        w = 12 * 60 * 60 * 1000  # halber Tag in ms, für die Breite der Kerzen

        # Hier werden die einzelnen Elemente der Kerze zum Koordinatensystem p1 hinzugefügt

        p1.segment(  # Hier werden die High und Lows für jeden Tag erstellt, dargestellt durch zwei verbunde Punkte 
            kursZeitreiheDF.zeitstempel,  # X Werte für Punkt 1
            kursZeitreiheDF.high,  # Y Werte für Punkt 1
            kursZeitreiheDF.zeitstempel,  # X Werte für Punkt 2 
            kursZeitreiheDF.low,  # Y Werte für Punkt 2
            color="black",
            legend_label=simulationsDaten["wertpapier"]["name"] +
            " - High-Low")

        p1.vbar(  # Hier werden die grünen Kerzen "Torsos" erstellt, dargestellt durch Balken je einem X-Wert, zwei Y-Werten und einer Breite
            kursZeitreiheDF.zeitstempel[inc],  # X Werte der Balken 
            w,  # Breite 
            kursZeitreiheDF.open[inc],  # Y1 Werte der Balken
            kursZeitreiheDF.close[inc],  # Y2 Werte der Balken
            fill_color="green",
            line_color="black",
            legend_label=simulationsDaten["wertpapier"]["name"] +
            " - Grüne Kerzen")

        p1.vbar(  # Hier werden die roten Kerzen "Torsos" erstellt, dargestellt durch Balken je einem X-Wert, zwei Y-Werten und einer Breite
            kursZeitreiheDF.zeitstempel[dec],  # X Werte der Balken 
            w,  # Breite 
            kursZeitreiheDF.open[dec],  # Y1 Werte der Balken
            kursZeitreiheDF.close[dec],  # Y2 Werte der Balken
            fill_color="red",
            line_color="black",
            legend_label=simulationsDaten["wertpapier"]["name"] +
            " - Rote Kerzen")
        # ---------------------------------

        p2.line(  # Hier wird der Aktienkurs als Linie zu dem Koordinatensystem p2 hinzugefügt
            kursZeitreiheDF.zeitstempel,  # X Werte der Linie
            kursZeitreiheDF.close,  # Y Werte der Linie
            line_width=3,
            color="red",
            alpha=0.5,
            legend_label=simulationsDaten["wertpapier"]["name"])
        p3.line(  # Hier wird die Performance als Linie zu dem Koordinatensystem p3 hinzugefügt
            stratZeitreiheDF.zeitstempel,
            stratZeitreiheDF.kurs_prozentual,
            line_width=3,
            color="black",
            alpha=0.5,
            legend_label="Kapital in Prozent")

        # Für jeden Key in der KeyListe
        for key in keyList:
            # Der nicht gleich zeitstempel, also für jeden Indikator
            if (key != "zeitstempel"):
                # wird ein eigenes DataFrame angelegt mit den entsprechenden Daten aus listenDict
                elementDataFrame = pd.DataFrame(listenDict[key])

                # Wenn Indikator eine eigene Skala braucht, wird ein neues Koordinatensystem erstellt
                inEigenesKoord = False
                if (pruefeObEigeneSkala(key, self)):
                    newPlot = figure(
                        plot_width=1000,
                        plot_height=700,
                        x_axis_type="datetime",
                        tools=
                        "pan, wheel_zoom, box_zoom, reset, save, crosshair",
                        x_range=p1.
                        x_range  # Verschiebungen entlang der X-Achse von p1 übernehmen
                    )
                    inEigenesKoord = True

                # für jeden key in diesem DataFrame, also für jeden Graph des Indikators
                for graph in listenDict[key][0].keys():
                    # wird eine eigene Linie erstellt mit den entsprechenden Y-Werten. Die X-Werte werden dabei vom ZeitstempelDataFrame übernommen,
                    # um es einheitlich zu halten
                    line = pd.concat(
                        [zeitstempelDataFrame, elementDataFrame[graph]],
                        axis=1)

                    # Wenn eigenes Koordianten System erstellt wurde, an dieses Koordinatensystem fügen
                    if (inEigenesKoord):
                        newPlot.line(zeitstempelDataFrame["zeitstempel"],
                                     line[graph],
                                     line_width=3,
                                     color=next(colors),
                                     alpha=1,
                                     legend_label="ID " + key + " - " + graph)

                    # Ansonsten in beide Koordinatensystemen p1 und p2
                    else:
                        for plot in [p1, p2]:
                            plot.line(
                                zeitstempelDataFrame["zeitstempel"],
                                line[graph],
                                line_width=3,
                                color=next(colors),
                                alpha=1,
                                legend_label="ID " + key + " - " + graph,
                            )

                # Wenn eigenes Koordinatensystem erstellt wurde, dann dieses zur KoordinatenSystem Liste hinzufügen
                if (inEigenesKoord):
                    plotListe.append(newPlot)

        # Wenn das KaufVerkaufDataFrame nicht leer ist
        if (not kaufVerkaufDF.empty):
            # boolischen Ausdrücke generieren
            kauf = kaufVerkaufDF.typ == "Kauf"
            verkauf = kaufVerkaufDF.typ == "Verkauf"

            # In beide Koordinatensystemen p1 und p2 werden die Markierungen für Käufe und Verkäufe eingefügt
            hauptPlotListe = [p1, p2]
            for plot in hauptPlotListe:
                plot.circle(  # Punkte für Käufe
                    pd.to_datetime(
                        kaufVerkaufDF.zeitstempel[kauf]
                    ),  # X-Werte, Zeitstempel der Daten wenn TransaktionsTyp = Kauf
                    # Für die Y-Werte wird der Kaufpreis der Aktie berechnet. Also die Menge an ausgegebenem Kapital durch die Anzahl der gekauften Aktien
                    (-1) * (kaufVerkaufDF.kapital_bestand_aenderung[kauf] /
                            kaufVerkaufDF.stueck_bestand_aenderung[kauf]),
                    size=20,
                    color="blue",
                    alpha=0.5,
                    legend_label="Käufe")
                plot.circle(  # Punkte für Verkäufe
                    pd.to_datetime(
                        kaufVerkaufDF.zeitstempel[verkauf]
                    ),  # X-Werte Zeitstempel der Daten wenn TransaktionsTyp = Verkauf
                    # Für die Y-Werte wird der Verkaufspreis der Aktie berechnet. Also die Menge an erhaltenem Kapital durch die Anzahl der verkauften Aktien
                    (-1) * (kaufVerkaufDF.kapital_bestand_aenderung[verkauf] /
                            kaufVerkaufDF.stueck_bestand_aenderung[verkauf]),
                    size=20,
                    color="yellow",
                    alpha=0.5,
                    legend_label="Verkäufe")

        # Hier werden alle Legenden Einstellungen und allg. Koordinaten System Einstellungen gemacht
        for plot in plotListe:
            plot.legend.location = "top_left"
            plot.legend.title = 'Graphen'
            plot.legend.title_text_font_style = "bold"
            plot.legend.title_text_font_size = "20px"
            plot.legend.click_policy = "hide"

            plot.output_backend = "svg"
            plot.background_fill_color = "#f5f5f5"
            plot.grid.grid_line_color = "white"
            plot.axis.axis_line_color = None
            plot.xaxis.major_label_orientation = pi / 4

        # script, div = components(Tabs(tabs=[tab1, tab2]))
        script, div = components(column(plotListe))

        return render(
            request, 'modulViews/generisch_ansicht_plotErgebnis.html', {
                'script': script,
                'div': div,
                'daten': anzeigeDaten,
                "appName": "simulation"
            })
예제 #7
0
    def get(self, request, *args, **kwargs):
        """
            Hier werden die benötigten Indikator- und Kursdaten geholt und in die entsprechenden Graphiken eingefügt.

            Es werden mit der Bibliothek "bokeh" für die Kursdaten als Referenzwert und die Daten des Indikators die entsprechenden Graphen generiert.
            Es werden insgesamt 2 Koordinaten-Systeme generiert.
            Im ersten sind die Aktienkurse-Daten des DAX als Candles dargestellt sowie alle Graphen des ausgewählten Indikators.
            Im zweiten sind die Aktienkurse-Daten des DAX als Linie dargestellt sowie alle Graphen des ausgewählten Indikators.
            Bei beiden Koordinaten-Systemen wird der Zeitraum vom 01.0.1.2019 bis 31.12.2020 dargestellt.
        """
        daten = {
            "id": self.kwargs.get("id"),
            "benutzer_id": self.request.user.username,
            "isin": "DE0008469008",
            "start_datum": "2019-01-01",
            "end_datum": "2020-12-31"
        }

        # Kurs daten werden hier geholt --------------
        aktienkursDaten = datenAnBackendSenden(hauptPfad="kurs",
                                               unterPfad="/get",
                                               daten=daten)

        # Prüfen ob kein Fehler entstanden ist
        # Wenn ja auf FehlerSeite leiten
        if (allgemeineFehlerPruefung(serverAntwort=aktienkursDaten,
                                     request=request)):
            return redirect(reverse('indikator:indikator-fehler'))
        # -----------------------

        # Indikatorgraph-Daten werden hier geholt, angewandt auf der oben festgelegten ISIN
        serverAntwort = datenAnBackendSenden(hauptPfad="indikator",
                                             unterPfad="/auswerten",
                                             daten=daten)
        # Prüfen ob kein Fehler entstanden ist
        # Wenn ja auf FehlerSeite leiten
        if (allgemeineFehlerPruefung(serverAntwort=serverAntwort,
                                     request=request)):
            return redirect(reverse('indikator:indikator-fehler'))
        # -----------------------

        indikatorenDaten = serverAntwort[
            "indikator_zeitreihe"]  # Die Indikatordaten werden für eine einfachere Verarbeitung in ein eigenes Objekt kopiert.
        keyListe = indikatorenDaten[0].keys()
        listenDict = {}

        # ersetze alle Leerzeichen mit der Leerzeichen Entity
        serverAntwort["indikator"]["berechnung_pseudo_code"] = serverAntwort[
            "indikator"]["berechnung_pseudo_code"].replace(" ", "&nbsp")
        # ersetze vier aufeinander folgende Leerzeichen durch zu 4 Leerzeichen Entity
        serverAntwort["indikator"]["berechnung_pseudo_code"] = serverAntwort[
            "indikator"]["berechnung_pseudo_code"].replace(
                "	", "&nbsp&nbsp&nbsp&nbsp")

        # Für jeden key wird eine Leere Liste im listenDict angelegt
        for key in keyListe:
            listenDict[key] = []

        # Jeder Datensatz in den IndikatorDaten wird an die entsprechende Liste im ListenDict Dictionary angehängt
        for datensatz in indikatorenDaten:
            for key in keyListe:
                listenDict[key].append(datensatz[key])

        p1 = figure(  # Koordinaten-System Deklaration
            plot_width=1000,
            plot_height=700,
            x_axis_type="datetime",
            tools="pan,wheel_zoom,box_zoom,reset,save")
        p2 = figure(  # Koordinaten-System Deklaration
            plot_width=1000,
            plot_height=700,
            x_axis_type="datetime",
            tools="pan,wheel_zoom,box_zoom,reset,save",
            x_range=p1.x_range,
            y_range=p1.y_range)

        plotListe = [p1, p2]
        # Wandelt die zeitstempel Daten in ein DataFrame um
        zeitstempelDataFrame = pd.DataFrame(listenDict["zeitstempel"],
                                            columns=['zeitstempel'])
        # Die Daten in der Spalte "zeitstempel" müssen in das entsprechende Format umgewandelt werden
        zeitstempelDataFrame["zeitstempel"] = pd.to_datetime(
            zeitstempelDataFrame["zeitstempel"])

        #Wandelt die kurs_zeitreihe Daten in ein DataFrame um
        aktienKursDataFrame = pd.DataFrame(aktienkursDaten["kurs_zeitreihe"])
        # Die Daten in der Spalte "zeitstempel" müssen in das entsprechende Format umgewandelt werden
        aktienKursDataFrame["zeitstempel"] = pd.to_datetime(
            aktienKursDataFrame["zeitstempel"])

        # Boolean der prüft, ob aktienKursDataFrame.close größer aktienKursDataFrame.open
        inc = aktienKursDataFrame.close > aktienKursDataFrame.open
        # Boolean der prüft, ob aktienKursDataFrame.close kleiner aktienKursDataFrame.open
        dec = aktienKursDataFrame.close < aktienKursDataFrame.open
        kerzenBreite = 12 * 60 * 60 * 1000  # halber Tag in ms, für die Breite der Kerzen

        #Jeder "Punkt" eines segment ist eine Linie die aus zwei Koordinaten-Paaren besteht.
        p1.segment(  # Hier werden die High und Lows für jeden Tag erstellt
            aktienKursDataFrame.zeitstempel,  # Paar-1 Werte für x-Achse 
            aktienKursDataFrame.high,  # Paar-1 Werte für y-Achse 
            aktienKursDataFrame.zeitstempel,  # Paar-2 Werte für x-Achse 
            aktienKursDataFrame.low,  # Paar-2 Werte für y-Achse 
            color="black",
            legend_label="High-Low-Linien")
        # Jedes "Punkt" einer vbar ist ein Rechteck mit einem x-Wert, einer Breite, und zwei Werten für die y-Achse (Rechteck-Höhe)
        p1.vbar(  # Hier werden die grünen Kerzen "Torsos" erstellt
            aktienKursDataFrame.zeitstempel[inc],  # Werte für x-Achse 
            kerzenBreite,
            aktienKursDataFrame.open[inc],  # Teil 1 Werte für y-Achse
            aktienKursDataFrame.close[inc],  # Teil 2 Werte für y-Achse
            fill_color="green",
            line_color="black",
            legend_label="Grüne Candlesticks")

        p1.vbar(  # Hier werden die roten Kerzen "Torsos" erstellt
            aktienKursDataFrame.zeitstempel[dec],  # Werte für x-Achse 
            kerzenBreite,
            aktienKursDataFrame.open[dec],  # Teil 1 Werte für y-Achse
            aktienKursDataFrame.close[dec],  # Teil 2 Werte für y-Achse
            fill_color="red",
            line_color="black",
            legend_label="Rote Candlesticks",
        )

        #Jeder Punkt einer line braucht ein Koordinaten-Paar
        p2.line(  # Hier wird der Aktienkurs als Linie erstellt
            aktienKursDataFrame.zeitstempel,  # Werte für x-Achse 
            aktienKursDataFrame.close,  # Werte für y-Achse 
            line_width=3,
            color="red",
            alpha=0.5,
            legend_label="DAX")

        farben = itertools.cycle(palette)  # Farbenauswahl

        for key in keyListe:
            if (key != "zeitstempel"):
                # Jede einzelne Liste im ListenDict wird in ein DataFrame umgewandelt, außer die Liste mit dem key "zeitstempel"
                elementDataFrame = pd.DataFrame(listenDict[key])
                for graph in listenDict[key][0].keys():

                    # für eine korrekte Darstellung müssen alle Graphen das selbe Zeitstempel DataFrame verwenden
                    # hier werden die Graphen-Werte der einzelnen Graphen mit den Zeitstempeln des zeitstempelDataFrame zu einen einzigen DataFrame vereinigt
                    angepassteDatenPunkte = pd.concat(
                        [zeitstempelDataFrame, elementDataFrame[graph]],
                        axis=1)
                    farbe = next(farben)
                    # und in beide Koordinatensysteme eingefügt
                    if (serverAntwort["indikator"]["eigene_skala"]):
                        p3 = figure(  # Koordinaten-System Deklaration
                            plot_width=1000,
                            plot_height=700,
                            x_axis_type="datetime",
                            tools="pan,wheel_zoom,box_zoom,reset,save",
                            x_range=p1.x_range)
                        p3.line(  # 
                            zeitstempelDataFrame["zeitstempel"],
                            angepassteDatenPunkte[graph],
                            line_width=3,
                            color=farbe,
                            alpha=1,
                            legend_label="ID " + key + " - " + graph,
                        )
                        plotListe.append(p3)

                    else:
                        for plot in plotListe:
                            plot.line(
                                zeitstempelDataFrame["zeitstempel"],
                                angepassteDatenPunkte[graph],
                                line_width=3,
                                color=farbe,
                                alpha=1,
                                legend_label="ID " + key + " - " + graph,
                            )

        # An beide Koordinaten-Systeme werden die gleichen Legenden Einstellungen sowie Stylingattribute vergeben
        for plot in plotListe:
            #Legenden Einstellung
            plot.legend.location = "top_left"
            plot.legend.title = 'Graphen'
            plot.legend.title_text_font_style = "bold"
            plot.legend.title_text_font_size = "20px"
            plot.legend.click_policy = "hide"
            #Koordinaten-System Styling
            plot.background_fill_color = "#f5f5f5"
            plot.grid.grid_line_color = "white"
            plot.axis.axis_line_color = None
            plot.xaxis.major_label_orientation = pi / 4

        tab1 = Panel(child=p1, title="Candlesticks")
        tab2 = Panel(child=p2, title="Linie")
        if (len(plotListe) == 2):
            script, div = components(Tabs(tabs=[tab1, tab2]))
        else:
            script, div = components(column(Tabs(tabs=[tab1, tab2]), p3))
        return render(
            request, 'indikator/indikator_graph.html', {
                'script': script,
                'div': div,
                'daten': serverAntwort["indikator"],
                'bearbeitbar': self.request.session["bearbeitbar"]
            })