Untitled
unknown
csharp
12 days ago
19 kB
6
Indexable
#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 System.Text.Json.Serialization; using System.Text.Json; using NinjaTrader.Gui.Updater; using System.Collections; using SharpDX; #endregion //This namespace holds Indicators in this folder and is required. Do not change it. namespace NinjaTrader.NinjaScript.Indicators { public class BetterSwing : Indicator { #region Properties [NinjaScriptProperty] [Display(Name = "Enable Swing Range Info", GroupName = "Parameters", Order = 0)] public bool EnableSwingPowerDrawing { get; set; } [NinjaScriptProperty] [Display(Name = "Swing percentage", GroupName = "Swing Settings", Order = 1)] [Range(0.01, 1)] public double ZigZagPercentage { get; set; } [NinjaScriptProperty] [Display(Name = "Enable ZigZag", GroupName = "Parameters", Order = 2)] public bool EnableZigZag { get; set; } #endregion private double tickSize; private SwingLinkedList Swings; public SwingLinkedList GetSwings { get { Update(); return Swings; } } private ZigZag ZigZagIndicator; // for fibo enum private Dictionary<FibonacciLevels, double> fibDictionary; public enum SwingType { SWING_LONG, SWING_SHORT } public ZigZag GetZigZagInstance() { Update(); return ZigZagIndicator; } #region ClassMySwing public class SwingLinkedList : IEnumerable<MySwing> { public MySwing Head { get; private set; } public MySwing Tail { get; private set; } public int Count { get; private set; } public SwingLinkedList() { Head = null; Tail = null; } public void Append(MySwing swing) { if (Head == null) { Head = swing; Tail = swing; } else { Tail.Next = swing; swing.Previous = Tail; Tail = swing; //if (owner != null) //owner.Print("Dodano nowy Swing do listy"); } Count++; } public override bool Equals(object obj) { if(obj is SwingLinkedList other) { if(this.Count != other.Count) { return false; } var thisNode = this.Head; var otherNode = other.Head; // 3. Iteracyjne porównanie każdego węzła while (thisNode != null && otherNode != null) { if (!thisNode.Equals(otherNode)) // <-- PORÓWNANIE PRZEZ MySwing return false; thisNode = thisNode.Next; otherNode = otherNode.Next; } return true; // Jeśli wszystkie węzły są równe, listy są równe } return false; } public override int GetHashCode() { unchecked { int hash = 17; var node = this.Head; while (node != null) { hash = hash * 31 + node.GetHashCode(); // Użycie hashcode MySwing node = node.Next; } return hash; } } // Implementacja interfejsu IEnumerable<MySwing> public IEnumerator<MySwing> GetEnumerator() { MySwing current = Head; while (current != null) { yield return current; current = current.Next; } } // Wymagana implementacja interfejsu IEnumerable IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public class MySwing : IEquatable<MySwing> { public MySwing Previous { get; set; } private MySwing? _next; public MySwing Next { get { return _next; } set { if (value != null) { // Naprzemienność ekstremów w zależności od typu if (this.SwingType == SwingType.SWING_LONG) { // Wymuszamy identyczny High if (this.HighPrice != value.HighPrice) throw new InvalidOperationException( "Jeśli poprzedni swing był LONG, to następny (SHORT) musi mieć ten sam High." ); } else if (this.SwingType == SwingType.SWING_SHORT) { // Wymuszamy identyczny Low if (this.LowPrice != value.LowPrice) throw new InvalidOperationException( "Jeśli poprzedni swing był SHORT, to następny (LONG) musi mieć ten sam Low." ); } } // Link zwrotny value.Previous = this; _next = value; } } // Cechy Swingu public SwingType SwingType { get; } // Get‐only property; ustalana tylko w konstruktorze public double LowPrice { get; } public double HighPrice { get; } public double SwingRange { get; } public DateTime LowTime { get; } public DateTime HighTime { get; } public MySwing(SwingType swingType, double lowPrice, double highPrice, double tickSize, DateTime lowTime, DateTime highTime) { SwingType = swingType; LowPrice = lowPrice; HighPrice = highPrice; SwingRange = (highPrice - lowPrice) / tickSize; LowTime = lowTime; HighTime = highTime; } public double GetSwingPower(TimeSpan totalMinutes) { double duration = totalMinutes.TotalMinutes; return (SwingRange / duration ); } public SwingType GetSwingType() { return SwingType; } public static double GetFibLevel(SwingType swingType, double lowPrice, double highPrice, double level) { double priceAmplitude = Math.Abs(highPrice - lowPrice); if (swingType == SwingType.SWING_SHORT) { // Swing short: poziom 0% jest na dole, 100% u g�ry return highPrice - (priceAmplitude * (1 - level)); } else if (swingType == SwingType.SWING_LONG) { // Swing long: poziom 0% jest na dole, 100% u g�ry return lowPrice + (priceAmplitude * (1 - level)); } else { throw new ArgumentException("Invalid swingType. Expected 'Up' or 'Down'."); } } public double GetFibLevel(double level) { double priceAmplitude = Math.Abs(HighPrice - LowPrice); if (SwingType == SwingType.SWING_SHORT) { return HighPrice - (priceAmplitude * (1 - level)); } else if (SwingType == SwingType.SWING_LONG) { return LowPrice + (priceAmplitude * (1 - level)); ; } else { throw new ArgumentException("Invalid swingType. Expected 'Up' or 'Down'."); } } // Equals + IEquatable public override bool Equals(object obj) => Equals(obj as MySwing); public bool Equals(MySwing other) { if (other == null) return false; return SwingType == other.SwingType && LowPrice.Equals(other.LowPrice) && HighPrice.Equals(other.HighPrice) && LowTime.Equals(other.LowTime) && HighTime.Equals(other.HighTime); } public override int GetHashCode() { unchecked { int hash = 17; hash = hash * 23 + SwingType.GetHashCode(); hash = hash * 23 + LowPrice.GetHashCode(); hash = hash * 23 + HighPrice.GetHashCode(); hash = hash * 23 + LowTime.GetHashCode(); hash = hash * 23 + HighTime.GetHashCode(); return hash; } } } #endregion protected override void OnStateChange() { if (State == State.SetDefaults) { Description = @"Enter the description for your new custom Indicator here."; Name = "BetterSwing"; Calculate = Calculate.OnBarClose; IsOverlay = true; DisplayInDataBox = true; DrawOnPricePanel = true; DrawHorizontalGridLines = true; DrawVerticalGridLines = true; PaintPriceMarkers = true; ScaleJustification = NinjaTrader.Gui.Chart.ScaleJustification.Right; //Disable this property if your indicator requires custom values that cumulate with each new market data event. //See Help Guide for additional information. IsSuspendedWhileInactive = true; AddPlot(Brushes.Blue, "ZigZag"); ZigZagPercentage = 0.25; } else if (State == State.Configure) { } else if (State == State.DataLoaded) { tickSize = Instrument.MasterInstrument.TickSize; Swings = new SwingLinkedList(); ZigZagIndicator = ZigZag(DeviationType.Percent, ZigZagPercentage, true); } } protected override void OnBarUpdate() { if (BarsInProgress != 0) return; if (CurrentBars[0] < 3) { return; } int currentLowIdx = -1, currentHighIdx = -1; int previousLowIdx = -1, previousHighIdx = -1; double currentLowPrice = 0, currentHighPrice = 0; double previousLowPrice = 0, previousHighPrice = 0; // pobranie indeksow ostatnich high and low - szukamy od "teraz" currentLowIdx = ZigZagIndicator.LowBar(0, 1, CurrentBars[0] - 1); currentHighIdx = ZigZagIndicator.HighBar(0, 1, CurrentBars[0] - 1); // walidacja czy znaleziono indeksy if (currentLowIdx == -1 || currentHighIdx == -1) { return; } // pobranie wartosci cen dla current swing currentLowPrice = Low[currentLowIdx]; currentHighPrice = High[currentHighIdx]; DateTime currentLowTime = Time[currentLowIdx]; DateTime currentHighTime = Time[currentHighIdx]; // Tworzenie obiektu current Swing nie ma sensu, ponieważ aktualny Swing aktualizuje sie na bieżąco, więc tylko marnujemy pamięc na stercie //CurrentSwing = new MySwing(currentLowIdx, currentLowPrice, currentLowTime, currentHighIdx, currentHighPrice, currentHighTime, tickSize); if(currentHighTime < currentLowTime) { // Jezeli czas szczytu aktualnie rozwijajacego sie Swingu jest mniejszy (wczesniejszy) niz czas low to znaczy ze to ruch spadkowy previousHighIdx = currentHighIdx; previousLowIdx = ZigZagIndicator.LowBar(previousHighIdx - 1, 1, CurrentBars[0] - 1); } else { // W odwrotnym przypadku jest to ruch wzrostowy previousLowIdx = currentLowIdx; previousHighIdx = ZigZagIndicator.HighBar(previousLowIdx - 1, 1, CurrentBars[0] - 1); } if (previousLowIdx < 0 || previousHighIdx < 0) { return; } previousLowPrice = Low[previousLowIdx]; previousHighPrice = High[previousHighIdx]; DateTime previousLowTime = Time[previousLowIdx]; DateTime previousHighTime = Time[previousHighIdx]; MySwing FormedSwing; if (previousLowTime < previousHighTime) { // Jezeli czas szczytu poprzedniego Swingu jest mniejszy (wczesniejszy) niz czas low to znaczy ze to ruch spadkowy FormedSwing = new MySwing(SwingType.SWING_LONG, previousLowPrice, previousHighPrice, tickSize, previousLowTime, previousHighTime); //Print("Utworzono swing wzrostowy"); } else { // W odwrotnym przypadku jest to ruch wzrostowy //PreviousSwing = new MySwing(SwingType.SWING_LONG, previousLowPrice, previousHighPrice, tickSize); FormedSwing = new MySwing(SwingType.SWING_SHORT, previousLowPrice, previousHighPrice, tickSize, previousLowTime, previousHighTime); //Print("Utworzono swing spadkowy"); } var lastSwing = Swings.Tail; if (lastSwing != null && lastSwing.Equals(FormedSwing)) { // Oznacza, że parametry (SwingType, LowPrice, HighPrice) są takie same, // więc pomijamy dodanie do listy //Print("Znaleziono duplikat swingu, pomijamy..."); } else { try { Swings.Append(FormedSwing); } catch (ArgumentException e) { //Print(e.Message); } catch (InvalidOperationException e) { //Print(e.Message); } if (Swings.Count == 0) { //Print("Lista jest pusta"); } } } } } #region NinjaScript generated code. Neither change nor remove. namespace NinjaTrader.NinjaScript.Indicators { public partial class Indicator : NinjaTrader.Gui.NinjaScript.IndicatorRenderBase { private BetterSwing[] cacheBetterSwing; public BetterSwing BetterSwing(bool enableSwingPowerDrawing, double zigZagPercentage, bool enableZigZag) { return BetterSwing(Input, enableSwingPowerDrawing, zigZagPercentage, enableZigZag); } public BetterSwing BetterSwing(ISeries<double> input, bool enableSwingPowerDrawing, double zigZagPercentage, bool enableZigZag) { if (cacheBetterSwing != null) for (int idx = 0; idx < cacheBetterSwing.Length; idx++) if (cacheBetterSwing[idx] != null && cacheBetterSwing[idx].EnableSwingPowerDrawing == enableSwingPowerDrawing && cacheBetterSwing[idx].ZigZagPercentage == zigZagPercentage && cacheBetterSwing[idx].EnableZigZag == enableZigZag && cacheBetterSwing[idx].EqualsInput(input)) return cacheBetterSwing[idx]; return CacheIndicator<BetterSwing>(new BetterSwing(){ EnableSwingPowerDrawing = enableSwingPowerDrawing, ZigZagPercentage = zigZagPercentage, EnableZigZag = enableZigZag }, input, ref cacheBetterSwing); } } } namespace NinjaTrader.NinjaScript.MarketAnalyzerColumns { public partial class MarketAnalyzerColumn : MarketAnalyzerColumnBase { public Indicators.BetterSwing BetterSwing(bool enableSwingPowerDrawing, double zigZagPercentage, bool enableZigZag) { return indicator.BetterSwing(Input, enableSwingPowerDrawing, zigZagPercentage, enableZigZag); } public Indicators.BetterSwing BetterSwing(ISeries<double> input , bool enableSwingPowerDrawing, double zigZagPercentage, bool enableZigZag) { return indicator.BetterSwing(input, enableSwingPowerDrawing, zigZagPercentage, enableZigZag); } } } namespace NinjaTrader.NinjaScript.Strategies { public partial class Strategy : NinjaTrader.Gui.NinjaScript.StrategyRenderBase { public Indicators.BetterSwing BetterSwing(bool enableSwingPowerDrawing, double zigZagPercentage, bool enableZigZag) { return indicator.BetterSwing(Input, enableSwingPowerDrawing, zigZagPercentage, enableZigZag); } public Indicators.BetterSwing BetterSwing(ISeries<double> input , bool enableSwingPowerDrawing, double zigZagPercentage, bool enableZigZag) { return indicator.BetterSwing(input, enableSwingPowerDrawing, zigZagPercentage, enableZigZag); } } } #endregion
Editor is loading...
Leave a Comment