O recurso está a ser carregado... Carregamento...

Tutorial de Introdução à Língua PINE do FMZ Quant

Autora:FMZ~Lydia, Criado: 2022-09-23 15:23:34, Atualizado: 2024-02-27 16:47:41

.3, limite=3)

se não barstate.ishistory e close < open estratégia. cancelar ((long1) estratégia. cancelar ((long2) estratégia. cancelar ((long3) isStop:= true


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

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

A funcionalidade e as definições dos parâmetros dostrategy.orderA sua função é quase idêntica à dosstrategy.entryA diferença é que ostrategy.orderA função não é afectada pelopyramidingconfigurações de parâmetros dostrategyfunção, e não há limite de contagem de ordens.

Parâmetros:

  • idO ID pode ser referenciado para cancelar, modificar ordens e fechar posições.
  • direction: Se a direcção da ordem for longa (comprar), passar na variável incorporadastrategy.long, e se você quiser ficar curto (vender), passe na variávelstrategy.short.
  • qty: Especificar o montante das ordens a realizar, se este parâmetro não for transmitido, será utilizado o montante por defeito das ordens.
  • when: Condição de execução, pode especificar este parâmetro para controlar se esta operação de ordem actual é desencadeada ou não.
  • limit: Especificar o preço limite da ordem.
  • stopPreço stop loss.

Usaremos o recurso questrategy.ordernão tem limite no número de encomendas feitas, combinado com ostrategy.exitFunção de saída condicional para construir um script semelhante à negociação em grade.

/*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)

Exemplos de estratégia

Os exemplos de estratégia neste tutorial são apenas para fins de instrução, para orientar ideias de design de estratégia, e não para qualquer orientação ou conselho de negociação.

Estratégia de Superindicador de Tendência

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()

É muito fácil escrever uma estratégia de tendência usando a linguagem Pine, e aqui vamos projetar uma estratégia simples de tendência com um indicador de tendência super.

Primeiro, o código de estratégia começa com algumas configurações simples usando ostrategyFunção:strategy("supertrend", overlay=true)``, which just sets a strategy title "supertrend". Thesobreposiçãoparameter is set toverdade, 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 thefunção input ` ` que aprendemos no curso anterior

[supertendência, direção] = ta.supertendência ((input ((5, factor),input.int(10, atrPeriodo))

Oinputchamada de função é usado como um parâmetro diretamente para ota.supertrendFunção de indicador para calcular o indicador de supertendência.

  • input ((5, factor)
  • input.int(10, atrPeriodo)

Por padrão, a função define dois controles de parâmetros na tela de estratégia da linguagem Pine, conforme mostrado abaixo:

img

Como podemos ver, o valor padrão no controle é o primeiro parâmetro doinputFunção einputsérie de funções (a seguirinput.intCom estas duas funções, podemos então definir os parâmetros dota.supertrendA função desupertrendFunção calcula dados de preçosupertrende dados de direcçãodirectionEntão usamos oplotFunção para desenhar um gráfico, note que ao desenhar o gráfico, baseia-se na direção do indicador de supertendência, apenas a direção atual é desenhada.directioné -1, a tendência actual do mercado é ascendente, quandodirectionAssim, podemos ver que a tendência de mercado atual é para baixo.plotFunção desenha o gráfico quando o julgamentodirectioné maior ou menor que 0.

O próximo.if... else ifA lógica é o julgamento do sinal de negociação.direction < 0O mercado actual está numa fase ascendente.supertrendno indicador de super tendência é superior ao preço do indicador de super tendência nos dois BAR anteriores (ou seja,supertrend[2], remember that the historical operator refers to the historical data of a variableSe houver uma posição atual, chamar a função de ordem reversa fechará a posição anterior primeiro e depois abrirá a posição de acordo com a direção atual da negociação.supertrend > supertrend[2]Não foram respeitadas, desde que ostrategy.position_size < 0mantendo posições curtas, irá desencadearstrategy.close_all()Execução da função para fechar todas as posições.

direction > 0Se houver posições longas, todas as posições serão fechadas e, em seguida, quando a condiçãosupertrend < supertrend[3]O que é que o sistema está a fazer?[3]O risco de curto prazo em alguns mercados, como o mercado de negociação de contratos, é ligeiramente maior do que o risco de longo prazo.

Parata.supertrendIndicador, alguém está interessado em como julgar se a tendência atual é para cima ou para baixo?

Na verdade, este indicador também pode ser implementado na forma de funções personalizadas na linguagem 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]

Esta função personalizada é exatamente o mesmo algoritmo que a função embutidata.supertrend, e é claro que os dados do indicador calculado também são exactamente os mesmos. Como podemos ver a partir deste algoritmo de função personalizada, Pines embutida em indicador de super tendência é calculado usando ohl2A variabilidade embutida (os preços mais altos e mais baixos são somados e depois divididos por 2, ou seja, a média dos preços mais altos e mais baixos), e depois o indicador ATR (volatilidade) é calculado para um determinado período com base no parâmetro atrPeriod.

AtualizaçãolowerBandeupperBandDe acordo com as expressões ternárias do código.

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

lowerBand: lowerBand, utilizado para determinar se a tendência ascendente mudou. upperBand: upperBand, utilizado para determinar se a tendência descendente mudou. lowerBand e upperBand são sempre calculados, apenas a direção atual da tendência é determinada no final desta função personalizada.

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

Aqui é julgado que se o valor do preço do último BAR na super tendência éprevUpperBand, ou seja, a banda superior, significa que a corrente é uma tendência descendente.closeexcede oupperBandA variável de direcção é a variável de direcção que, quando a tendência se transforma em uma tendência ascendente, é considerada como uma variável de direcção.directionÉ por isso que você vê na estratégia de super tendênciaif direction < 0quando a condição do sinal é desencadeada para ir longo.direction > 0, a condição do sinal é desencadeada para ir curto.

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

Por último, são devolvidos dados específicos de preços e de direção do Indicador de Super Tendência com base na seleção de direção.

Estratégia de equilíbrio dinâmico

/*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

Vamos continuar com alguns exemplos de design de estratégia em linguagem Pine, desta vez vamos aprender uma estratégia de equilíbrio dinâmico.BaseCurrencye o montante deQuoteCurrency. Qualquer que seja o preço relativo do ativo, o valor mantido na conta aumenta e o ativo é vendido. Se o preço relativo de um ativo diminui, o valor mantido na conta diminui e o ativo é comprado. Isso é conhecido como uma estratégia de equilíbrio dinâmico. Na verdade, a estratégia de equilíbrio dinâmico é um tipo de estratégia de grade que funciona bem em mercados oscilantes. Mas no mercado de tendência, continuará perdendo dinheiro, precisamos esperar que o preço retorne para reduzir as perdas lentamente para o lucro, mas a vantagem é que a estratégia de equilíbrio dinâmico sempre pode capturar a tendência oscilante do mercado.

A desvantagem, como mostrado no gráfico de backtest desta estratégia, é que a estratégia tem uma grande perda flutuante durante a fase da tendência geral de preços para cima (ou para baixo).

Vejamos o desenho do código de estratégia:

Utilizamos um projecto simplificado que simula umbalance(ou seja, o número de activos em moeda de cotação) estocksO número de ativos base (ou seja, o número de ativos BaseCurrency) informações de saldo na estratégia. Nós não ler o número real de ativos na conta, nós simplesmente usamos o valor simulado para calcular as compras e vendas apropriadas.maxDiffValue, que constitui o critério de apreciação para a realização do equilíbrio.BaseCurrencyeQuoteCurrencyexcedemaxDiffValueO processo de equilíbrio ocorre, vendendo o ativo a um preço elevado e comprando o ativo a um preço baixo para reequilibrar o ativo.

O gatilho do sinal de negociação de estratégia deve estar na fase BAR em tempo real, por isso, se os julgamentos nas condições de negociação de estratégia são definidos comnot barstate.ishistory. Compre quando obalancevalor excede ostocksA operação de venda é executada após a execução da declaração de transacção, a operação de venda é executada após a execução da declaração de transacção, a operação de venda é executada após a execução da declaração de transacção.balanceestocksAs variáveis são atualizadas e, em seguida, aguardar o próximo balanço acionador.

A informação acima da estratégia backtest contém o preço da espécie no momento do início da estratégia backtest, o preço é 1458, então eu defino o parâmetrobalancepara: 4374 (1458*3) deliberadamente, definir o parâmetrostocksPara: 3. Deixar o activo começar em equilíbrio.

Super estratégia de tendência com rastreamento Stop Loss e Take Profit

No curso anterior, aprendemos sobre astrategy.exitA função de saída de posição, da qual não tínhamos um exemplo para explicar a função de rastreamento stop e take profit.strategy.exitA função de optimizar uma estratégia de super tendência.

Em primeiro lugar, vamos analisar os parâmetros de rastreamento de stop-loss e take-profit dostrategy.exitFunção:

  1. Parâmetrotrail_price: A posição que desencadeia a ação lógica de colocação de uma ordem de stop-loss de acompanhamento e de encerramento de uma ordem de stop-loss (na posição especificada pelo preço).
  2. Parâmetrotrail_offsetA distância entre o preço mais alto (no caso de transações longas) e o preço mais baixo (no caso de transações short) de uma posição fechada colocada após a execução de uma ação de stop-loss e take-profit de rastreamento.
  3. Parâmetrotrail_pointsComo otrail_priceParâmetro, exceto que toma pontos de lucro como a posição especificada.

Não é fácil de entender? Não importa! Vamos passar por um cenário de backtesting estratégico para entender, que é realmente bastante simples.

/*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

Imediata entrada longa quando a estratégia começa a executar, e, em seguida, imediatamente colocado umstrategy.exitordem de saída (especificou os parâmetros de stop-loss e take-profit de rastreamento), quando o preço da mudança de mercado subiu acima da linha de gatilho trail_price, a implementação da lógica de stop-loss e take-profit de rastreamento, linha de stop-loss e take-profit (azul) começou a seguir o maior ajuste dinâmico de preço, a posição da linha azul é o gatilho de stop-loss e take-profit para fechar a posição e, finalmente, quando o preço de mercado cai abaixo da linha azul que desencadeia o fechamento da posição. Combinado com a linha desenhada no gráfico, é muito fácil de entender.

Então usamos este recurso para otimizar uma estratégia de super tendências, nós simplesmente atribuir umstrategy.exitA ordem de saída do plano para a ordem de entrada da estratégia para adicionar este recurso de stop-loss e 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

Código completo da estratégia:

/*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)

Mais.