# 均线策略和新高策略【被diss版】

320人阅读 评论(0)

## 基本策略

### 1 均线策略

1) 策略

2) 收益率回测

#### 1.2 Valeriy Zakamulin, Market timing with moving averages,2017

1) 移动平均的几种类型

I 基本类

i. 简单移动平均 Simple Moving Average(SMA)

ii. 线性移动平均 Linear Moving Average(LMA)

iii. 指数移动平均 Exponential Moving Average(EMA)

II 进阶：平均中的平均 Moving Averages of Moving Averages

i. 三角移动平均 Triangular Moving Average

ii.双／三指数平滑 Double and Triple Exponential Smoothing

III 混合移动平均 Double Exponential Moving Average (DEMA), by Mulloy (1994a)

2) 均线策略

i. 动量法则 Momentum Rule

ii.均线策略 Moving Average Change of Direction Rule

iii. Price Minus Moving Average Rule

iv. 均线交叉 Moving Average Crossover Rule (MAC)

v.多均线策略

vi.均线收敛／发散规则 Moving Average Convergence/Divergence Rule

### 2 新高策略

#### George, Hwang, The 52-Week High Momentum Investing, The Journal of Finance,Vol Lix No.5,Oct. 2004

1）指标构建

2）策略构建

3）收益率回测

• Ming Liu and Qianqiu Liu (2009),The 52-Week High Momentum Strategy in International Stock Markets
• Alsubaie and Najand (2008),Trading volume, Price Momentum,and the 52-Week High Momentum Strategy in the Saudi Stock Market

## 正文

### 1 均线策略

#### 1.1 C.J.Neely, P.A.Weller, Technical analysis in the foreign exchange market, Working Paper, Federal Reserve of St.Louis,2011.

An MA rule compares a short and a long moving average of past prices and generates a buy (sell) signal if the short moving average intersects the long moving average from below (above). For example, one widely used rule, which we write as MA(5, 20), compares a 5-day and a 20-day moving average.

1) 策略

import pandas as pd
import numpy as np
import math

## 均线构建 (参数n为均线构建期间)
def MA(n):
df['MA'+str(n)] = pd.rolling_mean(df['close'], n)

MA(5)  # 5日均线
MA(20) # 20日均线

## 多空信号
lst_signal=[]
df['signal']=df['MA5']-df['MA20']
for i in df['signal']:
if i>0:
lst_signal.append(1)   # 多头信号
else:
lst_signal.append(0)   # 空头信号

df['signal']=lst_signal



2）收益率回测

# 构建指标z
lst_z=[]
for j in df['signal']:
if i=1:
lst_z.append(1)   # 多头信号
else:
lst_z.append(-1)   # 空头信号

df['z']=lst_z

# 构建指标R
s_t1=pd.Series(df['close'].values).shift(1)
df['s_t1']=list(s_t1)   # 超前变量的设置，用shift函数
df['R_t1']=df['s_t1']/df['close']*df['i_']/df['i']
df['log_s_t1']=[math.log(i) for i in df['s_t1']]
df['log_s']=[math.log(j) for j in df['close']]
df['log_i_']=[math.log(i+1) for i in df['i_']]
df['log_i']=[math.log(j+1) for j in df['i']]
df['r_t1']=df['log_s_t1']-df['log_s']+df['log_i_']-df['log_i']
r=sum(df['z']*df['r+1'])+ math.log((1-c)/(1+c))    # r为交易期间使用策略获得的累计超额收益


#### 1.2 Valeriy Zakamulin, Market timing with moving averages,2017

1) 移动平均的几种类型

I 基本类

i. 简单移动平均 Simple Moving Average(SMA)

# 简单移动平均 SMA
def SMA(n):
df['SMA'+str(n)] = pd.rolling_mean(df['close'], n)
print(df.head())

ii. 线性移动平均 Linear Moving Average(LMA)

# 线性移动平均 LMA
def LMA(n):
LMA=0
for i in range(5):
p=pd.Series(df['close'].values).shift(i)
LMA=(5-i)*p+LMA
df['LMA'+str(5)]=list(LMA*2/(1+5)/5)

LMA(n)
df.head(10)

iii. 指数移动平均 Exponential Moving Average(EMA)

# 指数移动平均 EMA
def EMA(n):
df['EMA'+str(n)] = pd.ewma(df['close'], n)
print(df.head())

II 进阶：平均中的平均 Moving Averages of Moving Averages

i. 三角移动平均 Triangular Moving Average

# 三角移动平均
def TMA(n):
df['TMA'+str(n)] = pd.rolling_mean(df['SMA'+str(n)], n)
print(df.head())

ii.双／三指数平滑 Double and Triple Exponential Smoothing

# 双指数平均dEMA
def dEMA(n):
df['dEMA'+str(n)] = pd.ewma(df['EMA'+str(n)], n)

# 三指数平均tEMA
def tEMA(n):
df['tEMA'+str(n)] = pd.ewma(df['dEMA'+str(n)], n)
print(df.head())    

III 混合移动平均
Double Exponential Moving Average (DEMA), by Mulloy (1994a)

Triple Exponential Moving Average (TEMA), by Mulloy (1994b)

# DEMA
def DEMA(n):
df['DEMA'+str(n)] = 2*df['EMA'+str(n)] - df['dEMA'+str(n)]

# TEMA
def TEMA(n):
df['TEMA'+str(n)] = 3*df['EMA'+str(n)] - 3*df['dEMA'+str(n)]+df['tEMA'+str(n)]
print(df.head())

2) 均线策略

step1:At the first step, the value of a technical trading indicator is computed using the past prices including the last closing price

step2:At the second step, the value of the technical indicator is translated into a trading signal.

i. 动量法则 Momentum Rule

# 动量指标的构建
def MOM(n):
close_lag=pd.Series(df['close'].values).shift(1-n) #滞后n-1期
df['close_lag']=list(close_lag)
df['MOM'+str(n)] = df['close'] - df['close_lag']


ii.均线策略 Moving Average Change of Direction Rule

# MACD指标的构建
def MACD(n):
MA_lag=pd.Series(df['SMA'+str(n)].values).shift(-1) #滞后1期
df['MA_lag'+str(n)]=list(MA_lag)
df['MACD'+str(n)] = df['SMA'+str(n)]-df['MA_lag'+str(n)]
print(df.head())

iii. Price Minus Moving Average Rule

# PMA指标的构建 & 与交易信号
def PMA(n):
df['PMA'+str(n)] = df['close']-df['SMA'+str(n)]
signal_lst=[]
for i in df['PMA'+str(n)]:
if i>0:
signal_lst.append(1)
else:
signal_lst.append(0)
df['signal_PMA']=signal_lst # signal变量为1则表示多头信号，signal为零则是空头信号


iv. 均线交叉 Moving Average Crossover Rule (MAC)

# MAC指标的构建 & 与交易信号
def MAC(n,m):
df['MAC'+str(n)+'_'+str(m)] = df['MAC'+str(n)]-df['MAC'+str(m)]  # 参数n小于参数m
signal_lst=[]
for i in df['MAC'+str(n)+'_'+str(m)]:
if i>0:
signal_lst.append(1)
else:
signal_lst.append(0)
df['signal_MAC']=signal_lst # signal变量为1则表示多头信号，signal为零则是空头信号
print(df.head())

v.多均线策略

• When all moving averages are moving in the same direction (that is, parallel), the trend is said to be strong because all of them are largely in agreement.

• When moving averages in a ribbon start to converge or diverge, a trend change has already begun to occur.

• When all moving averages converge and fluctuate more than usual, the price moves sideways.

vi.均线收敛／发散规则 Moving Average Convergence/Divergence Rule

A Buy (Sell) signal is gernerated when MAC increases (decreases).

def delta_MAC(n,m):
MAC_lag=pd.Series(df['MAC'+str(n)+'_'+str(m)].values).shift(-1) #滞后1期
df['MAC_lag'+str(n)+'_'+str(m)]=list(MAC_lag)
df['deltaMAC'+str(n)+'_'+str(m)] = df['MAC'+str(n)+'_'+str(m)]-  df['MAC_lag'+str(n)+'_'+str(m)] # 参数n小于参数m
signal_lst=[]
for i in df['deltaMAC'+str(n)+'_'+str(m)]:
if i>0:
signal_lst.append(1)
else:
signal_lst.append(0)
df['signal_deltaMAC']=signal_lst # signal变量为1则表示多头信号，signal为零则是空头信号
print(df.head())

### 2 新高策略

#### George, Hwang, The 52-Week High Momentum Investing, The Journal of Finance,Vol Lix No.5,Oct. 2004

• 基于52周新高的动量策略，比起传统的动量，能帮助投资者获得更大的收益
• 新高之后并不一定出现长期反转，两者间相互独立

• Ming Liu and Qianqiu Liu (2009),The 52-Week High Momentum Strategy in International Stock Markets
• Alsubaie and Najand (2008),Trading volume, Price Momentum,and the 52-Week High Momentum Strategy in the Saudi Stock Market
#设：现在有一张DataFrame,索引是时间（年/月），列变量是A股所有股票的代码，
#行记录是回测期间的个股月收益率。
#(下面用随机数生成了每月股价，目的是方便写代码)

### 创建raw data（随机模拟了100只票，在2012.1.1至2017.1.1期间5年的月价格）

import pandas as pd
import random

# 创建列变量:股票代码
lst_col=[]
j=0
for i in range(100):
j=j+1
s=str(j)
k=s.zfill(6) #仿照股票代码，向左填充0至6位
lst_col.append(k)

# 创建行记录：个股月价格（利用随机数填充）
lst1=[]
lst2=[]
for i in range(61):
for j in range(100):
lst1.append(random.randint(1, 100))
lst2.append(lst1)
lst1=[]

lst_record=lst2

# 生成日期索引（以月为间隔）
time=[]
for i in range(2012,2017):
s=str(i)
for m in range(1,13):
m_=str(m).zfill(2)
time.append(s+m_)
time.append('201701')

# 生成raw data的DataFrame
df = pd.DataFrame(lst_record,index=time,columns=lst_col)
df.tail(2)
.dataframe thead tr:only-child th { text-align: right; } .dataframe thead th { text-align: left; } .dataframe tbody tr th { vertical-align: top; }
000001 000002 000003 000004 000005 000006 000007 000008 000009 000010 000091 000092 000093 000094 000095 000096 000097 000098 000099 000100
201612 71 26 36 32 100 14 42 34 54 82 71 61 90 66 43 72 43 45 9 69
201701 64 7 11 40 4 36 84 8 37 31 72 54 63 64 19 73 28 46 82 42

2 rows × 100 columns

1) 指标构建

P(i,t-1)/HIGH(i,t-1)

## 1）指标构建

# 生成前52周最大价格，新建保存在一张df中，命名为newdf
maxp=[] #这个列表储存过去52周（12个月）的最高价格
mp=[] #中转列表，无实际含义
for i in df3.columns[0:100]:
for j in df3['id'][12:61]: #前12个月没有足够的历史
l=j-13
r=j-1
mp.append(max(df3[str(i)][l:r].values))
maxp.append(mp)
mp=[]

newcol=[]
for i in lst_col:
newcol.append('max'+str(i))

t_maxp=list(map(list,zip(*maxp))) #将maxp矩阵转置，以适配df的生成
newdf=pd.DataFrame(t_maxp,index=time[12:61],columns=newcol)

# 横向合并表格
df_ind=df[12:61].join(newdf) # 把原始价格表df和含有指标的表newdf合并在一起，命名为df_ind

#生成指标
for i in lst_col:
df_ind['ind_'+str(i)]=df_ind[str(i)]/df_ind['max'+str(i)] #S生成比率指标

df_ind=df_ind.iloc[:,200:300]  #删除不需要的中间变量


.dataframe thead tr:only-child th { text-align: right; } .dataframe thead th { text-align: left; } .dataframe tbody tr th { vertical-align: top; }
ind_000001 ind_000002 ind_000003 ind_000004 ind_000005 ind_000006 ind_000007 ind_000008 ind_000009 ind_000010 ind_000091 ind_000092 ind_000093 ind_000094 ind_000095 ind_000096 ind_000097 ind_000098 ind_000099 ind_000100
201301 0.626506 0.894737 0.744186 1.044444 0.83 0.510204 0.868421 0.717172 0.369565 0.21 0.474747 0.600000 1.129870 0.257732 0.520833 1.034884 0.365591 0.784946 0.204301 0.302083
201302 0.458333 0.463158 0.043011 0.755556 0.48 0.908163 0.631579 0.646465 0.913043 0.53 0.858586 0.642105 0.545455 0.288660 0.406250 0.802326 0.763441 0.129032 0.763441 0.364583

2 rows × 100 columns

2) 策略构建：

• winner和loser portfolio的识别：

Winner portfolio：ratio排名在top 30%

Loser portfolio：ratio排名在bottom 30%

• 策略：买入winner组合里的股票，卖出loser组合里的股票，持有6个月
## 2）策略构建——构建winner和loser的股票池

# winner股票池（也即投资者按该策略每月应买入的股票组合）
winner=[]
for i in time[12:61]:
winner.append(list(df_ind.T.sort_values(str(i)).T.columns)[0:30]) #按行观测值排序

l=[] #l列表是一个中转列表，没有什么实际意义
winner_port=[]
for i in winner:
for j in i:
l.append(str(j)[4:10]) #去掉前面的“ind_”字符
winner_port.append(l) #将所有的top30收益的winner portfolios股票代码保存在winner_port的二维矩阵中
l=[]

# loser股票池
loser=[]
for i in time[12:61]:
loser.append(list(df_ind.T.sort_values(str(i),ascending=False).T.columns)[0:30]) #按行观测值排序

l=[] #l列表是一个中转列表，没有什么实际意义
loser_port=[]
for i in loser:
for j in i:
l.append(str(j)[4:10]) #去掉前面的“ind_”字符
loser_port.append(l) #将所有bottom30收益的loser portfolios股票代码保存在loser_port的二维矩阵中
l=[]
3) 收益回测： 回测期：38年半 1963年7月-2001年12月(在这里中我只用了5年的模拟数据) 每个月投资者都买入一个winner股票池，其收益率的计算是基于前6个月的回报水平，回报水平用简单算术平均来测算
## 3）收益回测

# 用随机数模拟每月收益变量，如：r_000001
lst3=[]
for i in lst_col:
for j in range(49):
lst3.append(random.randint(-100, 100)/100) #用随机数模拟收益率
df_ind['r_'+str(i)]=lst3
lst3=[]

# 创建持有期（6个月）的收益变量（向前移动平均）
re=[]
rr=[]
df_ind['id']=range(1,50)
for i in lst_col:
for j in df_ind['id'][0:43]: #最后6个月的收益无法计算
l=j+5
rr.append(sum(df_ind['r_'+str(i)][j:l].values)/6 )
re.append(rr)
rr=[]

newcol2=[]
for i in lst_col:
newcol2.append('avgr'+str(i))

t_re=list(map(list,zip(*re))) #将re矩阵转置，以适配df的生成
newdf2=pd.DataFrame(t_re,index=time[12:55],columns=newcol2)
newdf2.tail()

# 横向合并表格
dfr=df_ind[0:43].join(newdf2) # 把原始价格表df和含有指标的表newdf合并在一起，命名为df_ind
df_ind=dfr

df_ind['id']=range(1,44) #生成一个id变量，方便下面写循环

mid=[] #中间列表，无实际用处
ret=[] #收益率列表
int_winner_code=[]  # 将winner组合的股票代码以整数形式保存在列表int_winner_code中

for i in winner_port: #将winner_port这个二维列表转化为一维（实际处理时，可考虑补全所有代码，再删除匹配不到的缺失值）
for j in i:
int_winner_code.append(int(j))

# 获得策略的收益结果，保存在list中
for k in df_ind['id']:
lpara=(k-1)*30
rpara=k*30
for m in int_winner_code[lpara:rpara]: #由于每次购买的组合数均为30个，故可以直接按数字索引，以实现list和dataframe的匹配
u=k-1
n=m-1
mid.append(float(df_ind.iloc[u:k,n:m].values)) #每一次append一个数值，行坐标由id变量值决定，
#列坐标由代码值->列表中数值->数值又和df中的列向量匹配
ret.append(mid)  # ret为一个二维列表，外层有49个元素，代表日期月份，内层有30个元素，代表股票数
mid=[]

# 将结果整理到DataFrame中呈现出来
lst_col2=[]
for i in range(30):
lst_col2.append('stock'+str(i+1))

strategy_return = pd.DataFrame(ret,index=time[12:55],columns=lst_col2)

.dataframe thead tr:only-child th { text-align: right; } .dataframe thead th { text-align: left; } .dataframe tbody tr th { vertical-align: top; }
stock1 stock2 stock3 stock4 stock5 stock6 stock7 stock8 stock9 stock10 stock21 stock22 stock23 stock24 stock25 stock26 stock27 stock28 stock29 stock30
201301 0.041667 0.047619 0.050000 0.080808 0.109890 0.111111 0.112245 0.120000 0.142857 0.150000 0.275510 0.276316 0.279570 0.302083 0.312500 0.322581 0.325581 0.325843 0.330000 0.340426
201302 0.040816 0.042553 0.043011 0.070588 0.080000 0.084211 0.100000 0.105263 0.129032 0.134021 0.238636 0.240000 0.242424 0.255814 0.257143 0.269663 0.270000 0.288660 0.290000 0.291667
201303 0.013158 0.021053 0.021277 0.030000 0.053763 0.072917 0.090000 0.091837 0.105263 0.106383 0.193878 0.200000 0.210526 0.220000 0.242105 0.247423 0.250000 0.252525 0.261364 0.266667
201304 0.032258 0.046512 0.051020 0.056818 0.058824 0.060000 0.080808 0.090000 0.120000 0.120000 0.242105 0.242424 0.268041 0.276596 0.285714 0.285714 0.297872 0.298969 0.300000 0.301075
201305 0.030612 0.040000 0.041237 0.051020 0.055556 0.070000 0.072917 0.082474 0.142857 0.155556 0.244898 0.256410 0.260000 0.279570 0.290000 0.292929 0.329787 0.340000 0.354167 0.360465

5 rows × 30 columns

个人资料
等级：
访问量： 8591
积分： 486
排名： 10万+