Estrategias y Probador de estrategias
1Estrategias y Probador de estrategias
Cómo escribir una estrategia en LootScript y probarla sobre el historial en el probador: declaración strategy(), órdenes, modelo de ejecución, costes, pestañas del informe y limitaciones del backtest.
Una estrategia es un script que, además de dibujar líneas en el gráfico, envía órdenes. Las órdenes no las ejecuta un exchange real sino un simulador dentro del terminal: ejecuta la estrategia sobre el historial del gráfico con comisiones, deslizamiento y tasa de financiación, y muestra el resultado en la ventana Probador de estrategias.
Declaración strategy()
La primera línea diferencia una estrategia de un indicador: strategy(...) en lugar de indicator(...). Todo lo demás —ajustes, renderizado, datos de mercado— funciona igual. Las funciones strategy.* en un indicador no se compilan: “strategy.* disponible solo en strategy(…)”.
| Parámetro | Por defecto | Qué establece |
|---|---|---|
initialCapital |
10000 |
Capital inicial |
defaultQtyType, defaultQtyValue |
strategy.qty.fixed, 1 |
Tamaño de la orden si no se especifica qty |
commissionType, commissionValue |
porcentaje, no definido | Comisión: strategy.commission.percent — porcentaje sobre el volumen (0.05 = 0,05 %), strategy.commission.cash_per_contract — importe por unidad de cantidad, strategy.commission.cash_per_order — importe por ejecución |
slippageTicks |
0 |
Deslizamiento en ticks |
pyramiding |
0 |
Cuántas entradas en una misma dirección pueden estar abiertas; 0 — una sola |
positionModel |
strategy.model.netting |
Una posición agregada o posiciones separadas long/short (strategy.model.hedging) |
processOrdersOnClose |
false |
Ejecutar órdenes de mercado al cierre de la vela actual |
calcOnEveryTick |
false |
Permitir órdenes en la vela en formación |
marginLong, marginShort, leverage |
0, 0, 1 |
Margen en porcentaje o apalancamiento; con 0 la liquidación no se modela |
applyFunding |
true |
Tener en cuenta la tasa de financiación |
fillModel |
strategy.fill.conservative |
Suposición sobre el recorrido del precio dentro de la vela |
Los valores de parámetros solo pueden ser números y constantes literales. Una expresión o input.* en la declaración es un error de compilación. El parámetro calcOnOrderFills es aceptado, pero en esta versión no tiene efecto: en la pestaña “Propiedades” del probador aparece marcado como “no actúa en esta build”.
El tamaño de la orden cuando qty = na lo define defaultQtyType:
| Tipo | Qué significa defaultQtyValue |
|---|---|
strategy.qty.fixed |
Cantidad en monedas (moneda base) |
strategy.qty.cash |
Importe en la moneda cotizada |
strategy.qty.percent_of_equity |
Porcentaje del capital actual |
strategy.qty.risk_percent |
Porcentaje del capital que arriesgas hasta un stop protector |
Para strategy.qty.risk_percent se necesita un strategy.exit con stop (loss o stop); de lo contrario el compilador aborta: “requiere un stop respecto al cual calcular el tamaño”. La cantidad se redondea hacia abajo al paso de cantidad del instrumento. Si tras redondear queda cero, la orden se rechaza y se cuenta en el probador como “Rechazadas (por tamaño)”.
Órdenes
| Función | Qué hace |
|---|---|
strategy.entry(id, direction, qty, limit, stop, …) |
Abre o gira una posición. Respeta el modelo de posición y pyramiding |
strategy.order(id, direction, qty, limit, stop, …) |
Igual pero sin respetar el modelo de posición ni pyramiding |
strategy.exit(id, from_entry, qty, qty_percent, profit, limit, loss, stop, trail_price, trail_points, trail_offset, …) |
Coloca la salida —take, stop o trailing— para una entrada abierta |
strategy.close(id, comment, qty, qty_percent) |
Cierra la entrada con una orden de mercado |
strategy.close_all(comment) |
Cierra todo |
strategy.cancel(id), strategy.cancel_all() |
Elimina órdenes aún no ejecutadas |
La dirección — strategy.long o strategy.short. Todas las funciones admiten el opcional when: when = false evita la ejecución. Entradas, salidas y cierres admiten además comment — etiqueta de texto para la orden.
- Tipo de entrada. Sin
limitnistop— orden de mercado; conlimit— orden límite; constop— orden stop; con ambos — stop-limit. Unstrategy.entryrepetido con el mismoidreemplaza la orden pendiente. - Giro. En el modelo
nettinguna entrada en la dirección opuesta cierra la posición actual y abre la nueva en una sola acción. - Unidades de salida.
profityloss— en ticks desde el precio de entrada;limitystop— precios absolutos. El trailing se define con el par:trail_offsetmástrail_priceotrail_points. - Un
strategy.exitsin niveles no hace nada. El compilador avisará: “strategy.exit sin ningún nivel (profit/loss/stop/limit/trail) — operación vacía”. - Mover el stop. Un
strategy.exitrepetido con el mismoidreemplaza la salida — así se mueve el stop.
El estado de la estrategia se lee por filas: strategy.position_size (con signo, short es negativo), strategy.position_avg_price, strategy.equity, strategy.netprofit, strategy.openprofit, strategy.opentrades, strategy.closedtrades, strategy.funding_paid y más — la lista completa está en el referente.
Cómo el probador ejecuta las órdenes
Una orden enviada en una vela se ejecuta no antes de la siguiente vela. La decisión se toma al cierre de la vela, y ejecutarla al mismo precio implicaría mirar hacia adelante.
| Orden | Ejecución |
|---|---|
| Mercado | En la apertura de la siguiente vela más el deslizamiento. Con processOrdersOnClose = true — al cierre de la vela actual |
| Límite | Cuando el precio pasa el límite, al precio límite. Si la vela abrió más allá del límite — en la apertura |
| Stop | Cuando el precio pasa el stop, al precio del stop más deslizamiento. En caso de gap — en la apertura más deslizamiento |
Recorrido del precio dentro de la vela. El probador no conoce el recorrido real del precio dentro de la vela y lo asume. El modelo strategy.fill.conservative (por defecto) considera que el precio primero fue al peor extremo: en una vela alcista — apertura → mínimo → máximo → cierre; en una bajista — al revés. Si en una sola vela están stop y take, se dispara el stop. El modelo strategy.fill.optimistic asume lo contrario — sirve solo para comparar. En esta versión no hay reejecución sobre marcos menores: en la columna «Ruta» cada operación se marca como supuesta por el modelo.
Costes.
- Comisión. Si
commissionValueno está definido, el probador usa la tarifa por defecto: 0,02 % en ejecuciones límite y 0,05 % en órdenes de mercado y stop. La tarifa de tu cuenta y los rebates al terminal son desconocidos. Un valor especificado se aplica a todas las ejecuciones. - Deslizamiento —
slippageTicksen tu contra en ejecuciones de mercado y stop. Las órdenes límite no deslizan. - Tasa de financiación se descuenta en cada liquidación real del exchange — a la tasa real y al precio de cierre de la vela de cálculo. Para ello se requieren datos de financiación: futuros de exchanges desde la tabla de cobertura.
- Margen. Con
marginLong/marginShorto apalancamiento > 1 el probador modela un margen aislado simplificado. Una posición larga se liquida en precio entrada × (1 − m/2), la corta en entrada × (1 + m/2), donde m es la fracción del margen inicial. Una operación liquidada pierde todo el margen inicial.
Las operaciones no cerradas al final del historial se cierran al cierre de la última vela por la razón “fin de datos”.
Probador de estrategias
Añada la estrategia al gráfico
En el Editor pulse Añadir al gráfico (Ctrl+Enter). Un script con errores no se añadirá al gráfico.
Abra el probador
En la barra de herramientas del Editor pulse Probador de estrategias… — el botón está activo solo para scripts con strategy(...). Otra vía: desde los ajustes de la estrategia en la leyenda del gráfico (engranaje), botón Probador de estrategias….
Espere a que termine el proceso
El probador calcula sobre las velas cargadas en el gráfico. Mientras no haya velas, la ventana muestra “La estrategia aún no se ha calculado: espere a la carga de velas”. Cuando llegan nuevas velas, el resultado se recalcula automáticamente; el botón Recalcular lanza un recorrido completo manualmente.
Si hay varias estrategias en el gráfico, puedes seleccionar la que quieras directamente en la ventana del probador.
| Pestaña | Qué contiene |
|---|---|
| Resumen | Baldosas “Beneficio neto”, “Profit factor”, “Máx. drawdown (por cierres)”, “Porcentaje ganadoras”, “SQN”; franja “Qué no conoce este backtest”; curvas de capital, “comprar y mantener”, capital sin tasa de financiación y dos drawdowns |
| Métricas | Resultado, riesgo (drawdown por cierres y dentro de vela por separado, Sharpe, Sortino, Calmar), operaciones (porcentaje ganadoras, medias y mayores, rachas), costes (comisión y tasa de financiación) |
| Operaciones | Tabla de operaciones: entrada, salida, motivo, volumen, P&L, run-up, drawdown, comisión, financiación. Clic en la fila centra el gráfico en la vela de entrada; Ctrl+C copia las filas seleccionadas |
| Propiedades | Parámetros de la declaración, rango de velas, paso de precio, paso de cantidad, lote mínimo, comisión, contadores del proceso: órdenes rechazadas, saltadas por pyramiding, liquidaciones, cálculos de financiación |
En el título de la ventana — etiquetas de modo: conservative o optimistic por el modelo de ejecución y close-fill si processOrdersOnClose = true. Las etiquetas optimistic y close-fill indican que el resultado en vivo probablemente será peor.
Qué no puede leer la estrategia
Libro de órdenes en vivo y cinta de operaciones. Una estrategia que lea book.* o tape.* no se compila: “La estrategia lee … el libro y la cinta no tienen historial, el backtest sería ficticio”. Para historial del libro existe depth.*, para operaciones — delta.* y cluster.*.
Screener. screener.* también existe solo en la última vela, pero el compilador permite compilar esa estrategia. En el historial los valores del screener son na, por eso las condiciones con ellos no se cumplen y no habrá operaciones basadas en ellos en el informe.
Mirar hacia adelante. request.security(..., lookahead = true) en una estrategia muestra en el editor la advertencia “La estrategia mira hacia adelante … el informe está marcado como inalcanzable en tiempo real”. Trata ese informe como optimista: en el historial la estrategia ve valores que en vivo todavía no existirían. Más detalles en la sección de Datos de mercado.
Ejemplo
Ruptura de canal con confirmación por delta. Entrada — al cierre fuera del canal de los últimos len velas, si la delta de la vela coincide. Stop en ATR, take al doble.
strategy("Пробой канала с дельтой", overlay = true,
initialCapital = 10000,
defaultQtyType = strategy.qty.percent_of_equity, defaultQtyValue = 20,
commissionValue = 0.05, slippageTicks = 2)
len = input.int(20, "Канал, баров", minval = 5, maxval = 200)
stopAtr = input.float(1.5, "Стоп, ATR", minval = 0.5, maxval = 10, step = 0.1)
needFlow = input.bool(true, "Подтверждать дельтой")
upper = ta.highest(high, len)[1]
lower = ta.lowest(low, len)[1]
atr = ta.atr(14)
flowLong = not needFlow or (delta.available and delta.value > 0)
flowShort = not needFlow or (delta.available and delta.value < 0)
if close > upper and flowLong and strategy.position_size <= 0 {
strategy.entry("L", strategy.long, comment = "пробой вверх")
}
if close < lower and flowShort and strategy.position_size >= 0 {
strategy.entry("S", strategy.short, comment = "пробой вниз")
}
stopTicks = math.round(atr * stopAtr / sym.tick_size)
strategy.exit("L-x", from_entry = "L", loss = stopTicks, profit = stopTicks * 2)
strategy.exit("S-x", from_entry = "S", loss = stopTicks, profit = stopTicks * 2)
plot(upper, "Верх канала", color = color.teal)
plot(lower, "Низ канала", color = color.red)En un exchange sin delta (por ejemplo, Binance Alpha) con la opción “Confirmar por delta” activada la estrategia no realizará ninguna operación: delta.available allí es falso. Esto es la regla na en acción, no un error.
Limitaciones
- Solo simulación: no hay órdenes reales.
- Las órdenes límite se ejecutan como si fueras el primero en la cola. Para estrategias maker esto es la principal causa de resultados inflados.
- Tus operaciones no mueven el precio; no hay ejecuciones parciales: una orden se ejecuta entera o no se ejecuta.
- El recorrido del precio dentro de la vela se asume por un modelo, no se extrae de un timeframe menor.
- La liquidación está simplificada: no se modelan el motor de liquidaciones del exchange, ADL ni el fondo de seguros.
- La comisión es la tarifa por defecto, no la de tu cuenta.
- Falta de datos no es falta de movimiento: una vela sin clústeres igualmente tuvo movimiento.
- El resultado depende de cuánto historial esté cargado en el gráfico.
Dónde seguir
https://docs.lootx.trade/es/loot/strategies