# 加载中...

faruto
• 博客等级：
• 博客积分：0
• 博客访问：1,144,854
• 关注人气：2,115
• 获赠金笔：0支
• 赠出金笔：0支
• 荣誉徽章：

## 一种简化的截面动量组合测试[Python&MATLAB]

(2015-03-09 23:32:04)

### 股票

1）主要用到numpypandasmatplotlib等几个包

```
```# -*- coding: utf-8 -*-
"""
SimpleMomentumPortfolioTest
Created on 2015/05/01
@author: LiYang(faruto)
@group : FQuantStudio
@contact: farutoliyang@foxmail.com
"""

#%% import
import numpy as np
import pandas as pd
import pandas.io.data as web
import matplotlib.pylab as plt

from pandas import Series,DataFrame
from collections import defaultdict```
```

2）数据的获取基于pandas

```
```#%% GetData

names = ['AAPL', 'GOOGL', 'MSFT', 'IBM', 'GS', 'MS', 'BAC', 'C']

def get_px(stock, start, end):

px = DataFrame({n: get_px(n, '1/1/2005', '1/1/2015') for n in names})

px.plot()```
```

3）数据的时间轴对齐以及缺失数据填充

```
```#%% plot

rets = px.pct_change()

retcum = (1+rets).cumprod()-1
retcum.plot()```
```

4）子函数编写：特定回顾期的动量计算并作标准化

```
```#%% calc_mom

def calc_mom(price, lookback, lag):
mom_ret = price.shift(lag).pct_change(lookback)
ranks = mom_ret.rank(axis=1, ascending=False)
demeaned = ranks.subtract(ranks.mean(axis=1), axis=0)
return demeaned.divide(demeaned.std(axis=1), axis=0)```
```

5）子函数编写：给定回顾期和持有期，组合的夏普比例计算

```
```#%% strat_sr

compound = lambda x : (1 + x).prod() - 1
daily_sr = lambda x: x.mean() / x.std()

def strat_sr(prices, lb, hold):
# Compute portfolio weights
freq = '�' % hold
port = calc_mom(prices, lb, lag=1)

daily_rets = prices.pct_change()

# Compute portfolio returns
port = port.shift(1).resample(freq, how='first')
returns = daily_rets.resample(freq, how=compound)
port_rets = (port * returns).sum(axis=1)

return daily_sr(port_rets) * np.sqrt(252 / hold)

strat_sr(px, 70, 30)```
```

6）计算不同回顾期和持有期下组合的夏普比例值

```
```#%% calc with diff lookbacks and holdings

lookbacks = range(20, 90, 5)
holdings = range(20, 90, 5)
dd = defaultdict(dict)
for lb in lookbacks:
for hold in holdings:
dd[lb][hold] = strat_sr(px, lb, hold)

ddf = DataFrame(dd)
ddf.index.name = 'Holding Period'
ddf.columns.name = 'Lookback Period'```
```

7）进行策略参数分布图形展示

```
```#%% heatmap

def heatmap(df, cmap=plt.cm.gray_r):
fig = plt.figure()
axim = ax.imshow(df.values, cmap=cmap, interpolation='nearest')
ax.set_xlabel(df.columns.name)
ax.set_xticks(np.arange(len(df.columns)))
ax.set_xticklabels(list(df.columns))
ax.set_ylabel(df.index.name)
ax.set_yticks(np.arange(len(df.index)))
ax.set_yticklabels(list(df.index))
plt.colorbar(axim)

heatmap(ddf)```
```

1）函数说明

```
```function SimpleMomentumPortfolioTest
% by LiYang_faruto
% Email:farutoliyang@foxmail.com
% 2015/01/01
%% A Little Clean Work
% clear;
% clc;
% close all;
format compact;```
```

2）数据的获取基于FQuantToolBox

```
```%% GetDataFromWeb
tic;
StockCodeCell = {'600588sh','sh600030','600446','300024sz','sz000001','600570sh'};
StockNameCell = {'用友网络','中信证券','金证股份','机器人','平安银行','恒生电子'};

BeginDate = '20100101';
EndDate = '20150101';
Len = length(StockCodeCell);
StockDataCell = cell(length(StockCodeCell),1);
for i = 1:length(StockCodeCell)
StockCode = StockCodeCell{i};
[StockDataCell{i}] = GetStockTSDay_Web(StockCode,BeginDate,EndDate);
end

toc;
%% 前复权数据生成
StockDataCellXRD = StockDataCell;
for i = 1:Len
StockData = StockDataCell{i};
end```
```

3）数据的时间轴对齐以及缺失数据填充

```
```tic;
sdate = datenum(BeginDate,'yyyymmdd');
edate = datenum(EndDate,'yyyymmdd');
bdates = busdays(sdate, edate, 'Daily');
Bdates = str2num( datestr(bdates,'yyyymmdd') );

StockDataCell_pre = StockDataCell;
for i = 1:Len
tMat = zeros(length(Bdates),8);
tMat(:,1) = Bdates;

tMat_pre = StockDataCell{i};
for j = 1:length(Bdates)
tD = Bdates(j);
ind = find(tMat_pre(:,1)<=tD, 1,'last');
tMat(j,2:end) = tMat_pre(ind,2:end);
end

StockDataCell{i} = tMat;
end
toc;
%% 每只股票累计收益
StockMat = zeros(length(Bdates), Len+1);
StockMat(:,1) = Bdates;
for i = 1:Len
StockMat(:,i+1) = StockDataCell{i}(:,5);
end

Ret = tick2ret(StockMat(:,2:end));
CumRet = cumprod((1+Ret))-1;

scrsz = get(0,'ScreenSize');
figure('Position',[scrsz(3)*1/4 scrsz(4)*1/6 scrsz(3)*4/5 scrsz(4)]*3/4);
plot(CumRet,'LineWidth',1.5);
xlim([0,length(Bdates)+1]);
Dates = StockMat(2:end,1);
LabelSet(gca, Dates, [], [], 1);

M = StockNameCell;
H = legend(M);
H.Orientation = 'horizontal';
H.FontWeight = 'Bold';
H.FontSize = 12;
H.Location = 'northoutside';

str = '股票累计收益';
H = title(str);
H.FontWeight = 'Bold';
H.FontSize = 15;```
```

4）子函数编写：特定回顾期的动量计算并作标准化

```
```%% sub fun calc_mom
% ---------------------------------------------------
%  calc_mom
% ---------------------------------------------------
function weight = calc_mom(price,lookback)
weight = zeros(size(price));
weight(:,1) = price(:,1);
[m,n] = size(price);
% weight(1:lookback,2:end) = nan;
weight(1:lookback,2:end) = 0;
for j = lookback+1:m
for i = 2:n
tData = price(:,i);
weight(j,i) =  (tData(j-1)-tData(j-lookback))/tData(j-lookback);
end

temp = weight(j,2:end);
weight(j,2:end) = (temp-mean(temp))./std(temp);
end

weight(isnan(weight)) = 0;
end    ```
```

5）子函数编写：给定回顾期和持有期，组合的夏普比例计算

```
```%% sub fun strat_sr
% ---------------------------------------------------
%  strat_sr
% ---------------------------------------------------
function SR = strat_sr(prices, lb, hold)
SR = 0;
[m,n] = size(prices);
% 计算权重
port = calc_mom(prices,lb);
port(isnan(port)) = 0;

% 计算组合收益
PortResample = [];
Returns = [];
Ind = 1;
for i = hold:hold:m
PortResample(Ind,:) = port(i-hold+1,:);
Returns(Ind,:) = prices(i,:);
Returns(Ind,2:end) = (prices(i,2:end)-prices(i-hold+1,2:end))./prices(i-hold+1,2:end);

Ind = Ind + 1;
end
port_rets = PortResample(:,2:end).*Returns(:,2:end);
port_rets = sum(port_rets,2);
% 计算年化Sharpe Ratio
SR = mean(port_rets)/std(port_rets)*sqrt( 252/hold );

end```
```

6）计算不同回顾期和持有期下组合的夏普比例值

```
```%% calc
tic;
lookbacks = 20:5:90;
holdings = 20:5:100;

DD = zeros(length(lookbacks), length(holdings));

for i = 1:length(lookbacks)
for j = 1:length(holdings)
lb = lookbacks(i);
hold = holdings(j);
DD(i,j) = strat_sr(StockMat, lb, hold);
end
end
toc;```
```

7）进行策略参数分布图形展示

```
```%% HeatPlot
temp = num2cell(lookbacks);
temp = cellfun(@num2str,temp,'UniformOutput',false);
YVarNames = temp;

temp = num2cell(holdings);
temp = cellfun(@num2str,temp,'UniformOutput',false);
XVarNames = temp;

XLabelString = 'Holding Period';
YLabelString = 'Lookack Period';
Fmatrixplot(DD,'ColorBar','On','XVarNames',XVarNames,'YVarNames',YVarNames,...
'XLabelString',XLabelString,'YLabelString',YLabelString);```
```

MATLAB下，虽然此例的实现测试稍显臃肿，但也不是非常复杂。在MATLAB下免费的A股数据可以通过FQuantToolBox（作者faruto）获取，FQuantToolBox下载地址：

0

• 评论加载中，请稍候...

发评论

以上网友发言只代表其个人观点，不代表新浪网的观点或立场。

新浪BLOG意见反馈留言板　电话：4000520066 提示音后按1键（按当地市话标准计费）　欢迎批评指正

新浪公司 版权所有