#2-2 股票买卖策略评估:
#·策略:股价超出10日均线买入,跌破十日均线卖出
#·策略二:十日线上穿60日线买入,下穿60日线卖出(练习)
#加载数据,把date这一列设置为索引,简单起见,只要收盘价进行分析
import numpy as np
import pandas as pd
#使用pandas的read_csv()函数导入原csv文件,并在导入中增加index_col属性和usecols属性
#index_col:索引出口,可定义源文件导出后的定义索引列.下面将date这一组字段定义成索引列
#usecols:使用出口,指定义导出原数据的哪些部分,意思为取出x轴上的第一,第二组元素.
df = pd.read_csv(r'C:\Users\admin\Desktop\BABA_stock.csv',index_col='date',usecols = [0,1])
#先查看下数据
print(df.head(),type(df))
#将索引转化为datetime形式
df.index = pd.DatetimeIndex(df.index.str.strip("'"))
df.index
#按升序进行排序
# sort_index:排序列表,可将列表进行排序.
#sort_index函数默认为升序,如果需要降序要添加属性ascending=False,否则属性默认为True
# df.sort_index(inplace=True,ascending=False)
#注意需要开启inplace属性,这样计算出的值将会返回给原变量,否则将是新建一个
df.sort_index(inplace=True)
print(df)
#可以用describe属性来看其描述结果
df.describe()
#策略一:股价超出10日均线买入,跌破10均线卖出
#先算10日均线数据
#rolling:函数为滚动函数里面的数值是它的滚动周长,也能理解为按多少位一组
#mean:该函数为平均值,配合roling可算出每十个为一组的平均值
#由于我们是算十日均线的,所以十天之内的是无法算出10日平均线,这个时候系统就会将那先自动
#用nan来代替,所以我们需要使用dropna:取出空值将数据清理一下
ma10 = df.rolling(10).mean().dropna()
# print(ma10)
#买点
#计算过程中有nan出现他讲默认不等于任何计算比较条件
ma10_model = df['close'] - ma10['close'] > 0
print(ma10_model)
#第一个值False,第二个值是True,在True的时候买入,需要自定义一个移动窗口来处理函数
#因为卖出的时候还需要定义类似的函数,所以这里把两个函数放在一起
#可以在自定义函数中print一些信息,例如w值,以方便测试----这也是调试的一种方式
def get_deal_date(w,is_buy =True):
if is_buy == True:
return True if w[0]==False and w[1] ==True else False
else:
return True if w[0]==True and w[1] == False else False
# #raw=False 没有的话会有警告消息
# #如果删除Na值,会有缺失,所以这里有0填充,转换为bool值方便后面取值
# se_buy = ma10_model.rolling(2).apply(get_deal_date,raw = False).fillna(0).astype('bool')
# #apply的args接受数组或者字典给自定义函数传参
se_sale = ma10_model.rolling(2).apply(get_deal_date,raw = False,args = [False]).fillna(0).astype('bool')
# #具体的买点
buy_info = df[se_buy]
sale_info = df[se_sale.values]
print(buy_info.head())
print(sale_info.head())
#买和卖的索引值不一样,不过数据都有63条,所以删除时间索引信息
#reset_index(drop = True)这个用法可以将索引重置,期中属性drop=True时原本的索引将被删除,否则保留
no_index_buy_info = buy_info.reset_index(drop=True)
no_index_sale_info = sale_info.reset_index(drop=True)
print(no_index_buy_info.head(),type(no_index_buy_info))
print(no_index_sale_info.head())
#每次的盈利情况
profit = no_index_sale_info -no_index_buy_info
print(profit)
#加入有一万美元,最终盈利是多少
all_money = 10000
remain = all_money
for i in range(len(no_index_buy_info)):
buy_count = remain/ no_index_buy_info.iloc[i]
remain = buy_count * no_index_sale_info.iloc[i]
all_money = sale_info - all_money
print(remain)
#最后剩下13799.294014,年化10%多点,还不错
#将10日线改为60日线试试
#考虑一种边界情况,买了之后卖点现在还没有出现(因为是先买的,所以不可能买点比卖点多)
#这种情况我们把当前的股价加到卖点数据中(也可以把买点数据删除)
print(len(no_index_buy_info))
print(len(no_index_sale_info))
#最后用一个判断验证,处理买入和卖出数量不匹配问题
if (len(no_index_buy_info) > len(no_index_sale_info)):
#no_index_buy_info.drop(no_index_buy_info.index[-1],inplace = True)
no_index_sale_info.loc[len(no_index_sale_info)] = [df.iloc[-1,0]]
#再看下250天,也是盈利的,不是策略多牛逼,而是这个统计区间是在美股大的上升趋势中
#从五日线一直到250线,都是回测下,然后找到最高的