I had to wrap up Part -1 rather quickly and probably didn’t get my ideas across, completely. Here is what we did in Part – 1.
used my function to locate the First Notice Date in crude
used the same function to print out exact EasyLanguage syntax
chose to roll eight days before FND and had the function print out pure EasyLanguage
the output created array assignments and loaded the calculated roll points in YYYMMDD format into the array
visually inspected non-adjusted continuous contracts that were spliced eight days before FND
appended dates in the array to match roll points, as illustrated by the dip in open interest
Step 6 from above is very important, because you want to make sure you are out of a position on the correct rollover date. If you are not, then you will absorb the discount between the contracts into your profit/loss when you exit the trade.
Step 2 – Create the code that executes the rollover trades
Here is the code that handles the rollover trades.
// If in a position and date + 1900000 (convert TS date format to YYYYMMDD), // then exit long or short on the current bar's close and then re-enter // on the next bar's open
if d+19000000 = rollArr[arrCnt] then begin condition1 = true; arrCnt = arrCnt + 1; if marketPosition = 1 then begin sell("LongRollExit") this bar on close; buy("LongRollEntry") next bar at open; end; if marketPosition = -1 then begin buyToCover("ShrtRollExit") this bar on close; sellShort("ShrtRollEntry") next bar at open; end;
Code to rollover open position
This code gets us out of an open position during the transition from the old contract to the new contract. Remember our function created and loaded the rollArr for us with the appropriate dates. This simulation is the best we can do – in reality we would exit/enter at the same time in the two different contracts. Waiting until the open of the next bar introduces slippage. However, in the long run this slippage cost may wash out.
Step 3 – Create a trading system with entries and exits
The system will be a simple Donchian where you enter on the close when the bar’s high/low penetrates the highest/lowest low of the past 40 bars. If you are long, then you will exit on the close of the bar whose low is less than the lowest low of the past 20 bars. If short, get out on the close of the bar that is greater than the highest high of the past twenty bars. The first test will show the result of using an adjusted continuous contract rolling 8 days prior to FND
This test will use the exact same data to generate the signals, but execution will take place on a non-adjusted continuous contract with rollovers. Here data2 is the adjusted continuous contract and data1 is the non-adjusted.
Still a very nice trade, but in reality you would have to endure six rollover trades and the associated execution costs.
Here is the mechanism of the rollover trade.
And now the performance results using $30 for round turn execution costs.
Now with rollovers
The results are very close, if you take into consideration the additional execution costs. Since TradeStation is not built around the concept of rollovers, many of the trade metrics are not accurate. Metrics such as average trade, percent wins, average win/loss and max Trade Drawdown will not reflect the pure algorithm based entries and exits. These metrics take into consideration the entries and exits promulgated by the rollovers. The first trade graphic where the short was held for several months should be considered 1 entry and 1 exit. The rollovers should be executed in real time, but the performance metrics should ignore these intermediary trades.
I will test these rollovers with different algorithms, and see if we still get similar results, and will post them later. As you can see, testing on non-adjusted data with rollovers is no simple task. Email me if you would like to see some of the code I used in this post.
When I worked at Futures Truth, we tested everything with our Excalibur software. This software used individual contract data and loaded the entire history (well, the part we maintained) of each contract into memory and executed rollovers at a certain time of the month. Excalibur had its limitations as certain futures contracts had very short histories and rollover dates had to be predetermined – in other words, they were undynamic. Over the years, we fixed the short history problem by creating a dynamic continuous contract going back in time for the number of days required for a calculation. We also fixed the database with more appropriate rollover frequency and dates. So in the end, the software simulated what I had expected from trading real futures contracts. This software was originally written in Fortran and for the Macintosh. It also had limitations on portfolio analysis as it worked its way across the portfolio, one complete market at a time. Even with all these limitations, I truly thought that the returns more closely mirrored what a trader might see in real time. Today, there aren’t many, if any, simulation platforms that test on individual contracts. The main reasons for this are the complexity of the software, and the database management. However, if you are willing to do the work, you can get close to testing on individual contract data with EasyLanguage.
Step 1 – Get the rollover dates
This is critical as the dates will be used to roll out of one contract and into another. In this post, I will test a simple strategy on the crude futures. I picked crude because it rolls every month. Some data vendors use a specific date to roll contracts, such as Pinnacle data. In real time trading, I did this as well. We had a calendar for each month, and we would mark the rollover dates for all markets traded at the beginning of each month. Crude was rolled on the 11th or 12th of the prior month to expiration. So, if we were trading the September 2022 contract, we would roll on August 11th. A single order (rollover spread) was placed to sell (if long) the September contract and buy the October contract at the market simultaneously. Sometimes we would leg into the rollover by executing two separate orders – in hopes of getting better execution. I have never been able to find a historic database of when TradeStation performs its rollovers. When you use the default @CL symbol, you allow TradeStation to use a formula to determine the best time to perform a rollover. This was probably based on volume and open interest. TradeStation does allow you to pick several different rollover triggers when using their continuous data.
I am getting ahead of myself, because we can simply use the default @CL data to derive the rollover dates (almost.) Crude oil is one of those weird markets where LTD (last trade days) occurs before FND (first notice day.) Most markets will give you a notice before they back up a huge truck and dump a 1000 barrels of oil at your front door. With crude you have to be Johnny on the spot! Rollover is just a headache when trading futures, but it can be very expensive headache if you don’t get out in time. Some markets are cash settled so rollover isn’t that important, but others result in delivery of the commodity. Most clearing firms will help you unwind an expired contract for a small fee (well relatively small.) In the good old days your full service broker would give you heads up. They would call you and say, “George you have to get out of that Sept. crude pronto!” Some firms would automatically liquidate the offending contract on your behalf – which sounds nice but it could cost you. Over my 30 year history of trading futures I was caught a few times in the delivery process. You can determine these FND and LTD from the CME website. Here is the expiration description for crude futures.
Trading terminates 3 business day before the 25th calendar day of the month prior to the contract month. If the 25th calendar day is not a business day, trading terminates 4 business days before the 25th calendar day of the month prior to the contract month.
You can look this up on your favorite broker’s website or the handy calendars they send out at Christmas. Based on this description, the Sept. 2022 Crude contract would expire on August 20th and here’s why
August 25 is Tuesday
August 24 is Monday- DAY1
August 21 is Friday – DAY2
August 20 is Thursday – DAY3
This is the beauty of a well oiled machine or exchange. The FND will occur exactly as described. All you need to do is get all the calendars for the past ten years and find the 25th of the month and count back three business days. Or if the 25 falls on a weekend count back four business days. Boy that would be chore, would it not? Luckily, we can have the data and an EasyLanguage script do this for us. Take a look at this code and see if it makes any sense to you.
Case "@CL": If dayOfMonth(date) = 25 and firstMonthPrint = false then begin print(date+19000000:8:0); firstMonthPrint = true; end; If(dayOfMonth(date) < 25 and dayOfMonth(date) > 25 ) and firstMonthPrint = false then begin print(date+19000000:8:0); firstMonthPrint = true; end;
Code to printout all the FND of crude oil.
I have created a tool to print out the FND or LTD of any commodity futures by examining the date. In this example, I am using a Switch-Case to determine what logic is applied to the chart symbol. If the chart symbol is @CL, I look to see if the 25th of the month exists and if it does, I print the date 3 days prior out. If today’s day of month is greater than 25 and the prior day’s day of month is less than 25, I know the 25th occurred on a weekend and I must print out the date four bars prior. These dates are FN dates and cannot be used as is to simulate a rollover. You had best be out before the FND to prevent the delivery process. Pinnacle Date rolls the crude on the 11th day of the prior month for its crude continuous contracts. I aimed for this day of the month with my logic. If the FND normally fell on the 22nd of the month, then I should back up either 9 or 10 business days to get near the 11th of the month. Also I wanted to use the output directly in an EasyLanguage strategy so I modified my output to be exact EasyLanguage.
Case "@CL": If dayOfMonth(date) = 25 and firstMonthPrint = false then begin value1 = value1 + 1; print("rollArr[",value1:1:0,"]=",date+19000000:8:0,";"); firstMonthPrint = true; end; If(dayOfMonth(date) < 25 and dayOfMonth(date) > 25 ) and firstMonthPrint = false then begin value1 = value1 + 1; print("rollArr[",value1:1:0,"]=",date+19000000:8:0,";"); // print(date+19000000:8:0); firstMonthPrint = true; end;
Code to print our 9 or 10 bars prior to FND in actual EasyLanguage
Now. that I had the theoretical rollover dates for my analysis I had to make sure the data that I was going to use matched up exactly. As you saw before, you can pick the rollover date for your chart data. And you can also determine the discount to add or subtract to all prior data points based on the difference between the closing prices at the rollover point. I played around with the number of days prior to FND and selected non adjusted for the smoothing of prior data.
How did I determine 8 days Prior to First Notice Date? I plotted different data using a different number of days prior and determined 8 provided a sweet spot between the old and new contract data’s open interest. Can you see the rollover points in the following chart? Ignore the trades – these were a beta test.
The dates where the open interest creates a valley aligned very closely with the dates I printed out using my FND date finder function. To be safe, I compared the dates and fixed my array data to match the chart exactly. Here are two rollover trades – now these are correct.
This post turned out to be a little longer than I thought, so I will post the results of using an adjusted continuous contract with no rollovers, and the results using non-adjusted concatenated contracts with rollovers. The strategy will be a simple 40/20 bar Donchian entry/exit. You maybe surprised by the results – stay tuned.
Backtesting with [Trade Station,Python,AmiBroker, Excel]. Intended for informational and educational purposes only!