Back

ETF Trend Following Algorithm

This trend following algorithm is converted from Naoki Nagai combined with the improvement of Maxim Girbu about applying the weighted moving average to adjust position sizing.

First, choose the major ETFs in the index, fix income and commodity market. The linear regression over the open price of the last half year is used to decide the current trend. The trading signals are triggered by the following rules

1. Set a threshold to the slope of the regression line, trade if the slope exceeds the threshold

2. Uptrend ( slope > 0 and slope > threshold):  

  • Today's open cross the regression line upward and the equity is not invested  - long
  • The equity has already been invested(long) and today's open greater than 95% upper Bollinger band - liquidate 

3. Downtrend (slope < 0 and slope < - threshold)

  • Today's open cross below the regression line and the equity is not invested  - short
  • The equity has already been invested(short) and today's open lower than 95% lower Bollinger band - liquidate

4. If the equity has already been invested

  • long but the slope turns down, liquidate
  • short but the slope turns upward, liquidate

 5. Trailing stop

  • The stoploss percentage is the absolute value of slope over the lookback period, the price is the historical mean over the last three days
Update Backtest






The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.



nicely done,....thanks for posting.

0

Jing,

This is awesome! If you were to modify the algorithm to consume output from CourseSelection/FineSelection as a starting universe, how would you handle the uptake of the Universe symbols instead? I tinkered around with it a bit this morning, but need an extra nudge! Thanks in advance.

Aaron

0

nicely done,....thanks for posting.

0

Hi Aaron,

This is my attempt to add the universe selection for symbol picking. The universe selection is rebalanced every month and it picks the symbol based on PE ratio. It's a nice suggestion to improve the algorithm. If you have some great ideas about how to choose the universe, welcome to post it here.

0

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


As always, Thanks Jing! I will post a new version if I find anything worthwhile.

0

Hi Jing,

thanks you share the strategy !
what wrong of the following message that when I backtest the universe selection for symbol picking version strategy and backtest start date from 2015 

 

38 | 09:44:30:

Runtime Error: QuantConnect.Scheduling.ScheduledEventException: Python.Runtime.PythonException: ValueError : arrays must all be same length
at QuantConnect.Scheduling.ScheduleManager+<>c__DisplayClass16_0.<On>b__0 (System.String name, System.DateTime time) [0x00000] in <e60e6336223b4153a44c7c1bc57e55f5>:0
at QuantConnect.Scheduling.ScheduledEvent.OnEventFired (System.DateTime triggerTime) [0x00036] in <e60e6336223b4153a44c7c1bc57e55f5>:0
at QuantConnect.Scheduling.ScheduledEvent.OnEventFired (System.DateTime triggerTime) [0x00086] in <e60e6336223b4153a44c7c1bc57e55f5>:0
at QuantConnect.Scheduling.ScheduledEvent.Scan (System.DateTime utcTime) [0x0010f] in <e60e6336223b4153a44c7c1bc57e55f5>:0
at QuantConnect.Lean.Engine.RealTime.BacktestingRealTimeHandler.SetTime (System.DateTime time) [0x00019] in <edb82c23e8dc4c13a9514cc4c313efae>:0
at QuantConnect.Lean.Engine.AlgorithmManager.Run (QuantConnect.Packets.AlgorithmNodePacket job, QuantConnect.Interfaces.IAlgorithm algorithm, QuantConnect.Lean.Engine.DataFeeds.IDataFeed feed, QuantConnect.Lean.Engine.TransactionHandlers.ITransactionHandler transactions, QuantConnect.Lean.Engine.Results.IResultHandler results, QuantConnect.Lean.Engine.RealTime.IRealTimeHandler realtime, QuantConnect.Lean.Engine.Server.ILeanManager leanManager, QuantConnect.Lean.Engine.Alpha.IAlphaHandler alphas, System.Threading.CancellationToken token) [0x007d5] in <edb82c23e8dc4c13a9514cc4c313efae>:0
at QuantConnect.Lean.Engine.Engine+<>c__DisplayClass8_1.<Run>b__3 () [0x000ac] in <edb82c23e8dc4c13a9514cc4c313efae>:0 (Open Stacktrace)

0

Hi Devon, this error happens in calc_vol_scalar(self) function when trying to convert the dict into dataframe.

Converting the array value in dict into series will solve the problem.

  

0

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


Hi Jing,

I modified the parameters of your original algorithm to the following:

        self.SetStartDate(2017, 01, 01)  
        #self.SetEndDate(2018, 01, 01)
        self.SetCash(10000)            
 

And I got the exception below.  Any idea why?

Thanks,

Jon

Runtime Error: QuantConnect.Scheduling.ScheduledEventException: Python.Runtime.PythonException: KeyError : u'the label [DIA] is not in the [index]' at Python.Runtime.Dispatcher.Dispatch (System.Collections.ArrayList args) [0x00018] in <3e87c364169b46d2b45f0865ae967c08>:0 at __System_ActionDispatcher.Invoke () [0x00006] in <b753ea14828140f5ab856db1330c7db9>:0 at QuantConnect.Scheduling.ScheduleManager+<>c__DisplayClass16_0.<On>b__0 (System.String name, System.DateTime time) [0x00000] in <ac47dd9203a64ea18312e5eeec1c4507>:0 at QuantConnect.Scheduling.ScheduledEvent.OnEventFired (System.DateTime triggerTime) [0x00036] in <ac47dd9203a64ea18312e5eeec1c4507>:0 at QuantConnect.Scheduling.ScheduledEvent.OnEventFired (System.DateTime triggerTime) [0x00086] in <ac47dd9203a64ea18312e5eeec1c4507>:0 at QuantConnect.Scheduling.ScheduledEvent.Scan (System.DateTime utcTime) [0x0010f] in <ac47dd9203a64ea18312e5eeec1c4507>:0 at QuantConnect.Lean.Engine.RealTime.BacktestingRealTimeHandler.SetTime (System.DateTime time) [0x00019] in <8416f1e73c7e42ba8e4bf9805ee5f36a>:0 at QuantConnect.Lean.Engine.AlgorithmManager.Run (QuantConnect.Packets.AlgorithmNodePacket job, QuantConnect.Interfaces.IAlgorithm algorithm, QuantConnect.Lean.Engine.DataFeeds.IDataFeed feed, QuantConnect.Lean.Engine.TransactionHandlers.ITransactionHandler transactions, QuantConnect.Lean.Engine.Results.IResultHandler results, QuantConnect.Lean.Engine.RealTime.IRealTimeHandler realtime, QuantConnect.Lean.Engine.Server.ILeanManager leanManager, QuantConnect.Lean.Engine.Alpha.IAlphaHandler alphas, System.Threading.CancellationToken token) [0x007d5] in 

0

Hi Jing Wu, Thanks for your work.You normalized the slope as below, Can you explain about this?

# Normalized slope
slope = a / b *252.0

Is your intention to make it 'annualized slope'? (or else?) If you want to get annualized slopes, should'nt it be 'sqrt(252)'? Or am I missing something here? Thanks.

0

@Jing Wu: there is some error in the code with History for multiple parameters after I did a clone.

0

Hi Jing Wu, I got same error as below.

Runtime Error: QuantConnect.Scheduling.ScheduledEventException: In Scheduled Event 'SPY: EveryDay: SPY: 28 min after MarketOpen-6909e3d5b3c747ee9a4e80648b2061fc', TypeError : No method matches given arguments for History ---> Python.Runtime.PythonException: TypeError : No method matches given arguments for History
at QuantConnect.Scheduling.ScheduleManager+<>c__DisplayClass16_0.<On>b__0 (System.String name, System.DateTime time) [0x00000] in <669a48023294462e9e7fa428d3f38468>:0
at QuantConnect.Scheduling.ScheduledEvent.OnEventFired (System.DateTime triggerTime) [0x00036] in <669a48023294462e9e7fa428d3f38468>:0 (Open Stacktrace)140 | 18:27:32:Algorithm Id:(bfb08429eae765001044b2e6d847e9dc) completed in 13.08 seconds at 0k data points per
0

Hi Jing Wu, One more quick question. Is there way to get all the slopes of entire symbols that are filtered? You got candidates from filtering 'P/E ratio' in 'FineSelectionFunction' and then you got the slope of each stock by using linear regression. Instead, can we get the series (or in the form of dataframe) of all the slopes of entire stocks that we filetered with the P/E ratio as below?

# Slopes of each stock (I used just dummy numbers, not real slopes.)

AAPL 2.0
MSFT 1.5
AMZN 2.5
XOM 1.5
......

 So that we can play with this data (e.g. ranking, etc.). Thank you.

0

Hi Hanbyul, the normalized slope here is intended to show the percentage change at each bar. The formula should be 

Slope = Change in Price
Normalized Slope = Change in Price / Bar 

The bar here is 1/252. Thus Normalized Slope = a/b *252

This normalization would allow for comparison of the Regression Slope of different stocks trading in different price ranges. Thus here we divide the slope by the intercept b.

0

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


QuantTraderHanByul_p, the error message comes from the history request. The number of days parameter in self.History(symbols, number of days, resolution) must be int. In Python2, int/int will be automatically converted to int but in Python3, the result of int/int is a float.

# instead of self.lookback = 252/2
self.lookback = int(252/2)

The updated algorithm is attached.

0

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


Jing Wu, Thanks!

0

How to avoid the backtest issue:

47 | 00:15:21: Backtest Handled Error: The order quantity for SPY cannot be calculated: Reason: The portfolio does not have enough margin available..48 | 00:15:21: Backtest Handled Error: The order quantity for USO cannot be calculated: Reason: The portfolio does not hold enough cash including the order fees..
1

Hi Jing,

what wrong of the following message that when I backtest the universe selection for symbol picking version strategy ,
is the Python 3 issue? but how to solve it?

QuantConnect.Scheduling.ScheduledEventException: In Scheduled Event 'SPY: EveryDay: SPY: 30 min after MarketOpen', ---> Python.Runtime.PythonException: AttributeError : 'dict' object has no attribute 'iteritems'
at Python.Runtime.Dispatcher.Dispatch (System.Collections.ArrayList args) [0x00018] in <08c5f7c671544a85833a052ad010684a>:0
at __System_ActionDispatcher.Invoke () [0x00006] in :0
at QuantConnect.Scheduling.ScheduleManager+<>c__DisplayClass14_0.b__0 (System.String name, System.DateTime time) [0x00000] in :0
at QuantConnect.Scheduling.ScheduledEvent.OnEventFired (System.DateTime triggerTime) [0x00036] in :0
--- End of inner exception stack trace ---
  
0

When running the backtest I see a bunch of order warnings.  I am pretty sure this means that your algo was trying to enter orders and your portfolio didn't have enough available margin to enter them.  So the backtest isn't accurately representing the algorithm.

In a related matter I think there may be some bug with how the Lean engine is calculating margin requirements on orders, especially when going far back in time.  

39 | 04:17:37:
Backtest Handled Error: The order quantity for DIA cannot be calculated: Reason: The portfolio does not have enough margin available..
140 | 04:17:38:
Backtest Handled Error: The order quantity for DIA cannot be calculated: Reason: The portfolio does not have enough margin available..
141 | 04:17:40:
Backtest Handled Error: The order quantity for DIA cannot be calculated: Reason: The portfolio does not have enough margin available..
142 | 04:17:41:
Backtest Handled Error: The order quantity for USO cannot be calculated: Reason: The portfolio does not hold enough cash including the order fees..
143 | 04:17:41:
Your algorithm messaging has been rate limited to prevent browser flooding.
144 | 04:17:42:
Backtest Handled Error: The order quantity for DIA cannot be calculated: Reason: The portfolio does not have enough margin available..
145 | 04:17:45:
Backtest Handled Error: The order quantity for GLD cannot be calculated: Reason: The portfolio does not have enough margin available..
146 | 04:17:47:
Backtest Handled Error: The order quantity for DIA cannot be calculated: Reason: The portfolio does not hold enough cash including the order fees..
147 | 04:17:47:
Your algorithm messaging has been rate limited to prevent browser flooding.
148 | 04:17:48:
Backtest Handled Error: The order quantity for RWX cannot be calculated: Reason: The portfolio does not have enough margin available..
149 | 04:17:50:
Backtest Handled Error: The order quantity for DIA cannot be calculated: Reason: The portfolio does not have enough margin available..
150 | 04:17:50:
Backtest Handled Error: The order quantity for DIA cannot be calculated: Reason: The portfolio does not have enough margin available..
151 | 04:17:52:
Backtest Handled Error: The order quantity for SPY cannot be calculated: Reason: The portfolio does not hold enough cash including the order fees..
152 | 04:17:52:
Your algorithm messaging has been rate limited to prevent browser flooding.
153 | 04:17:53:
Backtest Handled Error: The order quantity for DIA cannot be calculated: Reason: The portfolio does not have enough margin available..
154 | 04:17:54:
Backtest Handled Error: The order quantity for DIA cannot be calculated: Reason: The portfolio does not have enough margin available..
155 | 04:17:55:
Backtest Handled Error: The order quantity for SPY cannot be calculated: Reason: The portfolio does not have enough margin available..
156 | 04:18:12:
Backtest Handled Error: The order quantity for GLD cannot be calculated: Reason: The portfolio does not hold enough cash including the order fees.
0

I believe there is an error in rule 4. although it is not hit if you change sign:

# Long but slope turns down, then exit
if symbol.weight > 0 and slope < 0:
symbol.weight = 0

# short but slope turns upward, then exit
if symbol.weight < 0 and slope > 0:
symbol.weight = 0
0

Could anyone possibly explain how a slope_min = 0.252 corresponds to at least 7% growth per year?

0

Can someone explain how self.weigth is determined in this algo? As is initialized with 0, but I don't see any part in which is assigned a new value for self.weigth. 

Thanks

Nicolas

0

Update Backtest





0

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


Loading...

This discussion is closed