If you have some time on your hands and you want to build your own Frankenstein monster from a parts bin, here is your chance. The Super Combo Day Trading System was originally published in my “Building Winning Trading Systems” book back in 2001. I designed it to be more of a tutorial than a pure trading system. You should be able to get the spare parts you need to create your own day trading system. Back in 2001, I wanted to show how to control and monitor different entry and exit techniques in one complete algorithm. The system was designed to day-trade the big SP and the results at the time looked promising. Since the transition to the ES and the higher levels of volatility that we have seen over the years and the adoption of overnight trading, the system hasn’t fared that well, but the concepts are still viable as an instructional tool today as they were 20 years ago. EasyLanguage has been improved over this time period so the coding for the Super Combo can definitely take advantage of the new enhancements.
Here are the main premises of the logic:
- take advantage of a buyEasier and shortEasier pattern setup
- incorporate daily and 5-minute time frames in one chart
- include a breakOut, failedBreakOut and reverseOnLiquidation trade entry techniques
- monitor which signal is currently online and apply the correct exit signal
- monitor profit and incorporate a break even stop
- monitor time and incorporate a trailing stop
- provide an interface into the logic via inputs
Okay here we go – there is quite a bit of code here so let’s divide an conquer by examining just one module at a time. This first module includes the inputs and variables section plus once per day calculations.
[LegacyColorValue = true];
{Super Combo by George Pruitt - redo 2020
This intra-day trading system will illustrate the multiple data
handling capabilities of TradeStation. All pertinent buy and sell
calculations will be based on daily bars and actual trades will be
executed on 5-min bars. I have made most of the parameters input
variables}
Inputs:waitPeriodMins(30),initTradesEndTime(1430),liqRevEndTime(1200),
thrustPrcnt1(0.30),thrustPrcnt2(0.60),breakOutPrcnt(0.25),
failedBreakOutPrcnt(0.25),protStopPrcnt1(0.30),protStopPrcnt2(0.20),
protStopAmt(3.00),breakEvenPrcnt(0.50),avgRngLength(10);
Variables:averageRange(0),canTrade(0),buyEasierDay(FALSE),
sellEasierDay(FALSE),buyBOPoint(0),sellBOPoint(0),longBreakPt(0),
shortBreakPt(0),longFBOPoint(0),shortFBOPoint(0),barCount(0),buysToday(0),
sellsToday(0),mp(0),longLiqPoint(0),shortLiqPoint(0),
longLiqPoint1(0),shortLiqPoint1(0),intraTradeHigh(0),intraTradeLow(999999);
{Just like we did in the psuedo code -- let's start out with the daily
bar calculations. If Date <> Date[1] -- first bar of day}
if(Date <> Date[1]) then {save time by doing these calculations once per day}
begin
averageRange = Average(Range,10) of Data2; {Data 2 points to daily bars}
canTrade = 0;
if range of data2 < averageRange then canTrade = 1;
{use close of data2 - seems to be more accurate than CloseD(1)
buyEasierDay =Close of Data2 >= Close[1] of Data2;
sellEasierDay = Close of Data2 < Close[1] of Data2;
buyBOPoint = Open + thrustPrcnt1*averageRange;
sellBOPoint= Open - thrustPrcnt2*averageRange;
if(sellEasierDay) then
begin
sellBOPoint= Open - thrustPrcnt1*averageRange;
buyBOPoint = Open + thrustPrcnt2*averageRange;
end;
longBreakPt = HighD(1) + breakOutPrcnt*averageRange;
shortBreakPt= LowD(1) - breakOutPrcnt*averageRange;
shortFBOPoint = HighD(1) - failedBreakOutPrcnt*averageRange;
longFBOPoint= LowD(1) + failedBreakOutPrcnt*averageRange;
{Go ahead and initialize any variables that we may need later on in the day}
barCount = 0;
buysToday = 0;sellsToday = 0;{You can put multiple statements on one line}
end;
First Modules of SuperCombo 2020
Here I am just setting up the inputs and variables that I will need to execute the algorithm. If you are using .D data then the code
if date <> date[1] then
is a valid test for the first bar of the day. A new date will represent the beginning of the next day. The code controlled by this if-then construct is only executed one time per day. So if you can put the lion’s share of daily calculations here, then it should speed stuff up. The first thing I do is calculate the average range of the last 10 daily bars. I access this date from data2. Can you build a loop and accumulate the difference between the HighD and LowD function calls?
- for i = 1 to 10 begin
- sum = sum + (HighD(i) – LowD(i));
- end;
The HighD() and LowD() functions are EasyLanguage enhancements that can help eliminate the need for a multi-data chart. However, if you do this, you will get an warning message that its not a good idea. I have done this and it seems to work, but to be safe just use Data2. Next I determine if there has been a narrow range or range compression by comparing yesterday’s range to the averageRange. If so, then I allow trading. This is an old filter that looks for range expansion after compression. The concept of a buyDay and sellDay was originated in the 1930s by George W. Cole (correct me if I am wrong here). I use this idea by comparing the prior two bars closing relationships. If there has been an up close, then I consider the next day to be a buyEasier day. If the opposite is true, then its a sellEasier day. This system isn’t unidirectional and does allow buying and shorting in the same session – hence the word easier. Continuing I calculate the levels that if the market reaches will hopefully trigger a short term trend in that direction. This is the once highly respected open range break out or ORBO. This methodology has lost its luster over the last 10 years or so due to overnight trading and allowing pent up buying and selling to be expressed in the overnight sessions. Twenty years ago it was still viable. The next bit of code creates the break out levels based on the buyEasier or sellEasier days. The thrust is calculated by multiplying the range by thrustPrcnt1 and thrustPrcnt2.
So that is method 1 – break out. Hope the market breaks out and continues to the close. I wish it were this easy. Since its not, the second methodolgy, FailedBreakOut, is calculated. This is also known as the “ClearOut” trade. The market is pushed to take out all the buy stops and then pulled back for the professionals to feast on the amateurs. SuperCombo tries to take advantage of this by calculating the two points to determine a failed break out. On the long side, it is the two points the market rises up to and then falls back to. If the market breaches the longBreakPt, then look to sellShort at the shortFBOPoint. Here is the next module
{Now lets trade and manage on 5-min bars}
barCount = barCount + 1; {count the number of bars of intraday data}
if(barCount >= waitPeriodMins/BarInterval and canTrade = 1) then {have we waited long enough}
begin
if(MarketPosition = 1) then buysToday = 1;
if(MarketPosition =-1) then sellsToday= 1;
if(buysToday = 0 and Time < initTradesEndTime) then
Buy("LBreakOut") next bar at buyBOPoint stop;
if(sellsToday= 0 and Time < initTradesEndTime) then
SellShort("SBreakout") next bar at sellBOPoint stop;
if(highD(0) > longBreakPt and sellsToday = 0 and Time < initTradesEndTime) then
SellShort("SfailedBO") next bar at shortFBOPoint stop;
if(lowD(0) < shortBreakPt and buysToday = 0 and Time < initTradesEndTime) then
Buy("BfailedBO") next bar at longFBOPoint stop;
Monitor Market Action and Place Trades Accordingly
if(barCount>= waitPeriodMins/BarInterval and canTrade = 1) then
Forces the logic to flow only if canTrade is 1 and we have waited for amateur hour to be completed – well 30 minutes to be accurate. Is the first hour really amateur hour? I don’t think this applies, but if you think it does this is how you control trading prior to the completion of this period. By dividing by BarInterval and counting each bar you can generalize this code for any time resolution. If MarketPosition is 1 then you know you entered a long position and the opposite is true for short positions. Only place the break out orders if time is less than initTradesEndTime. If the market penetrates the long and shortBreakPts, then prepare to take advantage of a failed breakout. Only go short if a short position has not already been entered – same for longs. So, this logic places the breakOut and failedBreakOut orders. Now for the last module.
{The next module keeps track of positions and places protective stops}
mp = marketPosition;
if(MarketPosition = 1) then
begin
longLiqPoint = EntryPrice-protStopPrcnt1*averageRange;
longLiqPoint = MinList(longLiqPoint,EntryPrice - protStopAmt);
longLiqPoint1 = EntryPrice - protStopPrcnt2*averageRange;
longLiqPoint1 = MinList(longLiqPoint1,EntryPrice - protStopAmt);
if Maxpositionprofit >= breakEvenPrcnt*averageRange*bigPointValue then
begin
longLiqPoint = EntryPrice; {Breakeven trade}
longLiqPoint1 = EntryPrice; {Breakeven trade}
end;
if(Time >= initTradesEndTime) then
begin
longLiqPoint = MaxList(longLiqPoint,Lowest(Low,3)); {Trailing stop}
longLiqPoint1 = MaxList(longLiqPoint1,Lowest(Low,3)); {Trailing stop}
end;
if(Time < liqRevEndTime and sellsToday = 0 and
longLiqPoint <> EntryPrice and BarsSinceEntry >= 4) then
SellShort("LongLiqRev") next bar at longLiqPoint stop;
Sell("LongLiq-BO") from entry("LBreakOut") next bar at longLiqPoint stop;
Sell("LongLiq-FBO") from entry("BFailedBO") next bar at longLiqPoint stop;
Sell("LongLiq-RLoss") from entry("ShortLiqRev") next bar at longLiqPoint1 stop;
end;
if(MarketPosition =-1) then
begin
shortLiqPoint = EntryPrice+protStopPrcnt1*averageRange;
shortLiqPoint = MaxList(shortLiqPoint,EntryPrice + protStopAmt);
shortLiqPoint1 = EntryPrice + protStopPrcnt2*averageRange;
shortLiqPoint1 = MaxList(shortLiqPoint1,EntryPrice + protStopAmt);
if maxPositionProfit >= breakEvenPrcnt*averageRange*bigPointValue then
begin
shortLiqPoint = EntryPrice; {Breakeven trade}
shortLiqPoint1 = EntryPrice;
end;
if(Time >= initTradesEndTime) then
begin
shortLiqPoint = MinList(shortLiqPoint,Highest(High,3)); {Trailing stop}
shortLiqPoint1 = MinList(shortLiqPoint1,Highest(High,3)); {Trailing stop}
end;
if(Time < liqRevEndTime and buysToday = 0 and
shortLiqPoint <> EntryPrice and BarsSinceEntry >= 4) then
Buy("ShortLiqRev") next bar at shortLiqPoint stop;
BuyToCover("ShortLiq-BO") from entry("SBreakOut") next bar at shortLiqPoint stop;
BuyToCover("ShortLiq-FBO") from entry("SFailedBO") next bar at shortLiqPoint stop;
BuyToCover("ShortLiq-RLoss") from entry("LongLiqRev") next bar at shortLiqPoint1 stop;
end;
end;
SetExitOnClose;
TradeManagement (Enter on Stop Loss or Not?)
This code looks a little hairy, but its not. Let’s just look at the long side logic to save time here. First let’s calculate the LongLiqPoints (1 and 2.) Twenty years ago I thought it would be better to have a smaller stop for entries that occurred on a LiquidationReversal. Oh yeah that code is in here to. Back in the day I wanted to make sure the stop was at least 3 handles – ha, ha, ha – no really I am serious. Really. Stop laughing!! That code could be eliminated. After calculating these two points I start to monitor profit and if it reaches a predetermined level I pull the the longLiqPoints toa BreakEven stop. If you are fortunate to still be in a trade after initTradesEndTime, then I start trailing the stop by the lowest low of the last 3 five minute bars – I don’t want to turn a small winner into a loser. Now this is the fun stuff.
- if(Time < liqRevEndTime and sellsToday = 0 and
longLiqPoint <> EntryPrice and BarsSinceEntry >= 4) then
- SellShort(“LongLiqRev”) next bar at longLiqPoint stop;
If time is less than liqRevEndTime and BarsSinceEntry, then reverse and go short at the longLiqPoint stop. Do this instead of liquidating. I thought if the market reversed course quickly, then I wanted to take advantage of this counter trend move. Eliminating this to see if it has any impact would be where I would start to play around with the template. Okay now the liquidations based on from Entry take place next. If I am long from a “ShortLiqRev“, then I use longLiqPoint1 instead of longLiqPoint. Okay that last part was the kitchen sink. Now you have enough code to make your own day trading system – really too much code, but you should be able to hobble something together from these parts. Let me know if you can create your own Frankenstein monster. I will update the parameters to see if there is any hope to the system as a whole. Keep checking back for updated performance metrics. Best to all and be safe!