
Se trata de una estrategia de trading cuantitativa basada en múltiples señales de cruce de medias móviles. La estrategia utiliza una cruce de medias móviles de precios de apertura y cierre como señal de trading y es compatible con varios tipos de medias móviles, incluyendo SMMA, EMA, DEMA, etc. La estrategia es altamente configurable y puede ser optimizada para diferentes entornos de mercado y necesidades de trading.
El núcleo de la estrategia es identificar el punto de conversión de la tendencia del mercado mediante la supervisión de la intersección de la media móvil de apertura y la media móvil de cierre. Cuando el precio de cierre cruza la media de apertura, se produce una señal de multiplicación; cuando el precio de cierre cruza la media de apertura por debajo de la media de cierre, se produce una señal de ruptura. La estrategia admite el retroceso de varios períodos de tiempo y ofrece una función de stop loss para administrar el riesgo.
La estrategia capta los puntos de conversión de las tendencias del mercado a través de señales cruzadas de múltiples líneas medias móviles, con una mayor configurabilidad y capacidad de gestión de riesgos. Se puede mantener un rendimiento estable en diferentes entornos de mercado a través de una optimización de parámetros y filtración de señales razonables. La clave para el éxito de la estrategia es elegir el tipo de línea mediana y la combinación de parámetros adecuados, así como establecer un mecanismo de control de riesgo eficaz.
/*backtest
start: 2024-08-01 00:00:00
end: 2025-02-18 08:00:00
period: 1d
basePeriod: 1d
exchanges: [{"eid":"Binance","currency":"ETH_USDT"}]
*/
//@version=6
strategy("Open Close Cross Strategy v6",
overlay=true,
pyramiding=0,
default_qty_type=strategy.percent_of_equity,
default_qty_value=10,
calc_on_every_tick=false)
// === INPUTS ===
var bool useRes = input.bool(true, "Use Alternate Resolution?")
var int intRes = input.int(3, "Multiplier for Alternate Resolution")
var string basisType = input.string("SMMA", "MA Type: ", options=["SMA", "EMA", "DEMA", "TEMA", "WMA", "VWMA", "SMMA", "HullMA", "LSMA", "ALMA", "SSMA", "TMA"])
var int basisLen = input.int(8, "MA Period", minval=1)
var int offsetSigma = input.int(6, "Offset for LSMA / Sigma for ALMA", minval=0)
var float offsetALMA = input.float(0.85, "Offset for ALMA", minval=0, step=0.01)
var bool scolor = input.bool(false, "Show coloured Bars to indicate Trend?")
var int delayOffset = input.int(0, "Delay Open/Close MA (Forces Non-Repainting)", minval=0, step=1)
var string tradeType = input.string("BOTH", "What trades should be taken : ", options=["LONG", "SHORT", "BOTH", "NONE"])
var float slPoints = input.float(0, "Initial Stop Loss Points (zero to disable)", minval=0)
var float tpPoints = input.float(0, "Initial Target Profit Points (zero for disable)", minval=0)
var int ebar = input.int(10000, "Number of Bars for Back Testing", minval=0)
var bool dummy = input.bool(false, "- SET to ZERO for Daily or Longer Timeframes")
// Определение таймфрейма для alternate resolution
getAlternateResolution() =>
timeframe.ismonthly ? str.tostring(timeframe.multiplier * intRes) + "M" :
timeframe.isweekly ? str.tostring(timeframe.multiplier * intRes) + "W" :
timeframe.isdaily ? str.tostring(timeframe.multiplier * intRes) + "D" :
timeframe.isintraday ? str.tostring(timeframe.multiplier * intRes) : "60"
stratRes = getAlternateResolution()
// === MA Functions ===
variant(type, src, len, offSig, offALMA) =>
float result = switch type
"EMA" => ta.ema(src, len)
"DEMA" => 2 * ta.ema(src, len) - ta.ema(ta.ema(src, len), len)
"TEMA" => 3 * (ta.ema(src, len) - ta.ema(ta.ema(src, len), len)) + ta.ema(ta.ema(ta.ema(src, len), len), len)
"WMA" => ta.wma(src, len)
"VWMA" => ta.vwma(src, len)
"SMMA" => ta.sma(src, len) // Упрощенная версия SMMA
"HullMA" => ta.wma(2 * ta.wma(src, len / 2) - ta.wma(src, len), math.round(math.sqrt(len)))
"LSMA" => ta.linreg(src, len, offSig)
"ALMA" => ta.alma(src, len, offALMA, offSig)
"TMA" => ta.sma(ta.sma(src, len), len)
"SSMA" =>
a1 = math.exp(-1.414 * math.pi / len)
b1 = 2 * a1 * math.cos(1.414 * math.pi / len)
c2 = b1
c3 = -a1 * a1
c1 = 1 - c2 - c3
c1 * (src + nz(src[1])) / 2 + c2 * nz(ta.sma(src, len)[1]) + c3 * nz(ta.sma(src, len)[2])
=> ta.sma(src, len)
// === Series Setup ===
closeSeries = variant(basisType, close[delayOffset], basisLen, offsetSigma, offsetALMA)
openSeries = variant(basisType, open[delayOffset], basisLen, offsetSigma, offsetALMA)
// Get Alternate resolution Series
closeSeriesAlt = useRes ? request.security(syminfo.tickerid, stratRes, closeSeries, barmerge.gaps_off, barmerge.lookahead_on) : closeSeries
openSeriesAlt = useRes ? request.security(syminfo.tickerid, stratRes, openSeries, barmerge.gaps_off, barmerge.lookahead_on) : openSeries
// === Plotting ===
color trendColor = closeSeriesAlt > openSeriesAlt ? color.green : color.red
color barColor = closeSeries > openSeriesAlt ? color.new(color.lime, 0) : color.new(color.red, 0)
// Перемещаем barcolor в глобальную область видимости
barcolor(scolor ? barColor : na)
var closePlot = plot(closeSeriesAlt, "Close Series", trendColor, 2, plot.style_line)
var openPlot = plot(openSeriesAlt, "Open Series", trendColor, 2, plot.style_line)
fill(closePlot, openPlot, color=trendColor)
// === Trade Conditions ===
xlong = ta.crossover(closeSeriesAlt, openSeriesAlt)
xshort = ta.crossunder(closeSeriesAlt, openSeriesAlt)
longCond = xlong
shortCond = xshort
// === Strategy Logic ===
float tp = tpPoints > 0 ? tpPoints : na
float sl = slPoints > 0 ? slPoints : na
var int lastPositionType = 0 // 1 для long, -1 для short, 0 для нет позиции
if ebar == 0 or (timenow - time) / (timeframe.multiplier * 60000) <= ebar and tradeType != "NONE"
// Закрытие позиций
if lastPositionType == 1 and shortCond
strategy.close("long")
lastPositionType := 0
label.new(bar_index, high, "Exit Long", color=color.red, style=label.style_label_down, textcolor=color.white)
if lastPositionType == -1 and longCond
strategy.close("short")
lastPositionType := 0
label.new(bar_index, low, "Exit Short", color=color.green, style=label.style_label_up, textcolor=color.white)
// Открытие новых позиций
if longCond and tradeType != "SHORT" and lastPositionType == 0
strategy.entry("long", strategy.long)
lastPositionType := 1
label.new(bar_index, low, "Long", color=color.green, style=label.style_label_up, textcolor=color.white)
if shortCond and tradeType != "LONG" and lastPositionType == 0
strategy.entry("short", strategy.short)
lastPositionType := -1
label.new(bar_index, high, "Short", color=color.red, style=label.style_label_down, textcolor=color.white)
// Take Profit и Stop Loss
if lastPositionType != 0
strategy.exit("TP/SL", profit=tp, loss=sl)