From 2bca78eb916d5c4d958f0da25ef2a86c77c84c16 Mon Sep 17 00:00:00 2001 From: Derek Melchin <38889814+DerekMelchin@users.noreply.github.com> Date: Tue, 16 Apr 2024 11:16:03 -0600 Subject: [PATCH 1/2] Update strategy library tutorial #01 --- .../03 Method.html | 54 +++++++++---------- .../05 Algorithm.html | 2 +- .../05 \347\256\227\346\263\225.cn.html" | 2 +- 3 files changed, 29 insertions(+), 29 deletions(-) diff --git a/04 Strategy Library/01 CAPM Alpha Ranking Strategy on Dow 30 Companies/03 Method.html b/04 Strategy Library/01 CAPM Alpha Ranking Strategy on Dow 30 Companies/03 Method.html index ffff064..26848dc 100755 --- a/04 Strategy Library/01 CAPM Alpha Ranking Strategy on Dow 30 Companies/03 Method.html +++ b/04 Strategy Library/01 CAPM Alpha Ranking Strategy on Dow 30 Companies/03 Method.html @@ -15,10 +15,10 @@

Step 1: Setup Event Handler

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.symbols[0]),
-                     self.TimeRules.AfterMarketOpen(self.symbols[0]),
-                     self.Rebalance)
+
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)

Step 2: History Function

@@ -26,33 +26,33 @@

Step 2: History Function

# Fetch the historical data to perform the linear regression
-history = self.History(
-    self.symbols + [self.benchmark], 
-    self.lookback,
-    Resolution.Daily).close.unstack(level=0)
+history = self.history( + self._symbols + [self._benchmark], + self._lookback, + Resolution.DAILY).close.unstack(level=0)

Step 3: Symbol Selection Function

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):
+
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()
+    benchmark = history[self._benchmark].pct_change().dropna()
 
     # Conducts linear regression for each symbol and save the intercept/alpha
-    for symbol in self.symbols:
-
+    for symbol in self._symbols:
+        
         # Get the security returns
         returns = history[symbol].pct_change().dropna()
-        returns = np.vstack([returns, np.ones(len(returns))]).T
+        bla = np.vstack([benchmark, np.ones(len(returns))]).T
 
         # Simple linear regression function in Numpy
-        result = np.linalg.lstsq(returns, benchmark)
+        result = np.linalg.lstsq(bla , returns)
         alphas[symbol] = result[0][1]
 
     # Select symbols with the highest intercept/alpha to the benchmark
@@ -64,23 +64,23 @@ 

Step 4: Rebalance Function:

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):
+
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)
+    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)
+    for holdings in self.portfolio.values():
+        symbol = holdings.symbol
+        if symbol not in symbols and holdings.invested:
+            self.liquidate(symbol)
 
-    # Invest 100% in the each of the selected symbols
+    # Invest 100% in the selected symbols
     for symbol in symbols:
-        self.SetHoldings(symbol, 1)
+ self.set_holdings(symbol, 1)
\ 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 645e3da..44979ab 100755 --- a/04 Strategy Library/01 CAPM Alpha Ranking Strategy on Dow 30 Companies/05 Algorithm.html +++ b/04 Strategy Library/01 CAPM Alpha Ranking Strategy on Dow 30 Companies/05 Algorithm.html @@ -1,6 +1,6 @@
- +
\ No newline at end of file diff --git "a/04 Strategy Library/01 CAPM Alpha Ranking Strategy on Dow 30 Companies/05 \347\256\227\346\263\225.cn.html" "b/04 Strategy Library/01 CAPM Alpha Ranking Strategy on Dow 30 Companies/05 \347\256\227\346\263\225.cn.html" index 4a79e84..815b9a5 100644 --- "a/04 Strategy Library/01 CAPM Alpha Ranking Strategy on Dow 30 Companies/05 \347\256\227\346\263\225.cn.html" +++ "b/04 Strategy Library/01 CAPM Alpha Ranking Strategy on Dow 30 Companies/05 \347\256\227\346\263\225.cn.html" @@ -4,6 +4,6 @@
- +
From db1f4cb41a547b58f1da9649508ce52ae94f10ac Mon Sep 17 00:00:00 2001 From: Derek Melchin <38889814+DerekMelchin@users.noreply.github.com> Date: Tue, 16 Apr 2024 11:17:55 -0600 Subject: [PATCH 2/2] Remove chinese version --- .../01 \347\256\200\344\273\213.cn.html" | 14 --- ...7\274\211\347\220\206\350\256\272.cn.html" | 44 --------- .../03 \346\226\271\346\263\225.cn.html" | 95 ------------------- .../04 \346\200\273\347\273\223.cn.html" | 14 --- .../05 \347\256\227\346\263\225.cn.html" | 9 -- ...0\200\203\346\226\207\347\214\256.cn.html" | 8 -- 6 files changed, 184 deletions(-) delete mode 100644 "04 Strategy Library/01 CAPM Alpha Ranking Strategy on Dow 30 Companies/01 \347\256\200\344\273\213.cn.html" delete mode 100644 "04 Strategy Library/01 CAPM Alpha Ranking Strategy on Dow 30 Companies/02 \350\265\204\346\234\254\350\265\204\344\272\247\345\256\232\344\273\267\346\250\241\345\236\213\357\274\210CAPM\357\274\211\347\220\206\350\256\272.cn.html" delete mode 100644 "04 Strategy Library/01 CAPM Alpha Ranking Strategy on Dow 30 Companies/03 \346\226\271\346\263\225.cn.html" delete mode 100644 "04 Strategy Library/01 CAPM Alpha Ranking Strategy on Dow 30 Companies/04 \346\200\273\347\273\223.cn.html" delete mode 100644 "04 Strategy Library/01 CAPM Alpha Ranking Strategy on Dow 30 Companies/05 \347\256\227\346\263\225.cn.html" delete mode 100644 "04 Strategy Library/01 CAPM Alpha Ranking Strategy on Dow 30 Companies/06 \345\217\202\350\200\203\346\226\207\347\214\256.cn.html" diff --git "a/04 Strategy Library/01 CAPM Alpha Ranking Strategy on Dow 30 Companies/01 \347\256\200\344\273\213.cn.html" "b/04 Strategy Library/01 CAPM Alpha Ranking Strategy on Dow 30 Companies/01 \347\256\200\344\273\213.cn.html" deleted file mode 100644 index 9ccb0d0..0000000 --- "a/04 Strategy Library/01 CAPM Alpha Ranking Strategy on Dow 30 Companies/01 \347\256\200\344\273\213.cn.html" +++ /dev/null @@ -1,14 +0,0 @@ -

- 本教程执行一个简单的线性回归来构建资本资产定价模型(CAPM),这是由William F. Sharpe和Harry Markowitz开发的一个经典模型。该模型对各资产都会产生alpha和beta值,并通过做多alpha值最高的股票进行交易。本教程将演示以下内容: -

- -
    -
  • 如何使用历史数据
  • -
  • 设置事件处理程序
  • -
  • 进行线性回归
  • -
  • 在QuantConnect算法实验室中构建自己的函数
  • -
- -

- 该策略的实施表明,在上个月跑赢大盘的股票很可能在接下来的一个月里再次跑赢大盘。该算法在市场平稳时性能良好。然而,当市场波动性增加时,模型未能捕捉到alpha值,且表现不佳。我们从中了解到,市场波动降低了线性回归系数的显著性水平,特别是当我们使用日收益率来拟合模型时。 -

diff --git "a/04 Strategy Library/01 CAPM Alpha Ranking Strategy on Dow 30 Companies/02 \350\265\204\346\234\254\350\265\204\344\272\247\345\256\232\344\273\267\346\250\241\345\236\213\357\274\210CAPM\357\274\211\347\220\206\350\256\272.cn.html" "b/04 Strategy Library/01 CAPM Alpha Ranking Strategy on Dow 30 Companies/02 \350\265\204\346\234\254\350\265\204\344\272\247\345\256\232\344\273\267\346\250\241\345\236\213\357\274\210CAPM\357\274\211\347\220\206\350\256\272.cn.html" deleted file mode 100644 index 7add139..0000000 --- "a/04 Strategy Library/01 CAPM Alpha Ranking Strategy on Dow 30 Companies/02 \350\265\204\346\234\254\350\265\204\344\272\247\345\256\232\344\273\267\346\250\241\345\236\213\357\274\210CAPM\357\274\211\347\220\206\350\256\272.cn.html" +++ /dev/null @@ -1,44 +0,0 @@ -

- 资本资产定价模型(CAPM)描述了系统性风险与资产(通常是股票)预期收益之间的关系。给定风险的资产预期收益计算公式如下: -

- -\[r_a = r_f + \beta_a*(r_m - r_f) + \epsilon \] - -

- 其中: -

- -\[r_f = Risk Free Rate\] -\[\beta = Beta of the security\] - -\[r_m = Expected market return\] - -\[\epsilon = Tracking error\] - -

- 将公式重构如下,可以更好地理解这个公式: -

- -\[(r_a - r_f ) = \beta_a*(r_m - r_f) + \epsilon \] - -

- 方程的左边给出了资产收益和无风险利率之间的差额,即"超额收益"。如果我们将市场超额收益资产超额收益进行对比,斜率代表资产的"beta"。因此,beta也可以通过公式计算: -

- -\[\beta = \frac{Cov(r_a,r_b)}{var(r_b)}\] - -

- 因此beta可以描述为: -

- -\[\beta = \rho _a,_b*\frac{\sigma _a}{\sigma_b}\] - -

- 由上式可知,beta可以解释为“关联相对波动”。为了更加简化,可以通过简单的线性回归来计算beta,线性回归可以看作是解释收僧的一个因素,跟踪误差可以表示alpha。为了使这个理论对我们的算法更加便利,我们将上面的公式改为如下形式: -

- -\[r_a = \beta*r_m + r_f*(1-\beta) + \epsilon\] - -

- 等式右边的r*(1-β) 是一个非常小的项目,在道琼斯前30强企业的背景下可以忽略不计。如果我们使用基准收益对股票收益进行回归,斜率和截距将分别为beta和alpha。 -

diff --git "a/04 Strategy Library/01 CAPM Alpha Ranking Strategy on Dow 30 Companies/03 \346\226\271\346\263\225.cn.html" "b/04 Strategy Library/01 CAPM Alpha Ranking Strategy on Dow 30 Companies/03 \346\226\271\346\263\225.cn.html" deleted file mode 100644 index b64df7a..0000000 --- "a/04 Strategy Library/01 CAPM Alpha Ranking Strategy on Dow 30 Companies/03 \346\226\271\346\263\225.cn.html" +++ /dev/null @@ -1,95 +0,0 @@ -

- 我们的投资逻辑简单明了。我们认为上个月跑赢大盘的股票将继续跑赢大盘。我们根据alpha值对股票进行排名,每个月我们都会对排名前两支的股票“做多”。要使这一战略发挥作用,我们需要在每月月初做下列工作: -

- -
    -
  • 计算道琼斯前30强股票在过去21个交易日的历史价格,并计算它们的日收益。
  • -
  • 根据基准(S&P 500指数,SPY)对每支股票的收益进行简单的线性回归。
  • -
  • 根据截距对股票进行排名。
  • -
  • 平掉所有仓位,并购买排序列表中的排名前两支股票。
  • -
-

- 道琼斯指数成份股很少变动,最近一次变动发生在2015年3月19日。为了使实施更加容易,我们在这个算法中简单地列出了当前的道琼期成份股。这意味着该算法最早的开始日期是2015年3月19日。 -

- -

步骤1:设置事件处理程序

-

- 在初始化方法中,我们定义了日程事件来触发投资组合的每月重新平衡。有关如何使用日程事件的更多细节,可以阅读Documentation或查看示例ScheduledEventsAlgorithm。 -

-
- -
def Initialize(self):
-    self.Schedule.On(self.DateRules.MonthStart(self.benchmark), self.TimeRules.AfterMarketOpen(self.benchmark), Action(self.rebalance))
-	
-
- -

步骤2:线性回归函数

-

- 为了进行线性回归,我们需要编写一个函数来获取价格数据并输出回归结果。函数获得“资产价格”列表(x)和一个“基准价格”列表(y),然后计算变化百分比并进行线性回归。输出是一个包含截距和斜率的元组。 -

- -
- -
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)
-
-
-

步骤3:历史功能

-

- 每个月我们都会使用History API获得道琼斯30强成份股的历史价格。数据作为复杂的Slice对象从API返回。为了使其在算法中可以使用,我们将资产价格和基准价格提取到一个列表中。 -

-
- -
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)
-
-    result = self.regression(symbol_price,benchmark_price)
-    return result
-
-
-

步骤4:再平衡功能

-

- 此功能是所有动作发生的地方,将作为预定事件在每个月的第一个交易日执行。SetHoldings的第二个参数是小数,将其设置为“1”表示算法将投资组合设置为“100%多头”而不使用杠杆。有关这一功能的更多信息可以在链接SetHoldings上阅读。 -

- -
- -
def rebalance(self):
-    # 获得历史股票代码和价格,然后放入元组中
-    history = self.History(self.regression_dates, Resolution.Daily)
-    filter = []
-    for i in self.symbols:
-        filter.append((i,self.get_regression_data(i, history)[0]))
-    # 根据alpha排序筛选
-    filter.sort(key = lambda x : x[1],reverse = True)
-    sorted_symbols = []
-    for i in range(2):
-    	sorted_symbols.append(filter[i][0])
-    # 获得所持有股票的代码
-    holding_list = []
-    for i in self.Portfolio:
-    	if i.Value.Invested:
-    		holding_list.append(i.Value.Symbol)
-    # 如果我们不打算继续持有现有的股份,则将其出售
-    if holding_list:
-    	for i in holding_list:
-    		if i not in sorted_symbols:
-    			self.Liquidate(i)
-    # 做多列表中的两支股票
-    for i in sorted_symbols:
-    	self.SetHoldings(i,1)
-		
diff --git "a/04 Strategy Library/01 CAPM Alpha Ranking Strategy on Dow 30 Companies/04 \346\200\273\347\273\223.cn.html" "b/04 Strategy Library/01 CAPM Alpha Ranking Strategy on Dow 30 Companies/04 \346\200\273\347\273\223.cn.html" deleted file mode 100644 index c68387d..0000000 --- "a/04 Strategy Library/01 CAPM Alpha Ranking Strategy on Dow 30 Companies/04 \346\200\273\347\273\223.cn.html" +++ /dev/null @@ -1,14 +0,0 @@ -

- 我们已经证明,在一个平稳的市场中,上个月跑赢大盘的股票很可能在接下来的一个月里再次跑赢大盘。当市场波动时,线性回归的显著性水平降低,模型性能下降。我们可以通过观察资产(x)和基准(y)的协方差来理解这一点。当协方差减小到零时,beta将会减小。 -

- -\[\hat{\beta} = \frac{Cov[x,y]}{\sum (x_i - \beta{x})^2}\] - -

- 作为实验,我们根据2015年的市场数据对算法进行了测试。对市场来说,这是一个极不稳定的时期,波动回到了接近于零的平均值,并在当年8月18日至8月25日期间下跌了近10%。该算法在今年的表现很差,收益率为-11.58%。与这一策略相关的风险包括大幅削减、缺乏对冲和止损。由于我们使用杠杆,风险增加了,因此在1月份有追加保证金的通知。我们可以通过应用以下技术来提高性能: -

- -
    -
  • 进行优化:我们可以实施均值方差分析来确定每月的资产配置,选择更多的股票进行交易。这将降低我们的风险,更科学地管理投资组合。
  • -
  • 考虑beta:如果我们想要更加积极,我们可以结合alpha和beta来选择目标。这意味着我们选择的股票具有比市场波动更大的高alpha值。然而,如果我们是保守的投资者,我们可以使策略保持市场中立,这意味着投资组合不会受到市场表现的影响。例如,如果我们做多两只beta值为1和-1的股票,并分别持有相同的头寸大小,那么我们的投资组合就会变得市场中性。
  • -
diff --git "a/04 Strategy Library/01 CAPM Alpha Ranking Strategy on Dow 30 Companies/05 \347\256\227\346\263\225.cn.html" "b/04 Strategy Library/01 CAPM Alpha Ranking Strategy on Dow 30 Companies/05 \347\256\227\346\263\225.cn.html" deleted file mode 100644 index 815b9a5..0000000 --- "a/04 Strategy Library/01 CAPM Alpha Ranking Strategy on Dow 30 Companies/05 \347\256\227\346\263\225.cn.html" +++ /dev/null @@ -1,9 +0,0 @@ -

- 使用OptionChainProvider进行回溯测试。 -

-
-
-
- -
-
diff --git "a/04 Strategy Library/01 CAPM Alpha Ranking Strategy on Dow 30 Companies/06 \345\217\202\350\200\203\346\226\207\347\214\256.cn.html" "b/04 Strategy Library/01 CAPM Alpha Ranking Strategy on Dow 30 Companies/06 \345\217\202\350\200\203\346\226\207\347\214\256.cn.html" deleted file mode 100644 index f6f75d0..0000000 --- "a/04 Strategy Library/01 CAPM Alpha Ranking Strategy on Dow 30 Companies/06 \345\217\202\350\200\203\346\226\207\347\214\256.cn.html" +++ /dev/null @@ -1,8 +0,0 @@ -
    -
  1. - https://en.wikipedia.org/wiki/Dow_Jones_Industrial_Average -
  2. -
  3. - Sharpe, William, 1990 http://www.nobelprize.org/nobel_prizes/economic-sciences/laureates/1990/sharpe-lecture.pdf -
  4. -