Linear Regression Trading Strategy for ThinkorSwim

Dublin_Capital

Dublin_Capital

Member
I thought it might be interesting to share a very basic Linear Regression Trading Strategy, and then see if we can build on it to improve results.

Here is the basic strategy - Using a 50 period Linear Regression Curve on an hourly chart, we enter / exit trades using the following rules:
  • Long Entry: The Linear Regression Curve is rising AND the close of the previous bar is above the Linear Regression Curve
  • Long Exit: The close of the previous bar is less than the Linear Regression Curve
  • Short Entry: The Linear Regression Curve is falling AND the close of the previous bar is below the Linear Regression Curve
  • Short Exit: The close of the previous bar is greater than the Linear Regression Curve
We enter and exit using one contract only. The strategy can be long, short, or flat.



Code:
#DS_LinRegStrategy
#Basic framework for a Linear Regression based strategy
#@Dublin_Capital
#2020-07-03

input price = close;
input displace = 0;
input LinRegLength = 50;

#Definitions

def LinReg = Inertia(price[-displace], LinRegLength);


#Defining Instrument Fundamentals & P&L for labels
def tickval = TickValue();
def ticksize = TickSize();
def FloatPL = FPL();


#Defining Long/Short Filters (these instructions determine entries / exits)


#Entry / Exit Requirements
def Long1 = LinReg > LinReg[1]
    and close > LinReg;

def ExitLong1 = close < LinReg;


def Short1 = LinReg < LinReg[1]
    and close < LinReg;

def ExitShort1 = close > LinReg[1];



#Order Entry (Set 1)
AddOrder(OrderType.BUY_TO_OPEN, Long1, tickcolor = Color.DARK_GREEN, arrowcolor = Color.DARK_GREEN, name = "LONG1");
AddOrder(OrderType.SELL_TO_CLOSE, ExitLong1, tickcolor = Color.DARK_GREEN, arrowcolor = Color.DARK_GREEN, name = "EXITLONG1");


AddOrder(OrderType.SELL_TO_OPEN, Short1, tickcolor = Color.DARK_RED, arrowcolor = Color.DARK_RED, name = "SHORT1");
AddOrder(OrderType.BUY_TO_CLOSE, ExitShort1, tickcolor = Color.DARK_RED, arrowcolor = Color.DARK_RED, name = "EXITSHORT1");


#Adding Linear Regression Plots
plot LinReg3 = LinReg;
LinReg3.SetDefaultColor(Color.BLUE);


#Adding Alerts
Alert(Long1, "Long", Alert.BAR, Sound.Ding);
Alert(Short1, "Short", Alert.BAR, Sound.Ding);
Alert(ExitLong1, "ExitLong", Alert.BAR, Sound.Ring);
Alert(ExitShort1, "ExitShort", Alert.BAR, Sound.Ring);


#Adding Labels
AddLabel(yes, "$" + tickval);
AddLabel(yes, ticksize);
AddLabel(yes, "$" + FloatPL, if FloatPL > 0 then Color.DARK_GREEN
    else if FloatPL < 0 then Color.DARK_RED
    else Color.GRAY);

#Coloring Bars
AssignPriceColor(if Long1 then Color.DARK_GREEN else if Short1 then Color.DARK_RED else Color.GRAY);
Backtesting for 360 trading days, the results of the strategy are as follows on a portfolio of commonly traded futures instruments. Although profitable, the P&L curve is not ideal, commissions too high, and the win rate could be improved. The majority of the profits come during a small fraction of the overall trading.

Used just as is, this strategy would be a good supplement to a long-only portfolio of stocks, as it seems to keep it's head above water during normal markets, but delivers strong returns during higher volatility (early 2020). That said, I would like to see if we can turn it into a stronger stand-alone strategy.

A linear regression channel is a representation of trend direction and volatility. Buying / selling above and below the middle line doesn't even really make sense, as price is expected to travel up and down within the channel. I guess my main point with all of this is that a profitable trading strategy can be based on almost anything.

I will be taking suggestions and adding / adjusting the strategy in an effort to improve these metrics.








 
Last edited:
T

tradebyday

Active member
If you wanted to apply a longer period channel but on a shorter timeframe, I suggest adding this indicator to your screen, Colored boxes above the red box= longs only off bottom of regression channel, colored boxes below red box= shorts off top of linear regression channel. Inside the red box you can trade off both sides of the channel. Trading higher timeframes in futures can be rather inefficient for many traders as they do not have access, capital, and/or the stomach to trade positions for that long. But the problem with many shorter timeframe traders is over trading and trying to trade against the trend at times for scalps. Adding this "rainnbow road" I call it will try to assist in the discipline. The boxes are based on % moves for the day and the % can be adjusted. I have it at settings that showed extremes for when to consider scale in for reversals, which I would like to note, may also help out the shorter time frame strategy by helping show areas of extremes when to stop entering trades long or short in areas of over-extension. I will be watching this forum to see what ideas are also thrown out to your original strategy as well.
Code:
#RainbowRoadPercentages by Tradebyday

input Range1 = .0065;
input Range2 = .015;
input Range3 = .03;
input Range4 = .05;

def pc = close(period = "DAY")[1];
plot priorclose = pc;
priorclose.setstyle(curve.short_DASH);
priorclose.setdefaultcolor(color.white);
priorclose.setLineWeight(1);

AddCloud(priorclose + priorclose*Range4, priorclose + priorclose*Range3, COLOR.BLUE);
AddCloud(priorclose + priorclose*Range3, priorclose + priorclose*Range2, COLOR.GREEN);
AddCloud(priorclose + priorclose*Range2, priorclose + priorclose*Range1, COLOR.YELLOW);
AddCloud(priorclose - priorclose*Range1, priorclose + priorclose*Range1, Color.RED);
AddCloud(priorclose - priorclose*Range1, priorclose - priorclose*Range2, Color.YELLOW);
AddCloud(priorclose - priorclose*Range2, priorclose - priorclose*Range3, Color.GREEN);
AddCloud(priorclose - priorclose*Range3, priorclose - priorclose*Range4, COLOR.BLUE);
 
Dublin_Capital

Dublin_Capital

Member
Before I make any adjustments to the code, I also wanted to look at some different settings. The original test used a 50 period Linear Regression. No other changes, except that I added Bitcoin to the test group.

The longer lengths increase hold time, reduce commissions (less trades), and reduce win rate. Metals and currencies become more profitable with the longer lengths, while indexes become less profitable.

Here are the results from a 100 period Linear Regression:




And here are the results from a 200 period Linear Regression:

 
S

STAZ012

New member
i think more important than anything is your linear regression blue line . try to create a trendline along up and downs of this reg trend line and i see some interesting patterns. for example check this trendline on daily one year chart for swbi , also look at one year daily chart on CIT , join Reg blue trendline for april 27th , june 3rd and present lows to form a trendline. If that trendline holds it will CIT stock to bounce from here but if it breaks that will be a mjor reversal to downside . Will be interesting to watch ...not sure however how to develop the system on reg trendline trendline pattern even if it holds true .
 
Dublin_Capital

Dublin_Capital

Member
Here is what happens to the strategy if you overlay an Exponential Moving Average on the Linear Regression Curve, and trade using the following settings:

Linear Regression Length: 50
EMA Length: 20

The system enters long when the Linear Regression Curve is rising and is greater than the EMA. It enters short when the Linear Regression Curve is falling and below the EMA.

Compared to the original test, using a 50 period Linear Regression Curve, this improves performance on Energies, Metals, Currencies, and Bonds, but destroys the performance on Indexes. From my experience, this is pretty common - indexes do not trade like other things. I find currencies tend to sustain trends longer and respond better to crossover strategies such as these. Also, long/short strategies have a lot of drag in a bull market (indexes).




 
Last edited:
Dublin_Capital

Dublin_Capital

Member
One more adjustment for now:

Linear Regression Length: 100
Hull Moving Average Length: 20

Same entry and exit rules as above. A hull moving average is more sensitive to recent price action, and provides a smoother curve than the Simple Moving Average or EMA. This results in more trades, higher commissions, and a shorter hold time. But it increases the return on the overall portfolio.

As I mentioned before, I don't think it makes sense to trade all instruments with the same settings. But when developing a system, I like to test strategies across a lot of markets using the same settings. I then make adjustments after looking at longer term backtests. This isn't ideal, but is the only way I have found to deal with the limitations of thinkorswim backtesting.





Here is code for this (it's a bit messy - I'll clean up at some point down the road):
Code:
#DS_LinRegStrategy v 3.0
#Basic framework for a Linear Regression based strategy
#@Dublin_Capital
#2020-07-03

input price = close;
input displace = 0;
input LinRegLength = 100;
input averageLength = 20;
input averageType = averageType.HULL;

#Definitions

def LinReg = Inertia(price[-displace], LinRegLength);
def MA = MovingAverage(averageType, LinReg, averageLength);


#Defining Instrument Fundamentals & P&L for labels
def tickval = TickValue();
def ticksize = TickSize();
def FloatPL = FPL();


#Defining Long/Short Filters (these instructions determine entries / exits)


#Entry / Exit Requirements
def Long1 = LinReg > MA
    and LinReg > LinReg[1];

def ExitLong1 = LinReg < MA;


def Short1 = LinReg < MA
    and LinReg < LinReg[1];

def ExitShort1 = LinReg > MA;



#Order Entry (Set 1)
AddOrder(OrderType.BUY_TO_OPEN, Long1, tickcolor = Color.DARK_GREEN, arrowcolor = Color.DARK_GREEN, name = "LONG1");
AddOrder(OrderType.SELL_TO_CLOSE, ExitLong1, tickcolor = Color.DARK_GREEN, arrowcolor = Color.DARK_GREEN, name = "EXITLONG1");


AddOrder(OrderType.SELL_TO_OPEN, Short1, tickcolor = Color.DARK_RED, arrowcolor = Color.DARK_RED, name = "SHORT1");
AddOrder(OrderType.BUY_TO_CLOSE, ExitShort1, tickcolor = Color.DARK_RED, arrowcolor = Color.DARK_RED, name = "EXITSHORT1");


#Adding Linear Regression Plots
plot LinReg3 = LinReg;
LinReg3.SetDefaultColor(Color.BLUE);

#plotting moving average
plot movingAverage = MA;
movingAverage.SetDefaultColor(Color.DARK_GREEN);



#Adding Alerts
Alert(Long1, "Long", Alert.BAR, Sound.Ding);
Alert(Short1, "Short", Alert.BAR, Sound.Ding);
Alert(ExitLong1, "ExitLong", Alert.BAR, Sound.Ring);
Alert(ExitShort1, "ExitShort", Alert.BAR, Sound.Ring);


#Adding Labels
AddLabel(yes, "$" + tickval);
AddLabel(yes, ticksize);
AddLabel(yes, "$" + FloatPL, if FloatPL > 0 then Color.DARK_GREEN
    else if FloatPL < 0 then Color.DARK_RED
    else Color.GRAY);

#Coloring Bars
AssignPriceColor(if Long1 then Color.DARK_GREEN else if Short1 then Color.DARK_RED else Color.GRAY);
 
Last edited:
N

Ninja Bull

New member
Hi everyone, looks like an interesting study-but I can't get it to work?
 
N

Ninja Bull

New member
thanks, but the indicator is not working when I installed it in tos.
 
MerryDay

MerryDay

Member
VIP
@Ninja Bull .. Did you create it under the Strategies tab? Strategies is the tab next to the Studies tab. It won't work otherwise.
 
N

Ninja Bull

New member
Dublin_Capital - perfect strategy specially for Swing Trading. The Linear_Regression_3 or Blue Line combining it with the VolumeProfile is a killer strategy! Can someone work on a Scanner for price to be above or below the Blue Regression Line?
 
Top