Announcement

Collapse
No announcement yet.

Partner 728x90

Collapse

visuals not showing up when loaded in strategy

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    visuals not showing up when loaded in strategy

    here the code :#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;
    #endregion

    // This namespace holds Indicators in this folder and is required. Do not change it.
    namespace NinjaTrader.NinjaScript.Indicators
    {
    public class VolumeSpikeNT8V3 : Indicator
    {
    // State variables for tracking spikes and price movements
    private bool isLongSpikeDetected = false;
    private bool isShortSpikeDetected = false;
    private double spikeLongPrice = 0.0;
    private double spikeShortPrice = 0.0;
    private int spikeLongBar = 0;
    private int spikeShortBar = 0;

    // Public boolean to track volume spike status
    private bool VolumeSpikeIsTrue = false;

    protected override void OnStateChange()
    {
    if (State == State.SetDefaults)
    {
    Description = @"VolumeSpikeNT8 detects significant volume spikes based on price action and a user-defined volume threshold. It triggers signals only when the volume spike is followed by a substantial price movement in the same direction.";
    Name = "VolumeSpikeNT8V3";
    Calculate = Calculate.OnBarClose;
    IsOverlay = true;
    DisplayInDataBox = true;
    DrawOnPricePanel = true;
    DrawHorizontalGridLines = true;
    DrawVerticalGridLines = true;
    PaintPriceMarkers = true;
    ScaleJustification = NinjaTrader.Gui.Chart.ScaleJustification.Right;
    IsSuspendedWhileInactive = false;
    Period = 5; // Look-back period for historical volume comparison
    VolumeThreshold = 5000; // Absolute volume threshold for spike detection
    PriceMoveThreshold = 100; // Minimum price movement after spike
    MaxBarsToCheck = 5; // Maximum bars to wait for price movement confirmation
    LongPriceMoveThreshold = 100; // Optional: separate threshold for long
    ShortPriceMoveThreshold = 100; // Optional: separate threshold for short
    }
    else if (State == State.Configure)
    {
    // Additional configuration logic (if any)
    }
    }

    protected override void OnBarUpdate()
    {
    // Ensure there are enough bars to perform calculations
    if (CurrentBar > Period)
    {
    // Reset VolumeSpikeIsTrue to false at the start of each bar update
    VolumeSpikeIsTrue = false;

    // Check for new volume spike conditions only if no active spike is being tracked
    if (!isLongSpikeDetected || !isShortSpikeDetected)
    {
    // LONG SIGNAL CONDITIONS
    if (
    (Low[0] <= Low[1]) && (Low[0] <= Low[2]) &&
    (Close[0] >= Close[1]) && (Close[0] >= Open[0]) &&
    (Close[0] - Open[0] < (High[0] - Low[0])) &&
    (Volume[1] > MAX(Volume, Period)[2]) &&
    (Volume[1] > VolumeThreshold)
    )
    {
    isLongSpikeDetected = true;
    spikeLongPrice = Close[1];
    spikeLongBar = CurrentBar - 1;
    // Draw a marker for the spike
    Draw.Dot(this, "LongSpikeDot" + CurrentBar, false, 1, Low[1] - TickSize, Brushes.Green);
    // Trigger an alert (optional)
    Alert("LongSpikeAlert" + CurrentBar, Priority.High, "Long Volume Spike Detected", "Alert1.wav", 0, Brushes.Transparent, Brushes.Transparent);
    }

    // SHORT SIGNAL CONDITIONS
    if (
    (High[0] >= High[1]) && (High[0] >= High[2]) &&
    (Close[0] <= Close[1]) && (Close[0] <= Open[0]) &&
    ((Open[0] - Close[0]) < (High[0] - Low[0])) &&
    (Volume[1] > MAX(Volume, Period)[2]) &&
    (Volume[1] > VolumeThreshold)
    )
    {
    isShortSpikeDetected = true;
    spikeShortPrice = Close[1];
    spikeShortBar = CurrentBar - 1; // Draw a marker for the spike
    Draw.Dot(this, "ShortSpikeDot" + CurrentBar, false, 1, High[1] + TickSize, Brushes.Red);
    // Trigger an alert (optional)
    Alert("ShortSpikeAlert" + CurrentBar, Priority.High, "Short Volume Spike Detected", "Alert2.wav", 0, Brushes.Transparent, Brushes.Transparent);
    }
    }

    // Monitor price movement for Long Spike
    if (isLongSpikeDetected)
    {
    int barsSinceSpike = CurrentBar - spikeLongBar;
    if (barsSinceSpike <= MaxBarsToCheck)
    {
    // Check if price has moved long by threshold
    if (Close[0] >= spikeLongPrice + LongPriceMoveThreshold)
    {
    // Trigger Long Signal
    BackBrush = Brushes.Green;
    // Draw a label for confirmation
    Draw.Text(this, "LongSignal" + CurrentBar, "Long Move", 0, spikeLongPrice + LongPriceMoveThreshold + TickSize, Brushes.Green);
    // Trigger an alert (optional)
    Alert("LongMoveAlert" + CurrentBar, Priority.High, "Price moved long after volume spike", "Alert3.wav", 0, Brushes.Transparent, Brushes.Transparent);
    // Reset the spike tracking
    VolumeSpikeIsTrue = true; // Set to true on trigger
    isLongSpikeDetected = false;
    }
    }
    else
    {
    // Reset if price movement condition not met within MaxBarsToCheck
    isLongSpikeDetected = false;
    }
    }

    // Monitor price movement for Short Spike
    if (isShortSpikeDetected)
    {
    int barsSinceSpike = CurrentBar - spikeShortBar;
    if (barsSinceSpike <= MaxBarsToCheck)
    {
    // Check if price has moved short by threshold
    if (Close[0] <= spikeShortPrice - ShortPriceMoveThreshold)
    {
    // Trigger Short Signal
    BackBrush = Brushes.Red;
    // Draw a label for confirmation
    Draw.Text(this, "ShortSignal" + CurrentBar, "Short Move", 0, spikeShortPrice - ShortPriceMoveThreshold - TickSize, Brushes.Red);
    // Trigger an alert (optional)
    Alert("ShortMoveAlert" + CurrentBar, Priority.High, "Price moved short after volume spike", "Alert4.wav", 0, Brushes.Transparent, Brushes.Transparent);
    // Reset the spike tracking
    VolumeSpikeIsTrue = true; // Set to true on trigger
    isShortSpikeDetected = false;
    }
    }
    else
    {
    // Reset if price movement condition not met within MaxBarsToCheck
    isShortSpikeDetected = false;
    }
    }
    }
    }

    region Properties
    [NinjaScriptProperty]
    [Range(1, int.MaxValue)]
    [Display(Name="Period", Description="Look-back period for historical volume comparison.", Order=1, GroupName="Parameters")]
    public int Period { get; set; }

    [NinjaScriptProperty]
    [Range(1, double.MaxValue)]
    [Display(Name="Volume Threshold", Description="Minimum volume required to trigger a spike signal.", Order=2, GroupName="Parameters")]
    public double VolumeThreshold { get; set; }

    [NinjaScriptProperty]
    [Range(1, double.MaxValue)]
    [Display(Name="Price Move Threshold", Description="Minimum price movement (in points) required after a volume spike to confirm the signal.", Order=3, GroupName="Parameters")]
    public double PriceMoveThreshold { get; set; }

    [NinjaScriptProperty]
    [Range(1, int.MaxValue)]
    [Display(Name="Max Bars to Check", Description="Maximum number of bars to wait after a volume spike for price movement confirmation.", Order=4, GroupName="Parameters")]
    public int MaxBarsToCheck { get; set; }

    [NinjaScriptProperty]
    [Range(1, double.MaxValue)]
    [Display(Name="Long Price Move Threshold", Description="Minimum price movement (in points) required after a bullish volume spike to confirm the signal.", Order=5, GroupName="Parameters")]
    public double LongPriceMoveThreshold { get; set; }

    [NinjaScriptProperty]
    [Range(1, double.MaxValue)]
    [Display(Name="Short Price Move Threshold", Description="Minimum price movement (in points) required after a bearish volume spike to confirm the signal.", Order=6, GroupName="Parameters")]
    public double ShortPriceMoveThreshold { get; set; }

    // Make VolumeSpikeIsTrue accessible to other scripts
    [Browsable(false)]
    [XmlIgnore]
    public bool volumeSpikeIsTrue
    {
    get { return VolumeSpikeIsTrue; }
    }
    #endregion
    }
    }

    region NinjaScript generated code. Neither change nor remove.

    namespace NinjaTrader.NinjaScript.Indicators
    {
    public partial class Indicator : NinjaTrader.Gui.NinjaScript.IndicatorRenderBase
    {
    private VolumeSpikeNT8V3[] cacheVolumeSpikeNT8V3;
    public VolumeSpikeNT8V3 VolumeSpikeNT8V3(int period, double volumeThreshold, double priceMoveThreshold, int maxBarsToCheck, double longPriceMoveThreshold, double shortPriceMoveThreshold)
    {
    return VolumeSpikeNT8V3(Input, period, volumeThreshold, priceMoveThreshold, maxBarsToCheck, longPriceMoveThreshold, shortPriceMoveThreshold);
    }

    public VolumeSpikeNT8V3 VolumeSpikeNT8V3(ISeries<double> input, int period, double volumeThreshold, double priceMoveThreshold, int maxBarsToCheck, double longPriceMoveThreshold, double shortPriceMoveThreshold)
    {
    if (cacheVolumeSpikeNT8V3 != null)
    for (int idx = 0; idx < cacheVolumeSpikeNT8V3.Length; idx++)
    if (cacheVolumeSpikeNT8V3[idx] != null && cacheVolumeSpikeNT8V3[idx].Period == period && cacheVolumeSpikeNT8V3[idx].VolumeThreshold == volumeThreshold && cacheVolumeSpikeNT8V3[idx].PriceMoveThreshold == priceMoveThreshold && cacheVolumeSpikeNT8V3[idx].MaxBarsToCheck == maxBarsToCheck && cacheVolumeSpikeNT8V3[idx].LongPriceMoveThreshold == longPriceMoveThreshold && cacheVolumeSpikeNT8V3[idx].ShortPriceMoveThreshold == shortPriceMoveThreshold && cacheVolumeSpikeNT8V3[idx].EqualsInput(input))
    return cacheVolumeSpikeNT8V3[idx];
    return CacheIndicator<VolumeSpikeNT8V3>(new VolumeSpikeNT8V3(){ Period = period, VolumeThreshold = volumeThreshold, PriceMoveThreshold = priceMoveThreshold, MaxBarsToCheck = maxBarsToCheck, LongPriceMoveThreshold = longPriceMoveThreshold, ShortPriceMoveThreshold = shortPriceMoveThreshold }, input, ref cacheVolumeSpikeNT8V3);
    }
    }
    }



    ​: cant get the visuals to show up on the chart when i have this AddChartIndicator​() so i could use some help on the proper way to get my indicator to show up in the strategy chart: i works great when just loaded on a chart as a indicator


    thanks in advance

    #2
    Helllo thehammer,

    The code shown is an indicator, we would need to see the strategies code to better understand what is happening with AddChartIndicator. To have that work the indicator has to be used on the primary series, not a secondary series and you need to call the indicator from the strategies OnBarUpdate to have it process. The strategy also has to be applied directly to a chart and not the control center.

    Comment


      #3
      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.Indicators;
      using NinjaTrader.NinjaScript.DrawingTools;
      using NinjaTrader.NinjaScript.AddOns; // Added for SharedDataStore

      #endregion

      // This namespace holds Strategies in this folder and is required. Do not change it.
      namespace NinjaTrader.NinjaScript.Strategies
      {
      public class APIreceiverCallRestructured : Strategy
      {
      private VWAP vwapIndicator;
      private string CurrentApiCall;
      private string DelayedApiCall;
      private bool CurrentAndDelayedApiAgree = false;
      public static bool OverrideCurrentAPICall { get; set; }
      private string finalCall;
      private DateTime finalCallNoneStartTime;
      private DateTime volumeSpikeStartTime;
      private bool isVolumeSpikeActive = false;
      private bool isFinalCallNoneTimerActive = false;
      private int finalCallCount = 0;
      private Dictionary<int, DateTime> finalCallTimes = new Dictionary<int, DateTime>();
      private int activationCount = 0; // Counter to track dictionary keys
      // Constants for magic numbers
      private const int FinalCallNoneDurationMinutes = 90;
      private VolumeSpikeNT8V3 volumeSpikeIndicator;

      region Parameters
      [NinjaScriptProperty]
      [Display(Name = "Volume Spike Period", Description = "Period for volume spike calculation", Order = 1, GroupName = "Parameters")]
      public int VolumeSpikePeriod { get; set; } = 3;

      [NinjaScriptProperty]
      [Display(Name = "Volume Threshold", Description = "Threshold for volume spike", Order = 2, GroupName = "Parameters")]
      public int VolumeThreshold { get; set; } = 800;

      #endregion


      protected override void OnStateChange()
      {
      if (State == State.SetDefaults)
      {
      Description = @"Enter the description for your new custom Strategy here.";
      Name = "API Receiver Call Restructured";
      Calculate = Calculate.OnBarClose;
      EntriesPerDirection = 1;
      EntryHandling = EntryHandling.AllEntries;
      IsExitOnSessionCloseStrategy = true;
      ExitOnSessionCloseSeconds = 30;
      IsFillLimitOnTouch = false;
      MaximumBarsLookBack = MaximumBarsLookBack.TwoHundredFiftySix;
      OrderFillResolution = OrderFillResolution.Standard;
      Slippage = 0;
      StartBehavior = StartBehavior.WaitUntilFlat;
      TimeInForce = TimeInForce.Gtc;
      TraceOrders = false;
      RealtimeErrorHandling = RealtimeErrorHandling.StopCancelClose;
      StopTargetHandling = StopTargetHandling.PerEntryExecution;
      BarsRequiredToTrade = 20;
      IsInstantiatedOnEachOptimizationIteration = true;

      API_ConsistentStateDuration = new TimeSpan(0, 0, 15); // default is a mere 15 seconds. User may consider 15 or 30 minutes to be his usable default. Exists in btAddOn
      }
      else if (State == State.Configure)
      {

      }
      else if (State == State.DataLoaded)
      {
      try
      {
      // Instantiate indicators
      vwapIndicator = VWAP();
      volumeSpikeIndicator = VolumeSpikeNT8V3(VolumeSpikePeriod,VolumeThreshold ,120,90,120,120);

      //AddChartIndicator(volumeSpikeIndicator);


      // Initialize shared data
      Share("btReceiverV2", "api");
      NinjaTrader.NinjaScript.AddOns.btAddOn.API_Consist entStateDuration = API_ConsistentStateDuration;

      CurrentApiCall = NinjaTrader.NinjaScript.AddOns.btAddOn.SharedStrin g;
      DelayedApiCall = NinjaTrader.NinjaScript.AddOns.btAddOn.SharedStrin gConfirmed;
      }
      catch (Exception ex)
      {
      Print($"Error during DataLoaded state: {ex.Message}");
      // Consider additional error handling or state management
      }
      }


      }

      protected override void OnBarUpdate()
      {
      if (State == State.Realtime)
      {
      NinjaTrader.NinjaScript.AddOns.btAddOn.API_Consist entStateDuration = API_ConsistentStateDuration; // set
      CompareCurrentApiToDelayedApi();
      FinalCallTimer();
      DecideFinalDirectionCall();

      NinjaTrader.NinjaScript.AddOns.btAddOn.SharedStrin g = finalCall;

      Draw.TextFixed(this, "finalCallText", "API Final Call: " + finalCall, TextPosition.TopLeft, Brushes.White, new Gui.Tools.SimpleFont("Arial", 14), Brushes.Transparent, Brushes.Transparent, 0);
      Draw.TextFixed(this, "isFinalCallNoneTimerActive", "Final Call Active: " + isFinalCallNoneTimerActive, TextPosition.TopLeft, Brushes.White, new Gui.Tools.SimpleFont("Arial", 14), Brushes.Transparent, Brushes.Transparent, 0).YPixelOffset = -30;
      Draw.TextFixed(this, "finalCallCountText", "Final Call Count: " + finalCallCount, TextPosition.TopLeft, Brushes.White, new Gui.Tools.SimpleFont("Arial", 14), Brushes.Transparent, Brushes.Transparent, 0).YPixelOffset = -60;
      Draw.TextFixed(this, "finalCallLastTime", "Last Time Activated: " + finalCallNoneStartTime, TextPosition.TopLeft, Brushes.White, new Gui.Tools.SimpleFont("Arial", 14), Brushes.Transparent, Brushes.Transparent, 0).YPixelOffset = -90;
      }
      }


      ​i have it commented out because it was not working

      Comment


        #4
        Hello thehammer,

        You need to call the indicator from OnBarUpdate in addition to using AddChartIndicator. The indicator won't process historically otherwise.

        If you have a plot you can call the plot and get a value to call the indicator, without a plot you can use volumeSpikeIndicator.Update();

        Comment


          #5
          protected override void OnStateChange()
          {
          if (State == State.SetDefaults)
          {
          Description = @"Enter the description for your new custom Strategy here.";
          Name = "API Receiver Call Restructured";
          Calculate = Calculate.OnBarClose;
          EntriesPerDirection = 1;
          EntryHandling = EntryHandling.AllEntries;
          IsExitOnSessionCloseStrategy = true;
          ExitOnSessionCloseSeconds = 30;
          IsFillLimitOnTouch = false;
          MaximumBarsLookBack = MaximumBarsLookBack.TwoHundredFiftySix;
          OrderFillResolution = OrderFillResolution.Standard;
          Slippage = 0;
          StartBehavior = StartBehavior.WaitUntilFlat;
          TimeInForce = TimeInForce.Gtc;
          TraceOrders = false;
          RealtimeErrorHandling = RealtimeErrorHandling.StopCancelClose;
          StopTargetHandling = StopTargetHandling.PerEntryExecution;
          BarsRequiredToTrade = 20;
          IsInstantiatedOnEachOptimizationIteration = true;

          API_ConsistentStateDuration = new TimeSpan(0, 0, 15); // default is a mere 15 seconds. User may consider 15 or 30 minutes to be his usable default. Exists in btAddOn
          }
          else if (State == State.Configure)
          {

          }
          else if (State == State.DataLoaded)
          {
          try
          {
          // Instantiate indicators
          vwapIndicator = VWAP();
          volumeSpikeIndicator = VolumeSpikeNT8V3(VolumeSpikePeriod,VolumeThreshold ,120,90,120,120);

          AddChartIndicator(volumeSpikeIndicator);


          // Initialize shared data
          Share("btReceiverV2", "api");
          NinjaTrader.NinjaScript.AddOns.btAddOn.API_Consist entStateDuration = API_ConsistentStateDuration;

          CurrentApiCall = NinjaTrader.NinjaScript.AddOns.btAddOn.SharedStrin g;
          DelayedApiCall = NinjaTrader.NinjaScript.AddOns.btAddOn.SharedStrin gConfirmed;
          }
          catch (Exception ex)
          {
          Print($"Error during DataLoaded state: {ex.Message}");
          // Consider additional error handling or state management
          }
          }


          }

          protected override void OnBarUpdate()
          {
          if (State == State.Realtime)
          {
          NinjaTrader.NinjaScript.AddOns.btAddOn.API_Consist entStateDuration = API_ConsistentStateDuration; // set
          CompareCurrentApiToDelayedApi();
          FinalCallTimer();
          DecideFinalDirectionCall();
          // Force indicator to update historically
          volumeSpikeIndicator.Update();

          NinjaTrader.NinjaScript.AddOns.btAddOn.SharedStrin g = finalCall;

          Draw.TextFixed(this, "finalCallText", "API Final Call: " + finalCall, TextPosition.TopLeft, Brushes.White, new Gui.Tools.SimpleFont("Arial", 14), Brushes.Transparent, Brushes.Transparent, 0);
          Draw.TextFixed(this, "isFinalCallNoneTimerActive", "Final Call Active: " + isFinalCallNoneTimerActive, TextPosition.TopLeft, Brushes.White, new Gui.Tools.SimpleFont("Arial", 14), Brushes.Transparent, Brushes.Transparent, 0).YPixelOffset = -30;
          Draw.TextFixed(this, "finalCallCountText", "Final Call Count: " + finalCallCount, TextPosition.TopLeft, Brushes.White, new Gui.Tools.SimpleFont("Arial", 14), Brushes.Transparent, Brushes.Transparent, 0).YPixelOffset = -60;
          Draw.TextFixed(this, "finalCallLastTime", "Last Time Activated: " + finalCallNoneStartTime, TextPosition.TopLeft, Brushes.White, new Gui.Tools.SimpleFont("Arial", 14), Brushes.Transparent, Brushes.Transparent, 0).YPixelOffset = -90;
          }
          }

          ​: like this ?

          Comment


            #6
            Hello thehammer,

            Yes that is correct, that will cause the indicators OnBarUpdate to be called. You need to move that outside of your if (State == State.Realtime) condition as well.

            Comment


              #7
              protected override void OnBarUpdate()
              {

              // Ensure volumeSpikeIndicator updates on every bar, not just real-time
              if (volumeSpikeIndicator != null)
              {
              // Force indicator to update historically
              volumeSpikeIndicator.Update();
              }

              if (State == State.Realtime)
              {
              NinjaTrader.NinjaScript.AddOns.btAddOn.API_Consist entStateDuration = API_ConsistentStateDuration; // set
              CompareCurrentApiToDelayedApi();
              FinalCallTimer();
              DecideFinalDirectionCall();

              NinjaTrader.NinjaScript.AddOns.btAddOn.SharedStrin g = finalCall;

              Draw.TextFixed(this, "finalCallText", "API Final Call: " + finalCall, TextPosition.TopLeft, Brushes.White, new Gui.Tools.SimpleFont("Arial", 14), Brushes.Transparent, Brushes.Transparent, 0);
              Draw.TextFixed(this, "isFinalCallNoneTimerActive", "Final Call Active: " + isFinalCallNoneTimerActive, TextPosition.TopLeft, Brushes.White, new Gui.Tools.SimpleFont("Arial", 14), Brushes.Transparent, Brushes.Transparent, 0).YPixelOffset = -30;
              Draw.TextFixed(this, "finalCallCountText", "Final Call Count: " + finalCallCount, TextPosition.TopLeft, Brushes.White, new Gui.Tools.SimpleFont("Arial", 14), Brushes.Transparent, Brushes.Transparent, 0).YPixelOffset = -60;
              Draw.TextFixed(this, "finalCallLastTime", "Last Time Activated: " + finalCallNoneStartTime, TextPosition.TopLeft, Brushes.White, new Gui.Tools.SimpleFont("Arial", 14), Brushes.Transparent, Brushes.Transparent, 0).YPixelOffset = -90;
              }
              }​: is this the correct way?

              Comment


                #8
                Hello thehammer,

                Yes that should work, are you seeing the visuals after re applying the indicator? Because you had AddChartIndicator commented out you'll need to remove and re apply it to see that take effect.

                Comment


                  #9
                  thanks for the help i got everything to work and am seeing it on the chart now,

                  regards , anton

                  Comment

                  Latest Posts

                  Collapse

                  Topics Statistics Last Post
                  Started by Geovanny Suaza, 02-11-2026, 06:32 PM
                  0 responses
                  576 views
                  0 likes
                  Last Post Geovanny Suaza  
                  Started by Geovanny Suaza, 02-11-2026, 05:51 PM
                  0 responses
                  334 views
                  1 like
                  Last Post Geovanny Suaza  
                  Started by Mindset, 02-09-2026, 11:44 AM
                  0 responses
                  101 views
                  0 likes
                  Last Post Mindset
                  by Mindset
                   
                  Started by Geovanny Suaza, 02-02-2026, 12:30 PM
                  0 responses
                  553 views
                  1 like
                  Last Post Geovanny Suaza  
                  Started by RFrosty, 01-28-2026, 06:49 PM
                  0 responses
                  551 views
                  1 like
                  Last Post RFrosty
                  by RFrosty
                   
                  Working...
                  X