Accessing SystemResults
Author: sedelstein
Creation Date: 2/1/2012 1:13 PM
profile picture

sedelstein

#1
I've run a strategy. I'd like to get data that would be displayed normally in a Visualizer written to a .csv file so I can use that data in Excel or other program.

I've downloaded the attachments at http://www2.wealth-lab.com/WL5WIKI/CommunityVisualizersMain.ashx

In the MS123 Scorecard source I see reference to

SystemResults results = performance.Results;
PerformanceEngine pe = new PerformanceEngine(performance, results);

and then further to code like the following

lvi.SubItems.Add(pe.apr.ToString("N2"));

It appears tat the data I want to write is being calculated already and I don't want to reinvent it.

I'm still new to C#. Is there a way to get this data that is written to a visualizer written to a file instead?

profile picture

sedelstein

#2
It looks as if I can use the kb article "Interacting with Equity" to run a strategy


The system results, I can get using

SystemResults results = (SystemResults)GetGlobal( results + "_PerformanceResults" );

the PerfromanceEngine is in PerformanceEngine.cs

I'm not sure where to get performance.Results
profile picture

Eugene

#3
QUOTE:
I'd like to get data that would be displayed normally in a Visualizer written to a .csv file so I can use that data in Excel or other program.

Take a look at the SaveToFile() method from the PVTrades2.cs class. This is the closest thing.
QUOTE:
the PerfromanceEngine is in PerformanceEngine.cs

The PerformanceEngine.cs is not the official API, it's a custom helper class that provides an array of performance metrics to some visualizers and MS123 Scorecard. It's not the place to start with.
QUOTE:
It appears tat the data I want to write is being calculated already and I don't want to reinvent it.

What you will have to reinvent is what the PerformanceEngine class is not calculating.
profile picture

sedelstein

#4
Ok I understand what you are saying

The problem I am having now is in this call

CODE:
Please log in to see this code.


I have sr (the second argument in the call from

CODE:
Please log in to see this code.


but not sure were to get the first argument "perfomance"

Can you help with that specifically so I can access the properties in the PerformanceEngine Object?

Thanks for your patience
profile picture

Eugene

#5
QUOTE:
but not sure were to get the first argument "perfomance"

I guess this is what you're looking for:
CODE:
Please log in to see this code.

profile picture

sedelstein

#6
Yes it seems to do the trick (compiles and runs) and is what I want but the results are odd.
I get a different Sharpe ratio when I run the donor strategy independently than from when I call it from within this code. Is there anything obvious that I'm doing wrong?

CODE:
Please log in to see this code.
profile picture

sedelstein

#7
It might be running a different dataset? Can I tell
CODE:
Please log in to see this code.
a specific dataset to run on?
profile picture

Eugene

#8
QUOTE:
I get a different Sharpe ratio when I run the donor strategy independently than from when I call it from within this code.

This is why this is beta and unsupported.
QUOTE:
a specific dataset to run on?

The code is open source, so feel free to explore and modify!
profile picture

sedelstein

#9
beta and unsupported.

got it.

Can you give me a hint on where I might specify the dataset?

It's the last part of this I think I need.
profile picture

sedelstein

#10
ok, see it in DataSetSymbols
profile picture

Eugene

#11
Good to know that you found it.

And by the way, the Sharpe ratio generally should not match Wealth-Lab figure. As I already told, the PerformanceEngine.cs is a custom helper class. Consequently, the monthly-based Sharpe ratio calculation differs a bit from Wealth-Lab's.
profile picture

sedelstein

#12
Last question for today ;->)

Is there a kb article or help area where I can learn how to manipulate the DataSetSymbols so that I can get this code to work on a particular set of symbols?
profile picture

Eugene

#13
None that I'm aware of.
profile picture

sedelstein

#14
??? so then, how can I specify the dataset it will run on. It seems to have chosen the first dataset in the set of datasets on the right portion of the strategy screen.
profile picture

sedelstein

#15
And if the Sharpe ratio is different, can I access the WL result, say, if I wanted to use it in my first Performance Visualizer?
profile picture

Eugene

#16
QUOTE:
so then, how can I specify the dataset it will run on.

At the risk of repeating myself, did I say it's an unsupported workaround? The solution's source code is open. Follow the code logic, read the comments, and experiment.
QUOTE:
And if the Sharpe ratio is different, can I access the WL result, say, if I wanted to use it in my first Performance Visualizer?

If you can't access it using standard API calls (you can't) then please see this FAQ: Documentation > Is there a documentation for WealthLab.dll class procedures and methods? ;) I guess that you'll have to code it from scratch, like everything else. Fidelity code is closed source.
profile picture

sedelstein

#17
Apologies, I'm not trying to make you repeat yourself, I'm just not as good a programmer



With respect to your comment

"The solution's source code is open."

The source for which routine specifically? I can follow code and logic when I see it but I guess I'm not seeing it or opening up the right source code.

Thanks for your help. I'll struggle with it a bit longer. From what I can tell, I'm 98% there and have to figure out this little bit.

Regards
profile picture

Eugene

#18
In the code you're looking at it's the area of the runDonor method where a List<Bars> is built to be passed on to the TradingSystemExecutor class. There's no way to pass a DataSet.
profile picture

sedelstein

#19
Hi Eugene

I guess I meant a list, as in a list of symbols and not a dataset

CODE:
Please log in to see this code.


Usually I can see some command completion after typing
CODE:
Please log in to see this code.
to see the methods and properties or see the arguments to the methods. Not in this case

Barring that, I went looking for documentation on runDonor and TradingSystemExecutor to see how I can finish this off

It's the final step. Can you offer another hint?

Thanks
profile picture

sedelstein

#20
So it looks like it's in Community.Components
and I have to unzip the attachment and see.
Getting closer
profile picture

sedelstein

#21
Ok, I see that I need to send runDonor a strategy name and a Bars object.

How do I set the Bars object to be the Bars of say, symbol = IBM ?

profile picture

sedelstein

#22
CODE:
Please log in to see this code.


Sets the Bar object and then I call
CODE:
Please log in to see this code.


But the code seems to run all of the symbols (count = 328) in another list

profile picture

Eugene

#23
For application in single symbol mode, the runDonor method is overloaded. Read the code Steve, it's documented with inline comments - and good luck with your venture.

Good news. An age-old issue of the "Interacting with Equity Curve" technique has been that generated equity curves can be different from the actual equity curves. In particular, this difference could be striking with stop/limit orders. I finally found a solution to this problem and will include it in the next release of Community Components (March 2012). Finally, then we will consider it out of beta!
profile picture

Eugene

#24
sedelstein asked:

QUOTE:
Hello Eugene

I have a question related to this but if it's in the wrong topic or requires a different post, please move it accordingly.

I am interacting with the equity curve as above and want to get the individual results for each symbol in a dataset.

I created two datasets, one call ONE_SYMBOL_ONLY and another called THREE_SYMBOLS and ran the code below once for THREE_SYMBOLS and 3x for ONE_SYMBOL_ONLY with each time containing only 1 of the 3 symbols in it.

The code prints out the number of positions it found via PrintDebug();

In the first case, running THREE_SYMBOLS I got
symbol = FCX sr.Positions.Count 24
symbol = HSP sr.Positions.Count 19
symbol = NLSN sr.Positions.Count 5

CODE:
Please log in to see this code.

QUOTE:

In the second case I got

symbol = FCX sr.Positions.Count 24
symbol = HSP sr.Positions.Count 18
symbol = NLSN sr.Positions.Count 4

different numbers. Is there some global variable I should be resetting or is there something fundamentally wrong.

I'd really appreciate your help on this

Steve
profile picture

Eugene

#25
Different numbers are normal. If you read the online help file, you'll notice three paragraphs dedicated to explaining what happened (in the middle):

WealthScript Techniques | Interacting Dynamically with Portfolio Level Equity
profile picture

Eugene

#26

sedelstein replied:
QUOTE:

Yes, I understand that part but EVEN radically different NUMBER of trades??

In one case, I get 7 trades over a time period and in stand alone mode, I get 2

Ideally, I think the stand alone mode (e.g. say bringing up MA X-over as in this example) is correct and if that came up with 2 trades, I'd like to use that.

I am certainly going to do a deep dive on
Wealth-Lab User Guide, Strategy Window > Backtesting Strategies > How Trades Are Chosen and QuickRef entry for Position.Priority.


Will the position priority settings enforce the result desired?

Thanks again
profile picture

Eugene

#27
The easiest way is to check "Use Worst Trades in Portfolio Simulation". If that fixes the trade count and position sizing for you, you've got the explanation. Otherwise let me know and if I have free time, I'll try to take a look.
profile picture

Eugene

#28
sedelstein replied:

QUOTE:
Well, even with that worst case box checked and a simple strategy such as the prepackaged moving average crossover it still gives different results ( I also closed WL and restarted)


When in 3 symbol data set

symbol = FCX sr.Positions.Count 24
symbol = HSP sr.Positions.Count 19
symbol = NLSN sr.Positions.Count 5


Each individually

symbol = HSP sr.Positions.Count 18
symbol = NLSN sr.Positions.Count 4


Here the differences are only one trade and in these cases the trades are small relative to the starting portfolio size.
The differences are bigger in other strategies

I tried
string myStrategyName = "R2 Strategy";
and
string myStrategyName = "ActiveTrader 2010-07|Improved R2 Strategy";

though on these cases I get

Error processing symbol HSP Object reference not set to an instance of an object.

If and when you get time, please take a look. I've spent 2 pretty full days looking at it.

Regards
profile picture

Eugene

#29
I guess you're not resetting the global variable properly between runs. Look up ClearGlobals in the QuickRef.
profile picture

sedelstein

#30
Hi Eugene

I really think there is something else going on.

This time I edited the code so that before the call to runDonor it looks like this

CODE:
Please log in to see this code.


So the Globals should be cleared

I now tried running with the pre-packaged strategy Darvas Box

CODE:
Please log in to see this code.


Running the ONE_SYMBOL_ONLY dataset 3x each with the following symbols gives results consistent with running Darvas Box by itself

symbol = HSP sr.Positions.Count 18
symbol = AAPL sr.Positions.Count 32
symbol = NLSN sr.Positions.Count 4

Running on THREE_SYMBOLS gives

Error processing symbol AAPL Basis price for Position entry cannot be zero
symbol = AAPL sr.Positions.Count 32

and the code stops

Removing AAPL from the dataset gives

Error processing symbol HSP Basis price for Position entry cannot be zero
symbol = HSP sr.Positions.Count 18


So there is something not obvious going on. I can't make out anything suspicious with my code.


I'll keep looking for a workaround. I tied encapsulating the part that calls runDonor in another object and returning a SystemResults object but that failed as well. runDonor is an incredibly useful too. I hope there is a solution


profile picture

sedelstein

#31
Not to beat a dead horse but to bolster the argument a bit.
I've tried the canned strategy "Two Bar Breakout" as well. 7 positions in standalone and ONE_SYMBOL dataset, 14 when run in a MSB
profile picture

sedelstein

#32

SOLVED ????

I changed the code and changed true to false

CODE:
Please log in to see this code.


I'm happy that it seems to work. Will certainly test it more

I'm curious as to why.

Any thoughts?

profile picture

sedelstein

#33
But...

Still getting

Error processing symbol "XXX" Object reference not set to an instance of an object.

where XXX = the first symbol in the dataset
profile picture

sedelstein

#34
Checking again this a.m.

Still different (true / false) isn't it. There's something else going on.
profile picture

Eugene

#35
To be frank, by now you already know more than me about this technique working in a DataSetSymbols loop because I haven't even considered this.
profile picture

sedelstein

#36
QUOTE:
by now you already know more than me about this technique


Perhaps.

I'm not wedded to the dataset loop or any other method. I'm after the result that when I run a strategy on it's own rather than through the runDonor method, that I get consistent results.

The code above is reasonably short and I would have thought it easy to figure out what was going on. It apparently isn't that easy. If you can suggest a different method to achieve the goal stated above, I'm happy to try it.

profile picture

Eugene

#37
Changing true to false in GetExternalSymbol makes sense because in this setup, you don't want to synchronize with the clicked symbol.

"Object reference..." in this context is a one-time or an intermittent error that usually goes away after reloading Strategy window or restarting WL. I have seen it occasionally but it wasn't something 100% reproducible.
profile picture

sedelstein

#38
Hello Eugene

When running runDonor as below

CODE:
Please log in to see this code.



I get a number of properties, one of which is
CODE:
Please log in to see this code.


I can then do something with them

CODE:
Please log in to see this code.



I notice there is another property
CODE:
Please log in to see this code.


Is there a way to do a foreach on just the open properties? I didnt see a collection for that. Is there one available?

Thanks

profile picture

sedelstein

#39
there's an extraneous gsp.Result.... after the paren. It's a typo cut/paste error
profile picture

sedelstein

#40
foreach on just the open positions?
profile picture

Eugene

#41
OpenPositionCount represents the historical DataSeries that powers the Open Positions overlay on the Equity chart. Keep in mind: visualizers run after a Strategy has finished executing. All positions appear closed (even open), there can be no alerts.
profile picture

sedelstein

#42
Ok. I dont really get what youre saying. I will think hard on it.

So for now, can you confirm that if I want to see (within my Execute method) which positions in he position collection are open, I have to test each position to see if it is active (as per the code snippet above)?
profile picture

Eugene

#43
Open positions as of Bars.Count-1 are:
CODE:
Please log in to see this code.


What I'm trying to say is that there are no "ActivePositions" analogue for each bar of the historical backtest results in SystemPerformance.

profile picture

sedelstein

#44
got it.

I only need the ones that are active on the last bar e.g. Bars.Count-1, the "currently" open positions.

so I think this will work.

profile picture

sedelstein

#45
I think that part of my problems are resulting from inactive symbols and then the code not generating an error message

Is there a way within the Execute method to ensure that a symbol is active? do you just compare the date series with say the current date (or some internally defined WL last valid data date)
profile picture

sedelstein

#46
This is strange but is real

I have a large dataset > 1500 symbols.

If I break it up into parts and run the parts (stand alone mode, no runDonor or meta strategy) everything runs fine. I get alerts and open positions (in the Open Positions tab) that seem reasonable.

If I run the strategy on the whole data set, alerts are ok but the Open Positions tab shows zero positions.

Any ideas?
profile picture

Eugene

#47
Guesswork, but maybe some sign of low memory and a ListView problem. A combination of many enabled visualizers, inappropriate data range, insufficient RAM and memory-hungry code like runDonor work towards that.
profile picture

Eugene

#48
Important note to the users of the PerformanceEngine class (internal, unsupported part of the MS123 Visualizers library):

The information regarding PerformanceEngine calling conventions provided across the forum before is actual as of the library version 2012.05.1 and earlier. In future versions, the syntax will most likely undergo a breaking change due to a complete rewrite of the PerformanceEngine class.
profile picture

aykuts

#49
Hi,

I downloaded and installed the community.component from the website in a bid to run strategies programatically and retrieve the performance results of the donor strategy, again with the help of c# codes.

- First, I found the following link (http://www2.wealth-lab.com/WL5WIKI/Default.aspx?Page=kbInteractingWithPortfolioEquity)
- And, copied the example code presented at this link,
- Compiled it with no issues,
- And got certain results (such as NetProfit)

However, when I opened the very same strategy itself, set the strategy with exactly the same date and position sizing setup, the results that I got from the first method (i.e. through c# code that uses the runDonor method) were completely different with that of the the second method.

Acknowledging that the second set of numbers are obviously the right set of numbers, it appears that my runDonor based code runs ok, but what i retrieve from this code is not the actual/correct values.

To help you:
First approach and respective code:
This is (what I call the runDonor code) that calls a preset strategy (that is already saved as xml):
CODE:
Please log in to see this code.


And, PrintDebug returns
CODE:
Please log in to see this code.




Second approach and correct performance results: The picture attached to this post shows the performance result of the same strategy.
(i.e. manually open strategy>click one ticker > get results > open and see results at the performance tab)

As you have seen, what runDonor approach returns as NetProfit is not the same with the what I see on this performance tab.

What am I missing here?

Thanks in advance for your interest and help. It is highly appreciated.

Aykut Saribiyik




profile picture

Eugene

#50
A difference will appear in situations when your system produces different results in each backtest run due to an insufficient funds condition (i.e. not enough money to take all trades). In other words, whenever there are skipped trade(s) and no Priority assigned, a difference is almost inevitable. To avoid that, your system must be either correctly assigning a value to the Position.Priority property AND/OR the option "Use worst trades in Portfolio Simulation" has to be activated in Wealth-Lab's Preferences dialog > "Backtest Settings".

Less important may be the impact of customized commission plan (if activated in Wealth-Lab's Preferences). The solution currently can only use its default settings, ignoring whatever customized Commission settings are set.

Lastly, I did my best to match the numbers but sometimes the solution just can produce results slightly different from actual backtesting results.

profile picture

aykuts

#51
Hi Eugene,

2 or, 3 quick questions:

Q1- Regarding your reference to `default settings`:
I changed the commission calculation methodology from `FIDELITY`to `PERCENT TRADE VALUE` with a certain commission rate at the time I purchased the license (as what fidelity charges to its client is far different both in terms of methodology and amount than what I actually pay here).

So, Does your `default settings` mean `THE FIDELITY option` or, does the term refer to `whatever I configured and saved as my preferences` ?

As you might have noticed, I dont touch to commission rates or anything while calling runDonor. So, If your answer is `default = fidelity setup` , then, that would explain the difference between what i expect (after commissions) and what the runDonor returns (after commissions).

Q2- Win rate:
How can I get the win rate of all trades from the performance results? (I recall that this issue was raised at some thread but i could not find it within the forum posts. But I know it is out there somewhere).

Q3- Better utilization of the forum's search feature:
I dont know whether it is me or the forum's search capabilities, but I cant return relevant posts whenever I try to search the forum from the search bar. Lots of results appear for a second or so, then, they disappear and only a few (and mostly the irrelevant posts) remain as the search result. As a test, I type `Neuro` to the search bar, and maybe one of most valuable posts, 'Neuro-Lab Performance Evaluation Script' from LenMoz doesnt show up. Anyway, skipping my search inabilities for the moment; could you please provide me, some (more) relevant links of previous posts regarding this runDonor examples - so that I can allocate my limited time for not trying to find the keyword but rather for reading and learning from the relevant material :-).

Thank you once again.

Aykut
profile picture

Eugene

#52
QUOTE:
So, Does your `default settings` mean `THE FIDELITY option` or, does the term refer to `whatever I configured and saved as my preferences` ?


In this regard, you can freely change the commission plan but not its own settings i.e. even if you customize the % commision, the Equity Interaction solution will internally execute your backtests with the default settings.

QUOTE:
How can I get the win rate of all trades from the performance results?


Trading by win rate and profit factor
Access Performance Metrics in Code

QUOTE:
Q3- Better utilization of the forum's search feature:


Much like explained here, utilize Google for full-text search: How to search for my own posts?
profile picture

aykuts

#53
Hi Eugene,

Regarding the commission rate:

Testing many alternatives of the same strategy using code via runDonor approach is a great tool in terms of both accuracy and efficiency, yet, the outcome of such test would mean nothing if the applicable commission rates (while performing this test manually and in an automated fashion via code) differ substantially.

For those who might end up at this post regarding this issue; the best work-around would be:
1. Eliminate commission calculations from the back-testing (File > Preferences > Apply no commissions)

2. Code the commission costs explicitly within the strategy (e.g. com_cost = close * 0.0015)

3. Whenever there is transaction, modify the Position.EntryCommission and Position.ExitCommission properties as follows;
(e.g. when the strategy generates a Buy signal: Buy-price would (be close, in parallel, p.EntryCommission would be set as = close*comm_rate')
(e.g. when the strategy generates an exit signal: Selling price would be Close [bar], and p.ExitCommission my by set as Close*comm_rate.

4. That way,
- whatever the manual strategy runs produce would not deviate much from whatever the runDonor loops would generate;
- the comm_costs would be included into the calculation in a realistic fashion
- most statistics (particularly the win rate) would be true

Thanks a lot.