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))