- ago
I'm confused. I thought PreExecute{} executed for a given bar, then ran Execute{}, for all stocks, for that particular bar. And that process is then repeated again for the next bar calling both PreExecute and then Execute for the next bar.

However, debug lines are suggesting PreExecute{} runs for all bars first (since its debug output is grouped together without the Execute debug lines). Once that's done, then Execute{} is called for each stock and bar without ever visiting PreExecute again.

Which scenario is correct? (Or are both scenarios somewhat wrong?)
0
359
11 Replies

Reply

Bookmark

Sort
- ago
#1
Naming issue).
0
- ago
#2
QUOTE:
Naming issue.
I'm not sure what naming has to do with this. But if you're wondering, the debug lines are printing scalers that are declared in the MyStrategy block (shared across MyStrategy methods) as "static private". No local debug variables are declared in methods.

But all the PreExecute debug lines are printed first. Then all the Execute debug lines follow. I was expecting them to intermingle grouped by one bar at a time. But that isn't happening.
0
- ago
#3
fyi, on a related note:
https://www.wealth-lab.com/Discussion/Should-symbols-be-executed-synchronously-in-portfolio-backtest-6801
0
- ago
#4
Interesting. So the debug lines are not printed out in the order they execute. I didn't know that. Well, that changes their interpretation.

I do know that variables to be shared between methods have to be declared as "static" in the MyStrategy block. My working "theory" is that PreExecute runs for a given bar, then Execute spawns off many threads for each stock employing the static variables set by PreExecute. But this is only a theory. So the first scenario described in the original question may be correct, and the debug output is reorganized (grouped) by the stock threads. That's tricky.
0
- ago
#5
QUOTE:
'm not sure what naming has to do with this.


I was expecting the same behaviour you were because of method's name. So a kind non intuitive naming I guess.
0
Cone8
 ( 26.65% )
- ago
#6
Just create a static List<string> variable and add your debug output to it. Then in the BacktestComplete() send each string in the list to WriteToDebugLog()
0
Glitch8
 ( 8.38% )
- ago
#7
There's nothing wrong with the naming of the methods, PreExecute in fact does get called before the following successive calls to Execute. The issue is the way WL7 groups the debug strings by symbols, this is not the first time it's caused confusion. I think we should remove that behavior and have the debug strings just presented as they're added, but probably with a symbol prefix so you know which symbol generated each debug string.
0
- ago
#8
QUOTE:
I think we should remove that behavior and have the debug strings just presented as they're added, but probably with a symbol prefix so you know which symbol generated each debug string.
Personally, I kind of like the behavior, but it's unexpected. Perhaps in the debug window it should be documented that the output lines are grouped and don't reflect the order in which they are executed by PreExecute and Execute.

You could also offer a checkbox in the debug window so one could set chronological or grouped-by-instrument ordering.

QUOTE:
... create a static List<BarHistory> variable and add your debug output to it.
I'm already doing that, but I wasn't getting the expected results.

Also, the static List<BarHistory> variable has to be searched in each trading instance, which is inefficient. What I've done instead is save the meritScore of the "tail end" of the List<BarHistory> variable into a "static double" meritScore threshold variable. Now I have a threshold test without searching the List<BarHistory> each time in Execute.
CODE:
public override void PreExecute(DateTime dt, List<BarHistory> participants) {    //for each fund in DataSet, calculate dipBuyMeritScore    foreach (BarHistory bars in participants)    {       //create meritScores and save them in participants List<BuyHistory>.UserData       ...       dipBuyMeritScore = 1 - pctRank[idx];       meritScore = (TimeSeries)bars.Cache["MeritTS"];       meritScore[idx] = dipBuyMeritScore;       bars.UserData = dipBuyMeritScore; //save merit score w/BarHistory instance    }    //sort highest meritScore values where participants[0]    participants.Sort((b, a) => a.UserDataAsDouble.CompareTo(b.UserDataAsDouble));    meritThreshold4Buy = participants[0].UserDataAsDouble; //sample meritScore for top stock    meritThreshold4Hold = participants[4].UserDataAsDouble; //sample meritScore for fifth from the top } public override void Execute(BarHistory bars, int idx) {    regEmaVelSellThreshold = Parameters[1].AsDouble;    TimeSeries meritScore4bars = (TimeSeries)bars.Cache["MeritTS"];    if (HasOpenPosition(bars, PositionType.Long))    {       //sell logic, sell if stock is below threshold       if (meritScore4bars[idx] < meritThreshold4Hold && regEmaVel[idx] < regEmaVelSellThreshold)       {          PlaceTrade(bars, TransactionType.Sell, OrderType.Market, 0, meritScore4bars[idx].ToString(".00=mrtScr"));       }       ...    }    else    {       //buy logic, buy if stock is above or equal to threshold       if (meritScore4bars[idx] >= meritThreshold4Buy)       {          PlaceTrade(bars, TransactionType.Buy, OrderType.Market, 0, meritScore4bars[idx].ToString(".00=mrtScr"));       }    } } //shared strategy variables double regEmaVelSellThreshold; static double meritThreshold4Buy, meritThreshold4Hold;
0
Cone8
 ( 26.65% )
- ago
#9
I like the debug behavior currently too. Maybe, though, an optional chronological output would be useful.
1
Glitch8
 ( 8.38% )
- ago
#10
It's been mentioned a few times, but no #FeatureRequest yet. If anyone really would like to see this option please submit the request.
0
Cone8
 ( 26.65% )
- ago
#11
Okay, it's official now:
https://www.wealth-lab.com/Discussion/A-Chronological-Debug-Output-Preference-6902
0

Reply

Bookmark

Sort