• Akshare 获取日线策略并发送邮件


    import akshare as ak
    import time
    # import datetime
    import numpy as np
    from datetime import datetime, timedelta
    import smtplib
    from email.mime.text import MIMEText
    from email.utils import formataddr
    from email.message import EmailMessage
    import logging
    import os
    
    nowtime = datetime.now()
    
    
    day_nums = 1  # 使用前一天的收盘价数据做信号判断
    stock_num = 1  # 买入评分最高的前stock_num只股票 可以修改
    momentum_day = 20  # 最新动量参考最近momentum_day的
    ref_stock = 'sh000300'  # 用ref_stock做择时计算的基础数据
    N = 18  # 计算最新斜率slope,拟合度r2参考最近N天
    M = 600  # 计算最新标准分zscore,rsrs_score参考最近M天
    score_threshold = 0.7  # rsrs标准分指标阈值
    
    
    
    def get_index_list(index_symbol='sh000068'):
        stocks2 = []
        stocks = ak.index_stock_hist(index_symbol).stock_code
        for stock in stocks[:]:
            if int(stock) < 100000:
                stock = 'sz' + stock
            else:
                stock = 'sh' + stock
            stocks2.append(stock)
        return stocks2
    
    
    stock_pool = get_index_list()
    
    
    # 找到有交易信号的股票,为之后交易进行准备
    
    
    # 动量因子:由收益率动量改为相对MA90均线的乖离动量
    def get_rank(stock_pool):
        rank, biasN = [], 90
        for stock in stock_pool:
            # print(stock)
            from_date = '2010-01-01'
            from_date = datetime.strptime(from_date, "%Y-%m-%d")
            day_nums = 1
            current_dt = time.strftime("%Y-%m-%d", time.localtime())
            current_dt = datetime.strptime(current_dt, '%Y-%m-%d')
            previous_date = current_dt - timedelta(days=day_nums)
            #         data = jq.get_price(stock, end_date=previous_date, count=biasN +
            #                             momentum_day, frequency='daily', fields=['close'])
            try:
                data = ak.stock_zh_a_daily(symbol=stock, start_date=from_date, end_date=previous_date)
            except:
                pass
            # print('2222',data.head())
            bias = np.array((data.close / data.close.rolling(biasN).mean())[-momentum_day:])  # 乖离因子
            #         print(bias)
            #         print(bias[0])
            score = np.polyfit(np.arange(momentum_day), bias / bias[0], 1)[0].real  # 乖离动量拟合
            rank.append([stock, score])
        rank.sort(key=lambda x: x[-1], reverse=True)
        return rank[0]
    
    
    # 线性回归:复现statsmodels的get_OLS函数
    def get_ols(x, y):
        slope, intercept = np.polyfit(x, y, 1)
        r2 = 1 - (sum((y - (slope * x + intercept)) ** 2) / ((len(y) - 1) * np.var(y, ddof=1)))
        return (intercept, slope, r2)
    
    
    def get_zscore(slope_series):
        mean = np.mean(slope_series)
        std = np.std(slope_series)
        return (slope_series[-1] - mean) / std
    
    
    # 择时过程 ----->--------------------------------------------
    def initial_slope_series():
        current_dt = time.strftime("%Y-%m-%d", time.localtime())
        current_dt = datetime.strptime(current_dt, '%Y-%m-%d')
        from_date = '2010-01-01'
        from_date = datetime.strptime(from_date, "%Y-%m-%d")
        previous_date = current_dt - timedelta(days=day_nums)
        data = ak.stock_zh_index_daily(symbol=ref_stock)
        data['date'] = data['date'].apply(lambda x: str(x))
        data['date'] = data['date'].apply(lambda x: datetime.strptime(str(x), '%Y-%m-%d'))
        data = data[(data['date'] >= from_date) & (data['date'] <= previous_date)]
        return [get_ols(data.low[i:i + N], data.high[i:i + N])[1] for i in range(M)]
    
    
    # 只看RSRS因子值作为买入、持有和清仓依据,前版本还加入了移动均线的上行作为条件
    def get_timing_signal(stock):
        current_dt = time.strftime("%Y-%m-%d", time.localtime())
        current_dt = datetime.strptime(current_dt, '%Y-%m-%d')
        previous_date = current_dt - timedelta(days=day_nums)
        from_date = '2010-01-01'
        from_date = datetime.strptime(from_date, "%Y-%m-%d")
        data = ak.stock_zh_index_daily(symbol=ref_stock)
        data['date'] = data['date'].apply(lambda x: str(x))
        data['date'] = data['date'].apply(lambda x: datetime.strptime(x, '%Y-%m-%d'))
        data['date'] = data['date'].apply(lambda x: x.to_pydatetime())
        # data = data[data['date']>=from_date & data['date']<= previous_date]
        data = data[(data['date'] >= from_date) & (data['date'] <= previous_date)]
        intercept, slope, r2 = get_ols(data.low, data.high)
        slope_series.append(slope)
        rsrs_score = get_zscore(slope_series[-M:]) * r2
        print('rsrs_score {:.3f}'.format(rsrs_score))
        if (rsrs_score > score_threshold):
            return "BUY"
        elif (rsrs_score < -score_threshold):
            return "SELL"
        else:
            return "KEEP"
    
    
    # slope_series = initial_slope_series()[:-1]  # 除去回测第一天的 slope ,避免运行时重复加入
    slope_series = initial_slope_series()[:-1]
    
    
    def my_trade():
        # print(stock_pool)
        # print(get_rank(stock_pool))
        check_out_list = get_rank(stock_pool)
        timing_signal = get_timing_signal(ref_stock)
        message = ""
        if len(check_out_list) > 0:
            each_check_out = check_out_list[0]
            #         security_info = jq.get_security_info(each_check_out)
            #         stock_name = security_info.display_name
            #         stock_code = each_check_out
            print('今日自选股:{}({})'.format(each_check_out, each_check_out))
            if timing_signal == 'SELL':
                #             for stock in list(positions.keys()):
                #                 close_position(stock)
                #                 message = '清仓!卖卖卖!'
                #                 message += "\r\n\r\n".join(positions.keys())
                #                 positions.clear()
                #                 print('今日择时信号:{}'.format(timing_signal))
                pass
            else:
                message = "今日自选股:{}({})".format(each_check_out, each_check_out)
                # adjust_position([each_check_out])
            print(message)
            sendMail(message)
    
    
    def mail(message):
        ret = True
    
        try:
    
            # 定义SMTP邮件服务器地址
            smtp_server = 'smtp.qq.com'
            # 邮件发送人邮箱
            from_addr = 'x x x x x x x@qq.com'  # 自己的邮想
            # 邮件发送人邮箱密码
            password = 'xxxxxxxx  # 邮箱密码
            # 邮件接收人
            to_addr = 'xxxxxxxxxx@qq.com'  # 测试接收邮件地址邮箱
    
            # 创建SMTP连接
            conn = smtplib.SMTP_SSL(smtp_server, 465)
            # 设计调试级别
            conn.set_debuglevel(1)
            # 登录邮箱
            conn.login(from_addr, password)
            # 创建邮件内容对象
            msg = EmailMessage()
            # 设置邮件内容
            msg.set_content('{}'.format(message), 'plain', 'utf-8')
            msg['Subject'] = '现在时间为:{}'.format(nowtime)
            msg['From'] = '星涅'
            msg['To'] = '我挚爱的朋友'
            # 发送邮件
            conn.sendmail(from_addr, [to_addr], msg.as_string())
            # 退出连接
            conn.quit()
    
    
    
        except Exception as e:  # 如果 try 中的语句没有执行,则会执行下面的 ret = False
            ret = False
            print(e)
    
        return ret
    
    
    def sendMail(message):
        ret = 0
        for _ in range(10):
            if ret:
                # 邮件发送成功推出
                break
            else:
                # 没有发送成功或失败继续
                ret = mail(message)
                time.sleep(1)
    
    
    if __name__ == '__main__':
        # positions["159928.XSHE"] = 100
        my_trade()
    
  • 相关阅读:
    WSL配置c语言环境
    vue无法获取$store中的变量
    接口自动化中全局参数以及用例信息
    正则表达式
    vue-i18n web 前端国际化
    elementui默认样式修改的问题
    setTimeOut的使用以及this指向问题
    elementui 在表格表头里面添加按钮
    各种
    element ui tabs标签页动态增加标签页,标签页引用组件
  • 原文地址:https://www.cnblogs.com/xingnie/p/16099214.html
Copyright © 2020-2023  润新知