logo资料库

python训练——简单股票数据分析.pdf

第1页 / 共6页
第2页 / 共6页
第3页 / 共6页
第4页 / 共6页
第5页 / 共6页
第6页 / 共6页
资料共6页,全文预览结束
python训练训练——简单股票数据分析 简单股票数据分析 本程序仅为个人学习测试使用,不做商业用途,据此操作,后果自负 本程序仅为个人学习测试使用,不做商业用途,据此操作,后果自负 主要的策略就是通过计算涨幅和平均值来判断买入与卖出的时机。 因为我自己本身对股票了解不多,所以我写的东西要为其他策略可能还是会有点困难的。 框架解释 框架解释 获取数据 用爬虫等相关操作获取到数据,并保存到本地,以避免重复爬取浪费时间与性能 将本地的数据导入我们的程序 通过保存的数据计算涨幅,并获取涨幅最大的股票 计算某段时间内的平均价格 实行买卖的判断 买操作 卖操作 画图,实现数据可视化 代码实现 代码实现 做最开始的初始化 做最开始的初始化 1. 输入参数的初始化 输入参数的初始化 codes 传入所需要分析的代码 列表格式,建议在定义对象之前就写好这个列表 默认是空,也就是 “[]” in_date 数据分析最开始的日期 默认是2014-01-01 这个日期在后续的计算中会一直后推,直到等于time time 数据分析的截止日期 默认是系统现在的日期,而且要格式化为“年-月-日” time_span_inc 用于分析涨幅 默认13,即求13天内的涨幅 time_span_avg 用于分析平均价格 默认13,即求13天内的平均价格 funds 是你手上现有的资金 默认为10w path 传入保存地址 2. 全局变量的初始化 全局变量的初始化 self.df = None 保存从本地文件中获取的数据 self.the_code = {“code”: None, “price”: None} 保存你手上持有的股票和买入的价格 在后续中可以改为列表,然后再添加一个字典属性:持有量 self.change = {“funds”: [], “date”: []} 获取所持有资金的变化数据,为后面 数据可视化做准备 3.示例示例 def __init__(self, codes=[], in_date="2014-01-01", time=time.strftime('%Y-%m-%d', time.localtime(time.time())), time_span_inc=13, time_span_avg=13, funds=100000, path="D:/"): self.codes = codes # 所需要获取的股票 self.in_date = in_date # 数据处理开始日期 self.time = time # 数据处理结束日期 self.time_span_inc = time_span_inc # 涨幅跨度 self.time_span_avg = time_span_avg # 平均值跨度 self.funds = funds # 现有资金 self.path = path # 获取股票数据保存的地址 self.df = None self.the_code = {"code": None, "price": None} self.change = {"funds": [], "date": []} 在互联网上获取数据 在互联网上获取数据 因为爬取的方法很多很多,我只用了最简单的方法 主要是通过循环获取传入的股票代码的相关信息,并格式化保存到本地 这个方法是只需要运行一次,把数据保存下来以后可以重复使用,方便改数据调整方案。 示例示例 获取的初步结果,所有相关数据都有,但是我们只要收盘的数据
筛选并保存数据 首先将“Close”这一列的标签索引重命名,然后只把这一列保存下来 这个就是保存的格式 在个别电脑上会出现只保留后面的数据,而不保存表头的情况,建议在保存到本地之后检查一下格式是否和下面是否相同 相关代码 # 获取相关数据 def get_all_data(self): # 获取数据的时间段-结束时间 end = datetime.date.today() for code in self.codes: # 这个方法是pandas_datareader.data里面自带的,通过传入股票代码可以在相关网站获取对应数据 stock = web.DataReader(code, "yahoo", self.in_date, end) # 将“Close”重命名为对应的code stock.rename(columns={"Close": code}, inplace=True) stock[code].to_csv(self.path + code + ".csv") # 保存到本地 获取本地的数据 获取本地的数据 将本地的数据获取到目前的程序里面来 # 获取Excel中数据,并存到data列表中 def get_data(self): # 直接将self.df初始化为第一支股票对应的数据,后面的数据只需要在这个基础上列相加就好了 self.df = pd.read_csv(self.path + self.codes[0] + ".csv") # 通过循环获取所有的数据 for code in self.codes[1:]: # 获取csv文件 df = pd.read_csv(self.path + code + ".csv") # 数据合并 self.df = pd.merge(self.df, df, left_on="Date", right_on="Date", how="outer") # 将索引设置为date self.df.set_index('Date', inplace=True) 获取某一天之前n天前的数据 获取某一天之前 天前的数据 这里的n是前面初始化的时候定义的time_span_inc与time_span_avg中更大的那个,为了在后续的处理中可以有充足的数据 获取的方法最好用切片,效率高也看起来方便,但是我的返回值时用的numpy,后面的操作基本上是根据numpy来的,所以懒得改了 # 获取那n天的数据,格式是numpy def get_n_day(self, in_data): try: # 获取输入那天的位置索引 position_index = self.df.index.get_loc(in_data) # 如果位置索引小于计算所需要的数字,那么说明数据量不够, if position_index>=max(self.time_span_avg, self.time_span_inc): # 用于保存每支股票的数据 code_list = [] for code in range(len(self.codes)): # 用于保存当前股票的数据 i_list = [] for i in range(max(self.time_span_avg, self.time_span_inc)): # 获取数据 i_list.append(self.df.iloc[position_index - i - 1, code]) code_list.append(i_list) # 这个地方应该要用切片来获取数据的,这么改虽然麻烦但是看得懂啊(其实就是懒得改了) return np.array(code_list) # 数据量不够,不能带入进行计算 else: return np.array([0]) except Exception as e: print("获取"+in_data+"的近日数据失败,估计这天没开盘,没有数据") return np.array([0]) 获取涨幅与平均价格 获取涨幅与平均价格 在获取涨幅的时候,还顺便获取了涨幅最大的股票代码号的序列号 # 计算涨幅 def get_increase(self, result): inc = [] for code in range(len(self.codes)): # 今天的价格/time_span_inc天前的价格 - 1 increase = (result[code][0] / result[code][self.time_span_inc - 1]) - 1 inc.append(increase) # 不仅仅获取了对应的涨幅,还获取了涨幅最大的股票代码号的序列号 return inc, inc.index(max(inc)) # 计算平均价格 def get_avg(self, result): avg_result = result[:, :self.time_span_avg].mean(axis=1) return avg_result 模拟买卖 模拟买卖 买的条件是判断现在的价格大于平均价格,涨幅最大而且要大于0 卖的条件是现在持有的股票不再是涨幅第一,或者现价小于近些天的平均价格 买卖的过程基本上就是重置手上持有的股票和持有的资金来完成的 1. 判断是买还是卖 判断是买还是卖 # 判断实行买卖 def buy_sell(self, increase, avg, result): # 参考数据 # ([0.05955, 0.02632, 0.058093], 0) 最后一个是涨幅最大的代码号 # [1.68161 3.96707 5.50792] 这段时间的平均价格 # [1.70799 4.01599 5.62799] 当前天的价格
# 获取现在涨幅最大股票的价格和平均价格 new_price = result[increase[1]] avg_price = avg[increase[1]] # 如果没有持有的股票则考虑买入 if self.the_code["code"] is None: # 满足条件:现在的价格大于平均价格,涨幅最大而且要大于0 if new_price > avg_price: self.buy(self.codes[increase[1]], new_price) # 如果现在持有的股票不再是涨幅第一,或者现价小于近些天的平均价,或者到了最后一天更新时间 elif (self.the_code["code"] != self.codes[increase[1]]) | (new_price avg_price) & (increase[0][increase[1]] > 0): self.buy(self.codes[increase[1]], new_price) else: print(self.in_date + "继续持有:", self.the_code["code"]) 2. 卖卖 def sell(self, result): # 因为卖出了,更新现有资金,并将现在持有的股票清空,用现在的价格/先前的价格再*现有的资金 print("卖" + "*" * 30) print("在" + self.in_date + "卖出") print("全部卖出:", self.the_code["code"]) # 卖出价格是持有股票(self.the_code["code"])的现价 sell_price = result[self.codes.index(str(self.the_code["code"]))] print("卖出价格", sell_price) # 更新价格 self.funds = self.funds * (sell_price / self.the_code["price"]) self.change["funds"].append(self.funds) self.change["date"].append(self.in_date) self.the_code["code"] = None self.the_code["price"] = None print("资金持有变为:", self.funds) print("*" * 30) 3. 买买 def buy(self, code, new_price): # 更新持有股票和对应买入价格 self.the_code["code"] = code self.the_code["price"] = new_price self.change["funds"].append(self.funds) self.change["date"].append(self.in_date) print("在" + self.in_date + "买入") print("将资金全部买入", self.the_code["code"]) print("买入价格:", self.the_code["price"]) print("资金持有变为:", self.funds) print("*" * 30) 后续辅助功能 后续辅助功能 将时间后推 tim就是后推的天数 没有返回值,直接操作in_date # 输入某天获取到第二天的str def get_next_day(self, tim=1): timeArray = time.strptime(self.in_date, "%Y-%m-%d") timeStamp = int(time.mktime(timeArray)) timeStamp = timeStamp + 86400 * tim timeArray = time.localtime(timeStamp) self.in_date = time.strftime("%Y-%m-%d", timeArray) 画一个能看的图 # 画图 def draw(self): x = self.change["date"] y = self.change["funds"] # 设置图片大小 plt.figure(figsize=(12, 8), dpi=80) # 绘图(折线) plt.plot(x, y, color="red", linewidth=2, alpha=0.6) # 设置轴的刻度 plt.xticks(list(x)[::20], x[::20], rotation=45) # rotation 为旋转角度 # 展示图片 plt.show() 最后的执行框架 最后的执行框架 获取本地数据 从第一天开始循环,将in_date后推 获取涨幅与平均价格 判断买卖,并实行 在循环结束之后输出现有的资金,和最大持有资金 画一个折线图反映变化 # 主函数 def the_main(self): self.get_data() while self.in_date != self.time: # 获取涨幅以及平均价格 np_result = self.get_n_day(self.in_date) # 得确定获取的数据是非为空 if np_result.any(): increase = self.get_increase(np_result) # 再次确定获取的数据是非为空 if increase != 0: avg = self.get_avg(np_result) # 进行买卖等操作 self.buy_sell(increase, avg, np_result[:, 0]) # 进入下一天 self.get_next_day() print("现在持有", self.funds) print(max(self.change["funds"]))
self.draw() 画出来的图如下 画出来的图如下 在最后你持有了31973.95元 到此结束 到此结束 最后附上全部代码 最后附上全部代码 # -*- coding: utf-8 -*- # 股票交易模拟 import datetime import time import numpy as np import pandas as pd import matplotlib.pyplot as plt import pandas_datareader.data as web class try_day: def __init__(self, codes=[], in_date="2014-01-01", time=time.strftime('%Y-%m-%d', time.localtime(time.time())), time_span_inc=13, time_span_avg=13, funds=100000, path="D:/"): self.codes = codes # 所需要获取的股票 self.in_date = in_date # 数据处理开始日期 self.time = time # 数据处理结束日期 self.time_span_inc = time_span_inc # 涨幅跨度 self.time_span_avg = time_span_avg # 平均值跨度 self.funds = funds # 现有资金 self.path = path # 获取股票数据保存的地址 self.df = None self.the_code = {"code": None, "price": None} self.change = {"funds": [], "date": []} # 获取相关数据 def get_all_data(self): end = datetime.date.today() for code in self.codes: stock = web.DataReader(code, "yahoo", self.in_date, end) stock.rename(columns={"Close": code}, inplace=True) stock[code].to_csv(self.path + code + ".csv") # 保存到本地 # 获取Excel中数据,并存到data列表中 def get_data(self): self.df = pd.read_csv(self.path + self.codes[0] + ".csv") for code in self.codes[1:]: df = pd.read_csv(self.path + code + ".csv") self.df = pd.merge(self.df, df, left_on="Date", right_on="Date", how="outer") self.df.set_index('Date', inplace=True)
# 获取那n天的数据,格式是numpy def get_n_day(self, in_data): try: position_index = self.df.index.get_loc(in_data) if position_index >= max(self.time_span_avg, self.time_span_inc): code_list = [] for code in range(len(self.codes)): i_list = [] for i in range(max(self.time_span_avg, self.time_span_inc)): i_list.append(self.df.iloc[position_index - i - 1, code]) code_list.append(i_list) return np.array(code_list) else: return np.array([0]) except Exception as e: return np.array([0]) # 计算涨幅 def get_increase(self, result): inc = [] for code in range(len(self.codes)): increase = (result[code][0] / result[code][self.time_span_inc - 1]) - 1 inc.append(increase) return inc, inc.index(max(inc)) # 计算平均价格 def get_avg(self, result): avg_result = result[:, :self.time_span_avg].mean(axis=1) return avg_result # 判断实行买卖 def buy_sell(self, increase, avg, result): new_price = result[increase[1]] avg_price = avg[increase[1]] if self.the_code["code"] is None: if new_price > avg_price: self.buy(self.codes[increase[1]], new_price) elif (self.the_code["code"] != self.codes[increase[1]]) | (new_price avg_price) & (increase[0][increase[1]] > 0): self.buy(self.codes[increase[1]], new_price) else: print(self.in_date + "继续持有:", self.the_code["code"]) def sell(self, result): print("卖" + "*" * 30) print("在" + self.in_date + "卖出") print("全部卖出:", self.the_code["code"]) sell_price = result[self.codes.index(str(self.the_code["code"]))] print("卖出价格", sell_price) self.funds = self.funds * (sell_price / self.the_code["price"]) self.change["funds"].append(self.funds) self.change["date"].append(self.in_date) self.the_code["code"] = None self.the_code["price"] = None print("资金持有变为:", self.funds) print("*" * 30) def buy(self, code, new_price): self.the_code["code"] = code self.the_code["price"] = new_price self.change["funds"].append(self.funds) self.change["date"].append(self.in_date) print("在" + self.in_date + "买入") print("将资金全部买入", self.the_code["code"]) print("买入价格:", self.the_code["price"]) print("资金持有变为:", self.funds) print("*" * 30) # 画图 def draw(self): x = self.change["date"] y = self.change["funds"] plt.figure(figsize=(12, 8), dpi=80) plt.plot(x, y, color="red", linewidth=2, alpha=0.6) plt.xticks(list(x)[::20], x[::20], rotation=45) # rotation 为旋转角度 plt.show() # 主函数 def the_main(self): self.get_data() while self.in_date != self.time: np_result = self.get_n_day(self.in_date) if np_result.any(): increase = self.get_increase(np_result) if increase != 0: avg = self.get_avg(np_result) self.buy_sell(increase, avg, np_result[:, 0]) # 进入下一天 self.get_next_day() print("现在持有", self.funds) print(max(self.change["funds"])) self.draw() # 输入某天获取到第二天的str def get_next_day(self, tim=1): timeArray = time.strptime(self.in_date, "%Y-%m-%d") timeStamp = int(time.mktime(timeArray)) timeStamp = timeStamp + 84600 * tim timeArray = time.localtime(timeStamp) self.in_date = time.strftime("%Y-%m-%d", timeArray)
if __name__ == '__main__': codes = ['159915.SZ', '510300.SS', '510500.SS'] p = try_day(path="D:/", codes=codes, time='2019-12-31') # p.get_all_data() p.the_main() 作者:Alivorth
分享到:
收藏