SMA — 移动平均及双均线模型
0. 引库
%matplotlib inline
import matplotlib.pyplot as plt
import seaborn
plt.style.use('seaborn')
import matplotlib as mpl
mpl.rcParams['font.family'] = 'serif'
import warnings; warnings.simplefilter('ignore')
import numpy as np
import pandas as pd
import tushare as ts
1. 前导知识备习
data = ts.get_k_data('600030', start = '2010-01-01', end='2017-06-30')
data.head()
| date | open | close | high | low | volume | code |
|---|
| 0 | 2010-01-04 | 17.016 | 16.639 | 17.176 | 16.612 | 1106207.58 | 600030 |
|---|
| 1 | 2010-01-05 | 16.777 | 17.452 | 17.601 | 16.383 | 2093915.41 | 600030 |
|---|
| 2 | 2010-01-06 | 17.548 | 17.250 | 17.628 | 17.229 | 1437889.30 | 600030 |
|---|
| 3 | 2010-01-07 | 17.239 | 16.830 | 17.484 | 16.697 | 1235592.34 | 600030 |
|---|
| 4 | 2010-01-08 | 16.718 | 17.154 | 17.208 | 16.644 | 1040929.92 | 600030 |
|---|
data.set_index('date', inplace = True)
data.head()
| open | close | high | low | volume | code |
|---|
| date | | | | | | |
|---|
| 2010-01-04 | 17.016 | 16.639 | 17.176 | 16.612 | 1106207.58 | 600030 |
|---|
| 2010-01-05 | 16.777 | 17.452 | 17.601 | 16.383 | 2093915.41 | 600030 |
|---|
| 2010-01-06 | 17.548 | 17.250 | 17.628 | 17.229 | 1437889.30 | 600030 |
|---|
| 2010-01-07 | 17.239 | 16.830 | 17.484 | 16.697 | 1235592.34 | 600030 |
|---|
| 2010-01-08 | 16.718 | 17.154 | 17.208 | 16.644 | 1040929.92 | 600030 |
|---|
data['SMA_20'] = data['close'].rolling(20).mean()
data['SMA_60'] = data['close'].rolling(60).mean()
data.tail()
| open | close | high | low | volume | code | SMA_20 | SMA_60 |
|---|
| date | | | | | | | | |
|---|
| 2017-06-26 | 16.186 | 16.492 | 16.635 | 16.148 | 2113195.0 | 600030 | 15.79700 | 15.467750 |
|---|
| 2017-06-27 | 16.482 | 16.349 | 16.511 | 16.301 | 924024.0 | 600030 | 15.83140 | 15.482400 |
|---|
| 2017-06-28 | 16.320 | 16.330 | 16.502 | 16.253 | 871050.0 | 600030 | 15.86245 | 15.497533 |
|---|
| 2017-06-29 | 16.320 | 16.330 | 16.425 | 16.224 | 668341.0 | 600030 | 15.89685 | 15.513783 |
|---|
| 2017-06-30 | 16.263 | 16.263 | 16.349 | 16.072 | 751091.0 | 600030 | 15.92745 | 15.528283 |
|---|
data[['close','SMA_20','SMA_60']].plot(figsize = (10,6))

data['returns'] = np.log(data['close'] / data['close'].shift(1))
data['returns_dis'] = data['close']/data['close'].shift(1) - 1
data['return_dis2'] = data['close'].pct_change()
data.head()
| open | close | high | low | volume | code | SMA_20 | SMA_60 | returns | returns_dis | return_dis2 |
|---|
| date | | | | | | | | | | | |
|---|
| 2010-01-04 | 17.016 | 16.639 | 17.176 | 16.612 | 1106207.58 | 600030 | NaN | NaN | NaN | NaN | NaN |
|---|
| 2010-01-05 | 16.777 | 17.452 | 17.601 | 16.383 | 2093915.41 | 600030 | NaN | NaN | 0.047705 | 0.048861 | 0.048861 |
|---|
| 2010-01-06 | 17.548 | 17.250 | 17.628 | 17.229 | 1437889.30 | 600030 | NaN | NaN | -0.011642 | -0.011575 | -0.011575 |
|---|
| 2010-01-07 | 17.239 | 16.830 | 17.484 | 16.697 | 1235592.34 | 600030 | NaN | NaN | -0.024649 | -0.024348 | -0.024348 |
|---|
| 2010-01-08 | 16.718 | 17.154 | 17.208 | 16.644 | 1040929.92 | 600030 | NaN | NaN | 0.019068 | 0.019251 | 0.019251 |
|---|
data['position'] = np.where(data['SMA_20'] > data['SMA_60'], 1, -1)
data['returns'].cumsum().apply(np.exp).plot(figsize=(10, 6));

SMA策略
1. 数据准备 & 回测准备
import numpy as np
import pandas as pd
import tushare as ts
data = ts.get_k_data('hs300', start = '2010-01-01', end='2017-06-30')
data = pd.DataFrame(data)
data.head()
| date | open | close | high | low | volume | code |
|---|
| 0 | 2010-01-04 | 3592.468 | 3535.229 | 3597.75 | 3535.23 | 66101080.0 | hs300 |
|---|
| 1 | 2010-01-05 | 3545.186 | 3564.038 | 3577.53 | 3497.66 | 85809641.0 | hs300 |
|---|
| 2 | 2010-01-06 | 3558.700 | 3541.727 | 3588.83 | 3541.17 | 78473125.0 | hs300 |
|---|
| 3 | 2010-01-07 | 3543.160 | 3471.456 | 3558.56 | 3452.77 | 80350037.0 | hs300 |
|---|
| 4 | 2010-01-08 | 3456.908 | 3480.130 | 3482.08 | 3426.70 | 60790253.0 | hs300 |
|---|
data.rename(columns={'close': 'price'}, inplace=True)
data.info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 1819 entries, 0 to 1818
Data columns (total 7 columns):
date 1819 non-null object
open 1819 non-null float64
price 1819 non-null float64
high 1819 non-null float64
low 1819 non-null float64
volume 1819 non-null float64
code 1819 non-null object
dtypes: float64(5), object(2)
memory usage: 113.7+ KB
data.head()
| date | open | price | high | low | volume | code |
|---|
| 0 | 2010-01-04 | 3592.468 | 3535.229 | 3597.75 | 3535.23 | 66101080.0 | hs300 |
|---|
| 1 | 2010-01-05 | 3545.186 | 3564.038 | 3577.53 | 3497.66 | 85809641.0 | hs300 |
|---|
| 2 | 2010-01-06 | 3558.700 | 3541.727 | 3588.83 | 3541.17 | 78473125.0 | hs300 |
|---|
| 3 | 2010-01-07 | 3543.160 | 3471.456 | 3558.56 | 3452.77 | 80350037.0 | hs300 |
|---|
| 4 | 2010-01-08 | 3456.908 | 3480.130 | 3482.08 | 3426.70 | 60790253.0 | hs300 |
|---|
data.set_index('date', inplace = True)
data.head()
| open | price | high | low | volume | code |
|---|
| date | | | | | | |
|---|
| 2010-01-04 | 3592.468 | 3535.229 | 3597.75 | 3535.23 | 66101080.0 | hs300 |
|---|
| 2010-01-05 | 3545.186 | 3564.038 | 3577.53 | 3497.66 | 85809641.0 | hs300 |
|---|
| 2010-01-06 | 3558.700 | 3541.727 | 3588.83 | 3541.17 | 78473125.0 | hs300 |
|---|
| 2010-01-07 | 3543.160 | 3471.456 | 3558.56 | 3452.77 | 80350037.0 | hs300 |
|---|
| 2010-01-08 | 3456.908 | 3480.130 | 3482.08 | 3426.70 | 60790253.0 | hs300 |
|---|
data['SMA_10'] = data['price'].rolling(10).mean()
data['SMA_60'] = data['price'].rolling(60).mean()
data.tail()
| open | price | high | low | volume | code | SMA_10 | SMA_60 |
|---|
| date | | | | | | | | |
|---|
| 2017-06-26 | 3627.02 | 3668.09 | 3671.94 | 3627.02 | 134637995.0 | hs300 | 3573.455 | 3475.314500 |
|---|
| 2017-06-27 | 3665.58 | 3674.72 | 3676.53 | 3648.76 | 97558702.0 | hs300 | 3582.700 | 3478.729667 |
|---|
| 2017-06-28 | 3664.16 | 3646.17 | 3672.19 | 3644.03 | 97920858.0 | hs300 | 3593.787 | 3481.746000 |
|---|
| 2017-06-29 | 3649.25 | 3668.83 | 3669.13 | 3644.73 | 85589498.0 | hs300 | 3607.791 | 3485.613833 |
|---|
| 2017-06-30 | 3654.73 | 3666.80 | 3669.76 | 3646.23 | 81510028.0 | hs300 | 3622.595 | 3489.126333 |
|---|
data[['price','SMA_10','SMA_60']].plot(title='HS300 stock price | 10 & 60 days SMAs', figsize=(10, 6));

2. 策略开发思路
data['position'] = np.where(data['SMA_10'] > data['SMA_60'], 1, -1)
data.head()
| open | price | high | low | volume | code | SMA_10 | SMA_60 | position |
|---|
| date | | | | | | | | | |
|---|
| 2010-01-04 | 3592.468 | 3535.229 | 3597.75 | 3535.23 | 66101080.0 | hs300 | NaN | NaN | -1 |
|---|
| 2010-01-05 | 3545.186 | 3564.038 | 3577.53 | 3497.66 | 85809641.0 | hs300 | NaN | NaN | -1 |
|---|
| 2010-01-06 | 3558.700 | 3541.727 | 3588.83 | 3541.17 | 78473125.0 | hs300 | NaN | NaN | -1 |
|---|
| 2010-01-07 | 3543.160 | 3471.456 | 3558.56 | 3452.77 | 80350037.0 | hs300 | NaN | NaN | -1 |
|---|
| 2010-01-08 | 3456.908 | 3480.130 | 3482.08 | 3426.70 | 60790253.0 | hs300 | NaN | NaN | -1 |
|---|
data.dropna(inplace=True)
data['position'].plot(ylim=[-1.1, 1.1], title='Market Positioning');

3. 计算策略年化收益并可视化
data['returns'] = np.log(data['price'] / data['price'].shift(1))
data.head()
| open | price | high | low | volume | code | SMA_10 | SMA_60 | position | returns |
|---|
| date | | | | | | | | | | |
|---|
| 2010-04-02 | 3400.139 | 3407.346 | 3412.20 | 3391.81 | 69073452.0 | hs300 | 3322.9136 | 3313.538117 | 1 | NaN |
|---|
| 2010-04-06 | 3422.849 | 3405.145 | 3436.29 | 3386.89 | 65191710.0 | hs300 | 3333.1653 | 3311.370050 | 1 | -0.000646 |
|---|
| 2010-04-07 | 3403.088 | 3386.949 | 3404.58 | 3369.02 | 54011228.0 | hs300 | 3344.3029 | 3308.418567 | 1 | -0.005358 |
|---|
| 2010-04-08 | 3381.306 | 3346.744 | 3381.31 | 3336.16 | 62185322.0 | hs300 | 3351.3104 | 3305.168850 | 1 | -0.011942 |
|---|
| 2010-04-09 | 3348.773 | 3379.170 | 3379.40 | 3342.47 | 51280567.0 | hs300 | 3366.3146 | 3303.630750 | 1 | 0.009642 |
|---|
data['returns'].hist(bins=35);

data['strategy'] = data['position'].shift(1) * data['returns']
data.head()
| open | price | high | low | volume | code | SMA_10 | SMA_60 | position | returns | strategy |
|---|
| date | | | | | | | | | | | |
|---|
| 2010-04-02 | 3400.139 | 3407.346 | 3412.20 | 3391.81 | 69073452.0 | hs300 | 3322.9136 | 3313.538117 | 1 | NaN | NaN |
|---|
| 2010-04-06 | 3422.849 | 3405.145 | 3436.29 | 3386.89 | 65191710.0 | hs300 | 3333.1653 | 3311.370050 | 1 | -0.000646 | -0.000646 |
|---|
| 2010-04-07 | 3403.088 | 3386.949 | 3404.58 | 3369.02 | 54011228.0 | hs300 | 3344.3029 | 3308.418567 | 1 | -0.005358 | -0.005358 |
|---|
| 2010-04-08 | 3381.306 | 3346.744 | 3381.31 | 3336.16 | 62185322.0 | hs300 | 3351.3104 | 3305.168850 | 1 | -0.011942 | -0.011942 |
|---|
| 2010-04-09 | 3348.773 | 3379.170 | 3379.40 | 3342.47 | 51280567.0 | hs300 | 3366.3146 | 3303.630750 | 1 | 0.009642 | 0.009642 |
|---|
data[['returns', 'strategy']].sum()
returns 0.073386
strategy 0.727122
dtype: float64
data[['returns','strategy']].tail()
| returns | strategy |
|---|
| date | | |
|---|
| 2017-06-26 | 0.012402 | 0.012402 |
|---|
| 2017-06-27 | 0.001806 | 0.001806 |
|---|
| 2017-06-28 | -0.007800 | -0.007800 |
|---|
| 2017-06-29 | 0.006196 | 0.006196 |
|---|
| 2017-06-30 | -0.000553 | -0.000553 |
|---|
data[['returns', 'strategy']].head()
| returns | strategy |
|---|
| date | | |
|---|
| 2010-04-02 | NaN | NaN |
|---|
| 2010-04-06 | -0.000646 | -0.000646 |
|---|
| 2010-04-07 | -0.005358 | -0.005358 |
|---|
| 2010-04-08 | -0.011942 | -0.011942 |
|---|
| 2010-04-09 | 0.009642 | 0.009642 |
|---|
data[['returns', 'strategy']].cumsum().tail()
| returns | strategy |
|---|
| date | | |
|---|
| 2017-06-26 | 0.073737 | 0.727474 |
|---|
| 2017-06-27 | 0.075543 | 0.729280 |
|---|
| 2017-06-28 | 0.067744 | 0.721480 |
|---|
| 2017-06-29 | 0.073939 | 0.727676 |
|---|
| 2017-06-30 | 0.073386 | 0.727122 |
|---|
data[['returns', 'strategy']].sum()
returns 0.073386
strategy 0.727122
dtype: float64
data[['returns', 'strategy']].cumsum().apply(np.exp).tail()
| returns | strategy |
|---|
| date | | |
|---|
| 2017-06-26 | 1.076524 | 2.069846 |
|---|
| 2017-06-27 | 1.078470 | 2.073587 |
|---|
| 2017-06-28 | 1.070091 | 2.057477 |
|---|
| 2017-06-29 | 1.076741 | 2.070263 |
|---|
| 2017-06-30 | 1.076145 | 2.069118 |
|---|
data[['returns', 'strategy']].cumsum().apply(np.exp).plot(figsize=(10, 6));

4. 策略收益风险评估
data[['returns', 'strategy']].mean() * 252
returns 0.010513
strategy 0.104170
dtype: float64
data[['returns', 'strategy']].std() * 252 ** 0.5
returns 0.245468
strategy 0.245382
dtype: float64
data['cumret'] = data['strategy'].cumsum().apply(np.exp)
data['cumret'].tail()
date
2017-06-26 2.069846
2017-06-27 2.073587
2017-06-28 2.057477
2017-06-29 2.070263
2017-06-30 2.069118
Name: cumret, dtype: float64
data['cummax'] = data['cumret'].cummax()
data['cummax'].head(6)
date
2010-04-02 NaN
2010-04-06 0.999354
2010-04-07 0.999354
2010-04-08 0.999354
2010-04-09 0.999354
2010-04-12 0.999354
Name: cummax, dtype: float64
data.tail()
| open | price | high | low | volume | code | SMA_10 | SMA_60 | position | returns | strategy | cumret | cummax |
|---|
| date | | | | | | | | | | | | | |
|---|
| 2017-06-26 | 3627.02 | 3668.09 | 3671.94 | 3627.02 | 134637995.0 | hs300 | 3573.455 | 3475.314500 | 1 | 0.012402 | 0.012402 | 2.069846 | 2.731778 |
|---|
| 2017-06-27 | 3665.58 | 3674.72 | 3676.53 | 3648.76 | 97558702.0 | hs300 | 3582.700 | 3478.729667 | 1 | 0.001806 | 0.001806 | 2.073587 | 2.731778 |
|---|
| 2017-06-28 | 3664.16 | 3646.17 | 3672.19 | 3644.03 | 97920858.0 | hs300 | 3593.787 | 3481.746000 | 1 | -0.007800 | -0.007800 | 2.057477 | 2.731778 |
|---|
| 2017-06-29 | 3649.25 | 3668.83 | 3669.13 | 3644.73 | 85589498.0 | hs300 | 3607.791 | 3485.613833 | 1 | 0.006196 | 0.006196 | 2.070263 | 2.731778 |
|---|
| 2017-06-30 | 3654.73 | 3666.80 | 3669.76 | 3646.23 | 81510028.0 | hs300 | 3622.595 | 3489.126333 | 1 | -0.000553 | -0.000553 | 2.069118 | 2.731778 |
|---|
data[['cumret', 'cummax']].plot(figsize=(10, 6));

drawdown = (data['cummax'] - data['cumret'])
drawdown.max()
0.7744165301748813
temp = drawdown[drawdown == 0]
temp.head()
date
2010-04-06 0.0
2010-05-06 0.0
2010-05-07 0.0
2010-05-11 0.0
2010-05-17 0.0
dtype: float64
temp.index[1:]
Index(['2010-05-06', '2010-05-07', '2010-05-11', '2010-05-17', '2010-06-07',
'2010-06-29', '2010-06-30', '2010-07-01', '2010-07-05', '2010-10-15',
'2010-10-19', '2010-10-20', '2010-10-25', '2010-11-05', '2010-11-08',
'2014-12-04', '2014-12-05', '2014-12-08', '2014-12-16', '2014-12-17',
'2014-12-19', '2014-12-22', '2014-12-26', '2014-12-29', '2014-12-30',
'2014-12-31', '2015-01-05', '2015-01-07', '2015-03-16', '2015-03-17',
'2015-03-18', '2015-03-20', '2015-03-23', '2015-03-24', '2015-03-30',
'2015-04-01', '2015-04-02', '2015-04-03', '2015-04-07', '2015-04-08',
'2015-04-10', '2015-04-13', '2015-04-14', '2015-04-16', '2015-04-17',
'2015-04-21', '2015-04-22', '2015-04-23', '2015-04-27', '2015-05-21',
'2015-05-22', '2015-05-25', '2015-05-26', '2015-06-05', '2015-06-08',
'2015-07-08', '2015-08-21', '2015-08-24', '2015-08-25', '2015-08-26'],
dtype='object', name='date')
temp.index[:-1]
Index(['2010-04-06', '2010-05-06', '2010-05-07', '2010-05-11', '2010-05-17',
'2010-06-07', '2010-06-29', '2010-06-30', '2010-07-01', '2010-07-05',
'2010-10-15', '2010-10-19', '2010-10-20', '2010-10-25', '2010-11-05',
'2010-11-08', '2014-12-04', '2014-12-05', '2014-12-08', '2014-12-16',
'2014-12-17', '2014-12-19', '2014-12-22', '2014-12-26', '2014-12-29',
'2014-12-30', '2014-12-31', '2015-01-05', '2015-01-07', '2015-03-16',
'2015-03-17', '2015-03-18', '2015-03-20', '2015-03-23', '2015-03-24',
'2015-03-30', '2015-04-01', '2015-04-02', '2015-04-03', '2015-04-07',
'2015-04-08', '2015-04-10', '2015-04-13', '2015-04-14', '2015-04-16',
'2015-04-17', '2015-04-21', '2015-04-22', '2015-04-23', '2015-04-27',
'2015-05-21', '2015-05-22', '2015-05-25', '2015-05-26', '2015-06-05',
'2015-06-08', '2015-07-08', '2015-08-21', '2015-08-24', '2015-08-25'],
dtype='object', name='date')
temp.index[1:].to_datetime() - temp.index[:-1].to_datetime()
TimedeltaIndex([ '30 days', '1 days', '4 days', '6 days',
'21 days', '22 days', '1 days', '1 days',
'4 days', '102 days', '4 days', '1 days',
'5 days', '11 days', '3 days', '1487 days',
'1 days', '3 days', '8 days', '1 days',
'2 days', '3 days', '4 days', '3 days',
'1 days', '1 days', '5 days', '2 days',
'68 days', '1 days', '1 days', '2 days',
'3 days', '1 days', '6 days', '2 days',
'1 days', '1 days', '4 days', '1 days',
'2 days', '3 days', '1 days', '2 days',
'1 days', '4 days', '1 days', '1 days',
'4 days', '24 days', '1 days', '3 days',
'1 days', '10 days', '3 days', '30 days',
'44 days', '3 days', '1 days', '1 days'],
dtype='timedelta64[ns]', freq=None)
periods = temp.index[1:].to_datetime() - temp.index[:-1].to_datetime()
periods
TimedeltaIndex([ '30 days', '1 days', '4 days', '6 days',
'21 days', '22 days', '1 days', '1 days',
'4 days', '102 days', '4 days', '1 days',
'5 days', '11 days', '3 days', '1487 days',
'1 days', '3 days', '8 days', '1 days',
'2 days', '3 days', '4 days', '3 days',
'1 days', '1 days', '5 days', '2 days',
'68 days', '1 days', '1 days', '2 days',
'3 days', '1 days', '6 days', '2 days',
'1 days', '1 days', '4 days', '1 days',
'2 days', '3 days', '1 days', '2 days',
'1 days', '4 days', '1 days', '1 days',
'4 days', '24 days', '1 days', '3 days',
'1 days', '10 days', '3 days', '30 days',
'44 days', '3 days', '1 days', '1 days'],
dtype='timedelta64[ns]', freq=None)
periods.max()
Timedelta('1487 days 00:00:00')
5. 策略优化的一种思路
hs300 = ts.get_k_data('hs300','2010-01-01', '2017-06-30')[['date','close']]
hs300 = pd.DataFrame(hs300)
hs300.rename(columns={'close': 'price'}, inplace=True)
hs300.set_index('date',inplace = True)
hs300.head()
| price |
|---|
| date | |
|---|
| 2010-01-04 | 3535.229 |
|---|
| 2010-01-05 | 3564.038 |
|---|
| 2010-01-06 | 3541.727 |
|---|
| 2010-01-07 | 3471.456 |
|---|
| 2010-01-08 | 3480.130 |
|---|
hs300['SMA_10'] = hs300['price'].rolling(10).mean()
hs300['SMA_60'] = hs300['price'].rolling(60).mean()
hs300[['price', 'SMA_10', 'SMA_60']].tail()
| price | SMA_10 | SMA_60 |
|---|
| date | | | |
|---|
| 2017-06-26 | 3668.09 | 3573.455 | 3475.314500 |
|---|
| 2017-06-27 | 3674.72 | 3582.700 | 3478.729667 |
|---|
| 2017-06-28 | 3646.17 | 3593.787 | 3481.746000 |
|---|
| 2017-06-29 | 3668.83 | 3607.791 | 3485.613833 |
|---|
| 2017-06-30 | 3666.80 | 3622.595 | 3489.126333 |
|---|
hs300[['price', 'SMA_10', 'SMA_60']].plot(grid=True, figsize = (8,6));

hs300['10-60'] = hs300['SMA_10'] - hs300['SMA_60']
hs300['10-60'].tail()
date
2017-06-26 98.140500
2017-06-27 103.970333
2017-06-28 112.041000
2017-06-29 122.177167
2017-06-30 133.468667
Name: 10-60, dtype: float64
SD = 20
hs300['regime'] = np.where(hs300['10-60'] > SD, 1,0)
hs300['regime'] = np.where(hs300['10-60'] < -SD, -1,hs300['regime'])
hs300['regime'].value_counts()
1 792
-1 751
0 276
Name: regime, dtype: int64
hs300.tail(20)
| price | SMA_10 | SMA_60 | 10-60 | regime |
|---|
| date | | | | | |
|---|
| 2017-06-05 | 3468.75 | 3457.542 | 3448.415500 | 9.126500 | 0 |
|---|
| 2017-06-06 | 3492.88 | 3466.445 | 3449.064167 | 17.380833 | 0 |
|---|
| 2017-06-07 | 3533.87 | 3478.708 | 3450.483167 | 28.224833 | 1 |
|---|
| 2017-06-08 | 3560.98 | 3492.387 | 3452.717167 | 39.669833 | 1 |
|---|
| 2017-06-09 | 3576.17 | 3507.587 | 3455.188500 | 52.398500 | 1 |
|---|
| 2017-06-12 | 3574.39 | 3516.460 | 3457.126667 | 59.333333 | 1 |
|---|
| 2017-06-13 | 3582.27 | 3526.644 | 3459.219667 | 67.424333 | 1 |
|---|
| 2017-06-14 | 3535.30 | 3530.886 | 3460.414000 | 70.472000 | 1 |
|---|
| 2017-06-15 | 3528.79 | 3533.991 | 3461.202000 | 72.789000 | 1 |
|---|
| 2017-06-16 | 3518.76 | 3537.216 | 3462.417833 | 74.798167 | 1 |
|---|
| 2017-06-19 | 3553.67 | 3545.708 | 3464.152167 | 81.555833 | 1 |
|---|
| 2017-06-20 | 3546.49 | 3551.069 | 3465.487833 | 85.581167 | 1 |
|---|
| 2017-06-21 | 3587.96 | 3556.478 | 3467.786333 | 88.691667 | 1 |
|---|
| 2017-06-22 | 3590.34 | 3559.414 | 3469.925667 | 89.488333 | 1 |
|---|
| 2017-06-23 | 3622.88 | 3564.085 | 3472.147000 | 91.938000 | 1 |
|---|
| 2017-06-26 | 3668.09 | 3573.455 | 3475.314500 | 98.140500 | 1 |
|---|
| 2017-06-27 | 3674.72 | 3582.700 | 3478.729667 | 103.970333 | 1 |
|---|
| 2017-06-28 | 3646.17 | 3593.787 | 3481.746000 | 112.041000 | 1 |
|---|
| 2017-06-29 | 3668.83 | 3607.791 | 3485.613833 | 122.177167 | 1 |
|---|
| 2017-06-30 | 3666.80 | 3622.595 | 3489.126333 | 133.468667 | 1 |
|---|
hs300['Market'] = np.log(hs300['price']/hs300['price'].shift(1))
hs300['Strategy'] = hs300['regime'].shift(1) * hs300['Market']
hs300[['Market','Strategy']].cumsum().apply(np.exp).plot(grid=True, figsize = (8,6));

hs300.head()
| price | SMA_10 | SMA_60 | 10-60 | regime | Market | Strategy |
|---|
| date | | | | | | | |
|---|
| 2010-01-04 | 3535.229 | NaN | NaN | NaN | 0 | NaN | NaN |
|---|
| 2010-01-05 | 3564.038 | NaN | NaN | NaN | 0 | 0.008116 | 0.0 |
|---|
| 2010-01-06 | 3541.727 | NaN | NaN | NaN | 0 | -0.006280 | -0.0 |
|---|
| 2010-01-07 | 3471.456 | NaN | NaN | NaN | 0 | -0.020040 | -0.0 |
|---|
| 2010-01-08 | 3480.130 | NaN | NaN | NaN | 0 | 0.002496 | 0.0 |
|---|
hs300[['Market', 'Strategy']].sum()
Market 0.036541
Strategy 0.896131
dtype: float64
hs300[['Market', 'Strategy']].mean() * 252
Market 0.005065
Strategy 0.124216
dtype: float64
hs300[['Market', 'Strategy']].std() * 252 ** 0.5
Market 0.244318
Strategy 0.235367
dtype: float64
所有评论(0)