当前位置: 首页 > 科技观察

用Python做了一个“守望机器人”,可以邮件通知!

时间:2023-03-19 20:56:14 科技观察

前言Python以其高开发效率和强大的特性,在众多编程语言中脱颖而出,成为大数据时代的分析利器。根据我多年的理解,编程语言只是一种按照人的意图实现特定功能的高效工具。通过编程实现的核心决策功能仍然需要人工智能的支持。在量化投资和交易领域,投资人认为什么交易逻辑非常重要。俗话说,重剑无锋,高手不灵(真正的剑术不靠剑锋,靠的是亲身实践,投资也是如此,投资人的素质才是最重要的)important),所以8020%的时间和精力都投入到了编程实现上。即将踏上量化投资交易的小伙伴们,要想做好本职工作,必先利其器。将Python作为量化投资交易的首选语言无疑是最明智的。余生短暂,请跟我一起用python!在量化交易方面,很多人应该都向往通过计算机程序自动实现股票跟踪,寻找买卖信号。但九层台起于堆土,千里之行始于足下。只有打好基础,一个一个突破每个知识点,综合运用,才能构建自己完整的量化交易体系。今天,我将从最基本的量化交易入门知识开始。通过Python程序,我将编写一个实时跟踪股票价格的机器人。当股价触发一定的上涨条件时,它会自动向投资者发送邮件或短信。这个场景可以适用于平时喜欢炒股但又没有时间关注市场的投资者。通过本文的学习,读者可以掌握获取证券(包括股票和基金)实时行情、发送邮件、定时运行程序、将程序打包成exe文件等知识点。凝视机器人工作流程图及效果图为了让读者从全局的角度理解整个程序运行的逻辑,特绘制流程图如下。一、程序工作流程图二、股价监控效果例如:2021年7月19日,监控标的股票三峡能源(证券交易所代码:600905)由于价格涨跌达到监控自动触发邮件某点位提醒,通过邮件告知投资者当前价格、涨跌幅、盈亏等数据。效果如下图所示。代码实现一、需要安装的第三方库及简介这里首先介绍一下本文需要用到的一些Python库。Tushare:一个免费开源的Python金融数据接口包,通过库的get_realtime_quotes(code)方法(code是目标证券的交易代码,包括股票和ETF基金的交易代码),可以返回当前行情的股票和成交信息,返回值的数据类型为DataFrame,DataFrame包括name(证券名称),open(今日开盘价),pre_close(昨日收盘价),price(现价)...time(时间)等,根据这个要求,只需要一些维度。对于其他维度,读者可以通过print()打印查看所有维度信息。pandas:数据分析的核心库。因为调用Tushare库的get_realtime_quotes(code)方法返回DataFrame数据类型,所以需要库对返回的数据进行操作。时间表:在证券交易系统中,有交易时间和收市时间。要实现程序的正常运行,这个库是必不可少的。具体参见程序部分库的使用介绍。smtplib:这个库主要实现邮件的发送。sys:交易日15:00后休市。为避免资源浪费,可以调用sys.exit()方法自动退出程序。pyinstaller:利用该库将程序打包成可执行的exe格式文件,方便程序运行。上面需要的第三方库可以使用pip命令安装。2.程序代码实现①编写获取当前证券价格信息的方法defget_now_jiaage(code):df=ts.get_realtime_quotes(code)[['name','price','pre_close','date','time']]returndf其中参数code为目标股票的交易代码,例如“三峡能源”股票的交易代码为“600905”。调用Tushare的get_realtime_quotes('600905')方法返回一个DataFrame类型的数据。根据功能需求,我们只需要获取name(股票名称)、price(当前价格)、pre_close(昨日收盘价)、date(价格对应的日期)和time(价格对应的时间)就足够了。写完这个方法,高手需要将目标股票的交易码传给get_now_jiage方法,获取需要的数据。②写一个判断是否在交易时间段内的方法。每个交易日,股票交易时间为09:30-11:30、13:00-15:00,程序在早上9:30开始监控,可以通过schedule实现(后面解释),11:30-13:00中午休市期间,为避免资源浪费,无需调用Tushare接口的数据。这个时间段可以称为暂停交易时间。判断交易时段是否暂停的方法写法如下:defpd_ztjytime():#判断是否是交易时段now_time=datetime.datetime.now().strftime('%Y-%m-%d%H:%M:%S')now_datetime=datetime.datetime.strptime(now_time,'%Y-%m-%d%H:%M:%S')d1=datetime.datetime.strptime(datetime.datetime.now().strftime('%Y-%m-%d')+'11:30:01','%Y-%m-%d%H:%M:%S')d2=datetime.datetime.strptime(datetime.datetime.now().strftime('%Y-%m-%d')+'13:00:00','%Y-%m-%d%H:%M:%S')delta1=(now_datetime-d1).total_seconds()delta2=(d2-now_datetime).total_seconds()ifdelta1>0anddelta2>0:#在挂起事务时间内returnTrue#在挂起事务时间范围内,返回Trueelse:returnFalse#Not在暂停交易的时间范围内,返回False③编写监控股价的主要运行程序。本模块作为股价监控、计算涨跌幅、判断是否发送通知的核心程序。为了配合早上9:30定时运行程序的模块,这个模块写成了一个独立的方法,完整的程序如下:defdo_programe(code):ifpd_ztjytime()==False:#判断是否在暂停交易时限内info=get_now_jiaage(code)#调用方法获取当前DataFramenow_jiaage=float(info['price'][0])#获取当前价格name=info['name'][0]#获取股票名称pre_close=float(info['pre_close'][0])#获取昨日收盘价riqi=info['date'][0]#获取当前价格对应的日期sj=info['time'][0]#获取价格对应的时间now_zdie=round((now_jiaage-pre_close)/pre_close*100,2)#计算当前涨跌幅all_zdie=round((now_jiaage-cbj)/cbj*100,2)#计算持股期间的总涨跌幅,其中cbj为时间ofpurchase成本价需要约定全局变量now_shizhi=round(shuliang*now_jiaage,2)#计算股票当前市值,其中shuliang为买入股票数量,需要约定为全局变量ykui=round(now_shizhi-cbj*shuliang,2)#计算股票总盈亏if(abs(now_zdie)>=3andabs(now_zdie)<3.09)or(abs(now_zdie)>=6andabs(now_zdie)<6.05)or(abs(now_zdie)>=9andabs(now_zdie)<9.1):#判断当前价格区间是否在目标区间内email_comment=[]email_comment.append('')email_comment.append('

您好:

')email_comment.append('

根据设置的参数,现在上报'+name+'('+str(code)+')如下:

')email_comment.append('')email_comment.append('')email_comment.append('序列号')email_comment.append('购买单价<')email_comment.append('分享数')email_comment.append('当前价格<')email_comment.append('当前涨跌幅')email_comment.append('总变化')email_comment.append('当前市值')email_comment.append('盈亏')email_comment.append('交易时间')电子邮件_评论。append('')email_comment.append('')email_comment.append(''+str(1)+'</td>')email_comment.append(''+str(cbj)+'')email_comment.append(''+str(shuliang)+'')email_comment.append(''+str(now_jiage)+'')email_comment.append(''+str(now_zdie)+'%')email_comment.append(''+str(all_zdie)+'%')email_comment.append(''+str(now_shizhi)+'元')email_comment.append(''+str(ykui)+'元')email_comment.append(''+str(riqi)+''+str(sj)+'')email_comment.append('')email_comment.append('')email_comment.append('

祝:股市天天红,天天发财!

')email_comment.append('')send_msg='\n'.join(email_comment)send_Email(email_add[0],send_msg)上述程序中判断是否发送通知的判断语句为:if(abs(now_zdie)>=3andabs(now_zdie)<3.1)or(abs(now_zdie)>=6andabs(now_zdie)<6.1)or(abs(now_zdie)>=9andabs(now_zdie)<9.1)以上if判断语句表示当前涨跌幅的绝对值在3%(含)到3.1%之间(不包括)(使用绝对值可以同时考虑涨跌幅度),或介于6%(含)至6.1%(不含)之间,或介于9%(含)至9.1%(不含)之间,将通过电子邮件发送通知,价格波动的特定触发参数。读者可以自行修改发送邮件的关键程序:send_Email(email_add[0],send_msg)其中email_add是一个列表的形式,可以存储多个接收通知的邮件地址。本例中,只设置了一个收件地址,全局变量email_add=['...'],所以获取这个地址的程序是email_add[0]。send_msg是要发送的邮件内容,使用列表email_comment添加邮件内容。这里发的邮件格式是html格式,是为了方便画表格用的。html文件的开头应该是,结尾应该是成对的,其中画表格的标签是和成对的
,表格行的标签是,该列的标签是。发送邮件send_Email方法的流程如下:defsend_Email(Email_address,email_text):from_addr='*****'#发送邮件地址password='*****'#发送邮件密码title='stockPricechange监听消息-'+datetime.datetime.now().strftime('%Y-%m-%d%H:%M:%S')#Emailtitlemsg=MIMEText(email_text,'html','utf-8')#邮件格式为HTMLmsg['From']=from_addrmsg['To']=Email_addressmsg['Subject']=titletry:server=smtplib.SMTP_SSL('smtp.qq.com',465)server.login(from_addr,password)#发送邮件server.send_message(msg)server.quit()#print(Email_address+'sendsuccess!')#send_info.append(Email_address+'sendsuccess!\n')exceptExceptionase:a+1#print(e)#send_info.append(e+'\n')#send_info.append(Email_address+'sendfailed!\n')#print(Email_address+'sendfailed!')from_addr是发件人邮箱,password是发件人的授权码,需要根据实际情况修改填写。另外,程序中:server=smtplib.SMTP_SSL('smtp.qq.com',465)是选择QQ邮箱的SMTP服务器地址smtp.qq.com,默认端口是465。如果是另一个邮箱,应该对应修改服务器和端口号。如何获取发件人的授权码?以QQ邮箱为例:第一步:登录QQ邮箱,点击顶部的“设置”链接,然后点击“账户”选项卡,如下图。第二步:在“账户”选项卡中向下滚动,直到看到下图所示的选项,点击“POP3/SMTP服务”右侧的“启用”链接,如下图。第三步:点击“打开”链接后,会有一个验证密码的过程。根据页面提示,向指定号码发送指定内容的手机短信。发送完成后,点击页面上的“我已发送”按钮,会弹出一个框,里面有SMTP授权码。复制并存储它。以后打电话方便。④编写调用do_programe(code)的监控程序为了实现主程序的调用,编写run()方法如下:defrun():whileTrue:do_programe('600905')now_time=datetime.datetime.now().strftime('%Y-%m-%d%H:%M:%S')d1=datetime.datetime.strptime(now_time,'%Y-%m-%d%H:%M:%S')d2=datetime.datetime.strptime(datetime.datetime.now().strftime('%Y-%m-%d')+'15:00:00','%Y-%m-%d%H:%M:%S')delta=d2-d1ifdelta.total_seconds()<=0:sys.exit()time.sleep(1)⑤按顺序编写每天9:30开始监控的主程序实现每个交易日的交易时间点击开始监控,需要的程序如下:if__name__=='__main__':schedule.every().day.at("09:30").do(run)whileTrue:schedule.run_pending()time.sleep(1)⑥程序打包及自动运行程序编写完成后,需要将程序以打包的形式转为exe格式。该格式的程序可以点击或设置为自动运行。打包好的库是pyinstaller,使用命令pyinstaller-w-F程序路径\程序名.py即可。其中-w表示生成的exe文件运行时不会出现黑色的DOS界面,我们只需要程序在后台“安静”运行即可。为了实现程序在开机时自动运行,可以将生成的exe文件复制到windwos系统的Startup文件夹中,点击windows的开始菜单-所有程序,找到“启动”或“启动”"文件夹,并将exe文件复制到该文件夹??下,电脑每次开机即可自动运行监控程序。由于程序不显示任何界面,为了检查程序是否运行,可以使用快捷键“CtrlAltDelete”打开任务管理器,在进程中可以看到“StockMonitor.exe”(这里的文件名是作者更改的文件名)表示程序正在被监控。展望一下,本程序只是一个设置股票的案例,作为一个简单的功能实现,还有改进的余地,下面说明。一是在实践中,往往会建立一个股票池(几只股票)来动态监控股价并自动判断交易时间点(如MACD、均线、KDJ指标等),而且往往需要结合数据库便于灵活构建股票池的技术。二、本文不介绍发送短信功能,只介绍email。其实短信通知的思路和邮件是一样的。如果想免费发短信,可以在twilio官网(https://www.twilio.com)注册,调用相应的功能,在线搜索即可。三是关于途享数据接口。本文使用的是途享的老接口API。目前官方主要维护的是TusharePro界面。业界良心之作,TusharePro,详见https://waditu.com/document/2。四是其他商业量化接口。可以推荐聚宽量化接口。有半年左右的免费试用期,但过了免费期后,仍然会有几千元的月费。读者可选择使用聚宽网站https://www.joinquant.com/view/community/list?listType=1。五是关于爬虫获取证券交易数据。目前,证券交易数据较为丰富的网站有东方财富、同花顺、新浪财经、和讯网等。也可以通过爬虫获取相应的数据,但需要注意的是,本文中每个交易日每秒调用一次API。如果是用爬虫来实现,就不太理想了,因为过于频繁的调用可能会触发网站的反爬虫机制。六、将程序设置为自动启动并在本地计算机上运行。程序不断优化和功能增加后,有兴趣的读者可以了解购买云服务器部署监控程序。