Esta estrategia utiliza dos promedios móviles con diferentes configuraciones de parámetros para las operaciones de cruce para determinar la dirección de la tendencia y las posiciones abiertas / cerradas. La estrategia permite elegir entre 9 tipos diferentes de promedios móviles, incluyendo promedio móvil simple (SMA), promedio móvil exponencial (EMA), promedio móvil ponderado (WMA), promedio móvil Arnaud Legoux (ALMA), promedio móvil ponderado por volumen (VWMA), etc. La estrategia también establece niveles de stop loss y take profit.
La lógica central de esta estrategia es comparar los valores de dos líneas de promedio móvil y determinar la dirección de tendencia del mercado en función de su cruce. Específicamente, establecemos una línea rápida y una línea lenta utilizando dos promedios móviles. Cuando la línea rápida cruza por encima de la línea lenta, creemos que el mercado está en una tendencia al alza y va largo. Cuando la línea rápida cruza por debajo de la línea lenta, creemos que el mercado está en una tendencia a la baja y va corto.
Después de entrar en una posición, si el precio toca la línea de stop loss, salimos de la posición para cortar las pérdidas. Si el precio toca la línea de take profit, salimos de la posición para bloquear las ganancias como se esperaba. Esto nos permite bloquear las ganancias y evitar que las pérdidas se expandan aún más.
A partir de la lógica del código, la estrategia se puede dividir en cuatro partes:
Calcular las medias móviles Basándose en la selección del usuario del tipo de media móvil, calcular las medias móviles de línea rápida y lenta.
Generar señales de trading. Generar señales largas y cortas basadas en las situaciones de cruce de la línea rápida y la línea lenta.
Establezca los niveles de stop loss y take profit. Basándose en el precio de entrada y los porcentajes de stop loss/take profit establecidos, calcule los niveles de stop loss y take profit en tiempo real.
Entrada y salida. Entrada basada en las señales largo/corto, salida basada en las señales stop loss/take profit.
La mayor ventaja de esta estrategia es que permite elegir libremente entre muchos tipos de promedios móviles. Diferentes tipos de promedios móviles tienen diferentes sensibilidades a los precios. Los usuarios pueden elegir el promedio móvil adecuado basado en sus propias necesidades. Además, la longitud de los promedios móviles se puede personalizar para optimizar la dimensión de tiempo.
Otra ventaja es que se establecen mecanismos de stop loss y take profit, lo que puede prevenir efectivamente nuevas pérdidas y bloquear las ganancias.
El principal riesgo de esta estrategia es que los promedios móviles tienen retraso. Cuando los precios fluctúan repentinamente violentamente, los promedios móviles no pueden responder a tiempo, lo que puede llevar a perder el mejor momento de entrada o salida. Esto puede conducir a grandes pérdidas.
Otro riesgo es el establecimiento de niveles de stop loss y take profit. Si el rango es demasiado pequeño, puede ser vulnerable a los scalpers. Si es demasiado grande, es fácil no bloquear las ganancias a tiempo. Por lo tanto, los parámetros de stop loss / take profit deben optimizarse de acuerdo con las condiciones del mercado durante la negociación en vivo.
En general, esta estrategia se basa principalmente en promedios móviles para determinar la dirección de la tendencia. Por lo tanto, su efectividad puede verse comprometida cuando los eventos repentinos causan grandes oscilaciones de precios. Además, los parámetros también pueden tener un gran impacto en los rendimientos de la estrategia.
Esta estrategia puede optimizarse en los siguientes aspectos:
Optimizar el tipo de media móvil. Seleccionar medias móviles más adecuadas basadas en diferentes entornos de mercado y productos comerciales.
Optimizar los parámetros de la media móvil y ajustar la longitud de la media móvil para adaptarla mejor a las características del mercado.
Añadir otros indicadores para filtrar. MACD, RSI y otros indicadores se pueden añadir para evitar el comercio frecuente cuando no hay una tendencia clara.
Optimizar las relaciones stop loss/take profit. Calcular los parámetros óptimos de stop loss/take profit basados en datos históricos.
Agregue modelos de aprendizaje automático. Utilice LSTM, algoritmos de bosque aleatorios para predecir los movimientos de precios y ayudar en la generación de señales comerciales.
Adopte algoritmos de stop loss para permitir que la línea de stop loss se mueva gradualmente junto con los movimientos de precios para reducir la probabilidad de ser golpeada.
En general, esta estrategia es relativamente simple y directa. Determina la dirección de la tendencia a través del cruce y pertenece a una estrategia típica de tendencia siguiente. Las ventajas son fáciles de entender y altamente flexibles con tipos y parámetros de promedios móviles personalizables. Las desventajas son reacciones más lentas a eventos repentinos y cierto grado de retraso. En general, esta estrategia es adecuada para los inversores que buscan rendimientos constantes a largo plazo.
/*backtest start: 2022-12-26 00:00:00 end: 2024-01-01 00:00:00 period: 1d basePeriod: 1h exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}] */ //@version=3 strategy("Kozlod - Yet Another Moving Average Cross Strategy", shorttitle="kozlod_yamacs", overlay = true) // // author: Kozlod // date: 2018-03-06 // //////////// // INPUTS // //////////// ma_type = input(title = "MA Type", defval = "SMA", options = ['SMA', 'EMA', 'WMA', 'ALMA', 'VWMA', 'HMA', 'LSMA', 'SMMA', 'DEMA']) short_ma_len = input(title = "Short MA Length", defval = 5, minval = 1) short_ma_src = input(title = "Short MA Source", defval = close) long_ma_len = input(title = "Long MA Length", defval = 15, minval = 2) long_ma_src = input(title = "Long MA Source", defval = close) alma_offset = input(title = "ALMA Offset", type = float, defval = 0.85, step = 0.01, minval = 0, maxval = 1) alma_sigma = input(title = "ALMA Sigma", type = float, defval = 6, step = 0.01) lsma_offset = input(title = "LSMA Offset", defval = 0, step = 1) sl_lev_perc = input(title = "SL Level % (0 - Off)", type = float, defval = 0, minval = 0, step = 0.01) pt_lev_perc = input(title = "PT Level % (0 - Off)", type = float, defval = 0, minval = 0, step = 0.01) // Set initial values to 0 short_ma = 0.0 long_ma = 0.0 // Simple Moving Average (SMA) if ma_type == 'SMA' short_ma := sma(short_ma_src, short_ma_len) long_ma := sma(long_ma_src, long_ma_len) // Exponential Moving Average (EMA) if ma_type == 'EMA' short_ma := ema(short_ma_src, short_ma_len) long_ma := ema(long_ma_src, long_ma_len) // Weighted Moving Average (WMA) if ma_type == 'WMA' short_ma := wma(short_ma_src, short_ma_len) long_ma := wma(long_ma_src, long_ma_len) // Arnaud Legoux Moving Average (ALMA) if ma_type == 'ALMA' short_ma := alma(short_ma_src, short_ma_len, alma_offset, alma_sigma) long_ma := alma(long_ma_src, long_ma_len, alma_offset, alma_sigma) // Hull Moving Average (HMA) if ma_type == 'HMA' short_ma := wma(2*wma(short_ma_src, short_ma_len/2)-wma(short_ma_src, short_ma_len), round(sqrt(short_ma_len))) long_ma := wma(2*wma(long_ma_src, long_ma_len /2)-wma(long_ma_src, long_ma_len), round(sqrt(long_ma_len))) // Volume-weighted Moving Average (VWMA) if ma_type == 'VWMA' short_ma := vwma(short_ma_src, short_ma_len) long_ma := vwma(long_ma_src, long_ma_len) // Least Square Moving Average (LSMA) if ma_type == 'LSMA' short_ma := linreg(short_ma_src, short_ma_len, lsma_offset) long_ma := linreg(long_ma_src, long_ma_len, lsma_offset) // Smoothed Moving Average (SMMA) if ma_type == 'SMMA' short_ma := na(short_ma[1]) ? sma(short_ma_src, short_ma_len) : (short_ma[1] * (short_ma_len - 1) + short_ma_src) / short_ma_len long_ma := na(long_ma[1]) ? sma(long_ma_src, long_ma_len) : (long_ma[1] * (long_ma_len - 1) + long_ma_src) / long_ma_len // Double Exponential Moving Average (DEMA) if ma_type == 'DEMA' e1_short = ema(short_ma_src, short_ma_len) e1_long = ema(long_ma_src, long_ma_len) short_ma := 2 * e1_short - ema(e1_short, short_ma_len) long_ma := 2 * e1_long - ema(e1_long, long_ma_len) ///////////// // SIGNALS // ///////////// long_signal = crossover( short_ma, long_ma) short_signal = crossunder(short_ma, long_ma) // Calculate PT/SL levels // Initial values last_signal = 0 prev_tr_price = 0.0 pt_level = 0.0 sl_level = 0.0 // Calculate previous trade price prev_tr_price := long_signal[1] or short_signal[1] ? open : nz(last_signal[1]) != 0 ? prev_tr_price[1] : na // Calculate SL/PT levels pt_level := nz(last_signal[1]) == 1 ? prev_tr_price * (1 + pt_lev_perc / 100) : nz(last_signal[1]) == -1 ? prev_tr_price * (1 - pt_lev_perc / 100) : na sl_level := nz(last_signal[1]) == 1 ? prev_tr_price * (1 - sl_lev_perc / 100) : nz(last_signal[1]) == -1 ? prev_tr_price * (1 + sl_lev_perc / 100) : na // Calculate if price hit sl/pt long_hit_pt = pt_lev_perc > 0 and nz(last_signal[1]) == 1 and close >= pt_level long_hit_sl = sl_lev_perc > 0 and nz(last_signal[1]) == 1 and close <= sl_level short_hit_pt = pt_lev_perc > 0 and nz(last_signal[1]) == -1 and close <= pt_level short_hit_sl = sl_lev_perc > 0 and nz(last_signal[1]) == -1 and close >= sl_level // What is last active trade? last_signal := long_signal ? 1 : short_signal ? -1 : long_hit_pt or long_hit_sl or short_hit_pt or short_hit_sl ? 0 : nz(last_signal[1]) ////////////// // PLOTTING // ////////////// // Plot MAs plot(short_ma, color = red, linewidth = 2) plot(long_ma, color = green, linewidth = 2) // Plot Levels plotshape(prev_tr_price, style = shape.cross, color = gray, location = location.absolute, size = size.small) plotshape(sl_lev_perc > 0 ? sl_level : na, style = shape.cross, color = red, location = location.absolute, size = size.small) plotshape(pt_lev_perc > 0 ? pt_level : na, style = shape.cross, color = green, location = location.absolute, size = size.small) ////////////// // STRATEGY // ////////////// strategy.entry("long", true, when = long_signal) strategy.entry("short", false, when = short_signal) strategy.close("long", when = long_hit_pt or long_hit_sl) strategy.close("short", when = short_hit_pt or short_hit_sl)