Ingénierie

Quand deux moteurs Pine divergent : recoupement PineForge vs PyneCore

Chaque release passe un balayage de parité TradingView et PyneCore. Voici les chiffres du dernier passage et pourquoi un second moteur « ami » est notre meilleur outil de debug.

9 min de lecture#pinecore#pineforge#parity#engineering

Il existe exactement deux moteurs Pine hors plateforme TradingView que nous considérons « de qualité production » : le nôtre, et PyneCore. PyneComp de PyneSys transpile Pine vers Python ; PyneCore est le runtime Python open-source qui exécute le résultat. Langage différent, VM différente, même source Pine, mêmes définitions d’API à honorer.

Nous traitons PyneCore comme oracle de second rang. Chaque release PineForge passe la batterie de parité à la fois contre les exports CSV « Liste des transactions » de TradingView et contre la sortie exécutée de PyneCore. Quand les trois concordent sur les trades, nous croyons le résultat. Quand deux concordent et un diverge, le divergent a presque toujours un bogue — souvent nous.

Ce billet montre à quoi ressemblent les chiffres du dernier barrage public.

Le corpus

50 stratégies de référence dans le barrage publié (le corpus plus large ~162 entrées reste privé ; ce sous-ensemble alimente le rapport de comparaison des trades). Pour chacune :

  • Compilée en Python par PyneComp, exécutée par PyneCore sur l’OHLCV canonique
  • Compilée en C++ par le codegen PineForge, exécutée par pineforge-engine sur le même OHLCV
  • Les deux sont diffées contre l’export CSV TradingView, fenêtre découpée à
    [fenêtre OHLCV] ∩ [fenêtre d’entrées TV] ∩ [fenêtre d’entrées moteur]
  • Degré de correspondance sur une échelle à 5 niveaux (excellent / strong / moderate / weak / minimal)

Le titre

Sur les 50 stratégies, 47 partagent le même palier dans PineForge et PyneCore. Les deux moteurs atteignent excellent (≥95 % de trades alignés sur l’export CSV TV) sur 47 ; PineForge tombe à strong sur 2 d’entre elles — artefact de la façon dont PineForge compte les deltas de code sur quelques stratégies limites.

Les 3 divergences de palier sont intéressantes : dans les trois cas PineForge est au-dessus.

StrategyPineForgePyneCoreNotes
49-partial-exit-qty-percent🟢 excellent🟠 weakPyneCore émet trop de fills de sortie
06-liquidity-sweep🟢 excellent🟡 moderateDérive de timing de sortie côté Pyne
07-scalping-strategy🟢 excellent🟡 moderatePnL p90 élevé côté Pyne ; entrées OK

Le cas marquant

49-partial-exit-qty-percent est le plus grand écart. La stratégie utilise strategy.exit(qty_percent=...) pour décrocher des portions sur objectif, en boucle — sortie complète, ré-entrée, portions à nouveau.

TV trades (raw, in-window):  725
PineForge engine trades:     852  →  725 in-window  →  725 matched (100% of TV)
PyneCore  engine trades:    3297  →  2805 in-window →  582 matched (80.3% of TV)

Le delta de count PyneCore sur cette stratégie est +74 %. Celui de PineForge est 0 %.

PineForge: count_delta 0.0000% · entry p90 0.0000% · exit p90 0.0004% · PnL p90 0.1321%
PyneCore : count_delta 74.1533% · entry p90 0.0000% · exit p90 1.0376% · PnL p90 (high)

Traduction : les deux moteurs déclenchent les entrées sur les bonnes bougies (p90 d’entrée à 0 % pour les deux — alignement parfait). Le désaccord est sur les sorties. PyneCore génère environ plus de fills de sortie que TradingView pour la même stratégie — probable ré-armement d’un même clause qty_percent avant que le processeur d’ordres TV ne la considère terminée.

Ce n’est pas un jugement de valeur sur PyneCore : c’est un coin de la sémantique strategy.exit() dans Pine, et nous avons martelé notre implémentation après que la batterie l’ait signalée. La chasse aux bogues va dans les deux sens : plusieurs fois PyneCore et TV ont concordé quand nous non.

Les deux autres

06-liquidity-sweep et 07-scalping-strategy sont la même forme à plus petite échelle : entrées alignées à 100 %, dérive de sortie ~1–2 points pourcentuels (PyneCore) contre moins de 0,05 % (PineForge). Sorties façon trailing et sémantique des fills partiels : là où la référence Pine est la moins documentée ; les deux moteurs doivent la reconstituer depuis le comportement observable.

API de compilation PyneSys

PyneSys expose l’étape compile en HTTP. Un curl suffit :

curl -X POST https://api.pynesys.io/compiler/compile \
  -H "Authorization: Bearer pyne_..." \
  --data-urlencode 'script=//@version=6
strategy("ma cross", overlay=true)
if ta.crossover(close, ta.sma(close, 20))
    strategy.entry("L", strategy.long)'

La réponse est un fichier Python ciblant le runtime open-source pynecore :

"""
@pyne
 
This code was compiled by PyneComp v6.0.31 — the Pine Script to Python compiler.
Run with open-source PyneCore: https://pynecore.org
Compile Pine Scripts online at PyneSys: https://pynesys.io
"""
from pynecore.lib import close, script, strategy, ta
 
 
@script.strategy("ma cross", overlay=True)
def main():
    if ta.crossover(close, ta.sma(close, 20)):
        strategy.entry('L', strategy.long)
 
 
if __name__ == "__main__":
    from pynecore.standalone import run
    run(__file__)

Enregistrez en .py, pip install pynecore, pointez votre OHLCV : vous avez la sortie du second moteur à comparer à PineForge.

Pourquoi c’est important

Un seul moteur qui dit « votre stratégie fait +12,4 % sur la fenêtre » ne dit qu’une chose : ce moteur le prétend. Sans comparaison, vous devez lui faire confiance aveuglément.

Deux moteurs indépendants qui donnent le même résultat sur le même script, c’est une preuve bien plus solide. Quand ils divergent, la divergence elle-même est une hypothèse : bogue dans l’un, coin ambigu de Pine, ou condition limite dans les données que ni l’un ni l’autre ne gère. Les trois sont utiles à connaître.

Nous utilisons PyneCore ainsi à chaque release. Si vous expédiez une stratégie avec du capital réel derrière, vous devriez faire pareil.

Ce qui n’est pas dans ce billet

  • Dérive au niveau indicateur. Un rapport séparé suit l’accord indicateur-par-indicateur entre PineForge, PyneCore et les valeurs de référence TradingView. Il vit dans benchmarks/results/indicator_comparison.md du dépôt moteur.
  • Les ~110 autres stratégies du corpus interne hors barrage public. Elles stressent les coins Pine (méthodes UDT, lookups multi-timeframes, groupes de sortie OCA) et font tourner la batterie en interne. Billet futur quand la méthodo sera publiée.

Essayez le motif vous-même

Deux moteurs, une source, trois sorties à comparer. Si tout concorde, vous pouvez avancer plus sereinement. Si ça diverge, vous apprenez quelque chose avant d’engager de l’argent réel.