Python进行股票分析

1.准备工作
可以结合视频进行学习,视频链接:视频

2.工具以及所需库

  jupyter notebook
  tushare、pandas、numpy、matplotlib

3.库的安装

  打开anaconda prompt命令框输入以下命令:
  conda install pandas
  conda install numpy
  conda install matplotlib
  conda install tushare

4.项目介绍

需求:股票分析
使用tushare包获取某股票的历史行情数据
输出该股票所有收盘比开盘上涨3%以上的日期
输出该股票所有开盘比前日收盘跌幅超过2%的日期
问如果我从2010年1月1日开始,每月第一个交易日买入1手股票,每年最后一个交易日卖出所有股票,到今天为止,我的收益如何?

tushare官网:官网

5.项目步骤

5.1 导入模块

# 导入相关的模块
import tushare as ts
import pandas as pd
from pandas import DataFrame,Series
import numpy as np

5.2 数据的获取写入以及读取

代码中所用到的数据集是从tushare官网上获取的,然后将其写入本地,再进行数据的读取。

 # 获取某只股票的历史行情数据
df=ts.get_k_data(code='600519',start='2000-01-01')  #ts.get_k_data(code=None,start='',end='',)
 # 将互联网上的股票数据写入到本地
df.to_csv('./gp.csv')   #调用to_xxx方法将df中的数据写入到本地进行存储  本地会生成一个gupiao.csv的文件
# 将本地存储的数据读入到df
df=pd.read_csv('./gp.csv')
df.head()  #显示前五行的数据

5.3 处理数据

# 需要对读取出来的数据进行相关的处理
# 删除df中指定的一列
df.drop(labels='Unnamed: 0',axis=1,inplace=True)   #drop中axis=1表示的是列,inplace=True更改原始数据,从前五行的数据可看出Unnamed: 0这一列没用需要给删去
# 这里有个问题:注意Unnamed:和0中间是有一个空格的
# 查看每一列的数据类型
df.info()  #info()可以查数据类型,也可以看出是否有空值缺失值
# data :object 字符串类型
# 将date列转换为时间序列类型
df['date']=pd.to_datetime(df['date'])
# 行隐式索引没有什么用
# 可以将date列作为源数据的行索引,因为股票是随着时间进行变化的,一条记录对应一个时间
df.set_index('date',inplace=True)
df.head()   

5.4 输出该股票所有收盘比开盘上涨3%以上的日期

#这个功能的实现视频中没有讲解,但是注释很清楚:
#df['open']取的是开盘的数据, df['close']取的是收盘的数据,
#满足条件的布尔值为True,可以将True作为df的行索引,那么利用df.loc[布尔值为True的行索引]
#就可以取出布尔值为True的行索引所对应的行数据
#输出该股票所有收盘比开盘上涨3%以上的日期
#伪代码:(收盘-开盘)/开盘 > 0.03
(df['open'] - df['close']) / df['open'] > 0.03

#在分析的过程中如果产生了boolean值则下一步马上将布尔值作为源数据的行索引
 #如果布尔值作为df的行索引,则可以取出true对应的行数据,忽略false对应的行数据
df.loc[(df['open'] - df['close']) / df['open'] > 0.03] #获取了True对应的行数据(满足需求的行数据)
df.loc[(df['open'] - df['close']) / df['open'] > 0.03].index #df的行数据,对应的是日期行索引

结果图如下所示:
运行图

5.5 输出该股票所有开盘比前日收盘跌幅超过2%的日期

#这里需要注意的是前日收盘我们应该如何处理:因为我们进行计算需要是同行数据进行计算,
#所以利用shift(1)将收盘的数据全部下移一行再与开盘进行计算即将开盘和前日收盘进行计算
#输出该股票所有开盘比前日收盘跌幅超过2%的日期
#伪代码:(开盘-前日收盘)/前日收盘 < -0.02  负数要小于才是超过
(df['open'] - df['close'].shift(1))/df['close'].shift(1) < -0.02
#将布尔值作为源数据的行索引取出True对应的行数据,shift(1)即将close一列下移一行,因为要减去的是前日收盘的 shift(-1)上移一位
df.loc[(df['open'] - df['close'].shift(1))/df['close'].shift(1) < -0.02]   # 取出满足条件的数据
df.loc[(df['open'] - df['close'].shift(1))/df['close'].shift(1) < -0.02].index   # 时间索引

结果图如下所示:
运行结果图

5.6 解决问题

#需求:如果我从2010年1月1日开始,每月第一个交易日买入      1%手股票,每年最后一个交易日卖出所有股票,到今天为止,我的收益如何?
#时间节点:2010-2021 原始数据时间从2001开始 所以需要拆分时间
#一手股票:100支股票
#买股票money:一年买入12手股票共1200支股票
#卖股票money:一年卖出1200支股票
#买卖股票的单价:另开盘价作为单价
# 时间控制在2010-2021
new_df=df['2010-01':'2021-04']  #[时间序列]

# 买股票 开盘价为单价
# 找出每个月的第一个交易日对应的行数据(捕获到开盘价)===》每月的第一行数据
df_monthly=new_df.resample('M').first() #数据的重新取样,每个月的第一行数据,这里日期索引是错误的,但是数据是对的

# 买入股票花费的总金额
cost=df_monthly['open'].sum()*100  #求和乘100

# 卖出股票的钱
# 特殊情况:2021年的股票目前还不能卖出
new_df.resample('A').last()   #最后一行2021年的数据目前用不到

# 将2021年最后一行数据切出
df_yearly=new_df.resample('A').last()[:-1]

# 卖出股票的钱
recv=df_yearly['open'].sum()*1200  

# 收益 最后手中的股票需要估量其价值计算到总数中
# 使用昨天的收盘价作为剩余股票的单价
last_money=400*new_df['close'][-1]

# 计算总收益
recv+last_money-cost

5.7 双均线策略制定

#计算该股票历史数据的5日均线和6日均线
#均线:对于每一个交易日,都可以计算出前N天的移动平均      值,
#然后把这些移动平均值连起来,成为一条线,就叫做N日移动平均线。
#移动平均线常用线有5天、 10天、30天、60天、120天和240天的指标。  
#5天和10天的是短线操作的参照指标,称做日均线指标;
#30天和60天的是中期均线指标,称做季均线指标;
#120天和240天的是长期均线指标,称做年均线指标。

#均线计算方法:MA=(C1+C2+C3+...+Cn)/N C:某日收盘价 N:移动平均周期(天数)
# 使用tushare包获取某股票的历史行情数据,返回新的表df
df=pd.read_csv('./gp.csv').drop(labels='Unnamed: 0',axis=1)

# 将date列转为时间序列,并作为源数据的行索引
df['date']=pd.to_datetime(df['date'])
df.set_index('date',inplace=True)

ma5=df['close'].rolling(5).mean()  # rolling(5)以5天为单位计算close总和,前四天不够五天所以为NaN
ma30=df['close'].rolling(30).mean()  #前29天为NaN

import matplotlib.pyplot as plt
%matplotlib inline
plt.plot(ma5)
plt.plot(ma30) 

结果如下所示:
运行结果图

plt.plot(ma5[50:180])
plt.plot(ma30[50:180])

结果如下所示:
运行结果图

金叉和死叉这部分代码可以结合下图进行理解:
理解图

# 要对ma5和m30进行比较,考虑到各自的缺失值,要对缺失值进行过滤
ma5=ma5[30:]
ma30=ma30[30:]

s1=ma5<ma30
s2=ma5>ma30

df=df[30:]

death_ex=s1&s2.shift(1)  #判定死叉的条件
df.loc[death_ex]  #死叉对应的行数据
death_date=df.loc[death_ex].index

golden_ex=-(s1|s2.shift(1))  #判定金叉的条件
df.loc[golden_ex]  #金叉对应的行数据
golden_date=df.loc[golden_ex].index #金叉的时间

5.8 解决问题

#如果我从2010年1月1日开始,初始资金为100000元,
#金叉尽量买入,死叉全部卖出,则到今天为止,我的炒股收益率如何?
#分析:买卖股票的单价使用开盘价
#买卖股票的时机(金叉或者死叉)
#最后手里可能没卖出去,如果最后一天为金叉,则买入股票,
#也就是手里会有股票,所以我们要估量剩余股票的价值计算到总收益
#剩余股票的单价使用最后一天的收盘价
# 划定时间区间2010-2021
# 对金叉和死叉进行标识,1为金叉,0为死叉
s1=Series(data=1,index=golden_date)  
s2=Series(data=0,index=death_date)
s=s1.append(s2)
s=s.sort_index()  #存储金叉和死叉的时间

s=s['2010':'2021']

​first_money=100000 #本金不变
money=first_money  #可变的,买卖股票的钱
hold=0  #持有股票的数量(100股=1手)

for i in range(0,len(s)):  #i表示的是s这个Series中的隐式索引
    if s[i]==1:  #金叉
#         基于100000的本金尽可能的买入股票
#         获取股票的单价(金叉时间对应的行数据中的开盘价)
        time=s.index[i]  #金叉的时间
        p=df.loc[time]['open']  #金叉时间对应的开盘价即股票的单价
        hand_count=money//(p*100)  #使用100000最多买入的股票数
        hold=hand_count*100
        
        money-=(hold*p)  #买股票要花钱呐
    
    else:
        death_time=s.index[i]
        p_death=df.loc[death_time]['open']  #买股票的单价即死叉对应的时间的开盘价
        money+=(p_death*hold)  #收钱啦,hold如果是金叉就是0,死叉就是剩余的数量
        hold=0  #卖出之后将其置为0

#如何判定最后一天是金叉还是死叉
last_money=hold*df['close'][-1]  #剩余的股票价值,金叉hold就是hold,死叉hold就是0

# # 总收益
total=money+last_money-first_money
total

文中有什么错误的地方欢迎提出哈!一起玩耍,一起学习,一起进步!大家都是最棒滴!

最后,送大家一句话:起风了,唯有努力生存!我们都要加油啊!

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐