- ago
One of the consultants posted this code below.
CODE:
public override void Initialize(BarHistory bars) { StartIndex = 200; _roc = ROC.Series(bars.Close, 1); _sma = SMA.Series(bars.Close, 200); _rsi = RSI.Series(bars.Close, 2); bars.Cache["roc"] = _roc; bars.Cache["sma"] = _sma; bars.Cache["rsi"] = _rsi; }

Now I know the .Series method caches the indicator in question in the bars object that creates it. But in looking at this code, it appears it's being cached again. Is the true, or am I misunderstanding whats going on here?

I should add that PreExecute() is being called later in this example. I'm assuming the indicator caches created by the .Series method are retained for PreExecute(). If this assumption is incorrect, please correct me.... And tell me why the indicator caches wouldn't be retained in PreExecute().
0
324
Solved
8 Replies

Reply

Bookmark

Sort
Glitch8
 ( 9.00% )
- ago
#2
The Series method and having it cache the indicator was a more recent development in the WL7 framework. It’s possible that the caching code was written prior to this. Or maybe the author was not aware of the Series caching? Finally it’s probably slightly more efficient caching and restoring using the hard coded key rather than constructing the key each time like the Series method does behind the scenes.
1
- ago
#3
One followup question. If you declare the indicators/TimeSeries in the MyStrategy{} block so they are visible for the Indicator and Execute blocks, then is there any point in doing the caching at all? ... whether or not there exists a PreExecute{} block?

I mean, all the indicators and TimeSeries declared in the MyStrategy{} will be visible whether these objects are cached or not. Right?

The only reason to cache something is if it's not declared in the MyStrategy{} block. Right?

QUOTE:
The Series method and having it cache the indicator was a more recent development in the WL7 framework.
I didn't know that. So older examples may include caching when it's not needed.

I do think it follows modern program design best to declare "global" variables in the outer most block so they are automatically visible to the inner blocks without the need for caching as expected.
0
Glitch8
 ( 9.00% )
- ago
#4
You’d typically use caching to retrieve indicators in places like the PreExecute method. You might want to loop through all of the BarHistories in the passed parameter and access cached indicators from each one.

For typical Strategies you’re right, just use the local variables.
1
Best Answer
- ago
#5
QUOTE:
... use caching to retrieve indicators in places like the PreExecute method. You might want to loop through all of the BarHistories in the passed parameter and access cached indicators from each one.
Thanks for correcting me. So PreExecute{} does not have access to variables declared in MyStrategy{}.

So the PreExecute{} block is nested inside UserStrategyBase; therefore, "private" MyStrategy variables are not automatically accessible to it. Now I finally understand the need for caching ... so UserStrategyBase methods can see those objects.

Although offering a programming guide to experienced WL6 users isn't that important, for virgin WL7 users, such a guide is essential for clarifying the role of caching (as a shared global) and such.
0
Cone8
 ( 26.80% )
- ago
#6
The discussion lacks context.

Glitch hit on it in Post #4 -
"Series caching" when creating an indicator avoids recreating the indicator every time it's called. The "key" to that Cache is basically unknown unless you look for it.

The "extra" caching you showed in the example is a convenience to access a specific symbol's indicators in Pre/PostExecute when looping through the participants. These are just references to existing objects, so there's almost no penalty for the "extra" cache, and as mentioned, even if you knew precisely how the key was created to access the existing reference, it's less efficient to recreate that key each time you need it.
0
- ago
#7
QUOTE:
"Series caching" when creating an indicator avoids recreating the indicator every time it's called. The "key" to that Cache is basically unknown unless you look for it.
But if both Initialize{} and PreExecute{} employ indicator.Series(), then neither needs to know the actual key value.

But I think the take home message is to avoid the .Series cache altogether because it's slower than caching it directly for PreExecute{}. And if you can access the indicator exclusively through "local" private variables (like for the Execute{} block), then you don't need caching at all, which reduces your memory footprint.

All the processor cores compete for the same on-chip cache hardware, so if the memory footprint of the problem can be reduced, you speed concurrent execution. (Now you see where I'm going with this.)
0
Cone8
 ( 26.80% )
- ago
#8
Did you just take it out of context again?

Let's be clear. You don't need to cache if you're only accessing a series for the symbol under test - you can get that from a private local variable.

The context is accessing multiple series from participants bar histories. And, the caching reference is just a convenient way to do it. You could do the same thing using a static Dictionary - but it's another operation to create that.

If you have a better way (consider the participants context) please share it!
1

Reply

Bookmark

Sort