Le chapitre précédent calculait à partir des données d’une seule bougie. La variation de clôture nécessite deux bougies : l’actuelle et la précédente. Dans ce chapitre, vous les relierez.

Le programme reste le même, la bougie change

Lorsque vous lancez le programme sur les données de démonstration, PyneCore parcourt les bougies dans l’ordre chronologique. main() traite la première bougie, puis la deuxième, et ainsi de suite. À chaque fois, close désigne la clôture de la bougie traitée.

C’est pourquoi un seul appel plot(close, "Close") peut tracer une ligne complète. Une exécution ajoute un point ; la suite des bougies produit la ligne entière.

La ligne midpoint = (high + low) / 2 du chapitre précédent s’exécute elle aussi à chaque bougie. L’affectation recalcule le prix médian de la bougie actuelle. Le nom de la variable reste le même ; sa valeur peut changer.

L’environnement d’exécution assure l’ordre du traitement. Vous n’avez pas à écrire votre propre boucle pour parcourir tout le graphique.

Consulter le passé avec les crochets

close[1] est la clôture de la bougie précédente. Le nombre entre crochets indique de combien de bougies on remonte dans le passé.

ExpressionQuelle clôture désigne-t-elle ?
closeCelle de la bougie traitée
close[0]Également celle de la bougie traitée
close[1]Celle de la bougie précédente
close[2]Celle de deux bougies auparavant

Si trois clôtures journalières successives sont 100, 103 et 101, alors à la troisième bougie close vaut 101, close[1] vaut 103 et close[2] vaut 100.

Dans ce cas, close - close[1] signifie 101 - 103, soit −2. C’est la différence entre deux clôtures successives. close - open compare l’ouverture et la clôture de la même bougie. Ces calculs répondent à deux questions différentes.

Le recul se mesure en bougies, pas en jours calendaires. Sur des données journalières de marché, un week-end ou un jour de fermeture peut séparer la bougie précédente de plusieurs jours.

Vos propres valeurs peuvent aussi avoir un historique

L’historique des prix intégrés est déjà disponible. Pour consulter le passé de votre propre calcul, déclarez une variable Series :

midpoint: Series[float] = (high + low) / 2

La partie après les deux-points est une annotation de type. float désigne un nombre qui peut avoir une partie décimale. Series[float] demande aussi à l’environnement d’exécution de conserver l’historique de cette variable pour chaque bougie.

L’affectation s’exécute toujours à chaque bougie. midpoint est la valeur calculée actuelle ; midpoint[1] est celle enregistrée à la bougie précédente. Il faut importer Series depuis le module pynecore.

Deux variations sur le graphique

Créez history_change.py dans le dossier scripts du projet :

"""
@pyne edge
"""
from pynecore import Series
from pynecore.lib import close, color, high, low, plot, script


@script.indicator("Changes Between Candles", overlay=False)
def main():
    midpoint: Series[float] = (high + low) / 2
    close_change = close - close[1]
    midpoint_change = midpoint - midpoint[1]
    plot(close_change, "Close change", color=color.blue)
    plot(midpoint_change, "Midpoint change", color=color.orange)

Enregistrez le fichier, puis choisissez Run Pyne code et les données demo. Deux lignes apparaissent dans un panneau séparé. La bleue montre la variation de clôture ; l’orange, celle du prix médian. Un point positif indique une hausse par rapport à la bougie précédente.

À côté de history_change.py, le graphique de PyneIDE affiche deux lignes de variation.
Les variations entre bougies de la clôture et du prix médian calculé, dans un panneau séparé.

Placez le pointeur sur une bougie. Les valeurs du graphique correspondent toujours à l’instant sous le pointeur ; vous n’avez pas à sélectionner cet instant dans le fichier.

Que se passe-t-il à la toute première bougie ?

La première bougie n’a pas de bougie précédente dans le fichier de données. close[1] y est donc une valeur manquante : na, abréviation de « not available ».

Un prix manquant n’est pas zéro. Le résultat de close - close[1] manque lui aussi ; le programme ne trace donc pas de variation valide à la première bougie. Ce résultat est correct : on ne peut pas calculer la différence entre deux bougies à partir d’une seule.

L’appel na(value) permet de vérifier si une valeur manque. Vous apprendrez à traiter les conditions dans le chapitre Conditions et repères graphiques. D’ici là, n’essayez pas de corriger le point manquant au début du graphique en lui donnant un prix nul.

Cette notation ne donne pas accès aux bougies futures. close[-1] ne signifie pas non plus la clôture suivante. Une décision ne peut utiliser que les données disponibles à son exécution.

À vous de jouer

Modifiez la ligne bleue pour comparer la clôture à celle de cinq bougies auparavant. Indiquez aussi cet écart de cinq bougies dans le titre de la ligne.

Avant l’exécution, déterminez combien de bougies initiales auront un résultat manquant.

Solution de l’exercice
close_change = close - close[5]
plot(close_change, "Five-candle change", color=color.blue)

Les cinq premières bougies n’ont pas de clôture cinq bougies auparavant. La sixième en a une : celle de la première bougie du fichier.

La ligne orange ne change pas. Pour calculer les deux variations sur cinq bougies, il faut aussi modifier midpoint[1].

Vérifier le calcul

Choisissez trois bougies successives. Notez leurs clôtures et calculez à la main la variation sur une bougie pour la deuxième et la troisième. La ligne bleue doit afficher ces valeurs. En cas d’écart, vérifiez d’abord les instants choisis et le nombre de bougies de recul.

Exercice complémentaire : conserver une valeur plutôt que son historique

Vous pouvez aussi réutiliser une seule valeur précédente en la conservant pour la bougie suivante. C’est le rôle d’une variable Persistent, présentée dans le chapitre Ce que le programme mémorise. Vous pouvez revenir à cet exercice après l’avoir lu.

Réécrivez history_change.py sans utiliser ni close[1] ni midpoint[1]. Deux variables persistantes doivent conserver la clôture et le prix médian de la bougie précédente. Les deux lignes doivent afficher les mêmes valeurs que dans le programme initial, et la variation doit toujours manquer à la première bougie.

Réfléchissez à l’ordre : quand faut-il lire la valeur conservée, et quand peut-on la remplacer par la valeur actuelle ?

Solution de l’exercice

Remplacez l’import de Series par celui de Persistent :

from pynecore import Persistent

Ajoutez na à l’import de pynecore.lib. Conservez le marqueur initial et les paramètres de l’indicateur, puis réécrivez main() ainsi :

def main():
    previous_close: Persistent[float] = na
    previous_midpoint: Persistent[float] = na
    midpoint = (high + low) / 2
    close_change = close - previous_close
    midpoint_change = midpoint - previous_midpoint
    plot(close_change, "Close change", color=color.blue)
    plot(midpoint_change, "Midpoint change", color=color.orange)
    previous_close = close
    previous_midpoint = midpoint

Les deux variables persistantes commencent à na, car aucun prix précédent n’existe à la première bougie. La première différence manque donc aussi. À la fin de la fonction, nous enregistrons les valeurs actuelles pour les utiliser à la bougie suivante.

Si vous placez previous_close = close avant la soustraction, vous soustrayez la clôture actuelle d’elle-même et obtenez zéro. Avec les variables persistantes, vous devez veiller à l’ordre des mises à jour.

Les deux approches conviennent pour remonter d’une seule bougie. La notation entre crochets est plus courte et donne aussi directement accès à des valeurs plus anciennes. Ces deux variables persistantes ne conservent que les derniers prix enregistrés.

Exécutez les deux versions sur les mêmes données de démonstration et comparez les deux lignes sur quelques bougies choisies.