一、股票数据分析
1. 获取茅台股票数据并存储到本地csv文件
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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)