Position Priority: LimitPriorityLong, SetTimeOfDayPriority, IntradayFillPriorityEstimate
Author: avishn
Creation Date: 12/16/2009 9:36 PM
profile picture

avishn

#1
I have a daily strategy with high exposure (high/spiking number of entry signals). Limit entry orders. It is my understanding that there are three options to test it in portfolio mode -

* Random position priority (default)... Does not give repeatable results (duh!)
* "Priority=Close[bar]" seen in many code samples on this forum... Makes results repeatable but less realistic (gives preference to higher priced stocks)
* Worst case scenario portfolio setting... Unrealistic (I know, I know), though useful as a reality check, but NOT for strategy comparison/fine tuning.

I'm trying to estimate which limit orders will realistically be hit first. Without dropping to the intraday data level, which brings a whole new set of performance and data size limit issues, I've came up with the following --

If we assume that the closer the limit price to the open, the more likely it is to be hit, we can set the priority to
CODE:
Please log in to see this code.
(reverse of distance, smaller distance gives higher priority). This needs to be normalized to volatility somewhat, so the final formula looks like this:
CODE:
Please log in to see this code.


I'm wondering if anybody else experimented with something like that and if results can be considered more or less reliable for sufficiently large values of X (bars, stocks). Is there possibly a better approach?

EDIT: I do realize that this is peeking. I think it should be fine, since it is used only to make testing results more realistic.

EDIT2 (12/27/09): Much more accurate estimate can be achieved for long limit entries with
CODE:
Please log in to see this code.

... where p is limit price. This gives quick and dirty approximation (compare to the results of the 100% accurate TimeOfDay method below which requires intraday data). Useful when scanning large data sets.

EDIT3 (3/8/2010): See updated version below in the post from 3/8/2010 (IntradayFillPriorityEstimate)
profile picture

Cone

#2
QUOTE:
I'm trying to estimate which limit orders will realistically be hit first.
The right way to do it for Limit entry orders is by assigning the Position Priority using time of day. In Version 4, we had the TIntraDay study that provided that ability. Unless Eugene has already done it, we need to work on this for v5. Your poor-man's guesstimate is probably sufficient for the task though.

But look, this is fine just to see "what could have been", but it's just a single simulation that will never repeat in the same order again. Random is the right way go if you're evaluating your Strategy, and to that end, you should be looking at the Monte Carlo Visualizer, new for 5.6.
profile picture

avishn

#3
Thank you.

It appears that TIntraDay tool is exactly what I would need. Also it seems it would help with the "limit exit at profit target unless stop loss is hit on the same bar" scenarios, which usually are very difficult to analyze through backtesting on daily data.

I'm curious what are the mechanics behind TIntraDay study in WL4? I guess it requires presence of intraday data for the same symbol. Anyways it would probably be different in WL5...

Yes, I'm looking into Monte-Carlo randomization now. I understand that to get closer to the true mean and variance of the returns I will need to randomize and resample the data. For me "what could have been" approach is interesting from the initial trade signal screening perspective to filter out signals and parameters which would definitely not work.
profile picture

Eugene

#4
QUOTE:
I'm curious what are the mechanics behind TIntraDay study in WL4? I guess it requires presence of intraday data for the same symbol.

For sure. Intraday datasource is required.
QUOTE:
I'm wondering if anybody else experimented with something like that and if results can be considered more or less reliable for sufficiently large values of X (bars, stocks). Is there possibly a better approach?

btw, another approach and some V4 code to help with the "what hit first" scenarios:

Bouncing Tick & Ordering of Fills
profile picture

avishn

#5
I guess I need to bring this issue up again.

Let's take BasicHiLoLimit strategy by DrKoch, or any other strategy which generates high number of limit entry orders for almost every bar. Testing it as is, without the position priority set, gives grossly incorrect (too optimistic) results. The reason being is that with the limit buy order, when the stock gaps down, we're guaranteed to get an execution at the open, which in most cases would be very unfavorable for that kind of a strategy (bottom fishing).

Let's say we have 20% equity position sizing, 1,000 signals for the given bar and 50 of those stocks gap down. In real life we're guaranteed to get 100% of our 100%/20%=5 maximum available executions from that pool of 50 gaped down stocks. However, without the priority set, the chances to enter one of those unfavorable trades are being reduced by WL to only 50/1,000=0.5%. More than that, the same problem persists even when using MonteCarlo trade randomizer, because, again, the trades will be selected randomly from the pool of 1,000 trade signals without any respect to what could've/should've happened if trade signals from that pool of 1,000 were executed in real life for sufficiently high number of trade sequences.

I understand that the problem have been discussed before, but I don't think there's any reliable solution available at the moment. I'm not sure how the prevously mentioned TIntraDay works in terms of all memory and I/O overhead and if we can get that solution available any time soon...

I was thinking that one way to fix it without switching to intraday data would be to generate and store some additional information along with each daily bar. Essentially what we need is a sequence of new alternating highs and lows for every day with timestamps, something like
09:30 LOW 15.10
11:30 HIGH 16.75
14:00 LOW 15.05
...in addition to your standard OHLC and Volume. In most cases there would be just a handful of additional data points for each bar.

The problem is that kind of data is not available from Fidelity, and even though the algorithm to extract it is very simple, I'm not sure how to generate it on the fly when needed (or when downloading the data update). Again the idea being that we don't want to suck all of the intraday data into memory when backtesting just to answer the question which stock dropped to the limit price first.

EDIT: This is what a yearly profit probability chart looks like for the slightly modified (single position per symbol) HiLoLimit strategy:


Chance of break even is 98.90%... Sign me up!

At the same time, an informal estimate of unfavorable trades outside of MonteCarlo tool gives the chance of break even somewhere below 50%.


profile picture

Cone

#6
QUOTE:
The problem is that kind of data is not available from Fidelity
Sure it is, back to April 2004. You can create these data from 30-min intraday bars.

But if you want accuracy, the TIntraday-type solution is the way to go. It doesn't make sense to me to put effort anywhere else.
profile picture

avishn

#7
Is there any ETA on the solution you're describing? If not, I guess I can write something for the time being and share it here... Hopefully with some more or less intelligent caching. The only question is how do I access intraday data for the current symbol from daily strategy in WL5?
profile picture

Cone

#8
ETA: a few minutes. I think this will be really easy in v5.
profile picture

Cone

#9
Well, there's always something that hangs you up when you get started on something new.. no exception this time. But here you go, with an example. Be sure to read the comments for the TimeAtPrice function.
CODE:
Please log in to see this code.
profile picture

avishn

#10
Awesome! Much appreciated.
profile picture

Cone

#11
Consider that a proof of concept. There's a better way to get this done in a single procedure call at the end of the script.
profile picture

Cone

#12
Here's another shot at a more robust method. Once it's vetted, maybe we can get Eugene to massage it into the 2010.1 Community.Components update. Then it's just a matter of calling the SetTimeOfDayPriority method after the trading loop.

A couple nice features of this version:
1. It can tell if you're missing a day of intraday data, and,
2. If a trade doesn't "cross" in the intraday data, the trade likely occurred due to a spike in the EOD bar. Here, this information is output to the debug window.

Finally, make sure to follow the guidelines in the comments.

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

Eugene

#13
QUOTE:
Once it's vetted, maybe we can get Eugene to massage it into the 2010.1 Community.Components update.

Great, will do.
profile picture

Eugene

#14
Included. Thanks you guys for this helpful contribution.
profile picture

avishn

#15
I'm seeing some strange behavior when using SetTimeOfDayPriority-instrumented strategy in optimization over a date range (this is important).

First of all, minimal code snippet to reproduce the problem (based on http://www2.wealth-lab.com/WL5WIKI/LimitOrderPriority.ashx) --

CODE:
Please log in to see this code.


When I run the strategy it works fine and generates some trades. It works fine for "Most Recent 1 Year" as well as an arbitrary "Date Range" setting.

Now, in the beginning of the strategy I've added a parameter. It does not do anything, it just can take values of 0 and 1 (the specifics of the strategy parameter(s) are not important here). Now when I run optimization over "Most Recent 1 Year" I get back 2 optimization results (since the parameter can have 2 possible values) with some trades, nothing particularly interesting. But, when I do optimization over any "Date Range" (let's say 1/1/2008 to 1/1/2009), I get back no trades in any of the optimization results. It appears like the call to SetTimeOfDayPriority causes strategy to lose any position data. Why?

As a side note, I've double checked and I do have enough of 5 min historical data to support the selected date range.

EDIT: If I comment out this --
CODE:
Please log in to see this code.

optimization starts working (i.e. generating trades) over any date range.
profile picture

Eugene

#16
Robert, could you take a look please?

I too have checked this setup in both WLP and WLD, different intraday providers, 30/60-min data to support priority, loaded a year of data starting from 1/1/2009 to 12/31/2009, had two optimization runs with the same numbers as when executing the strategy normally. In other words, I was unable to reproduce.
profile picture

avishn

#17
In the SetTimeOfDayPriority source code above (from Community.Components), in the following section --
CODE:
Please log in to see this code.


...shouldn't it be High, i.e.
CODE:
Please log in to see this code.

in the second code branch?

(This is unrelated to the problem I've posted earlier on Jan 29)
profile picture

Eugene

#18
The code was created by Robert, this week he's not around, so I'd suggest bumping it up later.
profile picture

Cone

#19
Good catch avishn. The first if statement checks when the Low is at or below the basis price to trigger BuyAtLimit or ShortAtStop orders. Conversely, the second if statement should check if the High is at or above the basis price for ShortAtLimit or BuyAtStop orders.

Eugene, please make that correction for your next update. tia.
profile picture

Eugene

#20
Done. Thanks Andrew.
profile picture

avishn

#21
In case anybody is interested... Updated intraday fill priority estimate, now includes both long and short as well as limit and stop order support. Replaces the old LimitPriorityLong method from the first post in this thread.

CODE:
Please log in to see this code.

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

Eugene

#22
Thank you, will update Community.Components.
profile picture

Eugene

#23
kribel asked:

I read the Setting Priority for AtStop/AtLimit Orders article.

I still have a few questions about this.

1) How does LimitPriorityLong() calculation work? Is it OpenSource? If yes, where can I get the code?
2) Is there a method LimitPriorityShort()?

Many Thanks!

07nioe asked:

QUOTE:
As I assume it is not possible to use the LimitPriorityLong for Alerts, right?
profile picture

Eugene

#24
Guys, I've moved your questions to the more suitable thread. Let's neither create new threads nor use an unrelated Strategy's thread and focus on LimitPriorityLong here where it has begun. Thanks.

kribel,

1) It's part of Community Components, an open source project.
2) No.

07nioe,

What's the problem with this approach?

CODE:
Please log in to see this code.