View Full Version : Plotting text -> Y = price, X = time...
funk101
05-23-2007, 07:11 PM
I would like to plot X according to time. On NT charts, X = time as:
07:30, 14:00, etc. Time[0] = mm/dd/yy hh:mm:ss. If I do ToTime(Time[0]) I get 73000, 140000, etc. Do I need to dig to a lower level and format to 07:30, 14:00 or is there some method/function available in NinjaScript to do this, or are NT charts smart enough to do the conversion. For instance:
graphics.DrawString("myString", textFont, textBrush, Time[0], Close[0], stringFormat);
I've tried the above, doesn't work, but I've tried this:
protected override void OnBarUpdate()
{
if (CurrentBar == 0){
Plot0.Set(0);
thisX = 0;
thisY = 0;
}
else
{
Plot0.Set(Close[0]);
}
}
public override void Plot(Graphics graphics, Rectangle bounds, double min, double max)
{
if (Bars == null)
return;
// Default plotting in base class. Uncomment if indicators holds at least one plot.
base.Plot(graphics, bounds, min, max);
// this var is needed for calc'ing height
// we just need any text here to init height
SizeF heightVal = graphics.MeasureString("Height", textFont);
//
stringFormat.Alignment = StringAlignment.Near;
textBrush.Color = Color.Black;
//thisX = bounds.X+90;
//thisY = bounds.Y;
thisX = ToTime(Time[0]);
thisY = (float)Close[0];
//
graphics.DrawString("hello", textFont, textBrush, thisX, thisY, stringFormat);
}
and I get the out of bounds error again...
"Error on plotting indicator...Please check the 'Plot' method: Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index"
Hmm, please point me in the right direction. :)
NinjaTrader_Ray
05-23-2007, 07:40 PM
You can't access series data such as Time[] or Close[] etc... from the Plot() method. That's what is giving you the error. I realize you would not have known this partly because we do not currently provide support for overriding the Plot() method and it is not documented.
What you should do is create variables that are assigned in the OnBarUpdate() method and then access these variables within the Plot() method.
funk101
05-23-2007, 08:00 PM
I understand, and I'm not getting the error, and I've changed it to:
thisX = bounds.X and thisY = Plot0[0], which gives me the Close[0], however, Y is now 1530(ie: ES) and the indicator bounds.Y = 640, so it appears that "my" Y is WAAAAAAAY off the map. Hmm, can I tell the indicator to utilize the Price model for Y values somehow? or do I have to jump thru hoops to equate it?
NinjaTrader_Ray
05-24-2007, 08:20 AM
You have to do some math...
int y = (int) ((bounds.Y + bounds.Height) - ((price - min) / (max - min)) * bounds.Height);
funk101
05-24-2007, 12:43 PM
Why am I getting this out of bounds error again?
"Error on calling 'OnBarUpdate' method for indicator, on bar0. Index was outside the bounds of the array." I don't understand, I thought I had the appropriate "checks" in place. Please check my code:
protected override void OnBarUpdate()
{
if (CurrentBar == 0)
{
//Plot0.Set(0);
Plot1.Set(0);
vol.Set(0);
Up.Set(0);
Down.Set(0);
Neutral.Set(0);
}
else
{
//Print("new "+newSlope+" old "+primary);
newSlope = (Volume[0] - Volume[1]) / (ToTime(Time[0]) - ToTime(Time[1]));
vol.Set(newSlope);
study = SMA(vol, 6)[0];
primary = vol[1]+vol[0];
//Plot0.Set(primary);
Plot1.Set(study);
if (newSlope > primary)
{
Up.Set(primary);
image = new Bitmap(imagePath+"thumbsUp.gif");
myOperator = ">";
}
else if (newSlope < primary)
{
Down.Set(primary);
image = new Bitmap(imagePath+"thumbsDown.gif");
myOperator = "<";
}
Neutral.Set(primary);
DrawHorizontalLine("L", Low[1], Color.Yellow);
}
}
NinjaTrader_Ray
05-24-2007, 12:49 PM
Hi,
I don't see anything that pops out at me. You will have to debug it by adding some Print() statements to see where in the code the error is.
funk101
05-25-2007, 01:04 AM
I had it working after your first reply, I come back next day, and voila! Not working. I didn't change anything. It's just a calc of the slope of volume from one bar to next. It works when I don't try and paint the multi-colored MA. Green for up, Red for down, etc. If I just do Plot0/Plot1 (Plot0 is the actually raw values, which is a faster line, and Plot1 is an SMA(6) of Plot0's values, smoothed line).
And now I rewrote it using the wizard, and I'm getting this new error:
Error on calling the 'OnBarUpdate' method for indicator ... on bar 2: Parameter is not valid.
I've debugged, it's something I can't see! First of all, when I Print(CurrentBar) I *always* get 0. I guess, 'cause it's failing as soon as the indicator starts maybe?
protected override void Initialize()
{
Add(new Plot(Color.Orange, PlotStyle.Line, "UpTick"));
Add(new Plot(Color.Green, PlotStyle.Line, "DownTick"));
Add(new Plot(Color.DarkViolet, PlotStyle.Line, "Neutral"));
Add(new Plot(Color.Firebrick, PlotStyle.Line, "MovAvg"));
CalculateOnBarClose = false;
Overlay = false;
PriceTypeSupported = false;
vol = new DataSeries(this);
}
/// <summary>
/// Called on each bar update event (incoming tick)
/// </summary>
protected override void OnBarUpdate()
{
Print(CurrentBar);
if (CurrentBar == 0)
{
UpTick.Set(0);
DownTick.Set(0);
Neutral.Set(0);
MovAvg.Set(0);
}
else
{
//Print("new "+newSlope+" old "+primary);
newSlope = (Volume[0] - Volume[1]) / (ToTime(Time[0]) - ToTime(Time[1]));
vol.Set(newSlope);
Print(vol[0]);
study = SMA(vol, 6)[0];
primary = vol[1]+vol[0];
MovAvg.Set(study);
if (newSlope > primary)
{
UpTick.Set(primary);
image = new Bitmap(imagePath+"thumbsUpTick.gif");
myOperator = ">";
}
else if (newSlope < primary)
{
DownTick.Set(primary);
image = new Bitmap(imagePath+"thumbsDownTick.gif");
myOperator = "<";
}
else
{
Neutral.Set(primary);
}
DrawHorizontalLine("L", Low[1], Color.Yellow);
}
}
funk101
05-25-2007, 01:23 AM
Now it's actually running, not Plotting any lines, getting the same error as previous post, but it's Printing where it's supposed to in the if/elseif/else conditions:
if (newSlope > primary)
{
Print("UP");
UpTick.Set(primary);
image = new Bitmap(imagePath+"thumbsUpTick.gif");
myOperator = ">";
}
else if (newSlope < primary)
{
Print("DOWN");
DownTick.Set(primary);
image = new Bitmap(imagePath+"thumbsDownTick.gif");
myOperator = "<";
}
else
{
Print("NEUTRAL");
Neutral.Set(primary);
}
That is a step forward, at least those Prints() are outputting, but still no plots, just a blank green panel. No name or anything.
What doesn't help is the *vagueness* of the output to log. "...on bar 2: Parameter is not valid." What parameter?? Ya know?
funk101
05-25-2007, 04:02 AM
It worked for a while then got this error.
Error on plotting indicator 'MyVolSlope'. Please check the 'Plot' method: Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index
This makes no sense to me. How could it work for a moment then just fail??
protected override void OnBarUpdate()
{
if (CurrentBar == 0)
{
MyVol.Set(0);
Plot0.Set(0);
}
else
{
newSlope = (Volume[0] - Volume[1]) / (ToTime(Time[0]) - ToTime(Time[1]));
MyVol.Set(newSlope);
Plot0.Set(MyVol[0]);
DrawHorizontalLine("L", Low[1], Color.Yellow);
}
}
This works, it doesn't let me plot different colors for up tick, or down. Once I start testing -> if (MyVol[0] > MyVol[1])...
That's what it doesn't like. It's basically saying "there is nothing in MyVol[1]"
Oy, I'm about ready to put my fist thru the monitor :)
NinjaTrader_Dierk
05-25-2007, 05:03 AM
- the problem is in the Plot method and not the OnBarUpdate method (see error message)
- we do not provide support for custom Plot() methods (as Ray pointed out below)
- hint: I suggest applying try..catch.. blocks in the Plot() method to isolate the case of the trouble (see any C# language reference for details on try/catch)
funk101
05-25-2007, 01:07 PM
Ok, thanks for the tip. It was, as usual, goofy and an oversight on my part. The try/catch blocks helped me to get there. Thanks for staying with me on this one :)
NinjaTrader_Ray
05-25-2007, 01:25 PM
Great, glad you were able to figure it out...