I seem to be running afoul of series operations again...
I have a piece of code that loops through all the symbols in the Dataset. It calculates a new series (Port) based on the Close of the current symbol, and it plots the series for the charted symbol:
CODE:
Please log in to see this code.
I've printed out the values of Port as I calculate them, and they're correct. In the code above you can see I also print out the values of Port and APort right before charting them. The code as shown above plots APort properly, but it plots bogus values for Port -- I haven't yet figured out where the bogus values come from. The plot doesn't match the value I printed right before the PlotSeries statement!!
But if I uncomment the second Port = new DataSeries line, it works as it should.
Help!?
Gary
Size:
Color:
The first Port has a non-variable Description, so APort never changes after the first calculation, despite looping through all the symbols. The commented Port has a unique Description, so APort is re-calculated for each symbol. In other words, APort doesn't return the same series from the Bars cache for every symbol in the second case.
Size:
Color:
But... APort **DOES** get calculated properly, whether I do the variable Port or not. It gets correct (different) values for each symbol. It plots correctly.
And Port also gets calculated properly. I print out the values and they're correct. The PrintDebug **right before** the plot shows the correct values. But the plot in the very next statement plots DIFFERENT values. !??
Size:
Color:
Well, I guess I'm wrong then. Where are the values coming from that are being plotted? You should be able to determine that.
Size:
Color:
I haven't been able to figure it out yet. Part of the difficulty in tracking this down is that the *values* in Port are exactly what they should be -- i.e. it doesn't seem to be a calculation error in my code -- but that's not what's getting plotted. I don't know how to figure out what's actually getting plotted.
Do you have any idea what might cause a print statement to print different values than the values that get plotted in the very next statement?? For example, here is an exact excerpt from my code:
CODE:
Please log in to see this code.
For the stock I happen to be testing, Port and APort print values around 8167 and 8190. Those values match the last-10-bar printout I do earlier in the code. But the plots for Port and APort end with
48832 and 8190!!
!?!?!??
Size:
Color:
QUOTE:
48832
Looks like
GetExternalSymbol is finding an intraday symbol.
Size:
Color:
?? Obviously that made sense to you but it doesn't to me. :-)
How would GetExternalSymbol have any effect on the calculated values in Port? Or, rather, the incorrect plotting of the calculated values in Port?
48832 was just the ending value. It started at an initial value of 10000 on 3/16/2007, and spent most of its time between 10k and 20k until shooting up after 11/5/2009. Whereas APort (which should be tracking Port, and DOES track the calculated values of Port that I print out) starts at 10k, gets as high as about 10400, then declines to the 8000 range.
EDIT: FWIW I just ran this thing in the Visual Studio debugger. I set a breakpoint on both PlotSeries statements. I verified that, immediately before PlotSeries was called, AND immediately after the PlotSeries returned, the end value of Port was 8167. But the plot had an end value of 48832.
PlotSeries seems to be grabbing a random series out of the aethers.
Size:
Color:
QUOTE:
?? Obviously that made sense to you but it doesn't to me. :-)
Disregard my comment. I was looking at "...[Stock.Count-1] ... [Stock.Count-1]", thinking that
GetExternalSymbol hitting data in a different bar scale, while you're pointing to the
Port value, not the indexer.
QUOTE:
PlotSeries seems to be grabbing a random series out of the aethers.
Note! PlotSeries - as other cosmetic chart methods - starts working when a strategy has finished executing.
Size:
Color:
And *THAT* appears to be an important part of the problem. I just tried modifying the code to remove ALL changes to Port after I did the PlotSeries -- and voila, it plotted correctly.
So even though I sent a known specific series to PlotSeries, it did NOT actually plot that series. It plotted whatever values happened to be left over in the series when the strategy finished. Out of curiosity, is this "interesting" cosmetic-chart behavior documented somewhere?
Furthermore, it does not appear to work to "save" a series for later use, as I initially tried. I saved ChartPort and ChartAPort (e.g. ChartPort = Port), and then plotted them at the end of the strategy. But that apparently just saves a pointer to Port and APort, because it worked the same as when I did the plots in the "if (sym == ChartSymbol)" section -- i.e. it plotted whatever happened to be in Port instead of what "should have been" in the "saved copy" in ChartPort.
I tried plotting "Port + 0.0" instead of Port, and that worked. Apparently that makes a temporary copy of the series expression, AND it apparently makes a new copy each time you use it. Maybe I should save it with "ChartPort = Port + 0.0" and place the PlotSeries at the end of the strategy, since that's when it's going to run anyway.
I've programmed in dozens of languages for over 35 years, including 4 or 5 trading-platform languages, and I've *never* run into as many time-eating minefields as I do in WLScript. Series in particular have mysterious behind-the-scenes semantics that are not at all clear to me, and as far as I can tell they're not documented anywhere. It seems to be "WL Lore" that you can only learn from painful experience. It's not safe to assume that "normal" programming techniques will work anything like they do with non-series data types. Any time I get mysterious unexplainable behavior, I have to start guessing what series "feature" I've run into this time. Makes programming in WL **SOO** enjoyable. NOT.
I would find it very helpful if all of these behaviors were clearly documented, with lots of examples of what to do and what not to do. I'm sure I wouldn't be the only one.
Size:
Color:
QUOTE:
Out of curiosity, is this "interesting" cosmetic-chart behavior documented somewhere?
It's been around since I don't know when. Maybe version 3? Robert, please correct me if I'm wrong.
QUOTE:
Furthermore, it does not appear to work to "save" a series for later use, as I initially tried.
Please see the
Bars.Cache property in the QuickRef, and especially Robert's remark above.
Yes, what you get is only a pointer when trying to save a series this way. Data series are cached inside the Bars.Cache, and recognized by their unique key that is the Description property.
Size:
Color:
"It's been around" is another way of saying "it's WL Lore that you can only learn from painful experience." Just because it's been that way for a long time doesn't mean it makes sense to anyone who doesn't already understand it. That's what documentation is for.
Size:
Color:
You keep changing the contents of the single object reference to the Port DataSeries before the series is actually rendered for plotting. By creating a new DataSeries (different objects with unique descriptions), you're sure to plot the object that you intended to plot.
PlotSeries logically must render after script execution (you can't plot anything in the script if you don't process the script first), it's not WL lore, and, Wealth-Lab didn't invent the way object references work.
Size:
Color:
Robert, I agree the WL model is self-consistent and seems logical once you understand the details of how it's implemented. You and Eugene understand WL better than almost anyone, and you've used it extensively for many years, so of course it makes perfect sense to you.
But you have to remember that not everyone understands WL's internal workings as well as you do. That understanding of exactly how & why it does things, the specific ways it applies standard things like object references and the ways it influences your programming, **IS** WL lore. Nobody starting out with WL is going to automatically have that knowledge, regardless of their experience with other platforms and other languages. If you want actual users to be able to use this stuff successfully, it would make sense to explain it to them.
I've starting using WL, and dropped it, at least 3 times in the last 10 years. Partly that was because I disagreed with some of the design choices in the product, which you could dismiss as personal tastes. Partly it's the hundreds of hours I waste fighting against mysterious behaviors (often caused by those design choices) -- vastly more than I've run into in ANY other environment. But partly it's frustration with the attitude I run into too often: "*I* understand it, so it's obviously intuitively clear to the casual observer, so we're not going to bother documenting it anywhere." Which causes me to waste those hundreds of hours. It's crazy-making. :-(
Size:
Color: