前言
前几天在翻查书籍的时候看到了书上介绍用42日与252日的移动平均线(Moving Average)的穿插作为交易信号并设置了最低阀值(意思是就算出现了交易信息,但移动值必须大于或小于最低阀值才会交易),我看了看觉得蛮有趣的,于是乎将其结合Tushare应用到国内的A股股票中。
免费注册Tushare.pro账号
首先,我们需要从tushare.pro注册一个账号并调用其API获取股票日线数据。可能大多数的童稚是第一次接触tushare.pro, 那我就直接贴上官方介绍:
Tushare是一个免费提供各类金融数据和区块链数据 , 助力智能投资与创新型投资的python财经数据接口包。拥有丰富的数据内容,如股票、基金、期货、数字货币等行情数据,公司财务、基金经理等基本面数据。
过程
1 | import tushare as ts |
通过调用tushare获取股票600377(宁沪高速)的股票数据,这里不设置日期,那么默认获取Tushare提供的历史数据。
1 | ticker_data = pro.daily(ts_code='600377.SH') |
输出:
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 4000 entries, 0 to 3999
Data columns (total 11 columns):
ts_code 4000 non-null object
trade_date 4000 non-null object
open 4000 non-null float64
high 4000 non-null float64
low 4000 non-null float64
close 4000 non-null float64
pre_close 4000 non-null float64
change 4000 non-null float64
pct_chg 4000 non-null float64
vol 4000 non-null float64
amount 4000 non-null float64
dtypes: float64(9), object(2)
memory usage: 343.8+ KB
从上面可以看出,序号并不是以时间作为单位的。那么我们首先需要将trade_date转为datetime格式,然后设置为序号以便于画图。
1 | ticker_data['trade_date'] = pd.to_datetime(ticker_data['trade_date'],format='%Y%m%d') |
输出,下图为收盘价的日线图:
然后我们再计算出42日和252日的移动平均线:
1 | ticker_data['42d'] = np.round(ticker_data['close'].rolling(window=42).mean(),2) |
输出:
- | close | 42d | 252d |
---|---|---|---|
trade_date | |||
2019-01-28 | 9.80 | 9.70 | 9.37 |
2019-01-29 | 9.98 | 9.71 | 9.37 |
2019-01-30 | 9.86 | 9.72 | 9.37 |
2019-01-31 | 9.85 | 9.73 | 9.37 |
2019-02-01 | 9.89 | 9.74 | 9.37 |
1 | ticker_data[['close','42d','252d']].plot(grid=True, figsize=(15, 5)) |
输出:
1 | ticker_data['42-252'] = ticker_data['42d'] - ticker_data['252d'] |
输出:
trade_date
2019-01-28 0.33
2019-01-29 0.34
2019-01-30 0.35
2019-01-31 0.36
2019-02-01 0.37
Name: 42-252, dtype: float64
1 | ticker_data['42-252'].head() |
输出:
trade_date
2002-05-08 NaN
2002-05-09 NaN
2002-05-10 NaN
2002-05-13 NaN
2002-05-14 NaN
Name: 42-252, dtype: float64
这里我们设置阀值为1, 你可以设置为其他阀值作测试。
1 | SD = 1 |
输出:
0 3012
-1 640
1 348
Name: Regime, dtype: int64
这说明了买入的股票的持续天数为348日,卖出为640日, 空仓天数为3012日。
1 | ticker_data['Regime'].plot(lw=1.5,figsize=(15, 5)) |
输出:
1 | ticker_data['Market'] = np.log(ticker_data['close'] / ticker_data['close'].shift(1)) |
1 | ticker_data['Strategy'] = ticker_data['Regime'].shift(1) * ticker_data['Market'] |
1 | ticker_data[['Market', 'Strategy']].cumsum().apply(np.exp).plot(grid=True,figsize=(15, 5)) |
输出:
结论
从上面的图可以看出,基本上都是以空仓为主,交易次数不算多,但足以跑赢买入持有策略(buy and hold)
。 但需要注意的是,这样的交易策略和交易次数是与我上面设置的阀值为1有关,这个值比较随意,导致不同的阀值有不同的结果。