在云服务器上部署监控股市脚本

  1. 一.准备
  2. 二.部署
  3. 三.代码

注意:代码有问题,还未解决

一.准备

  1. 自己打好SendMail.py脚本和monitor2.py脚本,前者是发送邮件脚本,后者是监控目标股票是否达到止盈点或者止损点(可以为股价例如25.44也可以是幅度例如0.2),还有监控大盘(每上涨/下跌50点)发送一次报告邮件。

  2. 因为云服务器上有多个版本的python和pip,所以这里有点疑惑,但是经查发现,使用python3执行脚本的话,只能导入利用pip3命令安装的包。

  3. tushare需要python3版本,所以用pip3版本安装包(另外不知道为什么pip命令失效,安装不了包)。

  4. 需要安装以下包:

    pip3 install tushare
    pip3 install numpy
    pip3 install pandas
    pip3 install apscheduler
    

    代码所需的bs4和smptlib,前者是tushare的依赖,后者python自带。

  5. pip3 list可以查看已经安装的依赖包,’pip3 show 包名’可以查看安装的包的位置

二.部署

执行
nohup python3 monitor2.py &
查看结果

image-20211001232407536

三.代码

SendMail.py代码:

import smtplib
from email.mime.text import MIMEText
from email.header import Header
import time
#This file is target to send a mail to target mail.
def sendMail(body):
    sender = 'xxxx@163.com'     #发送者邮箱
    receiver = 'xxx@126.com'    #接收者邮箱
    subject = '金融播报'         #主题
    smtpserver = 'smtp.163.com'
    username = 'xxxxx@163.com'  #用户名
    password = 'xxxxx'          #密码

    msg = MIMEText(body,'plain','utf-8') #中文需参数‘utf-8',单字节字符不需要  
    msg['Subject'] = Header(subject, 'utf-8')  
    msg['From'] = '闫同学<why_three@163.com>'    
    msg['To'] = receiver  
    #腾讯云服务器25端口禁用,所以必须使用SSL连接和465端口
    smtp = smtplib.SMTP_SSL('smtp.163.com',465)  
    smtp.login(username, password)  
    smtp.sendmail(sender, receiver, msg.as_string())  
    smtp.quit()

monitor2.py:

import tushare as ts
import numpy as np
import time
import pandas as pd
#获取上证实时指数自行爬取所需依赖包
from urllib.request import urlopen
from bs4 import BeautifulSoup  
#定时任务
from datetime import datetime
from datetime import date
from apscheduler.schedulers.background import BackgroundScheduler
from apscheduler.schedulers.blocking import BlockingScheduler
from SendMail import *

stocks = []
#股票代号,股票名称,成本,止盈点(可以为目标价位或者是比例,比如35.000或者0.1),止损点(止损价位或者止损比例)
stocks.append(['002389','航天彩虹', 33.476, 31.050, 28.000])   
stocks.append(['601989','中国重工', 4.035, 5.100, 0.2])
stocks.append(['600150','中国船舶', 17.977, 19.000,17.300])
stocks_codes = [x[0] for x in stocks]   #只能用列表解析的方式读取第一列,而np数组可以用slip
df_data = ts.get_realtime_quotes(stocks_codes)   #得到二维股票信息

#以interval分钟监控stocks,若达到止盈/止损点,则发邮件
def notice_by_price(stocks, interval=10):
    if_notice = 1       #是否允许通知
    if_send = 0         #是否发送过邮件
    body = "股价检测情况如下:\n"
    old_body = body
    while(if_notice):
        for stock in stocks:
            info = df_data.loc[df_data['code'] == stock[0]]

            now_price = info['price'].iat[0]    #现在的价位
            target_up_price = stock[-2] if stock[-2]>1 else stock[2]*(1+stock[-2])  #如果目标价位为价格的话复制,否则乘以涨跌幅再赋值
            target_down_price = stock[-1] if stock[-1]>1 else stock[2]-(stock[2]*stock[-1])    #止损价位
            target_up_price = format(target_up_price,'.3f')     #保留三位
            target_down_price = format(target_down_price, '.3f')

            new_notice = stock[1]+":"+"成本:"+str(stock[2])+",现价:"+str(now_price)
            new_notice+= ",止盈价:"+target_up_price
            if now_price >= target_up_price:
                new_notice += "已达到"
            new_notice+= ",止损价:"+target_down_price
            if now_price <= target_down_price:
                new_notice += "已达到"
            body += new_notice + "\n"
        if (body != old_body):          #如果新消息不等于旧消息,得通知一次
            if_send = 1
        if (if_send):                   #用if_send解耦一下,说不定以后添加什么新功能
            sendMail(body)
            if_send = 0
        old_body = body                 #旧消息等于新消息
        body = "股价检测情况如下:\n"     #消息初始格式
        time.sleep(interval*60)

#返回上证实时指数
def get_sh_now():
    url = "https://gu.qq.com/sh000001/zs"
    html = urlopen(url).read()
    soup = BeautifulSoup(html,'html.parser')
    #soup的css寻找需要在后面加下划线,因为class在python中是官方保留字
    sh = soup.find(class_="data").get_text()
    return sh

#监控上证指数,每interval点发送一次邮件,interval必须为5的整数倍,因为大盘点数是小数连续的,而我们只关注
#每interval点的大盘,所以将大盘指数除以interval映射成一个0-100的整数,用于下标
#每inter_time小时监控一次大盘,若间隔过大,比如3小时,可能出现暴涨100点,中间的50点不通知只通知100点
#若间隔过小,可能大盘在盯盘点半小时内反复横跳的话会多次通知
def notice_sh(interval = 50, inter_time = 1):
    #初始化
    monitor_bit = [0]*int(10000/interval)             #监控大盘10000点一下,每变化interval点发送一次提醒邮件
    init_sh = int(float(get_sh_now())/interval)                #执行脚本当天的初始大盘点数对应的整数
    for i in range(init_sh+1):
        monitor_bit[i] = 1
    times = 8    #每天执行7次,9点开始执行,整点查询一次,下午15:00结束阻塞等待18个小时候继续执行
    while(times):
        times = times-1
        print("times="+str(times))
        body = ""
        real_sh = 3601#float(get_sh_now())       #上证指数
        new_sh = int(real_sh/interval)      #循环执行时请求最新的上证点数对应的整数,并且字符串需要先转float再转int
        if monitor_bit[new_sh] == 1 and monitor_bit[new_sh+1] == 1:     #python逻辑运算符为and、or、not
            #当前大盘处于new_sh和new_sh之间且两边为(1,1)(即大盘从new_sh+1跌下来了)
            if_send = 1
            monitor_bit[new_sh+1]=0
            body = "上证指数已下跌至"+str((new_sh+1) * interval)+"以下"
        elif monitor_bit[new_sh] == 0 and monitor_bit[new_sh+1] == 0:   #python没有else if,只有elif
            #当前大盘处于new_sh和new_sh之间且两边为(0,0)(即大盘涨到new_sh以上了)
            if_send = 1
            monitor_bit[new_sh] = 1
            body = "上证指数已上涨至"+str((new_sh) * interval)+"以上"
        elif monitor_bit[new_sh] == 0 and monitor_bit[new_sh+1] == 1:
            #(new_sh,new_sh+1)=(0,1),这种情况时说明大盘暴在0.5小时内暴涨了50点之后又跌下到new_sh+1了
            if_send = 1
            monitor_bit[new_sh] = 1
            monitor_bit[new_sh+1] = 0
            body = "上证指数已下跌至"+str((new_sh+1) * interval)+"以下"
        else:
            #不通知情况即为(new_sh,new_sh+1)=(1,0)即达到new_sh并且通知过了
            if_send = 0
            pass
        body += ",现在上证指数为:"+str(real_sh)
        if (if_send):
            print(body)

        if (times != 0):
            time.sleep(1*60*60)     #time!=0即在9:00——15:00,休眠一小时
        else:
            time.sleep(18*60*60)    #time==0即盯盘结束,在15:00——9:00休息18个小时继续盯盘
            times = 8
#返回上证实时指数
def get_sh_now():
    url = "https://gu.qq.com/sh000001/zs"
    html = urlopen(url).read()
    soup = BeautifulSoup(html,'html.parser')
    #soup的css寻找需要在后面加下划线,因为class在python中是官方保留字
    sh = soup.find(class_="data").get_text()
    return sh

#APSscheduler有两种调度器,一种时BackgroundScheduler,一种是BlockingScheduler,而如果应用前者的话,
#定时任务会在后台运行,不会阻塞主线程,而我们的程序如果只盯大盘的话,主线程不执行其它程序,所以直接就结束
#线程了,因此定时任务不会执行,而使用BlockingScheduler的话会避免这种情况产生,但是有一个缺点就是不能用ctrl+c
#停止,只能手动杀死进程。
#参考链接https://blog.csdn.net/ybdesire/article/details/82228840#:~:text=%E9%82%A3%E4%BB%96%E4%BB%AC%E4%B9%8B%E9%97%B4%E6%9C%89,%E8%80%8C%20BackgroundScheduler%20%E4%B8%8D%E4%BC%9A%E9%98%BB%E5%A1%9E%E3%80%82&text=BlockingScheduler%20%3A%20%E8%B0%83%E7%94%A8start%E5%87%BD%E6%95%B0%E5%90%8E,%E6%97%B6%EF%BC%88%E5%A6%82%E4%B8%8A%E4%BE%8B%EF%BC%89%E4%BD%BF%E7%94%A8%E3%80%82
scheduler =BlockingScheduler()
#从1月19日开始执行监控大盘程序
job1 = scheduler.add_job(notice_sh, 'date', run_date='2021-01-19 09:00:00')
job2 = scheduler.add_job(notice_by_price, "date", run_date='2021-01-19 09:00:00',args=[stocks,0.5])
#周内媒体那9.30开始执行盯盘股票程序
#job2 = scheduler.add_job(notice_by_price, "cron",week="1-53",day_of_week="0-5",hour="9",minute="30",args=[stocks,0.5])
scheduler.start()   

欢迎在评论区中进行批评指正,转载请注明来源,如涉及侵权,请联系作者删除。

×

喜欢就点赞,疼爱就打赏