La idea principal de esta estrategia es utilizar la banda de ruptura para identificar la dirección de la tendencia y combinar el stop loss fijo para la gestión de riesgos. La estrategia primero calcula los precios más altos y más bajos durante un cierto período para formar una banda de ruptura. Cuando el precio rompe la banda de ruptura, se genera una señal de negociación. Además, la estrategia permite a los operadores establecer un monto de stop loss fijo. Cada vez que se realiza una operación, el sistema calculará el tamaño de la posición en función del monto de stop loss fijo, de modo que cada pérdida se fija.
La estrategia se compone de cuatro partes principales: gestión de posiciones, identificación de la banda de ruptura, ajuste de pérdidas y dimensionamiento de posiciones.
En primer lugar, la estrategia comprueba si hay alguna posición abierta.
En segundo lugar, la estrategia calcula los precios más altos y más bajos durante un período para formar una banda de ruptura. Cuando el precio rompe la banda, se genera una señal comercial. Específicamente, si el precio se rompe por encima de la banda superior, se genera una señal larga. Si el precio se rompe por debajo de la banda inferior, se genera una señal corta.
Además, cuando se genera una señal larga, la estrategia establece el punto medio de la banda de ruptura como la stop loss. Lo mismo ocurre con las señales cortas.
Finalmente, la estrategia permite establecer un monto de stop loss fijo. Cuando se genera una señal, la estrategia calcula el número de pips desde el stop loss hasta el precio actual, y combina factores como el tamaño del tick y el tipo de cambio, para determinar el cambio de precio entre el stop loss y el precio actual en términos monetarios.
Los principios principales de la estrategia son identificar la dirección de la tendencia con bandas de ruptura y controlar el riesgo con stop loss fijos.
Esta estrategia de stop loss fija de banda de ruptura tiene las siguientes ventajas:
Concepto avanzado de stop loss. La estrategia utiliza una cantidad fija de stop loss en lugar de una distancia fija de stop loss. Esto evita el problema de no poder fijar el riesgo en productos con diferentes valores de tick. Desde la perspectiva de la gestión de riesgos, la stop loss monetaria fija es más avanzada.
La estrategia puede calcular inteligentemente el tamaño de la posición en función del importe fijo de stop loss, de modo que la pérdida por operación se controle, gestionando así razonablemente la exposición al riesgo.
Identificación de ruptura simple y efectiva. Identificar ruptura con bandas es simple y directo, y puede identificar efectivamente la dirección de la tendencia.
La capacidad de la estrategia para ajustar la parada de pérdida en tiempo real para la parada de pérdida de seguimiento ayuda a bloquear más ganancias.
Amplia aplicabilidad. La estrategia es aplicable a cualquier producto. Siempre que los parámetros estén establecidos correctamente, se puede lograr un control de riesgo de pérdida de pérdida de cantidad fija, lo que hace que la estrategia sea muy versátil.
La estructura del código es clara y modular, por lo que es fácil de entender y optimizar.
A pesar de las ventajas, hay algunos riesgos a tener en cuenta para la estrategia:
La estrategia no juzga la calidad del patrón de ruptura y puede generar algunas señales de baja calidad.
El stop loss fijo puede ser demasiado mecánico. Los precios de mercado a menudo son dispares. El stop loss fijo puede depender demasiado de las reglas y carecer de flexibilidad en el ajuste.
La estrategia no limita la frecuencia del comercio y puede operar con demasiada frecuencia.
El importe fijo de la pérdida de detención es crucial para el control general del riesgo y debe tener en cuenta el tamaño del capital, el apetito por el riesgo, etc.
La dirección de la ruptura puede dar señales erróneas. Las señales de ruptura erróneas pueden ocurrir durante las oscilaciones de precios o retrocesos. Se necesitan más condiciones para optimizar la estrategia.
La estrategia actualmente no tiene la capacidad de obtener ganancias para bloquear activamente las ganancias. Esto puede llevar a ganancias insatisfactorias.
Para hacer frente a estos riesgos, algunas maneras de optimizar la estrategia incluyen:
Añadir indicadores para filtrar la calidad de la señal, por ejemplo, MACD, KD, etc.
Incorporar indicadores de resistencia a la ruptura para evaluar la calidad, por ejemplo, juzgar la resistencia a través de cambios de volumen.
Añadir límites de frecuencia de operaciones abiertas, por ejemplo, una operación por día.
Optimización de la lógica de stop loss fija, por ejemplo, stop loss basado en el porcentaje por encima de un umbral.
Se aplican otros filtros, por ejemplo, volatilidad, mejora de los stop loss, etc.
Incorporar estrategias de obtención de ganancias, por ejemplo, obtener ganancias cerca de la resistencia.
Sobre la base del análisis, la estrategia puede optimizarse en los siguientes aspectos:
Añadir filtros para mejorar la calidad de la señal utilizando múltiples indicadores técnicos y evaluar la calidad de la tendencia.
Optimización de stop loss para mayor flexibilidad. Puede cambiar a stop de seguimiento basado en el porcentaje después de un cierto retroceso. También puede optimizar dinámicamente basado en la volatilidad.
Control de la frecuencia de las operaciones para evitar el exceso de operaciones mediante la adición de filtros sobre los períodos de tiempo o la frecuencia.
Incorporar indicadores de tendencia para mejorar el calendario, por ejemplo, esperar la confirmación de la tendencia.
Optimización de las estrategias de obtención de beneficios para mejorar la rentabilidad a través de objetivos de ganancia, detención de ganancias, detención de volatilidad, etc.
Optimización de los parámetros de riesgo basados en backtests, tales como cantidad de parada fija, período de ruptura, etc.
Refactorización del código para una mejor extensibilidad mediante el desacoplamiento adicional de los módulos de señal, filtro, riesgo y ganancia.
Prueba más productos para oportunidades de arbitraje. Evalúa la ventaja en diferentes combinaciones de productos.
A través de estas dimensiones de optimización, la estrategia de stop loss de ruptura puede volverse más robusta y rentable. También sienta las bases para expandirse a más combinaciones de estrategias.
En general, la estrategia es razonable en el uso de bandas de ruptura para identificar tendencias y paradas de cantidad fija para el control del riesgo. Los conceptos son progresivos para la gestión del riesgo. La lógica de tamaño de posición también es sólida para controlar la pérdida por operación. Pero la estrategia se puede mejorar a través de varias optimizaciones para mejorar la calidad de la señal, la flexibilidad en el stop loss, la rentabilidad, etc. Al incorporar filtros de tendencia, mejorar la toma de ganancias y controlar estrictamente la frecuencia de operaciones, se puede lograr una mejora significativa.
/*backtest start: 2023-10-26 00:00:00 end: 2023-10-28 03:00:00 period: 10m basePeriod: 1m exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}] */ // This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/ //@version=4 //@author=Takazudo strategy("Fixed price SL", overlay=true, default_qty_type=strategy.fixed, initial_capital=0, currency=currency.USD) var COLOR_TRANSPARENT = color.new(#000000, 100) var COLOR_ENTRY_BAND = color.new(#43A6F5, 30) //============================================================================ // config //============================================================================ // Money management _g1 = 'Money management' var config_riskPrice = input(100, minval=1, title="Risk price for each entry", group=_g1) var config_depositCurrency = input(title="Deposit currency", type=input.string, defval="USD", options=["USD"], group=_g1) // Entry strategy _g2 = 'Entry strategy' var config_entryBandBars = input(defval = 100, title = "Entry band bar count", minval=1, group=_g2) // Backtesting range _g3 = 'Backtesting range' fromYear = input(defval = 2018, title = "From Year", minval = 1970, group=_g3) fromMonth = input(defval = 1, title = "From Month", minval = 1, maxval = 12, group=_g3) fromDay = input(defval = 1, title = "From Day", minval = 1, maxval = 31, group=_g3) toYear = input(defval = 2020, title = "To Year", minval = 1970, group=_g3) toMonth = input(defval = 12, title = "To Month", minval = 1, maxval = 12, group=_g3) toDay = input(defval = 31, title = "To Day", minval = 1, maxval = 31, group=_g3) //============================================================================ // exchange caliculations //============================================================================ // mico pip size caliculation // ex1: AUDCAD -> 0.0001 // ex2: USDJPY -> 0.01 f_calcMicroPipSize() => _base = syminfo.basecurrency _quote = syminfo.currency _result = 0.0001 if _quote == 'JPY' _result := _result * 100 if _base == 'BTC' _result := _result * 100 _result // convert price to pips f_convertPriceToPips(_price) => _microPipSize = f_calcMicroPipSize() _price / _microPipSize // caliculate exchange rate between deposit and quote currency f_calcDepositExchangeSymbolId() => _result = '' _deposit = config_depositCurrency _quote = syminfo.currency if (_deposit == 'USD') and (_quote == 'USD') _result := na if (_deposit == 'USD') and (_quote == 'AUD') _result := 'OANDA:AUDUSD' if (_deposit == 'EUR') and (_quote == 'USD') _result := 'OANDA:EURUSD' if (_deposit == 'USD') and (_quote == 'GBP') _result := 'OANDA:GBPUSD' if (_deposit == 'USD') and (_quote == 'NZD') _result := 'OANDA:NZDUSD' if (_deposit == 'USD') and (_quote == 'CAD') _result := 'OANDA:USDCAD' if (_deposit == 'USD') and (_quote == 'CHF') _result := 'OANDA:USDCHF' if (_deposit == 'USD') and (_quote == 'JPY') _result := 'OANDA:USDJPY' _result // Let's say we need CAD to USD exchange // However there's only "OANDA:USDCAD" symbol. // Then we need to invert the exhchange rate. // this function tells us whether we should invert the rate or not f_calcShouldInvert() => _result = false _deposit = config_depositCurrency _quote = syminfo.currency if (_deposit == 'USD') and (_quote == 'CAD') _result := true if (_deposit == 'USD') and (_quote == 'CHF') _result := true if (_deposit == 'USD') and (_quote == 'JPY') _result := true _result // caliculate how much quantity should I buy or sell f_calcQuantitiesForEntry(_depositExchangeRate, _slPips) => _microPipSize = f_calcMicroPipSize() _priceForEachPipAsDeposit = _microPipSize * _depositExchangeRate _losePriceOnSl = _priceForEachPipAsDeposit * _slPips floor(config_riskPrice / _losePriceOnSl) //============================================================================ // Quantity caliculation //============================================================================ depositExchangeSymbolId = f_calcDepositExchangeSymbolId() // caliculate deposit exchange rate rate = security(depositExchangeSymbolId, timeframe.period, hl2) shouldInvert = f_calcShouldInvert() depositExchangeRate = if config_depositCurrency == syminfo.currency // if USDUSD, no exchange of course 1 else // else, USDCAD to CADUSD invert if we need shouldInvert ? (1 / rate) : rate //============================================================================ // Range Edge caliculation //============================================================================ f_calcEntryBand_high() => _highest = max(open[3], close[3]) for i = 4 to (config_entryBandBars - 1) _highest := max(_highest, open[i], close[i]) _highest f_calcEntryBand_low() => _lowest = min(open[3], close[3]) for i = 4 to (config_entryBandBars - 1) _lowest := min(_lowest, open[i], close[i]) _lowest entryBand_high = f_calcEntryBand_high() entryBand_low = f_calcEntryBand_low() entryBand_height = entryBand_high - entryBand_low plot(entryBand_high, color=COLOR_ENTRY_BAND, linewidth=1) plot(entryBand_low, color=COLOR_ENTRY_BAND, linewidth=1) rangeBreakDetected_long = entryBand_high < close rangeBreakDetected_short = entryBand_low > close shouldMakeEntryLong = (strategy.position_size == 0) and rangeBreakDetected_long shouldMakeEntryShort = (strategy.position_size == 0) and rangeBreakDetected_short //============================================================================ // SL & Quantity //============================================================================ var sl_long = hl2 var sl_short = hl2 entryQty = 0 slPips = 0.0 // just show info bubble f_showEntryInfo(_isLong) => _str = 'SL pips: ' + tostring(slPips) + '\n' + 'Qty: ' + tostring(entryQty) _bandHeight = entryBand_high - entryBand_low _y = _isLong ? (entryBand_low + _bandHeight * 1/4) : (entryBand_high - _bandHeight * 1/4) _style = _isLong ? label.style_label_up : label.style_label_down label.new(bar_index, _y, _str, size=size.large, style=_style) if shouldMakeEntryLong sl_long := (entryBand_high + entryBand_low) / 2 slPips := f_convertPriceToPips(close - sl_long) entryQty := f_calcQuantitiesForEntry(depositExchangeRate, slPips) if shouldMakeEntryShort sl_short := (entryBand_high + entryBand_low) / 2 slPips := f_convertPriceToPips(sl_short - close) entryQty := f_calcQuantitiesForEntry(depositExchangeRate, slPips) // trailing SL if strategy.position_size > 0 sl_long := max(sl_long, entryBand_low) if strategy.position_size < 0 sl_short := min(sl_short, entryBand_high) //============================================================================ // backtest duration //============================================================================ // Calculate start/end date and time condition startDate = timestamp(fromYear, fromMonth, fromDay, 00, 00) finishDate = timestamp(toYear, toMonth, toDay, 00, 00) //============================================================================ // make entries //============================================================================ if (true) if shouldMakeEntryLong strategy.entry(id="Long", long=true, stop=close, qty=entryQty) f_showEntryInfo(true) if shouldMakeEntryShort strategy.entry(id="Short", long=false, stop=close, qty=entryQty) f_showEntryInfo(false) strategy.exit('Long-SL/TP', 'Long', stop=sl_long) strategy.exit('Short-SL/TP', 'Short', stop=sl_short) //============================================================================ // plot misc //============================================================================ sl = strategy.position_size > 0 ? sl_long : strategy.position_size < 0 ? sl_short : na plot(sl, color=color.red, style=plot.style_cross, linewidth=2, title="SL") value_bgcolor = rangeBreakDetected_long ? color.green : rangeBreakDetected_short ? color.red : COLOR_TRANSPARENT bgcolor(value_bgcolor, transp=95)