Jump to content
Tom Next - Daytrading Community

(CB) Plot zeichnen in die Zukunft


GoSPvC

Recommended Posts

Folgende Lösung habe ich wieder mangels Möglichkeiten von NT finden müssen. Und zwar war es bei TS Terminal möglich, einfach per negativem Displacement DrawLine() in die Zukunft zeichnen zu lassen.

 

DrawLine[-5](...) zeichnete somit 5 Bars in die Zukunft des Charts

 

NT erlaubt leider kein negatives "barsAgo", sondern es muß umständlich umgangen werden; aber es geht.

 

Auf BigMikeTrading[Punkt]com habe ich einen Ichimoku gefunden, der die Cloud in der Zukunft zeichnet. Hieraus habe ich das simple Plotten einer Linie in die ChartZukunft extrahiert. Ich bitte um Kommentare/Verbesserungen usw., falls nötig.

 

Hier der Beispielcode:

// Originalfile Ichimoku.cs - Developed by Tarantino - Found at bigmiketrading.com
#region Using declarations
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Xml.Serialization;
using System.Collections;
using System.Collections.Generic;
using NinjaTrader.Cbi;
using NinjaTrader.Data;
using NinjaTrader.Gui.Chart;
using NinjaTrader.Indicator;
using NinjaTrader.Strategy;
#endregion Using declarations
namespace NinjaTrader.Indicator
{
public class CB_PlotToFuture : Indicator
{
 #region Parameters and Variables
 // Parameters:
 private int   period    = 10;
 // Variables:
 private DataSeries futurePlot   = null;
 #endregion Parameters and Variables
 protected override void Initialize()
 {
  Add(new Plot(new Pen(Color.FromKnownColor(KnownColor.Orange), 1), PlotStyle.Line, "Plot0"));
  Plots[0].Pen.DashStyle = DashStyle.Solid;
  futurePlot = new DataSeries(this, MaximumBarsLookBack.Infinite);
  AutoScale = true;
  ScaleJustification = ScaleJustification.Right;
  Overlay = true;
  BarsRequired = period;
  PriceTypeSupported = false;
  PlotsConfigurable = false;
  CalculateOnBarClose = false;
 }
 protected override void OnBarUpdate()
 {
  #region First Bars in Chart
  if (Bars == null) { return; }
  //if (Data.BarsType.GetInstance(Bars.Period.Id).IsIntraday) { return; }
  //if (Bars.Period.Id == PeriodType.Day || Bars.Period.Id == PeriodType.Week || Bars.Period.Id == PeriodType.Month || Bars.Period.Id == PeriodType.Year) { return; }
  if (CurrentBar <= period) { return; }
  #endregion First Bars in Chart
  Plot0.Set(SMA(period)[0]);
  for (int i = 0; i <= period; i++)
  {
   futurePlot.Set(i, SMA(period)[0]);
  }
  futurePlot.Set(period - 1, Convert.ToDouble(null));
 }
 #region Properties
 [browsable(false)]
 [XmlIgnore()]
 public DataSeries Plot0
 {
  get { return Values[0]; }
 }
 [browsable(false)]
 [XmlIgnore]
 public DataSeries FuturePlot
 {
  get { return futurePlot; }
 }
 [Description("")]
 [GridCategory("Parameters")]
 [DisplayName("Parameter Nr. 0")]
 public int Period
 {
  get { return period; }
  set { period = Math.Max(1, value); }
 }
 [browsable(false)]
 public new int Displacement
 {
  get { return base.Displacement; }
  set { base.Displacement = 0; }
 }
 #endregion
 #region Override Plot()
 public override void Plot(Graphics graphics, Rectangle bounds, double min, double max)
 {
  //if ("check for no futurePlot")
  //{
  // base.Plot(graphics, bounds, min, max); // We call base Plot() method to paint defined Plots
  // return;		 // if check for no futurePlot == true to avoid unnecessary calculations
  //}
  List<Point> points = new List<Point>();
  int lastX = -1;
  double lastValue = -1;
  Pen pen = new Pen(Color.FromKnownColor(KnownColor.Red));
  for (int idx = FirstBarIndexPainted - period; idx <= LastBarIndexPainted; idx++)
  {
   if (idx < 0 || idx >= BarsArray[0].Count || (!ChartControl.ShowBarsRequired && idx < BarsRequired)) { continue; }
   bool futurePlotHasValue = futurePlot.IsValidPlot(idx) && futurePlot.Get(idx) > 0;
   if (!futurePlotHasValue) { continue; }
   double value = futurePlot.Get(idx);
   int x = ChartControl.GetXByBarIdx(BarsArray[0], idx + period);
   if (lastX >= 0)
   {
 int y0 = ChartControl.GetYByValue(this, lastValue);
 int y1 = ChartControl.GetYByValue(this, value);
 if (points.Count == 0) // We have a start painting
 {
  points.Clear();
  points.Add(new Point(lastX, y0));
  points.Add(new Point(x, y1));
 }
 else
 {
  int pos = points.Count;
  points.Insert(pos, new Point(x, y1));
 }
   }
   // Save as previous Point
   lastX = x;
   lastValue = value;
  }
  if (points.Count > 0 && pen != null)
  {
   SmoothingMode oldSmoothingMode = graphics.SmoothingMode;
   graphics.SmoothingMode = SmoothingMode.AntiAlias;
   graphics.DrawLines(pen, points.ToArray());
   graphics.SmoothingMode = oldSmoothingMode;
   points.Clear();
  }
  pen.Dispose();
  // Paint defined Plots
  base.Plot(graphics, bounds, min, max);
 }
 #endregion Override Plot()
}
}
#region NinjaScript generated code
namespace NinjaTrader.Indicator
{
public partial class Indicator : IndicatorBase
{
 private CB_PlotToFuture[] cacheCB_PlotToFuture = null; // <-- Anpassen
 private static CB_PlotToFuture checkCB_PlotToFuture = new CB_PlotToFuture(); // <-- Anpassen
 public CB_PlotToFuture CB_PlotToFuture(int period) // <-- Anpassen - alle Parameter; kommagetrennt; keine lokalen Variablen
 {
  return CB_PlotToFuture(Input, period); // <-- Anpassen - alle Parameter; kommagetrennt; keine lokalen Variablen
 }
 public CB_PlotToFuture CB_PlotToFuture(Data.IDataSeries input, int period) // <-- Anpassen - alle Parameter; kommagetrennt; keine lokalen Variablen
 {
  if (cacheCB_PlotToFuture != null) // <-- Anpassen
   for (int idx = 0; idx < cacheCB_PlotToFuture.Length; idx++) // <-- Anpassen
 if (cacheCB_PlotToFuture[idx].Period == period /*&&*/ && cacheCB_PlotToFuture[idx].EqualsInput(input)) // <-- Anpassen - alle Parameter; &&-getrennt; keine lokalen Variablen
  return cacheCB_PlotToFuture[idx]; // <-- Anpassen
  lock (checkCB_PlotToFuture) // <-- Anpassen
  {
   checkCB_PlotToFuture.Period = period; // <-- Anpassen
   period = checkCB_PlotToFuture.Period; // <-- Anpassen
   // Alle Parameter; keine lokalen Variablen
   if (cacheCB_PlotToFuture != null) // <-- Anpassen
 for (int idx = 0; idx < cacheCB_PlotToFuture.Length; idx++) // <-- Anpassen
  if (cacheCB_PlotToFuture[idx].Period == period /*&&*/ && cacheCB_PlotToFuture[idx].EqualsInput(input)) // <-- Anpassen - alle Parameter; &&-getrennt; keine lokalen Variablen
   return cacheCB_PlotToFuture[idx]; // <-- Anpassen
   CB_PlotToFuture indicator = new CB_PlotToFuture(); // <-- Anpassen
   indicator.BarsRequired = BarsRequired;
   indicator.CalculateOnBarClose = CalculateOnBarClose;
#if NT7
   indicator.ForceMaximumBarsLookBack256 = ForceMaximumBarsLookBack256;
   indicator.MaximumBarsLookBack = MaximumBarsLookBack;
#endif
   indicator.Input = input;
   indicator.Period = period; // <-- Anpassen
   // Alle Parameter; keine lokalen Variablen
   Indicators.Add(indicator);
   indicator.SetUp();
   CB_PlotToFuture[] tmp = new CB_PlotToFuture[cacheCB_PlotToFuture == null ? 1 : cacheCB_PlotToFuture.Length + 1]; // <-- Anpassen
   if (cacheCB_PlotToFuture != null) // <-- Anpassen
 cacheCB_PlotToFuture.CopyTo(tmp, 0); // <-- Anpassen
   tmp[tmp.Length - 1] = indicator;
   cacheCB_PlotToFuture = tmp; // <-- Anpassen
   return indicator;
  }
 }
}
}
namespace NinjaTrader.MarketAnalyzer
{
public partial class Column : ColumnBase
{
 [Gui.Design.WizardCondition("Indicator")]
 public Indicator.CB_PlotToFuture CB_PlotToFuture(int period) // <-- Anpassen - alle Parameter; kopmmagetrennt; keine lokalen Variablen
 {
  return _indicator.CB_PlotToFuture(Input, period);  // <-- Anpassen - alle Parameter; kommagetrennt; keine lokalen Variablen
 }
 public Indicator.CB_PlotToFuture CB_PlotToFuture(Data.IDataSeries input, int period) // <-- Anpassen - alle Parameter; kopmmagetrennt; keine lokalen Variablen
 {
  return _indicator.CB_PlotToFuture(input, period); // <-- Anpassen - alle Parameter; kopmmagetrennt; keine lokalen Variablen
 }
}
}
namespace NinjaTrader.Strategy
{
public partial class Strategy : StrategyBase
{
 [Gui.Design.WizardCondition("Indicator")]
 public Indicator.CB_PlotToFuture CB_PlotToFuture(int period) // <-- Anpassen - alle Parameter; kopmmagetrennt; keine lokalen Variablen
 {
  return _indicator.CB_PlotToFuture(Input, period); // <-- Anpassen - alle Parameter; kopmmagetrennt; keine lokalen Variablen
 }
 public Indicator.CB_PlotToFuture CB_PlotToFuture(Data.IDataSeries input, int period) // <-- Anpassen - alle Parameter; kopmmagetrennt; keine lokalen Variablen
 {
  if (InInitialize && input == null)
   throw new ArgumentException("You only can access an indicator with the default input/bar series from within the 'Initialize()' method");
  return _indicator.CB_PlotToFuture(input, period);// <-- Anpassen - alle Parameter; kopmmagetrennt; keine lokalen Variablen
 }
}
}
#endregion NinjaScript generated code

  • Upvote 2
Link to comment
Share on other sites

Nach etwas herumtesten mit dem Code habe ich noch ein paar Bugs gefunden:

futurePlot.Set(period - 1, Convert.ToDouble(null));

bringt nicht das von mir gewünschte Ergebnis. Eigentlich soll diese DataSeries nur in der ChartZukunft gezeichnet werden. Doch setzt man den Plot0 transparent, dann sieht man, dass der futurePlot "unter" dem Plot0 gezeichnet wird. Folgendes schafft hier Abhilfe:

Plot0.Set(SMA(period)[0]);
  for (int i = 0; i <= period + 1; i++)
  {
   double value = i < period + 1 ? SMA(period)[0] : Convert.ToDouble(null);
   futurePlot.Set(i, value);
  }

 

 

Als zweites habe ich die Beispieldaten des SMA() durch welche vom Momentum() ausgetauscht. Dabei ist mir aufgefallen, dass der futurePlot mit negativen Werten Probleme macht. Sobald ich (oder jemand anders??) eine Lösung hat, stell ich sie hier rein.

  • Upvote 1
Link to comment
Share on other sites

Ich hab's gefunden:

Folgende Zeilen unten in der override Plot()-Methode entscheidet:

bool futurePlotHasValue = futurePlot.IsValidPlot(idx) && futurePlot.Get(idx) > 0;
   if (!futurePlotHasValue) { continue; }

Hier werden nur gesetzte und >0 Werte zum plotten freigegeben.

Nicht zu zeichnende Werte werden aber jetzt mit Convert.ToDouble(null) beschrieben. Also sollte obige Zeile einfach mit:

bool futurePlotHasValue = futurePlot.IsValidPlot(idx) && futurePlot.Get(idx) != Convert.ToDouble(null);
   if (!futurePlotHasValue) { continue; }

ersetzt werden, dann geht's auch mit negativen Werten.

 

Eine Frage an jemanden, der sich auskennt: Ist eine 0 mit Datentyp double GLEICH einer null, die ToDouble convertiert ist??

Link to comment
Share on other sites

Jetzt aber: Mit futurePlot.Reset(barsAgo) kann einem Wert, der nicht mehr gezeichnet werden soll, Invalid gesetzt werden:

Plot0.Set(SMA(period)[0]);
  for (int i = 0; i <= period; i++)
  {
   futurePlot.Set(i, SMA(period)[0]);
  }
  futurePlot.Reset(period + 1);

Dadurch muß in der override Plot() nichtmehr auf >0 oder !=null getestet werden, sondern nur noch auf Valid:

if (!futurePlot.IsValidPlot(idx)) { continue; }

 

That's it !! Danke nochmal an Eddy...

Hier jetzt nochmal der komplette (funktionierende) Code:

#region Using declarations
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Xml.Serialization;
using System.Collections;
using System.Collections.Generic;
using NinjaTrader.Cbi;
using NinjaTrader.Data;
using NinjaTrader.Gui.Chart;
using NinjaTrader.Indicator;
using NinjaTrader.Strategy;
#endregion Using declarations
namespace NinjaTrader.Indicator
{
public class CB_PlotToFuture : Indicator
{
 #region Parameters and Variables
 // Parameters:
 private int   period    = 10;
 // Variables:
 private DataSeries futurePlot   = null;
 #endregion Parameters and Variables
 protected override void Initialize()
 {
  Add(new Plot(new Pen(Color.FromKnownColor(KnownColor.Transparent), 1), PlotStyle.Line, "Plot0"));
  Plots[0].Pen.DashStyle = DashStyle.Solid;
  futurePlot = new DataSeries(this, MaximumBarsLookBack.Infinite);
  AutoScale = true;
  ScaleJustification = ScaleJustification.Right;
  Overlay = true;
  BarsRequired = period;
  PriceTypeSupported = false;
  PlotsConfigurable = false;
  CalculateOnBarClose = false;
 }
 protected override void OnBarUpdate()
 {
  #region First Bars in Chart
  if (Bars == null) { return; }
  //if (Data.BarsType.GetInstance(Bars.Period.Id).IsIntraday) { return; }
  //if (Bars.Period.Id == PeriodType.Day || Bars.Period.Id == PeriodType.Week || Bars.Period.Id == PeriodType.Month || Bars.Period.Id == PeriodType.Year) { return; }
  if (CurrentBar <= period) { return; }
  #endregion First Bars in Chart
  Plot0.Set(SMA(period)[0]);
  for (int i = 0; i <= period; i++)
  {
   futurePlot.Set(i, SMA(period)[0]);
  }
  futurePlot.Reset(period + 1);
 }
 #region Properties
 [browsable(false)]
 [XmlIgnore()]
 public DataSeries Plot0
 {
  get { return Values[0]; }
 }
 [browsable(false)]
 [XmlIgnore]
 public DataSeries FuturePlot
 {
  get { return futurePlot; }
 }
 [Description("")]
 [GridCategory("Parameters")]
 [DisplayName("Parameter Nr. 0")]
 public int Period
 {
  get { return period; }
  set { period = Math.Max(1, value); }
 }
 [browsable(false)]
 public new int Displacement
 {
  get { return base.Displacement; }
  set { base.Displacement = 0; }
 }
 #endregion
 #region Override Plot()
 public override void Plot(Graphics graphics, Rectangle bounds, double min, double max)
 {
  // For advanced FillPolygon/brush plotting, see Imp_Ichimoku.cs
  //if ("check for no futurePlot")
  //{
  // base.Plot(graphics, bounds, min, max); // We call base Plot() method to paint defined Plots
  // return;		 // if check for no futurePlot == true to avoid unnecessary calculations
  //}
  List<Point> points = new List<Point>();
  int lastX = -1;
  double lastValue = -1;
  Pen pen = new Pen(Color.FromKnownColor(KnownColor.Red));
  for (int idx = FirstBarIndexPainted - period; idx <= LastBarIndexPainted; idx++)
  {
   if (idx < 0 || idx >= BarsArray[0].Count || (!ChartControl.ShowBarsRequired && idx < BarsRequired)) { continue; }
   if (!futurePlot.IsValidPlot(idx)) { continue; }
   double value = futurePlot.Get(idx);
   int x = ChartControl.GetXByBarIdx(BarsArray[0], idx + period);
   if (lastX >= 0)
   {
 int y0 = ChartControl.GetYByValue(this, lastValue);
 int y1 = ChartControl.GetYByValue(this, value);
 if (points.Count == 0) // We have a start painting
 {
  points.Clear();
  points.Add(new Point(lastX, y0));
  points.Add(new Point(x, y1));
 }
 else
 {
  int pos = points.Count;
  points.Insert(pos, new Point(x, y1));
 }
   }
   // Save as previous Point
   lastX = x;
   lastValue = value;
  }
  if (points.Count > 0 && pen != null)
  {
   SmoothingMode oldSmoothingMode = graphics.SmoothingMode;
   graphics.SmoothingMode = SmoothingMode.AntiAlias;
   graphics.DrawLines(pen, points.ToArray());
   graphics.SmoothingMode = oldSmoothingMode;
   points.Clear();
  }
  pen.Dispose();
  // Paint defined Plots
  base.Plot(graphics, bounds, min, max);
 }
 #endregion Override Plot()
}
}
#region NinjaScript generated code
namespace NinjaTrader.Indicator
{
public partial class Indicator : IndicatorBase
{
 private CB_PlotToFuture[] cacheCB_PlotToFuture = null; // <-- Anpassen
 private static CB_PlotToFuture checkCB_PlotToFuture = new CB_PlotToFuture(); // <-- Anpassen
 public CB_PlotToFuture CB_PlotToFuture(int period) // <-- Anpassen - alle Parameter; kommagetrennt; keine lokalen Variablen
 {
  return CB_PlotToFuture(Input, period); // <-- Anpassen - alle Parameter; kommagetrennt; keine lokalen Variablen
 }
 public CB_PlotToFuture CB_PlotToFuture(Data.IDataSeries input, int period) // <-- Anpassen - alle Parameter; kommagetrennt; keine lokalen Variablen
 {
  if (cacheCB_PlotToFuture != null) // <-- Anpassen
   for (int idx = 0; idx < cacheCB_PlotToFuture.Length; idx++) // <-- Anpassen
 if (cacheCB_PlotToFuture[idx].Period == period /*&&*/ && cacheCB_PlotToFuture[idx].EqualsInput(input)) // <-- Anpassen - alle Parameter; &&-getrennt; keine lokalen Variablen
  return cacheCB_PlotToFuture[idx]; // <-- Anpassen
  lock (checkCB_PlotToFuture) // <-- Anpassen
  {
   checkCB_PlotToFuture.Period = period; // <-- Anpassen
   period = checkCB_PlotToFuture.Period; // <-- Anpassen
   // Alle Parameter; keine lokalen Variablen
   if (cacheCB_PlotToFuture != null) // <-- Anpassen
 for (int idx = 0; idx < cacheCB_PlotToFuture.Length; idx++) // <-- Anpassen
  if (cacheCB_PlotToFuture[idx].Period == period /*&&*/ && cacheCB_PlotToFuture[idx].EqualsInput(input)) // <-- Anpassen - alle Parameter; &&-getrennt; keine lokalen Variablen
   return cacheCB_PlotToFuture[idx]; // <-- Anpassen
   CB_PlotToFuture indicator = new CB_PlotToFuture(); // <-- Anpassen
   indicator.BarsRequired = BarsRequired;
   indicator.CalculateOnBarClose = CalculateOnBarClose;
#if NT7
   indicator.ForceMaximumBarsLookBack256 = ForceMaximumBarsLookBack256;
   indicator.MaximumBarsLookBack = MaximumBarsLookBack;
#endif
   indicator.Input = input;
   indicator.Period = period; // <-- Anpassen
   // Alle Parameter; keine lokalen Variablen
   Indicators.Add(indicator);
   indicator.SetUp();
   CB_PlotToFuture[] tmp = new CB_PlotToFuture[cacheCB_PlotToFuture == null ? 1 : cacheCB_PlotToFuture.Length + 1]; // <-- Anpassen
   if (cacheCB_PlotToFuture != null) // <-- Anpassen
 cacheCB_PlotToFuture.CopyTo(tmp, 0); // <-- Anpassen
   tmp[tmp.Length - 1] = indicator;
   cacheCB_PlotToFuture = tmp; // <-- Anpassen
   return indicator;
  }
 }
}
}
namespace NinjaTrader.MarketAnalyzer
{
public partial class Column : ColumnBase
{
 [Gui.Design.WizardCondition("Indicator")]
 public Indicator.CB_PlotToFuture CB_PlotToFuture(int period) // <-- Anpassen - alle Parameter; kopmmagetrennt; keine lokalen Variablen
 {
  return _indicator.CB_PlotToFuture(Input, period);  // <-- Anpassen - alle Parameter; kommagetrennt; keine lokalen Variablen
 }
 public Indicator.CB_PlotToFuture CB_PlotToFuture(Data.IDataSeries input, int period) // <-- Anpassen - alle Parameter; kopmmagetrennt; keine lokalen Variablen
 {
  return _indicator.CB_PlotToFuture(input, period); // <-- Anpassen - alle Parameter; kopmmagetrennt; keine lokalen Variablen
 }
}
}
namespace NinjaTrader.Strategy
{
public partial class Strategy : StrategyBase
{
 [Gui.Design.WizardCondition("Indicator")]
 public Indicator.CB_PlotToFuture CB_PlotToFuture(int period) // <-- Anpassen - alle Parameter; kopmmagetrennt; keine lokalen Variablen
 {
  return _indicator.CB_PlotToFuture(Input, period); // <-- Anpassen - alle Parameter; kopmmagetrennt; keine lokalen Variablen
 }
 public Indicator.CB_PlotToFuture CB_PlotToFuture(Data.IDataSeries input, int period) // <-- Anpassen - alle Parameter; kopmmagetrennt; keine lokalen Variablen
 {
  if (InInitialize && input == null)
   throw new ArgumentException("You only can access an indicator with the default input/bar series from within the 'Initialize()' method");
  return _indicator.CB_PlotToFuture(input, period);// <-- Anpassen - alle Parameter; kopmmagetrennt; keine lokalen Variablen
 }
}
}
#endregion NinjaScript generated code

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.

Loading...
×
×
  • Create New...