Dimensionnement, marge et levier

La taille des entrées définit l’exposition réelle au marché, tandis que la marge détermine le levier disponible et le seuil de liquidation. Cette page explique comment le moteur les calcule et comment elles interagissent.

Repères

Avant d’entrer dans les règles du moteur, clarifions quelques notions importantes.

Le dimensionnement, la marge et le levier interviennent dès qu’une position est ouverte. Pour comprendre leur rôle, partons d’un exemple simple.

Imaginez un portefeuille de 1 000 USDT. Ces 1 000 USDT représentent votre capital de départ : c’est l’argent disponible sur le compte avant d’ouvrir une position.

Vous décidez ensuite d’acheter 0,08 BTC à 50 000 USDT. Le calcul est direct : 0,08 × 50 000 = 4 000 USDT.

Votre position a donc une valeur de 4 000 USDT. Cette valeur s’appelle la valeur notionnelle. C’est sur ces 4 000 USDT que vos gains et vos pertes seront calculés, et non sur votre capital de 1 000 USDT. Par exemple, si le Bitcoin gagne 1 %, votre position gagne 40 USDT, car 1 % de 4 000 USDT = 40 USDT. A l’inverse, si le Bitcoin perd 1 %, votre position perd 40 USDT.

On voit donc que la position ouverte est plus grande que le capital disponible. Vous avez 1 000 USDT sur le compte, mais vous êtes exposé à hauteur de 4 000 USDT sur le marché. Cela est possible parce que le moteur ne vous demande pas d’immobiliser toute la valeur de la position. Il vous demande seulement une garantie : la marge requise.

Supposons que la marge soit configurée à 20 %. Cela signifie que le moteur exige une garantie équivalente à 20 % de la valeur de la position. La position vaut 4 000 USDT, donc la marge requise est de : 20 % × 4 000 = 800 USDT.

Le moteur immobilise donc 800 USDT pour maintenir la position ouverte. Comme votre capital de départ est de 1 000 USDT, il reste 200 USDT disponibles sur le compte. Ce cash disponible peut servir à payer les frais, à ouvrir d’autres positions ou à absorber une partie des pertes latentes.

A tout moment, le moteur suit aussi l’équité du compte. L’équité représente la valeur réelle du compte en tenant compte du cash disponible, de la marge immobilisée et du gain ou de la perte latente de la position. Au moment de l’entrée, la position n’a encore ni gagné ni perdu. L’équité vaut donc toujours 1 000 USDT : 800 USDT de marge immobilisée et 200 USDT de cash disponible.

Si le Bitcoin monte de 1 %, la position gagne 40 USDT. L’équité passe alors de 1 000 USDT à 1 040 USDT. Si le Bitcoin baisse de 1 %, la position perd 40 USDT. L’équité descend alors à 960 USDT.

Le moteur vérifie que l’équité reste suffisante pour maintenir la position ouverte. Dans cet exemple, la marge requise est de 800 USDT. Tant que l’équité reste au-dessus de ce niveau, la position tient. Si l’équité descend jusqu’à ce seuil, le moteur considère que le compte n’a plus assez de sécurité pour porter la position et la liquide.

Le levier permet de mesurer cette exposition. Il compare la taille de la position au capital du compte. Ici, vous avez une position de 4 000 USDT avec un capital de 1 000 USDT : 4 000 / 1 000 = 4. Vous utilisez donc un levier de 4x.

Avec une marge configurée à 20 %, le levier maximal théorique est de 5x, car : 100 / 20 = 5. Cela signifie qu’avec 1 000 USDT d’équité, le moteur pourrait autoriser jusqu’à 5 000 USDT d’exposition. Mais ce n’est qu’un maximum. Vous n’êtes pas obligé d’utiliser tout le levier disponible. Dans notre exemple, vous ouvrez une position de 4 000 USDT, donc vous utilisez 4x, même si le plafond autorisé est 5x.

Enfin, il faut distinguer le prix utilisé pour dimensionner l’ordre du prix auquel l’ordre est réellement exécuté. Par exemple, un signal peut être déclenché à la clôture d’une bougie, lorsque le Bitcoin vaut 50 000 USDT. Le moteur utilise alors ce prix pour calculer la quantité à acheter : c’est le prix de sizing.

Mais si l’ordre est un ordre au marché, il peut être exécuté à l’ouverture de la bougie suivante, par exemple à 50 200 USDT. Dans ce cas, c’est ce prix de 50 200 USDT qui devient le prix réel de la position.

C’est toujours le prix d’exécution qui sert ensuite à calculer le notionnel réellement ouvert, les frais, les gains ou pertes, et le contrôle final de solvabilité du compte. Le prix de sizing sert à préparer l’ordre ; le prix d’exécution sert à calculer ce qui s’est réellement passé.

Dimensionner une entrée

Quand une entrée est créée, le moteur la dimensionne en trois étapes : il détermine d’où vient la consigne de taille, il l’interprète selon un mode de sizing, puis il la convertit en quantité à partir du prix de sizing.

La consigne peut venir de deux endroits. Le bloc [backtest] fixe un sizing global appliqué par défaut à toutes les entrées. Un bloc [[entry]] ou [[order]] peut remplacer ce sizing global en indiquant directement qty ou qty_percent. Dans ce cas, le moteur utilise la valeur définie sur le bloc pour cette entrée. Si l’ordre ne définit ni qty ni qty_percent, le moteur applique le sizing global du bloc [backtest].

Le mode décide comment interpréter la valeur. percent_of_equity la lit comme un pourcentage de l’équité, fixed comme une quantité absolue d’actif, cash comme un budget monétaire. Le sizing global choisit son mode avec default_qty_type ; le sizing local le choisit par la clef utilisée, qty pour une quantité absolue et qty_percent pour un pourcentage d’équité.

Quand aucun sizing global n’est renseigné, le moteur suit le défaut TradingView : default_qty_type = "fixed" avec default_qty_value = 1. Définir seulement default_qty_value conserve donc le mode fixed implicite. Pour exprimer un pourcentage d’équité, indiquez aussi default_qty_type = "percent_of_equity".

Le mode percent_of_equity

default_qty_type = "percent_of_equity" lit default_qty_value comme une base exprimée en pourcentage de l’équité. Ce n’est pas le mode implicite du bloc [backtest] : pour l’utiliser, définissez default_qty_type explicitement. Si default_qty_value est absent dans ce mode, le moteur utilise une base de 1.

[backtest]
default_qty_type  = "percent_of_equity"
default_qty_value = 40

Avec cette configuration, l’entrée visée est proche de 40 % de l’équité.

long_size_multiplier et short_size_multiplier ajustent cette base séparément pour le long et le short. Ils valent 1 par défaut et n’agissent qu’en percent_of_equity global, lorsque l’ordre ne définit pas déjà qty ou qty_percent. Ils ne changent ni la marge requise ni le levier.

[backtest]
default_qty_type      = "percent_of_equity"
default_qty_value     = 40
long_size_multiplier  = 1.5
short_size_multiplier = 0.5

Ici, la base de 40 % devient 40 × 1.5 = 60 pour le long et 40 × 0.5 = 20 pour le short. L’exposition visée est donc proche de 60 % de l’équité sur les longs et de 20 % sur les shorts.

Le calcul part toujours de l’équité totale, et non du seul cash disponible. La quantité réellement ouverte peut rester un peu en dessous de la cible affichée, car le moteur retranche les frais puis ajuste le résultat à la taille minimale de contrat.

Cette base se prête au grid search. L’exemple suivant fait varier l’exposition tout en gardant les marges fixes.

[backtest]
symbol                  = "BINANCE:BTCUSDT"
timeframe               = "240"
start_date              = 2024-01-01
end_date                = 2025-01-01
initial_capital         = 1000
margin_long             = 50
margin_short            = 100
default_qty_type        = "percent_of_equity"
default_qty_value.start = 20
default_qty_value.stop  = 80
default_qty_value.step  = 10

Pour la syntaxe des plages, voir Combinaisons d’hyperparamètres.

Le mode fixed

default_qty_type = "fixed" lit default_qty_value comme une quantité absolue d’actif.

[backtest]
default_qty_type  = "fixed"
default_qty_value = 0.01

[[entry]]
id       = "buy"
order_id = "main"

Avec cette configuration, l’entrée visée est de 0.01 unité d’actif. Si un ordre ne définit pas de sizing local, le moteur utilise default_qty_value ; si cette valeur est absente, il utilise 1 unité d’actif. Les multiplicateurs de côté n’ont aucun effet dans ce mode, la taille étant déjà une quantité absolue.

Le mode cash

default_qty_type = "cash" lit default_qty_value comme un budget monétaire nominal.

[backtest]
default_qty_type  = "cash"
default_qty_value = 500

[[entry]]
id       = "buy"
order_id = "main"

Avec cette configuration, 500 unités de devise quote sont converties en quantité d’actif à partir du prix de sizing, puis exécutées au prix réel de fill. Le budget reste nominal : si le prix de fill diffère du prix de sizing, le notionnel réellement exécuté peut s’écarter du budget initial. Comme en mode fixed, les multiplicateurs de côté n’ont pas d’effet. Si default_qty_value est absent en mode global cash, le budget implicite est 1 unité de devise quote.

qty et qty_percent dans [[entry]] et [[order]]

Dans [[entry]] et [[order]], qty désigne toujours une quantité absolue d’actif et qty_percent toujours un pourcentage d’équité, jamais un pourcentage de position. Ces deux façons de dimensionner l’ordre ne se cumulent pas dans un même bloc. qty_percent n’y est pas borné à 100 : une valeur supérieure vise une exposition plus forte, sous réserve des règles de marge et de l’acceptation finale de l’ordre.

[backtest]
default_qty_type     = "percent_of_equity"
default_qty_value    = 40
long_size_multiplier = 1.5

[[entry]]
id       = "buy_fixed_qty"
order_id = "main"
qty      = 0.25

[[entry]]
id          = "buy_local_pct"
order_id    = "main"
qty_percent = 25

Dans cet exemple, le premier ordre ouvre 0.25 unité d’actif et le second vise 25 % de l’équité. Aucun des deux n’utilise le sizing global : qty traite l’ordre comme une entrée à quantité fixe, qty_percent comme une entrée en percent_of_equity, même quand le mode global est fixed ou cash. Ces clefs remplacent le sizing global, elles ne le complètent pas.

Dans [[close]] et [[exit]], qty_percent change de sens : il désigne un pourcentage de la position déjà ouverte. Si une position vaut 2 BTC, qty_percent = 25 vise une sortie d’environ 0,5 BTC avant arrondis. Voir la documentation des blocs [[close]] et [[exit]] pour les règles propres à ces blocs.

Prix de sizing et prix d’exécution

La quantité n’est pas toujours calculée avec le prix du fill. Cette différence concerne surtout les entrées dont la taille dépend d’un budget ou d’un pourcentage d’équité.

Pour un ordre market exécuté à la clôture, l’ordre est dimensionné et exécuté au même prix. Pour un ordre market exécuté à l’ouverture suivante, le moteur conserve le prix de sizing de la bougie de signal puis exécute à l’ouverture. Pour un ordre limit, le prix de sizing est le prix limite ; pour un stop market, le prix stop ; pour un stop-limit, le prix limite.

[backtest]
default_qty_type  = "cash"
default_qty_value = 500

[[entry]]
id       = "buy_limit"
order_id = "main"
limit    = "close * 0.99"

Ici, la quantité est calculée à partir du prix limite, puis exécutée lorsque l’ordre est rempli. Si le fill final se fait à un autre prix, le notionnel exécuté, les frais débités et le contrôle final de solvabilité suivent le prix réel d’exécution.

Marge et levier

La marge ne définit pas la taille de l’entrée. Cette taille dépend du sizing : default_qty_type, default_qty_value, les multiplicateurs de côté, puis qty ou qty_percent. margin_long et margin_short interviennent ensuite et fixent la marge requise, le levier théorique maximal et les conditions de liquidation. Une marge plus faible ne crée donc pas, à elle seule, une entrée plus grande : elle change le cadre de solvabilité dans lequel l’entrée est acceptée, maintenue ou liquidée.

margin_long et margin_short

margin_long et margin_short sont des pourcentages de marge, exprimés directement en pourcentage dans le fichier TOML. margin_long = 50 signifie 50 % de marge, margin_long = 0.5 signifie 0,5 %. Les valeurs supérieures à 100 sont acceptées et représentent une marge plus restrictive qu’un cadre 1x.

La marge requise se calcule à partir de la valeur notionnelle : valeur notionnelle × (margin_long / 100) pour un long, valeur notionnelle × (margin_short / 100) pour un short. Le levier théorique maximal se lit de la même manière : 100 / margin_long pour un long, 100 / margin_short pour un short.

Ainsi une marge de 100 correspond à un cadre proche de 1x, une marge de 50 à environ 2x, une marge de 25 à environ 4x, et une marge de 0.5 à environ 200x. A l’inverse, une marge de 200 demande deux fois la valeur notionnelle en marge et limite l’exposition soutenable à environ la moitié de l’équité.

[backtest]
symbol          = "BINANCE:BTCUSDT"
timeframe       = "240"
start_date      = 2024-01-01
end_date        = 2025-01-01
initial_capital = 1000
margin_long     = 50
margin_short    = 100

Cet exemple fixe un plafond théorique long proche de 2x avec une marge long à 50 %, et un cadre short proche de 1x avec une marge short à 100 %. La taille réelle des entrées reste déterminée par le sizing.

Désactiver la marge

Quand une marge vaut 0, la logique de marge est désactivée sur le côté concerné : le moteur n’immobilise pas de marge et n’applique pas de liquidation par marge sur ce côté. Si une seule marge vaut 0, l’autre côté conserve sa propre logique et le comportement global reste mixte.

Avec margin_long = 0 et margin_short = 0, le moteur fonctionne sans marge des deux côtés. La taille des entrées reste pilotée par les règles de sizing : default_qty_type, default_qty_value, les multiplicateurs, qty et qty_percent.

[backtest]
symbol          = "BINANCE:BTCUSDT"
timeframe       = "240"
start_date      = 2024-01-01
end_date        = 2025-01-01
initial_capital = 1000
margin_long     = 0
margin_short    = 0

Solvabilité de l’entrée

Une fois la taille calculée, le moteur vérifie si l’entrée reste solvable. Quand la marge est active, il compare l’équité à la marge requise après l’entrée. Pour une marge différente de 100, ce contrôle a lieu avant le fill. Pour une marge égale à 100, la décision finale peut être prise après le fill, à partir du prix réellement exécuté et des frais réellement débités. Une entrée peut donc être exécutée puis liquidée immédiatement sur la même bougie : la quantité n’est pas réduite automatiquement pour la faire entrer dans la marge.

Liquidation par marge

Une liquidation par marge se produit lorsque l’équité devient inférieure ou égale à la marge requise. Elle n’existe que sur les côtés où la marge est active, c’est-à-dire margin_long > 0 pour les positions long et margin_short > 0 pour les positions short.

Le contrôle ne se limite pas à la clôture de la bougie : le moteur l’effectue aussi en cours de bougie. Une liquidation peut donc survenir avant la clôture, même si le prix revient ensuite. Quand le seuil est franchi, une partie de la position est réduite pour rétablir la marge requise ; selon les arrondis et la taille minimale de contrat, cette réduction partielle peut devenir une fermeture complète.

Même avec une marge à 100, un margin call immédiat peut apparaître lorsqu’une entrée vise presque toute l’équité et que le prix réel d’exécution et les frais font basculer le contrôle final.

Exemple chiffré de liquidation par marge

Prenons un cas simple, volontairement sans frais ni arrondis pour garder les chiffres lisibles : une équité initiale de 1 000 USDT, une exposition long de 4 000 USDT sur Bitcoin et margin_long = 20. Cette marge de 20 % correspond à un cadre théorique proche de 5x, car 100 / 20 = 5. A l’entrée, la marge requise vaut 4 000 × 20 % = 800 USDT.

L’exposition ouverte vaut 4 000 USDT, mais toute cette valeur n’a pas besoin d’être couverte par l’équité. Tant que l’équité reste strictement supérieure à la marge requise, la position reste ouverte.

Si le prix monte de 2 %, le gain latent est de 80 USDT. L’équité passe à 1 080 USDT, la valeur notionnelle à 4 080 USDT et la marge requise à 816 USDT : l’équité reste au-dessus. Si le prix baisse de 2 %, l’équité descend à 920 USDT et la marge requise tombe à 784 USDT (3 920 × 20 %) : l’équité reste encore au-dessus.

Le point critique apparaît quand l’équité rejoint la marge requise. Ici, cela se produit autour d’une baisse de 6,25 % : la perte vaut alors 250 USDT, l’équité tombe à 750 USDT et la valeur notionnelle à 3 750 USDT, dont la marge requise vaut 3 750 × 20 % = 750 USDT. A ce niveau, une liquidation par marge peut commencer. La liquidation dépend donc de la relation entre l’équité et la marge requise, et pas seulement du pourcentage de baisse du prix.