Instituto Quant · Ejemplo educativo
Ejemplo 1 — Setup Bajista XAUUSD 4h (Pine Script v5)
Copia el código y pégalo en el editor Pine de TradingView. Es un indicador de vigilancia, no una estrategia ejecutable automática.
⚠️ Aviso importante
- Esto NO es asesoría financiera ni de inversión. Es material educativo para aprender a construir indicadores en Pine Script.
- Operar instrumentos apalancados (oro, forex, futuros, cripto) puede causar la pérdida total o superior de tu capital. Solo arriesga lo que puedes permitirte perder.
- Los niveles, parámetros y confluencias mostrados son un ejemplo puntual con fecha de vigencia. No los uses fuera de su contexto temporal sin recalibrar.
- El rendimiento pasado no garantiza resultados futuros. Tú eres el único responsable de tus decisiones de trading.
Código Pine Script
//@version=5
indicator("Setup Bajista XAUUSD 4h - Profeta v5 SHOT", overlay=true, max_labels_count=20)
// ============================================================
// v5 - VIGILANTE DE UNA SOLA BALA (blindado)
// ============================================================
// Filosofía: vigila UN setup puntual identificado por Profeta.
// - Reloj de vigencia arranca solo en tiempo real
// - No re-dispara al recargar el gráfico
// - Guards contra divisiones por cero y volumen ausente
// - Reset manual disponible
// ============================================================
// ---------- NIVELES PROFETA ----------
grpSetup = "Setup (niveles Profeta)"
entryLow = input.float(4700.0, "Entrada baja", group=grpSetup)
entryHigh = input.float(4720.0, "Entrada alta", group=grpSetup)
slLevel = input.float(4747.0, "Stop Loss", group=grpSetup)
tp1Level = input.float(4666.68, "TP1", group=grpSetup)
tp2Level = input.float(4314.89, "TP2", group=grpSetup)
tp3Level = input.float(4200.0, "TP3 runner", group=grpSetup)
zoneTol = input.float(3.0, "Tolerancia zona (USD)", group=grpSetup)
grpFilters = "Confluencias"
useBB = input.bool(true, "1) Rechazo banda sup Bollinger", group=grpFilters)
useRSI = input.bool(true, "2) RSI girando a la baja <60", group=grpFilters)
useMACD = input.bool(true, "3) Histograma bajista MACD", group=grpFilters)
useDiv = input.bool(true, "4) Divergencia bajista oculta", group=grpFilters)
useCandle = input.bool(true, "5) Vela 4h bajista cuerpo > avg", group=grpFilters)
minConfluences = input.int(3, "Mínimo confluencias para disparar", minval=1, maxval=5, group=grpFilters)
grpVigencia = "Vigencia"
maxBarsToFire = input.int(40, "Velas máx esperando disparo (40 = ~7 días en 4h)", minval=5, group=grpVigencia)
resetSetup = input.bool(false, "🔄 Resetear setup (toggle para re-armar)", group=grpVigencia)
// ---------- INDICADORES TÉCNICOS ----------
bbBasis = ta.sma(close, 20)
bbDev = 2.0 * ta.stdev(close, 20)
bbUpper = bbBasis + bbDev
bbLower = bbBasis - bbDev
rsiVal = ta.rsi(close, 14)
rsiPrev = rsiVal[1]
[macdLine, signalLine, histLine] = ta.macd(close, 12, 26, 9)
// Guard contra volumen ausente (algunos brokers no reportan volume en XAUUSD)
hasVolume = ta.cum(volume) > 0
volAvg = ta.sma(volume, 20)
volRel = (hasVolume and volAvg > 0) ? volume / volAvg : 1.0
// Cuerpo promedio de las últimas 14 velas (más estable que bodyRange[1])
avgBody = ta.sma(math.abs(close - open), 14)
// ---------- CONFLUENCIAS (con guards) ----------
upperWick = high - math.max(open, close)
bodyNow = math.abs(close - open)
// 1) Rechazo Bollinger superior con mecha clara
bbRejection = high >= bbUpper and close < bbUpper and upperWick > bodyNow * 1.2
// 2) RSI girando bajista desde zona alta-neutral
rsiTurningDown = rsiPrev > rsiVal and rsiVal < 60 and rsiVal > 30
// 3) MACD bajista (histograma decreciendo)
macdBearish = macdLine < signalLine and histLine < nz(histLine[1], histLine)
// 4) Divergencia bajista oculta (reescrita más limpia)
// Precio hace HH en últimas 10 velas pero RSI no acompaña
highestHigh10 = ta.highest(high, 10)
highestHighIdx = ta.barssince(high == highestHigh10)
rsiAtPrevHigh = ta.valuewhen(high == ta.highest(high, 20) and bar_index < bar_index - 5, rsiVal, 0)
hiddenBearDiv = high >= highestHigh10 * 0.998 and not na(rsiAtPrevHigh) and rsiVal < rsiAtPrevHigh
// 5) Vela bajista con cuerpo significativo (vs promedio, no vs vela previa)
bearCandle = close < open and bodyNow > avgBody * 0.7
// Zona de entrada
inEntryZone = high >= (entryLow - zoneTol) and low <= (entryHigh + zoneTol)
confluences = (useBB and bbRejection ? 1 : 0) + (useRSI and rsiTurningDown ? 1 : 0) + (useMACD and macdBearish ? 1 : 0) + (useDiv and hiddenBearDiv ? 1 : 0) + (useCandle and bearCandle ? 1 : 0)
totalActive = (useBB?1:0)+(useRSI?1:0)+(useMACD?1:0)+(useDiv?1:0)+(useCandle?1:0)
// Trigger crudo (sin filtrar por tiempo real todavía)
triggerCondition = inEntryZone and confluences >= minConfluences and barstate.isconfirmed
// ---------- MÁQUINA DE ESTADOS BLINDADA ----------
// Estados: 0 = esperando | 1 = posición abierta | 2 = cerrado
var int state = 0
var int barsWaiting = 0
var float entryPrice = na
var string exitReason = ""
var bool clockStarted = false
var int firedAtBar = na
// Reset manual via input
if resetSetup
state := 0
barsWaiting := 0
entryPrice := na
exitReason := ""
clockStarted := false
firedAtBar := na
// El reloj solo arranca cuando llegamos a tiempo real (última vela del gráfico)
// Esto evita que el indicador "viva" toda la historia del gráfico
if barstate.islast and not clockStarted and state == 0
clockStarted := true
barsWaiting := 0
// Guardar estado previo ANTES de mutar (para detectar transiciones limpiamente)
prevState = state
// Lógica de estado: esperando disparo
if state == 0 and clockStarted
if barstate.isconfirmed
barsWaiting := barsWaiting + 1
if triggerCondition
state := 1
entryPrice := close
firedAtBar := bar_index
else if barsWaiting >= maxBarsToFire
state := 2
exitReason := "EXPIRADO sin activar"
// Lógica de estado: posición abierta (vigila SL/TP1)
// Nota: si una vela toca SL y TP1 a la vez (gap/mecha larga), SL tiene prioridad (conservador)
if state == 1
if high >= slLevel
state := 2
exitReason := "SL alcanzado"
else if low <= tp1Level
state := 2
exitReason := "TP1 alcanzado"
// Eventos de transición (solo true en la vela exacta donde ocurre el cambio)
justFired = state == 1 and prevState == 0
justClosed = state == 2 and prevState != 2
// ---------- DIBUJO ----------
plot(entryLow, "Entrada baja", color=color.new(color.orange, 0), linewidth=1)
plot(entryHigh, "Entrada alta", color=color.new(color.orange, 30), linewidth=1)
plot(slLevel, "SL", color=color.new(color.red, 0), linewidth=2)
plot(tp1Level, "TP1", color=color.new(color.green, 0), linewidth=1)
plot(tp2Level, "TP2", color=color.new(color.green, 40), linewidth=1)
plot(tp3Level, "TP3 runner", color=color.new(color.green, 70), linewidth=1, style=plot.style_circles)
// Fondo rojo tenue mientras posición abierta
bgcolor(state == 1 ? color.new(color.red, 92) : na, title="Posición activa")
// Marcadores de eventos
plotshape(justFired, title="DISPARO", style=shape.triangledown, location=location.abovebar, color=color.red, size=size.large, text="SHORT\nENTRY")
plotshape(justClosed and exitReason == "SL alcanzado", title="SL", style=shape.xcross, location=location.abovebar, color=color.red, size=size.normal, text="SL")
plotshape(justClosed and exitReason == "TP1 alcanzado", title="TP1", style=shape.triangleup, location=location.belowbar, color=color.green, size=size.normal, text="TP1")
plotshape(justClosed and exitReason == "EXPIRADO sin activar", title="EXP", style=shape.circle, location=location.abovebar, color=color.gray, size=size.tiny, text="exp")
// ---------- PANEL ----------
var table info = table.new(position.top_right, 2, 8, border_width=1)
if barstate.islast
estadoEmoji = state == 0 ? "🎯" : state == 1 ? "🔫" : "✓"
estadoText = state == 0 ? (clockStarted ? "Esperando disparo" : "Iniciando...") : state == 1 ? "Posición ABIERTA" : "Cerrado: " + exitReason
table.cell(info, 0, 0, "XAUUSD 4h - Profeta v5", text_color=color.white, bgcolor=color.new(color.red, 70))
table.cell(info, 1, 0, "Una sola bala", text_color=color.white, bgcolor=color.new(color.red, 70))
table.cell(info, 0, 1, "Estado")
table.cell(info, 1, 1, estadoEmoji + " " + estadoText)
table.cell(info, 0, 2, "Confluencias")
confText = state == 2 ? "—" : str.tostring(confluences) + " / " + str.tostring(totalActive) + " (min " + str.tostring(minConfluences) + ")"
table.cell(info, 1, 2, confText)
table.cell(info, 0, 3, "En zona entrada")
table.cell(info, 1, 3, state == 2 ? "—" : (inEntryZone ? "SÍ" : "no"))
table.cell(info, 0, 4, "RSI / MACD hist")
rsiMacdText = state == 2 ? "—" : str.tostring(rsiVal, "#.##") + " / " + str.tostring(histLine, "#.##")
table.cell(info, 1, 4, rsiMacdText)
table.cell(info, 0, 5, "Velas esperando")
velasText = state == 0 and clockStarted ? str.tostring(barsWaiting) + " / " + str.tostring(maxBarsToFire) : state == 1 ? "— (en posición)" : "—"
table.cell(info, 1, 5, velasText)
table.cell(info, 0, 6, "Entry price")
entryText = na(entryPrice) ? "—" : str.tostring(entryPrice, "#.##")
table.cell(info, 1, 6, entryText)
table.cell(info, 0, 7, "R:R TP1 / TP2 / TP3")
table.cell(info, 1, 7, "1:1.17 / 1:10.68 / 1:14.86")
// ---------- ALERTAS ----------
alertcondition(justFired, title="🔫 DISPARO setup bajista XAUUSD",
message='{"symbol":"XAUUSD","tf":"4h","action":"SHORT_NOW","entry_zone":"4700-4720","sl":4747,"tp1":4666.68,"tp2":4314.89,"tp3":4200,"rr_tp2":"1:10.68","source":"Profeta v5"}')
alertcondition(justClosed and exitReason == "SL alcanzado", title="❌ SL alcanzado XAUUSD",
message='{"symbol":"XAUUSD","action":"SL_HIT","level":4747,"source":"Profeta v5"}')
alertcondition(justClosed and exitReason == "TP1 alcanzado", title="✅ TP1 alcanzado XAUUSD",
message='{"symbol":"XAUUSD","action":"TP1_HIT","level":4666.68,"next_action":"move_SL_to_breakeven","source":"Profeta v5"}')
alertcondition(justClosed and exitReason == "EXPIRADO sin activar", title="⏱ Setup XAUUSD expirado sin activar",
message='{"symbol":"XAUUSD","action":"SETUP_EXPIRED","reason":"no_trigger_in_40_bars","source":"Profeta v5"}')Descargo de responsabilidad: Instituto Quant y su autor no son asesores financieros registrados. El contenido de esta página es estrictamente educativo e informativo. Ningún elemento aquí publicado constituye una recomendación de compra, venta o mantenimiento de instrumento financiero alguno.
Antes de operar consulta con un profesional autorizado en tu jurisdicción y estudia los riesgos del apalancamiento, slippage, comisiones e impuestos aplicables. El uso de este código es bajo tu propia responsabilidad.
© Instituto Quant · Material educativo