Les ressources ont été chargées... Je charge...

Tutoriel d'introduction à la langue PINE de FMZ Quant

Auteur:FMZ~Lydia, Créé: 2022-09-23 15:23:34, Mis à jour: 2024-02-27 16:47:41

.3, limite = 3)

Si ce n'est pas le cas, barstate.ishistory et close < open stratégie.annuler ((long1) stratégie.annuler ((long2) stratégie.annuler ((long3) estStop := vrai


---------------------------

6. ```strategy.cancel_all```

The ```strategy.cancel_all``` function is similar to the ```strategy.cancel``` function. It can cancel/stop all pre-listed commands. The ```when``` parameter can be specified.

Parameters:

- ```when```: Execution conditions.

```pine
/*backtest
start: 2022-07-03 00:00:00
end: 2022-07-09 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Binance","currency":"BTC_USDT"}]
*/

strategy("strategy.cancel Demo", pyramiding=3)

var isStop = false 
if isStop 
    runtime.error("stop")

strategy.entry("long1", strategy.long, 0.1, limit=1)
strategy.entry("long2", strategy.long, 0.2, limit=2)
strategy.entry("long3", strategy.long, 0.3, limit=3)

if not barstate.ishistory and close < open 
    strategy.cancel_all()
    isStop := true 

  1. strategy.order

La fonctionnalité et les paramètresstrategy.orderLes fonctions sont presque identiques àstrategy.entryLa différence est que lestrategy.orderLa fonction n'est pas affectée par lepyramidingparamètres de lastrategyfonction, et il n'y a pas de limite de nombre d'ordres.

Paramètres:

  • idL'id peut être utilisé pour annuler, modifier des ordres et fermer des positions.
  • direction: Si la direction de l'ordre est longue (acheter), passer dans la variable intégréestrategy.long, et si vous voulez vendre, passez la variablestrategy.short.
  • qty: spécifier le montant des ordres à passer, si ce paramètre n'est pas passé, le montant par défaut des ordres sera utilisé.
  • when: Condition d'exécution, vous pouvez spécifier ce paramètre pour contrôler si cette opération d'ordre en cours est déclenchée ou non.
  • limit: Indiquer le prix limite de commande.
  • stopLe prix stop-loss.

Nous utiliserons la fonctionnalité quistrategy.ordern'a pas de limite sur le nombre de commandes passées, combiné avec lestrategy.exitla fonction de sortie conditionnelle pour construire un script similaire au trading en grille.

/*backtest
start: 2021-03-01 00:00:00
end: 2022-08-30 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Binance","currency":"ETH_USDT"}]
args: [["ZPrecision",0,358374]]
*/

varip beginPrice = -1

if not barstate.ishistory
    if beginPrice == -1 or (math.abs(close - beginPrice) > 1000 and strategy.opentrades == 0) 
        beginPrice := close
    
    for i = 0 to 20
        strategy.order("buy"+i, strategy.long, 0.01, limit=beginPrice-i*200, when=(beginPrice-i*200)<close)
        strategy.exit("coverBuy"+i, "buy"+i, qty=0.01, profit=200)
        
        strategy.order("sell"+i, strategy.short, 0.01, limit=beginPrice+i*200, when=(beginPrice+i*200)>close)
        strategy.exit("coverSell"+i, "sell"+i, qty=0.01, profit=200)

Exemples de stratégie

Les exemples de stratégie dans ce tutoriel sont uniquement à des fins pédagogiques, pour guider les idées de conception de stratégie, et non pour des conseils ou des conseils commerciaux.

Stratégie de super indicateur de tendance

strategy("supertrend", overlay=true)

[supertrend, direction] = ta.supertrend(input(5, "factor"), input.int(10, "atrPeriod"))

plot(direction < 0 ? supertrend : na, "Up direction", color = color.green, style=plot.style_linebr)
plot(direction > 0 ? supertrend : na, "Down direction", color = color.red, style=plot.style_linebr)

if direction < 0
    if supertrend > supertrend[2]
        strategy.entry("entry long", strategy.long)
    else if strategy.position_size < 0
        strategy.close_all()
else if direction > 0
    if supertrend < supertrend[3]
        strategy.entry("entry short", strategy.short)
    else if strategy.position_size > 0
        strategy.close_all()

Il est très facile d'écrire une stratégie de tendance en utilisant le langage Pine, et ici nous allons concevoir une stratégie de suivi de tendance simple avec un indicateur de super tendance.

Tout d'abord, le code de stratégie commence par quelques réglages simples en utilisant lestrategyfonction:strategy("supertrend", overlay=true)``, which just sets a strategy title "supertrend". Thecouvertureparameter is set tovrai, so that the drawn indicator lines and other content are displayed on the main chart. The first thing we need to look at when designing a Pine strategy or learning a Pine strategy script is the strategy interface parameter design. Let's look at the source code of the ''supertrend indicator strategy'', which has thefonction d'entrée que nous avons apprise dans le cours précédent

[supertrend, direction] = ta.supertrend ((input ((5, facteur),input.int(Période de référence)

Leinputl'appel de fonction est utilisé comme paramètre directement sur leta.supertrendfonction d'indicateur pour le calcul de l'indicateur de supertendance.

  • l'entrée ((5, facteur)
  • input.int(Période de référence)

Par défaut, la fonction définit deux contrôles de paramètres sur l'écran de stratégie de la langue Pine, comme indiqué ci-dessous:

img

Comme nous pouvons le voir, la valeur par défaut sur la commande est le premier paramètre de lainputfonction et leinputsérie de fonctions (iciinput.intCes deux fonctions permettent ensuite de définir les paramètres de l'interfaceta.supertrendLa fonction de l'écran de stratégie.supertrendfonction calcule une donnée de prixsupertrendet les données de directiondirectionOn utilise alors leplotLorsque l'indicateur de tendance est basé sur la direction de l'indicateur de tendance, seule la direction actuelle est dessinée.directionest -1, la tendance actuelle du marché est à la hausse, lorsquedirectionest 1, la tendance actuelle du marché est à la baisse.plotfonction dessine le graphique lorsque le jugementdirectionest supérieur ou inférieur à 0.

Le prochain.if... else ifLa logique est le jugement du signal de trading.direction < 0Si les données relatives aux prix sont vraies, cela signifie que le marché actuel est en phase ascendante.supertrenddans l'indicateur de super tendance est supérieur au prix de l'indicateur de super tendance sur les deux BAR précédentes (c'est-à-diresupertrend[2], remember that the historical operator refers to the historical data of a variableSi vous avez une position en cours, l'appel de la fonction d'ordre inverse fermera d'abord la position précédente, puis ouvrira la position en fonction de la direction actuelle du trading.supertrend > supertrend[2]Les conditions de concurrence ne sont pas remplies tant que les conditions de concurrencestrategy.position_size < 0En tenant des positions courtes, il déclencherastrategy.close_all()l'exécution de la fonction de clôture de toutes les positions.

direction > 0Si les positions sont longues, toutes les positions seront fermées, et lorsque la condition est à la baisse, toutes les positions seront fermées.supertrend < supertrend[3]Le signal de détection de l'émission est atteint, un court signal sera déclenché.[3]Il est possible que l'auteur de la stratégie ait l'intention de le faire. Après tout, le risque court sur certains marchés, comme le marché du contract trading, est légèrement supérieur au risque long.

Pourta.supertrendIndicateur, est-ce que quelqu'un s'intéresse à la façon de juger si la tendance actuelle est à la hausse ou à la baisse?

En fait, cet indicateur peut également être mis en œuvre sous forme de fonctions personnalisées dans le langage Pine:

pine_supertrend(factor, atrPeriod) =>
	src = hl2
	atr = ta.atr(atrPeriod)
	upperBand = src + factor * atr
	lowerBand = src - factor * atr
	prevLowerBand = nz(lowerBand[1])
	prevUpperBand = nz(upperBand[1])

	lowerBand := lowerBand > prevLowerBand or close[1] < prevLowerBand ? lowerBand : prevLowerBand
	upperBand := upperBand < prevUpperBand or close[1] > prevUpperBand ? upperBand : prevUpperBand
	int direction = na
	float superTrend = na
	prevSuperTrend = superTrend[1]
	if na(atr[1])
		direction := 1
	else if prevSuperTrend == prevUpperBand
		direction := close > upperBand ? -1 : 1
	else
		direction := close < lowerBand ? 1 : -1
	superTrend := direction == -1 ? lowerBand : upperBand
	[superTrend, direction]

Cette fonction personnalisée est exactement le même algorithme que la fonction intégréeta.supertrend, et bien sûr les données d'indicateur calculées sont également exactement les mêmes. Comme nous pouvons le voir à partir de cet algorithme de fonction personnalisée, l'indicateur de super tendance intégré de Pine est calculé en utilisant lehl2La valeur de l'indicateur ATR (volatilité) est calculée pour une certaine période sur la base du paramètre atrPeriod.

Mise à jourlowerBandetupperBandselon les expressions ternaires du code.

    lowerBand := lowerBand > prevLowerBand or close[1] < prevLowerBand ? lowerBand : prevLowerBand
    upperBand := upperBand < prevUpperBand or close[1] > prevUpperBand ? upperBand : prevUpperBand

lowerBand: lowerBand, utilisé pour déterminer si la tendance à la hausse a changé. upperBand: upperBand, utilisé pour déterminer si la tendance à la baisse a changé. lowerBand et upperBand sont toujours calculés, seule la direction de la tendance actuelle est déterminée à la fin de cette fonction personnalisée.

    else if prevSuperTrend == prevUpperBand
        direction := close > upperBand ? -1 : 1
    else
        direction := close < lowerBand ? 1 : -1

Ici, il est jugé que si la valeur du prix du dernier BAR sur la super tendance estprevUpperBand, c'est-à-dire la bande supérieure, cela signifie que le courant est en baisse.closedépasse leupperBandLa variable de direction est la variable de direction de la tendance à la hausse.directionLa tendance à la hausse est définie sur -1 (tendance à la hausse). Sinon, elle est toujours définie sur 1 (tendance à la baisse).if direction < 0lorsque la condition de signal est déclenchée pour aller long.direction > 0, la condition de signal est déclenchée pour passer à court.

    superTrend := direction == -1 ? lowerBand : upperBand
    [superTrend, direction]

Enfin, des données spécifiques sur les prix et les données de direction de l'indicateur Super Trend sont renvoyées sur la base de la sélection de la direction.

Stratégie dynamique d'équilibrage

/*backtest
start: 2021-03-01 00:00:00
end: 2022-09-08 00:00:00
period: 1h
basePeriod: 15m
exchanges: [{"eid":"Binance","currency":"ETH_USDT"}]
args: [["v_input_1",4374],["v_input_2",3],["v_input_3",300],["ZPrecision",0,358374]]
*/

varip balance = input(50000, "balance")
varip stocks = input(0, "stocks")

maxDiffValue = input(1000, "maxDiffValue")


if balance - close * stocks > maxDiffValue and not barstate.ishistory
    // more balance , open long 
    tradeAmount = (balance - close * stocks) / 2 / close
    strategy.order("long", strategy.long, tradeAmount)
    balance := balance - tradeAmount * close
    stocks := stocks + tradeAmount
    runtime.log("balance:", balance, ", stocks:", stocks, ", tradeAmount:", tradeAmount)

else if close * stocks - balance > maxDiffValue and not barstate.ishistory
    // more stocks , open short 
    tradeAmount = (close * stocks - balance) / 2 / close
    strategy.order("short", strategy.short, tradeAmount)
    balance := balance + tradeAmount * close
    stocks := stocks - tradeAmount
    runtime.log("balance:", balance, ", stocks:", stocks, ", tradeAmount:", tradeAmount)

plot(balance, title="balance value(quoteCurrency)", color=color.red)
plot(stocks*close, title="stocks value(quoteCurrency)", color=color.blue)

img

img

Continuons avec quelques exemples de conception de stratégie en langage Pine, cette fois nous allons apprendre une stratégie d'équilibrage dynamique.BaseCurrencyet le montant deQuoteCurrency. Quelle que soit la hausse du prix relatif de l'actif, la valeur détenue dans le compte augmente et l'actif est vendu. Si le prix relatif d'un actif diminue, la valeur détenue dans le compte diminue et l'actif est acheté. Ceci est connu sous le nom de stratégie d'équilibrage dynamique. En fait, la stratégie d'équilibrage dynamique est une sorte de stratégie de grille qui fonctionne bien sur les marchés oscillants. Mais sur le marché tendance, il continuera à perdre de l'argent, nous devons attendre que le prix revienne pour réduire les pertes lentement au profit, mais l'avantage est que la stratégie d'équilibrage dynamique peut toujours capturer la tendance oscillant du marché.

L'inconvénient, comme le montre le graphique de backtest de cette stratégie, est que la stratégie a une grande perte flottante pendant la phase de la tendance générale des prix à la hausse (ou à la baisse).

Examinons la conception du code de stratégie:

Nous utilisons une conception simplifiée qui simule unbalance(c'est-à-dire le nombre d'actifs en devises cotées) etstocksNous ne lisons pas le nombre réel d'actifs dans le compte, nous utilisons simplement le montant simulé pour calculer les achats et les ventes appropriés.maxDiffValue, qui est le critère de jugement pour effectuer l'équilibrage.BaseCurrencyetQuoteCurrencydépassemaxDiffValuele processus d'équilibrage a-t-il lieu, en vendant l'actif à un prix élevé et en achetant l'actif à un prix bas pour rééquilibrer l'actif?

Le déclencheur du signal de négociation de stratégie doit être dans la phase BAR en temps réel, donc si les jugements dans les conditions de négociation de stratégie sont définis avecnot barstate.ishistory. Acheter quand lebalancela valeur dépasse lestocksL'opération de vente est effectuée sur la base de la valeur calculée en fonction du prix en cours.balanceetstocksLes variables sont mises à jour et attendent ensuite le prochain déclenchement de l'équilibre.

L'information ci-dessus de la stratégie backtest contient le prix de l'espèce au moment du début de la stratégie backtest, le prix est 1458, donc je définis le paramètrebalanceà: 4374 (1458*3) délibérément, définir le paramètrestocksLaissez l'actif commencer en équilibre.

Super stratégie de tendance avec suivi Stop Loss et Profit Take

Dans le cours précédent, nous avons étudié lesstrategy.exitDans cet exemple de conception de stratégie, nous utiliserons la fonction d'arrêt de suivi et de prise de profit.strategy.exitLa fonction de l'optimisation d'une stratégie de super tendance.

Tout d'abord, examinons les paramètres de suivi du stop-loss et du take-profit dustrategy.exitfonction:

  1. Paramètretrail_price: La position qui déclenche l' action logique consistant à placer un ordre stop-loss de suivi et un ordre de clôture de stop-loss (à la position spécifiée par le prix).
  2. Paramètretrail_offset: La distance entre le prix le plus élevé (en long) ou le prix le plus bas (en court) d'une position fermée placée après l'exécution d'une action de suivi stop-loss et take-profit.
  3. Paramètretrail_pointsComme letrail_priceParamètre, sauf qu'il prend des points de profit comme position spécifiée.

Ce n'est pas facile à comprendre? Cela n'a pas d'importance! Passons par un scénario de backtesting stratégique pour comprendre, qui est en fait assez simple.

/*backtest
start: 2022-09-23 00:00:00
end: 2022-09-23 08:00:00
period: 1m
basePeriod: 1m
exchanges: [{"eid":"Binance","currency":"ETH_USDT"}]
args: [["RunMode",1,358374],["ZPrecision",0,358374]]
*/

strategy("test", overlay = true)

varip a = na
varip highPrice = na
varip isTrade = false 
varip offset = 30

if not barstate.ishistory and not isTrade
    strategy.entry("test 1", strategy.long, 1)
    strategy.exit("exit 1", "test 1", 1, trail_price=close+offset, trail_offset=offset)
    a := close + offset
    runtime.log("the price per point is:", syminfo.mintick, ", current close:", close)
    isTrade := true 

if close > a and not barstate.ishistory
    highPrice := na(highPrice) ? close : highPrice
    highPrice := close > highPrice ? close : highPrice

plot(a, "trail_price trigger line")    
plot(strategy.position_size>0 ? highPrice : na, "current highest price")
plot(strategy.position_size>0 ? highPrice-syminfo.mintick*offset : na, "moving stop trigger line")

img

img

img

Entrée longue immédiate lorsque la stratégie commence à exécuter, puis immédiatement placé unstrategy.exitl'ordre de sortie (il spécifiait les paramètres de suivi stop-loss et take-profit), lorsque le prix du changement de marché s'élevait au-dessus de la ligne de déclenchement de trail_price, la mise en œuvre de la logique de stop-loss et take-profit de trailing, la ligne de stop-loss et take-profit (bleu) a commencé à suivre l'ajustement dynamique de prix le plus élevé, la position de ligne bleue est le déclencheur de stop-loss et take-profit pour fermer la position, et enfin lorsque le prix du marché tombe en dessous de la ligne bleue qui déclenche la fermeture de la position. Combiné avec la ligne dessinée sur le graphique, il est très facile à comprendre.

Ensuite, nous utilisons cette fonctionnalité pour optimiser une stratégie de super tendance, nous assignons simplement unstrategy.exitl'ordre de plan de sortie à l'ordre d'entrée de stratégie pour ajouter cette fonctionnalité de stop-loss et de take-profit.

if not barstate.ishistory and findOrderIdx("open") >= 0 and state == 1
    trail_price := strategy.position_size > 0 ? close + offset : close - offset
    strategy.exit("exit", "open", 1, trail_price=trail_price, trail_offset=offset)
    runtime.log("the price per point is:", syminfo.mintick, ", current close:", close, ",trail_price:", trail_price)
    state := 2 
    tradeBarIndex := bar_index

Code de stratégie complet:

/*backtest
start: 2022-05-01 00:00:00
end: 2022-09-27 00:00:00
period: 1d
basePeriod: 5m
exchanges: [{"eid":"Binance","currency":"ETH_USDT"}]
args: [["RunMode",1,358374],["ZPrecision",0,358374]]
*/

varip trail_price = na
varip offset = input(50, "offset")
varip tradeBarIndex = 0
// 0 : idle , 1 current_open , 2 current_close
varip state = 0  

findOrderIdx(idx) =>
    ret = -1 
    if strategy.opentrades == 0 
        ret
    else 
        for i = 0 to strategy.opentrades - 1 
            if strategy.opentrades.entry_id(i) == idx
                ret := i 
                break
        ret

if strategy.position_size == 0 
    trail_price := na 
    state := 0

[superTrendPrice, dir] = ta.supertrend(input(2, "atr coefficient"), input(20, "atr period"))

if ((dir[1] < 0 and dir[2] > 0) or (superTrendPrice[1] > superTrendPrice[2])) and state == 0 and tradeBarIndex != bar_index
    strategy.entry("open", strategy.long, 1)
    state := 1
else if ((dir[1] > 0 and dir[2] < 0) or (superTrendPrice[1] < superTrendPrice[2])) and state == 0 and tradeBarIndex != bar_index
    strategy.entry("open", strategy.short, 1)
    state := 1


// Reverse signal, close all positions
if strategy.position_size > 0 and dir[2] < 0 and dir[1] > 0
    strategy.cancel_all()
    strategy.close_all()
    runtime.log("trend reversal, long positions all closed")
else if strategy.position_size < 0 and dir[2] > 0 and dir[1] < 0
    strategy.cancel_all()
    strategy.close_all()
    runtime.log("trend reversal, short positions all closed")


if not barstate.ishistory and findOrderIdx("open") >= 0 and state == 1
    trail_price := strategy.position_size > 0 ? close + offset : close - offset
    strategy.exit("exit", "open", 1, trail_price=trail_price, trail_offset=offset)
    runtime.log("the price per point is:", syminfo.mintick, ", current close:", close, ", trail_price:", trail_price)
    state := 2 
    tradeBarIndex := bar_index


plot(superTrendPrice, "superTrendPrice", color=dir>0 ? color.red : color.green, overlay=true)

Plus de