TUSHARE之前写的代码全放出来了,懒得搞软件著作权了。。。

TUSHARE ID:419258

import tushare as ts
import datetime
import pandas as pd
import time
import requests
import json
import eventlet
import matplotlib.pyplot as plt
import urllib3
from lxml import etree

eventlet.monkey_patch()
from lxml import etree

ts.set_token('8bfa66c56501bc490569345915a2501ef58a4106106da27f406430fa')
pro = ts.pro_api()
all_codes_list = pro.stock_basic(exchange='', list_status='L', fields='ts_code')


# 找到某段时间内的上网发行的股票
def find_all_new_stock_during_date(start_date, end_date):
    df = pro.new_share(start_date=start_date, end_date=end_date)
    return df


# print(find_all_new_stock_during_date('20200327','20200410'))


# 找到某天之后上市的新股
def find_all_new_stock_on_market_after_the_date(date, industry):
    """

    :param date:
    :param industry:
    :return:
    """
    data = pro.query('stock_basic', fields='ts_code,symbol,name,area,industry,market,list_date')
    for i in range(len(data)):
        # 如果上市日期在date之前,就删去这一行
        if industry != '':
            if datetime.datetime.strptime(date, "%Y%m%d") > datetime.datetime.strptime(data['list_date'][i], "%Y%m%d") \
                    or industry != data['industry'][i]:
                data = data.drop(index=i)
        else:
            if datetime.datetime.strptime(date, "%Y%m%d") > datetime.datetime.strptime(data['list_date'][i], "%Y%m%d"):
                data = data.drop(index=i)
        # all_codes_list['list_date'][i]=datetime.datetime.strptime(all_codes_list['list_date'][i],"%Y%m%d")
    data.set_index('list_date', inplace=True)
    return data


# print(find_all_new_stock_on_market_after_the_date('20210322',''))

def get_last_on_market_date(date):
    date_ = datetime.datetime.strptime(date, "%Y%m%d")
    date = (date_ + datetime.timedelta(days=-1)).strftime("%Y%m%d")
    while pro.query('trade_cal', start_date=date, end_date=date)['is_open'][0] == 0:
        date_ += datetime.timedelta(days=-1)
        date = date_.strftime("%Y%m%d")
    return date


def get_ke_neng_ming_tian_zhang_stock_data_by_codes(codes, zhang_die_fu_limit, price_limit):
    """
    找到猛跌的股票
    :param codes: list
    :param zhang_die_fu_limit: 2 items tuple
    :param price_limit: 2 items tuple
    :return:'name', 'open':今日开盘价, 'pre_close'昨日收盘价, 'price':当前价格, 'high':今日最高价, 'low':今日最低价,
    'bid',竞买价,即“买一”报价, 'ask',竞卖价,即“卖一”报价, 'volume'成交量 ,maybe you need do volumn/100, 'amount',成交金额(元 CNY),
    'b1_v',委买一(笔数 bid volume), 'b1_p', 'b2_v', 'b2_p', 'b3_v', 'b3_p', 'b4_v', 'b4_p', 'b5_v', 'b5_p',
    'a1_v',委卖一(笔数 ask volume), 'a1_p', 'a2_v', 'a2_p', 'a3_v', 'a3_p', 'a4_v', 'a4_p', 'a5_v', 'a5_p',
    'date',日期, 'time',时间, 'code'

    """
    today = datetime.datetime.now().strftime("%Y%m%d")
    out_list = [['code', 'price', '涨跌幅', '换手率', '量比', 'date', 'time']]
    df = pro.query('daily_basic',
                   ts_code='',
                   trade_date=get_last_on_market_date(today),
                   fields='ts_code,trade_date,turnover_rate,volume_ratio,pe,pb')
    df = df.where(df.notnull(), -1)
    for i in range(len(codes)):
        data = ts.get_realtime_quotes(codes[i])
        if float(data['pre_close']) != 0:
            dang_qian_zhang_die_fu = (float(data['price'][0]) - float(data['pre_close'][0])) / float(
                data['pre_close'][0]) * 100
        else:
            return None
        if zhang_die_fu_limit[0] < dang_qian_zhang_die_fu < zhang_die_fu_limit[1]:
            if float(data['price'][0]) < price_limit:
                turnover_rate = int([df['turnover_rate'][x] for x in range(len(df)) if
                                     df['ts_code'][x].split('.')[0] == data['code'][0]][0])
                if turnover_rate > 3:
                    volume_ratio = int([df['volume_ratio'][x] for x in range(len(df)) if
                                        df['ts_code'][x].split('.')[0] == data['code'][0]][0])
                    if volume_ratio > 1:
                        out_list.append([data['code'][0],
                                         float(data['price'][0]),
                                         dang_qian_zhang_die_fu,
                                         turnover_rate,
                                         volume_ratio,
                                         data['date'][0],
                                         data['time'][0]])
                    else:
                        continue
                else:
                    continue
            else:
                continue
        else:
            continue
    out_list = pd.DataFrame(out_list)

    return out_list


# print(get_ke_neng_ming_tian_zhang_stock_data_by_codes([code.split('.') for code in all_codes_list['ts_code']],(-10,-3),20))


def get_last_on_market_date_include_today(date):
    date_ = datetime.datetime.strptime(date, "%Y%m%d")
    while pro.query('trade_cal', start_date=date, end_date=date)['is_open'][0] == 0:
        date_ += datetime.timedelta(days=-1)
        date = date_.strftime("%Y%m%d")
    return date


def get_n_days_ago_on_market_date(date, n):
    df = pro.query('trade_cal', start_date='19901010', end_date=date)
    df = df[df['is_open'] == 1].reset_index()
    date = df['cal_date'][len(df) - 1 - n]
    return date


def from_code_to_ts_code(code):
    first_letter = code[0]
    if first_letter == '6':
        code += '.SH'
    elif first_letter == '0' or '3':
        code += '.SZ'
    return code


def calc_wr_index(close, highest_list, lowest_list):
    """

    :param close:
    :param highest_list:
    :param lowest_list:
    :return: 一个数值
    """
    _C = close
    _H = max(highest_list)
    _L = min(lowest_list)
    _WR = (_H - _C) / (_H - _L) * 100
    return _WR


class WRAnalyse:
    """
    这是一个用来计算和处理WR指标的类
    """

    def __init__(self, code, n, end_date, WR_select=(6, 10)):
        """

        :param code:
        :param n: 包括end_date的前n天数据
        :param end_date:
        :param WR_select:
        """
        # 初始化的时候获得这只股票的基本行情
        self.jichuhangqing = pro.daily(ts_code=from_code_to_ts_code(code),
                                       start_date='19780101',
                                       end_date=end_date)
        #  先拿出需要的这一部分
        self.jichuhangqing = self.jichuhangqing.iloc[:n + WR_select[1] - 1]
        #  反转
        self.jichuhangqing = self.jichuhangqing[::-1]
        self.jichuhangqing.reset_index(drop=True, inplace=True)
        _data = self.jichuhangqing
        WR1_list = [0 for _ in range(n)]
        for i in range(n):
            close = _data['close'][i + WR_select[1] - 1]
            high_list = _data['high'][i:i + WR_select[1] - 1]
            low_list = _data['low'][i:i + WR_select[1] - 1]
            WR1_list[i] = calc_wr_index(close, high_list, low_list)
        WR2_list = [0 for _ in range(n)]
        for i in range(n):
            close = _data['close'][i + WR_select[1] - 1]
            high_list = _data['high'][i:i + WR_select[1] - 1]
            low_list = _data['low'][i:i + WR_select[1] - 1]
            WR2_list[i] = calc_wr_index(close, high_list, low_list)
        self.WR1_list = WR1_list
        self.WR2_list = WR2_list


# a=WRAnalyse('600010',10,'20210408')


def num_share_full_stack_buy_in(xianjin, stock_price):
    """

    :param xianjin:
    :param stock_price:
    :return: 能买的最大手数量
    """
    nengmaishou = int(xianjin / stock_price / 100)
    qian = 100 * nengmaishou * stock_price
    x = xianjin - qian - get_shouxufei(qian)
    while x < 0:
        nengmaishou -= 1
        qian = 100 * nengmaishou * stock_price
        x = xianjin - qian - get_shouxufei(qian)
    return nengmaishou


def get_shouxufei(money):
    yinhuashui = money * 0.001
    zhengguanfei = money * 0.00002
    jiaoyiyongjin = money * 3 / 1000
    if jiaoyiyongjin < 5:
        jiaoyiyongjin = 5
    return yinhuashui + zhengguanfei + jiaoyiyongjin


class MeasureProfitWithMultipleStrategy:
    def __init__(self, code, n, start_date, end_date, MA_select, WR_select):
        self.code = code
        self.n = n
        self.start_date = start_date  # 仍然是用的外面传过来的,不在这里计算
        self.end_date = end_date
        # 初始化一个MovingAverageAnalyse类
        self.ma_analyse = MovingAverageAnalyse(code, n, end_date, days_select=MA_select)
        self.MA_data = self.ma_analyse.MA_data
        # print(self.MA_data)
        # 初始化一个WRAnalyse类
        self.wr_analyse = WRAnalyse(code, n, end_date, WR_select=WR_select)
        self.WR1_data = self.wr_analyse.WR1_list
        self.WR2_data = self.wr_analyse.WR2_list

    def strategy1(self, xianjin):
        """
        每次交易,要不就满仓,要不就平仓,根据MA的金叉死叉选择买卖点,不会根据最高点去止损
        每次买入卖出都用最大值去做,每一手是100股,只能在这一天结束之后才能判断出这一天是不是金叉,
        也就是说,我在i天检测到了金叉,我在i+1天的早上开盘的时候才会买入,价格以开盘价来计算,
        同样的,卖出也会以开盘价去计算,因为我此时是很急迫想要离场的。
        :param xianjin:
        :return:
        """
        qidongzijin = xianjin
        all_good_date_to_buy_list = self.ma_analyse.get_all_good_date_to_buy_in_view_of_cross()
        all_good_date_to_sell_list = self.ma_analyse.get_all_good_date_to_sell_in_view_of_cross()
        xianyoushou = 0
        _data = self.MA_data
        for index in range(len(_data)):
            caozuole = 0
            date = _data['trade_date'][index]
            if date in all_good_date_to_buy_list:
                caozuole = 1
                _price = self.ma_analyse.get_open_price_the_next_date(date)
                nengmaishou = num_share_full_stack_buy_in(xianjin, _price)
                if nengmaishou == 0:  # 没买
                    pass
                else:  # 买入
                    qian = 100 * nengmaishou * _price
                    xianyoushou = nengmaishou
                    shouxufei = get_shouxufei(qian)
                    xianjin = xianjin - qian - shouxufei
                    xianjin = round(xianjin, 2)

            if date in all_good_date_to_sell_list:
                caozuole = 1
                _price = self.ma_analyse.get_open_price_the_next_date(date)
                if xianyoushou == 0:  # 手上没有
                    pass
                else:  # 手上有,就清仓
                    qian = 100 * xianyoushou * _price
                    shouxufei = get_shouxufei(qian)
                    xianjin = xianjin + qian - shouxufei
                    xianyoushou = 0
                    xianjin = round(xianjin, 2)

            # if caozuole == 1:
            # print(f"This is the {index} time, "
            #       f"I have {xianyoushou} hand of stock and {xianjin}, "
            #       f"that is {xianjin + xianyoushou * _data['open'][len(_data) - 1]}")

        now_money = xianjin + 100 * xianyoushou * _data['open'][len(_data) - 1]
        return now_money, now_money / qidongzijin, qidongzijin

    def strategy2(self, xianjin):
        """
        每次交易,要不就满仓,要不就平仓,根据MA的金叉死叉选择买卖点,并根据当前操作中的最高点去止损
        每次买入卖出都用最大值去做,每一手是100股,只能在这一天结束之后才能判断出这一天是不是金叉,
        也就是说,我在i天检测到了金叉,我在i+1天的早上开盘的时候才会买入,价格以开盘价来计算,
        同样的,卖出也会以开盘价去计算,因为我此时是很急迫想要离场的。
        :param xianjin:
        :return:
        """
        qidongzijin = xianjin
        all_good_date_to_buy_list = self.ma_analyse.get_all_good_date_to_buy_in_view_of_cross()
        all_good_date_to_sell_list = self.ma_analyse.get_all_good_date_to_sell_in_view_of_cross()
        xianyoushou = 0
        _data = self.MA_data
        chiyou = 0
        zuida_zongzichan = 0
        zongzichan = 0
        for index in range(len(_data)):
            caozuole = 0
            date = _data['trade_date'][index]
            # 买操作
            if date in all_good_date_to_buy_list:
                caozuole = 1
                _price = self.ma_analyse.get_open_price_the_next_date(date)
                nengmaishou = num_share_full_stack_buy_in(xianjin, _price)
                if nengmaishou == 0:  # 没买
                    pass
                else:  # 买入
                    chiyou = 1  # 只要是1就说明还在一波,0的时候就说明清仓了,到下一波了
                    qian = 100 * nengmaishou * _price
                    xianyoushou = nengmaishou
                    shouxufei = get_shouxufei(qian)
                    xianjin = xianjin - qian - shouxufei
                    xianjin = round(xianjin, 2)

            # 卖操作  根据死叉卖出
            if date in all_good_date_to_sell_list:
                _price = self.ma_analyse.get_open_price_the_next_date(date)
                if xianyoushou == 0:  # 手上没有
                    pass
                else:  # 手上有,就清仓
                    caozuole = 1
                    chiyou = 0
                    qian = 100 * xianyoushou * _price
                    shouxufei = get_shouxufei(qian)
                    xianjin = xianjin + qian - shouxufei
                    xianyoushou = 0
                    xianjin = round(xianjin, 2)

            # 卖操作  根据最高点下降5个点进行止损
            if chiyou == 1 and index < self.n - 1:
                zongzichan = xianjin + 100 * xianyoushou * _data['open'][index + 1]
                # 更新最大值
                if zongzichan > zuida_zongzichan:
                    zuida_zongzichan = zongzichan
                #  跌超5%清仓
                if zongzichan < zuida_zongzichan * 0.95:
                    caozuole = 1
                    chiyou = 0
                    qian = 100 * xianyoushou * _data['open'][index + 1]
                    shouxufei = get_shouxufei(qian)
                    xianjin = xianjin + qian - shouxufei
                    xianyoushou = 0
                    xianjin = round(xianjin, 2)
                    # print(zuida_zongzichan)
            else:
                zuida_zongzichan = 0

            # if caozuole == 1:
            #     print(f"This is the {index} time, the price is {_data['open'][index]},"
            #           f"I have {xianyoushou} hand of stock and {xianjin}, "
            #           f"that is {zongzichan}")

        now_money = xianjin + 100 * xianyoushou * _data['open'][len(_data) - 1]
        return now_money, now_money / qidongzijin, qidongzijin

    def strategy3(self, xianjin):
        """
        这个策略在
        :param xianjin:
        :return:
        """
        pass


class MovingAverageAnalyse:
    def __init__(self, code, n, end_date, days_select=(5, 10, 20)):
        self.n = n
        self.code = code
        self.short = days_select[0]
        self.middle = days_select[1]
        self.long = days_select[2]
        self.end_date = end_date
        # 取出的数据是已经经过处理的
        self.MA_data = ts.pro_bar(ts_code=from_code_to_ts_code(code),
                                  start_date='19780101',
                                  end_date=end_date,
                                  ma=[self.short, self.middle, self.long]).iloc[:-(self.long - 1)]
        # print(get_n_days_ago_on_market_date(today, n + self.long),get_last_on_market_date_include_today(today))
        self.MA_data = self.MA_data[self.n - 1::-1]
        self.MA_data.reset_index(drop=True, inplace=True)
        self.start_date = self.MA_data['trade_date'].iloc[0]

    def golden_cross(self):
        # 短线上穿长线
        _data = self.MA_data
        _short = self.short
        _long = self.long
        golden_cross_date_list = []
        for i in range(len(_data) - 1):
            if _data['ma' + str(_short)][i] < _data['ma' + str(_long)][i] \
                    and _data['ma' + str(_long)][i + 1] < _data['ma' + str(_short)][i + 1]:
                golden_cross_date_list.append(_data['trade_date'][i + 1])  # 我们不能提前知道涨跌,所以只能用交叉后的日期
        return golden_cross_date_list

    def dead_cross(self):
        # 长线上传短线
        """

        :return: 所有死叉的日期
        """
        _data = self.MA_data
        _short = self.short
        _long = self.long
        dead_cross_date_list = []
        for i in range(len(_data) - 1):
            if _data['ma' + str(_short)][i] > _data['ma' + str(_long)][i] \
                    and _data['ma' + str(_long)][i + 1] > _data['ma' + str(_short)][i + 1]:
                dead_cross_date_list.append(_data['trade_date'][i + 1])  # 我们不能提前知道涨跌,所以只能用交叉后的日期
        return dead_cross_date_list

    def is_this_day_golden_cross(self, date):
        _data = self.MA_data
        _short = self.short
        _long = self.long
        jintian_suoyin = _data[_data['trade_date'] == date].index[0]
        condition = 0
        if jintian_suoyin == 0:
            # print('此日不能是数据的开始日')
            return -1
        else:
            zuotian_suoyin = jintian_suoyin - 1
            if (_data['ma' + str(_short)][zuotian_suoyin] < _data['ma' + str(_long)][zuotian_suoyin]) \
                    and (_data['ma' + str(_long)][jintian_suoyin] < _data['ma' + str(_short)][jintian_suoyin]):
                condition = 1
        return condition

    def is_this_day_dead_cross(self, date):
        _data = self.MA_data
        _short = self.short
        _long = self.long
        jintian_suoyin = _data[_data['trade_date'] == date].index[0]
        condition = 0
        if jintian_suoyin == 0:
            # print('此日不能是数据的开始日')
            return -1
        else:
            zuotian_suoyin = jintian_suoyin - 1
            if _data['ma' + str(_short)][zuotian_suoyin] > _data['ma' + str(_long)][zuotian_suoyin] \
                    and _data['ma' + str(_long)][jintian_suoyin] > _data['ma' + str(_short)][jintian_suoyin]:
                condition = 1
        return condition

    def is_this_date_good_to_buy_from_view_of_cross(self, date):
        # 这个策略的思想就是,如果此日出现金叉,而且在此日之前的3天之内没有出现过死叉,那么发出买入信号,防止诱多
        _data = self.MA_data
        _short = self.short
        _long = self.long
        this_date_suoyin = _data[_data['trade_date'] == date].index[0]
        condition = 0
        if self.is_this_day_golden_cross(date):
            if this_date_suoyin >= 3:
                for i in range(3, 0, -1):
                    suoyin_i = this_date_suoyin - i
                    if self.is_this_day_dead_cross(_data['trade_date'][suoyin_i]):
                        condition = 0
                        break
                    else:
                        condition = 1
                        # 有一次死叉就不行
        return condition

    def is_this_date_good_to_sell_from_view_of_cross(self, date):
        condition = 0
        if self.is_this_day_dead_cross(date):
            condition = 1
        return condition

    def get_all_good_date_to_buy_in_view_of_cross(self):
        all_good_date_list = []
        golden_cross_list = self.golden_cross()
        for date in golden_cross_list:
            if self.is_this_date_good_to_buy_from_view_of_cross(date):
                all_good_date_list.append(date)
        return all_good_date_list

    def get_all_good_date_to_sell_in_view_of_cross(self):
        all_dead_date_list = self.dead_cross()
        return all_dead_date_list

    def get_open_price_the_next_date(self, date):
        """
        不能传入最后一天的日期
        :param date:
        :return:
        """
        _data = self.MA_data
        if date != self.end_date:
            next_date_suoyin = _data[_data['trade_date'] == date].index[0] + 1
            open_price = _data['open'][next_date_suoyin]
        else:
            date_suoyin = _data[_data['trade_date'] == date].index[0]
            open_price = _data['pre_close'][date_suoyin]
        return open_price

    # 画图
    def plot_the_k_line(self, is_cross_on_sight):
        # 设置figsize大一点比较清楚
        _data = self.MA_data
        MA_short = _data['ma' + str(self.short)]
        MA_middle = _data['ma' + str(self.middle)]
        MA_long = _data['ma' + str(self.long)]
        suoyin_list = [x for x in range(len(_data))]
        length = len(_data)
        plt.figure(figsize=(int(length / 3), int(length / 4)))
        plt.plot(suoyin_list, MA_short, 'r', linewidth=length / 200)
        plt.plot(suoyin_list, MA_middle, 'g', linewidth=length / 200)
        plt.plot(suoyin_list, MA_long, 'b', linewidth=length / 200)
        plt.legend([str(self.short), str(self.middle), str(self.long)])
        plt.xticks(suoyin_list[::10], _data['trade_date'][::10], rotation=40)
        for i in range(len(_data)):
            zuidijia = _data['low'][i]
            zuigaojia = _data['high'][i]
            kaipanjia = _data['open'][i]
            shoupanjia = _data['close'][i]
            x = [i, i]
            y = [zuidijia, zuigaojia]
            if kaipanjia > shoupanjia:
                color = 'g'
            else:
                color = 'r'
            plt.plot(x, [kaipanjia, shoupanjia], linewidth=1, color=color)  # 画宽柱子
            plt.plot(x, y, color=color, linewidth=length / 100)  # 画竖线
        # 画叉点
        if is_cross_on_sight == 1:
            all_golden_dates = self.get_all_good_date_to_buy_in_view_of_cross()
            all_dead_dates = self.get_all_good_date_to_sell_in_view_of_cross()
            for date in all_golden_dates:
                index = _data[_data['trade_date'] == date].index
                plt.scatter(index, _data['open'][index], color='pink', marker='o', edgecolors='r', s=200)
            for date in all_dead_dates:
                index = _data[_data['trade_date'] == date].index
                plt.scatter(index, _data['open'][index], color='orange', marker='o', edgecolors='g', s=200)
        plt.show()

    # 多头稳定上升
    def multiple_head_stable_rise_up(self):
        """
        当多头市场进入稳定上升时期,10MA、20MA、60MA向右上方推升,且三线多头排列(排列顺序自上而下分别为10MA、20MA、60MA),略呈平行状。
        :return:
        """
        condition = 0
        slope = []
        for i in range(len(self.MA_data) - 1):
            if self.MA_data['ma' + str(self.long)][i + 1] > self.MA_data['ma' + str(self.long)][i]:
                if self.MA_data['ma' + str(self.middle)][i + 1] > self.MA_data['ma' + str(self.middle)][i]:
                    if self.MA_data['ma' + str(self.short)][i + 1] > self.MA_data['ma' + str(self.short)][i]:
                        if self.MA_data['ma' + str(self.long)][i] < self.MA_data['ma' + str(self.middle)][i] < \
                                self.MA_data['ma' + str(self.short)][i]:
                            condition = 1
                            slope.append(sum(
                                [self.MA_data['ma' + str(self.long)][i + 1] / self.MA_data['ma' + str(self.long)][i],
                                 self.MA_data['ma' + str(self.middle)][i + 1] / self.MA_data['ma' + str(self.middle)][
                                     i],
                                 self.MA_data['ma' + str(self.short)][i + 1] > self.MA_data['ma' + str(self.short)][
                                     i]]) / 3)
                        else:
                            break
                    else:
                        break
                else:
                    break
            else:
                break

        if not slope:
            slope = -1
        else:
            slope = sum(slope) / len(slope)
        return condition, slope

    def technology_back_gear(self):
        """
        当10MA由上升趋势向右下方拐头而下,而20MA仍然向上方推升时,揭示此波段为多头市场中的技术回档,涨势并未结束。
        :return:
        """
        condition = 0
        for i in range(len(self.MA_data) - 1):
            if self.MA_data['ma' + str(self.long)][i + 1] < self.MA_data['ma' + str(self.long)][i] \
                    and self.MA_data['ma' + str(self.middle)][i + 1] > self.MA_data['ma' + str(self.middle)][i]:
                condition = 1
        return condition

    def from_kong_to_duo(self):
        """
        由空转多
        股市由空头市场进入多头市场时,
        10MA首先由上而下穿越K线图(注意是K线图),
        处于k线图的下方(即股价站在10MA之上),
        过几天20MA、60MA相继顺次,
        由上往下穿越K线图(既股价顺次站在20MA、60MA之上)。
        :return:
        """
        df = pro.daily(ts_code=from_code_to_ts_code(self.code), start_date=self.start_date, end_date=self.end_date)
        condition = 0
        for i in range(len(self.MA_data)):
            df_1 = df[df['trade_date'] == self.MA_data['trade_date'][i]]
            low = df_1['low']
            if low < self.MA_data['ma' + str(self.short)][i] < df_1['open'] < df_1['close']:  # 穿过k线图
                for j in range(i, len(self.MA_data)):
                    df_1 = df[df['trade_date'] == self.MA_data['trade_date'][i]]
                    if self.MA_data['ma' + str(self.middle)][i] < df_1['open'] < df_1['close']:
                        for k in range(j, len(self.MA_data)):
                            df_1 = df[df['trade_date'] == self.MA_data['trade_date'][i]]
                            if self.MA_data['ma' + str(self.long)][i] < df_1['open'] < df_1['close']:
                                condition = 1
                                break
                            else:
                                pass
                        else:
                            pass
                        break
                    else:
                        pass
                break
            else:
                pass
        return condition


# today = datetime.datetime.now().strftime("%Y%m%d")
# n=5
# long=20
# start_date=get_n_days_ago_on_market_date(today, n + long)
# end_date=get_last_on_market_date_include_today(today)
# tic=time.time()
# for code in codes:
#     a = MovingAverageAnalyse(code, 5,start_date=start_date,end_date=end_date,days_select=(5,10,20))
#     time.sleep(0.15)
#     if a.multiple_head_stable_rise_up()[1]<0:
#         continue
#     toc=time.time()
#     print(code,a.multiple_head_stable_rise_up(),f'{toc-tic}s')


# 根据东方财富http://so.eastmoney.com/web/s?keyword=002875&pageindex=1
# 了解这个股票的质地,评分
def get_stock_quality_and_score_and_main_money_in(code):
    url = f'http://gwapi.eastmoney.com/agent/1258/stockcomment/api/so/{code}.json?appid=1466&tk=28228DE7FA07D013677756DD94686DEA&cb=jQuery11240592770126391372_1617018500625&_=1617018500652'
    headers = {
        'Host': 'gwapi.eastmoney.com',
        'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 7_1_2 like Mac OS X) App leWebKit/537.51.2 (KHTML, like Gecko) Version/7.0 Mobile/11D257 Safari/9537.53',
        'Accept': '*/*',
        'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
        'Accept-Encoding': 'gzip, deflate',
        'Connection': 'keep-alive',
        'Referer': 'http://so.eastmoney.com/'
    }

    response = requests.get(url, headers=headers)
    while not response.ok:
        time.sleep(0.5)
        response = requests.get(url)
    a = response.content
    a = str(a.decode('utf-8'))
    a = a.split('1617018500625(')[1]
    a = a[:-1]
    b = json.loads(a)
    zonghepingfen = b['ApiResults']['zj']['Overall'][0]['TotalScore']
    jinribiaoxian = b['ApiResults']['zj']['Overall'][0]['TotalScoreCHG']
    dabaileduoshaogupiao = b['ApiResults']['zj']['Overall'][0]['LeadPre']
    cirishangzhanggailv = b['ApiResults']['zj']['Overall'][0]['RisePro']
    xiaoximian = b['ApiResults']['zj']['Overall'][0]['Comment'].split('消息面')[1].split(',')[0]
    zhulizijinqushi = b['ApiResults']['zj']['Overall'][0]['Comment'].split('主力资金')[1].split(',')[0]
    duanqiqushi = b['ApiResults']['zj']['Overall'][0]['Comment'].split('短期呈现')[1].split('趋势')[0]
    zhidi = b['ApiResults']['zj']['Overall'][0]['Comment'].split('公司质地')[1].split(',')[0]
    shichangguanzhuyiyuan = b['ApiResults']['zj']['Overall'][0]['Comment'].split('市场关注意愿')[1].split('。')[0]
    return [zonghepingfen, jinribiaoxian, dabaileduoshaogupiao, cirishangzhanggailv,
            xiaoximian, zhulizijinqushi, duanqiqushi, zhidi, shichangguanzhuyiyuan]


def download_stock_quality_and_score_and_main_money_in(codes):
    df = [['代码', '综合评分', '今日表现', '打败股票比例', '次日上涨概率', '消息面活跃度', '主力资金介入程度', '短期趋势', '公司质地', '市场关注意愿']]
    if codes == '':
        codes = [code.split('.')[0] for code in all_codes_list['ts_code']]
    count = 0
    tic0 = time.time()
    kaiqi = 0
    for code in codes:
        if code == '688665':
            kaiqi = 1
        if kaiqi == 0:
            continue
        tic = time.time()
        time.sleep(1)
        b = get_stock_quality_and_score_and_main_money_in(code)
        for i in range(len(b)):
            if i < 4:
                b[i] = round(float(b[i]), 2)
        df.append([code, b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7], b[8]])

        if count % 1 == 0 and count != 0:
            c = pd.DataFrame(df)
            c.to_excel('东方财富综合评价.xlsx', index=False, header=False)
        toc = time.time()
        print(f'code {code},此次用时{toc - tic},总用时{toc - tic0}')
        count += 1

    df = pd.DataFrame(df)
    df.to_excel('东方财富综合评价.xlsx', index=False, header=False)
    return pd.read_excel('东方财富综合评价.xlsx')


def get_stock_quality_and_score_and_main_money_in_no_download(codes):
    df = [['代码', '综合评分', '今日表现', '打败股票比例', '次日上涨概率', '消息面活跃度', '主力资金介入程度', '短期趋势', '公司质地', '市场关注意愿']]
    if codes == '':
        codes = [code.split('.')[0] for code in all_codes_list['ts_code']]
    count = 0
    timeout = 2
    unprocessed_code = []
    for code in codes:
        tic = time.time()
        time.sleep(0.2)
        with eventlet.Timeout(timeout, False):
            b = get_stock_quality_and_score_and_main_money_in(code)
            for i in range(len(b)):
                if i < 4:
                    b[i] = round(float(b[i]), 2)
            df.append([code, b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7], b[8]])
            count += 1
            toc = time.time()
        if toc - tic > timeout:
            # 超时处理
            print(f'Timeout, the code is {code}')
            unprocessed_code.append(code)
    print(f'unprocessed code list is {unprocessed_code}')
    df = pd.DataFrame(df)
    return df


# codes = [code.split('.')[0] for code in all_codes_list['ts_code']]
# # # download_stock_quality_and_score_and_main_money_in(codes)
today = datetime.datetime.now().strftime("%Y%m%d")
n = 200
# short,middle,long=10,30,60
# short, middle, long = 5, 10, 20
end_date = get_last_on_market_date_include_today(today)


# a = MovingAverageAnalyse('300059', n, end_date=end_date, days_select=(short, middle, long))
# print(a.MA_data['low'][len(a.MA_data)-1-60:len(a.MA_data)])
# # print(a.huice_profit_of_the_strategy_of_cross_in_full_stack(1000000))
#
# qidongzijin=10000
# yingshuliang=0
# codes=codes[:100]
# zongzengzhanglv=0
# for code in codes:
#     _data=ts.pro_bar(ts_code=from_code_to_ts_code(code),
#                start_date=start_date,
#                end_date=end_date,
#                ma=[short, middle, long]).iloc[:-(long - 1)]
#     # print(len(_data))
#     a = MovingAverageAnalyse(code, n, start_date=start_date, end_date=end_date, days_select=(short, middle, long))
#     b=a.huice_profit_of_the_strategy_of_cross_in_full_stack(qidongzijin)
#     zengzhanglv=(b[1]-1)*100
#     zongzengzhanglv+=zengzhanglv
#     if zengzhanglv>0:
#         yingshuliang+=1
#     print(code,a.huice_profit_of_the_strategy_of_cross_in_full_stack(qidongzijin))
#
# print(yingshuliang/len(codes))
# print(zongzengzhanglv/len(codes))


def measure_profit(codes, dates, start_date, end_date, ma, wr):
    for code in codes:
        a = MeasureProfitWithMultipleStrategy(code, dates, start_date, end_date, ma, wr)
        print(code, a.strategy1(100000))
        print(code, a.strategy2(100000))


def get_latest_price_of_stock(code):
    # 爬虫,直接在东方财富网获取数据
    is_in_shanghai = 0
    if code[0] == '6':
        is_in_shanghai = 1
    url = f'http://push2.eastmoney.com/api/qt/stock/get?ut=fa5fd1943c7b386f172d6893dbfba10b&invt=2&fltt=2&fields=f43&secid={is_in_shanghai}.{code}&cb=jQuery1124032163553318498406_1619439417617&_=1619439417618'
    headers = {
        'Accept': '*/*',
        'Accept-Encoding': 'gzip,deflate',
        'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
        'Connection': 'keep-alive',
        'Host': 'push2.eastmoney.com',
        'Referer': 'http: // quote.eastmoney.com /',
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:88.0) Gecko/20100101 Firefox/88.0'
    }
    response = requests.get(url, headers=headers)
    while not response.ok:
        time.sleep(0.5)
        response = requests.get(url)

    a = response.content
    a = str(a.decode('utf-8'))
    a = a.split('1124032163553318498406_1619439417617(')[1]
    a = a[:-2]
    b = json.loads(a)
    price = b['data']['f43']
    if price == '-':
        df = pro.daily(ts_code=from_code_to_ts_code(code), start_date='19780101', end_date=end_date)
        price = df['close'][0]
    return price


def is_stock_golden_cross_and_at_low_price_in_last_n_days(code, n):
    condition = 0
    # 找出60天的历史低位
    stock_ma_analysis = MovingAverageAnalyse(code, 60, end_date=end_date, days_select=(5, 10, 20))
    _data = stock_ma_analysis.MA_data
    lowest = min(_data['low'][:len(_data)])
    # 判断当前股价是否在历史低位,即是否超过低位10%
    is_price_low = 0
    now_price = float(get_latest_price_of_stock(code))
    if now_price < lowest * 1.1:
        is_price_low = 1
    # 判断前n天内是否出现金叉
    golden_cross_occur = 0
    for i in range(n):
        if stock_ma_analysis.is_this_day_golden_cross(date=_data['trade_date'][len(_data) - 1 - i]):
            golden_cross_occur = 1
            break
    if golden_cross_occur == 1 and is_price_low == 1:
        condition = 1
    return condition


# print(all_codes_list)

def get_all_stock_golden_cross_and_at_low_price_in_last_n_days_in_field(field, n):
    _data = pro.stock_basic(exchange='', list_status='L', fields='symbol,industry')
    codes = [code for code in _data['symbol'][_data['industry'] == field]]
    output = []
    for code in codes:
        print(code)
        status_is_stock_golden_cross_and_at_low_price_in_last_n_days = is_stock_golden_cross_and_at_low_price_in_last_n_days(
            code, 5)
        if status_is_stock_golden_cross_and_at_low_price_in_last_n_days == 1:
            print(code)
            output.append(code)
    return output


def get_code_list_in_industry(industry):
    """

    :param industry: 可选行业有
    ['证券', '全国地产', '航空', '软饮料',
    '新型电力', '造纸', '出版业', '食品',
    '电器仪表', '纺织机械', '公路', '小金属',
    '园区开发', '钢加工', '化纤', '商贸代理',
    '装修装饰', '半导体', '服饰', '石油贸易',
    '农药化肥', '啤酒', 'IT设备', '水运',
    '铅锌', '旅游服务', '染料涂料', '空运',
    '橡胶', '农业综合', '种植业', '饲料',
    '综合类', '轻工机械', '建筑工程', '白酒',
    '供气供热', '医药商业', '水力发电',
    '通信设备', '汽车整车', '区域地产',
    '电信运营', '铝', '房产服务', '纺织',
    '水泥', '玻璃', '港口', '影视音像',
    '船舶', '专用机械', '批发业', '摩托车',
    '红黄酒', '陶瓷', '化工原料', '水务',
    '银行', '工程机械', '普钢', '旅游景点',
    '其他建材', '电气设备', '仓储物流',
    '机械基件', '中成药', '焦炭加工', '公共交通',
    '铁路', '渔业', '矿物制品', '超市连锁',
    '家居用品', '医疗保健', '文教休闲', '其他商业',
    '日用化工', '保险', '机场', '机床制造',
    '农用机械', '黄金', '塑料', '化工机械',
    '百货', '广告包装', '家用电器', '酒店餐饮',
    '特种钢', '电器连锁', '互联网', '路桥',
    '元器件', '汽车配件', '生物制药', '石油加工',
    '煤炭开采', '化学制药', '环境保护', '石油开采',
    '汽车服务', '多元金融', '火力发电', '商品城',
    '铜', '乳制品', '运输设备', '软件服务', '林业']

    :return:
    """
    data = pro.query('stock_basic', exchange='', list_status='L', fields='symbol,industry')
    data=data[data['industry']==industry]
    return list(data['symbol'])


def get_all_industry():
    data = pro.query('stock_basic', exchange='', list_status='L', fields='symbol,industry')
    data=data['industry']
    data=list(data)
    data=set(data)
    data = list(data)
    return data


a=get_code_list_in_industry('环境保护')


def find_high_div_in_codes(codes, cash_div_per_yuan,stk_div,zengzhanglv):
    """
    stk_bo_rate是每股送股比例
    stk_co_rate是每股转增比例
    :param codes:
    :param cash_div_per_yuan:
    :param stk_div:
    :return:
    """
    out_codes=[]
    for code in codes:
        time.sleep(0.6)
        df = pro.dividend(ts_code=from_code_to_ts_code(code),
                          fields='ts_code,cash_div,div_proc,stk_div,record_date,ex_date')
        price = get_latest_price_of_stock(code)
        #  找出实施的分红方案
        a = df[df['div_proc'] == '实施']
        a = a.reset_index(drop=True, inplace=False)
        if len(a) > 0:
            if a['cash_div'][0] / price > cash_div_per_yuan \
                    or a['stk_div'][0]>stk_div \
                    or get_profit_from_div(price,a['cash_div'][0],stk_div=a['stk_div'][0])>zengzhanglv:
                print(code, a.iloc[0])
                out_codes.append([code, a.iloc[0]])
    return out_codes


def calc_basic_price(price,record):
    """
    https://baike.baidu.com/item/%E9%99%A4%E6%9D%83%E6%97%A5/4534575?fr=aladdin
    :param price:
    :param record:
    :return:
    """
    pass


def get_profit_from_div(price,cash_div_per_stock, stk_div):
    """
    此函数用来计算如果股票回到除权前的价格,能从中获利和成本的比例
    股票分红是持股小于一个月交20%的税,
    小于一年10%
    大于一年免税
    我们散户只玩短线,所以只考虑20%的税
    :param price:
    :param cash_div_per_stock:
    :param stk_div:
    :return:
    """
    return (cash_div_per_stock*0.8+stk_div*price)/price


print(find_high_div_in_codes(a,0,0,0.5))

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

朝不闻道,夕不可死

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值