天天看點

用python實時監控A股股票的波動并發送預警郵件

這幾天對量化交易頗感興趣,是以就鼓搗了一下,網上搜尋一波發現,Tushare是一個開源的股票資訊來源,可以輕松地擷取股票資訊,Tushare首頁:http://tushare.org/ ,目前主要是通過Tushare的實時分筆來擷取目前時間的股票資訊,主要是用來實時監控特定股票出現日内暴跌和日内較開盤價大幅下跌,後期還會添加更多内容。廢話不多說,直接上代碼。

import tushare as ts#導入tushare子產品
import datetime
import time
#導入純文字郵件發送子產品
import my_email as me
#實時監測函數,code為6位數字代碼字元串組成的數組,監測在10分鐘内跌幅大于5%和實時跌幅較開盤價大于10%時,發送郵件通知
#time_mins為跌速時間,change_mins_max為跌速深度,change_max為較開盤跌幅
def monitor(code,time_mins = 10,change_mins_max = 5,change_max = 10):
    data_today = []#儲存采集回來的資料
    n = 1#記錄從循環次數
    while 1:
        try:
            now_time = datetime.datetime.strptime(datetime.datetime.strftime(datetime.datetime.now(),'%H:%M:%S'),'%H:%M:%S')
            #now_time為記錄目前時間,由于從Tushare取回的實時分筆資料隻有時間,
            #沒有日期,是以用上面的操作把現在的時間的日期換成1900:1:1日,友善計算時間差
            rest_time = now_time - datetime.datetime.strptime('11:30:00','%H:%M:%S')
            #用來計算目前時間和中午11:30休市時間的內插補點
            if rest_time.days == 0 and rest_time.seconds > 0 and rest_time.seconds < 5400:
                #中午11:30~13:00為中午休市時間,時長5400 seconds
                print('中午休市時間')
                while rest_time.days == 0 and rest_time.seconds > 0 and rest_time.seconds < 5400:
                    now_time = datetime.datetime.strptime(datetime.datetime.strftime(datetime.datetime.now(),'%H:%M:%S'),'%H:%M:%S')
                    rest_time = now_time - datetime.datetime.strptime('11:30:00','%H:%M:%S')
                    time.sleep(2)
                    #time sleep 2秒,循環等待中午休市時間的結束
            if rest_time.days == 0 and rest_time.seconds > 12600:
                #下午15:00結束交易,與11:30的時間差為12600 seconds,關閉程式
                print('交易時間已結束!')
                break
            flag = 0#旗幟,flag==1則說明出現預警
            print('第%s次抓取資料'%n)
            n = n + 1#每循環一次 ,n + 1
            change_max = change_max
            realtime_qutoes = ts.get_realtime_quotes(code)#從tushare采集實時分筆資料
            last_time = datetime.datetime.strptime(realtime_qutoes.loc[0][31],'%H:%M:%S')
            #last_time記錄從Tushare得到資料裡的時間,realtime_qutoes.loc[0][31]為時間,存儲格式為字元串'%H:%M:%S'
            if (last_time - now_time).days == 0 and (last_time - now_time).seconds > 10:
                #如果從realtime_qutoes得到的時間大于目前實際時間,那麼說明,目前市場未在交易,
                #得到的資料為上一交易日最後一筆交易資料,為避免交易所時間和本地時間不一緻,設定10 seconds誤差
                print('今天不是交易日或者未到交易時間!')
                break
            print('資料抓取成功!')
            data_today.insert(0,realtime_qutoes)#儲存入數組
            if len(data_today) > 100*time_mins:
                for i in range(0,60*time_mins):
                    #為了避免data_day數組過長,增加記憶體占用,是以當長度大于一定程度時,删除一部分
                    del data_today[len(data_today) - 1]
            if len(data_today) > 30*time_mins:
                #隻需要對應時長的數組
                time_len = 30*time_mins
            else:
                time_len = len(data_today)
                #如果股票剛開始交易,分筆資料沒有那麼多,就全部作為需要的使用
            for i in range(0,len(code)):
                if (float(data_today[0].loc[i][2]) - float(data_today[time_len-1].loc[i][2])) < -1*change_mins_max:
                    #短時間下跌幅的确定
                    flag = 1#改變旗幟的值
                    text_add = '%s 分鐘跌幅超%s%%'%(time_mins,change_mins_max)
                    #text_add作為郵件提醒的部分文本,當一隻股票達到預警值時,結束繼續查找其它股票情況,立即發送郵件提醒
                    break
                if (float(data_today[0].loc[i][2]) - float(data_today[time_len-1].loc[i][2])) > change_mins_max:
                    #短時間上漲幅的确定
                    flag = 1#改變旗幟的值
                    text_add = '%s 分鐘漲幅超%s%%'%(time_mins,change_mins_max)
                    #text_add作為郵件提醒的部分文本,當一隻股票達到預警值時,結束繼續查找其它股票情況,立即發送郵件提醒
                    break
                if 100*(float(data_today[0].loc[i][3]) - float(data_today[0].loc[i][1]))/float(data_today[0].loc[i][2]) < -1*change_max:
                    change = 100*(float(data_today[0].loc[i][3]) - float(data_today[0].loc[i][1]))/float(data_today[0].loc[i][2])
                    #如果目前股價較開盤價跌幅較大,也發送提醒
                    flag = 1
                    text_add = '較開盤價跌%s %%'%(str(change)[:5])
                    break
                if 100*(float(data_today[0].loc[i][3]) - float(data_today[0].loc[i][1]))/float(data_today[0].loc[i][2]) > change_max:
                    change = 100*(float(data_today[0].loc[i][3]) - float(data_today[0].loc[i][1]))/float(data_today[0].loc[i][2])
                    #如果目前股價較開盤價漲幅較大,也發送提醒
                    flag = 1
                    text_add = '較開盤價漲%s %%'%(str(change)[:5])
                    break
                print(i)
            if flag == 1:
                del code[i]
                #一隻股票達到預警後将該隻股票剔除,代碼數組
                code_text = realtime_qutoes.loc[i][32]
                #股票6位數字代碼
                name = realtime_qutoes.loc[i][0]
                #股票名字
                open_price = realtime_qutoes.loc[i][1]
                #股票開盤價
                now_change = ((float(realtime_qutoes.loc[i][3]) - float(realtime_qutoes.loc[i][2]))/float(realtime_qutoes.loc[i][2]))*100
                #股票目前漲跌幅
                price = realtime_qutoes.loc[i][3]   
                #目前股價
                high = realtime_qutoes.loc[i][4]
                #當日最高價
                low = realtime_qutoes.loc[i][5]
                #當日最低價
                amount = str(float(realtime_qutoes.loc[i][9])/1e8)[:4]
                #當日成交金額,機關億,有效數字為3位
                time_text = realtime_qutoes.loc[i][31] 
                #采集到資料的分筆時間
                text = '%s %s %s 目前漲跌幅%s%% 開盤價%s 目前價格%s 最高價%s 最低價%s 總金額%s億 時間%s' \
                %(code_text,name,text_add,str(now_change)[:5],open_price,price,high,low,amount,time_text)
                #郵件要發送的文本資訊
                me.email(text)
                #發送郵件
                if len(code) == 0:
                #如果代碼數組沒有東西了,就結束程式
                    break
        except Exception as e:
            print('error:',e)
            time.sleep(2)
        time.sleep(2)
        #休息2秒,避免頻繁請求造成各種問題
if __name__ == '__main__':
    code = ['000958','002384','000063','000810','000988']
    monitor(code)