I'm "attempting" to stack (I mean superimpose) six scatter plots in ScottPlot, but only the last AddScatter plot in the outer For loop is plotted. So what's my stupid mistake in the code below?
I should add that I copied ScottPlot's stacked scatter plot examples (both of them) into WL Cleanup{} and they worked perfectly. So it's not an install problem with my system. The figure below shows the last plot in the outer For loop that gets returned without the previous other five superimposed.

What's weird is that the legend shows all six plots present. but only the sixth one is actually visible. Strange. How come both of ScottPlot's stacked AddScatter examples work in Cleanup{} and my code doesn't? Could it have something to do with me using an (outer) For loop where ScottPlot's examples do not? Is there a plt.AddScatter() scoping problem?
In the ScottPlot examples, plt.AddScatter() and plt.SaveFig() are in the same scoping {block}. But should that even matter if "plt" is declared--only once--in the outermost block?
CODE:
public override void Cleanup(BarHistory bars) { if (ExecutionDataSetName == null) //only plot stats in single-symbol mode { Plot plt = new ScottPlot.Plot(600,450); plt.XAxis.TickLabelNotation(multiplier: true); //use engineering notation plt.Title("Price change vs Volume"); plt.XLabel("Volume"); plt.YLabel("% Price change"); double[] xVol = new double[6], yPriceChg = new double[6]; List<Position> positions = GetPositions(); //foreach (Position pos in positions) for (int posIdx = 0; posIdx < positions.Count; posIdx++) { Position pos = positions[posIdx]; int preBuyBar = pos.EntryBar-1; //WriteToDebugLog(string.Format("{0:00.00}=close {1:0.00}=diff {2}=vol {3}=preBuyBar", bars.Close[preBuyBar], bars.Close[preBuyBar] -bars.Close[preBuyBar -1], bars.Volume[preBuyBar], preBuyBar)); for (int barOut = 0, barIn = pos.EntryBar-2; barOut < yPriceChg.Length && barIn < bars.Count; barOut++, barIn++) { xVol[barOut] = bars.Volume[barIn]; yPriceChg[barOut] = bars.Close[barIn] - bars.Close[barIn-1]; } plt.AddScatter(xVol, yPriceChg, label: preBuyBar.ToString()); } plt.Legend(); plt.SaveFig(@"C:\Users\mehl\Desktop\priceChgVsVolume.png"); } }
I should add that I copied ScottPlot's stacked scatter plot examples (both of them) into WL Cleanup{} and they worked perfectly. So it's not an install problem with my system. The figure below shows the last plot in the outer For loop that gets returned without the previous other five superimposed.
What's weird is that the legend shows all six plots present. but only the sixth one is actually visible. Strange. How come both of ScottPlot's stacked AddScatter examples work in Cleanup{} and my code doesn't? Could it have something to do with me using an (outer) For loop where ScottPlot's examples do not? Is there a plt.AddScatter() scoping problem?
In the ScottPlot examples, plt.AddScatter() and plt.SaveFig() are in the same scoping {block}. But should that even matter if "plt" is declared--only once--in the outermost block?
Rename
QUOTE:
What's weird is that the legend shows all six plots present. but only the sixth one is actually visible.
Which simply means they all contain the same values as the last one.
QUOTE:I don't follow. There are six separate positions and the legend is showing the start bar of each of all six separate positions. That aspect is working correctly.
Which simply means they all contain the same values as the last one.
But each position (of six) should be plotting six separate points for a total of 36 points. We should be seeing six groups (of different colors) of six points each; 6x6=36 pts total. That's not happening.
Note we have a double nested For loop and that produce six groups of six points each. But only the last group (of six points) is being plotted. Why is that?
Would it be helpful if I printed out all 36 different points from the six groups (six positions)? I could post that.
Because bars is the same. Shouldn't this be like...
CODE:
xVol[barOut] = pos.Bars.Volume[barIn]; yPriceChg[barOut] = pos.Bars.Close[barIn] - pos.Bars.Close[barIn-1];
I think both lines below are referring to the same BarHistory.
There's only one stock involved here in single-symbol mode, so there's only one possible BarHistory. (Were you thinking there were six different BarHistory's?)
Would it be helpful if I posted six figures of the six different positions (with their six points each) all from this one stock? The problem is I can't superimpose them like I want to.
I'm plotting the price-vs-volume pair of a couple bars just prior and just after the buy (six points in all) for each position purchased. And this stock was purchased six times over the Data Range. Only one stock is involved, which is ADNT, but any stock should reproduce this problem.
My goal here is to determine if the price-vs-volume behavior prior to the buy somehow reveals the price behavior after the buy. So I'm trying to compare points just before and after each buy. Each position will have six points interconnected by a different color as depicted by the legend.
CODE:The first one is referring to the BarHistory passed in by Cleanup{}. The second one is referring to the BarHistory pointed to by "pos". But both are the same BarHistory.
xVol[barOut] = bars.Volume[barIn]; xVol[barOut] = pos.Bars.Volume[barIn];
There's only one stock involved here in single-symbol mode, so there's only one possible BarHistory. (Were you thinking there were six different BarHistory's?)
Would it be helpful if I posted six figures of the six different positions (with their six points each) all from this one stock? The problem is I can't superimpose them like I want to.
I'm plotting the price-vs-volume pair of a couple bars just prior and just after the buy (six points in all) for each position purchased. And this stock was purchased six times over the Data Range. Only one stock is involved, which is ADNT, but any stock should reproduce this problem.
My goal here is to determine if the price-vs-volume behavior prior to the buy somehow reveals the price behavior after the buy. So I'm trying to compare points just before and after each buy. Each position will have six points interconnected by a different color as depicted by the legend.
After a while, I finally figured out the fundamental problem with the AddScatter() call. The X and Y arrays are passed into this call by reference (pointer) as in:
Now if someone can spot a behavioral difference from the positions that made money (the solid lines) from those that lost money (the dotted lines), please let me know.
CODE:although the documentation does not suggest this and this design is somewhat against how C# programs are typically architected. However, because these arrays are passed by reference, these arrays cannot be changed (after calling AddScatter) until the plot is finally rendered; otherwise, that plot will be lost. Although there are several possible workarounds, if one wants to call AddScatter() in an outer For loop, the only realistic option is to use a two-dimensional jagged C# array (which isn't actually jagged in this case) for passing the X and Y arrays into AddScatter. And that's the solution given below.
plt.AddScatter(ref xVol, ref yPriceChg); //However, AddScatter does *not* modify these arrays as the "ref" prefix would suggest
CODE:The resulting plot below plots six PriceChange-vs-Volume points as groups (of different color) for six different positions taken for the ADNT stock. Those bar positions that made money are connected with solid lines; whereas, those bar positions that lost money are connected with dotted lines. The bar points prior to each buy are plotted with diamonds; the bar depicting the day of the buy is plotted with an asterisk; and the bars after the buy are plotted with a small dot. The legend lists the buy date for each of the six positions traded.
public override void Cleanup(BarHistory bars) { if (ExecutionDataSetName == null) //only plot stats in single-symbol mode { Plot plt = new ScottPlot.Plot(700,500); plt.XAxis.TickLabelNotation(multiplier: true); //use engineering notation plt.Title("Price change vs Volume for " + bars.Symbol); plt.XLabel("Volume"); plt.YLabel("Price change"); List<Position> positions = GetPositions(); double[][] xVol = new double[positions.Count][], yPriceChg = new double[positions.Count][]; for (int posIdx = 0; posIdx < positions.Count; posIdx++) { Color plotColor = plt.GetNextColor(); Position pos = positions[posIdx]; xVol[posIdx] = new double[6]; yPriceChg[posIdx] = new double[6]; //plot 6 point per position for (int barOut = 0, barIn = pos.EntryBar-2; barOut < yPriceChg[posIdx].Length && barIn < bars.Count; barOut++, barIn++) { xVol[posIdx][barOut] = bars.Volume[barIn]; yPriceChg[posIdx][barOut] = bars.Close[barIn] - bars.Close[barIn-1]; if (barOut == 2) plt.AddPoint(xVol[posIdx][2], yPriceChg[posIdx][2], plotColor, 10, MarkerShape.asterisk); else if (barOut < 2) plt.AddPoint(xVol[posIdx][barOut], yPriceChg[posIdx][barOut], plotColor, 12, MarkerShape.openDiamond); } plt.AddScatter(xVol[posIdx], yPriceChg[posIdx], plotColor, lineWidth: (pos.ProfitPercent > 3.0) ? 2F:1F, lineStyle: (pos.ProfitPercent > 3.0) ? LineStyle.Solid:LineStyle.Dot, label: bars.DateTimes[pos.EntryBar].ToString("MM/dd/yy")); } plt.Legend(); plt.SaveFig(System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), @"priceChgVsVolume.png")); } }
Your Response
Post
Edit Post
Login is required