En la carga de los recursos... Cargando...

Tutorial introductorio del lenguaje PINE de FMZ Quant

El autor:FMZ~Lydia, Creado: 2022-09-23 15:23:34, Actualizado: 2024-02-27 16:47:41

.3, límite=3)

si no es barstate.ishistory y cierre < abierto Estrategia.cancel ((long1) Estrategia.cancel ((long2) Estrategia.cancel ((long3) isStop:= verdadero


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

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 funcionalidad y la configuración de parámetros destrategy.orderLas funciones de losstrategy.entryLa diferencia es que elstrategy.orderla función no se ve afectada por elpyramidingconfiguración de los parámetros delstrategyFunción, y no hay límite de número de órdenes.

Parámetros:

  • idSe puede entender como dar un nombre a una posición de negociación para la referencia.
  • direction: Si la dirección de la orden es larga (comprar), pasar en la variable incorporadastrategy.long, y si desea ir corto (vender), pasar en la variablestrategy.short.
  • qty: Especificar el importe de las órdenes a realizar, si no se pasa este parámetro, se utilizará el importe predeterminado de las órdenes.
  • when: Condición de ejecución, puede especificar este parámetro para controlar si se activa o no esta operación de orden actual.
  • limit: Especificar el precio límite de la orden.
  • stopPrecio de suspensión de pérdida.

Usaremos la característica questrategy.orderno tiene límite en el número de pedidos realizados, combinado con elstrategy.exitla función de salida condicional para construir un guión similar al comercio en red.

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

Ejemplos de estrategias

Los ejemplos de estrategias en este tutorial son solo para fines de instrucción, para guiar las ideas de diseño de estrategias, y no para cualquier guía o consejo comercial.

Estrategia de los súper indicadores de tendencia

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

Es muy fácil escribir una estrategia de tendencia usando el lenguaje Pine, y aquí vamos a diseñar una estrategia de tendencia simple con un indicador de tendencia súper.

En primer lugar, el código de estrategia comienza con algunas configuraciones simples mediante el uso de lastrategyFunción:strategy("supertrend", overlay=true)``, which just sets a strategy title "supertrend". Thesuperposiciónparameter is set toEs cierto, 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 theLa función de entrada que aprendimos en el curso anterior

[supertendencia, dirección] = ta.supertendencia ((entrada ((5, factor),input.int(por ejemplo, en el caso de las empresas de servicios de telecomunicaciones, en el caso de las empresas de telecomunicaciones)

Elinputllamada de la función se utiliza como un parámetro directamente a lata.supertrendfunción de indicador para calcular el indicador de supertendencia.

  • entrada ((5, factor)
  • input.int(Periodo de 10 años)

Por defecto, la función establece dos controles de parámetros en la pantalla de estrategia del lenguaje Pine, como se muestra a continuación:

img

Como podemos ver, el valor predeterminado en el control es el primer parámetro delinputLa función y elinputLa serie de funciones (aquí esinput.intCon estas dos funciones, podemos entonces establecer los parámetros de lata.supertrendLa función en la pantalla de la estrategia.supertrendFunción calcula un precio de datossupertrendy datos de direccióndirectionEntonces usamos elplotLa función para dibujar un gráfico, tenga en cuenta que al dibujar el gráfico, se basa en la dirección del indicador de supertrend, sólo se dibuja la dirección actual.directiones -1, la tendencia actual del mercado es al alza, cuandodirectionEs 1, la tendencia actual del mercado es a la baja.plotFunción dibuja el gráfico cuando el juiciodirectiones mayor o menor que 0.

El siguienteif... else ifLa lógica es el juicio de la señal de comercio.direction < 0En este momento, si los datos de precios son correctos, el mercado actual se encuentra en una fase ascendente.supertrenden el indicador de súper tendencia es superior al precio del indicador de súper tendencia en los dos BAR anteriores (es decir,supertrend[2], remember that the historical operator refers to the historical data of a variableSi hay una posición actual, llamar a la función de orden inversa cerrará la posición anterior primero, y luego abrirá la posición de acuerdo con la dirección de negociación actual.supertrend > supertrend[2]No se han cumplido, siempre y cuando elstrategy.position_size < 0manteniendo posiciones cortas, activarástrategy.close_all()ejecución de la función para cerrar todas las posiciones.

direction > 0Si hay posiciones largas, todas las posiciones se cerrarán, y luego cuando la condiciónsupertrend < supertrend[3]Cuando se cumple, se activará una señal corta.[3]En el caso de los mercados de valores, el riesgo corto en algunos mercados, como el mercado de negociación de contratos, es ligeramente mayor que el riesgo largo.

Parata.supertrendIndicador, ¿alguien está interesado en cómo juzgar si la tendencia actual es al alza o a la baja?

De hecho, este indicador también se puede implementar en forma de funciones personalizadas en el lenguaje 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 función personalizada es exactamente el mismo algoritmo que la función incorporadata.supertrend, y, por supuesto, los datos de los indicadores calculados también son exactamente los mismos. Como podemos ver en este algoritmo de función personalizada, el indicador de tendencia súper incorporado de Pine se calcula utilizando elhl2En el caso de los precios más bajos y los más altos, se calcula el valor medio de los precios más altos y los más bajos, y el indicador ATR (volatilidad) se calcula para un determinado período basándose en el parámetro atrPeriod.

ActualizaciónlowerBandyupperBandde acuerdo con las expresiones ternaras del 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 si la tendencia al alza ha cambiado. upperBand: upperBand, utilizado para determinar si la tendencia a la baja ha cambiado. lowerBand y upperBand siempre se calculan, solo se determina la dirección de tendencia actual al final de esta función personalizada.

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

Aquí se juzga que si el valor del precio de la última barra en la tendencia súper esprevUpperBand, es decir, la banda superior, significa que la corriente es una tendencia a la baja.closeexcede elupperBandLa variable de dirección es la variable de dirección de la tendencia.directionEs por eso que se ve en la estrategia de la súper tendenciaif direction < 0cuando la condición de la señal se activa para ir largo.direction > 0, la condición de la señal se activa para ir corto.

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

Por último, se devuelven datos específicos de precios y datos de dirección del Super Trend Indicator basados en la selección de dirección.

Estrategia de balance 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

Continuemos con algunos ejemplos de diseño de estrategia en lenguaje Pine, esta vez aprenderemos una estrategia de equilibrio dinámico.BaseCurrencyy la cantidad deQuoteCurrency. Cualquiera que sea el precio relativo del activo, el valor mantenido en la cuenta aumenta y el activo se vende. Si el precio relativo de un activo disminuye, el valor mantenido en la cuenta disminuye y el activo se compra. Esto se conoce como una estrategia de equilibrio dinámico. De hecho, la estrategia de equilibrio dinámico es un tipo de estrategia de red que funciona bien en los mercados oscilantes. Pero en el mercado de tendencia, continuará perdiendo dinero, necesitamos esperar a que el precio regrese para reducir las pérdidas lentamente a la ganancia, pero la ventaja es que la estrategia de equilibrio dinámico siempre puede capturar la tendencia oscilante del mercado.

La desventaja, como se muestra en el gráfico de backtest de esta estrategia, es que la estrategia tiene una gran pérdida flotante durante la etapa de la tendencia general del precio hacia arriba (o hacia abajo).

Veamos el diseño del código de estrategia:

Utilizamos un diseño simplificado que simula unbalance(es decir, el número de activos en moneda de cotización) ystocksEn la estrategia, el número de activos de base de divisas (es decir, el número de activos de base de divisas) es la información de balance.maxDiffValue, que es el criterio de evaluación para llevar a cabo la compensación.BaseCurrencyyQuoteCurrencyexcedemaxDiffValue¿se lleva a cabo el proceso de equilibración, vendiendo el activo a un precio alto y comprando el activo a un precio bajo para reequilibrar el activo?

El activador de la señal de negociación de estrategia debe estar en la etapa BAR en tiempo real, por lo que si los juicios en las condiciones de negociación de la estrategia se establecen connot barstate.ishistoryComprar cuando elbalanceel valor excede elstocksEn el caso de las operaciones de venta, el valor de la transacción se calcula en función del precio actual.balanceystocksLas variables se actualizan y luego esperan el siguiente balance.

La información anterior de la estrategia backtest contiene el precio de la especie en el momento de inicio de la estrategia backtest, el precio es 1458, por lo que establezco el parámetrobalancepara: 4374 (1458*3) deliberadamente, establecer el parámetrostocksPara: 3. Que el activo comience en equilibrio.

Estrategia de Super Tendencia con seguimiento de Stop Loss y Take Profit

En el curso anterior, hemos aprendido acerca de lastrategy.exitEn este ejemplo de diseño de estrategia, vamos a utilizar la función de salida de posición, de la que no tenemos un ejemplo para explicar el seguimiento de la parada y tomar beneficios función.strategy.exitLa función de optimizar una estrategia de súper tendencia.

En primer lugar, veamos los parámetros de seguimiento de stop-loss y take-profit de lastrategy.exitFunción:

  1. Parámetrotrail_price: La posición que desencadena la acción lógica de colocar una orden de stop-loss de seguimiento y una orden de cierre de stop-loss (en la posición especificada por el precio).
  2. Parámetrotrail_offset: Distancia entre el precio más alto (en caso de transacción larga) o el precio más bajo (en caso de transacción corta) de una posición cerrada colocada después de la ejecución de una acción de seguimiento de stop-loss y take-profit.
  3. Parámetrotrail_pointsComo eltrail_priceParámetro, excepto que toma puntos de ganancia como la posición especificada.

¿No es eso fácil de entender? No importa! Vamos a pasar por un escenario de backtesting de estrategia para entender, que en realidad es bastante 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

Inmediato entrada larga cuando la estrategia comienza a ejecutarse, y luego inmediatamente colocado unstrategy.exitorden de salida (especifica los parámetros de seguimiento de stop-loss y take-profit), cuando el precio del cambio de mercado se elevó por encima de la línea de activación de trail_price, la implementación de la lógica de stop-loss y take-profit, la línea de stop-loss y take-profit (azul) comenzó a seguir el ajuste dinámico de precio más alto, la posición de la línea azul es el detente de stop-loss y take-profit para cerrar la posición, y finalmente cuando el precio de mercado cae por debajo de la línea azul que desencadena el cierre de la posición. Combinado con la línea dibujada en el gráfico, es muy fácil de entender.

Luego usamos esta característica para optimizar una estrategia de super tendencias, simplemente asignamos unstrategy.exitla orden de salida del plan a la orden de entrada de la estrategia para añadir esta característica de stop-loss y 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 de la estrategia:

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

Más.