1-2-python数据分析-DataFrame基础操作巩固-股票分析、双均线策略制定
tushare财经数据接口包
- pip install tushare
- 作用:提供相关指定的财经数据
- 相关文档:http://tushare.org/
需求:股票分析
- 使用tushare包获取某股票的历史行情数据。
- 输出该股票所有收盘比开盘上涨3%以上的日期。
- 输出该股票所有开盘比前日收盘跌幅超过2%的日期。
- 假如我从2010年1月1日开始,每月第一个交易日买入1手股票,每年最后一个交易日卖出所有股票,到今天为止,我的收益如何?
数据处理
使用tushare包获取某股票的历史行情数据
df = ts.get_k_data(code='600519',start='1999-01-10')
df的持久化存储 df.to_xxx()
#将df的数据存储到本地 df.to_csv('./maotai.csv')
加载外部数据 pd.read_xxx()
#加载外部数据到df中:read_xxx() df = pd.read_csv('./maotai.csv') df.head()
将Unnamed: 0列进行删除
在drop系列的函数中
- axis=0表示的行,1表示的是列
- inplace=True将删除操作直接作用原始数据
df.drop(labels='Unnamed: 0', axis=1, inplace=True) df.head()
将date列的字符串类型的时间转换成时间序列类型
df['date'] = pd.to_datetime(df['date']) df['date'].dtype # dtype('<M8[ns]')
将date列作为源数据的行索引
df.set_index('date', inplace=True) df.head()
数据分析
1 、输出该股票所有收盘比开盘上涨3%以上的日期
- (收盘-开盘)/开盘 > 0.03
(df['close']-df['open']) / df['open'] >0.03
经验:在df的相关操作中如果一旦返回了布尔值,下一步马上将布尔值作为原始数据的行索引
将满足需求的行数据获取(收盘比开盘上涨3%以上)
# 发现布尔值可以作为df的行索引,可以直接取出true对应的行数据 df.loc[(df['close'] - df['open']) / df['open'] > 0.03]
获取满足要求的日期
df.loc[(df['close']-df['open']) / df['close'] > 0.03].index DatetimeIndex(['2001-08-28', '2001-09-10', '2001-12-21', '2002-01-18', '2002-01-31', '2003-01-14', '2003-10-29', '2004-01-05', '2004-01-14', '2004-01-29', ... '2019-09-12', '2019-09-18', '2020-02-11', '2020-03-02', '2020-03-10', '2020-04-02', '2020-04-22', '2020-05-06', '2020-07-06', '2020-07-07'], dtype='datetime64[ns]', name='date', length=299, freq=None)
2、输出该股票所有开盘比前日收盘跌幅超过2%的日期
- (开盘 - 前日收盘) / 前日收盘 < -0.02
- shift(n) 可以使该列整体移动n行,正数表示下移,负数表示上移
df.loc[(df['open']-df['close'].shift(1)) / df['close'].shift(1) < -0.02].index DatetimeIndex(['2001-09-12', '2002-06-26', '2002-12-13', '2004-07-01', '2004-10-29', '2006-08-21', '2006-08-23', '2007-01-25', '2007-02-01', '2007-02-06', '2007-03-19', '2007-05-21', '2007-05-30', '2007-06-05', '2007-07-27', '2007-09-05', '2007-09-10', '2008-03-13', '2008-03-17', '2008-03-25', '2008-03-27', '2008-04-22', '2008-04-23', '2008-04-29', '2008-05-13', '2008-06-10', '2008-06-13', '2008-06-24', '2008-06-27', '2008-08-11', '2008-08-19', '2008-09-23', '2008-10-10', '2008-10-15', '2008-10-16', '2008-10-20', '2008-10-23', '2008-10-27', '2008-11-06', '2008-11-12', '2008-11-20', '2008-11-21', '2008-12-02', '2009-02-27', '2009-03-25', '2009-08-13', '2010-04-26', '2010-04-30', '2011-08-05', '2012-03-27', '2012-08-10', '2012-11-22', '2012-12-04', '2012-12-24', '2013-01-16', '2013-01-25', '2013-09-02', '2014-04-25', '2015-01-19', '2015-05-25', '2015-07-03', '2015-07-08', '2015-07-13', '2015-08-24', '2015-09-02', '2015-09-15', '2017-11-17', '2018-02-06', '2018-02-09', '2018-03-23', '2018-03-28', '2018-07-11', '2018-10-11', '2018-10-24', '2018-10-25', '2018-10-29', '2018-10-30', '2019-05-06', '2019-05-08', '2019-10-16', '2020-01-02', '2020-02-03', '2020-03-13', '2020-03-23'], dtype='datetime64[ns]', name='date', freq=None)
3、假如我从2010年1月1日开始,每月第一个交易日买入1手(100支)股票,每年最后一个交易日卖出所有股票,到今天为止,我的收益如何?
- 买股票
- 每月的第一个交易日根据开盘价买入一手股票
- 一个完整的年需要买入12次12手1200支股票(1手股票100支)
- 卖股票
- 每年最后一个交易日根据开盘价(12-31)卖出所有的股票
- 一个完整的年需要卖出1200支股票
- 注意:2020年这个人只能买入700支股票,无法卖出。但是在计算总收益的时候需要将剩余股票的价值也计算在内
- 剩余股票价值如何计算:
- 700 * 买入当日的开盘价
- 剩余股票价值如何计算:
取2010年到2020年的数据
new_df = df['2010':'2020'] # 如果行索引为时间序列类型数据,就可以这样索引取值
数据的重新取样resample
- M代表的是月
# 将2010年到2020年所有的月份数据去取出来分组,取出每个月第一条数据 df_monthly = new_df.resample(rule='M').first() df_monthly #下图为部分数据示例,date显示的其实是每月的第一个交易日,这个是它内部bug导致这个原因
计算买入股票一共花了多少钱
cost = df_monthly['open'].sum() * 100 # 4636917.100000001
数据的重新取样resample
- A代表的是年
df_yearly = new_df.resample(rule='A').last()[0:-1] # 去掉2020年最后的那条数据 df_yearly
计算卖出股票收入多少钱
income = df_yearly['open'].sum() * 1200 # 4368184.8
计算剩余股票的价值
last = df['open'][-1] * 700 # 1182300.0
计算总收益
income + last - cost # 913567.6999999993
需求:双均线策略制定
- 使用tushare包获取某股票的历史行情数据
- 计算该股票历史数据的5日均线和30日均线
- 什么是均线?
- 对于每一个交易日,都可以计算出前N天的移动平均值,然后把这些移动平均值连起来,成为一条线,就叫做N日移动平均线。移动平均线常用线有5天、10天、30天、60天、120天和240天的指标。
- 5天和10天的是短线操作的参照指标,称做日均线指标;
- 30天和60天的是中期均线指标,称做季均线指标;
- 120天和240天的是长期均线指标,称做年均线指标。
- 对于每一个交易日,都可以计算出前N天的移动平均值,然后把这些移动平均值连起来,成为一条线,就叫做N日移动平均线。移动平均线常用线有5天、10天、30天、60天、120天和240天的指标。
- 均线计算方法:MA=(C1+C2+C3+...+Cn)/N C:某日收盘价 N:移动平均周期(天数)
- 什么是均线?
import pandas as pd import numpy as np import matplotlib.pyplot as plt from pandas import Series, DataFrame import tushare as ts df = ts.get_k_data(code='600519', start='1999-01-10') # ts获取数据 df.to_csv('./maotai.csv') # 保存数据 df = pd.read_csv('./maotai.csv') # 读取数据 df.drop(labels='Unnamed: 0', axis=1, inplace=True) # 删除Unnamed: 0列 df['date'] = pd.to_datetime(df['date']) # 时间由字符串转到时间 df.set_index('date', inplace=True) # 将date设置为索引 df.head() # 查看数据前5行
计算并制定双均线
# rolling(5)拿到每个数据的前5个数据,算他本身 # mean() 求平均 # 前几个数据显示NaN是因为它前边没有足够数据 df = df['2010':'2020'] ma5 = df['close'].rolling(5).mean() ma30 = df['close'].rolling(30).mean() plt.plot(ma5[50:200]) plt.plot(ma30[50:200])
分析输出所有金叉日期和死叉日期
- 股票分析技术中的金叉和死叉,可以简单解释为:
- 分析指标中的两根线,一根为短时间内的指标线,另一根为较长时间的指标线。
- 如果短时间的指标线方向拐头向上,并且穿过了较长时间的指标线,这种状态叫“金叉”;
- 如果短时间的指标线方向拐头向下,并且穿过了较长时间的指标线,这种状态叫“死叉”;
- 一般情况下,出现金叉后,操作趋向买入;死叉则趋向卖出。当然,金叉和死叉只是分析指标之一,要和其他很多指标配合使用,才能增加操作的准确性。
数据分析
- 如果我从假如我从2010年1月1日开始,初始资金为100000元,金叉尽量买入,死叉全部卖出,则到今天为止,我的炒股收益率如何?
- 分析:
- 买卖股票的单价使用开盘价
- 买卖股票的时机
- 最终手里会有剩余的股票没有卖出去
- 会有。如果最后一天为金叉,则买入股票。估量剩余股票的价值计算到总收益。
- 剩余股票的单价就是用最后一天的收盘价。
- 会有。如果最后一天为金叉,则买入股票。估量剩余股票的价值计算到总收益。
将时间节点的金叉和死叉日期全部找出
注意:金叉日期、死叉日期不可能连续
death_date = df.loc[s1&s2.shift(1)].index # 死叉日期 gold_date = df.loc[~(s1|s2.shift(1))].index # 金叉日期
将金叉日期和死叉日期分别存储到两个Series中,将日期作为Series的索引,将0和1作为Series的value值
- value为1对应的日期为金叉日期
- value为0对应的日期为死叉日期
series_1 = Series(data=1, index=gold_date) series_2 = Series(data=0, index=death_date) # 将金叉和死叉日期进行级联操作,并按时间索引升序排序 # 去除前30条的数据,因为这些日期存在金叉或死叉日期连续 series_all = series_1.append(series_2).sort_index()[30:]
收益计算
- 金叉尽量买入,死叉全部卖出,买卖股票的单价使用开盘价
- 特殊情况:昨天为金叉只能买入不能卖出,手里如果有剩余的股票也是需要将其价值计算到总收益
first_money = 100000 # 本金(不可变) cost_money = 100000 # (可变) hold = 0 # 持有股票的支数 for index in series_all.index: # index就是series_all的显示索引 if series_all[index] == 1: # 当日为金叉,需要买入股票 # 找出购买股票的单价 price = df['open'][index] # 所有的钱尽量买入股票的手数 hand = cost_money // (price * 100) hold = hand * 100 # 一共买入了多少只股票 # 将买股票花的钱从cost_money中减出 cost_money -= (hold * price) else: # 卖出股票 # 找出卖股票的单价 price = df['open'][index] cost_money += (price * hold) hold = 0 # 计算剩余股票的实际价值(如何知道是否存有剩余股票) last_money = hold * df['open'][-1] # 总收益 print(last_money + cost_money - first_money) 2194722.0999999996