Gap Fill Strategy
Author: jschneir
Creation Date: 3/31/2016 1:16 PM
profile picture

jschneir

#1
Hello,

I'm new to the wealth lab and was hoping I could get some help with coding. I've not coded with C# before, but I'm proficient in SQL and have at least been able to work my way around VB Script before.

My strategy is fairly simple that I'm trying to create:

If the stock gaps X% Up from yesterday's close, short at the market open
Or
If the stock gaps X% Down from yesterday's close, buy at the market open
Place a trailing stop at X% from yesterday's close or a market order at the end of the day

The second iteration of this strategy would be to do the same thing, but do it with options, where you buy a put or a call.

What I'm having trouble working is getting the code to buy the same day, and then create the stop orders based on movements intraday. If I use the Gap functions within the prebuilt items then it appears to buy the next day, not the current day. I'm also not sure if it can look at daily closes, but also place orders based on one minutes bars (different time frames).

I've been able to at least test this strategy in excel using historical data, but I would like to get it into wealth lab and then add the options component.

Jordan

profile picture

Eugene

#2
Welcome to the forums Jordan.

QUOTE:
If I use the Gap functions within the prebuilt items then it appears to buy the next day, not the current day.

That's right, with the built-in rules you'll have trouble buying on the bar where a gap has happened. It's possible to "unlock" the code and edit it to suit your needs. Here's a couple of of design patterns to backtest gaps:

1. Gap Strategy: Buy on 3% gap (simple, backtest only, no Alerts for live trading)
2. Looking to implement a gap strategy (valid for live trading, slightly more complex due to its use of GetSessionOpen)

QUOTE:
I'm also not sure if it can look at daily closes, but also place orders based on one minutes bars (different time frames).

Of course this (and vice versa) is possible. For example, here's how you can get the daily close using SetScale* methods:

Intraday / Multi-Time Frame | Compressed price series alignment

QUOTE:
The second iteration of this strategy would be to do the same thing, but do it with options, where you buy a put or a call.

See "Options" in the QuickRef (F11 key inside WLP).
profile picture

jschneir

#3
Hello,

I was sort of able to manipulate the drag and drop data to create what I wanted, but I'm not completely there. Right now it appears to buy and sell the same day when a gap is created, assuming the gap is >X%, which is the first step. However, I can't figure out how to put in the multi-time frame information to get it to create a sell or cover order at the close price of the previous day that is executed somewhere during that day.

I've listed the code I'm working with below. Also, I've started reading up on C#, but I'm unfamiliar what exactly "double" is. I see it in a lot of code, but don't understand it entirely.


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

Eugene

#4
QUOTE:
I've listed the code I'm working with below. Also, I've started reading up on C#, but I'm unfamiliar what exactly "double" is. I see it in a lot of code, but don't understand it entirely.

You'll find an answer quickly after following a pointer in this FAQ: How do I start with C# ?

QUOTE:
I was sort of able to manipulate the drag and drop data to create what I wanted, but I'm not completely there.

Nice attempt but there's a number of problems with your script. First, it will not generate entry alerts. Next, it sells in the past which can not happen. Also, dsGapPctDn and dsGapPctUp seem to be calculated incorrectly (a 0.02% and 0% gap consequently - did you mean 2%?)

Having said that, I stress that a good idea is to start with an existing design pattern - like Cone's code that I already referenced in my reply #2 to you above. The code below inherits from it. To elaborate on "don't code what you can beg, borrow or steal", feel free to explore a number of premade strategies downloadable straight from Wealth-Lab's "Open Strategy" dialog. Example: TASC 2016-04 | Trading Gap Reversals (Calhoun)

This code works on EOD (daily) bar scale:
CODE:
Please log in to see this code.
profile picture

Cone

#5
Looks like you can use a hand here.

Never, never execute a Market, Limit, or Stop order on "bar" (unless you're doing something unrealistic, or for testing). This should invariably be bar + 1.

Notes:
1. The helper function "this.FirstBarofDay(2)" requires that you install the Community.Components extension. Click for more info for Intraday helper functions

2. There's really no realistic was to get the opening price and enter a Position at that price (you can do it unrealistically if you want). Consequently, entries will always be on the second bar of the day.

3. Run the script with intraday data (any interval).

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

jschneir

#6
Thank you both.

Eugene - I actually did mean 0.2%. My theory is that gaps of a large enough size, but smaller than another will fill same day. I've been able to at least work through and test this in excel with historical daily data.

Cone - Thank you for your help, as you can tell I'm new at this, but I will learn quickly. You noted that I should never execute at bar. I assume based on what I've read that bar refers to the current bar being reviewed, which contains the OHLC/V. What would happen exactly if I tried to execute a trade at this? Does it just fail due to not having data within it?
profile picture

Eugene

#7
QUOTE:
What would happen exactly if I tried to execute a trade at this?


Here's what's going to happen:

* Wealth-Lab Wiki > The Dangers of Looking Ahead (Peeking) in Trading System Development
* WealthScript Programming Guide > Programming Trading Strategies > Peeking
profile picture

jschneir

#8
Thanks for all the help. I've adjusted the code a bit and it works as I would have expected now. Results are pretty close to what I expected, though it's having some issues with system memory when I try to run it back a ways:


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

Eugene

#9
QUOTE:
having some issues with system memory

You're using 32-bit WLP (ticket 27112) which isn't suitable for large DataSets of intraday data. To avoid out of memory exceptions, switch to 64-bit WLP if supported by your operating system.
profile picture

jschneir

#10
Thanks that helps out.

Also, is there a way to do a trailing buy order?

Jordan
profile picture

Eugene

#11
QUOTE:
Also, is there a way to do a trailing buy order?

QuickRef (F11 key) for BuyAtStop.
profile picture

Cone

#12
Re: your parameter values/range edits - e.g. _stoppct = CreateParameter("Stop %", 0.2, 1, 5, 0.01);

The first number is the default value. It should be enveloped by the next two numbers, the start and stop values. The last number is the step value.

If you're actually optimizing, then you are over-optimizing with steps of 1/100th of a percentage. More runs = more memory required. If you're looking for only 0.2% as a loss, for example, then something like the following makes more sense for the parameter range: 0.2, 0.1, 0.75, 0.05. Same argument for all three parameters.

profile picture

jschneir

#13
I've been working on my strategy code and gotten pretty far with where I'm wanting to go with it. I'm trying to figure out how to define a range based on the first 2 periods of time. The strategy is that when a gap occurs in price, given certain parameters, you short/buy the stock as long as it's creating a "U" shaped pattern (or it's inverse). What I'm trying to really create is a stop that is defined by the highest/lowest point in the first 2 bars.

My assumption is that I have to store that value into some constant and then refer to that constant within the code as to whether it's been reached or not (similar to a limit price). However, every attempt I've made to try to store that value does not appear to work.


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

Eugene

#14
The 2 first bars since when?
What's a "U" shaped pattern?
profile picture

jschneir

#15
Sorry, the U shape I'm referring to is the pattern created where by if you were to chart he time frame, for example from a gap down, it would open, start to move lower, flatten out, and then reverse back towards the opening price, with a goal of entering if the it breaks the high of the range.

The first two bars would be the first two opening bars of the day.


I've been working with a 15 minute time frame. The idea is that on the third bar, you enter at the market with a buy or as long as the first bar closed lower than the open, the second bar closed higher than the high of the first bar, and you create a stop at the low of the first two bars (this is for the long. The reverse sequence would be if you went short).

Since I'm not skilled enough yet to create ranges based on smaller time frames I'm trying to make the parameters simple and based on a fifteen minute time frame.

profile picture

Eugene

#16
Here's your 2-bar range (of the first two opening bars of the day):

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

jschneir

#17
Thank you that really helps me to understand how to store these values!
profile picture

jschneir

#18
I'm struggling a bit to get the code to work. For right now I'm trying to get the code to say:

Using the highest value from the first two bars of the day, set a stop limit at that value for trade. The code appears to be compiling correctly, but I'm stuck on how to store those values either before I get to the 3rd bar, or once I get to the 3rd bar, and then use those as stops. I know why the current code below isn't exiting at the stops listed, because it's only trying to do this at the 3rd bar. But I'm not sure how to get the Highs and Lows of the first two bars stored so that when it goes through the loop it retains those so it can use them as stop limits:

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

Eugene

#19
That's an inconvenient approach, also with the lowprice/highprice being defined erroneously. But there's a simpler way. Save your stop loss level after making sure a Position has been established. You can use the Position object's RiskStopLevel, AutoProfitLevel or Tag properties, for example. When exiting, exit at that level. Here's on-the-fly code snippet illustrating the concept:

Entry:
CODE:
Please log in to see this code.


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

jschneir

#20
Eugene,

Is there a best practice then for the order for entering and exiting? The initial code I worked with did exits first before entries, but this appears to indicate doing entries before exits.
profile picture

Eugene

#21
The order isn't inversed. I placed the entry snippet on top just to highlight the RiskStopLevel assignment. From a logical standpoint, it's counterintuitive to see how you'd use a new property that you may have not learned yet. In your code the exit should still precede the entry. Sorry for the confusion.
profile picture

jschneir

#22
Not a problem I appreciate it, and I'm trying to learn all the best practices.
profile picture

jschneir

#23
I incorporated the snippets into my code, but noticed that the trades were not stopping correctly at either the previous close, or the risk level. I've listed the code below as well as a screen shot of where it failed. I thought if I incorporated the dayClose[bar] into the Min/Max functions that that would work, but it didn't seem to either:

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

Eugene

#24
Try following my example precisely:
CODE:
Please log in to see this code.


What you're doing breaks the link:
CODE:
Please log in to see this code.
profile picture

jschneir

#25
I see what I did, works perfectly now
profile picture

jschneir

#26
Hello,

I've been looking through the results and though the code appears to be working most of the time, it seems to be triggering an exit early with respect to the stop levels. I've tried to adjust the Math.Max/Min code to account for 3 bars instead of 2. In the attached picture it appears to be triggering an exit order early. Is the code incorrect or is my understanding of the data incorrect? I'm using the SPY as the data set with 10 min intervals.

Bar 0 High: 201.88
Bar 1 High: 201.62
Bar 2 High: 201.57
Bar 3 High: 201.66 (Short initiated)
Bar 4 High: 201.75 (Short is covered too early)

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

jschneir

#27
I figured out the error in using limits instead of stops and corrected it.
profile picture

jschneir

#28
Hello,

I'm working with the SetScaleDaily, which initially is being used to determine the O/H/L/C of a particular bar. The remainder of the code works on the one minute data. I'm trying to run a test whereby it runs the strategy if the has been a lower high for each of the previous 3 days. When I write the code the difficulty I'm encountering is that once the scale has been restored to the normal one minute interval, I'm not sure how to access the highs of daily values.

How can I adjust the code to reference the high points of previous days while in the code looking at one minute data?

As the code initiates on bar == 0, I've attempted to compensate for the time frame issue by using calculations of bar-390 and bar-780, however I'm thrown an error:
Runtime Error: Index was out of range. Must be Non-negative and less than the size of collection
at WealthLab.Strategies.jschneirgaps.Execute()
at WealthLab.DataSeries: get_Item (Int32 i)
at System.ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument argument, ExceptionResource resource)

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

Eugene

#29
QUOTE:
As the code initiates on bar == 0, I've attempted to compensate for the time frame issue by using calculations of bar-390 and bar-780,

Don't do anything like "bar-390 / 780" again. Not only you're violating the index boundaries (as your code still starts from day #2) but are not considering the risk of certain days not having 390 1-min bars.

QUOTE:
I'm trying to run a test whereby it runs the strategy if the has been a lower high for each of the previous 3 days

Hint: you could use the CumDown indicator or in this case simply start processing the main loop on day #3:
CODE:
Please log in to see this code.

Consequently, the entry block becomes something like this if my understanding is correct:
CODE:
Please log in to see this code.
profile picture

jschneir

#30
Eugene,

So I like the concept of the CumDown indicator. If my current bars are using a 1 Minute time series, how do I have the CumDown measure on a daily time frame?

Effectively I'm trying to create a strategy that trades off one minute patterns (sometimes 5 minute), but use a mix of one minute/ 5 Minute patterns/indicators and daily indicators to evaluate whether to execute the trade or not.
profile picture

Eugene

#31
Have you tried to get your existing code running first?
profile picture

jschneir

#32
Eugene,

I have, below is actual code I'm working with (though at times it does throw an unhandled reference error, but it seems to come and go):

CODE:
Please log in to see this code.



Part of the reason I asked the original question in another forum is I conceptually get how to switch from one time frame to another. What I don't understand is how to reference previous periods while in a different time frame.

For example:

Within my current code I understand that the following is taking the bars object and rolling up the information to the daily scale from the minute/5 minute scale, etc:


CODE:
Please log in to see this code.


I've also referenced the following on the Wiki:
Intraday / Multi-Time Frame | Mixing intraday and daily data

I'm just not sure how to reference previous periods (say 3 days ago) using this item. You had mentioned using the CumDown function. I had been able to at least insert it into my code and compile it, but received an Index Out of Range Error (My guess being that when it starts on the first bar of the first day it can't look back 3 days and then throws an error). My attempt was as follows:

CODE:
Please log in to see this code.


I then attempted a PrintDebug(cumuldown[bar]) just to see if it worked (which it did not).
profile picture

Eugene

#33
QUOTE:
I have, below is actual code I'm working with

I fail to see where you've integrated any of my suggestions from post #29. Anyway, let's see if we can approach it from a different side:

QUOTE:
I'm just not sure how to reference previous periods (say 3 days ago) using this item.

Follow the GetWeeklyBar example in this KB article:

GetIntradayBar and the similar functions

Here's some on-the-fly code (untested):
CODE:
Please log in to see this code.
profile picture

jschneir

#34
Eugene,

I think I understand how this is working. So effectively we create a new dataseries object that is the "Bars" represented at a Daily Scale. We then can use this object when we look at the daily information we've gathered previously in the other DataSeries objects we created of the daily highs, lows etc.

Thus, when we reference the dayHigh[gdb -1] it is actually referencing the daily object we created CompBar, which was synchronized with the GetDailyBar.

Let me know if I misstated.
profile picture

Eugene

#35
Jordan,

Your understanding is correct.