diff --git a/04 Strategy Library/00 Strategy Library/01 Strategy Library.php b/04 Strategy Library/00 Strategy Library/01 Strategy Library.php index 6144105..9fc944f 100644 --- a/04 Strategy Library/00 Strategy Library/01 Strategy Library.php +++ b/04 Strategy Library/00 Strategy Library/01 Strategy Library.php @@ -678,6 +678,51 @@ ], 'description' => "Mathematically Deriving the Optimal Entry and Liquidation Values of a Pairs Trading Process", 'tags'=>'Pairs Trading, Ornstein-Uhlenbeck Process, Optimal Stopping' + ], + [ + 'name' => 'G-Score Investing', + 'link' => 'strategy-library/g-score-investing', + 'sources' => [ + 'SSRN' => 'https://papers.ssrn.com/sol3/papers.cfm?abstract_id=403180' + ], + 'description' => "Applying G-Score Investing to Invest in a Portfolio of Technology Stocks", + 'tags'=>'Fundamentals, Factor Investing, G-Score Investing, MorningStar data, equities' + ], + [ + 'name' => 'SVM Wavelet Forecasting', + 'link' => 'strategy-library/svm-wavelet-forecasting', + 'sources' => [ + 'Academia' => 'https://www.academia.edu/37180223/SVR_Wavelet_Adaptive_Model_for_Forecasting_Financial_Time_Series' + ], + 'description' => "Forecasting EURJPY prices with an SVM Wavelet model", + 'tags'=>'Support Vector Machines (SVM), Forex, Forecasting, Wavelet, Discrete Wavelet Transform' + ], + [ + 'name' => 'Gradient Boosting Model', + 'link' => 'strategy-library/gradient-boosting-model', + 'sources' => [ + 'arXiv' => 'https://ssrn.com/abstract=2323899' + ], + 'description' => "Forecasts future intraday returns with a gradient boosting model trained on technical indicators", + 'tags'=>'Gradient Boost, Regression Trees, Equities, Machine Learning' + ], + [ + 'name' => 'Using News Sentiment to Predict Price Direction of Drug Manufacturers', + 'link' => 'strategy-library/using-news-sentiment-to-predict-price-direction-of-drug-manufacturers', + 'sources' => [ + 'arXiv' => 'https://arxiv.org/abs/1812.04199' + ], + 'description' => "Analyzes the news releases of drug manufacturers and places intraday trades for the stocks with positive news.", + 'tags'=>'Equities, NLP, News Sentiment, Drug Manufacturers, Tiingo, Intraday' + ], + [ + 'name' => 'Gaussian Naive Bayes Model', + 'link' => 'strategy-library/gaussian-naive-bayes-model', + 'sources' => [ + 'Academia' => 'https://www.academia.edu/7677227/Forecasting_the_direction_of_stock_market_index_movement_using_three_data_mining_techniques_the_case_of_Tehran_Stock_Exchange' + ], + 'description' => "Forecasts the next day's return of technology stocks by fitting a gaussian naive bayes model to the historical returns of the technology sector constituents.", + 'tags'=>'Equities, Machine Learning, Naive Bayes, Gaussian' ] ]; diff --git a/04 Strategy Library/01 CAPM Alpha Ranking Strategy on Dow 30 Companies/05 Algorithm.html b/04 Strategy Library/01 CAPM Alpha Ranking Strategy on Dow 30 Companies/05 Algorithm.html index f47a119..645e3da 100755 --- a/04 Strategy Library/01 CAPM Alpha Ranking Strategy on Dow 30 Companies/05 Algorithm.html +++ b/04 Strategy Library/01 CAPM Alpha Ranking Strategy on Dow 30 Companies/05 Algorithm.html @@ -1,6 +1,6 @@
- +
\ No newline at end of file diff --git "a/04 Strategy Library/01 CAPM Alpha Ranking Strategy on Dow 30 Companies/05 \347\256\227\346\263\225.cn.html" "b/04 Strategy Library/01 CAPM Alpha Ranking Strategy on Dow 30 Companies/05 \347\256\227\346\263\225.cn.html" index 1f296ed..4a79e84 100644 --- "a/04 Strategy Library/01 CAPM Alpha Ranking Strategy on Dow 30 Companies/05 \347\256\227\346\263\225.cn.html" +++ "b/04 Strategy Library/01 CAPM Alpha Ranking Strategy on Dow 30 Companies/05 \347\256\227\346\263\225.cn.html" @@ -4,6 +4,6 @@
- +
diff --git a/04 Strategy Library/02 Combining Mean Reversion and Momentum in Forex Market/06 Algorithm.html b/04 Strategy Library/02 Combining Mean Reversion and Momentum in Forex Market/06 Algorithm.html index 5c357f4..9717146 100755 --- a/04 Strategy Library/02 Combining Mean Reversion and Momentum in Forex Market/06 Algorithm.html +++ b/04 Strategy Library/02 Combining Mean Reversion and Momentum in Forex Market/06 Algorithm.html @@ -1,6 +1,6 @@
- +
diff --git a/04 Strategy Library/03 Pairs Trading-Copula vs Cointegration/04 Part II - Cointegration Method.html b/04 Strategy Library/03 Pairs Trading-Copula vs Cointegration/04 Part II - Cointegration Method.html index 7011faf..d36c895 100755 --- a/04 Strategy Library/03 Pairs Trading-Copula vs Cointegration/04 Part II - Cointegration Method.html +++ b/04 Strategy Library/03 Pairs Trading-Copula vs Cointegration/04 Part II - Cointegration Method.html @@ -9,39 +9,44 @@

Step 1: Generate the Spread Series

\[spread_t=\log(price_t^y)-\beta \log(price_t^x)\] -

Step 2: Compute the Threshold

+

Step 2: Compute the Signals

- Using the standard deviation of spread during the rolling formation period, a threshold of two standard deviations is set up for the trading strategy as indicated in the paper. + Using the standard deviation of spread during the rolling formation period, a threshold of one standard deviation + is set up for the trading strategy. We enter a trade whenever the spread moves more than one standard deviations + away from its mean. Trades are exited when the spread reverts back to the mean trailing spread value. The position + sizes are scaled by the coefficient β.

-
price_x = pd.Series([float(i.Close) for i in self.symbols[0].hist_window],
-                     index = [i.Time for i in self.symbols[0].hist_window])
+
log_close_x = np.log(self.closes_by_symbol[self.x_symbol])
+log_close_y = np.log(self.closes_by_symbol[self.y_symbol])
+
+spread, beta = self.regr(log_close_x, log_close_y)
 
-price_y = pd.Series([float(i.Close) for i in self.symbols[1].hist_window],
-                     index = [i.Time for i in self.symbols[1].hist_window])
-if len(price_x) < 250: return
-spread = self.regr(np.log(price_x), np.log(price_y))
 mean = np.mean(spread)
 std = np.std(spread)
-ratio = floor(self.Portfolio[self.symbols[1]].Price / self.Portfolio[self.symbols[0]].Price)
-if spread[-1] > mean + self.threshold * std:
-    if not self.Portfolio[self.symbols[0]].Quantity > 0 and not self.Portfolio[self.symbols[0]].Quantity < 0:
-        self.Sell(self.symbols[1], 100)
-        self.Buy(self.symbols[0],  ratio * 100)
-
-elif spread[-1] < mean - self.threshold * std:
-    if not self.Portfolio[self.symbols[0]].Quantity < 0 and not self.Portfolio[self.symbols[0]].Quantity > 0:
-        self.Sell(self.symbols[0], 100)
-        self.Buy(self.symbols[1], ratio * 100)
+
+x_holdings = self.Portfolio[self.x_symbol]
+
+if x_holdings.Invested:
+    if x_holdings.IsShort and spread[-1] <= mean or \
+        x_holdings.IsLong and spread[-1] >= mean:
+        self.Liquidate()
 else:
-    self.Liquidate()
+    if beta < 1:
+        x_weight = 0.5
+        y_weight = 0.5 / beta
+    else:
+        x_weight = 0.5 / beta
+        y_weight = 0.5
+    
+    if spread[-1] < mean - self.threshold * std:
+        self.SetHoldings(self.y_symbol, -y_weight) 
+        self.SetHoldings(self.x_symbol, x_weight)
+    if spread[-1] > mean + self.threshold * std:
+        self.SetHoldings(self.x_symbol, -x_weight)
+        self.SetHoldings(self.y_symbol, y_weight)
 
- -

Step 3: Set up the Trading Signals

-

- On each trading day, we enter a trade whenever the spread moves more than two standard deviations away from its mean. In other words, we construct short positions in X and long positions in Y on the day that spread mean+2*std. We construct short positions in Y and long positions in X on the day that spread<mean-2*std. The trade is exited if the spread reverts to its equilibrium (defined as less than half a standard deviation from zero spread). The value of mean and standard deviation are calculated from the rolling formation period and will be updated once a month. -

diff --git a/04 Strategy Library/03 Pairs Trading-Copula vs Cointegration/05 Summary.html b/04 Strategy Library/03 Pairs Trading-Copula vs Cointegration/05 Summary.html index cd9ff46..44ab024 100755 --- a/04 Strategy Library/03 Pairs Trading-Copula vs Cointegration/05 Summary.html +++ b/04 Strategy Library/03 Pairs Trading-Copula vs Cointegration/05 Summary.html @@ -15,21 +15,21 @@ Copula -346 -274.293% -1.022 -19.4% +493 +8.884% +0.12 +26.1% Cointegration -91 -26.358% -0.298 -23.7% +126 +4.517% +0.196 +3.9%

- Generally, ETFs are not very volatile and so mean-reversion did not provide many trading opportunities. There are only 39 trades during 5 years for cointegration method. It is observed that the use of copula in pairs trading provides more trading opportunities as it does not require any rigid assumptions according to Liew R Q, Wu Y. - Pairs trading A copula approach. + Generally, ETFs are not very volatile and so mean-reversion did not provide many trading opportunities. There are only 91 trades during 5 years for cointegration method. It is observed that the use of copula in pairs trading provides more trading opportunities as it does not require any rigid assumptions according to Liew R Q, Wu Y. - Pairs trading A copula approach.

diff --git a/04 Strategy Library/03 Pairs Trading-Copula vs Cointegration/06 Algorithm.html b/04 Strategy Library/03 Pairs Trading-Copula vs Cointegration/06 Algorithm.html index 21099b5..228f289 100755 --- a/04 Strategy Library/03 Pairs Trading-Copula vs Cointegration/06 Algorithm.html +++ b/04 Strategy Library/03 Pairs Trading-Copula vs Cointegration/06 Algorithm.html @@ -4,7 +4,7 @@
- +
@@ -14,6 +14,6 @@
- +
diff --git "a/04 Strategy Library/03 Pairs Trading-Copula vs Cointegration/06 \347\256\227\346\263\225.cn.html" "b/04 Strategy Library/03 Pairs Trading-Copula vs Cointegration/06 \347\256\227\346\263\225.cn.html" index 932854a..c5d9f52 100644 --- "a/04 Strategy Library/03 Pairs Trading-Copula vs Cointegration/06 \347\256\227\346\263\225.cn.html" +++ "b/04 Strategy Library/03 Pairs Trading-Copula vs Cointegration/06 \347\256\227\346\263\225.cn.html" @@ -4,7 +4,7 @@
- +
@@ -14,6 +14,6 @@
- +
diff --git a/04 Strategy Library/04 The Dynamic Breakout II Strategy/04 Algorithm.html b/04 Strategy Library/04 The Dynamic Breakout II Strategy/04 Algorithm.html index 58173b8..3358861 100755 --- a/04 Strategy Library/04 The Dynamic Breakout II Strategy/04 Algorithm.html +++ b/04 Strategy Library/04 The Dynamic Breakout II Strategy/04 Algorithm.html @@ -4,7 +4,7 @@
- +

@@ -13,6 +13,6 @@

- +
diff --git a/04 Strategy Library/06 Can Crude Oil Predict Equity Returns/05 Algorithm.html b/04 Strategy Library/06 Can Crude Oil Predict Equity Returns/05 Algorithm.html index 01b99d6..0115518 100755 --- a/04 Strategy Library/06 Can Crude Oil Predict Equity Returns/05 Algorithm.html +++ b/04 Strategy Library/06 Can Crude Oil Predict Equity Returns/05 Algorithm.html @@ -4,6 +4,6 @@
- +
diff --git a/04 Strategy Library/07 Intraday Dynamic Pairs Trading using Correlation and Cointegration Approach/06 Algorithm.html b/04 Strategy Library/07 Intraday Dynamic Pairs Trading using Correlation and Cointegration Approach/06 Algorithm.html index 69b6365..3d55776 100755 --- a/04 Strategy Library/07 Intraday Dynamic Pairs Trading using Correlation and Cointegration Approach/06 Algorithm.html +++ b/04 Strategy Library/07 Intraday Dynamic Pairs Trading using Correlation and Cointegration Approach/06 Algorithm.html @@ -1,6 +1,6 @@
- +
diff --git "a/04 Strategy Library/07 Intraday Dynamic Pairs Trading using Correlation and Cointegration Approach/06 \347\256\227\346\263\225.cn.html" "b/04 Strategy Library/07 Intraday Dynamic Pairs Trading using Correlation and Cointegration Approach/06 \347\256\227\346\263\225.cn.html" index 69b6365..3d55776 100644 --- "a/04 Strategy Library/07 Intraday Dynamic Pairs Trading using Correlation and Cointegration Approach/06 \347\256\227\346\263\225.cn.html" +++ "b/04 Strategy Library/07 Intraday Dynamic Pairs Trading using Correlation and Cointegration Approach/06 \347\256\227\346\263\225.cn.html" @@ -1,6 +1,6 @@
- +
diff --git a/04 Strategy Library/08 The Momentum Strategy Based on the Low Frequency Component of Forex Market/05 Algorithm.html b/04 Strategy Library/08 The Momentum Strategy Based on the Low Frequency Component of Forex Market/05 Algorithm.html index 03b3ba2..f9505bd 100755 --- a/04 Strategy Library/08 The Momentum Strategy Based on the Low Frequency Component of Forex Market/05 Algorithm.html +++ b/04 Strategy Library/08 The Momentum Strategy Based on the Low Frequency Component of Forex Market/05 Algorithm.html @@ -1,6 +1,6 @@
- +
diff --git a/04 Strategy Library/09 Stock Selection Strategy Based on Fundamental Factors/04 Algorithm.html b/04 Strategy Library/09 Stock Selection Strategy Based on Fundamental Factors/04 Algorithm.html index bcf0bc2..8586edb 100755 --- a/04 Strategy Library/09 Stock Selection Strategy Based on Fundamental Factors/04 Algorithm.html +++ b/04 Strategy Library/09 Stock Selection Strategy Based on Fundamental Factors/04 Algorithm.html @@ -1,6 +1,6 @@
- +
diff --git "a/04 Strategy Library/09 Stock Selection Strategy Based on Fundamental Factors/04 \347\256\227\346\263\225.cn.html" "b/04 Strategy Library/09 Stock Selection Strategy Based on Fundamental Factors/04 \347\256\227\346\263\225.cn.html" index bcf0bc2..d1a72fa 100644 --- "a/04 Strategy Library/09 Stock Selection Strategy Based on Fundamental Factors/04 \347\256\227\346\263\225.cn.html" +++ "b/04 Strategy Library/09 Stock Selection Strategy Based on Fundamental Factors/04 \347\256\227\346\263\225.cn.html" @@ -1,6 +1,6 @@
- +
diff --git a/04 Strategy Library/09 Stock Selection Strategy Based on Fundamental Factors/05 References.html b/04 Strategy Library/09 Stock Selection Strategy Based on Fundamental Factors/05 References.html index 145c7bf..4d6f9c3 100644 --- a/04 Strategy Library/09 Stock Selection Strategy Based on Fundamental Factors/05 References.html +++ b/04 Strategy Library/09 Stock Selection Strategy Based on Fundamental Factors/05 References.html @@ -1,5 +1,5 @@
  1. - Factor Based Stock Selection Model for Turkish Equities, 2015, Ayhan Yüksel Online Copy + Factor Based Stock Selection Model for Turkish Equities, 2015, Ayhan Yüksel Online Copy
diff --git "a/04 Strategy Library/09 Stock Selection Strategy Based on Fundamental Factors/05 \345\217\202\350\200\203\346\226\207\347\214\256.cn.html" "b/04 Strategy Library/09 Stock Selection Strategy Based on Fundamental Factors/05 \345\217\202\350\200\203\346\226\207\347\214\256.cn.html" index 145c7bf..4d6f9c3 100644 --- "a/04 Strategy Library/09 Stock Selection Strategy Based on Fundamental Factors/05 \345\217\202\350\200\203\346\226\207\347\214\256.cn.html" +++ "b/04 Strategy Library/09 Stock Selection Strategy Based on Fundamental Factors/05 \345\217\202\350\200\203\346\226\207\347\214\256.cn.html" @@ -1,5 +1,5 @@
  1. - Factor Based Stock Selection Model for Turkish Equities, 2015, Ayhan Yüksel Online Copy + Factor Based Stock Selection Model for Turkish Equities, 2015, Ayhan Yüksel Online Copy
diff --git a/04 Strategy Library/10 Short-Term Reversal Strategy in Stocks/01 Abstract.html b/04 Strategy Library/10 Short-Term Reversal Strategy in Stocks/01 Abstract.html index eae0057..e1419ee 100755 --- a/04 Strategy Library/10 Short-Term Reversal Strategy in Stocks/01 Abstract.html +++ b/04 Strategy Library/10 Short-Term Reversal Strategy in Stocks/01 Abstract.html @@ -1,8 +1,8 @@

- This strategy is called Short-Term Reversal Strategy which is discussed in detail in the paper written by Wilma de Groot, Joop Huij and Weili Zhou (2011) titled "Another look at trading costs and short-term reversal profits". The standard reversal strategy takes the whole universe of stocks into consideration, while this paper limits the stock universe only to large cap stocks so that trading costs could be significantly reduced. -

-

- One simple version of this strategy could be described like this: The investment universe consists of 100 biggest companies by market capitalization. We go long on the 10% stocks which have the lowest performances in the last month while going short on the 10% stocks with the highest ones. The portfolio is rebalanced weekly. - In the paper, however, strategies with different investment universes and different rebalancing frequencies are all backtested. The results show that, the larger the size of the investment universe, the larger the trading costs caused by extensively trading in small cap stocks which are less liquid; and trading costs become substantially lower when the rebalancing frequency is decreased from daily to weekly, but so do gross returns. - In this tutorial, we only use 100 stocks with weekly rebalancing for illustration. + In this tutorial, we implement a version of the short-term reversal strategy published by De Groot, Huij, & Zhou + (2012). The strategy works by observing the returns of each security in the universe over the previous month. Every + week, the algorithm longs the worst performers and shorts the top performers. The original strategy outlined in the + literature considers the entire universe of stocks when trading. To reduce trading costs, we limit our universe to + the most liquid large cap stocks. Our analysis shows the strategy underperforms the S&P 500 index during all our + backtest periods except the 2020 market crash.

diff --git a/04 Strategy Library/10 Short-Term Reversal Strategy in Stocks/02 Method.html b/04 Strategy Library/10 Short-Term Reversal Strategy in Stocks/02 Method.html index a666b03..8b9f021 100755 --- a/04 Strategy Library/10 Short-Term Reversal Strategy in Stocks/02 Method.html +++ b/04 Strategy Library/10 Short-Term Reversal Strategy in Stocks/02 Method.html @@ -1,103 +1,141 @@

- The strategy code mainly consists of three parts: Initialization, Warm Up, and Weekly Rebalancing. + The strategy code mainly consists of four parts: Initialization, Universe Selection, OnData, and OnSecuritiesChanged.

-

Step 1: Initialization

+

Algorithm Initialization

- In the Initialize function, we set up look-back period, beginning cash balance, the size of the investment universe, the number of traded stocks, etc. We use self._numOfWeeks to count?the number of weeks that have passed since the start date, and self._LastDay to indicate whether it is a new week. self._ifWarmUp is true when the self._numOfWeeks is 3, which means as long as next week's data come, we can make our investment decisions.??self._stocks is a list containing all the symbols of the 100 stocks that are taken into consideration. self._values is a dictionary with keys the stock symbols and values the lists containing the prices of stock each week since 4 weeks ago. + When initializing the algorithm, we add a coarse universe selection method and specify several parameters to use + when selecting securities.

-
- -
    def Initialize(self):
-        self.SetStartDate(2005, 1, 1)
-        self.SetEndDate(2017, 5, 10)
-        self.SetCash(1000000)
-        
+
+class ShortTimeReversal(QCAlgorithm):
+    def Initialize(self):
+        # ...
+      
         self.UniverseSettings.Resolution = Resolution.Daily
-        self.AddUniverse(self.CoarseSelectionFunction)
-        self._numberOfSymbols = 100
-        self._numberOfTradings = int(0.1 * self._numberOfSymbols)
-        
-        self._numOfWeeks = 0
-        self._LastDay = -1
-        self._ifWarmUp = False
-        
-        self._stocks = []
-        self._values = {}
+        self.AddUniverse(self.SelectCoarse)
+      
+        self.dollar_volume_selection_size = 100
+        self.roc_selection_size = int(0.1 * self.dollar_volume_selection_size)
+      
+        self.lookback = 22
+        self.roc_by_symbol = {}
+        self.week = 0
+
 
-

- Also, we need to use?CoarseSelectionFunction to select 100 qualified stocks from the total stock universe. Here, we sort the total stock universe by each stock's DollarVolume in decreasing order. Then, we select the first 100 stocks that have the largest DollarVolume among all the stocks in the universe. -

-
-
-def CoarseSelectionFunction(self, coarse):
-     sortedByDollarVolume = sorted(coarse, key=lambda x: x.DollarVolume, reverse=True)
-     top100 = sortedByDollarVolume[:self._numberOfSymbols]
-     return [i.Symbol for i in top100]
-
-
-

Step 2:Warm Up

+ +

Universe Selection

- Before we are able to make our investment decisions, we must have at least 4 weeks' data to calculate the performance, i.e. the monthly return, of each stock. Hence, we need a warm up period as long as 3 weeks to accumulate price series, so that once the fourth week's data come we can calculate?the return of the whole month. + The coarse universe selection method creates a RateOfChange + indicator for each of the top 100 + most liquid securities in the market. Upon creation, the indicator is manually warmed-up with historical closing + prices. After the indicators are ready, the universe selects the securities with the 10 best and 10 worst + RateOfChange values.

+
+class ShortTimeReversal(QCAlgorithm):
+    # ...
+
+    def SelectCoarse(self, coarse):
+        
+        # We should keep a dictionary for all securities that have been selected
+        for cf in coarse:
+            symbol = cf.Symbol
+            if symbol in self.roc_by_symbol:
+                self.roc_by_symbol[symbol].Update(cf.EndTime, cf.AdjustedPrice)
+
+        # Refresh universe each week
+        week_number = self.Time.date().isocalendar()[1]
+        if week_number == self.week:
+            return Universe.Unchanged
+        self.week = week_number
+
+        # sort and select by dollar volume
+        sortedByDollarVolume = sorted(coarse, key=lambda x: x.DollarVolume, reverse=True)
+        selected = {cf.Symbol: cf for cf in sortedByDollarVolume[:self.dollar_volume_selection_size]} 
+        
+        # New selections need a history request to warm up the indicator
+        symbols = [k for k in selected.keys()
+            if k not in self.roc_by_symbol or not self.roc_by_symbol[k].IsReady]
+
+        if symbols:
+            history = self.History(symbols, self.lookback, Resolution.Daily)
+            if history.empty:
+                self.Log(f'No history for {", ".join([x.Value for x in symbols])}')
+            history = history.close.unstack(0)
+
+            for symbol in symbols:
 
-
self._stocks = []
-self.uni_symbol = None
-symbols = self.UniverseManager.Keys
-for i in symbols:
-        if str(i.Value) == "QC-UNIVERSE-COARSE-USA":
-                self.uni_symbol = i
-        for i in self.UniverseManager[self.uni_symbol].Members:
-                self._stocks.append(i.Value.Symbol)
-                self._values[i.Value.Symbol] = [self.Securities[i.Value.Symbol].Price]
+                if symbol not in history:
+                    continue
 
+                # Create and warm-up the RateOfChange indicator
+                roc = RateOfChange(self.lookback)
+                for time, price in history[symbol].dropna().iteritems():
+                    roc.Update(time, price)
+                
+                if roc.IsReady:
+                    self.roc_by_symbol[symbol] = roc
+        
+        # Sort the symbols by their ROC values
+        selectedRateOfChange = {}
+        for symbol in selected.keys():
+            if symbol in self.roc_by_symbol:
+                selectedRateOfChange[symbol] = self.roc_by_symbol[symbol]
+        sortedByRateOfChange = sorted(selectedRateOfChange.items(), key=lambda kv: kv[1], reverse=True)
+        
+        # Define the top and the bottom to buy and sell
+        self.rocTop = [x[0] for x in sortedByRateOfChange[:self.roc_selection_size]]
+        self.rocBottom = [x[0] for x in sortedByRateOfChange[-self.roc_selection_size:]]
+        
+        return self.rocTop + self.rocBottom
 
-

- We get all the symbols of qualified stocks from UniverseManager and keep them in self._stocks which is a list. Then we create for each key in the dictionary self._values a list where its first week's price is stored. And every time new data come, we append the new price to the end of the list of each stock. -

-
-
for stock in self._stocks:
-        self._values[stock].append(self.Securities[stock].Price)
-
-

Step 3:Weekly Rebalancing

+

The OnData Method

- After the warm-up period, we calculate monthly returns every week and based on the returns, we make our investment decisions. + As new data is passed to the OnData method, we issue orders to form a long-short portfolio. We long the securities + with the lowest RateOfChange values and short those with the largest values. After rebalancing, we clear the + `rocTop` and `rocBottom` lists to ensure we don’t trade again until the universe is refreshed.

-
+
+class ShortTimeReversal(QCAlgorithm):
+    # ...
 
-
returns = {}
-for stock in self._stocks:
-        newPrice = self.Securities[stock].Price
-        oldPrice = self._values[stock].pop(0)
-        self._values[stock].append(newPrice)
-        returns[stock] = newPrice/oldPrice
+    def OnData(self, data):
+        # Rebalance
+        for symbol in self.rocTop:
+            self.SetHoldings(symbol, -0.5/len(self.rocTop))
+        for symbol in self.rocBottom:
+            self.SetHoldings(symbol, 0.5/len(self.rocBottom))
+        
+        # Clear the list of securities we have placed orders for
+        # to avoid new trades before the next universe selection
+        self.rocTop.clear() 
+        self.rocBottom.clear()
 
+ +

The OnSecuritiesChanged Method

- Every week when new data come, we use them along with the data four weeks ago to calculate the monthly returns. At the same time, we remove the oldest data from our lists. This step is essential to prevent memory size exceeding the limit. + We are rebalancing the portfolio on a weekly basis, but securities can leave our defined universe between rebalance + days. To accommodate this, we liquidate any securities that are removed from the universe in the + OnSecuritiesChanged method.

-
+
+class ShortTimeReversal(QCAlgorithm):
+    # ...
 
-
newArr = [(v,k) for k,v in returns.items()]
-newArr.sort()
-for ret, stock in newArr[self._numberOfTradings:-self._numberOfTradings]:
-        self.SetHoldings(stock, 0)
-for ret, stock in newArr[0:self._numberOfTradings]:
-        self.SetHoldings(stock, 0.5/self._numberOfTradings)
-for ret, stock in newArr[-self._numberOfTradings:]:
-        self.SetHoldings(stock, -0.5/self._numberOfTradings)
+    def OnSecuritiesChanged(self, changes):
+        for security in changes.RemovedSecurities:
+            self.Liquidate(security.Symbol, 'Removed from Universe')
 
-
-

- Finally, we sort the returns in increasing order. For the stocks whose monthly returns fall into the first 10% (performed badly in last month), we long them; For those fall into the last 10% (performed well in last month), we short them. Others (between 10% and 90%) will be set to 0. -

+ \ No newline at end of file diff --git a/04 Strategy Library/10 Short-Term Reversal Strategy in Stocks/03 Summary.html b/04 Strategy Library/10 Short-Term Reversal Strategy in Stocks/03 Summary.html deleted file mode 100755 index 0c2b46e..0000000 --- a/04 Strategy Library/10 Short-Term Reversal Strategy in Stocks/03 Summary.html +++ /dev/null @@ -1,5 +0,0 @@ -

- In the paper, the look-back period is from 1990 to 2009. However, we want to test whether the strategy is still profitable in the new time period. Hence we use different look-back periods instead. - If we begin from 2005 and end in 2017, there will be a total return of 131.50%. Although to some extent the performance of this strategy is dependent on different market situations,?nevertheless, in either situation mentioned above, this strategy could significantly beat the S&P 500 benchmark. - Further research and backtesting could be done on different look-back periods, rebalancing frequencies, investment universes, numbers of traded stocks, etc. -

diff --git a/04 Strategy Library/10 Short-Term Reversal Strategy in Stocks/04 Algorithm.html b/04 Strategy Library/10 Short-Term Reversal Strategy in Stocks/04 Algorithm.html index 009e778..c2e37d5 100755 --- a/04 Strategy Library/10 Short-Term Reversal Strategy in Stocks/04 Algorithm.html +++ b/04 Strategy Library/10 Short-Term Reversal Strategy in Stocks/04 Algorithm.html @@ -1,6 +1,6 @@
- +
diff --git a/04 Strategy Library/10 Short-Term Reversal Strategy in Stocks/05 References.html b/04 Strategy Library/10 Short-Term Reversal Strategy in Stocks/05 References.html deleted file mode 100644 index 6c1e761..0000000 --- a/04 Strategy Library/10 Short-Term Reversal Strategy in Stocks/05 References.html +++ /dev/null @@ -1,5 +0,0 @@ -
    -
  1. - Groot, Wilma (2011). Another look at trading costs and short-term reversal profit, page 1,? Online Copy -
  2. -
diff --git a/04 Strategy Library/10 Short-Term Reversal Strategy in Stocks/05 Relative Performance.html b/04 Strategy Library/10 Short-Term Reversal Strategy in Stocks/05 Relative Performance.html new file mode 100644 index 0000000..3d18c34 --- /dev/null +++ b/04 Strategy Library/10 Short-Term Reversal Strategy in Stocks/05 Relative Performance.html @@ -0,0 +1,56 @@ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Period NameStart DateEnd DateStrategySharpeVariance
5 Year Backtest1/1/20161/1/2021Strategy0.240.058
Benchmark0.8250.028
2020 Crash2/19/20203/23/2020Strategy-1.0250.917
Benchmark-1.40.474
2020 Recovery3/23/20206/8/2020Strategy1.6880.16
Benchmark8.7650.103
+
+ diff --git a/04 Strategy Library/10 Short-Term Reversal Strategy in Stocks/07 Market & Competition Qualification.html b/04 Strategy Library/10 Short-Term Reversal Strategy in Stocks/07 Market & Competition Qualification.html new file mode 100644 index 0000000..1c0cad5 --- /dev/null +++ b/04 Strategy Library/10 Short-Term Reversal Strategy in Stocks/07 Market & Competition Qualification.html @@ -0,0 +1,13 @@ +

+ Although this strategy passes several of the + metrics required for Alpha Streams + and the Quant League competition, it requires further work to pass the following requirements: +

+ + diff --git a/04 Strategy Library/10 Short-Term Reversal Strategy in Stocks/08 Conclusion.html b/04 Strategy Library/10 Short-Term Reversal Strategy in Stocks/08 Conclusion.html new file mode 100644 index 0000000..ae81428 --- /dev/null +++ b/04 Strategy Library/10 Short-Term Reversal Strategy in Stocks/08 Conclusion.html @@ -0,0 +1,16 @@ +

+ The short-term reversal strategy implemented in this tutorial produced a lower Sharpe ratio than the S&P + 500 index ETF benchmark over all our testing periods except during the 2020 market crash. To continue the + development of this strategy, future areas of research include: +

+ +

+ To continue the development of this strategy, future areas of research include: +

+ + \ No newline at end of file diff --git a/04 Strategy Library/10 Short-Term Reversal Strategy in Stocks/09 References.html b/04 Strategy Library/10 Short-Term Reversal Strategy in Stocks/09 References.html new file mode 100644 index 0000000..2a52089 --- /dev/null +++ b/04 Strategy Library/10 Short-Term Reversal Strategy in Stocks/09 References.html @@ -0,0 +1,6 @@ +
    +
  1. + de Groot, Wilma and Huij, Joop and Zhou, Weili, Another Look at Trading Costs and Short-Term Reversal + Profits (July 1, 2011). Online copy +
  2. +
\ No newline at end of file diff --git a/04 Strategy Library/100 Trading with WTI BRENT Spread/03 Algorithm.html b/04 Strategy Library/100 Trading with WTI BRENT Spread/03 Algorithm.html index 15151d8..ccc8b22 100644 --- a/04 Strategy Library/100 Trading with WTI BRENT Spread/03 Algorithm.html +++ b/04 Strategy Library/100 Trading with WTI BRENT Spread/03 Algorithm.html @@ -1,6 +1,6 @@
- +
diff --git "a/04 Strategy Library/100 Trading with WTI BRENT Spread/03 \347\256\227\346\263\225.cn.html" "b/04 Strategy Library/100 Trading with WTI BRENT Spread/03 \347\256\227\346\263\225.cn.html" index 15151d8..ccc8b22 100644 --- "a/04 Strategy Library/100 Trading with WTI BRENT Spread/03 \347\256\227\346\263\225.cn.html" +++ "b/04 Strategy Library/100 Trading with WTI BRENT Spread/03 \347\256\227\346\263\225.cn.html" @@ -1,6 +1,6 @@
- +
diff --git a/04 Strategy Library/102 Option Expiration Week Effect/03 Algorithm.html b/04 Strategy Library/102 Option Expiration Week Effect/03 Algorithm.html index 516d50a..7ff9460 100644 --- a/04 Strategy Library/102 Option Expiration Week Effect/03 Algorithm.html +++ b/04 Strategy Library/102 Option Expiration Week Effect/03 Algorithm.html @@ -1,6 +1,6 @@
- +
diff --git a/04 Strategy Library/1023 Intraday Arbitrage Between Index ETFs/05 Relative Performance.html b/04 Strategy Library/1023 Intraday Arbitrage Between Index ETFs/05 Relative Performance.html index fd71509..2d3e6c9 100644 --- a/04 Strategy Library/1023 Intraday Arbitrage Between Index ETFs/05 Relative Performance.html +++ b/04 Strategy Library/1023 Intraday Arbitrage Between Index ETFs/05 Relative Performance.html @@ -6,6 +6,7 @@ across all our testing periods is displayed in the table below.

+
@@ -72,6 +73,7 @@
+

diff --git a/04 Strategy Library/1026 Intraday ETF Momentum/05 Conclusion.html b/04 Strategy Library/1026 Intraday ETF Momentum/05 Conclusion.html index ff087ea..bad583b 100644 --- a/04 Strategy Library/1026 Intraday ETF Momentum/05 Conclusion.html +++ b/04 Strategy Library/1026 Intraday ETF Momentum/05 Conclusion.html @@ -7,6 +7,7 @@ A breakdown of the results from all of the testing periods can be seen in the table below.

+
@@ -73,6 +74,7 @@
+

diff --git a/04 Strategy Library/1027 Using News Sentiment to Predict Price Direction of Drug Manufacturers/01 Abstract.html b/04 Strategy Library/1027 Using News Sentiment to Predict Price Direction of Drug Manufacturers/01 Abstract.html new file mode 100644 index 0000000..d02e534 --- /dev/null +++ b/04 Strategy Library/1027 Using News Sentiment to Predict Price Direction of Drug Manufacturers/01 Abstract.html @@ -0,0 +1,9 @@ +

+ Several studies have found that press releases and other media can impact the perspective of investors. In this + tutorial, we implement an intraday strategy to capitalize on the upward drift in the stock prices of drug + manufacturers following positive news releases. Our findings show that when combining the effect with the + day-of-the-week anomaly documented by Berument & Kiymaz (2001), there is enough directional accuracy for the + trading system to remain profitable throughout the 2020 stock market crash. However, the algorithm + underperforms the S&P 500 market index ETF, SPY, over the same time period. The algorithm we design here is + inspired by the work of Isah, Shah, & Zulkernine (2018). +

diff --git a/04 Strategy Library/1027 Using News Sentiment to Predict Price Direction of Drug Manufacturers/02 Background.html b/04 Strategy Library/1027 Using News Sentiment to Predict Price Direction of Drug Manufacturers/02 Background.html new file mode 100644 index 0000000..60fe4eb --- /dev/null +++ b/04 Strategy Library/1027 Using News Sentiment to Predict Price Direction of Drug Manufacturers/02 Background.html @@ -0,0 +1,14 @@ +

+ The use of alternative data sets to forecast stock prices has increased in recent years as the fundamental and + technical analysis spaces increase in competition. Utilizing Natural Language Processing (NLP) techniques to + analyze the sentiment of news releases and other text related to publicly traded companies has caught the interest + of many quant researchers. Such online information is frequently released and can be interpreted in a virtually + unlimited number of ways, leading to a novel approach to determining the "societal mood" (Isah et al, 2018, p. 2) + towards a company. +

+ +

+ There are several ways to implement a NLP system. In this tutorial, we utilize a dictionary to quantify the + sentiment of news releases. The dictionary provided herein was sourced from Isah et al (2018), where it's use + achieved a 70% accuracy when targeting several hand-picked stocks in India's pharmaceutical industry. +

\ No newline at end of file diff --git a/04 Strategy Library/1027 Using News Sentiment to Predict Price Direction of Drug Manufacturers/03 Method.html b/04 Strategy Library/1027 Using News Sentiment to Predict Price Direction of Drug Manufacturers/03 Method.html new file mode 100644 index 0000000..ac080d3 --- /dev/null +++ b/04 Strategy Library/1027 Using News Sentiment to Predict Price Direction of Drug Manufacturers/03 Method.html @@ -0,0 +1,183 @@ +

Universe Selection

+

+ We implement a universe selection model that provides the trading system with companies classified by + MorningStar as being in the drug + manufacturing industry group. We narrow our universe to include only the drug manufacturers with the greatest PE + ratios and dollar volume. +

+
+
+def SelectCoarse(self, algorithm, coarse):
+    has_fundamentals = [c for c in coarse if c.HasFundamentalData]
+    sorted_by_dollar_volume = sorted(has_fundamentals, key=lambda c: c.DollarVolume, reverse=True)
+    return [ x.Symbol for x in sorted_by_dollar_volume[:self.coarse_size] ]
+
+def SelectFine(self, algorithm, fine):
+    drug_manufacturers = [f for f in fine if f.AssetClassification.MorningstarIndustryGroupCode == MorningstarIndustryGroupCode.DrugManufacturers]
+    sorted_by_pe = sorted(drug_manufacturers, key=lambda f: f.ValuationRatios.PERatio, reverse=True)
+    return [ x.Symbol for x in sorted_by_pe[:self.fine_size] ]
+
+
+ + +

Alpha Construction

+

+ The DrugNewsSentimentAlphaModel emits insights to take long intraday positions for securities that have positive + news sentiment. During construction of the model, we: +

+ + + +

+ The `bars_before_insight` parameter determines how many bars the alpha model should observe after the market opens + before emitting insights. Isah et al (2018) batch the news released by each company into 30-minute intervals + before analyzing the sentiment of the batch. In this tutorial, we follow a similar procedure by setting + `bars_before_insight` to 30. +

+ +
+
+class DrugNewsSentimentAlphaModel(AlphaModel):
+    symbol_data_by_symbol = {}
+    sentiment_by_phrase = SentimentByPhrase.dictionary
+    max_phrase_words = max([len(phrase.split()) for phrase in sentiment_by_phrase.keys()])
+    sign = lambda _, x: int(x and (1, -1)[x < 0])
+    
+    def __init__(self, bars_before_insight=30):
+        self.bars_before_insight = bars_before_insight
+
+
+ +

Alpha Securities Management

+

+ When a new security is added to the universe, we create a SymbolData object for it to store information unique to + each security. The management of the SymbolData objects occurs in the alpha model's OnSecuritiesChanged method. +

+ +
+
+def OnSecuritiesChanged(self, algorithm, changes):
+    for security in changes.AddedSecurities:
+        self.symbol_data_by_symbol[security.Symbol] = SymbolData(security, algorithm)
+    
+    for security in changes.RemovedSecurities:
+        symbol_data = self.symbol_data_by_symbol.pop(security.Symbol, None)
+        if symbol_data:
+            algorithm.RemoveSecurity(symbol_data.tiingo_symbol)
+
+
+ +

+ The definition of the SymbolData class is shown below. We add properties to it to track the cumulative sentiment + of news releases over time and the number of bars the alpha model has received for each security since the market + open. In the constructor, we save a reference to the security's exchange so we can access the market hours of the + exchange when generating insights. This is also where we initialize the + Tiingo news feed for each security. +

+ +
+
+class SymbolData:
+    cumulative_sentiment = 0
+    bars_seen_today = 0
+    
+    def __init__(self, security, algorithm):
+        self.exchange = security.Exchange
+        self.tiingo_symbol = algorithm.AddData(TiingoNews, security.Symbol).Symbol
+
+
+ + +

Alpha Update

+

+ As new Tiingo objects are provided to the alpha model's Update method, we update the cumulative sentiment for each + security. The cumulative sentiment counter is reset at each market close. Therefore, when we emit insights + 30-minutes after the open, we are considering the sentiment of the news articles released from the previous close + to the current time. We employ the findings of Berument & Kiymaz (2001), restricting the alpha model's trading to + Wednesday, the most profitable day of the week. Positions are entered 30-minutes after the open and exited at the + close. +

+ +
+
+def Update(self, algorithm, data):
+    insights = []
+        
+    for symbol, symbol_data in self.symbol_data_by_symbol.items():
+    
+        # If it's after-hours or within 30-minutes of the open, update
+        # cumulative sentiment for each symbol    
+        if symbol_data.bars_seen_today < self.bars_before_insight:
+            tiingo_symbol = symbol_data.tiingo_symbol
+            if data.ContainsKey(tiingo_symbol) and data[tiingo_symbol] is not None:
+                article = data[tiingo_symbol]
+                symbol_data.cumulative_sentiment += self.CalculateSentiment(article)
+    
+        if data.ContainsKey(symbol) and data[symbol] is not None:
+            symbol_data.bars_seen_today += 1
+
+            # 30-mintes after the open, emit insights in the direction of the cumulative sentiment.
+            # Only emit insights on Wednesdays to capture the analomaly documented by Berument and 
+            # Kiymaz (2001).
+            if symbol_data.bars_seen_today == self.bars_before_insight and data.Time.weekday() == 2:
+                    next_close_time = symbol_data.exchange.Hours.GetNextMarketClose(data.Time, False)
+                    direction = self.sign(symbol_data.cumulative_sentiment)
+                    if direction == 0:
+                        continue
+                    insight = Insight.Price(symbol, 
+                                            next_close_time - timedelta(minutes=2),
+                                            direction)
+                    insights.append(insight)
+    
+            # At the close, reset the cumulative sentiment
+            if not symbol_data.exchange.DateTimeIsOpen(data.Time):
+                symbol_data.cumulative_sentiment = 0
+                symbol_data.bars_seen_today = 0
+    
+    return insights
+
+
+ + +

Calculating Sentiment

+

+ We define the following helper method to return the sentiment of a Tiingo news article by analyzing the article's + title and description. The `sentiment_by_phrase` dictionary was retrieved from queensbamlab's + NewsSentiment GitHub repository. Although we have + adjusted the dictionary to lowercase and removed some redundancies, this is the same dictionary used by Isah et + al (2018). "The dictionary was created by leveraging author's domain expertise and thorough analysis of news + articles over the years" (p. 3). +

+ +
+
+def CalculateSentiment(self, article):
+    sentiment = 0
+    for content in (article.Title, article.Description):
+        words = content.lower().split()
+        for num_words in range(1, self.max_phrase_words + 1):
+            for gram in ngrams(words, num_words):
+                phrase = ' '.join(gram)
+                if phrase in self.sentiment_by_phrase.keys():
+                    sentiment += self.sentiment_by_phrase[phrase]
+    return sentiment
+
+
+ + +

Portfolio Construction & Trade Execution

+

+ Following the guidelines of Alpha Streams and the + Quant League competition, we utilize the + + EqualWeightingPortfolioConstructionModel and the + + ImmediateExecutionModel. +

+ diff --git a/04 Strategy Library/1027 Using News Sentiment to Predict Price Direction of Drug Manufacturers/04 Algorithm.html b/04 Strategy Library/1027 Using News Sentiment to Predict Price Direction of Drug Manufacturers/04 Algorithm.html new file mode 100644 index 0000000..43dfb6f --- /dev/null +++ b/04 Strategy Library/1027 Using News Sentiment to Predict Price Direction of Drug Manufacturers/04 Algorithm.html @@ -0,0 +1,6 @@ +
+
+
+ +
+
\ No newline at end of file diff --git a/04 Strategy Library/1027 Using News Sentiment to Predict Price Direction of Drug Manufacturers/05 Conclusion.html b/04 Strategy Library/1027 Using News Sentiment to Predict Price Direction of Drug Manufacturers/05 Conclusion.html new file mode 100644 index 0000000..8f0a19e --- /dev/null +++ b/04 Strategy Library/1027 Using News Sentiment to Predict Price Direction of Drug Manufacturers/05 Conclusion.html @@ -0,0 +1,27 @@ +

+ We conclude that deploying the sentiment analysis strategy on the US drug manufacturing industry does not provide + as accurate of results as found by Isah et al (2018). Only after restricting trading to the most profitable day of + the week (Berument & Kiymaz, 2001) does the strategy achieve profitability over our testing period. Overall, the + strategy produces a Sharpe ratio of 0.116, while the + SPY benchmark + produces a 0.971 Sharpe ratio during the same period. We attribute the decrease in performance to the commissions + and spread costs simulated by LEAN. +

+ +

+To continue the development of this strategy, future areas of research include: +

+ + \ No newline at end of file diff --git a/04 Strategy Library/1027 Using News Sentiment to Predict Price Direction of Drug Manufacturers/06 References.html b/04 Strategy Library/1027 Using News Sentiment to Predict Price Direction of Drug Manufacturers/06 References.html new file mode 100644 index 0000000..8f8f421 --- /dev/null +++ b/04 Strategy Library/1027 Using News Sentiment to Predict Price Direction of Drug Manufacturers/06 References.html @@ -0,0 +1,11 @@ +
    +
  1. + Shah, Dev, Haruna Isah, and Farhana Zulkernine. “Predicting the Effects of News Sentiments on the Stock Market.” + 2018 IEEE International Conference on Big Data (Big Data) (2018). + Online copy +
  2. +
  3. + Berument, Hakan and Kiymaz, Halil, The Day of the Week Effect on Stock Market Volatility (2001). Journal of + Economics and Finance, Vol.25, No.2, pp. 181-193. Online copy +
  4. +
\ No newline at end of file diff --git a/04 Strategy Library/1028 Ichimoku Clouds in the Energy Sector/05 Relative Performance.html b/04 Strategy Library/1028 Ichimoku Clouds in the Energy Sector/05 Relative Performance.html index a1d1610..07a20e4 100644 --- a/04 Strategy Library/1028 Ichimoku Clouds in the Energy Sector/05 Relative Performance.html +++ b/04 Strategy Library/1028 Ichimoku Clouds in the Energy Sector/05 Relative Performance.html @@ -17,6 +17,7 @@ frames, implying that the strategy has more consistent returns than the benchmark.

+
@@ -83,6 +84,7 @@
+

We find the lack of performance for this strategy is not largely attributed to the transaction costs. After diff --git a/04 Strategy Library/1030 G-Score Investing/01 Abstract.html b/04 Strategy Library/1030 G-Score Investing/01 Abstract.html new file mode 100644 index 0000000..248865d --- /dev/null +++ b/04 Strategy Library/1030 G-Score Investing/01 Abstract.html @@ -0,0 +1,3 @@ +

+ In this tutorial, we apply G-Score Investing to choose a Universe of stocks to invest in. +

diff --git a/04 Strategy Library/1030 G-Score Investing/02 Introduction.html b/04 Strategy Library/1030 G-Score Investing/02 Introduction.html new file mode 100644 index 0000000..b26b9f7 --- /dev/null +++ b/04 Strategy Library/1030 G-Score Investing/02 Introduction.html @@ -0,0 +1,10 @@ +

+ Analyzing a company’s fundamentals is a method of trading that doesn’t + rely purely on price and volume data. We will apply the use of computers to automate + the analysis of this data, and we will do so using a method of + Factor Investing, + the process of using different attributes, in this case, fundamental data, to choose + stocks to purchase. More specifically, we will use G-Score investing, and evaluate companies + on seven factors that we will detail later. We specifically choose companies with Book-to-Market + due to abnormal returns as a result of the Risk Premium Effect. +

diff --git a/04 Strategy Library/1030 G-Score Investing/03 Method.html b/04 Strategy Library/1030 G-Score Investing/03 Method.html new file mode 100644 index 0000000..3a493ab --- /dev/null +++ b/04 Strategy Library/1030 G-Score Investing/03 Method.html @@ -0,0 +1,57 @@ +

+ We first sort all companies that have fundamental data by their Book-to-Market ratio, and narrow our universe to the + bottom quartile. We measure the Book-to-Market ratio using + fine.FinancialStatements.BalanceSheet.NetTangibleAssets.TwelveMonths divided by + fine.MarketCap. In this strategy, we will use Technology as the industry of choice, thus, we further + narrow this universe to Technology stocks only. +

+ +

+ For each of the conditions that are described below, if met, one point will be added to the G-Score. + Thus, with seven factors, our G-Score can range from 0 to 7. We evaluate a company based on the following: +

+ + + + +

+ The fundamental data used in our algorithms is sourced from MorningStar, and to read more about our fundamental data, + please visit the Fundamentals section of our + documentation. +

+ +

+ Once we have computed the G-Scores for each of the securities, we long the securities with G-Scores of 5 or higher. +

+ diff --git a/04 Strategy Library/1030 G-Score Investing/04 Algorithm.html b/04 Strategy Library/1030 G-Score Investing/04 Algorithm.html new file mode 100644 index 0000000..2c62d81 --- /dev/null +++ b/04 Strategy Library/1030 G-Score Investing/04 Algorithm.html @@ -0,0 +1,6 @@ +
+
+
+ +
+
diff --git a/04 Strategy Library/1030 G-Score Investing/05 Results.html b/04 Strategy Library/1030 G-Score Investing/05 Results.html new file mode 100644 index 0000000..5f327af --- /dev/null +++ b/04 Strategy Library/1030 G-Score Investing/05 Results.html @@ -0,0 +1,5 @@ +

+ Since we use Technology as the industry, we decided to use Nasdaq-100, or ^NDX, as the benchmark, which we track + using the QQQ ETF. Our algorithm achieves a Sharpe Ratio of 0.778 from April 2016 to September 2020, and so it is + outperformed by simply holding QQQ, which yielded a Sharpe Ratio of 1.22 over the same period. +

\ No newline at end of file diff --git a/04 Strategy Library/1030 G-Score Investing/06 References.html b/04 Strategy Library/1030 G-Score Investing/06 References.html new file mode 100644 index 0000000..f21473a --- /dev/null +++ b/04 Strategy Library/1030 G-Score Investing/06 References.html @@ -0,0 +1,6 @@ +
    +
  1. + Mohanram, Partha S., Separating Winners from Losers Among Low Book-to-Market Stocks Using Financial Statement + nalysis (April 2004). Online Copy. +
  2. +
\ No newline at end of file diff --git a/04 Strategy Library/1031 SVM Wavelet Forecasting/01 Abstract.html b/04 Strategy Library/1031 SVM Wavelet Forecasting/01 Abstract.html new file mode 100644 index 0000000..a93480f --- /dev/null +++ b/04 Strategy Library/1031 SVM Wavelet Forecasting/01 Abstract.html @@ -0,0 +1,3 @@ +

+ In this tutorial, we apply an SVM Wavelet model in an attempt to forecast EURJPY prices. +

diff --git a/04 Strategy Library/1031 SVM Wavelet Forecasting/02 Introduction.html b/04 Strategy Library/1031 SVM Wavelet Forecasting/02 Introduction.html new file mode 100644 index 0000000..6fe7274 --- /dev/null +++ b/04 Strategy Library/1031 SVM Wavelet Forecasting/02 Introduction.html @@ -0,0 +1,10 @@ +

+ Several methods have been developed to forecast time-series, from ARIMA to Neural Networks. In this strategy, we + combine a Support Vector Machine (SVM) and Wavelets in an attempt to forecast EURJPY. Although SVMs are generally + used for classification problems, such as classifying proteins, they can also be applied in regression problems, valued + for their ability to handle non-linear data. Furthermore, Wavelets are often applied in Signal Processing applications. Wavelets allow us + to decompose a time-series into multiple components, where each individual component can be denoised using thresholding, and this + leads to a cleaner time-series after the components are recombined. To use these two models in conjunction, we first + decompose the EURJPY data into components using Wavelet decomposition, then we apply the SVM to forecast one time-step + ahead of each of the components. After we recombine the components, we get the aggregate forecast of our SVM-Wavelet model. +

diff --git a/04 Strategy Library/1031 SVM Wavelet Forecasting/03 Method.html b/04 Strategy Library/1031 SVM Wavelet Forecasting/03 Method.html new file mode 100644 index 0000000..5cd8e93 --- /dev/null +++ b/04 Strategy Library/1031 SVM Wavelet Forecasting/03 Method.html @@ -0,0 +1,56 @@ +

+ Given EURJPY data, our first step is to decompose our data into multiple resolutions. + We work with wavelets using the pywt package. For denoising, Daubechies and + Symlets are good choices for Wavelets, and we use Symlets 10 in our strategy. We create a Symlets 10 Wavelet + using the following:  +

+ +
+
+w = pywt.Wavelet('sym10')
+
+
+

To determine the length of the data we’d need for a certain number of levels after decomposition, we can solve for:

+\[log_{2}(\frac{len(data)}{wavelength-1})=levels\] +

+ Given the length of a Symlet 10 wavelet is 20, if we want three levels, we + solve for len(data) to get len(data) = 152, which means data would need to have at least + 152 values. Since we will denoise our components using thresholding, + we specify threshold = 0.5 to indicate the strength of the thresholding. + This threshold value can be any number between 0 and 1. +

+

To decompose our data, we use: 

+ +
+
+coeffs = pywt.wavedec(data, w)
+
+
+ +

For each component, we threshold/denoise the component (except for the first component, the approximation coefficients), + roll the values of the component one spot to the left, + and replace the last value of the component with a value forecasted from an SVM. This process looks like the following in code:

+ +
+
+for i in range(len(coeffs)):
+    if i > 0:
+        # we don't want to threshold the approximation coefficients
+        coeffs[i] = pywt.threshold(coeffs[i], threshold*max(coeffs[i]))
+    forecasted = __svm_forecast(coeffs[i])
+    coeffs[i] = np.roll(coeffs[i], -1)
+    coeffs[i][-1] = forecasted
+
+
+ +

The __svm_forecast method fits partitioned data to an SVM model then predicts one value into the + future, and can be found under SVMWavelet.py file under the Algorithm section

+

Once we forecast one value into the future, we can aggregate the forecasts by recombining the components into a simple time-series. We do this with:

+
+
+datarec = pywt.waverec(coeffs, w)
+
+
+

Since we want the aggregate forecast one time-step into the future, we return the last element of this time-series, or datarec[-1].

+ +

Our trading rules are simple: feed in the past 152 points of daily closing prices of EURJPY into our SVM Wavelet forecasting method, and divide that number by the current close of EURJPY to get the forecasted percent change. Then, we emit an Insight based on the direction of the percent change with the weight of the Insight as the absolute value of the percent change. We use the InsightWeightPortfolioConstructionModel so that the weight of the Insight determines the portfolio allocation percentage, which means larger forecasted moves will have a larger allocation.

diff --git a/04 Strategy Library/1031 SVM Wavelet Forecasting/04 Algorithm.html b/04 Strategy Library/1031 SVM Wavelet Forecasting/04 Algorithm.html new file mode 100644 index 0000000..935af6f --- /dev/null +++ b/04 Strategy Library/1031 SVM Wavelet Forecasting/04 Algorithm.html @@ -0,0 +1,6 @@ +
+
+
+ +
+
diff --git a/04 Strategy Library/1031 SVM Wavelet Forecasting/05 Results.html b/04 Strategy Library/1031 SVM Wavelet Forecasting/05 Results.html new file mode 100644 index 0000000..96be5b5 --- /dev/null +++ b/04 Strategy Library/1031 SVM Wavelet Forecasting/05 Results.html @@ -0,0 +1,8 @@ +

The performance of the algorithm was decent. Over the past five years, the algorithm achieved a Sharpe Ratio of 0.252, + while buying and holding SPY over the same period would have achieved a Sharpe Ratio of 0.713. Some ideas for improvement include:

+ +

If a user comes across any interesting results with modifications of this algorithm, we’d love to hear about it in the Community Forum.

\ No newline at end of file diff --git a/04 Strategy Library/1031 SVM Wavelet Forecasting/06 References.html b/04 Strategy Library/1031 SVM Wavelet Forecasting/06 References.html new file mode 100644 index 0000000..1cc8866 --- /dev/null +++ b/04 Strategy Library/1031 SVM Wavelet Forecasting/06 References.html @@ -0,0 +1,5 @@ +
    +
  1. + M. S. Raimundo and J. Okamoto, "SVR-wavelet adaptive model for forecasting financial time series," 2018 International Conference on Information and Computer Technologies (ICICT), DeKalb, IL, 2018, pp. 111-114, doi: 10.1109/INFOCT.2018.8356851. Online Copy. +
  2. +
\ No newline at end of file diff --git a/04 Strategy Library/1033 Gradient Boosting Model/01 Abstract.html b/04 Strategy Library/1033 Gradient Boosting Model/01 Abstract.html new file mode 100644 index 0000000..1d309c1 --- /dev/null +++ b/04 Strategy Library/1033 Gradient Boosting Model/01 Abstract.html @@ -0,0 +1,7 @@ +

+ In this tutorial, we train a Gradient Boosting Model (GBM) to forecast the intraday price movements of the SPY ETF using a + collection of technical indicators. The implementation is based on the research produced by Zhou et al (2013), where a GBM + was found to produce an annualized Sharpe ratio greater than 20. Our research shows that throughout a 5 year backtest, the + model underperforms the SPY with its current parameter set. However, we finish the tutorial with highlighting potential + areas of further research to improve the model’s performance. +

diff --git a/04 Strategy Library/1033 Gradient Boosting Model/02 Background.html b/04 Strategy Library/1033 Gradient Boosting Model/02 Background.html new file mode 100644 index 0000000..597b32d --- /dev/null +++ b/04 Strategy Library/1033 Gradient Boosting Model/02 Background.html @@ -0,0 +1,24 @@ +

+ A GBM is trained by setting the initial model prediction to the mean target value in the training set. The model then + iteratively builds regression trees to predict the model’s pseudo-residuals on the training set to tighten the fit. The + pseudo-residuals are the differences between the target value and the model’s prediction on the current training iteration + for each sample. The model’s predictions are made by summing the mean target value and the products of the learning rate + and the regression tree outputs. The full algorithm is shown here. +

+ +
+ Tutorial1033-gradient-boost-1 +
+ +

+ We provide technical indicator values as inputs to the GBM. The model is trained to predict the security’s return over the + next 10 minutes and the performance of the model’s predictions are assessed using the mean squared error loss function. +

+ +\[ MSE = \frac{\Sigma_{i=1}^n(y_i - \hat{y}_i)^2}{n} \] + +

+ Zhou et al (2013) utilize custom loss functions to fit their GBM in a manner that aims to maximize the profit-and-loss or + Sharpe ratio over the training data set. The attached notebook shows training the GBM with these custom loss functions + leads to poor model predictions. +

\ No newline at end of file diff --git a/04 Strategy Library/1033 Gradient Boosting Model/03 Method.html b/04 Strategy Library/1033 Gradient Boosting Model/03 Method.html new file mode 100644 index 0000000..7e88ae2 --- /dev/null +++ b/04 Strategy Library/1033 Gradient Boosting Model/03 Method.html @@ -0,0 +1,163 @@ +

Universe Selection

+

+ We use a ManualUniverseSelectionModel to subscribe to the SPY ETF. The algorithm is designed to work with minute and + second data resolutions. In our implementation, we use data on a minute resolution. +

+
+
+symbols = [ Symbol.Create("SPY", SecurityType.Equity, Market.USA) ]
+self.SetUniverseSelection( ManualUniverseSelectionModel(symbols) )
+self.UniverseSettings.Resolution = Resolution.Minute
+
+
+ + +

Alpha Construction

+

+ The GradientBoostingAlphaModel predicts the direction of the SPY at each timestep. Each position taken is held for + 10 minutes, although this duration is customizable in the constructor. During construction of this alpha model, we + simply set up a dictionary to hold a SymbolData object for each symbol in the universe. In the case where the + universe consists of multiple securities, the alpha model holds each with equal weighting. +

+
+
+class GradientBoostingAlphaModel(AlphaModel):
+    symbol_data_by_symbol = {}
+    
+    def __init__(self, hold_duration = 10):
+        self.hold_duration = hold_duration
+        self.weight = 1
+
+
+ + +

Alpha Securities Management

+

+ When a new security is added to the universe, we create a SymbolData object for it to store information unique to + the security. The management of the SymbolData objects occurs in the alpha model's OnSecuritiesChanged method. +

+
+
+def OnSecuritiesChanged(self, algorithm, changes):
+    for security in changes.AddedSecurities:
+        symbol = security.Symbol
+        self.symbol_data_by_symbol[symbol] = SymbolData(symbol, algorithm, self.hold_duration)
+            
+    for security in changes.RemovedSecurities:
+        symbol_data = self.symbol_data_by_symbol.pop(security.Symbol, None)
+        if symbol_data:
+            symbol_data.dispose()
+
+    self.weight = 1 / len(self.symbol_data_by_symbol)
+
+
+
+ + +

SymbolData Class

+

+ The SymbolData class is used in this algorithm to manage indicators, train the GBM, and produce trading predictions. + The constructor definition is shown below. The class is designed to train at the end of each month, using the + previous 4 weeks of data to fit the GBM that consists of 20 stumps (regression trees with 2 leaves). To ensure + overnight holds are avoided, the class uses + Scheduled Events to stop trading + near the market close. +

+
+
+class SymbolData:    
+    def __init__(self, symbol, algorithm, hold_duration, k_start=0.5, k_end=5,
+                    k_step=0.25, training_weeks=4, max_depth=1, num_leaves=2, num_trees=20,
+                    commission=0.02, spread_cost=0.03):
+        self.symbol = symbol
+        self.algorithm = algorithm
+        self.hold_duration = hold_duration
+        self.resolution = algorithm.UniverseSettings.Resolution
+        self.training_length = int(training_weeks * 5 * 6.5 * 60) # training_weeks in minutes
+        self.max_depth = max_depth
+        self.num_leaves = num_leaves
+        self.num_trees = num_trees
+        self.cost = commission + spread_cost
+
+        self.indicator_consolidators = []
+
+        # Train a model at the end of each month
+        self.model = None
+        algorithm.Train(algorithm.DateRules.MonthEnd(symbol),
+                        algorithm.TimeRules.BeforeMarketClose(symbol),
+                          self.train)
+
+        # Avoid overnight holds
+        self.allow_predictions = False
+        self.events = [
+            algorithm.Schedule.On(algorithm.DateRules.EveryDay(symbol),
+                                  algorithm.TimeRules.AfterMarketOpen(symbol, 0),
+                                  self.start_predicting),
+            algorithm.Schedule.On(algorithm.DateRules.EveryDay(symbol),
+                                  algorithm.TimeRules.BeforeMarketClose(symbol, hold_duration + 1),
+                                  self.stop_predicting)
+        ]
+
+        self.setup_indicators(k_start, k_end, k_step)
+        self.train()
+
+
+ + +

GBM Predictions

+

+ For brevity, we omit the model training logic. Although, the code can be seen in the attached backtest. To make + predictions, we define the following method inside the SymbolData class. A position is held in the predicted + direction only if the predicted return in that direction exceeds the cost of the trade. +

+
+
+def predict_direction(self):
+    if self.model is None or not self.allow_predictions:
+        return 0
+
+    input_data = [[]]
+    for _, indicators in self.indicators_by_indicator_type.items():
+        for indicator in indicators:
+            input_data[0].append(indicator.Current.Value)
+                
+    return_prediction = self.model.predict(input_data)
+    if return_prediction > self.cost:
+        return 1
+    if return_prediction < -self.cost:
+        return -1
+    return 0
+
+
+ + +

Alpha Update

+

+ As new TradeBars are provided to the alpha model's Update method, each SymbolData object makes a directional + prediction for its security. If the prediction is not flat, the alpha model emits an insight in that direction with + a duration of 10 minutes. +

+
+
+def Update(self, algorithm, data):
+    insights = []
+    for symbol, symbol_data in self.symbol_data_by_symbol.items():
+        direction = symbol_data.predict_direction()
+        if direction:
+            hold_duration = timedelta(minutes=self.hold_duration) # Should match universe resolution
+            insights.append(Insight.Price(symbol, hold_duration, direction, None, None, None, self.weight))
+
+    return insights
+
+
+ + +

Portfolio Construction & Trade Execution

+

+ Following the guidelines of Alpha Streams + and the Quant League competition, we + utilize the + InsightWeightingPortfolioConstructionModel and the + + ImmediateExecutionModel. +

diff --git a/04 Strategy Library/1033 Gradient Boosting Model/04 Algorithm.html b/04 Strategy Library/1033 Gradient Boosting Model/04 Algorithm.html new file mode 100644 index 0000000..223e7f3 --- /dev/null +++ b/04 Strategy Library/1033 Gradient Boosting Model/04 Algorithm.html @@ -0,0 +1,6 @@ +
+
+
+ +
+
\ No newline at end of file diff --git a/04 Strategy Library/1033 Gradient Boosting Model/05 Relative Performance.html b/04 Strategy Library/1033 Gradient Boosting Model/05 Relative Performance.html new file mode 100644 index 0000000..415eea9 --- /dev/null +++ b/04 Strategy Library/1033 Gradient Boosting Model/05 Relative Performance.html @@ -0,0 +1,56 @@ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Period NameStart DateEnd DateStrategySharpeVariance
5 Year Backtest9/1/20159/17/2020Strategy-0.7160.006
Benchmark0.8450.036
2020 Crash2/19/20203/23/2020Strategy-2.8790.101
Benchmark-1.2430.628
2020 Recovery3/23/20206/8/2020Strategy-2.3290.027
Benchmark13.7610.149
+
+ diff --git a/04 Strategy Library/1033 Gradient Boosting Model/06 Market & Competition Qualification.html b/04 Strategy Library/1033 Gradient Boosting Model/06 Market & Competition Qualification.html new file mode 100644 index 0000000..d2ac60d --- /dev/null +++ b/04 Strategy Library/1033 Gradient Boosting Model/06 Market & Competition Qualification.html @@ -0,0 +1,13 @@ +

+ Although this strategy passes several of the + metrics required for Alpha Streams + and the Quant League competition, it requires further work to pass the following requirements: +

+ + + diff --git a/04 Strategy Library/1033 Gradient Boosting Model/07 Conclusion.html b/04 Strategy Library/1033 Gradient Boosting Model/07 Conclusion.html new file mode 100644 index 0000000..10701d6 --- /dev/null +++ b/04 Strategy Library/1033 Gradient Boosting Model/07 Conclusion.html @@ -0,0 +1,17 @@ +

+ The GBM implemented in this tutorial has a lower Sharpe ratio than the S&P 500 index ETF benchmark over the periods + we tested. However, the strategy generates a lower annual variance over all the testing period, implying more + consistent returns than buy-and-hold. To continue the development of this strategy, future areas of research + include: +

+ + \ No newline at end of file diff --git a/04 Strategy Library/1033 Gradient Boosting Model/08 References.html b/04 Strategy Library/1033 Gradient Boosting Model/08 References.html new file mode 100644 index 0000000..385172c --- /dev/null +++ b/04 Strategy Library/1033 Gradient Boosting Model/08 References.html @@ -0,0 +1,5 @@ +
    +
  1. + Zhou, Nan and Cheng, Wen and Qin, Yichen and Yin, Zongcheng, Evolution of High Frequency Systematic Trading: A Performance-Driven Gradient Boosting Model (September 10, 2013). Online copy +
  2. +
\ No newline at end of file diff --git a/04 Strategy Library/1036 Gaussian Naive Bayes Model/01 Abstract.html b/04 Strategy Library/1036 Gaussian Naive Bayes Model/01 Abstract.html new file mode 100644 index 0000000..9421bb8 --- /dev/null +++ b/04 Strategy Library/1036 Gaussian Naive Bayes Model/01 Abstract.html @@ -0,0 +1,7 @@ +

+ Naïve Bayes models have become popular for their success in spam email filtering. In this tutorial, we train + Gaussian Naïve Bayes (GNB) classifiers to forecast the daily returns of stocks in the technology sector given the + historical returns of the sector. Our implementation shows the strategy has a greater Sharpe and lower variance + than the SPY ETF over a 5 year backtest and during the 2020 stock market crash. The algorithm we build here follows + the research done by Lu (2016) and Imandoust & Bolandraftar (2014). +

diff --git a/04 Strategy Library/1036 Gaussian Naive Bayes Model/02 Background.html b/04 Strategy Library/1036 Gaussian Naive Bayes Model/02 Background.html new file mode 100644 index 0000000..f576900 --- /dev/null +++ b/04 Strategy Library/1036 Gaussian Naive Bayes Model/02 Background.html @@ -0,0 +1,47 @@ +

+ Naïve Bayes models classify observations into a set of classes by utilizing + Bayes’ Theorem +

+ +\[\text{posterior} = \frac{ \text{prior } * \text{ likelihood} } {\text{evidence}}\] + +

+ In symbols, this translates to +

+ +\[P(c_i | x_1, ..., x_n) = \frac{P(c_i)P(x_1, ..., x_n | c_i)}{P(x_1, ..., x_n)}\] + +

+ where \(c_i\) represents one of the \(m\) classes and \(x_1, ..., x_n\) are the features. +

+ +

+ The Naïve Bayes model assumes the features are independent, so that +

+ +\[P(c_i | x_1, ..., x_n) = \frac{P(c_i)\prod_{j=1}^{n} P(x_j | c_i)}{P(x_1, ..., x_n)} \propto P(c_i)\prod_{j=1}^{n} P(x_j|c_i)\] + +

+ The class that is most probable given the observation is then determined by solving +

+ +\[\hat{c} = \arg\max_{i \in \{1, ..., m\}} P(c_i) \prod_{j=1}^{n} P(x_j | c_i)\] + + +

+ In our use case, the classes in the model are: positive, negative, or flat future return for a security. The features + are the last 4 daily returns of the universe constituents. Since we are dealing with continuous data, we extend the + model to a GNB model by replacing \(P(x_j|c_i)\) in the equation above. First, we find the mean \(\mu_j\) and standard + deviation \(\sigma_j^2\) of the \(x_j\) feature vector in the training set labeled class \(c_i\). A normal distribution + parameterized by \(\mu_j\) and \(\sigma_j^2\) is then used to determine the likelihood of the observations. If \(o\) is the + observation for the \(j\)th feature. The likelihood of the observation given the class \(c_i\) is +

+ +\[P(x_j = o | c_i) = \frac{1} {\sqrt{2 \pi{} \sigma{}_j^2 }}e^{- \frac{(o - \mu{}_j)^2} {2 \sigma{}_j^2}} \] + +

+ The mechanics of the GNB model can be seen visually in + this video. Note that the GNB model has 2 underlying + assumptions: the feature vectors are independent and normally distributed. We do not test for these properties, but + rather leave it as an area of future research. +

\ No newline at end of file diff --git a/04 Strategy Library/1036 Gaussian Naive Bayes Model/03 Video Walkthrough.html b/04 Strategy Library/1036 Gaussian Naive Bayes Model/03 Video Walkthrough.html new file mode 100644 index 0000000..3a3ef40 --- /dev/null +++ b/04 Strategy Library/1036 Gaussian Naive Bayes Model/03 Video Walkthrough.html @@ -0,0 +1,5 @@ + \ No newline at end of file diff --git a/04 Strategy Library/1036 Gaussian Naive Bayes Model/04 Method.html b/04 Strategy Library/1036 Gaussian Naive Bayes Model/04 Method.html new file mode 100644 index 0000000..8ef11c2 --- /dev/null +++ b/04 Strategy Library/1036 Gaussian Naive Bayes Model/04 Method.html @@ -0,0 +1,223 @@ +

Universe Selection

+

+ Following Lu (2016), we implement a custom universe selection model to select the largest stocks from the technology + sector. We restrict our universe to have a size of 10, but this can be easily customized via the `fine_size` + parameter in the constructor. +

+
+
+class BigTechUniverseSelectionModel(FundamentalUniverseSelectionModel):
+    def __init__(self, fine_size=10):
+        self.fine_size = fine_size
+        self.month = -1
+        super().__init__(True)
+
+    def SelectCoarse(self, algorithm, coarse):
+        if algorithm.Time.month == self.month:
+            return Universe.Unchanged
+        return [ x.Symbol for x in coarse if x.HasFundamentalData ]
+    
+    def SelectFine(self, algorithm, fine):
+        self.month = algorithm.Time.month
+        
+        tech_stocks = [ f for f in fine if f.AssetClassification.MorningstarSectorCode == MorningstarSectorCode.Technology ]
+        sorted_by_market_cap = sorted(tech_stocks, key=lambda x: x.MarketCap, reverse=True)
+        return [ x.Symbol for x in sorted_by_market_cap[:self.fine_size] ]
+
+
+ + +

Alpha Construction

+

+ The GaussianNaiveBayesAlphaModel predicts the direction each security will move from a given day’s open to the next + day’s open. When constructing this alpha model, we set up a dictionary to hold a SymbolData object for each symbol + in the universe and a flag to show the universe has changed. +

+
+
+class GaussianNaiveBayesAlphaModel(AlphaModel):
+    symbol_data_by_symbol = {}
+    new_securities = False
+
+
+ + +

Alpha Securities Management

+

+ When a new security is added to the universe, we create a SymbolData object for it to store information unique to + the security. The management of the SymbolData objects occurs in the alpha model's OnSecuritiesChanged method. In + this algorithm, since we train the Gaussian Naive Bayes classifier using the historical returns of the securities + in the universe, we flag to train the model every time the universe changes. +

+
+
+class GaussianNaiveBayesAlphaModel(AlphaModel):
+    ...
+
+    def OnSecuritiesChanged(self, algorithm, changes):
+        for security in changes.AddedSecurities:
+            self.symbol_data_by_symbol[security.Symbol] = SymbolData(security, algorithm)
+            
+        for security in changes.RemovedSecurities:
+            symbol_data = self.symbol_data_by_symbol.pop(security.Symbol, None)
+            if symbol_data:
+                symbol_data.dispose()
+        
+        self.new_securities = True
+
+
+ + +

SymbolData Class

+

+ The SymbolData class is used to store training data for the GaussianNaiveBayesAlphaModel and manage a consolidator + subscription. In the constructor, we specify the training parameters, setup the consolidator, and warm up the + training data. +

+
+
+class SymbolData:
+    def __init__(self, security, algorithm, num_days_per_sample=4, num_samples=100):
+        self.exchange = security.Exchange
+        self.symbol = security.Symbol
+        self.algorithm = algorithm
+        self.num_days_per_sample = num_days_per_sample
+        self.num_samples = num_samples
+        self.previous_open = 0
+        self.model = None
+        
+        # Setup consolidators
+        self.consolidator = TradeBarConsolidator(timedelta(days=1))
+        self.consolidator.DataConsolidated += self.CustomDailyHandler
+        algorithm.SubscriptionManager.AddConsolidator(self.symbol, self.consolidator)
+        
+        # Warm up ROC lookback
+        self.roc_window = np.array([])
+        self.labels_by_day = pd.Series()
+        
+        data = {f'{self.symbol.ID}_(t-{i})' : [] for i in range(1, num_days_per_sample + 1)}
+        self.features_by_day = pd.DataFrame(data)
+        
+        lookback = num_days_per_sample + num_samples + 1
+        history = algorithm.History(self.symbol, lookback, Resolution.Daily)
+        if history.empty or 'close' not in history:
+            algorithm.Log(f"Not enough history for {self.symbol} yet")    
+            return
+        
+        history = history.loc[self.symbol]
+        history['open_close_return'] = (history.close - history.open) / history.open
+        
+        start = history.shift(-1).open
+        end = history.shift(-2).open
+        history['future_return'] = (end - start) / start
+        
+        for day, row in history.iterrows():
+            self.previous_open = row.open
+            if self.update_features(day, row.open_close_return) and not pd.isnull(row.future_return):
+                row = pd.Series([np.sign(row.future_return)], index=[day])
+                self.labels_by_day = self.labels_by_day.append(row)[-self.num_samples:]
+
+
+ +

+ The update_features method is called to update our training features with the latest data passed to the algorithm. + It returns True/False, representing if the features are in place to start updating the training labels. +

+ +
+
+class SymbolData:
+    ...
+
+    def update_features(self, day, open_close_return):
+        self.roc_window = np.append(open_close_return, self.roc_window)[:self.num_days_per_sample]
+        
+        if len(self.roc_window) < self.num_days_per_sample:
+            return False
+            
+        self.features_by_day.loc[day] = self.roc_window
+        self.features_by_day = self.features_by_day[-(self.num_samples+2):]
+        return True
+
+
+ + + + +

Model Training

+

+ The GNB model is trained each day the universe has changed. By default, it uses 100 samples to train. The features + are the historical open-to-close returns of the universe constituents. The labels are the returns from the open at + T+1 to the open at T+2 at each time step for each security. +

+
+
+class GaussianNaiveBayesAlphaModel(AlphaModel):
+    ...
+
+    def train(self):
+        features = pd.DataFrame()
+        labels_by_symbol = {}
+        
+        # Gather training data
+        for symbol, symbol_data in self.symbol_data_by_symbol.items():
+            if symbol_data.IsReady:
+                features = pd.concat([features, symbol_data.features_by_day], axis=1)
+                labels_by_symbol[symbol] = symbol_data.labels_by_day
+        
+        # Train the GNB model
+        for symbol, symbol_data in self.symbol_data_by_symbol.items():
+            if symbol_data.IsReady:
+                symbol_data.model = GaussianNB().fit(features.iloc[:-2], labels_by_symbol[symbol])
+
+
+ + +

Alpha Update

+

+ As new TradeBars are provided to the alpha model's Update method, we collect the latest TradeBar’s open-to-close + return for each security in the universe. We then predict the direction of each security using the security’s + corresponding GNB model, and return insights accordingly. +

+
+
+class GaussianNaiveBayesAlphaModel(AlphaModel):
+    ...
+
+    def Update(self, algorithm, data):
+        if self.new_securities:
+            self.train()
+            self.new_securities = False
+        
+        tradable_symbols = {}
+        features = [[]]
+        
+        for symbol, symbol_data in self.symbol_data_by_symbol.items():
+            if data.ContainsKey(symbol) and data[symbol] is not None and symbol_data.IsReady:
+                tradable_symbols[symbol] = symbol_data
+                features[0].extend(symbol_data.features_by_day.iloc[-1].values)
+
+        insights = []
+        if len(tradable_symbols) == 0:
+            return []
+        weight = 1 / len(tradable_symbols)
+        for symbol, symbol_data in tradable_symbols.items():
+            direction = symbol_data.model.predict(features)
+            if direction:
+                insights.append(Insight.Price(symbol, data.Time + timedelta(days=1, seconds=-1), 
+                                              direction, None, None, None, weight))
+
+        return insights
+
+
+ + +

Portfolio Construction & Trade Execution

+

+ Following the guidelines of Alpha Streams + and the Quant League competition, we + utilize the + InsightWeightingPortfolioConstructionModel and the + + ImmediateExecutionModel. +

diff --git a/04 Strategy Library/1036 Gaussian Naive Bayes Model/05 Algorithm.html b/04 Strategy Library/1036 Gaussian Naive Bayes Model/05 Algorithm.html new file mode 100644 index 0000000..7f48965 --- /dev/null +++ b/04 Strategy Library/1036 Gaussian Naive Bayes Model/05 Algorithm.html @@ -0,0 +1,6 @@ +
+
+
+ +
+
\ No newline at end of file diff --git a/04 Strategy Library/1036 Gaussian Naive Bayes Model/06 Relative Performance.html b/04 Strategy Library/1036 Gaussian Naive Bayes Model/06 Relative Performance.html new file mode 100644 index 0000000..3ddfffe --- /dev/null +++ b/04 Strategy Library/1036 Gaussian Naive Bayes Model/06 Relative Performance.html @@ -0,0 +1,56 @@ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Period NameStart DateEnd DateStrategySharpeVariance
5 Year Backtest10/1/201510/13/2020Strategy0.970.016
Benchmark0.8050.029
2020 Crash2/19/20203/23/2020Strategy-0.9810.353
Benchmark-1.40.474
2020 Recovery3/23/20206/8/2020Strategy-2.0110.035
Benchmark8.7650.103
+
+ diff --git a/04 Strategy Library/1036 Gaussian Naive Bayes Model/07 Market & Competition Qualification.html b/04 Strategy Library/1036 Gaussian Naive Bayes Model/07 Market & Competition Qualification.html new file mode 100644 index 0000000..d16c9d8 --- /dev/null +++ b/04 Strategy Library/1036 Gaussian Naive Bayes Model/07 Market & Competition Qualification.html @@ -0,0 +1,12 @@ +

+ Although this strategy passes several of the + metrics required for Alpha Streams + and the Quant League competition, it requires further work to pass the following requirements: +

+ + diff --git a/04 Strategy Library/1036 Gaussian Naive Bayes Model/08 Conclusion.html b/04 Strategy Library/1036 Gaussian Naive Bayes Model/08 Conclusion.html new file mode 100644 index 0000000..99f052c --- /dev/null +++ b/04 Strategy Library/1036 Gaussian Naive Bayes Model/08 Conclusion.html @@ -0,0 +1,17 @@ +

+ The GNB model strategy implemented in this tutorial produced a greater Sharpe ratio and lower annual variance than + buying and holding the S&P 500 index ETF benchmark over the backtesting period. In addition to outperforming during + the entire backtest, the strategy also outperformed during the 2020 stock market crash. +

+ +

+ To continue the development of this strategy, future areas of research include: +

+ + \ No newline at end of file diff --git a/04 Strategy Library/1036 Gaussian Naive Bayes Model/09 References.html b/04 Strategy Library/1036 Gaussian Naive Bayes Model/09 References.html new file mode 100644 index 0000000..0320284 --- /dev/null +++ b/04 Strategy Library/1036 Gaussian Naive Bayes Model/09 References.html @@ -0,0 +1,12 @@ +
    +
  1. + Imandoust, S. B., & Mohammad, B. (2014). Forecasting the direction of stock market index movement using three + data mining techniques: the case of Tehran Stock Exchange. Journal of Engineering Research and Applications, + 6(2), 106-117. + Online copy +
  2. +
  3. + Lu, N. (2016). A Machine Learning Approach to Automated Trading. + Online copy +
  4. +
\ No newline at end of file diff --git a/04 Strategy Library/11 Fundamental Factor Long Short Strategy/04 Algorithm.html b/04 Strategy Library/11 Fundamental Factor Long Short Strategy/04 Algorithm.html index 53170f5..b8d9c7d 100755 --- a/04 Strategy Library/11 Fundamental Factor Long Short Strategy/04 Algorithm.html +++ b/04 Strategy Library/11 Fundamental Factor Long Short Strategy/04 Algorithm.html @@ -1,6 +1,6 @@
- +
diff --git a/04 Strategy Library/113 January Barometer/03 Algorithm.html b/04 Strategy Library/113 January Barometer/03 Algorithm.html index be69ba3..e85f53d 100644 --- a/04 Strategy Library/113 January Barometer/03 Algorithm.html +++ b/04 Strategy Library/113 January Barometer/03 Algorithm.html @@ -1,6 +1,6 @@
- +
diff --git a/04 Strategy Library/114 January Effect in Stocks/03 Algorithm.html b/04 Strategy Library/114 January Effect in Stocks/03 Algorithm.html index f94dcba..6dc92eb 100644 --- a/04 Strategy Library/114 January Effect in Stocks/03 Algorithm.html +++ b/04 Strategy Library/114 January Effect in Stocks/03 Algorithm.html @@ -1,6 +1,6 @@
- +
diff --git a/04 Strategy Library/12 Asset Class Trend Following/03 Algorithm.html b/04 Strategy Library/12 Asset Class Trend Following/03 Algorithm.html index ca04542..77b7892 100644 --- a/04 Strategy Library/12 Asset Class Trend Following/03 Algorithm.html +++ b/04 Strategy Library/12 Asset Class Trend Following/03 Algorithm.html @@ -1,6 +1,6 @@
- +
diff --git a/04 Strategy Library/125 12 Month Cycle in Cross-Section of Stocks Returns/03 Algorithm.html b/04 Strategy Library/125 12 Month Cycle in Cross-Section of Stocks Returns/03 Algorithm.html index 6189f9c..e7aa2b2 100644 --- a/04 Strategy Library/125 12 Month Cycle in Cross-Section of Stocks Returns/03 Algorithm.html +++ b/04 Strategy Library/125 12 Month Cycle in Cross-Section of Stocks Returns/03 Algorithm.html @@ -1,6 +1,6 @@
- +
diff --git a/04 Strategy Library/13 Asset Class Momentum/03 Algorithm.html b/04 Strategy Library/13 Asset Class Momentum/03 Algorithm.html index 0e5258c..d001aad 100644 --- a/04 Strategy Library/13 Asset Class Momentum/03 Algorithm.html +++ b/04 Strategy Library/13 Asset Class Momentum/03 Algorithm.html @@ -1,6 +1,6 @@
- +
diff --git a/04 Strategy Library/14 Sector Momentum/03 Algorithm.html b/04 Strategy Library/14 Sector Momentum/03 Algorithm.html index 0cb1b39..80765bc 100644 --- a/04 Strategy Library/14 Sector Momentum/03 Algorithm.html +++ b/04 Strategy Library/14 Sector Momentum/03 Algorithm.html @@ -1,6 +1,6 @@
- +
diff --git a/04 Strategy Library/15 Short Term Reversal/03 Algorithm.html b/04 Strategy Library/15 Short Term Reversal/03 Algorithm.html index 09e4c6f..1970b93 100644 --- a/04 Strategy Library/15 Short Term Reversal/03 Algorithm.html +++ b/04 Strategy Library/15 Short Term Reversal/03 Algorithm.html @@ -1,6 +1,6 @@
- +
diff --git a/04 Strategy Library/155 Momentum and Reversal Combined with Volatility Effect in Stocks/03 Algorithm.html b/04 Strategy Library/155 Momentum and Reversal Combined with Volatility Effect in Stocks/03 Algorithm.html index e3a87f0..41faf63 100644 --- a/04 Strategy Library/155 Momentum and Reversal Combined with Volatility Effect in Stocks/03 Algorithm.html +++ b/04 Strategy Library/155 Momentum and Reversal Combined with Volatility Effect in Stocks/03 Algorithm.html @@ -1,6 +1,6 @@
- +
diff --git a/04 Strategy Library/16 Overnight Anomaly/03 Algorithm.html b/04 Strategy Library/16 Overnight Anomaly/03 Algorithm.html index e4a3020..cb7b3a9 100644 --- a/04 Strategy Library/16 Overnight Anomaly/03 Algorithm.html +++ b/04 Strategy Library/16 Overnight Anomaly/03 Algorithm.html @@ -1,6 +1,6 @@
- +
diff --git a/04 Strategy Library/162 Momentum Effect in Stocks in Small Portfolios/03 Algorithm.html b/04 Strategy Library/162 Momentum Effect in Stocks in Small Portfolios/03 Algorithm.html index 6bbcd8e..219c782 100644 --- a/04 Strategy Library/162 Momentum Effect in Stocks in Small Portfolios/03 Algorithm.html +++ b/04 Strategy Library/162 Momentum Effect in Stocks in Small Portfolios/03 Algorithm.html @@ -1,6 +1,6 @@
- +
diff --git "a/04 Strategy Library/162 Momentum Effect in Stocks in Small Portfolios/03 \347\256\227\346\263\225.cn.html" "b/04 Strategy Library/162 Momentum Effect in Stocks in Small Portfolios/03 \347\256\227\346\263\225.cn.html" index 6bbcd8e..219c782 100644 --- "a/04 Strategy Library/162 Momentum Effect in Stocks in Small Portfolios/03 \347\256\227\346\263\225.cn.html" +++ "b/04 Strategy Library/162 Momentum Effect in Stocks in Small Portfolios/03 \347\256\227\346\263\225.cn.html" @@ -1,6 +1,6 @@
- +
diff --git a/04 Strategy Library/17 Forex Momentum/03 Algorithm.html b/04 Strategy Library/17 Forex Momentum/03 Algorithm.html index b7fd60e..f8b0c4d 100644 --- a/04 Strategy Library/17 Forex Momentum/03 Algorithm.html +++ b/04 Strategy Library/17 Forex Momentum/03 Algorithm.html @@ -1,6 +1,6 @@
- +
diff --git a/04 Strategy Library/18 Volatility Effect in Stocks/03 Algorithm.html b/04 Strategy Library/18 Volatility Effect in Stocks/03 Algorithm.html index 0a0907d..97890a9 100644 --- a/04 Strategy Library/18 Volatility Effect in Stocks/03 Algorithm.html +++ b/04 Strategy Library/18 Volatility Effect in Stocks/03 Algorithm.html @@ -1,6 +1,6 @@
- +
diff --git a/04 Strategy Library/19 Pairs Trading with Stocks/03 Algorithm.html b/04 Strategy Library/19 Pairs Trading with Stocks/03 Algorithm.html index 17a97c9..4b088a3 100644 --- a/04 Strategy Library/19 Pairs Trading with Stocks/03 Algorithm.html +++ b/04 Strategy Library/19 Pairs Trading with Stocks/03 Algorithm.html @@ -1,6 +1,6 @@
- +
diff --git a/04 Strategy Library/199 ROA Effect within Stocks/03 Algorithm.html b/04 Strategy Library/199 ROA Effect within Stocks/03 Algorithm.html index c75531f..66e4458 100644 --- a/04 Strategy Library/199 ROA Effect within Stocks/03 Algorithm.html +++ b/04 Strategy Library/199 ROA Effect within Stocks/03 Algorithm.html @@ -1,6 +1,6 @@
- +
diff --git a/04 Strategy Library/20 Forex Carry Trade/03 Algorithm.html b/04 Strategy Library/20 Forex Carry Trade/03 Algorithm.html index 1bb774b..d433b13 100644 --- a/04 Strategy Library/20 Forex Carry Trade/03 Algorithm.html +++ b/04 Strategy Library/20 Forex Carry Trade/03 Algorithm.html @@ -1,6 +1,6 @@
- +
diff --git "a/04 Strategy Library/20 Forex Carry Trade/03 \347\256\227\346\263\225.cn.html" "b/04 Strategy Library/20 Forex Carry Trade/03 \347\256\227\346\263\225.cn.html" index 1bb774b..d433b13 100644 --- "a/04 Strategy Library/20 Forex Carry Trade/03 \347\256\227\346\263\225.cn.html" +++ "b/04 Strategy Library/20 Forex Carry Trade/03 \347\256\227\346\263\225.cn.html" @@ -1,6 +1,6 @@
- +
diff --git a/04 Strategy Library/207 Value Effect within Countries/03 Algorithm.html b/04 Strategy Library/207 Value Effect within Countries/03 Algorithm.html index b581b49..f2180a0 100644 --- a/04 Strategy Library/207 Value Effect within Countries/03 Algorithm.html +++ b/04 Strategy Library/207 Value Effect within Countries/03 Algorithm.html @@ -1,6 +1,6 @@
- +
diff --git a/04 Strategy Library/22 Momentum Effect in Country Equity Indexes/04 Algorithm.html b/04 Strategy Library/22 Momentum Effect in Country Equity Indexes/04 Algorithm.html index 37631d8..1f5050c 100644 --- a/04 Strategy Library/22 Momentum Effect in Country Equity Indexes/04 Algorithm.html +++ b/04 Strategy Library/22 Momentum Effect in Country Equity Indexes/04 Algorithm.html @@ -2,13 +2,13 @@

The Momentum Effect

- +

Equal Weighted Benchmark

- +
diff --git "a/04 Strategy Library/22 Momentum Effect in Country Equity Indexes/04 \347\256\227\346\263\225.cn.html" "b/04 Strategy Library/22 Momentum Effect in Country Equity Indexes/04 \347\256\227\346\263\225.cn.html" index cd34f0c..7078bbf 100644 --- "a/04 Strategy Library/22 Momentum Effect in Country Equity Indexes/04 \347\256\227\346\263\225.cn.html" +++ "b/04 Strategy Library/22 Momentum Effect in Country Equity Indexes/04 \347\256\227\346\263\225.cn.html" @@ -2,13 +2,13 @@

动量效应

- +

平均加权基准

- +
diff --git a/04 Strategy Library/229 Earnings Quality Factor/03 Algorithm.html b/04 Strategy Library/229 Earnings Quality Factor/03 Algorithm.html index 3bc488d..bdafd79 100644 --- a/04 Strategy Library/229 Earnings Quality Factor/03 Algorithm.html +++ b/04 Strategy Library/229 Earnings Quality Factor/03 Algorithm.html @@ -1,6 +1,6 @@
- +
diff --git a/04 Strategy Library/23 Mean Reversion Effect in Country Equity Indexes/03 Algorithm.html b/04 Strategy Library/23 Mean Reversion Effect in Country Equity Indexes/03 Algorithm.html index 547579a..2b216a7 100644 --- a/04 Strategy Library/23 Mean Reversion Effect in Country Equity Indexes/03 Algorithm.html +++ b/04 Strategy Library/23 Mean Reversion Effect in Country Equity Indexes/03 Algorithm.html @@ -1,6 +1,6 @@
- +
diff --git a/04 Strategy Library/24 Liquidity Effect in Stocks/03 Algorithm.html b/04 Strategy Library/24 Liquidity Effect in Stocks/03 Algorithm.html index 5041f10..15edb83 100644 --- a/04 Strategy Library/24 Liquidity Effect in Stocks/03 Algorithm.html +++ b/04 Strategy Library/24 Liquidity Effect in Stocks/03 Algorithm.html @@ -1,6 +1,6 @@
- +
diff --git a/04 Strategy Library/25 Volatility Risk Premium Effect/03 Algorithm.html b/04 Strategy Library/25 Volatility Risk Premium Effect/03 Algorithm.html index a0bce57..0733d81 100644 --- a/04 Strategy Library/25 Volatility Risk Premium Effect/03 Algorithm.html +++ b/04 Strategy Library/25 Volatility Risk Premium Effect/03 Algorithm.html @@ -1,6 +1,6 @@
- +
diff --git a/04 Strategy Library/29 Term Structure Effect in Commodities/03 Algorithm.html b/04 Strategy Library/29 Term Structure Effect in Commodities/03 Algorithm.html index ada8627..f820ca9 100644 --- a/04 Strategy Library/29 Term Structure Effect in Commodities/03 Algorithm.html +++ b/04 Strategy Library/29 Term Structure Effect in Commodities/03 Algorithm.html @@ -3,7 +3,7 @@
- +
@@ -11,7 +11,7 @@
- +
diff --git a/04 Strategy Library/30 Momentum Effect Combined with Term Structure in Commodities/03 Algorithm.html b/04 Strategy Library/30 Momentum Effect Combined with Term Structure in Commodities/03 Algorithm.html index 91052ac..b781228 100644 --- a/04 Strategy Library/30 Momentum Effect Combined with Term Structure in Commodities/03 Algorithm.html +++ b/04 Strategy Library/30 Momentum Effect Combined with Term Structure in Commodities/03 Algorithm.html @@ -1,6 +1,6 @@
- +
diff --git a/04 Strategy Library/31 Book-to-Market Value Anomaly/03 Algorithm.html b/04 Strategy Library/31 Book-to-Market Value Anomaly/03 Algorithm.html index e0ed93e..9029e2c 100644 --- a/04 Strategy Library/31 Book-to-Market Value Anomaly/03 Algorithm.html +++ b/04 Strategy Library/31 Book-to-Market Value Anomaly/03 Algorithm.html @@ -1,6 +1,6 @@
- +
diff --git a/04 Strategy Library/32 Gold Market Timing/03 Algorithm.html b/04 Strategy Library/32 Gold Market Timing/03 Algorithm.html index 414a43d..c74f50c 100644 --- a/04 Strategy Library/32 Gold Market Timing/03 Algorithm.html +++ b/04 Strategy Library/32 Gold Market Timing/03 Algorithm.html @@ -1,6 +1,6 @@
- +
diff --git a/04 Strategy Library/34 Momentum-Short Term Reversal Strategy/03 Algorithm.html b/04 Strategy Library/34 Momentum-Short Term Reversal Strategy/03 Algorithm.html index a38d444..b3b0694 100644 --- a/04 Strategy Library/34 Momentum-Short Term Reversal Strategy/03 Algorithm.html +++ b/04 Strategy Library/34 Momentum-Short Term Reversal Strategy/03 Algorithm.html @@ -1,6 +1,6 @@
- +
diff --git a/04 Strategy Library/36 Sentiment and Style Rotation Effect in Stocks/03 Algorithm.html b/04 Strategy Library/36 Sentiment and Style Rotation Effect in Stocks/03 Algorithm.html index 9af8464..cff2414 100644 --- a/04 Strategy Library/36 Sentiment and Style Rotation Effect in Stocks/03 Algorithm.html +++ b/04 Strategy Library/36 Sentiment and Style Rotation Effect in Stocks/03 Algorithm.html @@ -1,6 +1,6 @@
- +
diff --git "a/04 Strategy Library/36 Sentiment and Style Rotation Effect in Stocks/03 \347\256\227\346\263\225.cn.html" "b/04 Strategy Library/36 Sentiment and Style Rotation Effect in Stocks/03 \347\256\227\346\263\225.cn.html" index 9af8464..cff2414 100644 --- "a/04 Strategy Library/36 Sentiment and Style Rotation Effect in Stocks/03 \347\256\227\346\263\225.cn.html" +++ "b/04 Strategy Library/36 Sentiment and Style Rotation Effect in Stocks/03 \347\256\227\346\263\225.cn.html" @@ -1,6 +1,6 @@
- +
diff --git a/04 Strategy Library/37 Momentum and State of Market Filters/03 Algorithm.html b/04 Strategy Library/37 Momentum and State of Market Filters/03 Algorithm.html index c07b1c7..926770b 100644 --- a/04 Strategy Library/37 Momentum and State of Market Filters/03 Algorithm.html +++ b/04 Strategy Library/37 Momentum and State of Market Filters/03 Algorithm.html @@ -1,6 +1,6 @@
- +
diff --git a/04 Strategy Library/40 Pairs Trading with Country ETFs/03 Algorithm.html b/04 Strategy Library/40 Pairs Trading with Country ETFs/03 Algorithm.html index 7cf2e86..36343ed 100644 --- a/04 Strategy Library/40 Pairs Trading with Country ETFs/03 Algorithm.html +++ b/04 Strategy Library/40 Pairs Trading with Country ETFs/03 Algorithm.html @@ -1,6 +1,6 @@
- +
diff --git a/04 Strategy Library/58 VIX Predicts Stock Index Returns/03 Algorithm.html b/04 Strategy Library/58 VIX Predicts Stock Index Returns/03 Algorithm.html index f8ca3b6..529a2d1 100644 --- a/04 Strategy Library/58 VIX Predicts Stock Index Returns/03 Algorithm.html +++ b/04 Strategy Library/58 VIX Predicts Stock Index Returns/03 Algorithm.html @@ -1,6 +1,6 @@
- +
diff --git a/04 Strategy Library/61 Lunar Cycle in Equity Market/03 Algorithm.html b/04 Strategy Library/61 Lunar Cycle in Equity Market/03 Algorithm.html index 55f69ca..8caed63 100644 --- a/04 Strategy Library/61 Lunar Cycle in Equity Market/03 Algorithm.html +++ b/04 Strategy Library/61 Lunar Cycle in Equity Market/03 Algorithm.html @@ -1,6 +1,6 @@
- +
diff --git a/04 Strategy Library/66 Combining Momentum Effect with Volume/03 Algorithm.html b/04 Strategy Library/66 Combining Momentum Effect with Volume/03 Algorithm.html index 3956745..57f98de 100644 --- a/04 Strategy Library/66 Combining Momentum Effect with Volume/03 Algorithm.html +++ b/04 Strategy Library/66 Combining Momentum Effect with Volume/03 Algorithm.html @@ -1,6 +1,6 @@
- +
diff --git a/04 Strategy Library/71 Short Term Reversal with Futures/03 Algorithm.html b/04 Strategy Library/71 Short Term Reversal with Futures/03 Algorithm.html index 430008f..d3f5c48 100644 --- a/04 Strategy Library/71 Short Term Reversal with Futures/03 Algorithm.html +++ b/04 Strategy Library/71 Short Term Reversal with Futures/03 Algorithm.html @@ -1,6 +1,6 @@
- +
diff --git a/04 Strategy Library/77 Beta Factors in Stocks/03 Algorithm.html b/04 Strategy Library/77 Beta Factors in Stocks/03 Algorithm.html index c9839cd..91f1e5a 100644 --- a/04 Strategy Library/77 Beta Factors in Stocks/03 Algorithm.html +++ b/04 Strategy Library/77 Beta Factors in Stocks/03 Algorithm.html @@ -1,6 +1,6 @@
- +
diff --git a/04 Strategy Library/78 Beta Factor in Country Equity Indexes/03 Algorithm.html b/04 Strategy Library/78 Beta Factor in Country Equity Indexes/03 Algorithm.html index 36e3092..0447f1a 100644 --- a/04 Strategy Library/78 Beta Factor in Country Equity Indexes/03 Algorithm.html +++ b/04 Strategy Library/78 Beta Factor in Country Equity Indexes/03 Algorithm.html @@ -1,6 +1,6 @@
- +
diff --git a/04 Strategy Library/83 Pre-Holiday Effect/03 Algorithm.html b/04 Strategy Library/83 Pre-Holiday Effect/03 Algorithm.html index b59109e..64580ab 100644 --- a/04 Strategy Library/83 Pre-Holiday Effect/03 Algorithm.html +++ b/04 Strategy Library/83 Pre-Holiday Effect/03 Algorithm.html @@ -1,6 +1,6 @@
- +
diff --git a/05 Introduction to Financial Python[]/05 Pandas-Resampling and DataFrame/02 Fetching Data.html b/05 Introduction to Financial Python[]/05 Pandas-Resampling and DataFrame/02 Fetching Data.html index 325ecd6..181f0fc 100755 --- a/05 Introduction to Financial Python[]/05 Pandas-Resampling and DataFrame/02 Fetching Data.html +++ b/05 Introduction to Financial Python[]/05 Pandas-Resampling and DataFrame/02 Fetching Data.html @@ -1,98 +1,98 @@ -

- Here we use the Quandl API to retrieve data. -

-
- -
import quandl
-quandl.ApiConfig.api_key = 'dRQxJ15_2nrLznxr1Nn4'
-
-
-

- We will create a Series named "aapl" whose values are Apple's daily closing prices, which are of course indexed by dates: -

-
- -
aapl_table = quandl.get('WIKI/AAPL')
-aapl = aapl_table['Adj. Close']['2017']
-print aapl
-
-
- -

- Recall that we can fetch a specific data point using series['yyyy-mm-dd']. We can also fetch the data in a specific month using series['yyyy-mm']. -

-
- -
print aapl['2017-3']
-Date
-2017-03-01    138.657681
-2017-03-02    137.834404
-2017-03-03    138.647762
-2017-03-06    138.211326
-2017-03-07    138.389868
-2017-03-08    137.874080
-2017-03-09    137.556672
-2017-03-10    138.012946
-2017-03-13    138.072460
-2017-03-14    137.864161
-2017-03-15    139.322254
-2017-03-16    139.550391
-2017-03-17    138.856061
-2017-03-20    140.314154
-2017-03-21    138.707276
-2017-03-22    140.274478
-2017-03-23    139.778528
-2017-03-24    139.500796
-2017-03-27    139.738852
-2017-03-28    142.635200
-2017-03-29    142.952608
-2017-03-30    142.764147
-2017-03-31    142.496334
-
-
- -

- Or in several consecutive months: -

-
- -
aapl['2017-2':'2017-4']
-
-
- -

- .head(N) and .tail(N) are methods for quickly accessing the first or last N elements. -

-
- -
print aapl.head()
-print aapl.tail(10)
-
-
-

- The output: -

-
- -
-Date
-2017-01-03    114.715378
-2017-01-04    114.586983
-2017-01-05    115.169696
-2017-01-06    116.453639
-2017-01-09    117.520300
-Name: Adj. Close, dtype: float64
-Date
-2017-08-08    159.433108
-2017-08-09    160.409148
-2017-08-10    155.270000
-2017-08-11    157.480000
-2017-08-14    159.850000
-2017-08-15    161.600000
-2017-08-16    160.950000
-2017-08-17    157.870000
-2017-08-18    157.500000
-2017-08-21    157.210000
-Name: Adj. Close, dtype: float64
-
-
+

+ Here we use the Quandl API to retrieve data... +

+
+ +
import quandl
+quandl.ApiConfig.api_key = 'dRQxJ15_2nrLznxr1Nn4'
+
+
+

+ We will create a Series named "aapl" whose values are Apple's daily closing prices, which are of course indexed by dates: +

+
+ +
aapl_table = quandl.get('WIKI/AAPL')
+aapl = aapl_table['Adj. Close']['2017']
+print aapl
+
+
+ +

+ Recall that we can fetch a specific data point using series['yyyy-mm-dd']. We can also fetch the data in a specific month using series['yyyy-mm']. +

+
+ +
print aapl['2017-3']
+Date
+2017-03-01    138.657681
+2017-03-02    137.834404
+2017-03-03    138.647762
+2017-03-06    138.211326
+2017-03-07    138.389868
+2017-03-08    137.874080
+2017-03-09    137.556672
+2017-03-10    138.012946
+2017-03-13    138.072460
+2017-03-14    137.864161
+2017-03-15    139.322254
+2017-03-16    139.550391
+2017-03-17    138.856061
+2017-03-20    140.314154
+2017-03-21    138.707276
+2017-03-22    140.274478
+2017-03-23    139.778528
+2017-03-24    139.500796
+2017-03-27    139.738852
+2017-03-28    142.635200
+2017-03-29    142.952608
+2017-03-30    142.764147
+2017-03-31    142.496334
+
+
+ +

+ Or in several consecutive months: +

+
+ +
aapl['2017-2':'2017-4']
+
+
+ +

+ .head(N) and .tail(N) are methods for quickly accessing the first or last N elements. +

+
+ +
print aapl.head()
+print aapl.tail(10)
+
+
+

+ The output: +

+
+ +
+Date
+2017-01-03    114.715378
+2017-01-04    114.586983
+2017-01-05    115.169696
+2017-01-06    116.453639
+2017-01-09    117.520300
+Name: Adj. Close, dtype: float64
+Date
+2017-08-08    159.433108
+2017-08-09    160.409148
+2017-08-10    155.270000
+2017-08-11    157.480000
+2017-08-14    159.850000
+2017-08-15    161.600000
+2017-08-16    160.950000
+2017-08-17    157.870000
+2017-08-18    157.500000
+2017-08-21    157.210000
+Name: Adj. Close, dtype: float64
+
+
diff --git a/05 Introduction to Financial Python[]/12 Modern Portfolio Theory/06 Algorithm.html b/05 Introduction to Financial Python[]/12 Modern Portfolio Theory/06 Algorithm.html index 8d6082c..309e3c2 100755 --- a/05 Introduction to Financial Python[]/12 Modern Portfolio Theory/06 Algorithm.html +++ b/05 Introduction to Financial Python[]/12 Modern Portfolio Theory/06 Algorithm.html @@ -1,9 +1,9 @@ -

- Mean-variance analysis is used to optimize portfolios with several strategies. Here we treat Dow 30 stocks as strategy and designed an algorithm to test mean-variance analysis: -

-
-
-
- -
-
+

+ Mean-variance analysis is used to optimize portfolios with several strategies. Here we treat Dow 30 stocks as strategy and designed an algorithm to test mean-variance analysis: +

+
+
+
+ +
+
diff --git a/05 Introduction to Financial Python[]/13 Market Risk/06 Algorithm.html b/05 Introduction to Financial Python[]/13 Market Risk/06 Algorithm.html index 3069322..64474c1 100755 --- a/05 Introduction to Financial Python[]/13 Market Risk/06 Algorithm.html +++ b/05 Introduction to Financial Python[]/13 Market Risk/06 Algorithm.html @@ -1,13 +1,13 @@ -
-
-
- -
-
- -
-
-
- -
-
+
+
+
+ +
+
+ +
+
+
+ +
+
diff --git a/05 Introduction to Financial Python[]/14 Fama-French Multi-Factor Models/02 Fama-French Three-Factor Model.html b/05 Introduction to Financial Python[]/14 Fama-French Multi-Factor Models/02 Fama-French Three-Factor Model.html index 21d0568..1f83f6d 100755 --- a/05 Introduction to Financial Python[]/14 Fama-French Multi-Factor Models/02 Fama-French Three-Factor Model.html +++ b/05 Introduction to Financial Python[]/14 Fama-French Multi-Factor Models/02 Fama-French Three-Factor Model.html @@ -1,8 +1,5 @@ 

- This model was proposed in 1993 by Eugene Fama and Kenneth French to describe stock returns.[ref] Fama, E F; French, K R (1993). Common risk factors in the returns on stocks and bonds. Journal of Financial Economics. 33: 3. CiteSeerX 10.1.1.139.5892 Freely accessible. doi:10.1016/0304-405X(93)90023-5[/ref] -

-

- The 3-factor model is + This model was proposed in 1993 by Eugene Fama and Kenneth French to describe stock returns. The 3-factor model is

\[ R = \alpha + \beta_m MKT + \beta_s SMB + \beta_h HML \] @@ -12,7 +9,7 @@

diff --git a/05 Introduction to Financial Python[]/14 Fama-French Multi-Factor Models/05 Other Factors.html b/05 Introduction to Financial Python[]/14 Fama-French Multi-Factor Models/05 Other Factors.html deleted file mode 100755 index 510c436..0000000 --- a/05 Introduction to Financial Python[]/14 Fama-French Multi-Factor Models/05 Other Factors.html +++ /dev/null @@ -1,12 +0,0 @@ -

- The Fama-French 5-Factor model comprises two more factors: -

- - -

- RMW was proposed by Novy-Marx (2013) who wrote that: - "Controlling for gross profitability explains most earnings related anomalies, and a wide range of seemingly unrelated profitable trading strategies." CMA was proposed by Fama and French (2014) who pointed out that: A five-factor model directed at capturing the size, value, profitability, and investment patterns in average stock returns is rejected on the GRS test, but for applied purposes it provides an acceptable description of average returns. Finally, momentum is another commonly used factor. It captures excess returns of stocks with highest returns over those with lowest returns -

diff --git a/05 Introduction to Financial Python[]/14 Fama-French Multi-Factor Models/06 Summary.html b/05 Introduction to Financial Python[]/14 Fama-French Multi-Factor Models/05 Summary.html old mode 100755 new mode 100644 similarity index 98% rename from 05 Introduction to Financial Python[]/14 Fama-French Multi-Factor Models/06 Summary.html rename to 05 Introduction to Financial Python[]/14 Fama-French Multi-Factor Models/05 Summary.html index 549200f..d2b7e7a --- a/05 Introduction to Financial Python[]/14 Fama-French Multi-Factor Models/06 Summary.html +++ b/05 Introduction to Financial Python[]/14 Fama-French Multi-Factor Models/05 Summary.html @@ -1,3 +1,3 @@ -

- In this chapter we expand Capital Asset Pricing Model (CAPM) into multi-factor models: the Fama-French factor models in particular. They are the most empirically successful multi-factor models by far, and are commonly used in practice. -

+

+ In this chapter we expand Capital Asset Pricing Model (CAPM) into multi-factor models: the Fama-French factor models in particular. They are the most empirically successful multi-factor models by far, and are commonly used in practice. +

diff --git a/05 Introduction to Financial Python[]/14 Fama-French Multi-Factor Models/07 Algorithm.html b/05 Introduction to Financial Python[]/14 Fama-French Multi-Factor Models/06 Algorithm.html old mode 100755 new mode 100644 similarity index 74% rename from 05 Introduction to Financial Python[]/14 Fama-French Multi-Factor Models/07 Algorithm.html rename to 05 Introduction to Financial Python[]/14 Fama-French Multi-Factor Models/06 Algorithm.html index e3c69c8..3eb4334 --- a/05 Introduction to Financial Python[]/14 Fama-French Multi-Factor Models/07 Algorithm.html +++ b/05 Introduction to Financial Python[]/14 Fama-French Multi-Factor Models/06 Algorithm.html @@ -1,15 +1,15 @@ -

- Multi-factor strategies are stock picking strategies. Here we try to implement a 2013 paper published by AQR Capital Management. - The paper recommends picking stocks by their value, quality (profitability) and momentum. - The empirically successful measure of value is book-to-price ratio (B/P), but other measures can be used simultaneously to form a more robust and reliable view of a stock's value. The paper uses 5 measures: book-to-price, earnings-to-price ratio (EPS), forecasted EPS, cash flow-to-enterprise value and sales-to-enterprise value. - The paper suggested a few quality measures: total profit over assets, gross margin and free cash flow over assets. There are also various measures of momentum. 1-year momentum, fundamental momentum and returns around earnings announcement are good choices. -

-

- In our backtested strategy, we used operating profit margin to measure quality, P/B value to measure value, and 1-month momentum. The portfolio was rebalanced every 2 months and our backtest period runs from Jan 2012 to Jan 2015. You can build your own version by changing the factor, the weight of each factor, and the rebalance period based on the backtested strategy. -

-
-
-
- -
-
+

+ Multi-factor strategies are stock picking strategies. Here we try to implement a 2013 paper published by AQR Capital Management. + The paper recommends picking stocks by their value, quality (profitability) and momentum. + The empirically successful measure of value is book-to-price ratio (B/P), but other measures can be used simultaneously to form a more robust and reliable view of a stock's value. The paper uses 5 measures: book-to-price, earnings-to-price ratio (EPS), forecasted EPS, cash flow-to-enterprise value and sales-to-enterprise value. + The paper suggested a few quality measures: total profit over assets, gross margin and free cash flow over assets. There are also various measures of momentum. 1-year momentum, fundamental momentum and returns around earnings announcement are good choices. +

+

+ In our backtested strategy, we used operating profit margin to measure quality, book value per share to measure value, and 1-month momentum. The portfolio was rebalanced every month. You can build your own version by changing the factor, the weight of each factor, and the rebalance period based on the backtested strategy. +

+
+
+
+ +
+
diff --git a/05 Introduction to Financial Python[]/14 Fama-French Multi-Factor Models/08 References.html b/05 Introduction to Financial Python[]/14 Fama-French Multi-Factor Models/07 References.html similarity index 81% rename from 05 Introduction to Financial Python[]/14 Fama-French Multi-Factor Models/08 References.html rename to 05 Introduction to Financial Python[]/14 Fama-French Multi-Factor Models/07 References.html index 79b3bcb..eb7216e 100644 --- a/05 Introduction to Financial Python[]/14 Fama-French Multi-Factor Models/08 References.html +++ b/05 Introduction to Financial Python[]/14 Fama-French Multi-Factor Models/07 References.html @@ -14,4 +14,7 @@
  • Robert Novy-Marx (2013). The Other Side of Value: The Gross Profitability Premium Journal of Financial Economics 108 (1), 1-28. Retrieved from rnm.simon.rochester.edu/research/OSoV.pdf
  • +
  • + Fama, E. F. & French, K. R. (1993). Common risk factors in the returns on stocks and bonds. Journal of Financial Economics, 33, 3-56. doi: 10.1016/0304-405X(93)90023-5. Retrieved from rady.ucsd.edu. +
  • diff --git a/06 Introduction to Options[]/01 General Features of Options/04 The Value of Options.html b/06 Introduction to Options[]/01 General Features of Options/04 The Value of Options.html index f0877cc..b392bbd 100755 --- a/06 Introduction to Options[]/01 General Features of Options/04 The Value of Options.html +++ b/06 Introduction to Options[]/01 General Features of Options/04 The Value of Options.html @@ -12,5 +12,5 @@ \[Time Value= Premium-Intrinsic Value\]

    -For example, an AAPL call option contract which expires after 10 days has strike $143 and premium $10. now the market price of AAPL is $160. The intrinsic value of this contract is 160-143=$17, the time value is 17-10=$7. Although the intrinsic value of OTM and ATM options is zero, they have time values if they still have a certain amount of time until the option expires so for OTM and ATM options, their premiums equal their time values. +For example, an AAPL call option contract which expires after 10 days has strike $143 and premium $10. now the market price of AAPL is $150. The intrinsic value of this contract is 150-143=$7, the time value is 10-7=$3. Although the intrinsic value of OTM and ATM options is zero, they have time values if they still have a certain amount of time until the option expires so for OTM and ATM options, their premiums equal their time values.

    diff --git a/06 Introduction to Options[]/02 QuantConnect Options API/02 Add Options.html b/06 Introduction to Options[]/02 QuantConnect Options API/02 Add Options.html index a1d5a37..44c5959 100755 --- a/06 Introduction to Options[]/02 QuantConnect Options API/02 Add Options.html +++ b/06 Introduction to Options[]/02 QuantConnect Options API/02 Add Options.html @@ -22,8 +22,8 @@
    def Initialize(self):
    -    self.SetStartDate(2017, 01, 01)  #Set Start Date
    -    self.SetEndDate(2017, 06, 30)  #Set End Date
    +    self.SetStartDate(2017, 1, 1)  #Set Start Date
    +    self.SetEndDate(2017, 6, 30)  #Set End Date
         self.SetCash(50000)  #Set Strategy Cash
         equity = self.AddEquity("GOOG", Resolution.Minute) # Add the underlying stock: Google
         option = self.AddOption("GOOG", Resolution.Minute) # Add the option corresponding to underlying stock
    diff --git a/06 Introduction to Options[]/02 QuantConnect Options API/04 Select Contracts.html b/06 Introduction to Options[]/02 QuantConnect Options API/04 Select Contracts.html
    index 54084fb..07ea589 100755
    --- a/06 Introduction to Options[]/02 QuantConnect Options API/04 Select Contracts.html	
    +++ b/06 Introduction to Options[]/02 QuantConnect Options API/04 Select Contracts.html	
    @@ -65,11 +65,11 @@
     
    def OnData(self,slice):
         for i in slice.OptionChains:
             if i.Key != self.symbol: continue
    -	optionchain = i.Value
    -	self.Log("underlying price:" + str(optionchain.Underlying.Price))
    -	df = pd.DataFrame([[x.Right,float(x.Strike),x.Expiry,float(x.BidPrice),float(x.AskPrice)] for x in optionchain],
    -			   index=[x.Symbol.Value for x in optionchain],
    -			   columns=['type(call 0, put 1)', 'strike', 'expiry', 'ask price', 'bid price'])
    +        optionchain = i.Value
    +        self.Log("underlying price:" + str(optionchain.Underlying.Price))
    +        df = pd.DataFrame([[x.Right,float(x.Strike),x.Expiry,float(x.BidPrice),float(x.AskPrice)] for x in optionchain],
    +                           index=[x.Symbol.Value for x in optionchain],
    +                           columns=['type(call 0, put 1)', 'strike', 'expiry', 'ask price', 'bid price'])
             self.Log(str(df))
     
    @@ -160,18 +160,18 @@
    for i in slice.OptionChains:
         if i.Key != self.symbol: continue
    -    chain = i.Value
    -# differentiate the call and put options
    -call = [x for x in optionchain if chain.Right == 0]
    -put = [x for x in optionchain if chain.Right == 1]
    -# choose ITM contracts
    -contracts = [x for x in call if call.UnderlyingLastPrice - x.Strike > 0]
    -# or choose ATM contracts
    -contracts = sorted(optionchain, key = lambda x: abs(optionchain.Underlying.Price - x.Strike))[0]
    -# or choose OTM contracts
    -contracts = [x for x in call if call.UnderlyingLastPrice - x.Strike < 0]
    -# sort the contracts by their expiration dates
    -contracts = sorted(contracts, key = lambda x:x.Expiry, reverse = True)
    +    optionchain = i.Value
    +    # differentiate the call and put options
    +    call = [x for x in optionchain if x.Right == 0]
    +    put = [x for x in optionchain if x.Right == 1]
    +    # choose ITM call contracts
    +    contracts = [x for x in call if x.UnderlyingLastPrice - x.Strike > 0]
    +    # or choose ATM contracts
    +    contracts = sorted(optionchain, key = lambda x: abs(x.UnderlyingLastPrice - x.Strike))[0]
    +    # or choose OTM call contracts
    +    contracts = [x for x in call if x.UnderlyingLastPrice - x.Strike < 0]
    +    # sort the contracts by their expiration dates
    +    contracts = sorted(contracts, key = lambda x: x.Expiry, reverse = True)
     

    diff --git a/06 Introduction to Options[]/02 QuantConnect Options API/05 Algorithm.html b/06 Introduction to Options[]/02 QuantConnect Options API/05 Algorithm.html index 64b1d35..e485feb 100755 --- a/06 Introduction to Options[]/02 QuantConnect Options API/05 Algorithm.html +++ b/06 Introduction to Options[]/02 QuantConnect Options API/05 Algorithm.html @@ -4,6 +4,6 @@

    - +
    diff --git a/06 Introduction to Options[]/03 Put-Call Parity and Arbitrage Strategies/05 Algorithm.html b/06 Introduction to Options[]/03 Put-Call Parity and Arbitrage Strategies/05 Algorithm.html index 12d6ce9..b196a80 100755 --- a/06 Introduction to Options[]/03 Put-Call Parity and Arbitrage Strategies/05 Algorithm.html +++ b/06 Introduction to Options[]/03 Put-Call Parity and Arbitrage Strategies/05 Algorithm.html @@ -1,6 +1,6 @@
    - +
    diff --git a/07 Applied Options[]/01 Covered Call/04 Algorithm.html b/07 Applied Options[]/01 Covered Call/04 Algorithm.html index 9fa4e5e..6858e6e 100755 --- a/07 Applied Options[]/01 Covered Call/04 Algorithm.html +++ b/07 Applied Options[]/01 Covered Call/04 Algorithm.html @@ -4,7 +4,7 @@
    - +

    @@ -13,6 +13,6 @@

    - +
    diff --git a/07 Applied Options[]/02 Bull Call Spread/01 Definition.html b/07 Applied Options[]/02 Bull Call Spread/01 Definition.html index 0418abb..c361521 100755 --- a/07 Applied Options[]/02 Bull Call Spread/01 Definition.html +++ b/07 Applied Options[]/02 Bull Call Spread/01 Definition.html @@ -5,7 +5,7 @@ This strategy creates a ceiling and floor for the profit. By purchasing a call and selling a call with higher strike simultaneously, traders can reduce the cost of just one long call option with the premium of a short call option. But the premium of ITM call is more expensive than the OTM call. The strategy limits the loss resulting from a drop in the price of the underlying stock but still creates a ceiling to the profit while the underlying price is increasing.

    - Take GOOG as an example. If the share price of GOOG is $950 at time 0, the premium of ITM call option is 20 with strike 900 and the premium of OTM call option is 2 with strike 1000. If we ignore the commission, dividends and other transaction fees, the payoff of Bull Call Spread strategy is as follows: + Take GOOG as an example. If the share price of GOOG is $950 at time 0, the premium of ITM call option is 50 with strike 900 and the premium of OTM call option is 2 with strike 1000. If we ignore the commission, dividends and other transaction fees, the payoff of Bull Call Spread strategy is as follows:

    diff --git a/07 Applied Options[]/02 Bull Call Spread/04 Algorithm.html b/07 Applied Options[]/02 Bull Call Spread/04 Algorithm.html index 0e1c81b..ef1b62b 100755 --- a/07 Applied Options[]/02 Bull Call Spread/04 Algorithm.html +++ b/07 Applied Options[]/02 Bull Call Spread/04 Algorithm.html @@ -4,7 +4,7 @@
    - +

    @@ -13,6 +13,6 @@

    - +
    diff --git a/07 Applied Options[]/03 Long Straddle/04 Algorithm.html b/07 Applied Options[]/03 Long Straddle/04 Algorithm.html index 3e98c40..89e3d28 100755 --- a/07 Applied Options[]/03 Long Straddle/04 Algorithm.html +++ b/07 Applied Options[]/03 Long Straddle/04 Algorithm.html @@ -4,7 +4,7 @@
    - +

    @@ -13,6 +13,6 @@

    - +
    diff --git a/07 Applied Options[]/04 Long Strangle/04 Algorithm.html b/07 Applied Options[]/04 Long Strangle/04 Algorithm.html index 78ab066..09a8a85 100755 --- a/07 Applied Options[]/04 Long Strangle/04 Algorithm.html +++ b/07 Applied Options[]/04 Long Strangle/04 Algorithm.html @@ -4,7 +4,7 @@
    - +
    @@ -14,6 +14,6 @@
    - +
    diff --git a/07 Applied Options[]/05 Butterfly Spread/04 Algorithm.html b/07 Applied Options[]/05 Butterfly Spread/04 Algorithm.html index 134f5b1..beb7ac0 100755 --- a/07 Applied Options[]/05 Butterfly Spread/04 Algorithm.html +++ b/07 Applied Options[]/05 Butterfly Spread/04 Algorithm.html @@ -4,7 +4,7 @@
    - +
    @@ -14,6 +14,6 @@
    - +
    diff --git a/07 Applied Options[]/06 Iron Condor/04 Algorithm.html b/07 Applied Options[]/06 Iron Condor/04 Algorithm.html index cf2d154..7a08824 100755 --- a/07 Applied Options[]/06 Iron Condor/04 Algorithm.html +++ b/07 Applied Options[]/06 Iron Condor/04 Algorithm.html @@ -4,7 +4,7 @@
    - +

    @@ -14,6 +14,6 @@

    - +
    diff --git a/07 Applied Options[]/07 Iron Butterfly/04 Algorithm.html b/07 Applied Options[]/07 Iron Butterfly/04 Algorithm.html index cd42f7d..05d0e03 100755 --- a/07 Applied Options[]/07 Iron Butterfly/04 Algorithm.html +++ b/07 Applied Options[]/07 Iron Butterfly/04 Algorithm.html @@ -4,7 +4,7 @@
    - +
    @@ -14,6 +14,6 @@
    - +
    diff --git a/07 Applied Options[]/08 Protective Collar/04 Algorithm.html b/07 Applied Options[]/08 Protective Collar/04 Algorithm.html index 245885d..77dc3ce 100755 --- a/07 Applied Options[]/08 Protective Collar/04 Algorithm.html +++ b/07 Applied Options[]/08 Protective Collar/04 Algorithm.html @@ -4,7 +4,7 @@
    - +
    @@ -14,6 +14,6 @@
    - +
    diff --git a/README.md b/README.md index 5e2fd23..c9846d7 100644 --- a/README.md +++ b/README.md @@ -8,40 +8,22 @@ This repository is a collection of WordPress and Jupyter notebook tutorials for Lean Engine is an open-source fully managed C# algorithmic trading engine built for desktop and cloud usage. It was designed in Mono and operates in Windows, Linux and Mac platforms. For more information about the LEAN Algorithmic Trading engine see the [Lean][4] Engine repository. - -## New Tutorial Requests and Edits ## - -Please submit new tutorial requests as an issue to the [Tutorials][5] repository. Before submitting an issue please read others to ensure it is not a duplicate. Edits and fixes for clarity are warmly welcomed! - -## Mailing List ## - -The mailing list for the project can be found on [Google Groups][6] - ## Contributors and Pull Requests ## Contributions are warmly very welcomed but we ask you read the existing code to see how it is formatted, commented and ensure contributions match the existing style. All code submissions must include accompanying tests. Please see the [contributor guide lines][7]. ## Strategy Library Development Workflow ## -To publish a strategy to our [Strategy Library](https://www.quantconnect.com/tutorials/strategy-library/strategy-library), follow these steps: -1. Review filtered sources like SSRN, arxiv, and other academic journals/papers for a strategy to implement. Try to adhere to the [Quant League competition](https://www.quantconnect.com/competitions/quant-league-1) criteria and the Alpha Streams [minimum criteria](https://www.quantconnect.com/docs/alpha-streams/submitting-an-alpha#Submitting-an-Alpha-Minimum-Criteria) and [review process](https://www.quantconnect.com/docs/alpha-streams/submitting-an-alpha#Submitting-an-Alpha-Subsequent-Review-Process). -2. Post a 3-point development plan to [our Slack channel](https://www.quantconnect.com/slack) and wait for approval by @jaredbroad or @alexcatarino. See an example [here](https://cdn.quantconnect.com/i/tu/development-plan-example.png). -3. Develop the strategy (add [license and imports](https://github.com/QuantConnect/Lean/blob/master/Algorithm.Python/BasicTemplateAlgorithm.py#L1) to main.py). -4. Add an Issue to the [Tutorials repo](https://github.com/QuantConnect/Tutorials/issues) ([example](https://github.com/QuantConnect/Tutorials/issues/277)). -5. Add @alexcatarino as a [collaborator](https://www.quantconnect.com/blog/collaborating-in-quantconnect/) to the project. -6. Publish a strategy write-up in the Slack channel and wait for approval (see [Strategy Library](https://www.quantconnect.com/tutorials/strategy-library/strategy-library) for examples). -7. Convert the strategy write-up to HTML form ([examples](https://github.com/QuantConnect/Tutorials/tree/master/04%20Strategy%20Library)). -8. Make PR (following the [Contributor's Guidelines](https://github.com/QuantConnect/Lean/blob/master/CONTRIBUTING.md)): - - If the write-up includes images, upload them [here](https://www.quantconnect.com/admin/cdnUpload). - - Add summary HTML files to [Strategy Library directory](https://github.com/QuantConnect/Tutorials/tree/master/04%20Strategy%20Library). If it's a non-Quantpedia strategy, set the ID number (in the directory name) to the next available after 1023. - - If the strategy is from Quantpedia, add strategy ID and backtest ID to [quantpedia.json](https://github.com/QuantConnect/Tutorials/blob/master/quantpedia.json). - - Add strategy metadata to [this file](https://github.com/QuantConnect/Tutorials/blob/master/04%20Strategy%20Library/00%20Strategy%20Library/01%20Strategy%20Library.php) (Currently semi-sorted by Quantpedia strategy ID). -9. After the PR is merged, send @jaredbroad the URL and a 1-sentence summary of what the paper/strategy is about and post the strategy to the forum with the backtest of the algorithm and a short summary of the project ([example](https://www.quantconnect.com/forum/discussion/8608/strategy-library-addition-residual-momentum/p1)). + +To publish a strategy to our [Strategy Library](https://www.quantconnect.com/tutorials/strategy-library/strategy-library), follow the steps on the [documentation page](https://www.quantconnect.com/docs/v2/writing-algorithms/strategy-library#03-Contribute-Tutorials) + +## New Tutorial Requests and Edits ## + +Please submit new tutorial requests as an issue to the [Tutorials][5] repository. Before submitting an issue please read others to ensure it is not a duplicate. Edits and fixes for clarity are warmly welcomed! [1]: https://www.quantconnect.com/tutorials "Tutorials Viewer" [2]: https://www.quantconnect.com/lean/docs "Lean Documentation" [3]: https://github.com/QuantConnect/Lean/archive/master.zip [4]: https://github.com/QuantConnect/Lean [5]: https://github.com/QuantConnect/Tutorials/issues -[6]: https://groups.google.com/forum/#!forum/lean-engine [7]: https://github.com/QuantConnect/Lean/blob/master/CONTRIBUTING.md [8]: https://www.quantconnect.com/slack