Trading by win rate and profit factor
Author: tradercn
Creation Date: 3/7/2012 3:11 PM
profile picture

tradercn

#1
From Performance Visualizer, just had a sudden thought, but I was stuck at how to get the win rate and profit factor in the past performance of any strategy? For example,based on the strategy, Scalper QQQ & Stocks, I want to trade when average win rate (of past 100 trades) is lower than the average win rate (of past 10 trades), and profit factor is higher than the average profit factor (of past 30 trades). Is there any example strategy for that? Thanks.
profile picture

Eugene

#2
Looks like you and another user (sedelstein) are heading in the same direction:

Access to data/stats normally displayed in the performance tab during a backtest

Basic Question about Position Sizers
profile picture

Eugene

#3
Here's something for you to start with. What this example code does:

1. Loads the pre-built "Moving Average Crossover" Strategy, executing it with default parameters
2. Calculates the win rate of the past 10 closed trades and the win rate of the past 100 closed trades
3. Takes only trades that satisfy this condition: average win rate (of past 100 trades) is lower than the average win rate (of past 10 trades).

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

Eugene

#4
P.S.
QUOTE:
I want to trade when average win rate (of past 100 trades) is lower than the average win rate (of past 10 trades),

Although not exactly what you're looking for, the closest thing is to use either the built-in "Percent Winners" sizing or the "Percent Winners (% Equity)" PosSizer. Available instantly without any coding.
profile picture

sedelstein

#5
Hi Eugene

As you surmised, this is interesting to me.

Do you see any issue with taking the portion of code that generates the closed positions to date

CODE:
Please log in to see this code.


and generating the win/loss percentage for each symbol in the dataset?

put that section below the if {} statements and adding
CODE:
Please log in to see this code.
to the part that generates the list of trades

So take AAPL's trades if the win rate for AAPL is low but not IBM's if the win rate for IBM was high.

Would it take an extraordinarily long time to run or any other issues?
profile picture

sedelstein

#6
Update: It works for small datasets. Large datasets just take forever (and then some). Any thoughts?

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

Eugene

#7
Notes and Limitations
QUOTE:
4. The code that has "equity-trading" rules will run somewhat slower than the original Strategy. This is by design, as the Strategy has to execute another portfolio backtest.
profile picture

sedelstein

#8
I'll probably get in trouble with this but here goes

I want to use this technique above to run a strategy, call it ParentStrategy, which calls ChildStrategy via runDonor to get the equity curve, calculate some statistics based on it to decide whether to take the trades as of a date and perhaps even use SetShareSize to size the trade.

If I want to collect the results from the ParentStrategy, say via the performance engine in MS123 Scorecard, it is possible to create a GrandParent Strategy, and use runDonor to execute the ParentStrategy. Can runDonor in a sense be nested?

thanks for your help

Steve
profile picture

Eugene

#9
I see what you're after but you probably will not get what you looking for. Any visualizer works with a "snapshot" of a Strategy's performance. Consequenntly, the PerformanceEngine class can't be used to calculate some statistics while looping by SystemResults.Positions. It's not going to work. Consider asking further questions on runDonor in other threads started by you, please.

In essence, you're trying to push the limits of Combination Strategies (even though you're not using them for this task). But it would be great if support for conditional execution existed. So a better idea is to call your Fidelity rep and vote for an enhancement like that as a Combination Strategy feature:

Combination Strategy Impressions, Suggestions thread, Eugene 6/22/2011 4:45 AM - it's #3 on my list
profile picture

sedelstein

#10
Thanks Eugene

Conditional Execution would be great to have and not just in combination strategy.

I appreciate your input. I'll probably try coding it and see if it blows up. Worst case is a reboot I guess. ;->)

profile picture

Eugene

#11
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

innertrader

#12
Hi Eugene,

I have been working to repurpose the code from Post #3 above, so I trying to make sure I understand how it works. One thing is confusing me. In the code snippet

CODE:
Please log in to see this code.


What's the reason you put the foreach inside of the for loop? It seems that you are recreating the identical ClosedPositions list with each iteration. Shouldn't this code go before the for loop? Is there something I don't understand about the necessity for it to be where it is?

Robert
profile picture

Eugene

#13
QUOTE:
It seems that you are recreating the identical ClosedPositions list with each iteration.

Right.

QUOTE:
Shouldn't this code go before the for loop?

No. The list of closed positions must be recreated on every bar by its nature.
profile picture

superticker

#14
QUOTE:
It seems that you are recreating the identical ClosedPositions list with each iteration.

That's only because the code you cite in Post# 12 doesn't match the original code in Post# 6. Let's look at the code in Post# 6 again.
CODE:
Please log in to see this code.

Notice the if statement includes p.Symbol == Bars.Symbol, which is omitted in Post# 12. That condition means only closed positions relevant to the current stock selected by the for loop are getting saved into ClosedPositions. If you omitted that condition, then you could place the foreach block outside the for loop.

If your goal is to create a sorted listing of ClosedPositions by stock symbol, you could certainly sort the sr.Positions object instead to avoid the for loop. My "wild guess" is that the default order of the sr.Positions object is already sorted by symbol since they "may be" created that way, but I could be wrong. If that's the case, then you can just skip the sort step and for loop altogether.
profile picture

Eugene

#15
The topic deals with trading by {win rate, profit factor etc.} exclusively. This task implies calculating a rolling ratio based on closed positions on a bar by bar basis. For this reason, nested loops are required in post #3. Much like the Closed equity curve, it's not possible to avoid the for loop in this context.


UPDATE 02/26/2020

Loosely related discussion from this and other topics has been moved into a new thread:

Export a summary of performance stats by symbol programmatically
This website uses cookies to improve your experience. We'll assume you're ok with that, but you can opt-out if you wish (Read more).