From f028e8061bd3525b61f2609c9333bec9b741027b Mon Sep 17 00:00:00 2001
From: Jing Wu
+ Asset class trend following is a strategy that tries to exploit a momentum anomaly between various assets. It uses various moving averages or momentum filters to gain an exposure to an asset class only at the time when there is a higher probability for outperformance with less risk.
+ The basic logic behind the trend following is finding a method to detect the trend of price movement and buy an asset when its price trend goes up, and sell when its trend goes down.
+
+ This algorithm applies to trend following ideas to 5 ETFs in different asset classes like stocks, bonds, and commodities. The simple moving average is used to detect the trend. When the closing price is over its ten-month simple moving average,
+ we give equal allocation to those ETFs, otherwise stay in cash.
+ SMA(symbol, period, resolution) is used to generate the moving average value In LEAN implementation. A warm-up period of ten months is set to prime the data and initialize the indicator so the SMA is ready to use when the algorithm starts.
+
+Unlike the first trending following algorithm, this algorithm finds the entry point with the momentum effect. The momentum anomaly says that what was strongly going up in the past will probably continue to go up in the near future.
+In the calculation, it refers to the rate of change in price movements for a particular asset.
+
+ The portfolio of this algorithm contains 5 ETFs in different asset classes. LEAN has the momentum indicator MOM(symbol, period). The period is 12 months. After obtaining the most recent momentum value, we pick 3 ETFs with the strongest 12-month momentum into the portfolio and weight them equally. Hold for 1 month and then rebalance the portfolio with new momentum. Unlike asset class trend following strategy which combines asset classes into one portfolio, this rotational momentum system compares the performance of asset classes and picks only the best-performing assets from investment universe into investor's portfolio. The portfolio is rebalanced every month and portfolio's holdings are rotated so that only the best-performing assets are held.
+
+Sector rotation is a popular strategy with which capital is actively reallocated from one sector to another based upon changing market conditions.
+
+This algorithm is an adaptation of asset class momentum. Instead of rotating ETFs in different asset classes,
+the sector momentum algorithm picks 10 sector ETFs and pick 3 ETFs with the strongest 12-month momentum into
+the portfolio and weight them equally. The portfolio is rebalanced at the start of each month.
+
+The short-term reversal is the phenomenon that stocks with relatively low returns over the past month or week earn positive abnormal returns in the following month or week, and stocks with high returns earn negative abnormal returns.
+
+ To apply short-term reversal in stocks market, first, we use the universe selection API to pick the stocks with the price higher than 4 and rank those stocks by dollar volume and
+ choose the top 100 stocks as our asset pool. In fine universe selection, the prescreened stocks are sorted by market cap we choose the top 20. To detect the reversal effect,
+ the return is the most straightforward measure of the stock history performance. the indicator RateOfReturn() is used to calculate the monthly return. We go long on the 10 stocks
+ with the lowest performance in the previous month and go short on the 10 stocks with the greatest performance from the previous month.
+
+Instead of collecting profit from intraday trading, this algorithm is trying to view the overnight returns.
+
+ The strategy buys SPY ETF at its closing price and sells it at the opening each day.
+ The strategy makes a lot of trades, therefore, the whole strategy is very sensitive
+ to slippage costs and fees. Those returns are canceled out once transaction costs
+ are taken into account. With the InteractiveBrokers transaction model, fees for 20
+ years backtest is almost 25% of the initial cash.
+
+ Momentum is a trend following strategy, where the strategy buys the assets which have performed well in the past and sells the assets which have performed bad.
+
+ This algorithm applies momentum to the forex market. Our universe consists of 15 forex pairs
+ and covers period from 2006 to 2018. The algorithm goes long 3 currencies with strongest 12-month
+ momentum against USD and goes short 3 currencies with lowest 12-month momentum against USD.
+
+ The low volatility effect in equities refers to that stocks which previously
+ exhibited lower volatility will earn higher risk-adjusted returns than those with higher volatility.
+ This algorithm extends the study of the low volatility effect to U.S stocks with higher market capital.
+
+ To construct the investment universe which consists of US large cap stocks, first in coarse universe selection,
+ we exclude stocks without fundamental data and the price is below 5. A universe of 100 stocks is selected based on the dollar volume. In fine universe selection, we pick 50 stocks from the coarse universe with the highest market cap.
+
+ We create
+ The standard deviation is the typical statistic used to measure volatility. It is defined as the square root of the average variance of the data from its mean. We use the closing price series in RollingWindow to calculate the volatility.
+
+ The trading logic is we go long 5 stocks with the lowest volatility and liquidate stocks in the portfolio which does not in the lowest volatility list. The portfolio is rebalanced at the first trading day each month.
+
+ 2. We extract the factor values of candidate stocks at the beginning of each month and sort the stocks in ascending
+ order of their factor values. Here we use 12-months' total risk-based capital data
+
1. At the end of each month, we extract the one-month history close prices of each stock and compute the monthly returns.
@@ -226,8 +234,7 @@
We choose 4 factors: FCFYield, PriceChange1M, BookValuePerShare and RevenueGrowth.
-Unlike the first trending following algorithm, this algorithm finds the entry point with the momentum effect. The momentum anomaly says that what was strongly going up in the past will probably continue to go up in the near future.
-In the calculation, it refers to the rate of change in price movements for a particular asset.
+This trend following algorithm finds its entry points using the momentum effect. The momentum anomaly says that what was strongly going up in the past will probably continue to go up in the near future.
+The calculation performed uses the rate of change in price movements for a particular asset.
To apply short-term reversal in stocks market, first, we use the universe selection API to pick the stocks with the price higher than 4 and rank those stocks by dollar volume and
choose the top 100 stocks as our asset pool. In fine universe selection, the prescreened stocks are sorted by market cap we choose the top 20. To detect the reversal effect,
- the return is the most straightforward measure of the stock history performance. the indicator RateOfReturn() is used to calculate the monthly return. We go long on the 10 stocks
+ the return is the most straightforward measure of the stock history performance. The RateOfReturn indicator is used to calculate the monthly return. We go long on the 10 stocks
with the lowest performance in the previous month and go short on the 10 stocks with the greatest performance from the previous month.
@@ -13,6 +13,6 @@
@@ -13,6 +13,6 @@
@@ -13,6 +13,6 @@
@@ -13,6 +13,6 @@
The iron condor is an option strategy that earns money as long as the underlying asset price does move out of a predetermined price range. In this algorithm, that range is $775 to $827.5. At 02/01/2017, we long $750 put at $1.25 and short $775 put at $3.5. At the same time, we short $827.5 call at$2.3 and long $850 call at $0.75. At this moment, the GOOG share price is $799.55 all the options are out the money. At expiration date 02/17/2017, the share price of GOOG is $828.07. The long put, short put and long call expire worthless. The short call is exercised. Thus we get the short position of 100 GOOG shares.
Backtesing using SetFilter
@@ -15,6 +14,6 @@
+ The pairs trading algorithm aims to find two stocks which have prices that moved historically together.
+ If price series diverges, long and short positions are opened in the opposite direction. With the assumption
+ of mean reversion, the algorithm expects to make profits from the abnormal fluctuation of prices.
+ The crucial part of pairs trading is how to find the paired stocks and how to define the price divergence.
+
+ The first step of this algorithm is to select stock pairs from a universe of stocks. We use the history request to get the history closing price for the last one year. This is called the formation period.
+ The matching partner for each stock is found by looking for the security that minimizes the sum of squared deviations between two normalized price series. Assume there are two stocks A and B with the price series X and Y. For price normalization, the starting price during formation period is set to $1.
+ The formula of distance measure is
+ \[\sum_{i=1}^n{(\frac{x_i}{x_1}-\frac{y_i}{y_1}})^2\]
+ Top 4 pairs with the smallest historical distance measure are then traded. The trading pairs are selected
+ every half year. We use the schedule event method to fire the rebalance function.
+
+ As prices in a pair of stocks were closely cointegrated in past, there is high probability that those two securities share common sources of fundamental return correlations. A temporary shock could move one stock out of the common price band which presents statistical arbitrage opportunity. Given the trading pairs, the trading period is the next six months. We calculate the price spread series of the last one year. When pair prices have diverged by two standard deviations,
+ which means the spread is 2 times standard deviation away from its long-term mean, the algorithm will go short the stock which price is diverging up and go long the stock which price is diverging down. The position is closed when prices revert back.
+Universe Selection
+Calculate the Volatility
+SymbolData class and use RollingWindow to store the price data for symbols returned by fine universe.
+ The lookback period is 252 trading days. First, we request history data to initialize the RollingWindow for the added symbols and update it's value with the closing price every day in OnData().
+Trading stocks
+Step 1: Ranking the stocks by factor values
-2. We extract the factor values of candidate stocks at the beginning of each month and sort the stocks in ascending order of their factor values. Here we use 12-months' total risk-based capital data x.FinancialStatements.TotalRiskBasedCapital.TwelveMonths as an example. It is the sum of Tier 1 and Tier 2 Capital. x.Symbol.Value can give the string symbol of selected stock x. Then we save those sorted symbols as self.symbol.
+x.FinancialStatements.TotalRiskBasedCapital.TwelveMonths as an example.
+ It is the sum of Tier 1 and Tier 2 Capital. x.Symbol.Value
+ can give the string symbol of selected stock x. Then we save those sorted symbols as self.symbol.
+def FineSelectionFunction(self, fine):
@@ -66,6 +73,7 @@
Step 1: Ranking the stocks by factor values
return []
Step 2: Compute the monthly return of portfolios
Step 3: Generate the metrics to test the factor significance
-
-
+
Summary
Algorithm
Algorithm
diff --git a/07 Applied Options[]/07 Iron Butterfly/04 Algorithm.html b/07 Applied Options[]/07 Iron Butterfly/04 Algorithm.html
index 968a1fb..cd42f7d 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 16f8299..245885d 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 @@
From 4cc747514fce7abe9eef028f81a204c79c566bec Mon Sep 17 00:00:00 2001
From: Jing Wu Pairs Formation
+ Trading Pairs
+
+ The fundamental reason is important behind interest rate changes. Carry trade is one of + the most popular trading strategies among currency traders. It systematically sells low + interest rate currencies and buys high interest rates currencies trying to capture the spread between the rates. +
diff --git a/04 Strategy Library/20 Forex Carry Trade/02 Method.html b/04 Strategy Library/20 Forex Carry Trade/02 Method.html new file mode 100644 index 0000000..673aa83 --- /dev/null +++ b/04 Strategy Library/20 Forex Carry Trade/02 Method.html @@ -0,0 +1,22 @@ +
+ The central bank interest rate data is from Quandl. For the trading universe, we choose 9 currencies
+ whose central bank interest rate data is available in Quandl. The method to import the custom data is
+ AddData(type, symbol, resoltuion, timeZone, fillDataForward). As the custom file has it's unique
+ colume name, we need to create a class to specify the colume name of interest rate.
+
+from QuantConnect.Python import PythonQuandl +class QuandlRate(PythonQuandl): + def __init__(self): + self.ValueColumnName = 'Value' ++
+ We save the interest rate symbol and the correspondent forex asset symbol into a dictionary. +
++ Next step we sort the forex symbol by the value of interest rate. The algorithm goes long the currency with the highest interest rates and goes short the currency with the lowest interest rate. The strategy is rebalanced monthly. The schedule event method is used to fire the rebalance event at the first trading day each month. +
diff --git a/04 Strategy Library/20 Forex Carry Trade/03 Algorithm.html b/04 Strategy Library/20 Forex Carry Trade/03 Algorithm.html new file mode 100644 index 0000000..1bb774b --- /dev/null +++ b/04 Strategy Library/20 Forex Carry Trade/03 Algorithm.html @@ -0,0 +1,6 @@ + From d85d9152545d37a3541a0ed9598aa329dc5858e5 Mon Sep 17 00:00:00 2001 From: Jing Wu- The fundamental reason is important behind interest rate changes. Carry trade is one of - the most popular trading strategies among currency traders. It systematically sells low - interest rate currencies and buys high interest rates currencies trying to capture the spread between the rates. + Carry trade is very common in the foreign exchange market. + The strategy systematically sells low interest rate currencies and buys high interest rates currencies. The “carry” of a asset is the + opportunity cost of holding that asset. Carry trade strategy holds one currency relative to another in order to capture + the spread between the rates. We can think of this strategy as borrowing money in one country with a lower interest rate and investing it in another + country with a higher interest rate.
From 65847cb140e2b1b4bb1714b42a76930297c6484a Mon Sep 17 00:00:00 2001 From: Jing WuCarry trade is very common in the foreign exchange market. - The strategy systematically sells low interest rate currencies and buys high interest rates currencies. The “carry” of a asset is the - opportunity cost of holding that asset. Carry trade strategy holds one currency relative to another in order to capture - the spread between the rates. We can think of this strategy as borrowing money in one country with a lower interest rate and investing it in another - country with a higher interest rate. + The strategy systematically sells low-interest rate currencies and buys high-interest rates currencies. The “carry” of an asset is the opportunity cost of holding that asset. Carry trade strategy holds one currency relative to another in order to capture the spread between the rates. We can think of this strategy as borrowing money from one country with a lower interest rate and investing it in another country with a higher interest rate.
From dfa4d849a134e520787c83c4a410cfe5d730905b Mon Sep 17 00:00:00 2001 From: Jing Wu+ The momentum anomaly says that what was strongly going up in the past will probably continue to go up shortly. Stocks which outperform peers on 3-12 month period tend to perform well also in the future. + This algorithm will explore the momentum effect on large-cap stocks. +
diff --git a/04 Strategy Library/21 Momentum Effect in Stocks/02 Method.html b/04 Strategy Library/21 Momentum Effect in Stocks/02 Method.html new file mode 100644 index 0000000..8029888 --- /dev/null +++ b/04 Strategy Library/21 Momentum Effect in Stocks/02 Method.html @@ -0,0 +1,37 @@ ++ We use the universe selection API to create the momentum portfolio. The coarse universe selection eliminates stocks with the price lower than 5 and ETFs which does not have fundamental data. The fine universe selection chooses 50 biggest companies by market capitalization. +
++ Momentum is the absolute difference in stocks. + \[Momentum = Close_{today}-Close_{N-days-ago}\] + LEAN has the Momentum indicator. We create a class to save the momentum value and warm up the indictor for each symbol. +
+class SymbolData: + def __init__(self, symbol, lookback): + self.symbol = symbol + self.MOM = Momentum(lookback) + + def WarmUpIndicator(self, history): + # warm up the Momentum indicator with the history request + for tuple in history.itertuples(): + item = IndicatorDataPoint(self.symbol, tuple.Index, float(tuple.close)) + self.MOM.Update(item) ++
+ Dictionary self.symbolDataDict is used to save the momentum class instance SymbolData for each symbol.
+ In OnSecuritiesChanged event method, we add the newly selected symbol to the dictionary and initialize the momentum indicator with the history request. For symbols removed from the universe, we remove it from the dictionary. Each day in OnData,
+ Momentum indicator for all symbols in the dictionary will be updated with the latest closing price.
+
+ We choose the period of the momentum to be 12 months. Stocks with the best 12-month momentum (12-month performance) are then added to our portfolio and are weighted equally. +
+ +
+ The portfolio is rebalanced once a month. The coarse and fine universe selection is set to default to run at midnight once a day. To make the universe selection run at the first trading day each month, we use the bool variable
+ self.monthly_rebalance to manage the universe selection. At the start of each month, the universe selection will filter new stocks. In other days, it will return the same symbols. In contrast to returning an empty list, returning the same symbols as before is a better way for monthly rebalance universe selection. Since if there are no open positions for certain symbol, returning empty list will stop the data subscription of that symbol. You might not be able to update the indicator value in OnData().
+
- The momentum anomaly says that what was strongly going up in the past will probably continue to go up shortly. Stocks which outperform peers on 3-12 month period tend to perform well also in the future. - This algorithm will explore the momentum effect on large-cap stocks. +The momentum anomaly says that what was strongly going up in the near past will probably continue to go up shortly. Stocks which outperform peers on 3-12 month period tend to perform well also in the future. This algorithm will explore the momentum effect on large-cap stocks.
From 842796bf6a9515e25847b3f8c18d912b5d1920ad Mon Sep 17 00:00:00 2001 From: Jared- We use the universe selection API to create the momentum portfolio. The coarse universe selection eliminates stocks with the price lower than 5 and ETFs which does not have fundamental data. The fine universe selection chooses 50 biggest companies by market capitalization. + We use the universe selection API to create a momentum portfolio. Our coarse-universe selection eliminates stocks with a price lower than $5 and ETFs which do not have fundamental data. Fine-universe selection chooses the 50 largest companies ranked by market capitalization.
-Momentum is the absolute difference in stocks. \[Momentum = Close_{today}-Close_{N-days-ago}\] @@ -23,15 +23,15 @@
Dictionary self.symbolDataDict is used to save the momentum class instance SymbolData for each symbol.
- In OnSecuritiesChanged event method, we add the newly selected symbol to the dictionary and initialize the momentum indicator with the history request. For symbols removed from the universe, we remove it from the dictionary. Each day in OnData,
+ In OnSecuritiesChanged event method, we add the newly selected symbol to the dictionary and initialize the momentum indicator with the history request. For symbols removed from the universe, we remove it from the dictionary. Each day in OnData, the
Momentum indicator for all symbols in the dictionary will be updated with the latest closing price.
- We choose the period of the momentum to be 12 months. Stocks with the best 12-month momentum (12-month performance) are then added to our portfolio and are weighted equally. + We choose a period of 12 months for the momentum indicator. Stocks with the best 12-month momentum (12-month performance) are then added to our portfolio and are weighted equally.
The portfolio is rebalanced once a month. The coarse and fine universe selection is set to default to run at midnight once a day. To make the universe selection run at the first trading day each month, we use the bool variable
- self.monthly_rebalance to manage the universe selection. At the start of each month, the universe selection will filter new stocks. In other days, it will return the same symbols. In contrast to returning an empty list, returning the same symbols as before is a better way for monthly rebalance universe selection. Since if there are no open positions for certain symbol, returning empty list will stop the data subscription of that symbol. You might not be able to update the indicator value in OnData().
+ self.monthly_rebalance to manage the universe selection. At the start of each month, the universe selection will filter new stocks. On all other days, the universe selection function will return the same symbols. In contrast to returning an empty list, returning the same symbols as before is a better way for monthly rebalance universe selection. Since if there are no open positions for certain symbol, returning empty list will stop the data subscription of that symbol halt updates of the indicator.
= $strategy['description'] ?>
+ = $sources ?>+ API tutorials seek to give you an introduction to building an algorithm using the QuantConnect API. +
From 493fada1dd80519c6e7bba248be05f2df705d542 Mon Sep 17 00:00:00 2001 From: JaredTutorial Series
From deafec0cd28f796e3e8907beae73aa0acc603052 Mon Sep 17 00:00:00 2001 From: JaredThe time rules trigger specify when on the day the event should be triggered. They can be specified as below:
-| Implementation Steps | |
|---|---|
| 1. | Laying a Foundation, (IBrokerageFactory) Stub out the implementation and initialize a brokerage instance. |
+
| 2. | Creating The Brokerage (IBrokerage) Installing key brokerage application logic, where possible using a brokerage SDK. |
+
| 3. | Translating Symbol Conventions (ISymbolMapper) Translate brokerage specific tickers to LEAN format for a uniform algorithm design experience. |
+
| 4. | Describe Broker Limitations (IBrokerageModel) Describe brokerage support of orders and set transaction models. |
+
| 5. | Enable Live Data Streaming (IDataQueueHandler) Live streaming data service from brokerage supplied source. |
+
| 6. | Enable Serving Historical Data (IHistoryProvider) Tap into the brokerage historical data API to serve history for live algorithms. |
+
| 7. | Download Data (IDataDownloader) Save data from the brokerage to disk in LEAN format. |
+
| 8. | Describe Brokerage Fee Structures (IFeeModel) Enable accurate backtesting with specific fee structures of the brokerage. |
+
| 9. | Update Algorithm API for Easy Setup of Brokerage Models (ISecurityTransactionModel) Combine the various models together to form a brokerage set. |
+
- Liquidity has a powerful impact on price and the valuation of equities. Stocks with little liquidity are used to earning higher returns than stocks with high liquidity. In this algorithm, - We present the effect of liquidity on returns for the lowest capitalization quartile from the largest 1500 stocks. + Liquidity has a powerful impact on price and the valuation of equities. Stocks with little liquidity are used to earning higher returns than stocks with high liquidity. In this algorithm, we present the effect of liquidity on returns for the lowest capitalization quartile from the largest 1500 stocks.
From a03e642a2d67769cb21c458b5c54ac3f717ee749 Mon Sep 17 00:00:00 2001 From: Jing Wu
From bc76992a9cd4f3071b78c76809a6eb60724962a3 Mon Sep 17 00:00:00 2001
From: www-data
The root of the brokerage system is the algorithm job packets. These hold configuration information about how to run LEAN. The program logic is a little convoluted; it moves from config.json > create job packet > create brokerage factory matching name > set job packet brokerage data > factory creates brokerage instance. Because of this we'll start creating a brokerage at the root -- the configuration and brokerage factory...
\ No newline at end of file From 95ec2db72fea329a06feb67cfbfd05a703a03eaa Mon Sep 17 00:00:00 2001 From: www-dataThe root of the brokerage system is the algorithm job packets. These hold configuration information about how to run LEAN. The program logic is a little convoluted; it moves from config.json > create job packet > create brokerage factory matching name > set job packet brokerage data > factory creates brokerage instance. Because of this we'll start creating a brokerage at the root -- the configuration and brokerage factory...
\ No newline at end of file + \ No newline at end of file From f96c4b41dfe4a188eec55ba1880f634cf06f7b28 Mon Sep 17 00:00:00 2001 From: Jared BroadThe root of the brokerage system is the algorithm job packets. These hold configuration information about how to run LEAN. The program logic is a little convoluted; it moves from config.json > create job packet > create brokerage factory matching name > set job packet brokerage data > factory creates brokerage instance. Because of this we'll start creating a brokerage at the root -- the configuration and brokerage factory...
\ No newline at end of file From 80e1b9c180419051a6998f506366a5e3fb48101e Mon Sep 17 00:00:00 2001 From: www-data
+The IBrokerageFactory creates brokerage instances with a Job Packet which configures LEAN. It contains the name of the selected brokerage to create, which is used to create the right BrokerageFactory type. The configuration live-mode-brokerage key is used to set the brokerage name.
+
+In the configuration file add a few key-values with your brokerage configuration information. This will be used for most local debugging and testing as the default. E.g. oanda-access-token and oanda-account-id. These will be copied to the job packet which contains a matching field BrokerageData. This is a dictionary of <string,string> pairs.
+
+By default the IBrokerageFactory.BrokerageData implementation should load all required configuration from the config file using the Config class. E.g. Config.Get("oanda-access-token"). This can be a simple pass through to the config for most brokerages.
+
+Brokerage Models tell LEAN what order types a brokerage supports, whether we're allowed to update an order, and what transaction models to use for fills. It is important to do but something we can come back to later. For now, we should just create a stub implementation which we'll extend and improve later. This file MyBrokerageBrokerageModel.cs lives in the /Common/Brokerages folder. For now, you can make it an empty implementation inheriting from the DefaultBrokerageModel. See this example of a partially implemented model here. Set your empty placeholder model to the BrokerageModel property.
+
Brokerage Models tell LEAN what order types a brokerage supports, whether we're allowed to update an order, and what transaction models to use for fills. It is important to do but something we can come back to later. For now, we should just create a stub implementation which we'll extend and improve later. This file MyBrokerageBrokerageModel.cs lives in the /Common/Brokerages folder. For now, you can make it an empty implementation inheriting from the DefaultBrokerageModel. See this example of a partially implemented model here. Set your empty placeholder model to the BrokerageModel property.
+
+The Brokerage Factory uses a job packet to create an initialized brokerage instance. This happens in the CreateBrokerage() method. You should assume the job has the best source of data not the class BrokerageData property. The BrokerageData property on the factory are the starting default values sourced from config which can be overridden by a runtime job.
+
+Given our IBrokerage implementation hasn't been started yet let's make a placeholder file for our brokerage with the methods stubbed out: MyBrokerage.cs in the MyBrokerage folder, in the Brokerages solution. All the methods should throw a new NotImplementedException() for now except for the constructor which should save any required authentication data to private variables. The CreateBrokerage() method should create a brokerage object but not connect to the brokerage. The connection is done later in the LEAN start up process.
live-mode-brokerage key is used to set the brokerage name.
-
In the configuration file add a few key-values with your brokerage configuration information. This will be used for most local debugging and testing as the default. E.g. oanda-access-token and oanda-account-id. These will be copied to the job packet which contains a matching field BrokerageData. This is a dictionary of <string,string> pairs.
By default the IBrokerageFactory.BrokerageData implementation should load all required configuration from the config file using the Config class. E.g. Config.Get("oanda-access-token"). This can be a simple pass through to the config for most brokerages.
Brokerage Models tell LEAN what order types a brokerage supports, whether we're allowed to update an order, and what transaction models to use for fills. It is important to do but something we can come back to later. For now, we should just create a stub implementation which we'll extend and improve later. This file MyBrokerageBrokerageModel.cs lives in the /Common/Brokerages folder. For now, you can make it an empty implementation inheriting from the DefaultBrokerageModel. See this example of a partially implemented model here. Set your empty placeholder model to the BrokerageModel property.
The Brokerage Factory uses a job packet to create an initialized brokerage instance. This happens in the CreateBrokerage() method. You should assume the job has the best source of data not the class BrokerageData property. The BrokerageData property on the factory are the starting default values sourced from config which can be overridden by a runtime job.
Given our IBrokerage implementation hasn't been started yet let's make a placeholder file for our brokerage with the methods stubbed out: MyBrokerage.cs in the MyBrokerage folder, in the Brokerages solution. All the methods should throw a new NotImplementedException() for now except for the constructor which should save any required authentication data to private variables. The CreateBrokerage() method should create a brokerage object but not connect to the brokerage. The connection is done later in the LEAN start up process.
+
+In the config file LEAN has helper environments which group configuration flags together and override the root configuration values. You should make a mybrokerage-live environment for your brokerage which specifies the brokerage type name for live-mode-brokerage. You should copy the paper-trading brokerage setup to start. You should set the environment value to your new brokerage environment for testing.
Guide to using the desktop charting environment that comes with LEAN (UX v1.0).
VIsual Studio plugin integrated with the QuantConnect API.
+ +Configuring your installation to pull financial data from the QuantConnect website repository.
Guide to implementing your own brokerage in LEAN.
+ ++The Visual Studio plugin is a tool which allows you to code locally; harnessing all the power of Visual Studio's autocomplete and code analysis; while also backtesting in the QuantConnect Cloud. It aims to facilitate your strategy development. +
+ ++ You can download the plugin here: + QuantConnect.VisualStudioPlugin.vsix +
\ No newline at end of file From f696232f4d76f9c477c71f62f8fef109835ddc60 Mon Sep 17 00:00:00 2001 From: www-dataYou can download the plugin here: QuantConnect.VisualStudioPlugin.vsix -
\ No newline at end of file + + +Visual Studio 2015 and 2017 are supported.
\ No newline at end of file From 7c9d8f275e3f1a319abca59652e72eb29f03bc43 Mon Sep 17 00:00:00 2001 From: www-dataYou can download the plugin here: - QuantConnect.VisualStudioPlugin.vsix -
- -Visual Studio 2015 and 2017 are supported.
\ No newline at end of file + QuantConnect.VisualStudioPlugin.vsix + \ No newline at end of file From c4bd8ec3cbf62aff0fe45bfae272ad549730c45a Mon Sep 17 00:00:00 2001 From: www-data+To install the plugin simply build the binary supplied above; or you can rebuild it from scratch from the LEAN project. To build it from scratch please follow the instructions below. +
+ ++If you have intstalled a previous version of the plugin you first need to remove this by your Tools Menu. You can find this in the ‘Tools’ Menu → ‘Extensions and Updates...’ → ‘Installed’. Then search for ‘QuantConnect.VisualStudioPlugin’ and uninstall. Once uninstalled; restart Visual Studio. +
++After building navigate to ‘..\Lean\VisualStudioPlugin\bin\Release’. Execute ‘QuantConnect.VisualStudioPlugin.vsix’. +
+ +
+The Visual Studio plugin is a tool which allows you to code locally; harnessing all the power of Visual Studio's autocomplete and code analysis; while also backtesting in the QuantConnect Cloud. It aims to facilitate your strategy development.
From 5d847ad187555b8f7a11f29cc37ff34cd5f3b409 Mon Sep 17 00:00:00 2001 From: www-data
++Manually logging in is only required the first time. After the first login the plugin will automatically login, using previously saved credentials. +
\ No newline at end of file From bfb4190ab5eda6b1baee5314fafc8369c146aee3 Mon Sep 17 00:00:00 2001 From: www-data+The Visual Studio plugin can currently save files to a project, compile the project, and backtest it in the cloud. Through the accompanying "tool window" it can also rename, open or add a note to a backtest, and create a new project. +
+ ++Save files from your local project to a QuantConnect project. You can save many files at a time. +
+

+This feature allows you to upload one or more files to a target project, compile it and backtest it in the QuantConnect cloud. +
+

+The backtesting tool window utility allows you to monitor and control ongoing backtests, along with editing various properties of existing completed backtests. +
+
++If you select a project ‘BuyTheDip_007’ using the tool windows combo box and launch a backtest using ‘Send For Backtesting’ for ‘BuyTheDip_007’ project, it will display the backtests progress in the tool window. +
+ ++From the Visual Studio IDE go to ‘View’ menu → ‘Other Windows’ → ‘QuantConnect’. If there are previous valid credentials, the tool window will auto login when open or when the user performs an action. +
+ +
+
++VisualStudio plugin can write log data to the VisualStudio activity log, but only if VisualStudio is started with the /log parameter switch. To debug the QuantConnect plugin start VisualStudio with the following command: +
+devenv /log <path-to-log>+
+See Visual Studio Documentation for more information. +
\ No newline at end of file From 9b127751c05b3c939530cf7917aca52748ce6f93 Mon Sep 17 00:00:00 2001 From: Jared+ Long volatility means that the value of your portfolio increases when the volatility goes up. + Short volatility means that you make money when the volatility goes down. The simplest example of volatility selling involves the sale of put and call contracts. + Traders often long volatility by holding the long position of put or call options for hedging purpose. + In contrast, the short volatility strategy expects to earn the systematic risk premium by selling options. + This algorithm will explore the risk premium effect in volatility selling. +
diff --git a/04 Strategy Library/25 Volatility Risk Premium Effect/02 Method.html b/04 Strategy Library/25 Volatility Risk Premium Effect/02 Method.html new file mode 100644 index 0000000..fbf46c1 --- /dev/null +++ b/04 Strategy Library/25 Volatility Risk Premium Effect/02 Method.html @@ -0,0 +1,48 @@ ++ This short volatility algorithm first prescreens the option contracts by the expiry and the strike. + To include the weekly contract, we use the universe function +
+def Initialize(self): + option.SetFilter(self.UniverseFunc) + def UniverseFunc(self, universe): + return universe.IncludeWeeklys().Strikes(-20, 20).Expiration(timedelta(25), timedelta(35)) ++
+ The algorithm selects contracts with one month until maturity so we choose a small range for expiration. +
+
+ In OnData(), we divide the option chain into put and call options. Then we create two lists
+ expiries and strikes to save all available expiration dates and stike prices to facilitate
+ sorting and filtering.
+
+ The algorithm needs three option contracts with one month to the maturity: one ATM call, one ATM put to contruct the ATM straddle,
+ one 15% OTM put. As it's difficult to find the contract with the specified days to maturity and strikes,
+ we use min() to find the most closest contract.
+
expiries = [i.Expiry for i in puts] +# determine expiration date nearly 30 days +expiry = min(expiries, key=lambda x: abs((x.date()-self.Time.date()).days-30)) +strikes = [i.Strike for i in puts] +# determine at-the-money strike +strike = min(strikes, key=lambda x: abs(x-underlying_price)) +# determine 15% out-of-the-money strike +otm_strike = min(strikes, key = lambda x:abs(x-Decimal(0.85)*underlying_price)) ++
+ From the above expiration date and strike price, we pick three option contracts +
+self.atm_call = [i for i in calls if i.Expiry == expiry and i.Strike == strike] +self.atm_put = [i for i in puts if i.Expiry == expiry and i.Strike == strike] +self.otm_put = [i for i in puts if i.Expiry == expiry and i.Strike == otm_strike] ++
+ In trading, we sell the ATM straddle by selling one ATM call and one ATM put. Then we buy an OTM put option as insurance against a market crash. + Then we wait until the expiration and sell the underlying positions after option exercise and assignment. The portfolio is rebalanced once a month. +
diff --git a/04 Strategy Library/25 Volatility Risk Premium Effect/04 Algorithm.html b/04 Strategy Library/25 Volatility Risk Premium Effect/04 Algorithm.html new file mode 100644 index 0000000..a0bce57 --- /dev/null +++ b/04 Strategy Library/25 Volatility Risk Premium Effect/04 Algorithm.html @@ -0,0 +1,6 @@ + From b654eab0071d5c1b6b251e52801e85caeae2f49b Mon Sep 17 00:00:00 2001 From: www-data-To install the plugin simply build the binary supplied above; or you can rebuild it from scratch from the LEAN project. To build it from scratch please follow the instructions below. +To install the plugin simply build the binary supplied above, or you can rebuild it from scratch from the LEAN project. To build it from scratch please follow the instructions below.
-If you have intstalled a previous version of the plugin you first need to remove this by your Tools Menu. You can find this in the ‘Tools’ Menu → ‘Extensions and Updates...’ → ‘Installed’. Then search for ‘QuantConnect.VisualStudioPlugin’ and uninstall. Once uninstalled; restart Visual Studio. +If you have intstalled a previous version of the plugin you first need to remove this first. You do this from the ‘Tools’ Menu → ‘Extensions and Updates...’ → ‘Installed’. Then search for ‘QuantConnect.VisualStudioPlugin’ and click uninstall. Once uninstalled; remember to restart Visual Studio.
-After building navigate to ‘..\Lean\VisualStudioPlugin\bin\Release’. Execute ‘QuantConnect.VisualStudioPlugin.vsix’. +After building navigate to ‘..\Lean\VisualStudioPlugin\bin\Release’. If you built sucessfully you should be able to execute ‘QuantConnect.VisualStudioPlugin.vsix’.
-Manually logging in is only required the first time. After the first login the plugin will automatically login, using previously saved credentials. +Manually logging in is only required the first time. After the first login, the plugin will automatically log in using previously saved credentials.
\ No newline at end of file From d58b262d4612d614c99a6c8f8b4c7ee51d487921 Mon Sep 17 00:00:00 2001 From: www-data
\ No newline at end of file
From 82c7ca5b8aa599dd88707bfe6d4fd02bd83bea2e Mon Sep 17 00:00:00 2001
From: www-data To install the plugin simply build the binary supplied above, or you can rebuild it from scratch from the LEAN project. To build it from scratch please follow the instructions below.
--The Visual Studio plugin is a tool which allows you to code locally; harnessing all the power of Visual Studio's autocomplete and code analysis; while also backtesting in the QuantConnect Cloud. It aims to facilitate your strategy development. +The Visual Studio plugin is a tool which allows you to code locally; harnessing all the power of Visual Studio's autocomplete and code analysis; while also backtesting in the QuantConnect Cloud. It aims to facilitate your strategy development. The plugin supports Visual Studio 2015 and 2017.
From e22816d38ace1ec1366e841902a6f94f7e7e60c9 Mon Sep 17 00:00:00 2001
From: www-data
-To install the plugin simply build the binary supplied above, or you can rebuild it from scratch from the LEAN project. To build it from scratch please follow the instructions below.
+To install the plugin simply execute the binary supplied download above, or you can rebuild it from scratch from the LEAN project. To build it from scratch please follow the instructions below.
To install the plugin simply execute the binary supplied download above, or you can rebuild it from scratch from the LEAN project. To build it from scratch please follow the instructions below.
-Building Plugin
+Build
- In OnData(), we divide the option chain into put and call options. Then we create two lists
+ In OnData(), we divide the option chain into put and call options. Then we create two lists
expiries and strikes to save all available expiration dates and stike prices to facilitate
sorting and filtering.
| + Strategy Name + | +
|---|
|
+ = $strategy['name'] ?>
+ = $strategy['description'] ?> + = $sources ?> + |
+
| + Strategy Name + | +
|---|
|
+ = $strategy['name'] ?>
+ = $strategy['description'] ?> + = $sources ?> + |
+
| - Strategy Name - | -
|---|
|
- = $strategy['name'] ?>
- = $strategy['description'] ?> - = $sources ?> - |
-
+ Commodity futures are excellent portfolio diversifiers and some of them are an effective hedge against inflation. + This algorithm will explore the momentum effect in commodity futures with the momentum return. +
diff --git a/04 Strategy Library/27 Momentum Effect in Commodities Futures/02 Method.html b/04 Strategy Library/27 Momentum Effect in Commodities Futures/02 Method.html new file mode 100644 index 0000000..3bc10d3 --- /dev/null +++ b/04 Strategy Library/27 Momentum Effect in Commodities Futures/02 Method.html @@ -0,0 +1,48 @@ ++ This short volatility algorithm first prescreens the option contracts by the expiry and the strike. + To include the weekly contract, we use the universe function +
+def Initialize(self): + option.SetFilter(self.UniverseFunc) + def UniverseFunc(self, universe): + return universe.IncludeWeeklys().Strikes(-20, 20).Expiration(timedelta(25), timedelta(35)) ++
+ The algorithm selects contracts with one month until maturity so we choose a small range for expiration. +
+
+ In OnData(), we divide the option chain into put and call options. Then we create two lists
+ expiries and strikes to save all available expiration dates and stike prices to facilitate
+ sorting and filtering.
+
+ The algorithm needs three option contracts with one month to the maturity: one ATM call, one ATM put to contruct the ATM straddle,
+ one 15% OTM put. As it's difficult to find the contract with the specified days to maturity and strikes,
+ we use min() to find the most closest contract.
+
expiries = [i.Expiry for i in puts] +# determine expiration date nearly 30 days +expiry = min(expiries, key=lambda x: abs((x.date()-self.Time.date()).days-30)) +strikes = [i.Strike for i in puts] +# determine at-the-money strike +strike = min(strikes, key=lambda x: abs(x-underlying_price)) +# determine 15% out-of-the-money strike +otm_strike = min(strikes, key = lambda x:abs(x-Decimal(0.85)*underlying_price)) ++
+ From the above expiration date and strike price, we pick three option contracts +
+self.atm_call = [i for i in calls if i.Expiry == expiry and i.Strike == strike] +self.atm_put = [i for i in puts if i.Expiry == expiry and i.Strike == strike] +self.otm_put = [i for i in puts if i.Expiry == expiry and i.Strike == otm_strike] ++
+ In trading, we sell the ATM straddle by selling one ATM call and one ATM put. Then we buy an OTM put option as insurance against a market crash. + Then we wait until the expiration and sell the underlying positions after option exercise and assignment. The portfolio is rebalanced once a month. +
diff --git a/04 Strategy Library/27 Momentum Effect in Commodities Futures/04 Algorithm.html b/04 Strategy Library/27 Momentum Effect in Commodities Futures/04 Algorithm.html new file mode 100644 index 0000000..a0bce57 --- /dev/null +++ b/04 Strategy Library/27 Momentum Effect in Commodities Futures/04 Algorithm.html @@ -0,0 +1,6 @@ + From afee6643122dde76bad5b83a0b52f472d0849f90 Mon Sep 17 00:00:00 2001 From: Jing Wu- This short volatility algorithm first prescreens the option contracts by the expiry and the strike. - To include the weekly contract, we use the universe function -
-def Initialize(self): - option.SetFilter(self.UniverseFunc) - def UniverseFunc(self, universe): - return universe.IncludeWeeklys().Strikes(-20, 20).Expiration(timedelta(25), timedelta(35)) --
- The algorithm selects contracts with one month until maturity so we choose a small range for expiration. + As the strategy needs the continuous futures contract, we import the custom data from Quandl. + We create a universe of tradable commodity futures from all available commodity futures traded on CME and ICE. + They are all liquid and active continuous contracts #1. The data from Quandl are non-adjusted price based on spot-month continuous contract calculations. + The data resolution is daily.
- In OnData(), we divide the option chain into put and call options. Then we create two lists
- expiries and strikes to save all available expiration dates and stike prices to facilitate
- sorting and filtering.
-
- The algorithm needs three option contracts with one month to the maturity: one ATM call, one ATM put to contruct the ATM straddle,
- one 15% OTM put. As it's difficult to find the contract with the specified days to maturity and strikes,
- we use min() to find the most closest contract.
+ The first step is importing the data.
expiries = [i.Expiry for i in puts] -# determine expiration date nearly 30 days -expiry = min(expiries, key=lambda x: abs((x.date()-self.Time.date()).days-30)) -strikes = [i.Strike for i in puts] -# determine at-the-money strike -strike = min(strikes, key=lambda x: abs(x-underlying_price)) -# determine 15% out-of-the-money strike -otm_strike = min(strikes, key = lambda x:abs(x-Decimal(0.85)*underlying_price)) +from QuantConnect.Python import PythonQuandl +for symbol in self.symbols: + self.AddData(QuandlFutures, symbol, Resolution.Daily) + +class QuandlFutures(PythonQuandl): + def __init__(self): + self.ValueColumnName = "settle"
- From the above expiration date and strike price, we pick three option contracts
+ Here we use the indicator RateOfChange(period) to simulate the momentum return. Here the period is 12 months.
+ As we are using the custom data, the indicator initialization should use the history request to update the value manually.
+ All indicators are saved in the dictionary self.roc.
self.atm_call = [i for i in calls if i.Expiry == expiry and i.Strike == strike]
-self.atm_put = [i for i in puts if i.Expiry == expiry and i.Strike == strike]
-self.otm_put = [i for i in puts if i.Expiry == expiry and i.Strike == otm_strike]
+self.roc = {}
+for symbol in self.symbols:
+ self.AddData(QuandlFutures, symbol, Resolution.Daily)
+ self.roc[symbol] = RateOfChange(period)
+ hist = self.History([symbol], 400, Resolution.Daily).loc[symbol]
+ for i in hist.itertuples():
+ self.roc[symbol].Update(i.Index, i.settle)
- In trading, we sell the ATM straddle by selling one ATM call and one ATM put. Then we buy an OTM put option as insurance against a market crash.
- Then we wait until the expiration and sell the underlying positions after option exercise and assignment. The portfolio is rebalanced once a month.
+ In OnData(self, data), indicators for all futures contracts are updated every day with the settlement price.
+
+ We rank the contracts by the last 12-month return and divide them into quintiles. + In the trading part, the algorithm goes long on the quintile with the highest momentum return and goes short on the quintile with the lowest momentum return. + The portfolio is rebalanced each month.
diff --git a/04 Strategy Library/27 Momentum Effect in Commodities Futures/04 Algorithm.html b/04 Strategy Library/27 Momentum Effect in Commodities Futures/04 Algorithm.html index a0bce57..a368a10 100644 --- a/04 Strategy Library/27 Momentum Effect in Commodities Futures/04 Algorithm.html +++ b/04 Strategy Library/27 Momentum Effect in Commodities Futures/04 Algorithm.html @@ -1,6 +1,6 @@ - From ab613748ba68aee076c3754350f451be271ea83f Mon Sep 17 00:00:00 2001 From: Jared+ Small caps are typically defined as companies with market caps that are less than $2 billion. + The advantage of investing in small cap companies is that they are young companies with significant growth potential. + However, the risk of failure is greater with small-cap stocks than with large-cap and mid-cap stocks. + In this algorithm, we will explore the performance of the small-capitalization investment. +
diff --git a/04 Strategy Library/28 Small Capitalization Stocks Premium Anomaly/02 Method.html b/04 Strategy Library/28 Small Capitalization Stocks Premium Anomaly/02 Method.html new file mode 100644 index 0000000..0e4dce1 --- /dev/null +++ b/04 Strategy Library/28 Small Capitalization Stocks Premium Anomaly/02 Method.html @@ -0,0 +1,28 @@ ++ The first step is corase universe selection. We create an investment universe with stocks that have fundmental data and has price greater than $5. +
+self.filtered_coarse = [x.Symbol for x in coarse if (x.HasFundamentalData) and (float(x.AdjustedPrice) > 5)] ++
In fine universe selection, we sort the stocks in universe by the market capitalization and choose 10 stocks with the lowest market cap. +
+def FineSelectionFunction(self, fine): + if self.yearly_rebalance: + fine = [x for x in fine if (x.ValuationRatios.PERatio > 0) + and (x.EarningReports.BasicAverageShares.ThreeMonths > 0) + and (x.EarningReports.BasicEPS.TwelveMonths > 0)] + for i in fine: + i.MarketCap = float(i.EarningReports.BasicAverageShares.ThreeMonths * (i.EarningReports.BasicEPS.TwelveMonths*i.ValuationRatios.PERatio)) + sorted_market_cap = sorted(fine, key=lambda x: x.MarketCap) + self.filtered_fine = [i.Symbol for i in sorted_market_cap[:20]] + self.yearly_rebalance = False + return self.filtered_fine + else: + return [] ++
+ In OnData(), we buy 10 stocks in the list of lowest market-cap. The portfolio is rebalanced every year.
+
-The IBrokerageFactory creates brokerage instances with a Job Packet which configures LEAN. It contains the name of the selected brokerage to create, which is used to create the right BrokerageFactory type. The configuration live-mode-brokerage key is used to set the brokerage name.
-
The IBrokerageFactory creates brokerage instances with a Job Packet which configures LEAN. It contains the name of the selected brokerage to create, which is used to create the right BrokerageFactory type. The configuration live-mode-brokerage key is used to set the brokerage name.
-In the configuration file add a few key-values with your brokerage configuration information. This will be used for most local debugging and testing as the default. E.g. oanda-access-token and oanda-account-id. These will be copied to the job packet which contains a matching field BrokerageData. This is a dictionary of <string,string> pairs.
-
In the configuration file add a few key-values with your brokerage configuration information. This will be used for most local debugging and testing as the default. E.g. oanda-access-token and oanda-account-id. These will be copied to the job packet which contains a matching field BrokerageData. This is a dictionary of <string,string> pairs.
-By default the IBrokerageFactory.BrokerageData implementation should load all required configuration from the config file using the Config class. E.g. Config.Get("oanda-access-token"). This can be a simple pass through to the config for most brokerages.
-
By default the IBrokerageFactory.BrokerageData implementation should load all required configuration from the config file using the Config class. E.g. Config.Get("oanda-access-token"). This can be a simple pass through to the config for most brokerages.
-Brokerage Models tell LEAN what order types a brokerage supports, whether we're allowed to update an order, and what transaction models to use for fills. It is important to do but something we can come back to later. For now, we should just create a stub implementation which we'll extend and improve later. This file MyBrokerageBrokerageModel.cs lives in the /Common/Brokerages folder. For now, you can make it an empty implementation inheriting from the DefaultBrokerageModel. See this example of a partially implemented model here. Set your empty placeholder model to the BrokerageModel property.
-
Brokerage Models tell LEAN what order types a brokerage supports, whether we're allowed to update an order, and what transaction models to use for fills. It is important to do but something we can come back to later. For now, we should just create a stub implementation which we'll extend and improve later. This file MyBrokerageBrokerageModel.cs lives in the /Common/Brokerages folder. For now, you can make it an empty implementation inheriting from the DefaultBrokerageModel. See this example of a partially implemented model here. Set your empty placeholder model to the BrokerageModel property.
-The Brokerage Factory uses a job packet to create an initialized brokerage instance. This happens in the CreateBrokerage() method. You should assume the job has the best source of data not the class BrokerageData property. The BrokerageData property on the factory are the starting default values sourced from config which can be overridden by a runtime job.
-
-Given our IBrokerage implementation hasn't been started yet let's make a placeholder file for our brokerage with the methods stubbed out: MyBrokerage.cs in the MyBrokerage folder, in the Brokerages solution. All the methods should throw a new NotImplementedException() for now except for the constructor which should save any required authentication data to private variables. The CreateBrokerage() method should create a brokerage object but not connect to the brokerage. The connection is done later in the LEAN start up process.
-
The Brokerage Factory uses a job packet to create an initialized brokerage instance. This happens in the CreateBrokerage() method. You should assume the job has the best source of data not the class BrokerageData property. The BrokerageData property on the factory are the starting default values sourced from config which can be overridden by a runtime job.
Given our IBrokerage implementation hasn't been started yet let's make a placeholder file for our brokerage with the methods stubbed out: MyBrokerage.cs in the MyBrokerage folder, in the Brokerages solution. All the methods should throw a new NotImplementedException() for now except for the constructor which should save any required authentication data to private variables. The CreateBrokerage() method should create a brokerage object but not connect to the brokerage. The connection is done later in the LEAN start up process.
-In the config file LEAN has helper environments which group configuration flags together and override the root configuration values. You should make a mybrokerage-live environment for your brokerage which specifies the brokerage type name for live-mode-brokerage. You should copy the paper-trading brokerage setup to start. You should set the environment value to your new brokerage environment for testing.
-
In the config file LEAN has helper environments which group configuration flags together and override the root configuration values. You should make a mybrokerage-live environment for your brokerage which specifies the brokerage type name for live-mode-brokerage. You should copy the paper-trading brokerage setup to start. You should set the environment value to your new brokerage environment for testing.
In the IBrokerageFactory examples, you'll see code like this: Composer.Instance.AddPart<IDataQueueHandler>(dataQueueHandler), which is adding parts to the "Composer". The Composer is a system in LEAN for loading types dynamically. In this case, it is adding an instance of the DataQueueHandler for the brokerage to the composer. You can think of the composer as a library, and adding parts is like adding books to its collection. But we'll come back to this later...
| IBrokerageFactory | |
|---|---|
| Primary Role | Create and initialize a brokerage instance. |
| Interface | IBrokerage.cs |
| Example | GDAXBrokerageFactory.cs |
| Target Location | In Brokerages Folder in Brokerages Solution |
| Stage 1: Checklist | |
|---|---|
| Configuration keys and placeholder values for brokerage authentication requirements. | |
Created folder for brokerage in Brokerages solution; with MyBrokerageFactory.cs. | |
| Implemented all interfaces of the BrokerageFactory (some with stub implementations). | |
| Create a stub MyBrokerage.cs with Not Implemented exceptions. | |
| Create a stub MyBrokerageBrokerageModel.cs inheriting from DefaultBrokerageModel. | |
Created a mybrokerage live configuration environment specifying your class. | |
Set the environment configuration to your new brokerage environment. | |
environment configuration to your new brokerage environment.Build the solution. Although running won't work the stub implementations should still build.
++The IBrokerage holds the bulk of the core logic responsible for running the brokerage implementation. It has many important roles vital for the stability of a running algorithm. These include: +
+Many smaller models described later use the Brokerage implementation internally so its best to start implementation of the IBrokerage now. Brokerage classes can get quite large so you should use a partial class modifier to break up the files in appropriate categories.
-The IBrokerage holds the bulk of the core logic responsible for running the brokerage implementation. It has many important roles vital for the stability of a running algorithm. These include:
+The IBrokerage holds the bulk of the core logic responsible for running the brokerage implementation. Many smaller models described later use the Brokerage implementation internally so its best to start implementation of the IBrokerage now. Brokerage classes can get quite large so you should use a partial class modifier to break up the files in appropriate categories. It has many important roles vital for the stability of a running algorithm. These include:
Many smaller models described later use the Brokerage implementation internally so its best to start implementation of the IBrokerage now. Brokerage classes can get quite large so you should use a partial class modifier to break up the files in appropriate categories.
+Often brokerages will have their own ticker styles, order class names, event names. Many of the methods in the brokerage implementation may simply be converting from the brokerage object format into LEAN format. You should plan accordingly to write neat code. +
+ +QuantConnect is best used with streaming or socket based brokerage connections. Streaming brokerage implementations allow for the easiest translation of broker events into LEAN events. Without streaming order-events you will need to poll for to check for fills. In our experience this is fraught with additional risks and challenges.
+ +
+Most brokerages will provide a wrapper for their API. You should use this where possible as long as it has a permissive license. Although it is technically possible to embed an external github repository we've elected to not do this to make LEAN easier to install (submodules can be tricky for beginners). You should copy the library into its own subfolder of the brokerage implementation: /Brokerages/MyBrokerage/BrokerLib/*.
+
Libraries will need to be .NET Framework 4.6.2 compatible as LEAN is fully cross-platform via Mono.
++LEAN Open-Source. If you copy and paste code from an external source leave the comments and headers intact, and if they do not have a comment header be sure to add one to each file referencing the source. Let's keep the attributions in place. +
+ +| IBrokerage | |
|---|---|
| Primary Role | Brokerage connection, orders and fill events. |
| Interface | IBrokerage.cs |
| Example | GDAXBrokerage.cs |
| Target Location | QuantConnect.Brokerages.sln |
The IBrokerageFactory creates brokerage instances with a Job Packet which configures LEAN. It contains the name of the selected brokerage to create, which is used to create the right BrokerageFactory type. The configuration live-mode-brokerage key is used to set the brokerage name.
+The IBrokerageFactory creates brokerage instances with a Job Packet which configures LEAN. It contains the name of the selected brokerage to create, which is used to create the right BrokerageFactory type. The configuration live-mode-brokerage key is used to set the brokerage name.
+
In the configuration file add a few key-values with your brokerage configuration information. This will be used for most local debugging and testing as the default. E.g. oanda-access-token and oanda-account-id. These will be copied to the job packet which contains a matching field BrokerageData. This is a dictionary of <string,string> pairs.
+In the configuration file add a few key-values with your brokerage configuration information. This will be used for most local debugging and testing as the default. E.g. oanda-access-token and oanda-account-id. These will be copied to the job packet which contains a matching field BrokerageData. This is a dictionary of <string,string> pairs.
+
By default the IBrokerageFactory.BrokerageData implementation should load all required configuration from the config file using the Config class. E.g. Config.Get("oanda-access-token"). This can be a simple pass through to the config for most brokerages.
+By default the IBrokerageFactory.BrokerageData implementation should load all required configuration from the config file using the Config class. E.g. Config.Get("oanda-access-token"). This can be a simple pass through to the config for most brokerages.
+
Brokerage Models tell LEAN what order types a brokerage supports, whether we're allowed to update an order, and what transaction models to use for fills. It is important to do but something we can come back to later. For now, we should just create a stub implementation which we'll extend and improve later. This file MyBrokerageBrokerageModel.cs lives in the /Common/Brokerages folder. For now, you can make it an empty implementation inheriting from the DefaultBrokerageModel. See this example of a partially implemented model here. Set your empty placeholder model to the BrokerageModel property.
+Brokerage Models tell LEAN what order types a brokerage supports, whether we're allowed to update an order, and what transaction models to use for fills. It is important to do but something we can come back to later. For now, we should just create a stub implementation which we'll extend and improve later. This file MyBrokerageBrokerageModel.cs lives in the /Common/Brokerages folder. For now, you can make it an empty implementation inheriting from the DefaultBrokerageModel. See this example of a partially implemented model here. Set your empty placeholder model to the BrokerageModel property.
+
The Brokerage Factory uses a job packet to create an initialized brokerage instance. This happens in the CreateBrokerage() method. You should assume the job has the best source of data not the class BrokerageData property. The BrokerageData property on the factory are the starting default values sourced from config which can be overridden by a runtime job.
Given our IBrokerage implementation hasn't been started yet let's make a placeholder file for our brokerage with the methods stubbed out: MyBrokerage.cs in the MyBrokerage folder, in the Brokerages solution. All the methods should throw a new NotImplementedException() for now except for the constructor which should save any required authentication data to private variables. The CreateBrokerage() method should create a brokerage object but not connect to the brokerage. The connection is done later in the LEAN start up process.
+The Brokerage Factory uses a job packet to create an initialized brokerage instance. This happens in the CreateBrokerage() method. You should assume the job has the best source of data not the class BrokerageData property. The BrokerageData property on the factory are the starting default values sourced from config which can be overridden by a runtime job.
+
+Given our IBrokerage implementation hasn't been started yet let's make a placeholder file for our brokerage with the methods stubbed out: MyBrokerage.cs in the MyBrokerage folder, in the Brokerages solution. All the methods should throw a new NotImplementedException() for now except for the constructor which should save any required authentication data to private variables. The CreateBrokerage() method should create a brokerage object but not connect to the brokerage. The connection is done later in the LEAN start-up process.
+
In the config file LEAN has helper environments which group configuration flags together and override the root configuration values. You should make a mybrokerage-live environment for your brokerage which specifies the brokerage type name for live-mode-brokerage. You should copy the paper-trading brokerage setup to start. You should set the environment value to your new brokerage environment for testing.
+In the config file LEAN has helper environments which group configuration flags together and override the root configuration values. You should make a mybrokerage-live environment for your brokerage which specifies the brokerage type name for live-mode-brokerage. You should copy the paper-trading brokerage setup to start. You should set the environment value to your new brokerage environment for testing.
+
In the IBrokerageFactory examples, you'll see code like this: Composer.Instance.AddPart<IDataQueueHandler>(dataQueueHandler), which is adding parts to the "Composer". The Composer is a system in LEAN for loading types dynamically. In this case, it is adding an instance of the DataQueueHandler for the brokerage to the composer. You can think of the composer as a library, and adding parts is like adding books to its collection. But we'll come back to this later...
| IBrokerage | |
|---|---|
| Primary Role | Brokerage connection, orders and fill events. |
| Interface | IBrokerage.cs |
| Example | GDAXBrokerage.cs |
| Target Location | QuantConnect.Brokerages.sln |
The IBrokerage holds the bulk of the core logic responsible for running the brokerage implementation. Many smaller models described later use the Brokerage implementation internally so its best to start implementation of the IBrokerage now. Brokerage classes can get quite large so you should use a partial class modifier to break up the files in appropriate categories. It has many important roles vital for the stability of a running algorithm. These include:
+Implementation Style. This guide will focus mostly on implementing the brokerage step by step in LEAN; as its a more natural workflow for most people. You can also follow a more test-driven-development process by following the test harness. To do this create a new test class which extends from the base class in /Tests/Brokerages/BrokerageTests.cs. This test-framework tests all the methods for an IBrokerage implementation.
+
QuantConnect is best used with streaming or socket based brokerage connections. Streaming brokerage implementations allow for the easiest translation of broker events into LEAN events. Without streaming order-events you will need to poll for to check for fills. In our experience this is fraught with additional risks and challenges.
@@ -21,24 +37,16 @@
Most brokerages will provide a wrapper for their API. You should use this where possible as long as it has a permissive license. Although it is technically possible to embed an external github repository we've elected to not do this to make LEAN easier to install (submodules can be tricky for beginners). You should copy the library into its own subfolder of the brokerage implementation: /Brokerages/MyBrokerage/BrokerLib/*.
+LEAN Open-Source. If you copy and paste code from an external source leave the comments and headers intact, and if they do not have a comment header be sure to add one to each file referencing the source. Let's keep the attributions in place. +
Libraries will need to be .NET Framework 4.6.2 compatible as LEAN is fully cross-platform via Mono.
-LEAN Open-Source. If you copy and paste code from an external source leave the comments and headers intact, and if they do not have a comment header be sure to add one to each file referencing the source. Let's keep the attributions in place. -
- -| IBrokerage | |
|---|---|
| Primary Role | Brokerage connection, orders and fill events. |
| Interface | IBrokerage.cs |
| Example | GDAXBrokerage.cs |
| Target Location | QuantConnect.Brokerages.sln |
Build the project again to make sure the library is compiling successfully. Its good to make sure your library is integrated successfully before continuing.
+| IBrokerageFactory | |
|---|---|
| Primary Role | Create and initialize a brokerage instance. |
| Interface | IBrokerageFactory.cs |
| Example | GDAXBrokerageFactory.cs |
| Target Location | In Brokerages Folder in Brokerages Solution |
The IBrokerageFactory creates brokerage instances with a Job Packet which configures LEAN. It contains the name of the selected brokerage to create, which is used to create the right BrokerageFactory type. The configuration live-mode-brokerage key is used to set the brokerage name.
In the IBrokerageFactory examples, you'll see code like this: Composer.Instance.AddPart<IDataQueueHandler>(dataQueueHandler), which is adding parts to the "Composer". The Composer is a system in LEAN for loading types dynamically. In this case, it is adding an instance of the DataQueueHandler for the brokerage to the composer. You can think of the composer as a library, and adding parts is like adding books to its collection. But we'll come back to this later...
| IBrokerageFactory | |
|---|---|
| Primary Role | Create and initialize a brokerage instance. |
| Interface | IBrokerage.cs |
| Example | GDAXBrokerageFactory.cs |
| Target Location | In Brokerages Folder in Brokerages Solution |
| Advanced BootCamp Lessons | +Status | +
|---|---|
Coming Soon |
++ |
Every BootCamp lesson is focused on an algorithmic strategy's implementation. The first step to planning a lesson is choosing a strategy which does not overlap with any of the existing BootCamp topics. This can be incrementally more difficult but should introduce new concepts.
+ ++After selecting your strategy you need to fully implement the algorithm, writing the code in C# and Python as simply as possible. Users new to coding have a hard time deciphering large blocks of code so strategies should be kept very simple. +
+ +In writing the strategy remain aware of the conceptual layers you put into the algorithm's codebase. These layers of concepts are where you can separate out the lesson tasks. For example: in writing a lesson "Buy and Hold, with Trailing Stop" you might start by coding up the buy and hold logic, followed by placing a "trailing stop" (Stop Market Order), then finally you can make the stop move by updating its trigger price. These conceptual layers form the basis for how tasks are grouped together.
+QuantConnect has worked with the community to create a list of lessons to be created which would be eligible for compensation. The table below describes these strategies and their associated difficulty level.
+ ++Writing a bootcamp lesson starts by carefully writing out the complete code for the strategy. This should be drafted as simply as possible to ensure each task the student needs to complete will only be 2-5 lines of code. +
+Readability is critical and the code should be well commented with descriptive variable names. Depending on the complexity of the algorithm sometimes its more readable to use string tickers instead of class variables. +
++Carefully write code in a way which neatly separates the algorithm concepts as much as possible. Keep in mind the algorithm will be implemented in tasks by the student. +
+ +| x | dx |
|---|---|
| x | |
| x | |
| x |
-Carefully write code in a way which neatly separates the algorithm concepts as much as possible. Keep in mind the algorithm will be implemented in tasks by the student. +Carefully write code in a way which neatly separates the algorithm concepts as much as possible. Keep in mind the algorithm will be implemented in separate tasks by the student.
- -| x | dx |
|---|---|
| Style | Code Tag |
| x | |
| x | |
| x | |
Headings |
+<h4>Initializaing Algorithms</h4> |
+
-Writing a bootcamp lesson starts by carefully writing out the complete code for the strategy, after this you can break it into tasks, and write small text summaries for each task with the documentation required to teach the reader how to complete the task. +Writing a BootCamp lesson starts by carefully writing out the complete code for the strategy, breaking it into tasks, and write small text summaries for each task with the documentation required to teach the reader how to complete the task.
self.filtered_coarse = [x.Symbol for x in coarse if (x.HasFundamentalData) and (float(x.AdjustedPrice) > 5)] +return [x.Symbol for x in coarse if x.HasFundamentalData and x.AdjustedPrice > 5]
In fine universe selection, we sort the stocks in the universe by the market capitalization and choose 10 stocks with the lowest market cap.
def FineSelectionFunction(self, fine): - if self.yearly_rebalance: - fine = [x for x in fine if (x.ValuationRatios.PERatio > 0) - and (x.EarningReports.BasicAverageShares.ThreeMonths > 0) - and (x.EarningReports.BasicEPS.TwelveMonths > 0)] - for i in fine: - i.MarketCap = float(i.EarningReports.BasicAverageShares.ThreeMonths * (i.EarningReports.BasicEPS.TwelveMonths*i.ValuationRatios.PERatio)) - sorted_market_cap = sorted(fine, key=lambda x: x.MarketCap) - self.filtered_fine = [i.Symbol for i in sorted_market_cap[:20]] - self.yearly_rebalance = False - return self.filtered_fine - else: - return [] + if self.year == self.Time.year: + return self.symbols + + # Calculate the market cap and add the "MarketCap" property to fine universe object + for i in fine: + i.MarketCap = (i.EarningReports.BasicAverageShares.ThreeMonths * + i.EarningReports.BasicEPS.TwelveMonths * + i.ValuationRatios.PERatio) + + sorted_market_cap = sorted([x for x in fine if x.MarketCap > 0], key=lambda x: x.MarketCap) + + self.symbols = [i.Symbol for i in sorted_market_cap[:10]] + return self.symbols
diff --git a/04 Strategy Library/28 Small Capitalization Stocks Premium Anomaly/03 Algorithm.html b/04 Strategy Library/28 Small Capitalization Stocks Premium Anomaly/03 Algorithm.html index 5be3efc..8bab69d 100644 --- a/04 Strategy Library/28 Small Capitalization Stocks Premium Anomaly/03 Algorithm.html +++ b/04 Strategy Library/28 Small Capitalization Stocks Premium Anomaly/03 Algorithm.html @@ -1,6 +1,6 @@ div class="qc-embed-frame" style="display: inline-block; position: relative; width: 100%; min-height: 100px; min-width: 300px;">
return [x.Symbol for x in coarse if x.HasFundamentalData and x.AdjustedPrice > 5] +return [x.Symbol for x in coarse if x.HasFundamentalData and x.Price > 5]
In fine universe selection, we sort the stocks in the universe by the market capitalization and choose 10 stocks with the lowest market cap. diff --git a/04 Strategy Library/28 Small Capitalization Stocks Premium Anomaly/03 Algorithm.html b/04 Strategy Library/28 Small Capitalization Stocks Premium Anomaly/03 Algorithm.html index 8bab69d..f14f61e 100644 --- a/04 Strategy Library/28 Small Capitalization Stocks Premium Anomaly/03 Algorithm.html +++ b/04 Strategy Library/28 Small Capitalization Stocks Premium Anomaly/03 Algorithm.html @@ -1,6 +1,6 @@ div class="qc-embed-frame" style="display: inline-block; position: relative; width: 100%; min-height: 100px; min-width: 300px;">
Momentum is the absolute difference in stocks. \[Momentum = Close_{today}-Close_{N-days-ago}\] - LEAN has the Momentum indicator. We create a class to save the momentum value and warm up the indictor for each symbol. -
-class SymbolData: - def __init__(self, symbol, lookback): - self.symbol = symbol - self.MOM = Momentum(lookback) - - def WarmUpIndicator(self, history): - # warm up the Momentum indicator with the history request - for tuple in history.itertuples(): - item = IndicatorDataPoint(self.symbol, tuple.Index, float(tuple.close)) - self.MOM.Update(item) --
- Dictionary self.symbolDataDict is used to save the momentum class instance SymbolData for each symbol.
- In OnSecuritiesChanged event method, we add the newly selected symbol to the dictionary and initialize the momentum indicator with the history request. For symbols removed from the universe, we remove it from the dictionary. Each day in OnData, the
- Momentum indicator for all symbols in the dictionary will be updated with the latest closing price.
+ Dictionary self.mom is used to save the LEAN Momentum class instance Momentum for each symbol.
+ In OnSecuritiesChanged event method, we add the newly selected symbol to the dictionary and initialize the momentum indicator with the history request. For symbols removed from the universe, we remove it from the dictionary and liquidate its positions. Each day in OnData, the Momentum indicator for all symbols in the dictionary will be updated with the latest closing price.
We choose a period of 12 months for the momentum indicator. Stocks with the best 12-month momentum (12-month performance) are then added to our portfolio and are weighted equally. @@ -32,6 +16,5 @@
- The portfolio is rebalanced once a month. The coarse and fine universe selection is set to default to run at midnight once a day. To make the universe selection run at the first trading day each month, we use the bool variable
- self.monthly_rebalance to manage the universe selection. At the start of each month, the universe selection will filter new stocks. On all other days, the universe selection function will return the same symbols. In contrast to returning an empty list, returning the same symbols as before is a better way for monthly rebalance universe selection. Since if there are no open positions for certain symbol, returning empty list will stop the data subscription of that symbol halt updates of the indicator.
+ The portfolio is rebalanced once a month. The coarse and fine universe selection is set to default to run at midnight once a day. To make the universe selection run at the first trading day each month, we use the int variable self.month that tracks the current month to manage the universe selection. At the start of each month, the universe selection will filter new stocks. On all other days, the universe selection function will return the same symbols self.symbols. In contrast to returning an empty list, returning the same symbols as before is a better way for monthly rebalance universe selection. Since if there are no open positions for certain symbol, returning empty list will stop the data subscription of that symbol halt updates of the indicator.
- The portfolio is rebalanced once a month. The coarse and fine universe selection is set to default to run at midnight once a day. To make the universe selection run at the first trading day each month, we use the int variable self.month that tracks the current month to manage the universe selection. At the start of each month, the universe selection will filter new stocks. On all other days, the universe selection function will return the same symbols self.symbols. In contrast to returning an empty list, returning the same symbols as before is a better way for monthly rebalance universe selection. Since if there are no open positions for certain symbol, returning empty list will stop the data subscription of that symbol halt updates of the indicator.
+ The portfolio is rebalanced once a month. The coarse and fine universe selection is set to default to run at midnight once a day. To make the universe selection run at the first trading day each month, we use the int variable self.month that tracks the current month to manage the universe selection. At the start of each month, the universe selection will filter new stocks. On all other days, the universe selection function will return Universe.Unchanged. In contrast to returning an empty list or a list of previously selected symbols, returning Universe.Unchanged is the best way for monthly rebalance universe selection. If there are no open positions for certain symbol, returning an empty list will stop the data subscription of that symbol and halt updates of the indicator.
Buy and Hold with Trailing Stop
Placing and updating a stop-market order combined with basic charting to visualize the stop price movement.
Assigned
Completed
Completed
Assigned
Assigned
Assigned
Assigned
Assigned
Assigned
Assigned
Assigned
Sector Balanced Universe Selection
Selecting an equally weighted universe of assets covering 33% technology stocks, 33% finance and 33% consumer goods.
Assigned
Hedging FX Books with Interest Rate
Harnessing an alternative data source (Trading Economics) to invest proportionately with interest rate changes in the underlying economies.
Buy and Hold with Trailing Stop
Placing and updating a stop-market order combined with basic charting to visualize the stop price movement.
Completed
Assigned
Completed
Assigned
Assigned
Assigned
Assigned
Assigned
Assigned
Assigned
Assigned
Sector Balanced Universe Selection
Selecting an equally weighted universe of assets covering 33% technology stocks, 33% finance and 33% consumer goods.
Assigned
Hedging FX Books with Interest Rate
Harnessing an alternative data source (Trading Economics) to invest proportionately with interest rate changes in the underlying economies.
Buy and Hold with Trailing Stop
Placing and updating a stop-market order combined with basic charting to visualize the stop price movement.
Assigned
Completed
Completed
Assigned
Assigned
Assigned
Assigned
Assigned
Assigned
Assigned
Assigned
Sector Balanced Universe Selection
Selecting an equally weighted universe of assets covering 33% technology stocks, 33% finance and 33% consumer goods.
Assigned
Hedging FX Books with Interest Rate
Harnessing an alternative data source (Trading Economics) to invest proportionately with interest rate changes in the underlying economies.
-With a few configuration changes you can get desktop charting in LEAN with a HTML5 interface very similar to the one you see in QuantConnect.com. This gives you better visual feedback on your strategy and allows you to improve faster. This tutorial guides you through configuring a desktop charting environment with LEAN. -
-- Local charting (and all local backtesting) requires you to have your own source of data. We provide a way to download FX and CFD data through our API. To get started make sure you have your data in your data folder. By default this is the /Data/ directory relative to your LEAN installation. -
-- Two configuration changes are required for desktop charting to work: -
-"environment": "backtesting-desktop",-
// To get your api access token go to quantconnect.com/account - "job-user-id": "....", - "api-access-token": "...........",-
- With those changes in place you can simply run the project and your backtesting chart will appear in a few seconds. For live trading; use the"live-desktop" configuration environment.
- If you get the run-time exception "The port configured in config.json is either being used or blocked by a firewall"- This normally means you've left the user interface open (you should close it between each run). It can also be because another program is sharing that port. You can fix this by changing the port LEAN transmits the data with the "desktop-http-port" setting.
-
- In the tutorial video below we demonstrate this feature on LEAN: -
- From b7d105a2bc22eabd0006105a8209ac00f03371ff Mon Sep 17 00:00:00 2001 From: Martin Molinero- We often want to use an IDE for algorithm development because it provides comprehensive facilities such as a source code editor and a debugger. QuantConnect delivers a robust online source code editor, but not a debugger. For some algorithm developers, a debugger is an essential tool; therefore they opt to work offline with full-featured IDE. -
-- Visual Studio is a full-featured IDE that makes debugging easy. Unlike other solutions that only allows debugging a single process/language, we can use it to debug a python algorithm in Lean (C# engine). -
-- In this tutorial, we'll show you how to debug your algorithm in LEAN from Visual Studio. -
diff --git a/03 Open Source/01 Debugging Python in Visual Studio/02 Prerequisites.html b/03 Open Source/01 Debugging Python in Visual Studio/02 Prerequisites.html deleted file mode 100644 index 5f525e7..0000000 --- a/03 Open Source/01 Debugging Python in Visual Studio/02 Prerequisites.html +++ /dev/null @@ -1,3 +0,0 @@ -Python Tools for Visual Studio debug (ptvsd) server python library. It can be easily installed using pip:
-pip install ptvsd
Unfortunately, this debugging scenario entails some limitations.
-It is not possible to concurrently debug the python algorithm and Lean (C# code). That means that the debugger will not stop at breakpoints in Lean nor we can step into methods defined in Lean (e.g., SetHoldings).
-The algorithm will always stop after ptvsd.break_into_debugger() call and it not possible to untoggled it. However, we can use conditional statements to prevent its call and avoid unnecessary breaks. In order to resume the algorithm execution without breakpoints, we need to detach the process (Debug -> Detach All).
diff --git a/03 Open Source/01 Debugging Python in Visual Studio/00.html b/03 Open Source/01 Debugging Python/00.html similarity index 100% rename from 03 Open Source/01 Debugging Python in Visual Studio/00.html rename to 03 Open Source/01 Debugging Python/00.html diff --git a/03 Open Source/01 Debugging Python/01 Introduction.html b/03 Open Source/01 Debugging Python/01 Introduction.html new file mode 100644 index 0000000..ea57f4a --- /dev/null +++ b/03 Open Source/01 Debugging Python/01 Introduction.html @@ -0,0 +1,7 @@ + + ++ In this tutorial, for those algorithm developers who opt to work offline, we will explore the different methods to debug a python algorithm. +
\ No newline at end of file diff --git a/03 Open Source/01 Debugging Python in Visual Studio/03 Installing LEAN with Python.html b/03 Open Source/01 Debugging Python/02 Installing LEAN with Python.html similarity index 100% rename from 03 Open Source/01 Debugging Python in Visual Studio/03 Installing LEAN with Python.html rename to 03 Open Source/01 Debugging Python/02 Installing LEAN with Python.html diff --git a/03 Open Source/01 Debugging Python in Visual Studio/04 Attaching the Debugger.html b/03 Open Source/01 Debugging Python/03 Method 1 - PTVSD.html similarity index 88% rename from 03 Open Source/01 Debugging Python in Visual Studio/04 Attaching the Debugger.html rename to 03 Open Source/01 Debugging Python/03 Method 1 - PTVSD.html index aaf8b00..4407bf1 100644 --- a/03 Open Source/01 Debugging Python in Visual Studio/04 Attaching the Debugger.html +++ b/03 Open Source/01 Debugging Python/03 Method 1 - PTVSD.html @@ -1,3 +1,8 @@ +Python Tools for Visual Studio debug (ptvsd) server python library. It can be easily installed using pip:
+pip install ptvsd
The process that we will use to attach the python debugger requires that we run Lean without debugging and attach the process.
First, we will add the ptvsd library, and the following statements:
diff --git a/03 Open Source/01 Debugging Python/04 Method 2 - PDB.html b/03 Open Source/01 Debugging Python/04 Method 2 - PDB.html new file mode 100644 index 0000000..026b73a --- /dev/null +++ b/03 Open Source/01 Debugging Python/04 Method 2 - PDB.html @@ -0,0 +1,24 @@ +This method uses the built in, cross-platform, command line python debugger (pdb). + +
+
+ "debugging": true, ++
+ break add ../../../Algorithm.Python/BasicTemplateAlgorithm.py:37 + continue + print(self.Portfolio.Invested) ++
\ No newline at end of file
diff --git a/03 Open Source/01 Debugging Python/05 Method 3 - VisualStudio Debugger.html b/03 Open Source/01 Debugging Python/05 Method 3 - VisualStudio Debugger.html
new file mode 100644
index 0000000..16bec79
--- /dev/null
+++ b/03 Open Source/01 Debugging Python/05 Method 3 - VisualStudio Debugger.html
@@ -0,0 +1,25 @@
+This method uses the (VisualStudio python debugger). + +
Visual Studio Python development feature. It can be easily installed at Tools -> Get Tools and Features...
+ ++
+ "debugging": true, + "debugging-method": "VisualStudio", ++
\ No newline at end of file
diff --git a/03 Open Source/01 Debugging Python/06 Limitations.html b/03 Open Source/01 Debugging Python/06 Limitations.html
new file mode 100644
index 0000000..f126eb5
--- /dev/null
+++ b/03 Open Source/01 Debugging Python/06 Limitations.html
@@ -0,0 +1,3 @@
+Unfortunately, this debugging scenario entails some limitations.
+It is not possible to concurrently debug the python algorithm and Lean (C# code). That means that the debugger will not stop at breakpoints in Lean nor we can step into methods defined in Lean (e.g., SetHoldings).
+Method 1 ptvsd will always stop after ptvsd.break_into_debugger() call and it not possible to untoggled it. However, we can use conditional statements to prevent its call and avoid unnecessary breaks. In order to resume the algorithm execution without breakpoints, we need to detach the process (Debug -> Detach All).
diff --git a/03 Open Source/01 Debugging Python in Visual Studio/06 Summary.html b/03 Open Source/01 Debugging Python/07 Summary.html similarity index 100% rename from 03 Open Source/01 Debugging Python in Visual Studio/06 Summary.html rename to 03 Open Source/01 Debugging Python/07 Summary.html From 827e272da339991879efbea5d7254fdc74580135 Mon Sep 17 00:00:00 2001 From: Martin MolineroThis method uses the built in, cross-platform, command line python debugger (pdb). +
This method uses the built in, cross-platform, command line python debugger pdb.
"debugging": true,
+ "debugging-method": "CommandLine",
This method uses the (VisualStudio python debugger). +
This method uses the Visual Studio Python Development Tools.
Visual Studio Python development feature. It can be easily installed at Tools -> Get Tools and Features...
From 58fdb388df72157c8cafb5e6a5246122abd3f0d9 Mon Sep 17 00:00:00 2001 From: Daniel Chen <44457690+QilongChan@users.noreply.github.com> Date: Wed, 21 Aug 2019 15:01:22 -0700 Subject: [PATCH 509/687] Fama-French Five-Factor Strategy --- .../01 Introduction.html | 3 + .../02 Fama French Five-Factor Model.html | 17 +++++ .../03 Algorithm.html | 66 +++++++++++++++++++ .../04 References.html | 5 ++ 4 files changed, 91 insertions(+) create mode 100644 04 Strategy Library/230 Fama French Five Factors/01 Introduction.html create mode 100644 04 Strategy Library/230 Fama French Five Factors/02 Fama French Five-Factor Model.html create mode 100644 04 Strategy Library/230 Fama French Five Factors/03 Algorithm.html create mode 100644 04 Strategy Library/230 Fama French Five Factors/04 References.html diff --git a/04 Strategy Library/230 Fama French Five Factors/01 Introduction.html b/04 Strategy Library/230 Fama French Five Factors/01 Introduction.html new file mode 100644 index 0000000..12ef392 --- /dev/null +++ b/04 Strategy Library/230 Fama French Five Factors/01 Introduction.html @@ -0,0 +1,3 @@ ++ At QuantConnect, we seek to make financial models ever more accessible to our community. This article will walk through the implementation of a stock selection strategy based on the popular Fama French five-factor financial model. +
\ No newline at end of file diff --git a/04 Strategy Library/230 Fama French Five Factors/02 Fama French Five-Factor Model.html b/04 Strategy Library/230 Fama French Five Factors/02 Fama French Five-Factor Model.html new file mode 100644 index 0000000..fd20400 --- /dev/null +++ b/04 Strategy Library/230 Fama French Five Factors/02 Fama French Five-Factor Model.html @@ -0,0 +1,17 @@ ++ The Fama French five-factor model was proposed in 2014 and is adapted from the Fama French three-factor model (Fama and French, 2015). It builds upon the dividend discount model which states that the value of stocks today is dependent upon future dividends. + Fama and French add two factors, investment and profitability, to the dividend discount model to better capture the relationship between risk and return. + The model is as follows +
+\[ R = \alpha + \beta_m MKT + \beta_s SMB + \beta_h HML + \beta_r RMW + \beta_c CMA\] + ++where +
++ Taking inspiration from the Fama French five-factor model, we can develop a multi-factor stock selection strategy that focuses on five factors: size, value, quality, profitability, and investment pattern. +
++ In the following backtest, we use the terms TotalEquity, BookValuePerShare, OperationProfitMargin, ROE, and TotalAssetsGrowth to account for the five factors, respectively. We then calculate a custom ranking metric for each stock using these five terms. Our algorithm will long the five stocks with the highest scores and short the five stocks with the lowest scores. +
+
+def FineSelectionFunction(self, fine):
+ '''Select securities with highest score on Fama French 5 factors'''
+
+ # select stocks with these 5 factors
+
+ # Operation profit margin: Quality
+ # Book value per share: Value
+ # ROE: Profitability
+ # TotalEquity: Size
+ # TotalAssetsGrowth: Investment Pattern
+ filtered = [x for x in fine if x.OperationRatios.OperationMargin.Value
+ and x.ValuationRatios.BookValuePerShare
+ and x.OperationRatios.ROE
+ and x.FinancialStatements.BalanceSheet.TotalEquity
+ and x.OperationRatios.TotalAssetsGrowth]
+
+
+ # sort by factors
+ sortedByFactor1 = sorted(filtered, key=lambda x: x.OperationRatios.OperationMargin.Value, reverse=True)
+ sortedByFactor2 = sorted(filtered, key=lambda x: x.ValuationRatios.BookValuePerShare, reverse=True)
+ sortedByFactor3 = sorted(filtered, key=lambda x: x.OperationRatios.ROE.Value, reverse=True)
+ sortedByFactor4 = sorted(filtered, key=lambda x: x.FinancialStatements.BalanceSheet.TotalEquity.Value, reverse=True)
+ sortedByFactor5 = sorted(filtered, key=lambda x: x.OperationRatios.TotalAssetsGrowth.Value, reverse=False)
+
+ stockBySymbol = {}
+
+ # get the rank based on 5 factors for every stock
+ for index, stock in enumerate(sortedByFactor1):
+ rank1 = index
+ rank2 = sortedByFactor2.index(stock)
+ rank3 = sortedByFactor3.index(stock)
+ rank4 = sortedByFactor4.index(stock)
+ rank5 = sortedByFactor5.index(stock)
+ avgRank = np.mean([rank1,rank2,rank3,rank4,rank5])
+ stockBySymbol[stock.Symbol] = avgRank
+
+ sorted_dict = sorted(stockBySymbol.items(), key = lambda x: x[1], reverse = True)
+ symbols = [x[0] for x in sorted_dict]
+
+ # pick the stocks with the highest scores to long
+ self.longSymbols= symbols[:self.num_long]
+ # pick the stocks with the lowest scores to short
+ self.shortSymbols = symbols[-self.num_short:]
+
+ return self.longSymbols + self.shortSymbols
+
++ In this example, the portfolio is rebalanced every 30 days and the backtest period runs from Jan 2010 to Aug 2019. You can improve upon this strategy by changing the fundamental factors, the weight of each factor and the rebalance frequency. +
+ + diff --git a/04 Strategy Library/230 Fama French Five Factors/04 References.html b/04 Strategy Library/230 Fama French Five Factors/04 References.html new file mode 100644 index 0000000..a660292 --- /dev/null +++ b/04 Strategy Library/230 Fama French Five Factors/04 References.html @@ -0,0 +1,5 @@ + \ No newline at end of file From fcbfcea5a6613e5249d258dc53bcdf0b9d74ebf7 Mon Sep 17 00:00:00 2001 From: Daniel Chen <44457690+QilongChan@users.noreply.github.com> Date: Wed, 21 Aug 2019 17:26:38 -0700 Subject: [PATCH 510/687] Requested Changes --- .../02 Fama French Five-Factor Model.html | 10 +-- .../03 Algorithm.html | 75 ++++++++++--------- 2 files changed, 44 insertions(+), 41 deletions(-) diff --git a/04 Strategy Library/230 Fama French Five Factors/02 Fama French Five-Factor Model.html b/04 Strategy Library/230 Fama French Five Factors/02 Fama French Five-Factor Model.html index fd20400..0cd9ad3 100644 --- a/04 Strategy Library/230 Fama French Five Factors/02 Fama French Five-Factor Model.html +++ b/04 Strategy Library/230 Fama French Five Factors/02 Fama French Five-Factor Model.html @@ -9,9 +9,9 @@ where- In the following backtest, we use the terms TotalEquity, BookValuePerShare, OperationProfitMargin, ROE, and TotalAssetsGrowth to account for the five factors, respectively. We then calculate a custom ranking metric for each stock using these five terms. Our algorithm will long the five stocks with the highest scores and short the five stocks with the lowest scores. + In the following backtest, we use the terms TotalEquity, BookValuePerShare, OperationProfitMargin, ROE, and TotalAssetsGrowth to account for the five factors, respectively. We then calculate a custom ranking metric for each stock using these five terms. Our algorithm will go long in the five stocks with the highest scores and short the five stocks with the lowest scores.
def FineSelectionFunction(self, fine):
'''Select securities with highest score on Fama French 5 factors'''
-
- # select stocks with these 5 factors
-
- # Operation profit margin: Quality
- # Book value per share: Value
- # ROE: Profitability
- # TotalEquity: Size
- # TotalAssetsGrowth: Investment Pattern
- filtered = [x for x in fine if x.OperationRatios.OperationMargin.Value
- and x.ValuationRatios.BookValuePerShare
- and x.OperationRatios.ROE
+
+ # Select stocks with these 5 factors:
+ # MKT -- Book value per share: Value
+ # SMB -- TotalEquity: Size
+ # HML -- Operation profit margin: Quality
+ # RMW -- ROE: Profitability
+ # CMA -- TotalAssetsGrowth: Investment Pattern
+ filtered = [x for x in fine if x.ValuationRatios.BookValuePerShare
and x.FinancialStatements.BalanceSheet.TotalEquity
+ and x.OperationRatios.OperationMargin.Value
+ and x.OperationRatios.ROE
and x.OperationRatios.TotalAssetsGrowth]
-
-
- # sort by factors
- sortedByFactor1 = sorted(filtered, key=lambda x: x.OperationRatios.OperationMargin.Value, reverse=True)
- sortedByFactor2 = sorted(filtered, key=lambda x: x.ValuationRatios.BookValuePerShare, reverse=True)
- sortedByFactor3 = sorted(filtered, key=lambda x: x.OperationRatios.ROE.Value, reverse=True)
- sortedByFactor4 = sorted(filtered, key=lambda x: x.FinancialStatements.BalanceSheet.TotalEquity.Value, reverse=True)
- sortedByFactor5 = sorted(filtered, key=lambda x: x.OperationRatios.TotalAssetsGrowth.Value, reverse=False)
-
+
+ # Sort by factors
+ sortedByMkt = sorted(filtered, key=lambda x: x.ValuationRatios.BookValuePerShare, reverse=True)
+ sortedBySmb = sorted(filtered, key=lambda x: x.FinancialStatements.BalanceSheet.TotalEquity.Value, reverse=True)
+ sortedByHml = sorted(filtered, key=lambda x: x.OperationRatios.OperationMargin.Value, reverse=True)
+ sortedByRmw = sorted(filtered, key=lambda x: x.OperationRatios.ROE.Value, reverse=True)
+ sortedByCma = sorted(filtered, key=lambda x: x.OperationRatios.TotalAssetsGrowth.Value, reverse=False)
+
stockBySymbol = {}
-
- # get the rank based on 5 factors for every stock
- for index, stock in enumerate(sortedByFactor1):
- rank1 = index
- rank2 = sortedByFactor2.index(stock)
- rank3 = sortedByFactor3.index(stock)
- rank4 = sortedByFactor4.index(stock)
- rank5 = sortedByFactor5.index(stock)
- avgRank = np.mean([rank1,rank2,rank3,rank4,rank5])
+
+ # Get the rank based on 5 factors for every stock
+ for index, stock in enumerate(sortedByMkt):
+ mktRank = self.beta_m * index
+ smbRank = self.beta_s * sortedBySmb.index(stock)
+ hmlRank = self.beta_h * sortedByHml.index(stock)
+ rmwRank = self.beta_r * sortedByRmw.index(stock)
+ cmaRank = self.beta_c * sortedByCma.index(stock)
+ avgRank = np.mean([mktRank,smbRank,hmlRank,rmwRank,cmaRank])
stockBySymbol[stock.Symbol] = avgRank
-
+
sorted_dict = sorted(stockBySymbol.items(), key = lambda x: x[1], reverse = True)
symbols = [x[0] for x in sorted_dict]
-
- # pick the stocks with the highest scores to long
+
+ # Pick the stocks with the highest scores to long
self.longSymbols= symbols[:self.num_long]
- # pick the stocks with the lowest scores to short
+ # Pick the stocks with the lowest scores to short
self.shortSymbols = symbols[-self.num_short:]
-
+
return self.longSymbols + self.shortSymbols
+ The Fama French five-factor model provides a scientific way to measure asset pricing. For the five aspects that Fama and French mentioned, we used one possible combination in our backtest and it performed well. + However, there are still many aspects need to be improved (e.g. the weights of factors, a different set of factors for different kinds of equities,etc.) We encourage you to explore and create better algorithms upon this tutorial! +
\ No newline at end of file From ee6ca904f2c343dc6055b406eeb41e609dcbeb23 Mon Sep 17 00:00:00 2001 From: Daniel Chen <44457690+QilongChan@users.noreply.github.com> Date: Wed, 21 Aug 2019 18:04:36 -0700 Subject: [PATCH 511/687] requested changes --- .../230 Fama French Five Factors/03 Algorithm.html | 4 ++-- quantpedia.json | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/04 Strategy Library/230 Fama French Five Factors/03 Algorithm.html b/04 Strategy Library/230 Fama French Five Factors/03 Algorithm.html index 7f2f419..7f04f12 100644 --- a/04 Strategy Library/230 Fama French Five Factors/03 Algorithm.html +++ b/04 Strategy Library/230 Fama French Five Factors/03 Algorithm.html @@ -64,6 +64,6 @@- The Fama French five-factor model provides a scientific way to measure asset pricing. For the five aspects that Fama and French mentioned, we used one possible combination in our backtest and it performed well. - However, there are still many aspects need to be improved (e.g. the weights of factors, a different set of factors for different kinds of equities,etc.) We encourage you to explore and create better algorithms upon this tutorial! + The Fama French five-factor model provides a scientific way to measure asset pricing. For the five aspects that Fama and French mentioned, we used one possible combination in our backtest. We can see from the results that it achieves an annual rate of return around 5% with a max drawdown of 30% over 8 years. + These factors perhaps cannot capture a sufficient amount of information on the assets' pricing, and therefore, there are still many aspects can be improved (e.g. the weights of factors, a different set of factors for different kinds of equities,etc.) We encourage you to explore and create better algorithms upon this tutorial!
\ No newline at end of file diff --git a/quantpedia.json b/quantpedia.json index cd0aa80..807c061 100644 --- a/quantpedia.json +++ b/quantpedia.json @@ -47,4 +47,5 @@ 199: "2deff750ba4eff5bf2f2138ecffb4a7c", 207: "9bcf7ac117397af393ca59f795c4abdd", 229: "5544552803512ca667342d5011dedd1d", + 230: "78601a5bd785ca32803c13525c688046", } From 2a0f7c1308930ecc90e89c86d34b7cef4f902d3b Mon Sep 17 00:00:00 2001 From: Daniel Chen <44457690+QilongChan@users.noreply.github.com> Date: Thu, 22 Aug 2019 08:42:43 -0700 Subject: [PATCH 512/687] requested changes --- .../01 Introduction.html | 0 .../02 Fama French Five-Factor Model.html | 0 .../03 Algorithm.html | 0 .../04 References.html | 0 quantpedia.json | 1 - 5 files changed, 1 deletion(-) rename 04 Strategy Library/{230 Fama French Five Factors => Fama French Five Factors}/01 Introduction.html (100%) rename 04 Strategy Library/{230 Fama French Five Factors => Fama French Five Factors}/02 Fama French Five-Factor Model.html (100%) rename 04 Strategy Library/{230 Fama French Five Factors => Fama French Five Factors}/03 Algorithm.html (100%) rename 04 Strategy Library/{230 Fama French Five Factors => Fama French Five Factors}/04 References.html (100%) diff --git a/04 Strategy Library/230 Fama French Five Factors/01 Introduction.html b/04 Strategy Library/Fama French Five Factors/01 Introduction.html similarity index 100% rename from 04 Strategy Library/230 Fama French Five Factors/01 Introduction.html rename to 04 Strategy Library/Fama French Five Factors/01 Introduction.html diff --git a/04 Strategy Library/230 Fama French Five Factors/02 Fama French Five-Factor Model.html b/04 Strategy Library/Fama French Five Factors/02 Fama French Five-Factor Model.html similarity index 100% rename from 04 Strategy Library/230 Fama French Five Factors/02 Fama French Five-Factor Model.html rename to 04 Strategy Library/Fama French Five Factors/02 Fama French Five-Factor Model.html diff --git a/04 Strategy Library/230 Fama French Five Factors/03 Algorithm.html b/04 Strategy Library/Fama French Five Factors/03 Algorithm.html similarity index 100% rename from 04 Strategy Library/230 Fama French Five Factors/03 Algorithm.html rename to 04 Strategy Library/Fama French Five Factors/03 Algorithm.html diff --git a/04 Strategy Library/230 Fama French Five Factors/04 References.html b/04 Strategy Library/Fama French Five Factors/04 References.html similarity index 100% rename from 04 Strategy Library/230 Fama French Five Factors/04 References.html rename to 04 Strategy Library/Fama French Five Factors/04 References.html diff --git a/quantpedia.json b/quantpedia.json index 807c061..cd0aa80 100644 --- a/quantpedia.json +++ b/quantpedia.json @@ -47,5 +47,4 @@ 199: "2deff750ba4eff5bf2f2138ecffb4a7c", 207: "9bcf7ac117397af393ca59f795c4abdd", 229: "5544552803512ca667342d5011dedd1d", - 230: "78601a5bd785ca32803c13525c688046", } From 3675f27e197eccdd51b7ab770a0f594573e88842 Mon Sep 17 00:00:00 2001 From: Daniel Chen <44457690+QilongChan@users.noreply.github.com> Date: Thu, 22 Aug 2019 13:33:06 -0700 Subject: [PATCH 513/687] requested changes --- .../01 Introduction.html | 3 + .../02 Method.html | 93 +++++++++++++++++++ .../03 Results.html | 8 ++ .../04 Algorithm.html | 6 ++ .../05 References.html | 5 + .../01 Introduction.html | 3 - .../02 Fama French Five-Factor Model.html | 17 ---- .../03 Algorithm.html | 69 -------------- .../04 References.html | 5 - 9 files changed, 115 insertions(+), 94 deletions(-) create mode 100644 04 Strategy Library/353 Fama French Five Factors/01 Introduction.html create mode 100644 04 Strategy Library/353 Fama French Five Factors/02 Method.html create mode 100644 04 Strategy Library/353 Fama French Five Factors/03 Results.html create mode 100644 04 Strategy Library/353 Fama French Five Factors/04 Algorithm.html create mode 100644 04 Strategy Library/353 Fama French Five Factors/05 References.html delete mode 100644 04 Strategy Library/Fama French Five Factors/01 Introduction.html delete mode 100644 04 Strategy Library/Fama French Five Factors/02 Fama French Five-Factor Model.html delete mode 100644 04 Strategy Library/Fama French Five Factors/03 Algorithm.html delete mode 100644 04 Strategy Library/Fama French Five Factors/04 References.html diff --git a/04 Strategy Library/353 Fama French Five Factors/01 Introduction.html b/04 Strategy Library/353 Fama French Five Factors/01 Introduction.html new file mode 100644 index 0000000..c5889c0 --- /dev/null +++ b/04 Strategy Library/353 Fama French Five Factors/01 Introduction.html @@ -0,0 +1,3 @@ ++ The relationship between return and risk has long been a popular topic for research. Investors have been seeking financial models that quantify risk and use it to estimate the expected return on equity. The Fama French five-factor model, improved from the Fama French three-factor model, is one of the most classic models (Fama and French, 2015). In this post, we will discuss this model and develop a stock-picking strategy based on it. +
\ No newline at end of file diff --git a/04 Strategy Library/353 Fama French Five Factors/02 Method.html b/04 Strategy Library/353 Fama French Five Factors/02 Method.html new file mode 100644 index 0000000..1fd2f52 --- /dev/null +++ b/04 Strategy Library/353 Fama French Five Factors/02 Method.html @@ -0,0 +1,93 @@ ++ The Fama French five-factor model was proposed in 2014 and is adapted from the Fama French three-factor model (Fama and French, 2015). It builds upon the dividend discount model which states that the value of stocks today is dependent upon future dividends. + Fama and French add two factors, investment and profitability, to the dividend discount model to better capture the relationship between risk and return. + The model is as follows +
+\[ R = \alpha + \beta_m MKT + \beta_s SMB + \beta_h HML + \beta_r RMW + \beta_c CMA\] + ++where +
++ Taking inspiration from the Fama French five-factor model, we can develop a multi-factor stock selection strategy that focuses on five factors: size, value, quality, profitability, and investment pattern. +
+ ++ First, we run a Coarse Selection to drop equities which have no fundamental data or have too low prices. Then we select those with the highest dollar volume. + Note that a useful technique is used here: we can use Universe.Unchanged to remain the same universe when there is no necessary change, which greatly speeds up the backtest. +
+ ++def CoarseSelectionFunction(self, coarse): + '''Drop securities which have no fundamental data or have too low prices. + Select those with highest by dollar volume''' + + if self.Time < self.nextLiquidate: + return Universe.Unchanged + + selected = sorted([x for x in coarse if x.HasFundamentalData and x.Price > 5], + key=lambda x: x.DollarVolume, reverse=True) + + return [x.Symbol for x in selected[:self.num_coarse]] ++
+ Secondly, in Fine Selection, we use the terms TotalEquity, BookValuePerShare, OperationProfitMargin, ROE, and TotalAssetsGrowth to account for the five factors, respectively. We then calculate a custom ranking metric for each stock using these five terms. Our algorithm will go long in the five stocks with the highest scores and short the five stocks with the lowest scores. +
+
+def FineSelectionFunction(self, fine):
+ '''Select securities with highest score on Fama French 5 factors'''
+
+ # Select stocks with these 5 factors:
+ # MKT -- Book value per share: Value
+ # SMB -- TotalEquity: Size
+ # HML -- Operation profit margin: Quality
+ # RMW -- ROE: Profitability
+ # CMA -- TotalAssetsGrowth: Investment Pattern
+ filtered = [x for x in fine if x.ValuationRatios.BookValuePerShare
+ and x.FinancialStatements.BalanceSheet.TotalEquity
+ and x.OperationRatios.OperationMargin.Value
+ and x.OperationRatios.ROE
+ and x.OperationRatios.TotalAssetsGrowth]
+
+ # Sort by factors
+ sortedByMkt = sorted(filtered, key=lambda x: x.ValuationRatios.BookValuePerShare, reverse=True)
+ sortedBySmb = sorted(filtered, key=lambda x: x.FinancialStatements.BalanceSheet.TotalEquity.Value, reverse=True)
+ sortedByHml = sorted(filtered, key=lambda x: x.OperationRatios.OperationMargin.Value, reverse=True)
+ sortedByRmw = sorted(filtered, key=lambda x: x.OperationRatios.ROE.Value, reverse=True)
+ sortedByCma = sorted(filtered, key=lambda x: x.OperationRatios.TotalAssetsGrowth.Value, reverse=False)
+
+ stockBySymbol = {}
+
+ # Get the rank based on 5 factors for every stock
+ for index, stock in enumerate(sortedByMkt):
+ mktRank = self.beta_m * index
+ smbRank = self.beta_s * sortedBySmb.index(stock)
+ hmlRank = self.beta_h * sortedByHml.index(stock)
+ rmwRank = self.beta_r * sortedByRmw.index(stock)
+ cmaRank = self.beta_c * sortedByCma.index(stock)
+ avgRank = np.mean([mktRank,smbRank,hmlRank,rmwRank,cmaRank])
+ stockBySymbol[stock.Symbol] = avgRank
+
+ sorted_dict = sorted(stockBySymbol.items(), key = lambda x: x[1], reverse = True)
+ symbols = [x[0] for x in sorted_dict]
+
+ # Pick the stocks with the highest scores to long
+ self.longSymbols= symbols[:self.num_long]
+ # Pick the stocks with the lowest scores to short
+ self.shortSymbols = symbols[-self.num_short:]
+
+ return self.longSymbols + self.shortSymbols
+
++ In this example, the portfolio is rebalanced every 30 days and the backtest period runs from Jan 2010 to Aug 2019. You can improve upon this strategy by changing the fundamental factors, the weight of each factor and the rebalance frequency. +
+ ++ The Fama French five-factor model provides a scientific way to measure asset pricing. For the five aspects that Fama and French mentioned, we used one possible combination in our backtest. We can see from the results that it achieves an annual rate of return around 5% with a max drawdown of 30% over 8 years. + These factors perhaps cannot capture a sufficient amount of information on the assets' pricing, and therefore, there are still many aspects can be improved (e.g. the weights of factors, a different set of factors for different kinds of equities,etc.) We encourage you to explore and create better algorithms upon this tutorial! +
\ No newline at end of file diff --git a/04 Strategy Library/353 Fama French Five Factors/04 Algorithm.html b/04 Strategy Library/353 Fama French Five Factors/04 Algorithm.html new file mode 100644 index 0000000..f3cdbee --- /dev/null +++ b/04 Strategy Library/353 Fama French Five Factors/04 Algorithm.html @@ -0,0 +1,6 @@ + diff --git a/04 Strategy Library/353 Fama French Five Factors/05 References.html b/04 Strategy Library/353 Fama French Five Factors/05 References.html new file mode 100644 index 0000000..4a09697 --- /dev/null +++ b/04 Strategy Library/353 Fama French Five Factors/05 References.html @@ -0,0 +1,5 @@ + \ No newline at end of file diff --git a/04 Strategy Library/Fama French Five Factors/01 Introduction.html b/04 Strategy Library/Fama French Five Factors/01 Introduction.html deleted file mode 100644 index 12ef392..0000000 --- a/04 Strategy Library/Fama French Five Factors/01 Introduction.html +++ /dev/null @@ -1,3 +0,0 @@ -- At QuantConnect, we seek to make financial models ever more accessible to our community. This article will walk through the implementation of a stock selection strategy based on the popular Fama French five-factor financial model. -
\ No newline at end of file diff --git a/04 Strategy Library/Fama French Five Factors/02 Fama French Five-Factor Model.html b/04 Strategy Library/Fama French Five Factors/02 Fama French Five-Factor Model.html deleted file mode 100644 index 0cd9ad3..0000000 --- a/04 Strategy Library/Fama French Five Factors/02 Fama French Five-Factor Model.html +++ /dev/null @@ -1,17 +0,0 @@ -- The Fama French five-factor model was proposed in 2014 and is adapted from the Fama French three-factor model (Fama and French, 2015). It builds upon the dividend discount model which states that the value of stocks today is dependent upon future dividends. - Fama and French add two factors, investment and profitability, to the dividend discount model to better capture the relationship between risk and return. - The model is as follows -
-\[ R = \alpha + \beta_m MKT + \beta_s SMB + \beta_h HML + \beta_r RMW + \beta_c CMA\] - --where -
-- Taking inspiration from the Fama French five-factor model, we can develop a multi-factor stock selection strategy that focuses on five factors: size, value, quality, profitability, and investment pattern. -
-- In the following backtest, we use the terms TotalEquity, BookValuePerShare, OperationProfitMargin, ROE, and TotalAssetsGrowth to account for the five factors, respectively. We then calculate a custom ranking metric for each stock using these five terms. Our algorithm will go long in the five stocks with the highest scores and short the five stocks with the lowest scores. -
-
-def FineSelectionFunction(self, fine):
- '''Select securities with highest score on Fama French 5 factors'''
-
- # Select stocks with these 5 factors:
- # MKT -- Book value per share: Value
- # SMB -- TotalEquity: Size
- # HML -- Operation profit margin: Quality
- # RMW -- ROE: Profitability
- # CMA -- TotalAssetsGrowth: Investment Pattern
- filtered = [x for x in fine if x.ValuationRatios.BookValuePerShare
- and x.FinancialStatements.BalanceSheet.TotalEquity
- and x.OperationRatios.OperationMargin.Value
- and x.OperationRatios.ROE
- and x.OperationRatios.TotalAssetsGrowth]
-
- # Sort by factors
- sortedByMkt = sorted(filtered, key=lambda x: x.ValuationRatios.BookValuePerShare, reverse=True)
- sortedBySmb = sorted(filtered, key=lambda x: x.FinancialStatements.BalanceSheet.TotalEquity.Value, reverse=True)
- sortedByHml = sorted(filtered, key=lambda x: x.OperationRatios.OperationMargin.Value, reverse=True)
- sortedByRmw = sorted(filtered, key=lambda x: x.OperationRatios.ROE.Value, reverse=True)
- sortedByCma = sorted(filtered, key=lambda x: x.OperationRatios.TotalAssetsGrowth.Value, reverse=False)
-
- stockBySymbol = {}
-
- # Get the rank based on 5 factors for every stock
- for index, stock in enumerate(sortedByMkt):
- mktRank = self.beta_m * index
- smbRank = self.beta_s * sortedBySmb.index(stock)
- hmlRank = self.beta_h * sortedByHml.index(stock)
- rmwRank = self.beta_r * sortedByRmw.index(stock)
- cmaRank = self.beta_c * sortedByCma.index(stock)
- avgRank = np.mean([mktRank,smbRank,hmlRank,rmwRank,cmaRank])
- stockBySymbol[stock.Symbol] = avgRank
-
- sorted_dict = sorted(stockBySymbol.items(), key = lambda x: x[1], reverse = True)
- symbols = [x[0] for x in sorted_dict]
-
- # Pick the stocks with the highest scores to long
- self.longSymbols= symbols[:self.num_long]
- # Pick the stocks with the lowest scores to short
- self.shortSymbols = symbols[-self.num_short:]
-
- return self.longSymbols + self.shortSymbols
-
-- In this example, the portfolio is rebalanced every 30 days and the backtest period runs from Jan 2010 to Aug 2019. You can improve upon this strategy by changing the fundamental factors, the weight of each factor and the rebalance frequency. -
- - - -- The Fama French five-factor model provides a scientific way to measure asset pricing. For the five aspects that Fama and French mentioned, we used one possible combination in our backtest. We can see from the results that it achieves an annual rate of return around 5% with a max drawdown of 30% over 8 years. - These factors perhaps cannot capture a sufficient amount of information on the assets' pricing, and therefore, there are still many aspects can be improved (e.g. the weights of factors, a different set of factors for different kinds of equities,etc.) We encourage you to explore and create better algorithms upon this tutorial! -
\ No newline at end of file diff --git a/04 Strategy Library/Fama French Five Factors/04 References.html b/04 Strategy Library/Fama French Five Factors/04 References.html deleted file mode 100644 index a660292..0000000 --- a/04 Strategy Library/Fama French Five Factors/04 References.html +++ /dev/null @@ -1,5 +0,0 @@ - \ No newline at end of file From 4af0db1856b075832c5487e363167cd247de6942 Mon Sep 17 00:00:00 2001 From: AlexCatarino
def Initialize(self):
+
self.SetStartDate(2001, 1, 1)
self.SetEndDate(2018, 8, 1)
self.SetCash(100000)
- self.tickers = [
- "IJJ", # iShares S&P MidCap 400 Value Index ETF
- "IJS", # iShares S&P SmallCap 600 Value ETF
- "IVE", # iShares S&P 500 Value Index ETF
- "IVW", # iShares S&P 500 Growth ETF
- "IJK", # iShares S&P Mid-Cap 400 Growth ETF
- "IJT", # iShares S&P Small-Cap 600 Growth ETF
- ]
- self.symbols = []
- for ticker in self.tickers:
- self.symbols.append(self.AddEquity(ticker, Resolution.Daily).Symbol)
- self.SetWarmUp(timedelta(days=12*20))
- # save all momentum indicator in the dictionary
- self.mom = {i:self.MOM(i, 12*20, Resolution.Daily) for i in self.symbols}
+
+ tickers = ["IJJ", # iShares S&P Mid-Cap 400 Value Index ETF
+ "IJK", # iShares S&P Mid-Cap 400 Growth ETF
+ "IJS", # iShares S&P Small-Cap 600 Value ETF
+ "IJT", # iShares S&P Small-Cap 600 Growth ETF
+ "IVE", # iShares S&P 500 Value Index ETF
+ "IVW"] # iShares S&P 500 Growth ETF
+
+ lookback = 12*20
+
+ # Save all momentum indicator into the dictionary
+ self.mom = dict()
+ for ticker in tickers:
+ symbol = self.AddEquity(ticker, Resolution.Daily).Symbol
+ self.mom[symbol] = self.MOM(symbol, lookback)
@@ -33,12 +35,15 @@
def Rebalance(self):
+ # Order the MOM dictionary by value
sorted_mom = sorted(self.mom, key = lambda x: self.mom[x].Current.Value)
- invested = [x.Key for x in self.Portfolio if x.Value.Invested]
- for i in invested:
- if i not in [sorted_mom[0], sorted_mom[1]]:
- self.Liquidate(i)
- self.SetHoldings(sorted_mom[0], -0.5)
- self.SetHoldings(sorted_mom[-1], 0.5)
+
+ # Liquidate the ETFs that are no longer selected
+ for symbol in sorted_mom[1:-1]:
+ if self.Portfolio[symbol].Invested:
+ self.Liquidate(symbol, 'No longer selected')
+
+ self.SetHoldings(sorted_mom[-1], -0.5) # Short the ETF with lowest MOM
+ self.SetHoldings(sorted_mom[0], 0.5) # Long the ETF with highest MOM
-+ In this tutorial, we will study the model-driven statistical arbitrage strategies in U.S. stocks market. We employ a combination of Principal Components Analysis (PCA) and Linear Regression to implement this strategy. First, by applying PCA, we get a generalized statistical arbitrage strategy that minimizes exposure to market factors and the asset universe is projected onto its first n (n=3 in our algorithm) orthogonal principal components. Secondly, we model the mean-reverting residuals of the cluster of assets and get their weights based on the level of deviation using linear regression. +
diff --git a/04 Strategy Library/211 Mean-Reversion Statistical Arbitrage Strategy in Stocks/02 Method.html b/04 Strategy Library/211 Mean-Reversion Statistical Arbitrage Strategy in Stocks/02 Method.html new file mode 100644 index 0000000..759a3ca --- /dev/null +++ b/04 Strategy Library/211 Mean-Reversion Statistical Arbitrage Strategy in Stocks/02 Method.html @@ -0,0 +1,62 @@ ++ There are three elements of the strategy that will promote mean-reversion and the opportunity for statistical arbitrage: (1) Utilize Coarse selection to obtain the initial universe, (2) Employ PCA to historical prices to get the first 3 principal components for dimension reduction, (3) Apply Linear Regression to get the residuals for measuring the price deviation of each stock in the universe. + We will show how we apply Coarse selection first. +
+ ++ # Sort the equities in DollarVolume decendingly + selected = sorted([x for x in coarse if x.Price > 5], + key=lambda x: x.DollarVolume, reverse=True) + symbols = [x.Symbol for x in selected[:self.num_equities]] ++
+ We see that in Coarse selection we drop stocks with prices lower than $5 and pick the ones with the highest dollar volume. + Then, we go to the PCA part. In this part, based on historical close values, we perform PCA to get the first 3 principal components of the feature space (formed by the historical close values). This helps us + reduce the dimension of the feature space and exclude the noise at the same time. +
+ ++ # Sample data for PCA (smooth it using np.log function) + sample = np.log(history.dropna(axis=1)) + sample -= sample.mean() # Center it column-wise + + # Fit the PCA model for sample data + model = PCA().fit(sample) + + # Get the first n_components factors + factors = np.dot(sample, model.components_.T)[:,:self.num_components] ++
+ Finally, we get to the linear regression part. This part helps us get the weight of each stock in the portfolio based on its price deviation measured by the residual. + If the absolute value of the residual is large, it means that the level of price deviation is high and hence we should give it more weight in the portfolio. Similarly, if the absolute value of the residual is small, + it is reasonable to give the stock less weight in the portfolio. Therefore, we could first standardize the residuals to get their z scores. Then, + based on the z scores, it is easy to detect the level of price deviation. Specifically, the level of deviation is higher when the absolute values of the z scores are large. + So it is natural to use the inverse of the absolute values of the z scores as a measurement of the weights of the portfolio. + All details can be found in the following code snippet. +
+ +
+ # Train Ordinary Least Squares linear model for each stock
+ OLSmodels = {ticker: sm.OLS(sample[ticker], factors).fit() for ticker in sample.columns}
+
+ # Get the residuals from the linear regression after PCA for each stock
+ resids = pd.DataFrame({ticker: model.resid for ticker, model in OLSmodels.items()})
+
+ # Get the Z scores by standarize the given pandas dataframe X
+ zscores = ((resids - resids.mean()) / resids.std()).iloc[-1] # residuals of the most recent day
+
+ # Get the stocks far from mean (for mean reversion)
+ selected = zscores[zscores < -1.5]
+
+ # Return the weights for each selected stock
+ weights = selected * (1 / selected.abs().sum())
+
++ In this tutorial, the portfolio is rebalanced every 30 days and the backtest period runs from Jan 2010 to Aug 2019. We can see from the results that it achieves an annual rate of return over 7% with a max drawdown of around 40% for nearly 10 years. + The performance is generally good, which indicates using PCA combined with Linear regression to measure the deviation level is reasonable. However, there are still many aspects can be improved. + For example, we could expand the original coarse-selected universe. Now we only used 20 equities in this example, and sometimes the algorithm only find one or even no candidate, which might be not enough. + You might increase the number of universe. Besides, we can develop this strategy to a long & short one (now it is only a long strategy). + You could also come up with another way to measure the level of deviation or change the rebalance frequency of the algorithm(30 days in this example). We sincerely hope you create more amazing algorithms upon this tutorial. +
+ diff --git a/04 Strategy Library/211 Mean-Reversion Statistical Arbitrage Strategy in Stocks/04 Algorithm.html b/04 Strategy Library/211 Mean-Reversion Statistical Arbitrage Strategy in Stocks/04 Algorithm.html new file mode 100644 index 0000000..78e62f1 --- /dev/null +++ b/04 Strategy Library/211 Mean-Reversion Statistical Arbitrage Strategy in Stocks/04 Algorithm.html @@ -0,0 +1,6 @@ + diff --git a/04 Strategy Library/211 Mean-Reversion Statistical Arbitrage Strategy in Stocks/05 Reference.html b/04 Strategy Library/211 Mean-Reversion Statistical Arbitrage Strategy in Stocks/05 Reference.html new file mode 100644 index 0000000..218aff7 --- /dev/null +++ b/04 Strategy Library/211 Mean-Reversion Statistical Arbitrage Strategy in Stocks/05 Reference.html @@ -0,0 +1,5 @@ + From 046e6301923ab0d9013dad6636fb332e2bde1383 Mon Sep 17 00:00:00 2001 From: Sherry Yang- In this tutorial, we will study the model-driven statistical arbitrage strategies in U.S. stocks market. We employ a combination of Principal Components Analysis (PCA) and Linear Regression to implement this strategy. First, by applying PCA, we get a generalized statistical arbitrage strategy that minimizes exposure to market factors and the asset universe is projected onto its first n (n=3 in our algorithm) orthogonal principal components. Secondly, we model the mean-reverting residuals of the cluster of assets and get their weights based on the level of deviation using linear regression. + In this tutorial, we will take a close look at a principal component analysis (PCA)-based statistical arbitrage strategy + based on the paper + Statistical Arbitrage in teh U.S. Equities Market. +
++ First, we will apply PCA to minimizes our algorithm's exposure to market factors and project the first n (n=3 in our algorithm) + orthogonal principal components on our asset universe. Then we will model the mean-reverting residuals of our assets. + Next we will create our model using linear regression. Each factor will have a weight or coefficient equal to the residuals' level + of deviation from the mean.
From e32237d82353d929f93e115fab5cde854660201d Mon Sep 17 00:00:00 2001 From: Sherry Yang- There are three elements of the strategy that will promote mean-reversion and the opportunity for statistical arbitrage: (1) Utilize Coarse selection to obtain the initial universe, (2) Employ PCA to historical prices to get the first 3 principal components for dimension reduction, (3) Apply Linear Regression to get the residuals for measuring the price deviation of each stock in the universe. - We will show how we apply Coarse selection first. + ...mean-reversion and opportunity for statistical arbitrage...
We see that in Coarse selection we drop stocks with prices lower than $5 and pick the ones with the highest dollar volume. Then, we go to the PCA part. In this part, based on historical close values, we perform PCA to get the first 3 principal components of the feature space (formed by the historical close values). This helps us @@ -32,14 +35,15 @@ +
- Finally, we get to the linear regression part. This part helps us get the weight of each stock in the portfolio based on its price deviation measured by the residual. + We use linear regression to derive the weight of each stock in the portfolio based on its price deviation measured by the residual. If the absolute value of the residual is large, it means that the level of price deviation is high and hence we should give it more weight in the portfolio. Similarly, if the absolute value of the residual is small, it is reasonable to give the stock less weight in the portfolio. Therefore, we could first standardize the residuals to get their z scores. Then, based on the z scores, it is easy to detect the level of price deviation. Specifically, the level of deviation is higher when the absolute values of the z scores are large. So it is natural to use the inverse of the absolute values of the z scores as a measurement of the weights of the portfolio. All details can be found in the following code snippet. -
+From 5d9d3a96d14563fda3b56f4b61c460111b1b48c2 Mon Sep 17 00:00:00 2001 From: Sherry YangDate: Wed, 28 Aug 2019 13:36:18 -0700 Subject: [PATCH 518/687] Update 01 Introduction.html Submit word change. --- .../01 Introduction.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/04 Strategy Library/211 Mean-Reversion Statistical Arbitrage Strategy in Stocks/01 Introduction.html b/04 Strategy Library/211 Mean-Reversion Statistical Arbitrage Strategy in Stocks/01 Introduction.html index c3e8b0a..0021b43 100644 --- a/04 Strategy Library/211 Mean-Reversion Statistical Arbitrage Strategy in Stocks/01 Introduction.html +++ b/04 Strategy Library/211 Mean-Reversion Statistical Arbitrage Strategy in Stocks/01 Introduction.html @@ -1,6 +1,6 @@ In this tutorial, we will take a close look at a principal component analysis (PCA)-based statistical arbitrage strategy - based on the paper + derived from the paper Statistical Arbitrage in teh U.S. Equities Market.
From 520a8fcb48c8266e2212b171f7796f9c7349c97f Mon Sep 17 00:00:00 2001 From: Sherry Yang
Date: Wed, 28 Aug 2019 13:40:56 -0700 Subject: [PATCH 519/687] Update 03 Results.html Submit initial changes. --- .../03 Results.html | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/04 Strategy Library/211 Mean-Reversion Statistical Arbitrage Strategy in Stocks/03 Results.html b/04 Strategy Library/211 Mean-Reversion Statistical Arbitrage Strategy in Stocks/03 Results.html index ceddace..8734b4f 100644 --- a/04 Strategy Library/211 Mean-Reversion Statistical Arbitrage Strategy in Stocks/03 Results.html +++ b/04 Strategy Library/211 Mean-Reversion Statistical Arbitrage Strategy in Stocks/03 Results.html @@ -1,8 +1,15 @@ + Results
- In this tutorial, the portfolio is rebalanced every 30 days and the backtest period runs from Jan 2010 to Aug 2019. We can see from the results that it achieves an annual rate of return over 7% with a max drawdown of around 40% for nearly 10 years. - The performance is generally good, which indicates using PCA combined with Linear regression to measure the deviation level is reasonable. However, there are still many aspects can be improved. - For example, we could expand the original coarse-selected universe. Now we only used 20 equities in this example, and sometimes the algorithm only find one or even no candidate, which might be not enough. - You might increase the number of universe. Besides, we can develop this strategy to a long & short one (now it is only a long strategy). - You could also come up with another way to measure the level of deviation or change the rebalance frequency of the algorithm(30 days in this example). We sincerely hope you create more amazing algorithms upon this tutorial. + In this tutorial, the portfolio is rebalanced every 30 days and the backtest period runs from Jan 2010 to Aug 2019. + We can see from the results that it achieves an annual rate of return over 7% with a max drawdown of around 40% for nearly 10 years. + The performance is generally good, which indicates using PCA combined with Linear regression to measure the deviation level is + reasonable. However, there are still many aspects can be improved. +
++ For example, we could expand the original coarse-selected universe. Now we only used 20 equities in this example, and sometimes the + algorithm only find one or even no candidate, which might be not enough. You might increase the number of universe. Besides, we can + develop this strategy to a long & short one (now it is only a long strategy). You could also come up with another way to measure the + level of deviation or change the rebalance frequency of the algorithm(30 days in this example). We sincerely hope you create more + amazing algorithms upon this tutorial.
From 91d15af3f084a0e19821f8a5e13741097dcb4a6e Mon Sep 17 00:00:00 2001 From: Sherry YangDate: Wed, 28 Aug 2019 13:41:58 -0700 Subject: [PATCH 520/687] Update 04 Algorithm.html Submit initial edits. --- .../04 Algorithm.html | 1 + 1 file changed, 1 insertion(+) diff --git a/04 Strategy Library/211 Mean-Reversion Statistical Arbitrage Strategy in Stocks/04 Algorithm.html b/04 Strategy Library/211 Mean-Reversion Statistical Arbitrage Strategy in Stocks/04 Algorithm.html index 78e62f1..f404e0b 100644 --- a/04 Strategy Library/211 Mean-Reversion Statistical Arbitrage Strategy in Stocks/04 Algorithm.html +++ b/04 Strategy Library/211 Mean-Reversion Statistical Arbitrage Strategy in Stocks/04 Algorithm.html @@ -1,3 +1,4 @@ + Algorithm
Assigned
Completed
Assigned
Completed
Assigned
Completed
Assigned
+Completed
Separation of Concerns with the Algorithm Framework
A simple strategy to buy SPY each morning on market open using the algorithm framework - a scaffolding for powerful strategy design.
The Algorithm Framework
A simple strategy to buy SPY each morning on market open using the algorithm framework - a scaffolding for powerful strategy design.
Pairs Trading with Cointegration Test
Scanning a basket of assets monthly for potential cointegration and making a pairs trade when detect a divergent pair. Using scheduled events for the cointegration test, and
Pairs Trading with Cointegration Test
Scanning a basket of assets monthly for potential cointegration and making a pairs trade when detect a divergent pair. Using scheduled events for the cointegration test.
Sentiment Analysis on Stocks
Harness Psychsignal data to rank the sentiment of a basket of US Equity stocks and invest in those with the most postive sentiment.
Sentiment Analysis on Stocks
Harness Psychsignal data to rank the sentiment of a basket of US Equity stocks and invest in those with the most positive sentiment.
Our investment logic is simple and straightforward. We assume that stocks which beat the market last month will continue to beat the market. We rank stocks according to their alpha, and each month we "long" the top two stocks. For this strategy to work, we need to do the following at the start of each month:
-Dow Jones components change very infrequently, with the last change being on March 19th, 2015. To make the implementation easier we have simply listed the current Dow components in this algorithm. This means that the earliest start date of this algorithm is March 19th, 2015.
-In the initialize method we define a Scheduled Event to trigger a monthly re-balancing of the portfolio. For more details about how to use Scheduled Events, you can read the Documentation or see the example ScheduledEventsAlgorithm.
def Initialize(self): - self.Schedule.On(self.DateRules.MonthStart(self.benchmark), self.TimeRules.AfterMarketOpen(self.benchmark), Action(self.rebalance)) --
- In order to conduct linear regression, we need to write a function to take the price data and output the regression results. The function takes a list of the "asset prices" (x) and a list of the "benchmark prices" (y). It then calculates the percentage change and conducts a linear regression. The output is a tuple which contains the intercept and slope. + Each month we get the historical prices of the DOW30 components using the History API. The data is returned from the API as a pandas.DataFrame indexed by Symbol objects. The close data is selected and the data frame is unstack to create columns of Symbol objects.
-def regression(self,x,y): - x = np.array(x) - x = np.diff(x)/x[:-1] - y = np.array(y) - y = np.diff(y)/y[:-1] - A = np.vstack([x, np.ones(len(x))]).T - result = np.linalg.lstsq(A, y)[0] - beta = result[0] - alpha = result[1] - return(alpha,beta) -+
# Fetch the historical data to perform the linear regression +history = self.History( + self.symbols + [self.benchmark], + self.lookback, + Resolution.Daily).close.unstack(level=0)
- Each month we get the historical prices of the DOW30 components using the History API. The data is returned from the API as complex Slice objects. To make this useful in the algorithm we extract the asset prices, and benchmark prices to a list. + We aim to trade the two assets with the highest alpha to the benchmark. In order to conduct linear regression to find the alpha (linear regression intercept), we need to compute returns (percentage change of closing price) benchmark and the asset then conduct a linear regression.
def SelectSymbols(self, history): + '''Select symbols with the highest intercept/alpha to the benchmark + ''' + alphas = dict() -def get_regression_data(self,symbol,history): - symbol_price = [] - benchmark_price = [] - for i in history: - bar = i[symbol] - benchmark = i[self.benchmark] - symbol_price.append(bar.Close) - benchmark_price.append(benchmark.Close) + # Get the benchmark returns + benchmark = history[self.benchmark].pct_change().dropna() - result = self.regression(symbol_price,benchmark_price) - return result -+ # Conducts linear regression for each symbol and save the intercept/alpha + for symbol in self.symbols: + + # Get the security returns + returns = history[symbol].pct_change().dropna() + returns = np.vstack([returns, np.ones(len(returns))]).T + + # Simple linear regression function in Numpy + result = np.linalg.lstsq(returns, benchmark) + alphas[symbol] = result[0][1] + + # Select symbols with the highest intercept/alpha to the benchmark + selected = sorted(alphas.items(), key=lambda x: x[1], reverse=True)[:2] + return [x[0] for x in selected]
- This function is where all the action happens, it will be executed on the first trading day of each month as a scheduled event. The second argument of SetHoldings is a decimal, setting this to "1" tells the algorithm to set the portfolio as "long 100%" with no leverage. More information on the function can be read on this link: SetHoldings. + This function is where all the action happens, it will be executed on the first trading day of each month as a scheduled event. The algorithm closes all positions of securities that were not selected using Liquidate and go 100% long for both of the selected symbols using SetHoldings.
-def Rebalance(self): + + # Fetch the historical data to perform the linear regression + history = self.History( + self.symbols + [self.benchmark], + self.lookback, + Resolution.Daily).close.unstack(level=0) + + symbols = self.SelectSymbols(history) + + # Liquidate positions that are not held by selected symbols + for holdings in self.Portfolio.Values: + symbol = holdings.Symbol + if symbol not in symbols and holdings.Invested: + self.Liquidate(symbol) -\ No newline at end of file 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 3d63cc8..f47a119 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,9 +1,6 @@ -def rebalance(self): - # get historical stock symbols and prices, then put them in tuples - history = self.History(self.regression_dates, Resolution.Daily) - filter = [] - for i in self.symbols: - filter.append((i,self.get_regression_data(i, history)[0])) - # sort the filter by alpha - filter.sort(key = lambda x : x[1],reverse = True) - sorted_symbols = [] - for i in range(2): - sorted_symbols.append(filter[i][0]) - # get the symbols of our holding stocks - holding_list = [] - for i in self.Portfolio: - if i.Value.Invested: - holding_list.append(i.Value.Symbol) - # if we have holdings and we are not going to hold them anymore, sell them - if holding_list: - for i in holding_list: - if i not in sorted_symbols: - self.Liquidate(i) - # Long the 2 stock in our list. - for i in sorted_symbols: - self.SetHoldings(i,1) -+ # Invest 100% in the each of the selected symbols + for symbol in symbols: + self.SetHoldings(symbol, 1)
- Backtest using OptionChainProvider -
+