金融量化

一、股票数据分析

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
tushare的get_k_data接口
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')
tushare的Pro接口
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)
    
原文地址:https://www.cnblogs.com/standby/p/10745043.html