python之股票小工具开发学习

一个简单粗糙的python写的显示股票k线和买卖点的小工具。

用了新浪的源,主要是学习python的编程。

本软件仅供学习交流,任何问题与本人无关,特此声明。侵删。

用到的知识点:

1、requests模块获取http网页信息

2、matplotlib画图,包括mpl_finance画k线,pyplot画界面,widgets添加小工具

 

代码:

1、

import requests
import os
import re

import datetime
import matplotlib.dates as mdates
import matplotlib.pyplot as plt
import matplotlib
from matplotlib.widgets import Button
from matplotlib.widgets import TextBox
from matplotlib.widgets import RadioButtons
import pandas as pd
from matplotlib.dates import MONDAY, DateFormatter, DayLocator, WeekdayLocator

from mpl_finance import candlestick_ohlc 

导入用到的模块

2、

#import zh font
zhfont = matplotlib.font_manager.FontProperties(fname='./fonts/msyh.ttf')

#global var
get_str=''
stock_code=''
data_path='./data/'
fig, ax = plt.subplots()

zhfont是导入自定义的字体文件,matplot不支持中文,导入后可以指定字体属性来显示中文。其他的是全局变量,在后边的函数中会用到。get_str保存从文本框得到的字符串,stock_code保存股票代码字符串,data_path保存数据文件夹的路径,fig和ax是subplots的返回值。

3、

def get_stock_name(stock_code):
	if stock_code=='':
		return
	url='http://hq.sinajs.cn/list={}'.format(stock_code)
	req = requests.request('GET',url)
	str1=req.text.split('="',1)[1]
	if len(str1)<5:
		print('get stock details failed')
		return
	str1=str1.split(',')[0]
	print ('get stock name:'+str1)
	return str1

此函数获取股票的名称,requests会返回类似下图的信息,=“后第一个,前是股票名称,提取出来返回。如果没有对应的名称,引号内为空,所以通过判断第一次分割后第二个字符串的长度可以确定是否返回成功。

4、

def get_stock_data(stock_code,scale=240,datalen=30,mode='w',header=True):
	dic={}
	if stock_code=='':
		return False
	url='http://money.finance.sina.com.cn/quotes_service/api/json_v2.php/CN_MarketData.getKLineData?symbol={}&scale={}&datalen={}'.format(stock_code,scale,datalen)
	print (url)
	req = requests.request('GET',url)
	if req.text == 'null':
		print('get stock data failed')
		return False
	strlist=req.text.replace('[{','')
	strlist=strlist.replace('}]','')
	strlist=strlist.split('},{')  
	for strl in strlist:
		str1=strl.split(',')
		for s in str1:
			t=s.split(':',1)
			if 	t[0] in dic:
				dic[t[0]].append(t[1].replace('"',''))
			else:
				dic[t[0]]=[t[1].replace('"','')]
	df = pd.DataFrame(dic)
	#print (df)
	df.to_csv(data_path+'{}.csv'.format(stock_code),mode=mode,index=False,header=header)
	print ('write data to file')
	return True

此函数获取指定股票、指定条数、指定间隔的信息,返回如下信息,这些信息都是字符串,需要做进一步处理,先去掉首尾的[{和}],再按照},{分割,子串再按照,分割,最后按照:分割将结果存在字典中。

通过pd.DataFrame()函数将字典转换为2维数组,调用to_csv()写入到csv格式的文件中。

5、

def write_buy_sell_to_file(string):
	if string =='':
		return
	dic={'day':'','buy':'','sell':''}
	str1=re.split(',| ',string)
	for stri in str1:
		if stri=='':
			continue
		if stri[0]=='d':
			dic['day']=stri.replace('d','')
		elif stri[0]=='b':
			dic['buy']=stri.replace('b','')
		elif stri[0]=='s':
			dic['sell']=stri.replace('s','')
		else:
			print ('input error')
			return
	if dic['day']=='':
		dic['day']=datetime.datetime.now().strftime('%Y-%m-%d')
	print (dic)
	df = pd.DataFrame(dic,index=[0])
	if os.path.exists(data_path+'{}-bs.csv'.format(stock_code)):
		df.to_csv(data_path+'{}-bs.csv'.format(stock_code),mode='a',index=False,header=False)
	else:
		df.to_csv(data_path+'{}-bs.csv'.format(stock_code),mode='w',index=False)

此函数用来记录买卖点到另一个csv文件中,三个item分别是日期day、买入价buy和卖出价sell。在输入时需要加标识符d、b、s表明是什么数据,同时用空格或者逗号分割,日期的格式是xxxx-xx-xx(年-月-日)。写入文件时判断文件是否已经存在,如果存在就追加,不存在就新建。

6、

def get_data_and_display(stock_code,startdate=(datetime.date.today()-datetime.timedelta(1)).strftime('%Y-%m-%d'),datalen=60):
	global ax
	if stock_code=='':
		return
	if not os.path.exists(data_path+'{}.csv'.format(stock_code)):
		print ('not exists')
		if not get_stock_data(stock_code,datalen=60):
			return
	# plot_day_summary(ax, quotes, ticksize=3)
	print ('read scv {}'.format(stock_code))
	ax.cla()
	ax.set_title(get_stock_name(stock_code),fontproperties=zhfont)
	ax.xaxis.set_major_locator(mondays)
	ax.xaxis.set_minor_locator(alldays)
	ax.xaxis.set_major_formatter(weekFormatter)
	ax.xaxis_date()
	ax.autoscale_view()
	if os.path.exists(data_path+'{}-bs.csv'.format(stock_code)):
		bs = pd.read_csv(data_path+'{}-bs.csv'.format(stock_code),index_col=0,parse_dates=True,infer_datetime_format=True)
		ax.plot(mdates.date2num(bs.index.to_pydatetime()),bs['buy'],'mo')
		ax.plot(mdates.date2num(bs.index.to_pydatetime()),bs['sell'],'c^')
	if os.path.exists(data_path+'{}.csv'.format(stock_code)):
		print ('get csv data')
		quotes = pd.read_csv(data_path+'{}.csv'.format(stock_code),index_col=0,parse_dates=True,infer_datetime_format=True)
		cutlen=len(quotes)
		print('{} {}'.format(quotes.last_valid_index(),startdate))
		quotes = quotes[quotes.index <= startdate]
		cutlen-=len(quotes)
		if (quotes.last_valid_index().strftime('%Y-%m-%d')<startdate or len(quotes)<datalen):
			get_stock_data(stock_code,datalen=datalen+cutlen)
			quotes = pd.read_csv(data_path+'{}.csv'.format(stock_code),index_col=0,parse_dates=True,infer_datetime_format=True)
			quotes = quotes[quotes.index <= startdate]
		#print (quotes.at_time('2019-06-20'))
		quotes = quotes.tail(datalen)
		print(quotes)
		ax.plot(mdates.date2num(quotes.index.to_pydatetime()),quotes['ma_price5'],'k-')
		ax.plot(mdates.date2num(quotes.index.to_pydatetime()),quotes['ma_price10'],'m-')
		ax.plot(mdates.date2num(quotes.index.to_pydatetime()),quotes['ma_price30'],'b-')
		candlestick_ohlc(ax, zip(mdates.date2num(quotes.index.to_pydatetime()),
				                 quotes['open'], quotes['high'],
				                 quotes['low'], quotes['close']),
				         width=0.6,colorup='r', colordown='g')
	else:
		raise

该函数获取数据并显示k线图。首选判断文件是否存在,不存在说明是第一次显示这个股票,需要获取数据。之后清除显示准备新的数据,先读取买卖信息,显示买卖点。再读取股票数据信息,需要判断读取到的信息是不是最新的,数据长度够不够。如果从一个旧的时间点读取很可能数据不够,需要从新拉取数据。得到最终需要的数据后显示5日线、10日线和30日线,最后显示k线。

7、

#button
def bdspl_handle(event):
	global stock_code
	lens=60
	date1=(datetime.date.today()-datetime.timedelta(1)).strftime('%Y-%m-%d')
	str1=re.split(',| ',get_str)
	for stri in str1:
		if stri[0:2]=='sh' or stri[0:2]=='sz':
			stock_code=stri
			get_data_and_display(stock_code)
		elif stri[0:3]=='len':			
			lens=int(stri[3:])
		elif stri[0:4]=='date':
			date1=stri[4:]
		else:
			print ('input error')
			return
	get_data_and_display(stock_code,date1,lens)

显示按钮回调函数

8、

def b_s_handle(event):
	print ('buy-sell')
	write_buy_sell_to_file(get_str)
	get_data_and_display(stock_code)

从文本框获取信息并写入到文件中然后显示。

9、

###text###
def submit(text):
	global get_str
	get_str=text

获取文本框信息

10、

if __name__=='__main__':
	if not os.path.exists(data_path): 
		os.makedirs(data_path)
	if not os.path.exists('setup.txt'): 
		os.mknod('setup.txt')
	f=open('setup.txt','r')
	stock_code=f.readline().strip('\n')
	f.close()

		
	axdspl = plt.axes([0.81, 0.05, 0.1, 0.075])
	bdspl = Button(axdspl, 'stock')
	bdspl.on_clicked(bdspl_handle)
	
	axb_s = plt.axes([0.7, 0.05, 0.1, 0.075])
	bb_s = Button(axb_s, 'buy-sell')
	bb_s.on_clicked(b_s_handle)
		
	axbox = plt.axes([0.1, 0.05, 0.2, 0.075])
	text_box = TextBox(axbox, 'input', initial='')
	text_box.on_submit(submit)
	
	mondays = WeekdayLocator(MONDAY)        # major ticks on the mondays
	alldays = DayLocator()              # minor ticks on the days
	weekFormatter = DateFormatter('%b %d')  # e.g., Jan 12
	dayFormatter = DateFormatter('%d')      # e.g., 12

	# select desired range of dates
	#quotes = quotes[(quotes.index >= date1) & (quotes.index <= date2)]
	fig.subplots_adjust(bottom=0.2)
	#fig.subplots_adjust(left=0.2)

	#display the one last software close 
	get_data_and_display(stock_code)

	plt.setp(plt.gca().get_xticklabels(), rotation=45, horizontalalignment='right')

	plt.show()      

	print ('save setup')
	f=open('setup.txt','w')
	print (stock_code)
	f.write(stock_code)
	f.close()

main函数,先读取配置文件,此处只是保存了上次关闭软件前显示的股票代码。创建按钮和文本框,显示图表,显示是block的。关闭软件后将当前股票代码写入文件中。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值