Die Folge der Kerzen durchläuft die Laufzeit. Innerhalb einer einzelnen Kerze kannst du selbst Wiederholungen brauchen, etwa um die letzten fünf Schlusskurse zu addieren. Dafür gibt es Schleifen.

for und range

for offset in range(5):
    total += close[offset]

Bei range(5) erhält die Variable offset nacheinander die Werte 0, 1, 2, 3 und 4. Die 5 ist nicht mehr enthalten. Die eingerückte Zeile läuft mit jedem dieser Werte einmal.

close[offset] bezeichnet somit zuerst den aktuellen Schlusskurs, dann den eine, zwei, drei und vier Kerzen zuvor. Wir addieren genau fünf Werte.

Vor der Schleife muss total auf null gesetzt werden. Sie ist ein Zwischenergebnis der Berechnung für eine Kerze, kein zwischen Kerzen gespeicherter Zähler.

range(1, 5) ergibt eine andere Folge: 1, 2, 3, 4. Der Anfangswert ist enthalten, der Endwert nicht. Ohne angegebenen Anfangswert beginnen wir bei null.

Ein selbst geschriebener gleitender Durchschnitt

Lege die Datei manual_average.py an:

"""
@pyne edge
"""
from pynecore.lib import close, color, input, plot, script, ta


@script.indicator("Manual Average Check", overlay=False)
def main(
    length: int = input.int(5, title="Length", minval=1, maxval=100),
):
    total = 0.0
    for offset in range(length):
        total += close[offset]
    manual_average = total / length
    builtin_average = ta.sma(close, length)
    difference = manual_average - builtin_average
    plot(difference, "Difference", color=color.blue)

Führe sie auf den Demodaten aus. Die Linie zeigt die Differenz zwischen dem eigenen Durchschnitt und dem fertigen SMA. Nach der Aufwärmphase muss sie bei null oder wegen der Zahlendarstellung sehr nahe an null verlaufen.

Neben manual_average.py zeigt ein eigenes Panel der PyneIDE die Differenz der beiden Durchschnitte.
Die Differenz zwischen der eigenen Schleife und dem fertigen SMA bleibt nach der Aufwärmphase ungefähr null.

Wir zeichnen keine zwei überlappenden Linien, denn daran wären kleine Unterschiede schwer zu erkennen. Die Differenz zeigt direkt, ob beide Berechnungen übereinstimmen.

Was passiert bei einer Ausführung?

Bei Länge fünf ist die Reihenfolge:

  1. total wird auf null gesetzt.
  2. Die Schleife addiert den aktuellen und die vier vorherigen Schlusskurse.
  3. Wir teilen die Summe durch fünf.
  4. Wir berechnen auch den fertigen SMA und bilden die Differenz zu unserem eigenen Ergebnis.
  5. Wir zeichnen einen einzigen Punkt für die Differenzlinie.

Dann geht die Laufzeit zur nächsten Kerze. Dort beginnt total wieder bei null, und die Schleife addiert die fünf Werte, die zur neuen Kerze gehören.

Würdest du total zu einer Persistent-Variablen machen, setzte die nächste Kerze mit der vorherigen Summe fort. Auf jeder Kerze würdest du weitere fünf Werte zum alten Ergebnis addieren und nicht mehr den Durchschnitt des aktuellen Fensters berechnen.

Fehlende historische Werte

Auf den ersten vier Kerzen der Daten fehlt mindestens ein Schlusskurs für das Fenster aus fünf Werten. Ein na in der Summe lässt auch den eigenen Durchschnitt fehlen. Der fertige SMA mit Länge fünf ist ebenfalls erst auf der fünften Kerze gültig.

In den Demodaten des Buchs sind alle Schlusskurse gültig. Bei einer Quelle mit Lücken auch in der Mitte kann sich die Behandlung fehlender Werte durch ta.sma von einer einfachen Addition über Kerzenabstände unterscheiden. Deshalb prüfen wir dieses Beispiel auf den hier angegebenen Daten.

Wie viele Wiederholungen verlangst du?

Bei einem Fenster über hundert Kerzen führen wir pro Kerze hundert Additionen aus. Für zweitausend Kerzen sind das bereits zweihunderttausend Schleifenschritte.

Die fertige Funktion ta.sma soll genau diese häufige Aufgabe mit der dafür vorgesehenen Berechnung der Laufzeit lösen. Die eigene Schleife dient hier zum Verstehen und Vergleichen. Verwende die fertige Funktion, wenn sie die gewünschte Aufgabe erledigt.

Das Ende einer Schleife muss bekannt und begrenzt sein. Mit dem Maximum des Inputs legen wir auch fest, wie viel Arbeit ein Benutzer innerhalb einer Kerze anfordern kann.

break und continue

break beendet die Schleife. continue überspringt den Rest des aktuellen Schleifenschritts und geht zum nächsten Schritt.

Verwende beide bei einem Durchschnittsfenster vorsichtig. Wenn du drei Werte addiert hast und dann aufhörst, kannst du die Summe nicht wie bei fünf enthaltenen Werten durch fünf teilen. Auslassungen verändern die Bedeutung der Berechnung.

Probiere es selbst aus

Stelle die Länge auf drei. Notiere für eine Kerze die in der Schleife verwendeten Abstände und die zugehörigen drei Kurse. Ändere dann das Programm so, dass es den eigenen und den fertigen Durchschnitt im Overlay-Modus zusätzlich zur Differenz berechnet und darstellt.

Lösung der Aufgabe

Die drei Abstände sind 0, 1 und 2. Im Dekorator muss overlay=True stehen; nach der Berechnung ergänzt du:

plot(manual_average, "Manual average", color=color.blue, linewidth=2)
plot(builtin_average, "Built-in average", color=color.orange)

Entferne die Darstellung der Differenz aus dieser Ansicht. Die Linie um null und Durchschnitte auf Kursniveau sind auf derselben Skala schwer lesbar. Für Prüfungen kannst du das ursprüngliche Differenzpanel in einer eigenen Programmvariante behalten.

Erkenne ein verschobenes Fenster

Überlege, was sich bei einer Schleife mit range(1, length + 1) ändern würde. Die Anzahl bliebe fünf, aber die aktuelle Kerze würde entfallen und der Wert fünf Kerzen zuvor hinzukommen. Das wäre das Durchschnittsfenster der vorherigen Kerze statt der aktuellen.