Was das Programm sich merkt
Mit einer Persistent-Variablen zählst du Kreuzungen und unterscheidest Zustand von historischen Werten.
Eine Kreuzungsmarkierung zeigt, wo ein Ereignis stattgefunden hat. Möchtest du auch wissen, wie oft es seit Beginn der Daten aufgetreten ist, muss das Programm den Zählerstand behalten.
Warum reicht eine einfache Variable nicht?
Diese beiden Zeilen beginnen auf jeder Kerze von vorn zu zählen:
count = 0
count += 1Die erste Zeile setzt die Variable bei jeder Ausführung von main() auf null. Die zweite addiert eins. Das Ergebnis ist deshalb auf jeder Kerze 1.
+= ist eine verkürzte Zuweisung: count += 1 bedeutet dasselbe wie count = count + 1. Zuerst wird der alte Wert gelesen, dann eins addiert und das Ergebnis wieder in der Variablen gespeichert.
Um Ereignisse zu zählen, brauchen wir einen anderen Anfang. Wir wollen den Zähler nur beim ersten Anlegen auf null setzen.
Die Variable Persistent
count: Persistent[int] = 0Die Kennzeichnung Persistent legt fest, dass der Wert zwischen den Kerzen erhalten bleibt. Die anfängliche Null setzt die Variable einmal. Auf der nächsten Kerze setzen wir mit dem von der vorherigen abgeschlossenen Kerze erhaltenen Wert fort.
int bezeichnet hier den ganzzahligen Typ des Zählers. Wir importieren Persistent aus dem Modul pynecore, genau wie zuvor Series.
Die Kennzeichnung speichert keine Daten auf der Festplatte. Ein neuer Lauf beginnt wieder am Datenanfang mit einem Zählerstand von null. Gemeint ist das Beibehalten zwischen den Kerzen innerhalb des Programmlaufs.
Zähle die Aufwärtskreuzungen
Lege die Datei event_counter.py an:
"""
@pyne edge
"""
from pynecore import Persistent
from pynecore.lib import close, color, plot, script, ta
@script.indicator("Crossing Counter", overlay=False)
def main():
fast_average = ta.sma(close, 5)
slow_average = ta.sma(close, 20)
crosses_up = ta.crossover(fast_average, slow_average)
count: Persistent[int] = 0
if crosses_up:
count += 1
plot(count, "Crossing count", color=color.blue, linewidth=2)Führe sie auf den Demodaten aus. Der Zähler im eigenen Panel beginnt bei null. Bei einer Aufwärtskreuzung steigt er um eins, auf den Kerzen dazwischen bleibt er unverändert.

Ist der letzte Chartwert beispielsweise 12, bedeutet das zwölf Aufwärtskreuzungen in den gesamten verarbeiteten Daten. Im kurzen sichtbaren Zeitraum können weniger Signale liegen. Das Zoomen des Charts startet den Zähler nicht neu.
Zustand und Historie
Die beiden Kennzeichnungen erfüllen unterschiedliche Aufgaben:
| Kennzeichnung | Was verlangen wir von der Laufzeit? |
|---|---|
Series[float] | Die Werte früherer Kerzen sollen abrufbar sein |
Persistent[int] | Die Variable soll mit dem gespeicherten Wert weitermachen |
Die Zuweisung einer Series-Variablen wird auf jeder Kerze ausgeführt. Die so erhaltenen Werte bilden ihre Historie. Die anfängliche Zuweisung einer Persistent-Variablen findet nur einmal statt; anschließend entwickeln die Änderungen im Code ihren Zustand weiter.
Möchtest du auch einen früheren Zählerstand direkt abrufen, kannst du den aktuellen Stand in einer eigenen Series-Variablen ablegen. Das Beibehalten eines Werts und das Indizieren vergangener Werte sind zwei getrennte Fragen.
Wo die gespeicherte Variable steht
Wir deklarieren den Zähler vor der Bedingung an einer Stelle, die auf jeder Kerze erreicht wird. So hat er auch unabhängig von der Bedingung einen Wert, und plot kann ihn auf jeder Kerze zeichnen.
Lege oberhalb von main() keinen gewöhnlichen veränderlichen globalen Zähler an. Beschreibe den Zustand zwischen den Kerzen mit der Kennzeichnung an der Stelle, an der das Programm ihn verwendet.
Der hier untersuchte historische Lauf rechnet einmal pro Kerze. In einem Ausführungsmodus, der dieselbe Kerze mehrfach auswertet, beginnt Persistent erneut mit dem Zustand der vorherigen abgeschlossenen Kerze. Es zählt deshalb nicht sämtliche technischen Ausführungen. Wir verwenden den Zähler dieses Buchs für Ereignisse abgeschlossener Kerzen.
Eine Bedingung kann den Wert auch zurücksetzen
Wenn du aufeinanderfolgende steigende Kerzen zählst, kannst du bei einer fallenden Kerze oder bei gleichem Eröffnungs- und Schlusskurs auf null zurücksetzen:
if close > open:
streak += 1
else:
streak = 0Du musst streak vorher mit Persistent[int] anlegen. Das Zurücksetzen ist hier eine bewusste bedingte Aktion. Es geschieht nicht automatisch am Anfang jeder Kerze.
Probiere es selbst aus
Ergänze einen zweiten gespeicherten Zähler. Er soll Abwärtskreuzungen zählen und als orangefarbene Linie erscheinen. Beide Berechnungen sollen auf jeder Kerze laufen.
Lösung der Aufgabe
Ergänze neben der Berechnung der Aufwärtskreuzung:
crosses_down = ta.crossunder(fast_average, slow_average)
down_count: Persistent[int] = 0
if crosses_down:
down_count += 1
plot(down_count, "Downward count", color=color.orange, linewidth=2)Behalte die vorhandene Variable count und ihre Darstellung bei. Die beiden Zähler sind unabhängig. Ein neuer Lauf baut beide wieder von null auf.
Prüfe ein Signal
Vergleiche die Markierungen aus dem Kapitel über Kreuzungen mit den Änderungen des Zählers auf denselben Daten. Auf der Kerze einer Aufwärtskreuzung muss er genau um eins steigen. Auf der nächsten Kerze darf er nur dann erneut steigen, wenn eine neue Aufwärtskreuzung aufgetreten ist.