La première stratégie ne fermait qu’au croisement opposé. Nous allons aussi utiliser des distances de perte et de gain par rapport au prix d’entrée. La fermeture par croisement reste présente.

Trois raisons de sortir

Dans cet exemple, trois événements peuvent fermer une position longue :

  • le prix atteint le niveau de l’ordre stop de protection ;
  • le prix atteint le niveau de l’ordre limite de prise de profit ;
  • la moyenne rapide croise la lente à la baisse et la fermeture au marché s’exécute.

Le stop et la limite sont des ordres conditionnés par le prix. strategy.close passe un ordre de fermeture au marché. Leurs règles d’exécution peuvent différer : vérifiez donc le prix et l’instant dans le tableau des transactions.

Une distance ou un prix précis ?

strategy.exit accepte deux modes de définition :

ArgumentValeur fournie
lossDistance de perte en ticks
profitDistance de gain en ticks
stopPrix stop précis
limitPrix limite précis

loss=100 ne signifie ni 100 % ni nécessairement 100 unités monétaires. Vous demandez une distance de cent ticks depuis le prix d’entrée.

Le tick DEMO vaut 0,01. Cent ticks représentent donc 1 unité de prix, deux cents ticks 2 unités. Pour une entrée longue à 200, cela donne un stop à 199 et un objectif à 202, sans l’effet supplémentaire du slippage et des conditions d’exécution.

Le programme complet

Créez protected_strategy.py :

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


@script.strategy(
    "Crossing Strategy with Exits",
    overlay=True,
    initial_capital=10000,
    default_qty_type=strategy.fixed,
    default_qty_value=1,
    pyramiding=1,
    commission_type=strategy.commission.percent,
    commission_value=0.1,
    slippage=2,
)
def main(
    fast_length: int = input.int(5, title="Fast length", minval=1, maxval=200),
    slow_length: int = input.int(20, title="Slow length", minval=1, maxval=200),
    stop_ticks: int = input.int(100, title="Stop distance (ticks)", minval=1),
    target_ticks: int = input.int(200, title="Target distance (ticks)", minval=1),
):
    fast_average = ta.sma(close, fast_length)
    slow_average = ta.sma(close, slow_length)
    crosses_up = ta.crossover(fast_average, slow_average)
    crosses_down = ta.crossunder(fast_average, slow_average)
    if crosses_up:
        strategy.entry("Long", strategy.long)
    if crosses_down:
        strategy.close("Long")
    strategy.exit("Bracket", "Long", loss=stop_ticks, profit=target_ticks)
    plot(fast_average, "Fast average", color=color.blue, linewidth=2)
    plot(slow_average, "Slow average", color=color.orange, linewidth=2)

Bracket identifie le groupe d’ordres de sortie. Le deuxième argument, Long, indique l’entrée associée. loss et profit utilisent les deux inputs ci-dessus.

Nous exécutons cet appel de sortie à chaque bougie avec le même identifiant. Il gère la règle de sortie définie ; il n’ouvre pas une nouvelle position indépendante à chaque appel.

Exécutez le programme sur les données de démonstration. Trades peut maintenant afficher des sorties Bracket en plus des fermetures au marché par croisement.

PyneIDE affiche l’exécution de protected_strategy.py ; les transactions peuvent aussi être fermées par le stop ou l’objectif.
En plus de la fermeture par croisement, la stratégie utilise un stop et un objectif exprimés en ticks.

Quand la protection est-elle créée ?

Le programme peut donner une instruction d’entrée et une instruction de sortie associée dans la même exécution. L’environnement peut rattacher les distances en ticks au prix d’exécution effectif de l’entrée.

Si vous calculiez plutôt un prix stop précis à partir de la clôture du signal, le niveau serait basé sur ce prix de signal. Avec une ouverture suivante différente, sa distance à l’entrée effective ne serait plus la même.

Choisissez donc le mode selon la règle à exprimer. loss est une distance en ticks depuis l’entrée ; stop est un niveau de prix précis.

Une bougie ne contient pas tous les mouvements de prix

Les données OHLCV donnent l’ouverture, le plus haut, le plus bas et la clôture. Elles ne donnent pas automatiquement l’ordre chronologique de tous les prix intermédiaires.

Si le plus haut d’une même bougie atteint l’objectif et son plus bas le stop, ces quatre prix ne suffisent pas à savoir lequel est survenu d’abord. Le simulateur applique alors les règles de son modèle d’exécution. Des données d’une unité de temps inférieure peuvent permettre une étude plus fine.

Vérifiez ce cas séparément, sans choisir toujours à la main l’issue la plus favorable. L’hypothèse du modèle fait partie du résultat.

Le prix stop ne garantit pas non plus un prix d’exécution exact. Si la bougie suivante ouvre de l’autre côté du stop, le saut de prix peut provoquer une exécution moins favorable que le niveau franchi. Le slippage peut ajouter un écart supplémentaire.

Distance et perte monétaire

Pour une position longue d’une unité, avec une valeur de point de 1, une distance de 100 ticks de 0,01 représente 1 unité monétaire d’écart de prix. Avec dix unités, le résultat lié au prix est multiplié par dix.

La quantité, la taille du tick et la valeur du point déterminent ensemble le montant du mouvement jusqu’au stop. Les commissions et les conditions d’exécution effectives s’y ajoutent.

Si vous donnez directement qty dans un ordre, cette valeur en définit la quantité propre. L’exemple utilise la quantité par défaut, qui peut aussi être remplacée dans Properties → Order size.

Les distances de 100 et 200 ticks de l’exercice DEMO servent d’illustration. Sur un autre instrument, les mêmes nombres peuvent correspondre à d’autres distances de prix et montants.

À vous de jouer

Conservez longueurs rapide et lente, quantité et coûts. Exécutez une version avec un stop et un objectif de 100/200, puis une avec 200/400. Suivez le sort d’un même signal d’entrée.

Solution de l’exercice

Dans Inputs, modifiez seulement Stop distance (ticks) et Target distance (ticks). Les distances plus grandes peuvent faire fermer la position à une autre bougie ou pour une autre raison.

La fermeture par croisement reste active dans les deux versions. Un objectif plus éloigné ne signifie donc pas que la position restera ouverte jusqu’à l’atteindre. Les règles de sortie agissent ensemble.

Après l’enregistrement des inputs, attendez toujours la fin du recalcul avant de lire le nouveau résultat. Conservez les deux exports sous des noms différents pour les comparer plus tard.

Trouver la raison d’une sortie

Choisissez une transaction clôturée et vérifiez son prix d’entrée, ses distances en ticks et les valeurs OHLC de la bougie de sortie. À partir du prix et de l’instant de sortie, déterminez quelle règle explique la transaction. Si la bougie touche plusieurs niveaux, tenez aussi compte du modèle d’exécution.