Jump to content

WOLFE WAVE


Recommended Posts

Vor 11 Minuten sagte Ninja_On_The_Roof:

Bedeutet das: „Haben Sie es für NinjaTrader 8?“🤔

Vor 11 Minuten sagte Ninja_On_The_Roof:

Bedeutet das: „Haben Sie es für NinjaTrader 8?“🤔

Vor 11 Minuten sagte Ninja_On_The_Roof:

Bedeutet das: „Haben Sie es für NinjaTrader 8?“🤔

Vor 11 Minuten sagte Ninja_On_The_Roof:

Bedeutet das: „Haben Sie es für NinjaTrader 8?“🤔

Kann jemand das zum NT8 Optimieren?

Nein leider nicht , nur eine NT7 DATEI

 

Link to comment
Share on other sites

Hello, here is the first BETA release from Convert. Could you send me a screenshot of how it looks in ThinkorSwim?
 

#region Using declarations
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using System.Xml.Serialization;
using NinjaTrader.Cbi;
using NinjaTrader.Gui;
using NinjaTrader.Gui.Chart;
using NinjaTrader.Gui.SuperDom;
using NinjaTrader.Gui.Tools;
using NinjaTrader.Data;
using NinjaTrader.NinjaScript;
using NinjaTrader.Core.FloatingPoint;
using NinjaTrader.NinjaScript.DrawingTools;
using NinjaTrader.NinjaScript.Indicators;
#endregion

namespace NinjaTrader.NinjaScript.Indicators
{
    public class WolfeWaveNT8_Opt : Indicator
    {
        [Range(2, 50), NinjaScriptProperty]
        public int WaveLength { get; set; } = 13;

        [NinjaScriptProperty]
        public bool LabelPoints { get; set; } = true;

        private struct Extremum { public int BarIndex; public double Price; }

        private List<Extremum> swingHighs = new List<Extremum>();
        private List<Extremum> swingLows = new List<Extremum>();

        private int lastBullPatternBar = -1;
        private int lastBearPatternBar = -1;

        protected override void OnStateChange()
        {
            if (State == State.SetDefaults)
            {
                Name = "WolfeWaveNT8_Opt";
                IsOverlay = true;
                Description = "Wolfe Wave para NinjaTrader 8 - optimizado";
            }
        }

        protected override void OnBarUpdate()
        {
            if (CurrentBar < WaveLength) return;

            // Detectar máximos y mínimos de swing una sola vez para esta barra
            if (High[WaveLength / 2] == MAX(High, WaveLength)[WaveLength / 2])
            {
                int idx = CurrentBar - WaveLength / 2;
                double price = High[WaveLength / 2];
                // Evita añadir dos veces el mismo punto (por ejemplo en el primer ciclo)
                if (swingHighs.Count == 0 || swingHighs[swingHighs.Count - 1].BarIndex != idx)
                    swingHighs.Add(new Extremum() { BarIndex = idx, Price = price });
                if (swingHighs.Count > 20) swingHighs.RemoveAt(0);
            }
            if (Low[WaveLength / 2] == MIN(Low, WaveLength)[WaveLength / 2])
            {
                int idx = CurrentBar - WaveLength / 2;
                double price = Low[WaveLength / 2];
                if (swingLows.Count == 0 || swingLows[swingLows.Count - 1].BarIndex != idx)
                    swingLows.Add(new Extremum() { BarIndex = idx, Price = price });
                if (swingLows.Count > 20) swingLows.RemoveAt(0);
            }

            // Wolfe Bullish
            if (swingLows.Count >= 5)
            {
                var pts = swingLows.GetRange(swingLows.Count - 5, 5);
                // Revisa si este patrón ya se dibujó (no lo repite)
                if (pts[4].BarIndex != lastBullPatternBar)
                {
                    // Patrón Wolfe básico: puedes ampliar reglas aquí a gusto
                    if (pts[0].Price < pts[2].Price&&pts[2].Price < pts[4].Price)
                    {
                        string tagBase = "BullWolfe_" + pts[0].BarIndex + "_" + pts[4].BarIndex;
                        // Limpia tags antiguos de este patrón si existen
                        for (int i = 0; i < 5; i++)
                            RemoveDrawObject("BullP" + (i + 1) + "_" + tagBase);
                        for (int i = 0; i < 4; i++)
                            RemoveDrawObject("BullWolfe" + i + "_" + tagBase);
                        RemoveDrawObject("BullTarget" + tagBase);
                        RemoveDrawObject("BullArrow" + tagBase);

                        // Dibuja líneas
                        for (int i = 0; i < 4; i++)
                        {
                            Draw.Line(
                                this,
                                "BullWolfe" + i + "_" + tagBase,
                                false,
                                CurrentBar - pts[i].BarIndex, pts[i].Price,
                                CurrentBar - pts[i + 1].BarIndex, pts[i + 1].Price,
                                Brushes.Orange, DashStyleHelper.Solid, 2
                            );
                        }
                        Draw.Line(
                            this,
                            "BullTarget" + tagBase,
                            false,
                            CurrentBar - pts[0].BarIndex, pts[0].Price,
                            CurrentBar - pts[3].BarIndex, pts[3].Price,
                            Brushes.Green, DashStyleHelper.Dash, 3
                        );
                        // Puntos y flecha solo si se solicita
                        if (LabelPoints)
                        {
                            for (int i = 0; i < 5; i++)
                            {
                                int barsAgo = CurrentBar - pts[i].BarIndex;
                                Draw.Text(
                                    this,
                                    "BullP" + (i + 1) + "_" + tagBase,
                                    false,
                                    (i + 1).ToString(),
                                    barsAgo,
                                    pts[i].Price - TickSize * 2,
                                    0,
                                    Brushes.Orange,
                                    new SimpleFont("Arial", 13),
                                    TextAlignment.Center,
                                    Brushes.Transparent,
                                    Brushes.Transparent,
                                    100
                                );
                            }
                            // Flecha entrada en p5
                            Draw.ArrowUp(this, "BullArrow" + tagBase, false, 0, pts[4].Price - TickSize * 2, Brushes.Green);
                        }
                        lastBullPatternBar = pts[4].BarIndex;
                    }
                }
            }

            // Wolfe Bearish
            if (swingHighs.Count >= 5)
            {
                var pts = swingHighs.GetRange(swingHighs.Count - 5, 5);
                if (pts[4].BarIndex != lastBearPatternBar)
                {
                    if (pts[0].Price > pts[2].Price&&pts[2].Price > pts[4].Price)
                    {
                        string tagBase = "BearWolfe_" + pts[0].BarIndex + "_" + pts[4].BarIndex;
                        for (int i = 0; i < 5; i++)
                            RemoveDrawObject("BearP" + (i + 1) + "_" + tagBase);
                        for (int i = 0; i < 4; i++)
                            RemoveDrawObject("BearWolfe" + i + "_" + tagBase);
                        RemoveDrawObject("BearTarget" + tagBase);
                        RemoveDrawObject("BearArrow" + tagBase);

                        for (int i = 0; i < 4; i++)
                        {
                            Draw.Line(
                                this,
                                "BearWolfe" + i + "_" + tagBase,
                                false,
                                CurrentBar - pts[i].BarIndex, pts[i].Price,
                                CurrentBar - pts[i + 1].BarIndex, pts[i + 1].Price,
                                Brushes.Pink, DashStyleHelper.Solid, 2
                            );
                        }
                        Draw.Line(
                            this,
                            "BearTarget" + tagBase,
                            false,
                            CurrentBar - pts[0].BarIndex, pts[0].Price,
                            CurrentBar - pts[3].BarIndex, pts[3].Price,
                            Brushes.Red, DashStyleHelper.Dash, 3
                        );
                        if (LabelPoints)
                        {
                            for (int i = 0; i < 5; i++)
                            {
                                int barsAgo = CurrentBar - pts[i].BarIndex;
                                Draw.Text(
                                    this,
                                    "BearP" + (i + 1) + "_" + tagBase,
                                    false,
                                    (i + 1).ToString(),
                                    barsAgo,
                                    pts[i].Price + TickSize * 2,
                                    0,
                                    Brushes.Magenta,
                                    new SimpleFont("Arial", 13),
                                    TextAlignment.Center,
                                    Brushes.Transparent,
                                    Brushes.Transparent,
                                    100
                                );
                            }
                            Draw.ArrowDown(this, "BearArrow" + tagBase, false, 0, pts[4].Price + TickSize * 2, Brushes.Red);
                        }
                        lastBearPatternBar = pts[4].BarIndex;
                    }
                }
            }
        }
    }
}

 

Edited by tradevelopers
Link to comment
Share on other sites

HERE AN UPDATE 

#region Using declarations
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using System.Xml.Serialization;
using NinjaTrader.Cbi;
using NinjaTrader.Gui;
using NinjaTrader.Gui.Chart;
using NinjaTrader.Gui.SuperDom;
using NinjaTrader.Gui.Tools;
using NinjaTrader.Data;
using NinjaTrader.NinjaScript;
using NinjaTrader.Core.FloatingPoint;
using NinjaTrader.NinjaScript.DrawingTools;
using NinjaTrader.NinjaScript.Indicators;
#endregion


namespace NinjaTrader.NinjaScript.Indicators
{
    public class WolfeWaveVisual : Indicator
    {
        #region Variables

        private List<WolfePoint> peakPoints = new List<WolfePoint>();
        private List<WolfePoint> valleyPoints = new List<WolfePoint>();
        
        private int lastProcessedBar = 0;
        private bool isDebugMode = false;
        private int patternCount = 0;
        
        private class WolfePoint
        {
            public int BarIndex { get; set; }      // Índice de la barra
            public double Price { get; set; }      // Precio del punto
            public DateTime Time { get; set; }     // Tiempo asociado
            public bool IsPeak { get; set; }       // Si es pico (true) o valle (false)
            
            public WolfePoint(int barIndex, double price, DateTime time, bool isPeak)
            {
                BarIndex = barIndex;
                Price = price;
                Time = time;
                IsPeak = isPeak;
            }
        }
        
        private class WolfePattern
        {
            public WolfePoint Point1 { get; set; }
            public WolfePoint Point2 { get; set; }
            public WolfePoint Point3 { get; set; }
            public WolfePoint Point4 { get; set; }
            public WolfePoint Point5 { get; set; }
            public bool IsBullish { get; set; }
            public double TargetPrice { get; set; }
        }

        #endregion

        #region Properties

        [NinjaScriptProperty]
        [Range(1, 10)]
        [Display(Name="Fractal Strength", Description="Number of bars on each side to confirm fractals", Order=1, GroupName="Parameters")]
        public int FractalStrength { get; set; }

        [NinjaScriptProperty]
        [Range(1, 500)]
        [Display(Name="Max Lookback Bars", Description="Maximum number of bars to look back for patterns", Order=2, GroupName="Parameters")]
        public int MaxLookback { get; set; }
        
        [NinjaScriptProperty]
        [Range(0.1, 1.0)]
        [Display(Name="Pattern Tolerance", Description="Tolerance for validating patterns (0.1-1.0)", Order=3, GroupName="Parameters")]
        public double PatternTolerance { get; set; }
        
        [NinjaScriptProperty]
        [Display(Name="Show All ZigZag Points", Description="Show all detected zigzag points", Order=4, GroupName="Visualization")]
        public bool ShowAllPoints { get; set; }
        
        [NinjaScriptProperty]
        [Display(Name="Bullish Pattern Color", Order=5, GroupName="Visualization")]
        public Brush BullishColor { get; set; }
        
        [NinjaScriptProperty]
        [Display(Name="Bearish Pattern Color", Order=6, GroupName="Visualization")]
        public Brush BearishColor { get; set; }
        
        [NinjaScriptProperty]
        [Display(Name="ZigZag Line Color", Order=7, GroupName="Visualization")]
        public Brush ZigZagColor { get; set; }
        
        [NinjaScriptProperty]
        [Display(Name="Triangle Size", Description="Size of triangles marking pattern completion", Order=8, GroupName="Visualization")]
        public int TriangleSize { get; set; }
        
        [NinjaScriptProperty]
        [Display(Name="Show Target Projection", Description="Show target price projection", Order=9, GroupName="Visualization")]
        public bool ShowTargetProjection { get; set; }
        
        [NinjaScriptProperty]
        [Display(Name="Min Points For Pattern", Description="Minimum number of zigzag points needed before checking patterns", Order=10, GroupName="Parameters")]
        public int MinPointsForPattern { get; set; }
        
        [NinjaScriptProperty]
        [Display(Name="Debug Mode", Description="Show additional information for debugging", Order=11, GroupName="Parameters")]
        public bool DebugMode { get; set; }

        #endregion

        protected override void OnStateChange()
        {
            if (State == State.SetDefaults)
            {
                Description = "Wolfe Wave Indicator with Enhanced Visualization";
                Name = "WolfeWaveVisual";
                Calculate = Calculate.OnEachTick;  // Vamos a calcular en cada tick para mayor precisión
                IsOverlay = true;
                DisplayInDataBox = true;
                DrawOnPricePanel = true;
                DrawHorizontalGridLines = true;
                DrawVerticalGridLines = true;
                PaintPriceMarkers = true;
                ScaleJustification = NinjaTrader.Gui.Chart.ScaleJustification.Right;
                
                // Establecer valores predeterminados
                FractalStrength = 2;
                MaxLookback = 200;
                PatternTolerance = 0.5;
                ShowAllPoints = true;
                BullishColor = Brushes.LimeGreen;
                BearishColor = Brushes.Crimson;
                ZigZagColor = Brushes.DodgerBlue;
                TriangleSize = 8;
                ShowTargetProjection = true;
                MinPointsForPattern = 5;
                DebugMode = true;
                
                // Crear plots para asegurar que el indicador aparezca en el gráfico
                AddPlot(new Stroke(ZigZagColor, 2), PlotStyle.Line, "ZigZag");
            }
            else if (State == State.Configure)
            {
                // No necesita configuración adicional
            }
            else if (State == State.DataLoaded)
            {
                // Inicializar variables
                peakPoints.Clear();
                valleyPoints.Clear();
                lastProcessedBar = 0;
                isDebugMode = DebugMode;
                
                if (isDebugMode)
                {
                    ClearOutputWindow();
                    Print("WolfeWaveVisual: Inicializado con Fractal=" + FractalStrength + 
                        ", Lookback=" + MaxLookback + ", Tolerance=" + PatternTolerance);
                }
            }
            else if (State == State.Historical)
            {
                // Limpiar gráfico al empezar
                RemoveDrawObjects();
            }
        }

        protected override void OnBarUpdate()
        {
            // Asegurarse de que tenemos suficientes barras para el análisis
            if (CurrentBar < FractalStrength * 2 + 1)
                return;
                
            // Actualizar plots para asegurar que el indicador se ve
            Values[0][0] = Close[0];
            
            // Solo procesar una vez por barra
            if (lastProcessedBar == CurrentBar)
                return;
                
            lastProcessedBar = CurrentBar;
            
            // Detectar y almacenar picos y valles
            FindZigZagPoints();
            
            // Mostrar ZigZag si está habilitado
            if (ShowAllPoints)
            {
                DrawZigZag();
            }
            
            // Solo buscar patrones si tenemos suficientes puntos
            if (peakPoints.Count >= MinPointsForPattern/2&&valleyPoints.Count >= MinPointsForPattern/2)
            {
                // Detectar patrones Wolfe Wave
                FindWolfeWavePatterns();
            }
        }
        
        #region ZigZag Detection
        
        private void FindZigZagPoints()
        {
            // Primero, verificar si hay un nuevo pico
            if (IsPeak(FractalStrength))
            {
                // Verificar si este pico ya fue agregado
                bool alreadyExists = false;
                foreach (var point in peakPoints)
                {
                    if (point.BarIndex == CurrentBar - FractalStrength)
                    {
                        alreadyExists = true;
                        break;
                    }
                }
                
                if (!alreadyExists)
                {
                    WolfePoint newPeak = new WolfePoint(
                        CurrentBar - FractalStrength,
                        High[FractalStrength],
                        Time[FractalStrength],
                        true
                    );
                    
                    peakPoints.Add(newPeak);
                    
                    if (isDebugMode)
                    {
                        Print("WolfeWaveVisual: Nuevo pico detectado en barra " + newPeak.BarIndex + 
                            " a precio " + newPeak.Price);
                    }
                    
                    // Marca el pico visualmente
                    string tagName = "Peak_" + newPeak.BarIndex;
                    Draw.Diamond(this, tagName, false, FractalStrength, High[FractalStrength], Brushes.Gold);
                    Draw.Text(this, "txt_" + tagName, false, "P", FractalStrength, High[FractalStrength] + 3*TickSize, 
                        0, Brushes.White, new SimpleFont("Arial", 9), TextAlignment.Center, Brushes.DarkGoldenrod, Brushes.DarkGoldenrod, 80);
                }
            }
            
            // Luego, verificar si hay un nuevo valle
            if (IsValley(FractalStrength))
            {
                // Verificar si este valle ya fue agregado
                bool alreadyExists = false;
                foreach (var point in valleyPoints)
                {
                    if (point.BarIndex == CurrentBar - FractalStrength)
                    {
                        alreadyExists = true;
                        break;
                    }
                }
                
                if (!alreadyExists)
                {
                    WolfePoint newValley = new WolfePoint(
                        CurrentBar - FractalStrength,
                        Low[FractalStrength],
                        Time[FractalStrength],
                        false
                    );
                    
                    valleyPoints.Add(newValley);
                    
                    if (isDebugMode)
                    {
                        Print("WolfeWaveVisual: Nuevo valle detectado en barra " + newValley.BarIndex + 
                            " a precio " + newValley.Price);
                    }
                    
                    // Marca el valle visualmente
                    string tagName = "Valley_" + newValley.BarIndex;
                    Draw.Diamond(this, tagName, false, FractalStrength, Low[FractalStrength], Brushes.DarkOrange);
                    Draw.Text(this, "txt_" + tagName, false, "V", FractalStrength, Low[FractalStrength] - 3*TickSize, 
                        0, Brushes.White, new SimpleFont("Arial", 9), TextAlignment.Center, Brushes.DarkOrange, Brushes.DarkOrange, 80);
                }
            }
            
            // Limpia puntos antiguos fuera del lookback
            CleanupOldPoints();
        }
        
        private bool IsPeak(int strength)
        {
            if (CurrentBar < strength * 2)
                return false;
                
            double middleHigh = High[strength];
            
            // Verificar las barras a la izquierda (barras más antiguas)
            for (int i = 1; i <= strength; i++)
            {
                if (High[strength + i] >= middleHigh)
                    return false;
            }
            
            // Verificar las barras a la derecha (barras más recientes)
            for (int i = 1; i <= strength; i++)
            {
                if (High[strength - i] >= middleHigh)
                    return false;
            }
            
            return true;
        }
        
        private bool IsValley(int strength)
        {
            if (CurrentBar < strength * 2)
                return false;
                
            double middleLow = Low[strength];
            
            // Verificar las barras a la izquierda (barras más antiguas)
            for (int i = 1; i <= strength; i++)
            {
                if (Low[strength + i] <= middleLow)
                    return false;
            }
            
            // Verificar las barras a la derecha (barras más recientes)
            for (int i = 1; i <= strength; i++)
            {
                if (Low[strength - i] <= middleLow)
                    return false;
            }
            
            return true;
        }
        
        private void CleanupOldPoints()
        {
            // Mantener solo los puntos dentro del lookback
            int lookbackBar = Math.Max(0, CurrentBar - MaxLookback);
            
            // Limpiar picos antiguos
            peakPoints.RemoveAll(p => p.BarIndex < lookbackBar);
            
            // Limpiar valles antiguos
            valleyPoints.RemoveAll(v => v.BarIndex < lookbackBar);
        }
        
        private void DrawZigZag()
        {
            // Combinar todos los puntos
            List<WolfePoint> allPoints = new List<WolfePoint>();
            allPoints.AddRange(peakPoints);
            allPoints.AddRange(valleyPoints);
            
            // Ordenar por índice de barra (del más antiguo al más reciente)
            allPoints = allPoints.OrderBy(p => p.BarIndex).ToList();
            
            // Dibujar líneas ZigZag entre puntos consecutivos
            for (int i = 0; i < allPoints.Count - 1; i++)
            {
                WolfePoint current = allPoints[i];
                WolfePoint next = allPoints[i + 1];
                
                // Solo conectar si son de tipos diferentes (pico a valle o valle a pico)
                if (current.IsPeak != next.IsPeak)
                {
                    string tagName = "ZigZag_" + current.BarIndex + "_" + next.BarIndex;
                    Draw.Line(this, tagName, false, 
                        CurrentBar - current.BarIndex, current.Price, 
                        CurrentBar - next.BarIndex, next.Price, 
                        ZigZagColor, DashStyleHelper.Solid, 1);
                }
            }
        }
        
        #endregion
        
        #region Wolfe Wave Pattern Detection
        
        private void FindWolfeWavePatterns()
        {
            FindBullishWolfeWaves();
            FindBearishWolfeWaves();
        }
        
        private void FindBullishWolfeWaves()
        {
            // Verificar si tenemos suficientes valles (necesitamos al menos 3) y picos (necesitamos al menos 2)
            if (valleyPoints.Count < 3 || peakPoints.Count < 2)
                return;
                
            // Ordenar puntos de más recientes a más antiguos
            List<WolfePoint> sortedValleys = valleyPoints.OrderByDescending(v => v.BarIndex).ToList();
            List<WolfePoint> sortedPeaks = peakPoints.OrderByDescending(p => p.BarIndex).ToList();
            
            // Si no tenemos al menos un valle reciente para el punto 5, no hay patrón
            if (sortedValleys.Count == 0)
                return;
                
            // Comenzar con el valle más reciente como punto 5
            WolfePoint point5 = sortedValleys[0];
            
            // Buscar un pico antes del punto 5 para ser el punto 4
            WolfePoint point4 = null;
            foreach (var peak in sortedPeaks)
            {
                if (peak.BarIndex < point5.BarIndex&&peak.Price > point5.Price)
                {
                    point4 = peak;
                    break;
                }
            }
            
            if (point4 == null)
                return;
                
            // Buscar un valle antes del punto 4 para ser el punto 3
            WolfePoint point3 = null;
            foreach (var valley in sortedValleys)
            {
                if (valley.BarIndex < point4.BarIndex&&valley.Price < point4.Price)
                {
                    point3 = valley;
                    break;
                }
            }
            
            if (point3 == null)
                return;
                
            // Buscar un pico antes del punto 3 para ser el punto 2
            WolfePoint point2 = null;
            foreach (var peak in sortedPeaks)
            {
                if (peak.BarIndex < point3.BarIndex&&peak.Price > point3.Price)
                {
                    point2 = peak;
                    break;
                }
            }
            
            if (point2 == null)
                return;
                
            // Buscar un valle antes del punto 2 para ser el punto 1
            WolfePoint point1 = null;
            foreach (var valley in sortedValleys)
            {
                if (valley.BarIndex < point2.BarIndex&&valley.Price < point2.Price)
                {
                    point1 = valley;
                    break;
                }
            }
            
            if (point1 == null)
                return;
                
            // Verificar si es un patrón Wolfe Wave Bullish válido
            if (IsBullishWolfeWaveValid(point1, point2, point3, point4, point5))
            {
                // Calcular el objetivo de precio
                double targetPrice = CalculateBullishTarget(point1, point3, point5);
                
                // Dibujar el patrón
                DrawBullishWolfeWave(point1, point2, point3, point4, point5, targetPrice);
                
                if (isDebugMode)
                {
                    Print("WolfeWaveVisual: Patrón ALCISTA encontrado en barra " + CurrentBar);
                }
            }
        }
        
        private void FindBearishWolfeWaves()
        {
            // Verificar si tenemos suficientes picos (necesitamos al menos 3) y valles (necesitamos al menos 2)
            if (peakPoints.Count < 3 || valleyPoints.Count < 2)
                return;
                
            // Ordenar puntos de más recientes a más antiguos
            List<WolfePoint> sortedPeaks = peakPoints.OrderByDescending(p => p.BarIndex).ToList();
            List<WolfePoint> sortedValleys = valleyPoints.OrderByDescending(v => v.BarIndex).ToList();
            
            // Si no tenemos al menos un pico reciente para el punto 5, no hay patrón
            if (sortedPeaks.Count == 0)
                return;
                
            // Comenzar con el pico más reciente como punto 5
            WolfePoint point5 = sortedPeaks[0];
            
            // Buscar un valle antes del punto 5 para ser el punto 4
            WolfePoint point4 = null;
            foreach (var valley in sortedValleys)
            {
                if (valley.BarIndex < point5.BarIndex&&valley.Price < point5.Price)
                {
                    point4 = valley;
                    break;
                }
            }
            
            if (point4 == null)
                return;
                
            // Buscar un pico antes del punto 4 para ser el punto 3
            WolfePoint point3 = null;
            foreach (var peak in sortedPeaks)
            {
                if (peak.BarIndex < point4.BarIndex&&peak.Price > point4.Price)
                {
                    point3 = peak;
                    break;
                }
            }
            
            if (point3 == null)
                return;
                
            // Buscar un valle antes del punto 3 para ser el punto 2
            WolfePoint point2 = null;
            foreach (var valley in sortedValleys)
            {
                if (valley.BarIndex < point3.BarIndex&&valley.Price < point3.Price)
                {
                    point2 = valley;
                    break;
                }
            }
            
            if (point2 == null)
                return;
                
            // Buscar un pico antes del punto 2 para ser el punto 1
            WolfePoint point1 = null;
            foreach (var peak in sortedPeaks)
            {
                if (peak.BarIndex < point2.BarIndex&&peak.Price > point2.Price)
                {
                    point1 = peak;
                    break;
                }
            }
            
            if (point1 == null)
                return;
                
            // Verificar si es un patrón Wolfe Wave Bearish válido
            if (IsBearishWolfeWaveValid(point1, point2, point3, point4, point5))
            {
                // Calcular el objetivo de precio
                double targetPrice = CalculateBearishTarget(point1, point3, point5);
                
                // Dibujar el patrón
                DrawBearishWolfeWave(point1, point2, point3, point4, point5, targetPrice);
                
                if (isDebugMode)
                {
                    Print("WolfeWaveVisual: Patrón BAJISTA encontrado en barra " + CurrentBar);
                }
            }
        }
        
        private bool IsBullishWolfeWaveValid(WolfePoint p1, WolfePoint p2, WolfePoint p3, WolfePoint p4, WolfePoint p5)
        {
            // Verificar la secuencia de tiempo
            if (!(p1.BarIndex < p2.BarIndex&&p2.BarIndex < p3.BarIndex&&p3.BarIndex < p4.BarIndex&&p4.BarIndex < p5.BarIndex))
            {
                return false;
            }
            
            // Verificar que los puntos alternan entre picos y valles
            if (!(p1.IsPeak == false&&p2.IsPeak == true&&p3.IsPeak == false&&p4.IsPeak == true&&p5.IsPeak == false))
            {
                return false;
            }
            
            // Para patrones bullish, el punto 5 debe ser más bajo que el punto 3
            if (p5.Price >= p3.Price)
            {
                if (isDebugMode) Print("WolfeWaveVisual: Patrón BULLISH rechazado - Punto 5 no es más bajo que Punto 3");
                return false;
            }
            
            // El punto 4 debe ser más alto que el punto 2
            if (p4.Price <= p2.Price)
            {
                if (isDebugMode) Print("WolfeWaveVisual: Patrón BULLISH rechazado - Punto 4 no es más alto que Punto 2");
                return false;
            }
            
            // Calcular pendientes
            double slope13 = CalculateSlope(p1, p3);
            double slope24 = CalculateSlope(p2, p4);
            double slope14 = CalculateSlope(p1, p4);
            
            // En un patrón bullish, la pendiente 1-3 debe ser menos positiva (o más negativa) que la pendiente 2-4
            // Permitimos cierta tolerancia
            double tolerance = Math.Abs(slope24 * PatternTolerance);
            if (slope13 >= slope24 + tolerance)
            {
                if (isDebugMode) Print("WolfeWaveVisual: Patrón BULLISH rechazado - Pendiente 1-3 no converge con 2-4");
                return false;
            }
            
            return true;
        }
        
        private bool IsBearishWolfeWaveValid(WolfePoint p1, WolfePoint p2, WolfePoint p3, WolfePoint p4, WolfePoint p5)
        {
            // Verificar la secuencia de tiempo
            if (!(p1.BarIndex < p2.BarIndex&&p2.BarIndex < p3.BarIndex&&p3.BarIndex < p4.BarIndex&&p4.BarIndex < p5.BarIndex))
            {
                return false;
            }
            
            // Verificar que los puntos alternan entre picos y valles
            if (!(p1.IsPeak == true&&p2.IsPeak == false&&p3.IsPeak == true&&p4.IsPeak == false&&p5.IsPeak == true))
            {
                return false;
            }
            
            // Para patrones bearish, el punto 5 debe ser más alto que el punto 3
            if (p5.Price <= p3.Price)
            {
                if (isDebugMode) Print("WolfeWaveVisual: Patrón BEARISH rechazado - Punto 5 no es más alto que Punto 3");
                return false;
            }
            
            // El punto 4 debe ser más bajo que el punto 2
            if (p4.Price >= p2.Price)
            {
                if (isDebugMode) Print("WolfeWaveVisual: Patrón BEARISH rechazado - Punto 4 no es más bajo que Punto 2");
                return false;
            }
            
            // Calcular pendientes
            double slope13 = CalculateSlope(p1, p3);
            double slope24 = CalculateSlope(p2, p4);
            double slope14 = CalculateSlope(p1, p4);
            
            // En un patrón bearish, la pendiente 1-3 debe ser más positiva (o menos negativa) que la pendiente 2-4
            // Permitimos cierta tolerancia
            double tolerance = Math.Abs(slope24 * PatternTolerance);
            if (slope13 <= slope24 - tolerance)
            {
                if (isDebugMode) Print("WolfeWaveVisual: Patrón BEARISH rechazado - Pendiente 1-3 no converge con 2-4");
                return false;
            }
            
            return true;
        }
        
        private double CalculateSlope(WolfePoint start, WolfePoint end)
        {
            if (end.BarIndex == start.BarIndex)
                return 0;
                
            return (end.Price - start.Price) / (end.BarIndex - start.BarIndex);
        }
        
        #endregion
        
        #region Visualization Methods
        
        private void DrawBullishWolfeWave(WolfePoint p1, WolfePoint p2, WolfePoint p3, WolfePoint p4, WolfePoint p5, double targetPrice)
        {
            patternCount++;
            string patternId = "Bull_" + CurrentBar + "_" + patternCount;
            
            // Calcular las coordenadas de barra para el dibujo (distancia desde la barra actual)
            int x1 = CurrentBar - p1.BarIndex;
            int x2 = CurrentBar - p2.BarIndex;
            int x3 = CurrentBar - p3.BarIndex;
            int x4 = CurrentBar - p4.BarIndex;
            int x5 = CurrentBar - p5.BarIndex;
            
            // Dibujar líneas conectando los puntos
            Draw.Line(this, patternId + "_1_2", false, x1, p1.Price, x2, p2.Price, BullishColor, DashStyleHelper.Solid, 2);
            Draw.Line(this, patternId + "_2_3", false, x2, p2.Price, x3, p3.Price, BullishColor, DashStyleHelper.Solid, 2);
            Draw.Line(this, patternId + "_3_4", false, x3, p3.Price, x4, p4.Price, BullishColor, DashStyleHelper.Solid, 2);
            Draw.Line(this, patternId + "_4_5", false, x4, p4.Price, x5, p5.Price, BullishColor, DashStyleHelper.Solid, 2);
            
            // Dibujar líneas de proyección si está habilitado
            if (ShowTargetProjection)
            {
                // Extender la línea 1-3 para proyectar el objetivo de precio
                // Calculamos la barra donde la proyección alcanzaría el objetivo
                double slope13 = CalculateSlope(p1, p3);
                int barsFromPoint1 = p5.BarIndex - p1.BarIndex;
                int projectionBars = barsFromPoint1 + Math.Min(50, barsFromPoint1 / 2);
                
                // Dibujar proyección desde punto 1 hasta el objetivo
                Draw.Line(this, patternId + "_target", false, 
                         x1, p1.Price, 
                         CurrentBar - (p1.BarIndex + projectionBars), targetPrice, 
                         Brushes.Gold, DashStyleHelper.Dash, 2);
                
                // Etiquetar el precio objetivo
                Draw.Text(this, patternId + "_targetlabel", false, 
                         "Target: " + FormatPrice(targetPrice), 
                         CurrentBar - (p1.BarIndex + projectionBars/2), targetPrice, 
                         0, Brushes.White, new SimpleFont("Arial", 10), TextAlignment.Center, 
                         Brushes.DarkGoldenrod, Brushes.DarkGoldenrod, 80);
            }
            
            // Etiquetar los puntos
            Draw.Text(this, patternId + "_p1", false, "1", x1, p1.Price, 0, 
                     Brushes.White, new SimpleFont("Arial", 10), TextAlignment.Center, 
                     Brushes.DarkGreen, Brushes.DarkGreen, 80);
            Draw.Text(this, patternId + "_p2", false, "2", x2, p2.Price, 0, 
                     Brushes.White, new SimpleFont("Arial", 10), TextAlignment.Center, 
                     Brushes.DarkGreen, Brushes.DarkGreen, 80);
            Draw.Text(this, patternId + "_p3", false, "3", x3, p3.Price, 0, 
                     Brushes.White, new SimpleFont("Arial", 10), TextAlignment.Center, 
                     Brushes.DarkGreen, Brushes.DarkGreen, 80);
            Draw.Text(this, patternId + "_p4", false, "4", x4, p4.Price, 0, 
                     Brushes.White, new SimpleFont("Arial", 10), TextAlignment.Center, 
                     Brushes.DarkGreen, Brushes.DarkGreen, 80);
            Draw.Text(this, patternId + "_p5", false, "5", x5, p5.Price, 0, 
                     Brushes.White, new SimpleFont("Arial", 10), TextAlignment.Center, 
                     Brushes.DarkGreen, Brushes.DarkGreen, 80);
            
            // Dibujar un triángulo para marcar el patrón completo
            Draw.TriangleUp(this, patternId + "_marker", false, x5, p5.Price - 2 * TickSize, BullishColor);
            
            Alert("WolfeWave_Bull", Priority.Medium, "Wolfe Wave Bullish Pattern", 
                 NinjaTrader.Core.Globals.InstallDir + @"\sounds\Alert1.wav", 
                 0, Brushes.LimeGreen, Brushes.Black);
        }
        
        private void DrawBearishWolfeWave(WolfePoint p1, WolfePoint p2, WolfePoint p3, WolfePoint p4, WolfePoint p5, double targetPrice)
        {
            patternCount++;
            string patternId = "Bear_" + CurrentBar + "_" + patternCount;
            
            // Calcular las coordenadas de barra para el dibujo (distancia desde la barra actual)
            int x1 = CurrentBar - p1.BarIndex;
            int x2 = CurrentBar - p2.BarIndex;
            int x3 = CurrentBar - p3.BarIndex;
            int x4 = CurrentBar - p4.BarIndex;
            int x5 = CurrentBar - p5.BarIndex;
            
            // Dibujar líneas conectando los puntos
            Draw.Line(this, patternId + "_1_2", false, x1, p1.Price, x2, p2.Price, BearishColor, DashStyleHelper.Solid, 2);
            Draw.Line(this, patternId + "_2_3", false, x2, p2.Price, x3, p3.Price, BearishColor, DashStyleHelper.Solid, 2);
            Draw.Line(this, patternId + "_3_4", false, x3, p3.Price, x4, p4.Price, BearishColor, DashStyleHelper.Solid, 2);
            Draw.Line(this, patternId + "_4_5", false, x4, p4.Price, x5, p5.Price, BearishColor, DashStyleHelper.Solid, 2);
            
            // Dibujar líneas de proyección si está habilitado
            if (ShowTargetProjection)
            {
                // Extender la línea 1-3 para proyectar el objetivo de precio
                // Calculamos la barra donde la proyección alcanzaría el objetivo
                double slope13 = CalculateSlope(p1, p3);
                int barsFromPoint1 = p5.BarIndex - p1.BarIndex;
                int projectionBars = barsFromPoint1 + Math.Min(50, barsFromPoint1 / 2);
                
                // Dibujar proyección desde punto 1 hasta el objetivo
                Draw.Line(this, patternId + "_target", false, 
                         x1, p1.Price, 
                         CurrentBar - (p1.BarIndex + projectionBars), targetPrice, 
                         Brushes.Gold, DashStyleHelper.Dash, 2);
                
                // Etiquetar el precio objetivo
                Draw.Text(this, patternId + "_targetlabel", false, 
                         "Target: " + FormatPrice(targetPrice), 
                         CurrentBar - (p1.BarIndex + projectionBars/2), targetPrice, 
                         0, Brushes.White, new SimpleFont("Arial", 10), TextAlignment.Center, 
                         Brushes.DarkGoldenrod, Brushes.DarkGoldenrod, 80);
            }
            
            // Etiquetar los puntos
            Draw.Text(this, patternId + "_p1", false, "1", x1, p1.Price, 0, 
                     Brushes.White, new SimpleFont("Arial", 10), TextAlignment.Center, 
                     Brushes.DarkRed, Brushes.DarkRed, 80);
            Draw.Text(this, patternId + "_p2", false, "2", x2, p2.Price, 0, 
                     Brushes.White, new SimpleFont("Arial", 10), TextAlignment.Center, 
                     Brushes.DarkRed, Brushes.DarkRed, 80);
            Draw.Text(this, patternId + "_p3", false, "3", x3, p3.Price, 0, 
                     Brushes.White, new SimpleFont("Arial", 10), TextAlignment.Center, 
                     Brushes.DarkRed, Brushes.DarkRed, 80);
            Draw.Text(this, patternId + "_p4", false, "4", x4, p4.Price, 0, 
                     Brushes.White, new SimpleFont("Arial", 10), TextAlignment.Center, 
                     Brushes.DarkRed, Brushes.DarkRed, 80);
            Draw.Text(this, patternId + "_p5", false, "5", x5, p5.Price, 0, 
                     Brushes.White, new SimpleFont("Arial", 10), TextAlignment.Center, 
                     Brushes.DarkRed, Brushes.DarkRed, 80);
            
            // Dibujar un triángulo para marcar el patrón completo
            Draw.TriangleDown(this, patternId + "_marker", false, x5, p5.Price + 2 * TickSize, BearishColor);
            
            Alert("WolfeWave_Bear", Priority.Medium, "Wolfe Wave Bearish Pattern", 
                 NinjaTrader.Core.Globals.InstallDir + @"\sounds\Alert2.wav", 
                 0, Brushes.Crimson, Brushes.Black);
        }
        
        private double CalculateBullishTarget(WolfePoint p1, WolfePoint p3, WolfePoint p5)
        {
            double slope = CalculateSlope(p1, p3);
            int barDiff = p5.BarIndex - p1.BarIndex;
            double targetPrice = p1.Price + slope * barDiff;
            
            // Asegurar que el objetivo sea razonable (si es demasiado bajo, ajustarlo)
            return Math.Max(targetPrice, p5.Price + 5 * TickSize);
        }
        
        private double CalculateBearishTarget(WolfePoint p1, WolfePoint p3, WolfePoint p5)
        {
            double slope = CalculateSlope(p1, p3);
            int barDiff = p5.BarIndex - p1.BarIndex;
            double targetPrice = p1.Price + slope * barDiff;
            
            // Asegurar que el objetivo sea razonable (si es demasiado alto, ajustarlo)
            return Math.Min(targetPrice, p5.Price - 5 * TickSize);
        }
        
        private string FormatPrice(double price)
        {
            return Instrument.MasterInstrument.FormatPrice(price);
        }
        
        #endregion
    }
}

 

Link to comment
Share on other sites

WolfeWaveVisual Indicator - User Manual

Overview

The WolfeWaveVisual indicator is designed to automatically identify and display Wolfe Wave patterns on your NinjaTrader 8 charts. This implementation features enhanced visualization, flexible detection parameters, and real-time alerts.

Key Features

  • Automatic Pattern Detection: Identifies both bullish and bearish Wolfe Wave patterns
  • Clear Visual Markers: Highlights each swing point with diamonds and numbered labels
  • ZigZag Visualization: Shows the underlying price structure used for pattern detection
  • Target Price Projection: Calculates and displays potential price targets based on pattern geometry
  • Configurable Parameters: Adjust sensitivity and visualization to suit different markets and timeframes
  • Debug Mode: Provides detailed information about pattern detection process
  • Real-time Alerts: Notifies you when new patterns form

Parameter Settings

Parameter Description Recommended Range
FractalStrength Number of bars on each side to confirm swing points 2-5
MaxLookback Maximum number of bars to analyze for patterns 100-500
PatternTolerance Flexibility in pattern validation (higher = more patterns) 0.3-0.7
MinPointsForPattern Minimum number of swing points before pattern checking 5-10
ShowAllPoints Display all detected zigzag points True
ShowTargetProjection Display target price projection lines True
DebugMode Show detailed debug information True (initially)

Color Settings

Setting Description
BullishColor Color for bullish Wolfe Wave patterns
BearishColor Color for bearish Wolfe Wave patterns
ZigZagColor Color for the zigzag connecting swing points

Pattern Identification

The indicator identifies two types of Wolfe Wave patterns:

Bullish Wolfe Wave

  • Forms during downtrends
  • Consists of 5 points (3 valleys and 2 peaks)
  • Point 5 is lower than point 3
  • Points 1-3 and 2-4 converge
  • Potential buying opportunity at point 5

Bearish Wolfe Wave

  • Forms during uptrends
  • Consists of 5 points (3 peaks and 2 valleys)
  • Point 5 is higher than point 3
  • Points 1-3 and 2-4 converge
  • Potential selling opportunity at point 5

Troubleshooting

Issue Solution
No patterns detected Increase PatternTolerance, decrease FractalStrength
Too many false patterns Decrease PatternTolerance, increase FractalStrength
ZigZag lines missing Ensure ShowAllPoints is enabled
No visual elements Check that the indicator is applied to price panel

Tips for Best Results

  1. Use on higher timeframes (H1, H4, Daily) for more reliable patterns
  2. Combine with volume analysis and support/resistance levels
  3. Start with DebugMode enabled to understand detection process
  4. Adjust FractalStrength based on market volatility
  5. Consider patterns more reliable when they align with the overall trend

Technical Notes

  • Indicator recalculates on each new bar
  • Pattern detection uses a zigzag-based approach
  • Target prices are calculated using projection of line 1-3
  • Alerts trigger once when a pattern is first detected
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • Create New...