一、股票数据分析
1. 获取茅台股票数据并存储到本地csv文件
1 Signature: 2 ts.get_k_data( 3 code=None, 4 start='', 5 end='', 6 ktype='D', 7 autype='qfq', 8 index=False, 9 retry_count=3, 10 pause=0.001, 11 ) 12 Docstring: 13 获取k线数据 14 --------- 15 Parameters: 16 code:string 17 股票代码 e.g. 600848 18 start:string 19 开始日期 format:YYYY-MM-DD 为空时取上市首日 20 end:string 21 结束日期 format:YYYY-MM-DD 为空时取最近一个交易日 22 autype:string 23 复权类型,qfq-前复权 hfq-后复权 None-不复权,默认为qfq 24 ktype:string 25 数据类型,D=日k线 W=周 M=月 5=5分钟 15=15分钟 30=30分钟 60=60分钟,默认为D 26 retry_count : int, 默认 3 27 如遇网络等问题重复执行的次数 28 pause : int, 默认 0 29 重复请求数据过程中暂停的秒数,防止请求间隔时间太短出现的问题 30 return 31 ------- 32 DataFrame 33 date 交易日期 (index) 34 open 开盘价 35 high 最高价 36 close 收盘价 37 low 最低价 38 volume 成交量 39 amount 成交额 40 turnoverratio 换手率 41 code 股票代码 42 File: /usr/local/python3.6/lib/python3.6/site-packages/tushare/stock/trading.py 43 Type: function
1 import tushare as ts 2 3 token = 'Your token' 4 ts.set_token(token) 5 6 pro = ts.pro_api() 7 df = pro.daily(ts_code='xxx')
In [1]: import numpy as np
In [2]: import pandas as pd
In [3]: import tushare as ts
In [4]: import matplotlib.pyplot as plt
In [5]: df = ts.get_k_data("600519",start='1988-01-01')
In [6]: df.to_csv('600519.csv')
In [7]: df = pd.read_csv('600519.csv',index_col='date',parse_dates=['date'])[['open','close','high','low']]
In [8]: df.head()
Out[8]:
open close high low
date
2001-08-27 5.392 5.554 5.902 5.132
2001-08-28 5.467 5.759 5.781 5.407
2001-08-29 5.777 5.684 5.781 5.640
2001-08-30 5.668 5.796 5.860 5.624
2001-08-31 5.804 5.782 5.877 5.749
In [9]: df.tail()
Out[9]:
open close high low
date
2019-04-15 931.00 907.00 939.00 907.00
2019-04-16 904.90 939.90 939.90 901.22
2019-04-17 938.00 952.00 955.51 925.00
2019-04-18 945.41 945.50 954.68 936.22
2019-04-19 943.96 952.56 960.95 931.31
In [10]:
2. 输出该股票所有收盘比开盘上涨8%以上的日期
In [13]: df[ (df['close']-df['open'])/df['open']>=0.08 ]
Out[13]:
open close high low
date
2004-03-02 5.463 6.031 6.079 5.463
2005-06-08 11.383 12.555 12.639 11.383
2006-02-10 14.894 16.165 16.310 14.796
2006-05-29 25.024 27.520 27.520 25.024
2006-12-18 49.409 54.051 54.214 49.409
2007-06-11 67.313 73.569 73.569 66.913
2007-10-09 92.221 99.938 101.348 92.221
2007-12-14 125.269 135.970 137.154 124.029
2008-11-14 57.017 62.417 62.417 57.017
2009-03-04 73.123 79.024 79.961 72.756
2015-04-16 177.135 192.185 192.185 176.523
2015-07-09 201.180 219.085 221.182 197.901
In [14]: df[ (df['close']-df['open'])/df['open']>=0.1 ]
Out[14]:
open close high low
date
2004-03-02 5.463 6.031 6.079 5.463
2005-06-08 11.383 12.555 12.639 11.383
# 国内股票限制:最多涨10%
In [15]: df[ (df['close']-df['open'])/df['open']>=0.11 ]
Out[15]:
Empty DataFrame
Columns: [open, close, high, low]
Index: []
In [16]:
In [17]: df[ (df['close']-df['open'])/df['open']>=0.08 ].index
Out[17]:
DatetimeIndex(['2004-03-02', '2005-06-08', '2006-02-10', '2006-05-29',
'2006-12-18', '2007-06-11', '2007-10-09', '2007-12-14',
'2008-11-14', '2009-03-04', '2015-04-16', '2015-07-09'],
dtype='datetime64[ns]', name='date', freq=None)
In [18]:
3. 输出该股票所有开盘价比前日收盘价跌幅超过5%的日期
涉及到和前一天数据相比,笨办法自己写for循环,
好在pandas提供了shift函数,非常方便的移动df的数据
In [30]: df.head()
Out[30]:
open close high low
date
2001-08-27 5.392 5.554 5.902 5.132
2001-08-28 5.467 5.759 5.781 5.407
2001-08-29 5.777 5.684 5.781 5.640
2001-08-30 5.668 5.796 5.860 5.624
2001-08-31 5.804 5.782 5.877 5.749
In [31]: df['close'].shift(1).head()
Out[31]:
date
2001-08-27 NaN
2001-08-28 5.554
2001-08-29 5.759
2001-08-30 5.684
2001-08-31 5.796
Name: close, dtype: float64
In [32]: df[ (df['open']-df['close'].shift(1))/df['close'].shift(1)<=-0.05 ]
Out[32]:
open close high low
date
2008-03-13 124.709 133.893 135.341 120.258
2012-11-22 150.981 158.104 158.228 150.471
2015-07-08 194.504 201.180 208.085 186.656
2018-10-11 635.010 644.990 668.940 635.010
2018-10-29 549.090 549.090 549.090 549.090
2018-10-30 510.000 524.000 543.000 509.020
In [33]:
In [33]: df[ (df['open']-df['close'].shift(1))/df['close'].shift(1)<=-0.05 ].index
Out[33]:
DatetimeIndex(['2008-03-13', '2012-11-22', '2015-07-08', '2018-10-11',
'2018-10-29', '2018-10-30'],
dtype='datetime64[ns]', name='date', freq=None)
In [34]:
4. 假如我从2001年1月1日开始,每月第一个交易日买入1手(1手等于100股)股票,每年最后一个交易日卖出所有股票,
那么迄今为止, 我的收益是多少?
In [72]: df = pd.read_csv('600519.csv',index_col='date',parse_dates=['date'])[['open','close','high','low']]
In [73]: df.head()
Out[73]:
open close high low
date
2001-08-27 5.392 5.554 5.902 5.132
2001-08-28 5.467 5.759 5.781 5.407
2001-08-29 5.777 5.684 5.781 5.640
2001-08-30 5.668 5.796 5.860 5.624
2001-08-31 5.804 5.782 5.877 5.749
In [74]: df.tail()
Out[74]:
open close high low
date
2019-04-15 931.00 907.00 939.00 907.00
2019-04-16 904.90 939.90 939.90 901.22
2019-04-17 938.00 952.00 955.51 925.00
2019-04-18 945.41 945.50 954.68 936.22
2019-04-19 943.96 952.56 960.95 931.31
In [75]: price_last = df['open'][-1] # 记住当前最近一天开盘价
In [76]: df = df['2001-09':'2019-03'] # 剔除首尾无用数据
In [77]: df.head()
Out[77]:
open close high low
date
2001-09-03 5.812 5.779 5.870 5.757
2001-09-04 5.782 5.852 5.949 5.762
2001-09-05 5.876 5.849 5.924 5.813
2001-09-06 5.835 5.734 5.854 5.704
2001-09-07 5.702 5.574 5.773 5.570
In [78]: df.tail()
Out[78]:
open close high low
date
2019-03-25 786.00 775.60 788.00 773.30
2019-03-26 780.00 773.00 785.94 764.10
2019-03-27 781.00 788.50 793.88 775.00
2019-03-28 793.43 806.80 814.48 785.68
2019-03-29 835.00 853.99 866.68 830.17
In [79]:
# 利用resample重新采样:获取每月第一天的股票信息
In [83]: df_monthly = df.resample("M").first()
In [84]: df.resample('A').last()
Out[84]:
open close high low
date
2001-12-31 5.885 6.023 6.140 5.852
2002-12-31 4.473 4.448 4.504 4.447
2003-12-31 4.940 4.921 4.940 4.888
2004-12-31 9.325 9.310 9.579 9.168
2005-12-31 14.309 14.039 14.316 13.817
2006-12-31 53.482 54.946 57.617 52.900
2007-12-31 139.495 144.783 144.846 137.085
2008-12-31 68.502 68.818 69.318 68.058
2009-12-31 107.993 108.369 108.516 107.718
2010-12-31 117.103 118.469 118.701 116.620
2011-12-31 138.039 138.468 139.600 136.105
2012-12-31 155.208 152.087 156.292 150.144
2013-12-31 93.188 96.480 97.179 92.061
2014-12-31 157.642 161.056 161.379 157.132
2015-12-31 207.487 207.458 208.704 207.106
2016-12-31 317.239 324.563 325.670 317.239
2017-12-31 707.948 687.725 716.329 681.918
2018-12-31 563.300 590.010 596.400 560.000
2019-12-31 835.000 853.990 866.680 830.170
# 利用resample重新采样:获取每年最后一天的股票信息
# 当前是2019-04-21,前面剔除了4月的数据,所以计算是到2019年3月
# 2019年还未结束,所以最后手里应该还持有2019年前三个月月初买入的股票
In [85]: df.resample('A').last()[:-1]
Out[85]:
open close high low
date
2001-12-31 5.885 6.023 6.140 5.852
2002-12-31 4.473 4.448 4.504 4.447
2003-12-31 4.940 4.921 4.940 4.888
2004-12-31 9.325 9.310 9.579 9.168
2005-12-31 14.309 14.039 14.316 13.817
2006-12-31 53.482 54.946 57.617 52.900
2007-12-31 139.495 144.783 144.846 137.085
2008-12-31 68.502 68.818 69.318 68.058
2009-12-31 107.993 108.369 108.516 107.718
2010-12-31 117.103 118.469 118.701 116.620
2011-12-31 138.039 138.468 139.600 136.105
2012-12-31 155.208 152.087 156.292 150.144
2013-12-31 93.188 96.480 97.179 92.061
2014-12-31 157.642 161.056 161.379 157.132
2015-12-31 207.487 207.458 208.704 207.106
2016-12-31 317.239 324.563 325.670 317.239
2017-12-31 707.948 687.725 716.329 681.918
2018-12-31 563.300 590.010 596.400 560.000
In [86]: df_yearly = df.resample('A').last()[:-1]
# 计算2001年9月到2019年3月购买茅台股票的当前收益
# 当前收益包括两部分:之前每年清仓后的收益和当前持有2019年的股票市值
In [93]: cost = 0
In [94]: hold = 0
In [95]: for year in range(2001, 2020):
...: cost += df_monthly[str(year)]['open'].sum()*100
...: hold += len(df_monthly[str(year)])*100
...: if 2019 != year:
...: cost -= df_yearly[str(year)]['open'][0]*hold
...: hold = 0
...:
In [96]: cost -= hold*price_last
In [97]: print(-cost) # 45万... (5块钱涨到943块...)
454879.89999999985
In [98]:
二、查找历史金叉死叉日期
1. 获取平安银行股票(601318)的历史行情数据
略
2. 计算该股票历史数据的5日均线和30日均线并进行可视化展示
5日均线:其实就是最近5天的收盘价的简单移动平均
2.1 纯手写
In [159]: df = pd.read_csv('601318.20190412.csv',index_col='date',parse_dates=['date'])[['open','close','high','low']]
In [160]: df.head()
Out[160]:
open close high low
date
2007-03-01 21.254 19.890 21.666 19.469
2007-03-02 19.979 19.728 20.166 19.503
2007-03-05 19.545 18.865 19.626 18.504
2007-03-06 18.704 19.235 19.554 18.597
2007-03-07 19.252 19.758 19.936 19.090
In [161]: for i in range(4,len(df)):
...: df.loc[df.index[i],'ma5'] = df['close'][i-4:i+1].mean()
...:
In [162]: for i in range(29,len(df)):
...: df.loc[df.index[i],'ma30'] = df['close'][i-29:i+1].mean()
...:
In [163]: df.head()
Out[163]:
open close high low ma5 ma30
date
2007-03-01 21.254 19.890 21.666 19.469 NaN NaN
2007-03-02 19.979 19.728 20.166 19.503 NaN NaN
2007-03-05 19.545 18.865 19.626 18.504 NaN NaN
2007-03-06 18.704 19.235 19.554 18.597 NaN NaN
2007-03-07 19.252 19.758 19.936 19.090 19.4952 NaN
In [164]: df.tail()
Out[164]:
open close high low ma5 ma30
date
2019-04-15 82.23 81.66 83.88 81.60 81.188 75.443333
2019-04-16 81.22 85.01 85.13 80.90 81.970 75.857667
2019-04-17 84.92 84.48 85.35 83.80 82.460 76.271333
2019-04-18 84.69 84.30 85.02 83.88 83.178 76.676000
2019-04-19 85.27 87.00 87.00 84.20 84.490 77.233000
In [165]:
2.2 pandas实现
In [167]: df['ma5'] = df['close'].rolling(5).mean()
In [168]: df['ma30'] = df['close'].rolling(30).mean()
2.3 numpy实现(进行卷积运算)
In [216]: df = pd.read_csv('601318.20190412.csv',index_col='date',parse_dates=['date'])[['open','close','high','low']]
In [217]: weights = np.ones(5)/5 # 构造array
In [218]: weights
Out[218]: array([0.2, 0.2, 0.2, 0.2, 0.2])
# np.convolve 卷积运算
# np.hstack,即 horizontal stack,得到ma5的array
In [219]: arr = np.hstack( (np.array([np.NaN]*4),np.convolve(df['close'],weights)[4:-4]) )
# 构造ma5的df_ma5
In [220]: df_ma5 = pd.DataFrame({'ma5':arr},index=df.index)
In [221]: df_ma5.head()
Out[221]:
ma5
date
2007-03-01 NaN
2007-03-02 NaN
2007-03-05 NaN
2007-03-06 NaN
2007-03-07 19.4952
In [222]: df.head()
Out[222]:
open close high low
date
2007-03-01 21.254 19.890 21.666 19.469
2007-03-02 19.979 19.728 20.166 19.503
2007-03-05 19.545 18.865 19.626 18.504
2007-03-06 18.704 19.235 19.554 18.597
2007-03-07 19.252 19.758 19.936 19.090
# 合并到df里
In [223]: df = pd.concat([df, df_ma5], axis=1, join_axes=[df.index])
In [224]: df.head()
Out[224]:
open close high low ma5
date
2007-03-01 21.254 19.890 21.666 19.469 NaN
2007-03-02 19.979 19.728 20.166 19.503 NaN
2007-03-05 19.545 18.865 19.626 18.504 NaN
2007-03-06 18.704 19.235 19.554 18.597 NaN
2007-03-07 19.252 19.758 19.936 19.090 19.4952
In [225]: df.tail()
Out[225]:
open close high low ma5
date
2019-04-15 82.23 81.66 83.88 81.60 81.188
2019-04-16 81.22 85.01 85.13 80.90 81.970
2019-04-17 84.92 84.48 85.35 83.80 82.460
2019-04-18 84.69 84.30 85.02 83.88 83.178
2019-04-19 85.27 87.00 87.00 84.20 84.490
In [226]:
# 30日均线同理
ma5和ma30可视化
df[['close','ma5','ma30']].plot(figsize=[12,7],title='ALL')
plt.show()
3. 查找出金叉和死叉日期
3.1 纯手写
In [232]: df.head()
Out[232]:
open close high low ma5 ma30
date
2007-03-01 21.254 19.890 21.666 19.469 NaN NaN
2007-03-02 19.979 19.728 20.166 19.503 NaN NaN
2007-03-05 19.545 18.865 19.626 18.504 NaN NaN
2007-03-06 18.704 19.235 19.554 18.597 NaN NaN
2007-03-07 19.252 19.758 19.936 19.090 19.4952 NaN
In [233]: df.shape
Out[233]: (2888, 6)
In [234]: df = df.dropna()
In [235]: df.shape
Out[235]: (2859, 6)
In [236]: golden_cross = []
In [237]: death_cross = []
In [238]: for i in range(1,len(df)):
...: if df['ma5'][i]>=df['ma30'][i] and df['ma5'][i-1]<df['ma30'][i-1]:
...: golden_cross.append(df.index[i].to_pydatetime())
...: if df['ma5'][i]<=df['ma30'][i] and df['ma5'][i-1]>df['ma30'][i-1]:
...: death_cross.append(df.index[i].to_pydatetime())
...:
In [239]: golden_cross
Out[239]:
[datetime.datetime(2007, 6, 14, 0, 0),
datetime.datetime(2007, 12, 10, 0, 0),
datetime.datetime(2008, 4, 23, 0, 0),
datetime.datetime(2008, 7, 30, 0, 0),
datetime.datetime(2008, 8, 6, 0, 0),
datetime.datetime(2008, 8, 26, 0, 0),
datetime.datetime(2008, 11, 14, 0, 0),
datetime.datetime(2008, 12, 5, 0, 0),
datetime.datetime(2009, 3, 6, 0, 0),
datetime.datetime(2009, 5, 6, 0, 0),
datetime.datetime(2009, 6, 2, 0, 0),
datetime.datetime(2009, 9, 14, 0, 0),
datetime.datetime(2010, 3, 22, 0, 0),
datetime.datetime(2010, 6, 23, 0, 0),
datetime.datetime(2010, 12, 9, 0, 0),
datetime.datetime(2011, 2, 18, 0, 0),
datetime.datetime(2011, 3, 4, 0, 0),
datetime.datetime(2011, 4, 6, 0, 0),
datetime.datetime(2011, 6, 30, 0, 0),
datetime.datetime(2011, 10, 28, 0, 0),
datetime.datetime(2012, 1, 13, 0, 0),
datetime.datetime(2012, 4, 17, 0, 0),
datetime.datetime(2012, 6, 13, 0, 0),
datetime.datetime(2012, 9, 13, 0, 0),
datetime.datetime(2012, 9, 27, 0, 0),
datetime.datetime(2012, 12, 7, 0, 0),
datetime.datetime(2013, 4, 22, 0, 0),
datetime.datetime(2013, 5, 9, 0, 0),
datetime.datetime(2013, 8, 14, 0, 0),
datetime.datetime(2013, 10, 14, 0, 0),
datetime.datetime(2013, 11, 1, 0, 0),
datetime.datetime(2014, 1, 21, 0, 0),
datetime.datetime(2014, 4, 2, 0, 0),
datetime.datetime(2014, 5, 28, 0, 0),
datetime.datetime(2014, 7, 4, 0, 0),
datetime.datetime(2014, 9, 5, 0, 0),
datetime.datetime(2014, 10, 31, 0, 0),
datetime.datetime(2015, 3, 17, 0, 0),
datetime.datetime(2015, 5, 25, 0, 0),
datetime.datetime(2015, 6, 8, 0, 0),
datetime.datetime(2015, 9, 22, 0, 0),
datetime.datetime(2015, 12, 4, 0, 0),
datetime.datetime(2015, 12, 17, 0, 0),
datetime.datetime(2016, 3, 4, 0, 0),
datetime.datetime(2016, 4, 14, 0, 0),
datetime.datetime(2016, 5, 31, 0, 0),
datetime.datetime(2016, 7, 1, 0, 0),
datetime.datetime(2016, 8, 9, 0, 0),
datetime.datetime(2016, 11, 1, 0, 0),
datetime.datetime(2017, 1, 18, 0, 0),
datetime.datetime(2017, 3, 24, 0, 0),
datetime.datetime(2017, 4, 26, 0, 0),
datetime.datetime(2017, 8, 22, 0, 0),
datetime.datetime(2017, 10, 12, 0, 0),
datetime.datetime(2017, 12, 8, 0, 0),
datetime.datetime(2017, 12, 21, 0, 0),
datetime.datetime(2018, 1, 12, 0, 0),
datetime.datetime(2018, 3, 19, 0, 0),
datetime.datetime(2018, 6, 6, 0, 0),
datetime.datetime(2018, 7, 24, 0, 0),
datetime.datetime(2018, 8, 9, 0, 0),
datetime.datetime(2018, 8, 24, 0, 0),
datetime.datetime(2018, 10, 22, 0, 0),
datetime.datetime(2018, 11, 6, 0, 0),
datetime.datetime(2018, 11, 19, 0, 0),
datetime.datetime(2019, 1, 21, 0, 0)]
In [240]: death_cross
Out[240]:
[datetime.datetime(2007, 6, 4, 0, 0),
datetime.datetime(2007, 11, 6, 0, 0),
datetime.datetime(2007, 12, 13, 0, 0),
datetime.datetime(2008, 5, 20, 0, 0),
datetime.datetime(2008, 7, 31, 0, 0),
datetime.datetime(2008, 8, 13, 0, 0),
datetime.datetime(2008, 9, 8, 0, 0),
datetime.datetime(2008, 11, 24, 0, 0),
datetime.datetime(2009, 3, 3, 0, 0),
datetime.datetime(2009, 4, 28, 0, 0),
datetime.datetime(2009, 5, 18, 0, 0),
datetime.datetime(2009, 8, 11, 0, 0),
datetime.datetime(2009, 11, 26, 0, 0),
datetime.datetime(2010, 4, 29, 0, 0),
datetime.datetime(2010, 11, 16, 0, 0),
datetime.datetime(2010, 12, 20, 0, 0),
datetime.datetime(2011, 2, 23, 0, 0),
datetime.datetime(2011, 3, 17, 0, 0),
datetime.datetime(2011, 5, 5, 0, 0),
datetime.datetime(2011, 7, 21, 0, 0),
datetime.datetime(2011, 11, 21, 0, 0),
datetime.datetime(2012, 3, 9, 0, 0),
datetime.datetime(2012, 6, 5, 0, 0),
datetime.datetime(2012, 7, 27, 0, 0),
datetime.datetime(2012, 9, 17, 0, 0),
datetime.datetime(2012, 10, 29, 0, 0),
datetime.datetime(2013, 2, 25, 0, 0),
datetime.datetime(2013, 4, 24, 0, 0),
datetime.datetime(2013, 5, 13, 0, 0),
datetime.datetime(2013, 10, 9, 0, 0),
datetime.datetime(2013, 10, 17, 0, 0),
datetime.datetime(2013, 12, 23, 0, 0),
datetime.datetime(2014, 1, 28, 0, 0),
datetime.datetime(2014, 5, 19, 0, 0),
datetime.datetime(2014, 6, 25, 0, 0),
datetime.datetime(2014, 8, 26, 0, 0),
datetime.datetime(2014, 9, 15, 0, 0),
datetime.datetime(2015, 2, 2, 0, 0),
datetime.datetime(2015, 5, 18, 0, 0),
datetime.datetime(2015, 6, 2, 0, 0),
datetime.datetime(2015, 6, 18, 0, 0),
datetime.datetime(2015, 12, 1, 0, 0),
datetime.datetime(2015, 12, 10, 0, 0),
datetime.datetime(2016, 1, 5, 0, 0),
datetime.datetime(2016, 4, 12, 0, 0),
datetime.datetime(2016, 5, 6, 0, 0),
datetime.datetime(2016, 6, 27, 0, 0),
datetime.datetime(2016, 8, 8, 0, 0),
datetime.datetime(2016, 9, 29, 0, 0),
datetime.datetime(2016, 12, 20, 0, 0),
datetime.datetime(2017, 3, 2, 0, 0),
datetime.datetime(2017, 4, 13, 0, 0),
datetime.datetime(2017, 8, 11, 0, 0),
datetime.datetime(2017, 9, 20, 0, 0),
datetime.datetime(2017, 12, 7, 0, 0),
datetime.datetime(2017, 12, 18, 0, 0),
datetime.datetime(2017, 12, 29, 0, 0),
datetime.datetime(2018, 2, 8, 0, 0),
datetime.datetime(2018, 3, 28, 0, 0),
datetime.datetime(2018, 6, 25, 0, 0),
datetime.datetime(2018, 8, 7, 0, 0),
datetime.datetime(2018, 8, 16, 0, 0),
datetime.datetime(2018, 10, 15, 0, 0),
datetime.datetime(2018, 10, 31, 0, 0),
datetime.datetime(2018, 11, 14, 0, 0),
datetime.datetime(2018, 11, 20, 0, 0)]
In [241]:
3.2 pandas实现
1 df['ma5'] < df['ma30'] 2 3 TTTFFFTTT 4 FFFTTTFFF 5 6 df['ma5'] >= df['ma30']
In [260]: death_cross = df[sr1 & sr2.shift(1)].index
In [261]: golden_cross = df[~(sr1 | sr2.shift(1))].index
In [262]: golden_cross
Out[262]:
DatetimeIndex(['2007-04-12', '2007-06-14', '2007-12-10', '2008-04-23',
'2008-07-30', '2008-08-06', '2008-08-26', '2008-11-14',
'2008-12-05', '2009-03-06', '2009-05-06', '2009-06-02',
'2009-09-14', '2010-03-22', '2010-06-23', '2010-12-09',
'2011-02-18', '2011-03-04', '2011-04-06', '2011-06-30',
'2011-10-28', '2012-01-13', '2012-04-17', '2012-06-13',
'2012-09-13', '2012-09-27', '2012-12-07', '2013-04-22',
'2013-05-09', '2013-08-14', '2013-10-14', '2013-11-01',
'2014-01-21', '2014-04-02', '2014-05-28', '2014-07-04',
'2014-09-05', '2014-10-31', '2015-03-17', '2015-05-25',
'2015-06-08', '2015-09-22', '2015-12-04', '2015-12-17',
'2016-03-04', '2016-04-14', '2016-05-31', '2016-07-01',
'2016-08-09', '2016-11-01', '2017-01-18', '2017-03-24',
'2017-04-26', '2017-08-22', '2017-10-12', '2017-12-08',
'2017-12-21', '2018-01-12', '2018-03-19', '2018-06-06',
'2018-07-24', '2018-08-09', '2018-08-24', '2018-10-22',
'2018-11-06', '2018-11-19', '2019-01-21'],
dtype='datetime64[ns]', name='date', freq=None)
In [263]: death_cross
Out[263]:
DatetimeIndex(['2007-06-04', '2007-11-06', '2007-12-13', '2008-05-20',
'2008-07-31', '2008-08-13', '2008-09-08', '2008-11-24',
'2009-03-03', '2009-04-28', '2009-05-18', '2009-08-11',
'2009-11-26', '2010-04-29', '2010-11-16', '2010-12-20',
'2011-02-23', '2011-03-17', '2011-05-05', '2011-07-21',
'2011-11-21', '2012-03-09', '2012-06-05', '2012-07-27',
'2012-09-17', '2012-10-29', '2013-02-25', '2013-04-24',
'2013-05-13', '2013-10-09', '2013-10-17', '2013-12-23',
'2014-01-28', '2014-05-19', '2014-06-25', '2014-08-26',
'2014-09-15', '2015-02-02', '2015-05-18', '2015-06-02',
'2015-06-18', '2015-12-01', '2015-12-10', '2016-01-05',
'2016-04-12', '2016-05-06', '2016-06-27', '2016-08-08',
'2016-09-29', '2016-12-20', '2017-03-02', '2017-04-13',
'2017-08-11', '2017-09-20', '2017-12-07', '2017-12-18',
'2017-12-29', '2018-02-08', '2018-03-28', '2018-06-25',
'2018-08-07', '2018-08-16', '2018-10-15', '2018-10-31',
'2018-11-14', '2018-11-20'],
dtype='datetime64[ns]', name='date', freq=None)
In [264]:
注意:判断金叉和死叉,应该依赖每天的开盘价,更符合事实。
这里做练习就以收盘价做实验了。
4. 假如我从2010年1月1日开始,初始资金是100000元,金叉尽量买入,死叉全部卖出;
那么迄今为止,我的炒股收益如何?
In [304]: sr1 = pd.Series(1,index=golden_cross)
In [305]: sr1[:5]
Out[305]:
date
2010-03-22 1
2010-06-23 1
2010-12-09 1
2011-02-18 1
2011-03-04 1
dtype: int64
In [306]: sr2 = pd.Series(0,index=death_cross)
In [307]: sr2[:5]
Out[307]:
date
2010-04-29 0
2010-11-16 0
2010-12-20 0
2011-02-23 0
2011-03-17 0
dtype: int64
In [308]: sr = sr1.append(sr2).sort_index() # 把金叉和死叉按时间顺序组合
In [309]: sr[:6]
Out[309]:
date
2010-03-22 1
2010-04-29 0
2010-06-23 1
2010-11-16 0
2010-12-09 1
2010-12-20 0
dtype: int64
In [310]: first_money = 100000
In [311]: money = first_money
In [312]: hold = 0 # 持有多少股
In [313]: for i in range(0,len(sr)):
...: p = df['open'][sr.index[i]]
...: if 1 == sr.iloc[i]:
...: # 金叉,应该尽量买入
...: buy = money//(p*100)
...: hold += buy*100
...: money -= buy*100*p
...: else:
...: # 死叉,应该全部卖出
...: money += hold*p
...: hold = 0
...:
In [314]: p = df['open'][-1] # 记住最后一天的开盘价
In [315]: now_money = money + hold*p # 全部收益包括两部分:持有股票价值和手里已有的现金
In [316]: print(now_money-first_money)
502734.7999999997
In [317]:
三、第一个量化策略
# 导入函数库
from jqdata import *
# 初始化函数,设定基准等等
def initialize(context):
# 设置基本收益
set_benchmark('000300.XSHG')
# 获取股票池
g.security = get_index_stocks('000300.XSHG')
set_option('use_real_price', True)
# 股票类每笔交易时的手续费是:买入时佣金万分之三,卖出时佣金万分之三加千分之一印花税, 每笔交易佣金最低扣5块钱
set_order_cost(OrderCost(open_tax=0, close_tax=0.001, open_commission=0.0003, close_commission=0.0003, close_today_commission=0, min_commission=5), type='stock')
# 每个交易日执行一次
def handle_data(context, data):
# 一般情况下先卖后买
tobuy = []
for stock in g.security:
p = get_current_data()[stock].day_open
# 持有的股票数量
amount = context.portfolio.positions[stock].total_amount
# 平均的开仓成本
cost = context.portfolio.positions[stock].avg_cost
if amount>0 and p>=cost*1.25:
order_target(stock, 0) # 清仓止盈
if amount>0 and p<=cost*0.9:
order_target(stock, 0) # 清仓止损
if p<=10 and 0==amount:
tobuy.append(stock) # 可以买
cash_per_stock = context.portfolio.available_cash / len(tobuy)
for stock in tobuy:
order_value(stock, cash_per_stock)