-
Notifications
You must be signed in to change notification settings - Fork 241
Expand file tree
/
Copy path03 Method.html
More file actions
executable file
·86 lines (77 loc) · 4.83 KB
/
03 Method.html
File metadata and controls
executable file
·86 lines (77 loc) · 4.83 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
<p>
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:
</p>
<ul>
<li>Get the historical price of Dow 30 stocks in the past 21 trading days and calculate their daily rates of return.</li>
<li>Conduct simple linear regression on the return of each stock against a benchmark (S&P 500 index, SPY).</li>
<li>Rank the stocks by their intercepts.</li>
<li>Liquidate all our positions and purchase the first 2 stocks in our sorted list.</li>
</ul>
<p>
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.
</p>
<h3>Step 1: Setup Event Handler</h3>
<p>
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 <a href="https://www.quantconnect.com/docs#Scheduled-Events">Documentation</a> or see the example <a href="https://github.com/QuantConnect/Lean/blob/master/Algorithm.Python/ScheduledEventsAlgorithm.py">ScheduledEventsAlgorithm</a>.
</p>
<div class="section-example-container">
<pre class="python">def initialize(self):
self.schedule.on(self.date_rules.month_start(self._symbols[0]),
self.time_rules.after_market_open(self._symbols[0]),
self._rebalance)</pre>
</div>
<h3>Step 2: History Function</h3>
<p>
Each month we get the historical prices of the DOW30 components using the <a href="https://www.quantconnect.com/docs/algorithm-reference/historical-data">History</a> API. The data is returned from the API as a pandas.DataFrame indexed by <em>Symbol</em> objects. The close data is selected and the data frame is unstack to create columns of <em>Symbol</em> objects.
</p>
<div class="section-example-container">
<pre class="python"># Fetch the historical data to perform the linear regression
history = self.history(
self._symbols + [self._benchmark],
self._lookback,
Resolution.DAILY).close.unstack(level=0)</pre>
</div>
<h3>Step 3: Symbol Selection Function</h3>
<p>
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.
</p>
<div class="section-example-container">
<pre class="python">def _select_symbols(self, history):
'''Select symbols with the highest intercept/alpha to the benchmark
'''
alphas = dict()
# Get the benchmark returns
benchmark = history[self._benchmark].pct_change().dropna()
# 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()
bla = np.vstack([benchmark, np.ones(len(returns))]).T
# Simple linear regression function in Numpy
result = np.linalg.lstsq(bla , returns)
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]</pre>
</div>
<h3>Step 4: Rebalance Function:</h3>
<p>
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 <a href="https://www.quantconnect.com/docs/algorithm-reference/trading-and-orders#Trading-and-Orders-Liquidating-Portfolio">Liquidate</a> and go 100% long for both of the selected symbols using <a href="https://www.quantconnect.com/docs/algorithm-reference/trading-and-orders#Trading-and-Orders-Automatic-Position-Sizing-SetHoldings">SetHoldings</a>.
</p>
<div class="section-example-container">
<pre class="python">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._select_symbols(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)
# Invest 100% in the selected symbols
for symbol in symbols:
self.set_holdings(symbol, 1)</pre>
</div>