@ -0,0 +1,9 @@
|
||||
const.json
|
||||
.vscode
|
||||
venv
|
||||
numpy_pandas.md
|
||||
test.py
|
||||
report_show
|
||||
notes
|
||||
temp.*
|
||||
log
|
@ -0,0 +1 @@
|
||||
{"sum_6": {"MA_5": 1744503, "MA_10": 1693476, "MA_15": 1645285, "MA_20": 1597488}, "sum_7": {"MA_5": 1744503, "MA_10": 1693476, "MA_15": 1645285, "MA_20": 1597488}, "sum_8": {"MA_5": 1744503, "MA_10": 1693476, "MA_15": 1645285, "MA_20": 1597488}, "sum_9": {"MA_5": 1744503, "MA_10": 1693476, "MA_15": 1645285, "MA_20": 1597488}, "sum_10": {"MA_5": 1744503, "MA_10": 1693476, "MA_15": 1645285, "MA_20": 1597488}}
|
@ -0,0 +1 @@
|
||||
{"_5": 1033749, "_7": 1051246, "_9": 1055143, "_10": 1052648, "_11": 1047408, "_12": 1040868, "_6": 1053234, "_8": 1056156}
|
@ -0,0 +1 @@
|
||||
{"_5": 721152, "_6": 688496, "_7": 682389, "_8": 678305, "_9": 682749, "_10": 683570, "_11": 681318, "_12": 680672}
|
@ -0,0 +1 @@
|
||||
{"_5": 158387, "_6": 75437, "_7": 36881, "_8": 19231, "_9": 10873, "_10": 6797, "_11": 4612, "_12": 3317}
|
@ -0,0 +1 @@
|
||||
{"_5": 28435, "_6": 13959, "_7": 6385, "_8": 2659, "_9": 1218, "_10": 611, "_11": 353, "_12": 240}
|
@ -0,0 +1,104 @@
|
||||
import sys
|
||||
import os
|
||||
import json
|
||||
import pandas as pd
|
||||
import numpy as np
|
||||
from tqdm import tqdm
|
||||
from collections import deque
|
||||
import copy
|
||||
|
||||
class Raise(object):
|
||||
|
||||
def __init__(self, day_arr=[5,6,7,8,9,10,11,12], ma_arr=[5,6,7,8,9,10,10]):
|
||||
const_path = sys.path[0].replace("\\analyze_data", "")
|
||||
f = open(const_path + "\\const.json", "r", encoding="utf8")
|
||||
self.consts = json.loads(f.read())
|
||||
self.dayline_file_prefix = self.consts['day_line_file_prefix']['netease_clean']
|
||||
self.with_my_result = self.consts['path']['result']['hly']
|
||||
|
||||
self.day_arr = day_arr
|
||||
self.ma_arr = ma_arr
|
||||
self.res_up = {}
|
||||
self.res_down = {}
|
||||
|
||||
self.up_res_group_by_date = {}
|
||||
|
||||
def one(self, code):
|
||||
try:
|
||||
df = pd.read_csv("%s%s.csv" % (self.with_my_result, code), encoding="gbk")
|
||||
except:
|
||||
print("ERROR %s " % code)
|
||||
return
|
||||
sum_arr = {}
|
||||
for index, row in df[::-1].iterrows():
|
||||
for day in self.day_arr:
|
||||
if day in sum_arr.keys():
|
||||
sum_arr[day].append(row['hly_score'])
|
||||
if len(sum_arr[day]) < day:
|
||||
continue
|
||||
if index-5 >= 0:
|
||||
if (self.isRaise(sum_arr[day], type=1)): # 满足形态
|
||||
self.updateRes(row['ma_5'] > df.loc[index-5, 'ma_5'], day, row, code)
|
||||
sum_arr[day].popleft()
|
||||
# for ma in self.ma_arr:
|
||||
# self.updateRes(row['ma_%s' % ma] > df.loc[index-ma, 'ma_%s' % ma], day, ma)
|
||||
else:
|
||||
return
|
||||
else:
|
||||
sum_arr[day] = deque([row['hly_score']])
|
||||
|
||||
def all(self):
|
||||
filelist = os.listdir(self.with_my_result)
|
||||
for i in tqdm(range(len(filelist))):
|
||||
code = filelist[i][0:6]
|
||||
self.one(code)
|
||||
# print(self.res_up)
|
||||
# print(self.res_down)
|
||||
f = open("%s\\up_res_group_by_date_strict_mode.json" % sys.path[0], "w", encoding="utf-8")
|
||||
f.write(json.dumps(self.up_res_group_by_date, ensure_ascii=False))
|
||||
f.close()
|
||||
|
||||
# f = open("%s\\hly_count_res_ma5_type_1_up.json" % sys.path[0], "w", encoding="utf-8")
|
||||
# f.write(json.dumps(self.res_up, ensure_ascii=False))
|
||||
# f.close()
|
||||
|
||||
# f = open("%s\\hly_count_res_ma5_type_1_down.json" % sys.path[0], "w", encoding="utf-8")
|
||||
# f.write(json.dumps(self.res_down, ensure_ascii=False))
|
||||
# f.close()
|
||||
|
||||
def isRaise(self, arr, type):
|
||||
c = copy.deepcopy(arr)
|
||||
c.popleft()
|
||||
if type == 1:
|
||||
for item in c:
|
||||
if item <= 0:
|
||||
return False
|
||||
return True
|
||||
if type == 2:
|
||||
x = np.array(list(range(len(arr))))
|
||||
y = np.array(arr)
|
||||
line = np.polyfit(x, y, deg=1)
|
||||
return line[0] > 0
|
||||
|
||||
def updateRes(self, flag, day, row, code):
|
||||
key = "_%s"%day
|
||||
if flag: # 上升
|
||||
if not key in self.res_up.keys():
|
||||
self.res_up[key] = 0
|
||||
self.res_up[key] += 1
|
||||
|
||||
if not row['日期'] in self.up_res_group_by_date.keys():
|
||||
self.up_res_group_by_date[row['日期']] = {}
|
||||
if not key in self.up_res_group_by_date[row['日期']].keys():
|
||||
self.up_res_group_by_date[row['日期']][key] = []
|
||||
self.up_res_group_by_date[row['日期']][key].append(code)
|
||||
else:
|
||||
if not key in self.res_down.keys():
|
||||
self.res_down[key] = 0
|
||||
self.res_down[key] += 1
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
r = Raise()
|
||||
r.all()
|
||||
# r.count()
|
@ -0,0 +1,73 @@
|
||||
import sys
|
||||
import json
|
||||
import pandas as pd
|
||||
|
||||
class Unity(object):
|
||||
|
||||
def __init__(self):
|
||||
const_path = sys.path[0].replace("\\analyze_data", "")
|
||||
f = open(const_path + "\\const.json", "r", encoding="utf8")
|
||||
self.consts = json.loads(f.read())
|
||||
|
||||
def do(self):
|
||||
f1 = open(sys.path[0] + "\\hly_count_res_max_4_group_by_date.json", "r", encoding="utf-8")
|
||||
hly = json.loads(f1.read())
|
||||
|
||||
f2 = open(sys.path[0] + "\\zljc\\zljc_day_a.json", "r", encoding="utf-8")
|
||||
zljc = json.loads(f2.read())
|
||||
|
||||
res = {}
|
||||
for code in zljc:
|
||||
for a in zljc[code]:
|
||||
for day in zljc[code][a]:
|
||||
for date in zljc[code][a][day]["dates_yes"]:
|
||||
# 筛选 hly 中该日期的股票有没有当前这只
|
||||
if date in hly.keys() and code in hly[date]:
|
||||
if date not in res.keys(): res[date] = []
|
||||
if code not in res[date]: res[date].append(code)
|
||||
|
||||
|
||||
f3 = open(sys.path[0] + "\\hly_and_zljc_res.json", "w", encoding="utf-8")
|
||||
f3.write(json.dumps(res, ensure_ascii=False))
|
||||
f3.close()
|
||||
f2.close()
|
||||
f1.close()
|
||||
|
||||
def verify(self):
|
||||
f = open(sys.path[0] + "\\hly_and_zljc_res.json", "r", encoding="utf-8")
|
||||
res = json.loads(f.read())
|
||||
transform_dic = {}
|
||||
for date in res:
|
||||
for code in res[date]:
|
||||
if code not in transform_dic:
|
||||
transform_dic[code] = []
|
||||
transform_dic[code].append(date)
|
||||
# f3 = open(sys.path[0] + "\\hly_and_zljc_res_transform.json", "w", encoding="utf-8")
|
||||
# f3.write(json.dumps(transform_dic, ensure_ascii=False))
|
||||
# f3.close()
|
||||
|
||||
count = {
|
||||
"yes": 0,
|
||||
"no": 0
|
||||
}
|
||||
for code in transform_dic:
|
||||
print(code)
|
||||
try:
|
||||
df = pd.read_csv("%s%s.csv" % (self.consts['path']['result']['hly'], code), encoding="gbk")
|
||||
except:
|
||||
print("ERROR OPENING %s" % code)
|
||||
continue
|
||||
for index, row in df.iterrows():
|
||||
if row['日期'] in transform_dic[code]:
|
||||
if index - 5 > 0:
|
||||
if df.loc[index-5, "收盘价"] > row["收盘价"]:
|
||||
count["yes"] += 1
|
||||
else:
|
||||
count["no"] += 1
|
||||
|
||||
print(count)
|
||||
|
||||
if __name__ == "__main__":
|
||||
u = Unity()
|
||||
# u.do()
|
||||
u.verify()
|
@ -0,0 +1,116 @@
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
import pandas as pd
|
||||
import numpy as np
|
||||
from collections import deque
|
||||
from tqdm import tqdm
|
||||
|
||||
class ZLJCCalc(object):
|
||||
|
||||
def __init__(self):
|
||||
const_path = sys.path[0].replace("\\analyze_data\\zljc", "")
|
||||
f = open(const_path + "\\const.json", "r", encoding="utf8")
|
||||
self.consts = json.loads(f.read())
|
||||
|
||||
self.day_line_file_prefix = self.consts['day_line_file_prefix']['netease']
|
||||
self.data_clean_prefix = self.consts['day_line_file_prefix']['netease_clean'] + "new\\"
|
||||
self.zljc_path = self.consts['path']['result']['zljc']
|
||||
|
||||
def var1(self, close, low, high):
|
||||
return (close + low + high) / 3
|
||||
|
||||
def var2(self, var1, ref_low_1, high, vol, low, var2_yesterday):
|
||||
division = 1 if high == low else high - low
|
||||
var2_today = ((var1 - ref_low_1) - (high - var1)) * (vol / 100) / 100000 / division
|
||||
return float(var2_yesterday) + float(var2_today)
|
||||
|
||||
def ma(self, arr):
|
||||
res = 0
|
||||
for i in arr:
|
||||
res += i
|
||||
return res / len(arr)
|
||||
|
||||
def zljc(self, df):
|
||||
M = 12
|
||||
L = 26
|
||||
df['JCS'] = ""
|
||||
df['JCM'] = ""
|
||||
df['JCL'] = ""
|
||||
|
||||
ma_jcm = deque([])
|
||||
ma_jcl = deque([])
|
||||
sum_jcm = 0
|
||||
sum_jcl = 0
|
||||
|
||||
yesterday = pd.DataFrame([])
|
||||
for index, row in df[::-1].iterrows():
|
||||
var1 = self.var1(row['收盘价'], row['最低价'], row['最高价'])
|
||||
if yesterday.empty:
|
||||
df.loc[index, "JCS"] = self.var2(var1, row['最低价'], row['最高价'], row['成交量'], row['最低价'], 0)
|
||||
df.loc[index, "JCM"] = 0
|
||||
df.loc[index, "JCL"] = 0
|
||||
else:
|
||||
var3 = self.var2(var1, yesterday['最低价'], row['最高价'], row['成交量'], row['最低价'], yesterday['JCS'])
|
||||
df.loc[index, "JCS"] = var3
|
||||
ma_jcm.append(var3)
|
||||
ma_jcl.append(var3)
|
||||
sum_jcm += var3
|
||||
sum_jcl += var3
|
||||
if len(ma_jcm) < M: # 不够计算 MA
|
||||
df.loc[index, "JCM"] = 0
|
||||
else: # 计算 MA
|
||||
df.loc[index, "JCM"] = sum_jcm / M
|
||||
sum_jcm -= ma_jcm.popleft()
|
||||
|
||||
if len(ma_jcl) < L: # 不够计算 MA
|
||||
df.loc[index, "JCL"] = 0
|
||||
else: # 计算 MA
|
||||
df.loc[index, "JCL"] = sum_jcl / L
|
||||
sum_jcl -= ma_jcl.popleft()
|
||||
yesterday = df.loc[index]
|
||||
return df
|
||||
|
||||
|
||||
def handle_one(self, code):
|
||||
try:
|
||||
# df = pd.read_csv("%s%s.csv" % (self.day_line_file_prefix, code), encoding="gbk")
|
||||
df = pd.read_csv("%s%s.csv" % (self.data_clean_prefix, code), encoding="gbk")
|
||||
except:
|
||||
print("\nERROR OPEING %s.csv")
|
||||
return
|
||||
df = self.zljc(df)
|
||||
df.to_csv("%s%s.csv" % (self.zljc_path, code), encoding="gbk",index=None)
|
||||
|
||||
def handle_all(self):
|
||||
filelist = os.listdir(self.data_clean_prefix)
|
||||
for i in tqdm(range(len(filelist))):
|
||||
code = filelist[i][0:6]
|
||||
self.handle_one(code)
|
||||
|
||||
def module_export(self):
|
||||
for file in os.listdir(self.zljc_path):
|
||||
try:
|
||||
df = pd.read_csv(self.zljc_path + file , encoding="gbk")
|
||||
except:
|
||||
print("ERROR OPENING %s" % file)
|
||||
continue
|
||||
f = open("%sjs\\%s.js" %(self.zljc_path, file[0:6]),"w", encoding="utf-8")
|
||||
f.write('''module.exports=[
|
||||
''')
|
||||
for index,row in df.iterrows():
|
||||
f.write('''{
|
||||
date: '%s',
|
||||
jcs: %.2f,
|
||||
jcm: %.2f,
|
||||
jcl: %.2f,
|
||||
},''' % (row['日期'], row['JCS'], row['JCM'], row['JCL']))
|
||||
f.write('''
|
||||
]''')
|
||||
f.close()
|
||||
|
||||
if __name__ == "__main__":
|
||||
zljc = ZLJCCalc()
|
||||
# zljc.handle_one('000001')
|
||||
zljc.handle_all()
|
||||
# zljc.module_export()
|
@ -0,0 +1,147 @@
|
||||
import sys
|
||||
import json
|
||||
import pandas as pd
|
||||
from collections import deque
|
||||
import copy
|
||||
import numpy as np
|
||||
import os
|
||||
from tqdm import tqdm
|
||||
|
||||
class ZljcRaisePoint(object):
|
||||
|
||||
def __init__(self, judge_days=3, limit_a=[1], after_days=[3,4,5,6,7]):
|
||||
const_path = sys.path[0].replace("\\analyze_data\\zljc", "")
|
||||
f = open(const_path + "\\const.json", "r", encoding="utf8")
|
||||
self.consts = json.loads(f.read())
|
||||
|
||||
self.zljc_path = self.consts['path']['result']['zljc']
|
||||
self.judge_days = judge_days # 计算回归拟合的天数
|
||||
self.res = {}
|
||||
self.limit_a = limit_a
|
||||
self.after_days = after_days
|
||||
self.k_arr = []
|
||||
|
||||
def one(self, code):
|
||||
try:
|
||||
df = pd.read_csv("%s%s.csv" %(self.zljc_path, code) , encoding="gbk")
|
||||
except:
|
||||
print("ERROR OPEN %s" % code)
|
||||
return
|
||||
jcs = deque([])
|
||||
jcm = deque([])
|
||||
jcl = deque([])
|
||||
self.k_arr = []
|
||||
|
||||
for index,row in df[::-1].iterrows():
|
||||
if row['日期'] < '2014-01-01':continue
|
||||
jcs.append(row["JCS"])
|
||||
jcm.append(row["JCM"])
|
||||
jcl.append(row["JCL"])
|
||||
|
||||
if (len(jcs) < self.judge_days):
|
||||
continue
|
||||
# 1. 最后一天的 `JCS > JCM and JCS > JCL`
|
||||
if (jcs[-1] < jcm[-1] or jcs[-1] < jcl[-1]):
|
||||
jcs.popleft()
|
||||
jcm.popleft()
|
||||
jcl.popleft()
|
||||
continue
|
||||
if (jcs[-1]-max(jcm[-1], jcl[-1])) < 2 * abs(jcm[-1] - jcl[-1]):
|
||||
jcs.popleft()
|
||||
jcm.popleft()
|
||||
jcl.popleft()
|
||||
continue
|
||||
# 2. 前一日之前的所有 `JCS` 必须在 `JCM` 或 `JCL` 下方 ********
|
||||
# 2. 前一日之前的所有 `JCS` 不得远大于 `JCM` 或 `JCL`
|
||||
flag = True
|
||||
for i in range(self.judge_days - 2):
|
||||
# if jcs[i] > jcm[i] or jcs[i] > jcl[i]:
|
||||
if (jcs[i]-max(jcm[i], jcl[i])) > 2 * abs(jcm[i] - jcl[i]):
|
||||
flag = False
|
||||
if not flag:
|
||||
jcs.popleft()
|
||||
jcm.popleft()
|
||||
jcl.popleft()
|
||||
continue
|
||||
# 3. 第二日趋势为上升
|
||||
for a in self.limit_a:
|
||||
# 检查是否满足条件
|
||||
if self.is_raise(jcs, a):
|
||||
# 验证 n 天后是否价格上涨
|
||||
for day in self.after_days:
|
||||
if index - day < 0: continue
|
||||
# print(code, ":", row['日期'])
|
||||
self.update_res(a,day,code, row['日期'], df.loc[index-day, "收盘价"] > row['收盘价'])
|
||||
# print(self.res)
|
||||
# print(self.res)
|
||||
|
||||
def all(self):
|
||||
filelist = os.listdir(self.zljc_path)
|
||||
for i in tqdm(range(len(filelist))):
|
||||
self.one(filelist[i][0:6])
|
||||
f = open("%s\\zljc_day_a.json" % sys.path[0], "w", encoding="utf-8")
|
||||
f.write(json.dumps(self.res, ensure_ascii=False))
|
||||
f.close()
|
||||
|
||||
def is_raise(self, arr, limit_a, type=1):
|
||||
if type == 2:
|
||||
x = np.array(list(range(len(arr))))
|
||||
y = np.array(arr)
|
||||
line = np.polyfit(x,y,deg=2)
|
||||
return (line[0] > 0 and line[0] >= limit_a) and (-1 * line[1] / (2*line[0]) <= 0)
|
||||
if type == 1:
|
||||
x = np.array(list(range(len(arr))))
|
||||
y = np.array(arr)
|
||||
line = np.polyfit(x, y, deg=1)
|
||||
self.k_arr.append(line[0])
|
||||
if len(self.k_arr) < 2: return False
|
||||
return self.k_arr[-1]>0 and self.k_arr[-1] / self.k_arr[-2] > limit_a
|
||||
|
||||
def update_res(self, a, day, code, date, flag):
|
||||
if code not in self.res.keys():
|
||||
self.res[code] = {}
|
||||
if a not in self.res[code].keys():
|
||||
self.res[code][a] = {}
|
||||
if day not in self.res[code][a].keys():
|
||||
self.res[code][a][day] = {}
|
||||
if "yes" not in self.res[code][a][day].keys():
|
||||
self.res[code][a][day]['yes'] = 0
|
||||
if "no" not in self.res[code][a][day].keys():
|
||||
self.res[code][a][day]['no'] = 0
|
||||
if "dates_yes" not in self.res[code][a][day].keys():
|
||||
self.res[code][a][day]['dates_yes'] = []
|
||||
if "dates_no" not in self.res[code][a][day].keys():
|
||||
self.res[code][a][day]['dates_no'] = []
|
||||
if flag:
|
||||
self.res[code][a][day]['dates_yes'].append(date)
|
||||
self.res[code][a][day]['yes'] += 1
|
||||
else:
|
||||
self.res[code][a][day]['dates_no'].append(date)
|
||||
self.res[code][a][day]['no'] += 1
|
||||
|
||||
def count(self):
|
||||
path = sys.path[0]
|
||||
f = open("%s\\zljc_day_a.json" % (sys.path[0]), "r", encoding="utf8")
|
||||
res = json.loads(f.read())
|
||||
count = {}
|
||||
for code in res:
|
||||
for a in res[code]:
|
||||
if not a in count.keys():
|
||||
count[a] = {}
|
||||
for day in res[code][a]:
|
||||
if not day in count[a].keys():
|
||||
count[a][day] = {"yes": 0, "no": 0}
|
||||
count[a][day]["yes"] += res[code][a][day]["yes"]
|
||||
count[a][day]["no"] += res[code][a][day]["no"]
|
||||
f = open("%s\\zljc_day_a_count.json" % sys.path[0], "w", encoding="utf-8")
|
||||
f.write(json.dumps(count, ensure_ascii=False))
|
||||
f.close()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# limit_a = [0.010, 0.0125, 0.015, 0.0175, 0.020]
|
||||
limit_a = [1.5, 1.75, 2]
|
||||
after_days = [3,4,5]
|
||||
z = ZljcRaisePoint(limit_a=limit_a, after_days=after_days)
|
||||
z.all()
|
||||
# z.count()
|
@ -0,0 +1,16 @@
|
||||
{
|
||||
"1.5": {
|
||||
"3": {
|
||||
"yes": 18903,
|
||||
"no": 20586
|
||||
},
|
||||
"4": {
|
||||
"yes": 18805,
|
||||
"no": 20678
|
||||
},
|
||||
"5": {
|
||||
"yes": 19096,
|
||||
"no": 20385
|
||||
}
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 80 KiB |
After Width: | Height: | Size: 53 KiB |
After Width: | Height: | Size: 26 KiB |
@ -0,0 +1,10 @@
|
||||
{
|
||||
"folders": [
|
||||
{
|
||||
"key": "696069852956fa92307d",
|
||||
"color": "#30D5C8",
|
||||
"name": "doc"
|
||||
}
|
||||
],
|
||||
"version": "1.0"
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
import pandas as pd
|
||||
import time
|
||||
from tqdm import tqdm
|
||||
|
||||
class CountInvalidData(object):
|
||||
|
||||
def __init__(self, end_date="20140101"):
|
||||
const_path = sys.path[0].replace("\\clean_data", "")
|
||||
f = open(const_path + "\\const.json", "r", encoding="utf8")
|
||||
self.consts = json.loads(f.read())
|
||||
self.end_date = end_date
|
||||
self.day_line_file_prefix = self.consts["day_line_file_prefix"]["netease"]
|
||||
self.COUNT_INVALID_DATA = 0
|
||||
self.COUNT_INVALID_CODE = 0
|
||||
|
||||
def handle_one(self, code):
|
||||
try:
|
||||
df = pd.read_csv("%s%s.csv" % (self.day_line_file_prefix, code), encoding="gbk", error_bad_lines=False)
|
||||
except:
|
||||
print("ERROR While Opening Code %s" % code )
|
||||
return
|
||||
all_right = True
|
||||
for index,row in df.iterrows():
|
||||
if row['日期'] < self.end_date: break
|
||||
flag = True # 标记是否有效
|
||||
# 遍历行中的每一项
|
||||
for i,val in row.items():
|
||||
if val == "None" or val == "NaN" or (val == 0 and (i[:2] != '涨跌')):
|
||||
flag = False
|
||||
all_right = False
|
||||
self.COUNT_INVALID_DATA += 1
|
||||
break
|
||||
|
||||
if not all_right:
|
||||
self.COUNT_INVALID_CODE += 1
|
||||
|
||||
|
||||
def handle_all(self):
|
||||
time_start = time.time()
|
||||
file_list = os.listdir(self.day_line_file_prefix)
|
||||
file_count = len(file_list)
|
||||
for i in tqdm(range(file_count)):
|
||||
file = file_list[i]
|
||||
code = file[0:6]
|
||||
self.handle_one(code)
|
||||
# time.sleep(1)
|
||||
print("无效的数据数量:", self.COUNT_INVALID_DATA)
|
||||
print("有无效数据的股票数量:", self.COUNT_INVALID_CODE)
|
||||
time_end = time.time()
|
||||
time_c= time_end - time_start #运行所花时间
|
||||
print('time cost:', time_c, 's')
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
cid = CountInvalidData()
|
||||
cid.handle_all()
|
@ -0,0 +1,38 @@
|
||||
import os
|
||||
import sys
|
||||
import pandas as pd
|
||||
import json
|
||||
import time
|
||||
from tqdm import tqdm
|
||||
|
||||
class HandleNaN(object):
|
||||
|
||||
def __init__(self):
|
||||
const_path = sys.path[0].replace("\\clean_data", "")
|
||||
f = open(const_path + "\\const.json", "r", encoding="utf8")
|
||||
self.consts = json.loads(f.read())
|
||||
|
||||
self.dayline_file_prefix = self.consts["day_line_file_prefix"]['netease']
|
||||
|
||||
def handle_one(self,code):
|
||||
try:
|
||||
df = pd.read_csv("%s%s.csv" % (self.dayline_file_prefix, code), encoding="gbk")
|
||||
except:
|
||||
print("error")
|
||||
return
|
||||
df = df[df['日期'] > "20140101"]
|
||||
return df.isna().any().any()
|
||||
|
||||
def handle_all(self):
|
||||
time_start = time.time()
|
||||
file_list = os.listdir(self.dayline_file_prefix)
|
||||
for i in tqdm(range(len(file_list))):
|
||||
if self.handle_one(file_list[i][0:6]): print(file_list[i])
|
||||
time_end = time.time()
|
||||
time_c= time_end - time_start
|
||||
print("Finished! Take %s Seconds" % time_c)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
hn = HandleNaN()
|
||||
hn.handle_all()
|
@ -0,0 +1,107 @@
|
||||
import sys
|
||||
import json
|
||||
import pandas as pd
|
||||
import tushare as ts
|
||||
import os
|
||||
from tqdm import tqdm
|
||||
|
||||
import time
|
||||
import random
|
||||
|
||||
class DataClean(object):
|
||||
|
||||
def __init__(self, end_date="20120101"):
|
||||
const_path = sys.path[0].replace("\\clean_data", "")
|
||||
f = open(const_path + "\\const.json", "r", encoding="utf8")
|
||||
self.consts = json.loads(f.read())
|
||||
|
||||
self.end_date = end_date
|
||||
self.tushare_token = self.consts["tushare"]["token"]
|
||||
self.day_line_file_prefix = self.consts["day_line_file_prefix"]["netease"]
|
||||
self.COUNT_INVALID_DATA = 0
|
||||
self.COUNT_INVALID_CODE = 0
|
||||
|
||||
# 处理单只股票
|
||||
def handle_one(self, code):
|
||||
# handled = self.is_handled(code)
|
||||
# if handled: return
|
||||
try:
|
||||
df = pd.read_csv("%s%s.csv" % (self.day_line_file_prefix, code), encoding="gbk", error_bad_lines=False)
|
||||
except:
|
||||
print("ERROR While Opening Code %s" % code )
|
||||
return
|
||||
newData = pd.DataFrame([],columns=df.columns)
|
||||
codeInfo = pd.Series([])
|
||||
for index,row in df.iterrows():
|
||||
if row['日期'] < self.end_date: continue
|
||||
flag = True # 标记是否有效
|
||||
new_row = row
|
||||
# 遍历行中的每一项
|
||||
for i,val in row.items():
|
||||
if val == "None" or val == "NaN" or (val == 0 and (i[:2] != '涨跌')):
|
||||
flag = False
|
||||
if codeInfo.empty:
|
||||
try:
|
||||
codeInfo = pd.read_csv("%s%s.csv"%(self.consts['day_line_file_prefix']['tushare'], code), encoding="gbk")
|
||||
except:
|
||||
print("打开tushare %s失败" % code)
|
||||
invalid_date = "".join(row['日期'].split("-"))
|
||||
try:
|
||||
tushare_row = codeInfo.loc[codeInfo['trade_date']==invalid_date]
|
||||
except:
|
||||
tushare_row = pd.Series([])
|
||||
if not tushare_row.empty: # tushare 有这一天的数据
|
||||
new_row = pd.Series([
|
||||
row['日期'], # 日期
|
||||
row['股票代码'], # 股票代码
|
||||
row['名称'], # 名称
|
||||
tushare_row['close'], # 收盘价
|
||||
tushare_row['high'], # 最高价
|
||||
tushare_row['low'], # 最低价
|
||||
tushare_row['open'], # 开盘价
|
||||
tushare_row['prev_close'], # 前收盘
|
||||
tushare_row['change'], # 涨跌额
|
||||
tushare_row['pct_chg'], # 涨跌幅
|
||||
0, # 换手率
|
||||
tushare_row['vol'], # 成交量
|
||||
tushare_row['amount'], # 成交额
|
||||
row['总市值'], # 总市值
|
||||
row['流通市值'], # 流通市值
|
||||
], columns=df.columns)
|
||||
newData.loc[len(newData.index)] = new_row
|
||||
break # 该行以发现无效数据, 整行处理, 不继续遍历改行的剩余元素
|
||||
if (not flag):
|
||||
# print("[%s.csv] 在 [%s] 数据无效;" % (code, row['日期']))
|
||||
self.COUNT_INVALID_DATA += 1 # 埋点,统计无效的数据数量
|
||||
else:
|
||||
newData.loc[len(newData.index)] = row
|
||||
|
||||
if not codeInfo.empty: self.COUNT_INVALID_CODE+=1 # 埋点,统计无效的股票数量
|
||||
newData.to_csv('%s%s.csv'%(self.consts['day_line_file_prefix']['netease_clean'], code), encoding="gbk")
|
||||
|
||||
def handle_all(self):
|
||||
time_start = time.time()
|
||||
file_list = os.listdir(self.day_line_file_prefix)
|
||||
file_count = len(file_list)
|
||||
for i in tqdm(range(file_count)):
|
||||
file = file_list[i]
|
||||
code = file[0:6]
|
||||
self.handle_one(code)
|
||||
# time.sleep(1)
|
||||
print("无效的数据数量:", self.COUNT_INVALID_DATA)
|
||||
print("有无效数据的股票数量:", self.COUNT_INVALID_CODE)
|
||||
time_end = time.time()
|
||||
time_c= time_end - time_start #运行所花时间
|
||||
print('time cost: %s Seconds' % time_c)
|
||||
|
||||
def is_handled(self, code):
|
||||
try:
|
||||
df = pd.read_csv('%snew\\%s.csv'%(self.consts['day_line_file_prefix']['netease_clean'], code), encoding="gbk")
|
||||
return True
|
||||
except:
|
||||
return False
|
||||
|
||||
if __name__ == "__main__":
|
||||
data_clean = DataClean()
|
||||
# data_clean.handle_one('000503')
|
||||
data_clean.handle_all()
|
@ -0,0 +1,40 @@
|
||||
{
|
||||
"tushare": {
|
||||
"token": "ur tushare token",
|
||||
"username": "ur tushare username"
|
||||
},
|
||||
"type": "https",
|
||||
"check_url1": "https://vip.stock.finance.sina.com.cn/quotes_service/api/json_v2.php/Market_Center.getHQNodeData?page=2&num=40&sort=amount&asc=0&node=hs_a&symbol=&_s_r_a=auto",
|
||||
"check_url": "https://www.baidu.com",
|
||||
"mysql": {
|
||||
"host": "localhost",
|
||||
"port": 3306,
|
||||
"username": "root",
|
||||
"password": "",
|
||||
"database": "tourist_route"
|
||||
},
|
||||
"libs": [
|
||||
"requests",
|
||||
"BeautifulSoup4"
|
||||
],
|
||||
"day_line_file_prefix": {
|
||||
"netease": "E:\\files\\stock\\dayline\\netease\\",
|
||||
"netease_clean": "E:\\files\\stock\\dayline\\clean\\",
|
||||
"ease_money": "E:\\files\\stock\\dayline\\eastMoney\\",
|
||||
"tushare": "E:\\files\\stock\\dayline\\tushare\\",
|
||||
"with_my_result": "E:\\files\\stock\\dayline\\with_my_result\\"
|
||||
},
|
||||
"stock_list_file": "E:\\files\\stock\\code_list.csv",
|
||||
"macd_img_path": "E:\\files\\stock\\dayline\\macd_img\\",
|
||||
"path": {
|
||||
"stock_list": {
|
||||
"sina": "E:\\files\\stock\\stock_list\\sina_list",
|
||||
"netease": "E:\\files\\stock\\stock_list\\netease_list",
|
||||
"tushare": "E:\\files\\stock\\stock_list\\tushare"
|
||||
},
|
||||
"result": {
|
||||
"hly": "E:\\files\\stock\\dayline\\hly_new_2\\",
|
||||
"zljc": "E:\\files\\stock\\dayline\\zljc\\"
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,146 @@
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import json
|
||||
import requests
|
||||
import random
|
||||
import urllib
|
||||
import http.client
|
||||
import csv
|
||||
from bs4 import BeautifulSoup
|
||||
try:
|
||||
import ip as ipmanage
|
||||
except:
|
||||
from download import ip as ipmanage
|
||||
|
||||
class Downloader(object):
|
||||
|
||||
def __init__(self):
|
||||
self.ip_pool = []
|
||||
self.headers = {
|
||||
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36'
|
||||
}
|
||||
|
||||
# 初始化IP池
|
||||
def init_ip_pool(self, ip_num=100):
|
||||
try:
|
||||
t = os.path.getmtime(sys.path[0] + "\\ip_pool.json")
|
||||
flag = True
|
||||
except:
|
||||
flag = False
|
||||
if flag and time.time() - t < 3600: # ip池未过期, 调用本地缓存
|
||||
f = open(sys.path[0] + "\\ip_pool.json", "r", encoding="utf8")
|
||||
self.ip_pool = json.loads(f.read())
|
||||
else:
|
||||
ip_manage = ipmanage.IpManage(max_ip_num=ip_num)
|
||||
ip_manage.craw_ips()
|
||||
self.ip_pool = ip_manage.ip_pool
|
||||
|
||||
# get 请求
|
||||
def requests_get(self, url, type, data=None):
|
||||
response = requests.get(url=url, headers=self.headers, data=data)
|
||||
if response.status_code == 200:
|
||||
# request successfully
|
||||
if type == "img":
|
||||
# 获取图片
|
||||
return response.content
|
||||
if type == "html":
|
||||
html = response.content
|
||||
# html_content = str(html,'utf-8')
|
||||
html_content = html.decode("utf-8","ignore")
|
||||
return html_content
|
||||
if type == "text":
|
||||
return response.text
|
||||
if type == "json":
|
||||
return response.content
|
||||
else:
|
||||
print("Request Falied For Code: %s" % response.status_code)
|
||||
return "0"
|
||||
|
||||
# post 请求
|
||||
def requests_post(self, url, type, data=None):
|
||||
response = requests.post(url=url, headers=self.headers, data=data)
|
||||
if response.status_code == 200:
|
||||
# request successfully
|
||||
if type == "img":
|
||||
# 获取图片
|
||||
return response.content
|
||||
if type == "html":
|
||||
html = response.content
|
||||
# html_content = str(html,'utf-8')
|
||||
html_content = html.decode("utf-8","ignore")
|
||||
return html_content
|
||||
if type == "text":
|
||||
return response.text
|
||||
else:
|
||||
print("Request Falied For Code: %s" % response.status_code)
|
||||
|
||||
def download_netease_csv(self, url, filepath):
|
||||
# response = requests.get(url=url)
|
||||
# with open(filepath, "wb", encoding="gbk") as f:
|
||||
# f.write(response.content)
|
||||
http.client.HTTPConnection._http_vsn = 10
|
||||
http.client.HTTPConnection._http_vsn_str = 'HTTP/1.0'
|
||||
urllib.request.urlretrieve(url, filepath)
|
||||
|
||||
|
||||
# 通过代理发起 get 请求
|
||||
def proxy_get(self, url, type, data=None):
|
||||
# try:
|
||||
ip = self.ip_pool[random.randint(0, len(self.ip_pool)-1)]
|
||||
proxy = {
|
||||
"http": "http://%s:%s" % (ip['ip'], ip['port'])
|
||||
}
|
||||
print(proxy)
|
||||
response = requests.get(url, proxies=proxy, headers=self.headers, data=data)
|
||||
# response = requests.get(url=url, headers=self.headers, data=data)
|
||||
if response.status_code == 200:
|
||||
# request successfully
|
||||
if type == "img":
|
||||
# 获取图片
|
||||
return response.content
|
||||
if type == "html":
|
||||
html = response.content
|
||||
# html_content = str(html,'utf-8')
|
||||
html_content = html.decode("utf-8","ignore")
|
||||
return html_content
|
||||
if type == "text":
|
||||
return response.text
|
||||
else:
|
||||
print("Request Falied For Code: %s" % response.status_code)
|
||||
return "0"
|
||||
# except:
|
||||
# return "0"
|
||||
|
||||
# 通过 代理ip平台的ip获取get请求
|
||||
def zhilian_ip_proxy_get(self, url):
|
||||
zhilian_ip_json_path = sys.path[0].split("quant-on-volume")[0] + "quant-on-volume\\zhilian_ip.json"
|
||||
f = open(zhilian_ip_json_path, 'r', encoding="utf-8")
|
||||
ips = json.loads(f.read())
|
||||
while True:
|
||||
ip = ips[random.randint(0, len(ips)-1)] # 随机 ip
|
||||
try:
|
||||
proxy = {
|
||||
"http": "http://%s:%s" % (ip['IP'], ip['Port']),
|
||||
"https": "http://%s:%s" % (ip['IP'], ip['Port'])
|
||||
}
|
||||
response = requests.get(url, proxies=proxy, headers=self.headers, timeout=1)
|
||||
if response.status_code == 200:
|
||||
return response.content
|
||||
elif response.status_code == 503:
|
||||
self.init_zhilian_ip()
|
||||
else:
|
||||
print("http://%s:%s" % (ip['IP'], ip['Port']), ":FAILED-1")
|
||||
continue
|
||||
except:
|
||||
print("http://%s:%s" % (ip['IP'], ip['Port']), ":FAILED-2")
|
||||
|
||||
# 初始化 智联 ip
|
||||
def init_zhilian_ip(self):
|
||||
# url = input("输入api:\n")
|
||||
url = "http://t.11jsq.com/index.php/api/entry?method=proxyServer.generate_api_url&packid=1&fa=0&fetch_key=&qty=100&time=1&pro=&city=&port=1&format=json&ss=5&css=&dt=1&specialTxt=3&specialJson=&usertype=16"
|
||||
response = requests.get(url)
|
||||
ips = json.loads(response.content)['data']
|
||||
zhilian_ip_json_path = sys.path[0].split("quant-on-volume")[0] + "quant-on-volume\\zhilian_ip.json"
|
||||
with open(zhilian_ip_json_path, "w") as f:
|
||||
json.dump(ips, f)
|
@ -0,0 +1,134 @@
|
||||
import sys
|
||||
from download import download
|
||||
import json
|
||||
import time
|
||||
import random
|
||||
|
||||
import pandas as pd
|
||||
from tqdm import tqdm
|
||||
|
||||
request_params = [
|
||||
{ "key":"rtntype",
|
||||
"value":"5",
|
||||
"equals":True,
|
||||
"description":"",
|
||||
"enabled":True
|
||||
},
|
||||
|
||||
{ "key":"token",
|
||||
"value":"4f1862fc3b5e77c150a2b985b12db0fd",
|
||||
"equals":True,
|
||||
"description":"",
|
||||
"enabled":True
|
||||
},
|
||||
|
||||
{ "key":"cb",
|
||||
"value":"jQuery1124036208821942748104_1574562443091",
|
||||
"equals":True,
|
||||
"description":"",
|
||||
"enabled":True
|
||||
},
|
||||
|
||||
{ "key":"id",
|
||||
"value":"%s",
|
||||
"equals":True,
|
||||
"description":"",
|
||||
"enabled":True
|
||||
},
|
||||
|
||||
{ "key":"type",
|
||||
"value":"k",
|
||||
"equals":True,
|
||||
"description":"",
|
||||
"enabled":True
|
||||
},
|
||||
|
||||
{ "key":"authorityType",
|
||||
"value":"",
|
||||
"equals":True,
|
||||
"description":"",
|
||||
"enabled":True
|
||||
},
|
||||
|
||||
{ "key":"_",
|
||||
"value":"1574509941411",
|
||||
"equals":True,
|
||||
"description":"",
|
||||
"enabled":True}
|
||||
]
|
||||
URI = "http://pdfm.eastmoney.com/EM_UBG_PDTI_Fast/api/js?"
|
||||
|
||||
for param in request_params:
|
||||
URI += '%s=%s&' % (param["key"], param["value"])
|
||||
|
||||
class EastMoneyDayLine(object):
|
||||
|
||||
def __init__(self, end_date='00000000'):
|
||||
|
||||
const_path = sys.path[0].replace("\\craw_data\\dayline", "")
|
||||
f = open(const_path + "\\const.json", "r", encoding="utf8")
|
||||
self.consts = json.loads(f.read())
|
||||
|
||||
self.stock_list_file = self.consts['stock_list_file'] # 全部股票信息的csv文件
|
||||
self.save_path_prefix = self.consts['day_line_file_prefix']['ease_money'] # 日线存储文件夹目录
|
||||
self.end_date = end_date # 截止日期
|
||||
self.codes = self.get_codes()
|
||||
|
||||
self.downloader = download.Downloader() # 下载器
|
||||
|
||||
def craw_one(self, code):
|
||||
url = URI % self.process_code(code)
|
||||
content = self.handle_jsonp(self.downloader.requests_get(url, type="json").decode("utf8"))
|
||||
# print(content)
|
||||
data = json.loads(content)
|
||||
self.save_json_to_csv(data, code)
|
||||
|
||||
def get_codes(self):
|
||||
try:
|
||||
df = pd.read_csv(self.stock_list_file, encoding="gbk", error_bad_lines=False)
|
||||
except:
|
||||
print("ERROR Opening File: %s" % self.stock_list_file)
|
||||
return False
|
||||
|
||||
codes = []
|
||||
for index, row in df.iterrows():
|
||||
codes.append(row['股票代码'][1:])
|
||||
return codes
|
||||
|
||||
def save_json_to_csv(self, data, code):
|
||||
realdata = data['data']
|
||||
f = open(self.save_path_prefix + str(code) + ".csv", "w", encoding="gbk")
|
||||
f.write(",".join(['日期', '开盘', '收盘', '最高', '最低', '成交量', '成交额', '振幅']))
|
||||
f.write("\n")
|
||||
for row in realdata[:-1]:
|
||||
if ("".join(row[:10].split("-")) < self.end_date): continue
|
||||
f.write(row[:-2])
|
||||
f.write("\n")
|
||||
f.close()
|
||||
|
||||
def process_code(self, code):
|
||||
return '%s1' % code
|
||||
|
||||
def handle_jsonp(self, response_content):
|
||||
return response_content[response_content.find("{"):-1]
|
||||
|
||||
def check_is_downloaded(self, code):
|
||||
try:
|
||||
df = pd.read_csv(self.save_path_prefix + code + ".csv")
|
||||
return True
|
||||
except:
|
||||
return False
|
||||
|
||||
|
||||
def controller(self):
|
||||
for i in tqdm(range(len(self.codes))):
|
||||
code = self.codes[i]
|
||||
if (self.check_is_downloaded(code)) return
|
||||
self.craw_one(code)
|
||||
time.sleep(random.random()*2)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
east_money_day_line = EastMoneyDayLine()
|
||||
east_money_day_line.controller()
|
||||
# east_money_day_line.craw_one(600175) # test craw
|
@ -0,0 +1,71 @@
|
||||
import sys
|
||||
import json
|
||||
import pandas as pd
|
||||
import tushare as ts
|
||||
import os
|
||||
from tqdm import tqdm
|
||||
|
||||
import time
|
||||
import random
|
||||
|
||||
const_path = sys.path[0].replace("craw_data\\dayline", "")
|
||||
f = open(const_path + "\\const.json", "r", encoding="utf8")
|
||||
consts = json.loads(f.read())
|
||||
ts.set_token(consts["tushare"]["token"])
|
||||
pro = ts.pro_api()
|
||||
|
||||
class TuShareDayline(object):
|
||||
|
||||
def __init__(self,start_date="20140101", end_date="20191111"):
|
||||
const_path = sys.path[0].replace("craw_data\\dayline", "")
|
||||
f = open(const_path + "\\const.json", "r", encoding="utf8")
|
||||
self.consts = json.loads(f.read())
|
||||
|
||||
self.start_date = start_date
|
||||
self.end_date = end_date
|
||||
self.stock_list_prefix = self.consts['path']['stock_list']['tushare']
|
||||
self.tushare_token = self.consts["tushare"]["token"]
|
||||
self.day_line_file_prefix = self.consts["day_line_file_prefix"]["tushare"]
|
||||
|
||||
|
||||
def craw_one(self, code):
|
||||
if self.check_is_downloaded(code):
|
||||
print("%s已下载"%code)
|
||||
return
|
||||
try:
|
||||
codeInfo = pro.daily(ts_code=code, start_date=self.start_date, end_date=self.end_date)
|
||||
codeInfo.to_csv('%s%s.csv'%(self.day_line_file_prefix,code[0:6]), encoding="gbk", index=0)
|
||||
return True
|
||||
except:
|
||||
print("调用接口失败")
|
||||
for i in range(60):
|
||||
print("SLEEPING.....................%s" % (60-i))
|
||||
time.sleep(1)
|
||||
return False
|
||||
|
||||
|
||||
|
||||
def check_is_downloaded(self, code):
|
||||
file_list = os.listdir(self.day_line_file_prefix)
|
||||
return (code[0:6] + ".csv") in file_list
|
||||
|
||||
def get_all(self):
|
||||
df = pd.read_csv(self.stock_list_prefix+'\\tushare.csv', encoding="gbk")
|
||||
count = df.index.size
|
||||
|
||||
LIMIT = 100
|
||||
|
||||
for index,row in df.iterrows():
|
||||
print("%s/%s-----------%s" % (index+1, count, (index+1)/count))
|
||||
completed = self.craw_one(row['ts_code'])
|
||||
if LIMIT == 0:
|
||||
LIMIT = 100
|
||||
for i in range(60):
|
||||
print("SLEEPING.....................%s" % (60-i))
|
||||
time.sleep(1)
|
||||
if completed: LIMIT -= 1
|
||||
|
||||
if __name__ == "__main__":
|
||||
tsd = TuShareDayline()
|
||||
# tsd.craw_one('000001')
|
||||
tsd.get_all()
|
@ -0,0 +1,44 @@
|
||||
import sys
|
||||
sys.path.append(sys.path[0].replace('stock_list', '') + 'dayline')
|
||||
from download import download
|
||||
import json
|
||||
from tqdm import tqdm
|
||||
import ast
|
||||
|
||||
uri = "http://vip.stock.finance.sina.com.cn/quotes_service/api/json_v2.php/Market_Center.getHQNodeData?page=%s&num=40&sort=amount&asc=0&node=hs_a&symbol=&_s_r_a=auto"
|
||||
|
||||
class SinaStockList(object):
|
||||
|
||||
def __init__(self):
|
||||
const_path = sys.path[0].replace("\\craw_data\\stock_list", "")
|
||||
f = open(const_path + '\\const.json', 'r', encoding='utf8')
|
||||
self.consts = json.loads(f.read())
|
||||
|
||||
self.downloader = download.Downloader()
|
||||
# self.downloader.init_zhilian_ip() # 使用代理 ip (付费)
|
||||
# self.downloader.init_ip_pool() # 使用代理 ip (免费)
|
||||
|
||||
self.arr = []
|
||||
|
||||
def get_stock_list(self, max_page=100):
|
||||
for i in tqdm(range(max_page)):
|
||||
res = self.downloader.requests_get(uri % i).decode("gbk","ignore")
|
||||
# res = self.downloader.zhilian_ip_proxy_get(uri % i).decode("gbk","ignore")
|
||||
if res == "null":
|
||||
continue
|
||||
res = json.loads(self.json_format(res))
|
||||
# print(res)
|
||||
self.arr.extend(res)
|
||||
with open(self.consts['path']['stock_list']['sina'] + "\\stock_list.json", "w", encoding="utf-8") as f:
|
||||
json.dump(self.arr, f, ensure_ascii=False)
|
||||
|
||||
def json_format(self, str):
|
||||
import re
|
||||
str = re.sub(u'{([^{:]*):', u'{"\\1":', str)
|
||||
str = re.sub(u',([^,:{]*):', u',"\\1":', str)
|
||||
str = str.replace(' ', '')
|
||||
return str
|
||||
|
||||
if __name__ == "__main__":
|
||||
sina_stock_list = SinaStockList()
|
||||
sina_stock_list.get_stock_list()
|
@ -0,0 +1,16 @@
|
||||
import tushare as ts
|
||||
import pandas as pd
|
||||
import sys
|
||||
import json
|
||||
|
||||
const_path = sys.path[0].replace("craw_data\\stock_list", "")
|
||||
f = open(const_path + "\\const.json", "r", encoding="utf8")
|
||||
consts = json.loads(f.read())
|
||||
|
||||
ts.set_token(consts["tushare"]["token"])
|
||||
pro = ts.pro_api()
|
||||
data = pro.stock_basic(exchange='', list_status='L', fields='ts_code,symbol,name,area,industry,list_date')
|
||||
|
||||
data.to_csv(consts['path']['stock_list']['tushare'] +'\\tushare.csv', encoding="gbk")
|
||||
with open(consts['path']['stock_list']['tushare'] +'\\tushare.json', 'w', encoding='utf-8') as file:
|
||||
data.to_json(file, orient="records", lines=True, force_ascii=False)
|
@ -0,0 +1,21 @@
|
||||
.DS_Store
|
||||
node_modules
|
||||
/dist
|
||||
|
||||
# local env files
|
||||
.env.local
|
||||
.env.*.local
|
||||
|
||||
# Log files
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# Editor directories and files
|
||||
.idea
|
||||
.vscode
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
@ -0,0 +1,24 @@
|
||||
# display
|
||||
|
||||
## Project setup
|
||||
```
|
||||
npm install
|
||||
```
|
||||
|
||||
### Compiles and hot-reloads for development
|
||||
```
|
||||
npm run serve
|
||||
```
|
||||
|
||||
### Compiles and minifies for production
|
||||
```
|
||||
npm run build
|
||||
```
|
||||
|
||||
### Lints and fixes files
|
||||
```
|
||||
npm run lint
|
||||
```
|
||||
|
||||
### Customize configuration
|
||||
See [Configuration Reference](https://cli.vuejs.org/config/).
|
@ -0,0 +1,19 @@
|
||||
module.exports = {
|
||||
presets: [
|
||||
'@vue/cli-plugin-babel/preset'
|
||||
],
|
||||
"plugins": [
|
||||
[
|
||||
"component",
|
||||
{
|
||||
"libraryName": "element-ui",
|
||||
"styleLibraryName": "theme-chalk"
|
||||
}
|
||||
],
|
||||
/* ant-design-vue-component-import */
|
||||
[
|
||||
"import",
|
||||
{ libraryName: "ant-design-vue", libraryDirectory: "es", style: true }
|
||||
],
|
||||
]
|
||||
}
|
@ -0,0 +1,87 @@
|
||||
{
|
||||
"name": "display",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"serve": "vue-cli-service serve",
|
||||
"build": "vue-cli-service build",
|
||||
"lint": "vue-cli-service lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"ant-design-vue": "^1.4.8",
|
||||
"core-js": "^3.4.3",
|
||||
"echarts-wordcloud": "^1.1.3",
|
||||
"element-ui": "^2.13.0",
|
||||
"lodash": "^4.17.15",
|
||||
"vue": "^2.6.10",
|
||||
"vue-router": "^3.1.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vue/cli-plugin-babel": "^4.1.0",
|
||||
"@vue/cli-plugin-eslint": "^4.1.0",
|
||||
"@vue/cli-service": "^4.1.0",
|
||||
"babel-eslint": "^10.0.3",
|
||||
"babel-plugin-component": "^1.1.1",
|
||||
"eslint": "^5.16.0",
|
||||
"eslint-plugin-vue": "^5.0.0",
|
||||
"less": "^3.10.3",
|
||||
"less-loader": "^5.0.0",
|
||||
"node-sass": "^4.13.0",
|
||||
"sass-loader": "^8.0.0",
|
||||
"vue-template-compiler": "^2.6.10"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"root": true,
|
||||
"env": {
|
||||
"node": true
|
||||
},
|
||||
"extends": [
|
||||
"plugin:vue/essential",
|
||||
"eslint:recommended"
|
||||
],
|
||||
"parserOptions": {
|
||||
"parser": "babel-eslint"
|
||||
},
|
||||
"rules": {
|
||||
"no-console": 0,
|
||||
"no-unused-vars": 0,
|
||||
"no-useless-escape": 0,
|
||||
"vue/no-dupe-keys": 0,
|
||||
"vue/no-duplicate-attributes": 0,
|
||||
"vue/no-parsing-error": 0,
|
||||
"vue/no-reserved-keys": 0,
|
||||
"vue/no-shared-component-data": 0,
|
||||
"vue/no-side-effects-in-computed-properties": 0,
|
||||
"vue/no-template-key": 0,
|
||||
"vue/no-textarea-mustache": 0,
|
||||
"vue/no-unused-components": 0,
|
||||
"vue/no-use-v-if-with-v-for": 0,
|
||||
"vue/require-component-is": 0,
|
||||
"vue/require-prop-type-constructor": 0,
|
||||
"vue/no-async-in-computed-properties": 0,
|
||||
"vue/require-render-return": 0,
|
||||
"vue/require-v-for-key": 0,
|
||||
"vue/require-valid-default-prop": 0,
|
||||
"vue/return-in-computed-property": 0,
|
||||
"vue/use-v-on-exact": 0,
|
||||
"vue/valid-template-root": 0,
|
||||
"vue/valid-v-bind": 0,
|
||||
"vue/valid-v-cloak": 0,
|
||||
"vue/valid-v-else-if": 0,
|
||||
"vue/valid-v-else": 0,
|
||||
"vue/valid-v-for": 0,
|
||||
"vue/valid-v-html": 0,
|
||||
"vue/valid-v-if": 0,
|
||||
"vue/valid-v-model": 0,
|
||||
"vue/valid-v-on": 0,
|
||||
"vue/valid-v-once": 0,
|
||||
"vue/valid-v-pre": 0,
|
||||
"vue/valid-v-show": 0,
|
||||
"vue/valid-v-text": 0
|
||||
}
|
||||
},
|
||||
"browserslist": [
|
||||
"> 1%",
|
||||
"last 2 versions"
|
||||
]
|
||||
}
|
After Width: | Height: | Size: 4.2 KiB |
@ -0,0 +1,17 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
|
||||
<title>display</title>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>
|
||||
<strong>We're sorry but display doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
|
||||
</noscript>
|
||||
<div id="app"></div>
|
||||
<!-- built files will be auto injected -->
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,12 @@
|
||||
import os
|
||||
import sys
|
||||
|
||||
|
||||
codeList = os.listdir("E:\\files\\stock\\dayline\\with_my_result\\")
|
||||
f = open(sys.path[0].replace("script", "src") + "\\data\\code_list.js", "w", encoding="utf-8")
|
||||
f.write('''export default [
|
||||
''')
|
||||
for filename in codeList:
|
||||
f.write('''"%s",
|
||||
''' % filename[0:6])
|
||||
f.write("]")
|
@ -0,0 +1,22 @@
|
||||
import os
|
||||
import sys
|
||||
|
||||
import pandas as pd
|
||||
|
||||
codeList = os.listdir("E:\\files\\stock\\dayline\\with_my_result\\")
|
||||
|
||||
for filename in codeList:
|
||||
f = open(sys.path[0].replace("script", "src") + "\\data\\dayline\\%s.js"%filename[0:6], "w", encoding="utf-8")
|
||||
f.write('''module.exports [
|
||||
''')
|
||||
try:
|
||||
df = pd.read_csv("E:\\files\\stock\\dayline\\with_my_result\\" + filename, encoding="gbk", error_bad_lines=False, index_col=0)
|
||||
except:
|
||||
print("ERROR ORENING %s" % filename)
|
||||
for index, row in df.iterrows():
|
||||
# print(list(row.items()))
|
||||
f.write('''%s,
|
||||
''' % row.to_dict())
|
||||
f.write("]")
|
||||
f.close()
|
||||
# break
|
@ -0,0 +1,35 @@
|
||||
<template>
|
||||
<div id="app">
|
||||
<router-view />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "app",
|
||||
components: {}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
html {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #f6f6f6;
|
||||
body {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #f6f6f6;
|
||||
|
||||
#app {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #f6f6f6;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
@ -0,0 +1,285 @@
|
||||
import { cloneDeep } from "lodash";
|
||||
|
||||
const opt = {
|
||||
backgroundColor: '#21202D',
|
||||
legend: {
|
||||
data: ['日K', 'MA5', 'MA10', 'MA20', 'MA30'],
|
||||
inactiveColor: '#777',
|
||||
textStyle: {
|
||||
color: '#fff'
|
||||
}
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: {
|
||||
animation: false,
|
||||
type: 'cross',
|
||||
lineStyle: {
|
||||
color: '#376df4',
|
||||
width: 2,
|
||||
opacity: 1
|
||||
}
|
||||
},
|
||||
// formatter: '{b0}: {c0}<br />{b1}: {c1}'
|
||||
},
|
||||
xAxis: [{
|
||||
type: 'category',
|
||||
// data: dates,
|
||||
axisLine: { lineStyle: { color: '#8392A5' } }
|
||||
},
|
||||
{
|
||||
type: "category",
|
||||
axisLine: { lineStyle: { color: '#8392A5' } },
|
||||
gridIndex: 1
|
||||
},
|
||||
{
|
||||
type: "category",
|
||||
axisLabel: { show: false },
|
||||
gridIndex: 2
|
||||
}
|
||||
],
|
||||
yAxis: [{
|
||||
scale: true,
|
||||
axisLine: { lineStyle: { color: '#8392A5' } },
|
||||
splitLine: { show: false }
|
||||
},
|
||||
{
|
||||
id: "sumY",
|
||||
scale: true,
|
||||
axisLine: { lineStyle: { color: '#8392A5' } },
|
||||
splitLine: { show: false },
|
||||
gridIndex: 1
|
||||
},
|
||||
{
|
||||
scale: true,
|
||||
axisLine: { show: false, onZeroAxisIndex: "sumY" },
|
||||
axisLabel: { show: false },
|
||||
axisTick: { show: false },
|
||||
splitLine: { show: false },
|
||||
|
||||
gridIndex: 2,
|
||||
|
||||
}
|
||||
],
|
||||
grid: [
|
||||
// k 线区域
|
||||
{
|
||||
left: '5%',
|
||||
right: '5%',
|
||||
height: '50%'
|
||||
},
|
||||
// 胡立阳打分结果
|
||||
{
|
||||
left: '5%',
|
||||
right: '5%',
|
||||
bottom: '20%',
|
||||
height: '15%'
|
||||
},
|
||||
// 胡立阳盈利结果
|
||||
{
|
||||
left: '5%',
|
||||
right: '5%',
|
||||
bottom: '20%',
|
||||
height: '15%'
|
||||
}
|
||||
],
|
||||
dataZoom: [{
|
||||
textStyle: {
|
||||
color: '#8392A5'
|
||||
},
|
||||
startValue: 200,
|
||||
endValue: 250,
|
||||
handleIcon: 'M10.7,11.9v-1.3H9.3v1.3c-4.9,0.3-8.8,4.4-8.8,9.4c0,5,3.9,9.1,8.8,9.4v1.3h1.3v-1.3c4.9-0.3,8.8-4.4,8.8-9.4C19.5,16.3,15.6,12.2,10.7,11.9z M13.3,24.4H6.7V23h6.6V24.4z M13.3,19.6H6.7v-1.4h6.6V19.6z',
|
||||
handleSize: '80%',
|
||||
dataBackground: {
|
||||
areaStyle: {
|
||||
color: '#8392A5'
|
||||
},
|
||||
lineStyle: {
|
||||
opacity: 0.8,
|
||||
color: '#8392A5'
|
||||
}
|
||||
},
|
||||
xAxisIndex: [0, 1, 2],
|
||||
handleStyle: {
|
||||
color: '#fff',
|
||||
shadowBlur: 3,
|
||||
shadowColor: 'rgba(0, 0, 0, 0.6)',
|
||||
shadowOffsetX: 2,
|
||||
shadowOffsetY: 2
|
||||
}
|
||||
}, {
|
||||
type: 'inside'
|
||||
},
|
||||
{
|
||||
type: 'inside'
|
||||
}],
|
||||
animation: false,
|
||||
series: [
|
||||
{
|
||||
type: 'candlestick',
|
||||
name: '日K',
|
||||
itemStyle: {
|
||||
normal: {
|
||||
color: '#FD1050',
|
||||
color0: '#0CF49B',
|
||||
borderColor: '#FD1050',
|
||||
borderColor0: '#0CF49B'
|
||||
}
|
||||
}
|
||||
},
|
||||
]
|
||||
};
|
||||
|
||||
|
||||
export default function ({
|
||||
data,
|
||||
zljcData,
|
||||
daySum,
|
||||
ma,
|
||||
selectedZhiBiao
|
||||
}) {
|
||||
const sortedData = cloneDeep(data)
|
||||
sortedData.sort(compareDate)
|
||||
|
||||
// X 轴
|
||||
opt.xAxis.forEach(item => {
|
||||
item.data = sortedData.map(row => row['日期'])
|
||||
})
|
||||
|
||||
const init_days = 40
|
||||
opt.dataZoom[0].startValue = sortedData.length - init_days
|
||||
opt.dataZoom[0].endValue = sortedData.length
|
||||
|
||||
opt.series = []
|
||||
|
||||
// 日 K
|
||||
opt.series.push({
|
||||
type: 'candlestick',
|
||||
name: '日K',
|
||||
data: sortedData.map(row => [row['开盘价'], row['收盘价'], row['最低价'], row['最高价']]),
|
||||
itemStyle: {
|
||||
normal: {
|
||||
color: '#FD1050',
|
||||
color0: '#0CF49B',
|
||||
borderColor: '#FD1050',
|
||||
borderColor0: '#0CF49B'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
if (selectedZhiBiao == 0) {
|
||||
// 胡立阳打分数据
|
||||
opt.legend.data = Object.keys(sortedData[0]).map(key => {
|
||||
if (key === `sum_${daySum}`)
|
||||
return key
|
||||
}).filter(key => key != undefined)
|
||||
opt.series = opt.series.concat(opt.legend.data.map(key => {
|
||||
return {
|
||||
name: key,
|
||||
type: "line",
|
||||
data: sortedData.map(row => row[key]),
|
||||
smooth: true,
|
||||
xAxisIndex: 1,
|
||||
yAxisIndex: 1,
|
||||
}
|
||||
}))
|
||||
let sum_max = opt.series[1].data.reduce((prev, curr) => {
|
||||
if (curr > prev) return curr
|
||||
return prev
|
||||
}, -Infinity)
|
||||
let sum_min = opt.series[1].data.reduce((prev, curr) => {
|
||||
if (curr < prev) return curr
|
||||
return prev
|
||||
}, Infinity)
|
||||
let sum_abs_max = Math.max(Math.abs(sum_max), Math.abs(sum_min))
|
||||
opt.yAxis[1].max = Math.abs(sum_abs_max)
|
||||
opt.yAxis[1].min = -1 * Math.abs(sum_abs_max)
|
||||
|
||||
// 增长 / 减少的价格
|
||||
opt.series = opt.series.concat({
|
||||
name: "priceChange",
|
||||
type: "bar",
|
||||
data: sortedData.map((row, index) => {
|
||||
if (!index) return 0
|
||||
return parseInt((row['收盘价'] - sortedData[index - 1]['收盘价']) * 100) / 100
|
||||
}),
|
||||
xAxisIndex: 2,
|
||||
yAxisIndex: 2,
|
||||
label: {
|
||||
show: false
|
||||
}
|
||||
})
|
||||
let delta_max = opt.series[2].data.reduce((prev, curr) => {
|
||||
if (curr > prev) return curr
|
||||
return prev
|
||||
}, -Infinity);
|
||||
let delta_min = opt.series[2].data.reduce((prev, curr) => {
|
||||
if (curr < prev) return curr
|
||||
return prev
|
||||
}, Infinity)
|
||||
let delta_abs_max = Math.max(Math.abs(delta_max), Math.abs(delta_min))
|
||||
opt.yAxis[2].max = Math.abs(delta_abs_max)
|
||||
opt.yAxis[2].min = -1 * Math.abs(delta_abs_max)
|
||||
|
||||
opt.series = opt.series.concat(ma.map(val => {
|
||||
return {
|
||||
name: `MA${val}`,
|
||||
type: 'line',
|
||||
data: calculateMA(val, sortedData),
|
||||
smooth: true,
|
||||
lineStyle: {
|
||||
normal: { opacity: 0.5 },
|
||||
}
|
||||
}
|
||||
}))
|
||||
} else if(selectedZhiBiao == 1) {
|
||||
let legend = Object.keys(zljcData[0]).slice(1)
|
||||
legend.pop()
|
||||
opt.legend.data = legend
|
||||
opt.series = opt.series.concat(opt.legend.data.map(key => {
|
||||
return {
|
||||
name: key,
|
||||
type: "line",
|
||||
data: sortedData.map(row => {
|
||||
return zljcData.filter(e => {
|
||||
return e.date === row['日期']
|
||||
})[0][key]
|
||||
}),
|
||||
smooth: true,
|
||||
xAxisIndex: 1,
|
||||
yAxisIndex: 1,
|
||||
symbolSize: 0,
|
||||
lineStyle: {
|
||||
color: key == 'jcs' ? '#fff': (key == 'jcm' ? '#F4D03F': '#A569BD')
|
||||
}
|
||||
}
|
||||
}))
|
||||
opt.yAxis[1].min = null
|
||||
opt.yAxis[1].max = null
|
||||
}
|
||||
return opt
|
||||
}
|
||||
|
||||
function compareDate(d1, d2) {
|
||||
// let d1 = new Date(a['日期']);
|
||||
// let d2 = new Date(b['日期']);
|
||||
// return d1.getTime() < d2.getTime();
|
||||
return parseInt(d1['日期'].split("-").join("")) - parseInt(d2['日期'].split("-").join(""))
|
||||
}
|
||||
|
||||
function calculateMA(dayCount, data) {
|
||||
var result = [];
|
||||
for (var i = 0, len = data.length; i < len; i++) {
|
||||
if (i < dayCount) {
|
||||
result.push('-');
|
||||
continue;
|
||||
}
|
||||
var sum = 0;
|
||||
for (var j = 0; j < dayCount; j++) {
|
||||
sum += data[i - j]['收盘价'];
|
||||
}
|
||||
result.push(+(sum / dayCount).toFixed(3));
|
||||
}
|
||||
return result;
|
||||
}
|
@ -0,0 +1,344 @@
|
||||
import { cloneDeep } from "lodash";
|
||||
|
||||
const opt_3d_scatter = {
|
||||
tooltip: {},
|
||||
visualMap: [{
|
||||
bottom: 10,
|
||||
calculable: true,
|
||||
dimension: 3,
|
||||
// max: max.color / 2,
|
||||
inRange: {
|
||||
color: ['#1710c0', '#0b9df0', '#00fea8', '#00ff0d', '#f5f811', '#f09a09', '#fe0300'],
|
||||
symbolSize: [0, 100]
|
||||
},
|
||||
textStyle: {
|
||||
color: '#fff'
|
||||
}
|
||||
}],
|
||||
xAxis3D: {
|
||||
name: "连续打分天数",
|
||||
type: 'value'
|
||||
},
|
||||
yAxis3D: {
|
||||
name: "用于计算的 MA 天数",
|
||||
type: 'value'
|
||||
},
|
||||
zAxis3D: {
|
||||
name: "得分结果",
|
||||
type: 'value'
|
||||
},
|
||||
grid3D: {
|
||||
axisLine: {
|
||||
lineStyle: {
|
||||
color: '#fff'
|
||||
}
|
||||
},
|
||||
axisPointer: {
|
||||
lineStyle: {
|
||||
color: '#ffbd67'
|
||||
}
|
||||
},
|
||||
viewControl: {
|
||||
// autoRotate: true
|
||||
// projection: 'orthographic'
|
||||
}
|
||||
},
|
||||
series: [{
|
||||
type: 'scatter3D',
|
||||
data: [],
|
||||
symbolSize: 12,
|
||||
// symbol: 'triangle',
|
||||
itemStyle: {
|
||||
borderWidth: 1,
|
||||
borderColor: 'rgba(255,255,255,0.8)'
|
||||
},
|
||||
emphasis: {
|
||||
|
||||
itemStyle: {
|
||||
color: '#fff'
|
||||
}
|
||||
}
|
||||
}]
|
||||
}
|
||||
|
||||
const opt_htmap = {
|
||||
tooltip: {
|
||||
position: 'top'
|
||||
},
|
||||
animation: false,
|
||||
grid: {
|
||||
height: '80%'
|
||||
},
|
||||
xAxis: {
|
||||
name: "得分和",
|
||||
type: 'category',
|
||||
// data: hours,
|
||||
splitArea: {
|
||||
show: true
|
||||
},
|
||||
nameTextStyle: {
|
||||
color:"#fff"
|
||||
},
|
||||
axisLine: {
|
||||
lineStyle: {
|
||||
color: "#fff",
|
||||
}
|
||||
},
|
||||
axisTick: {
|
||||
lineStyle: {
|
||||
color: "#fff"
|
||||
}
|
||||
},
|
||||
axisLabel: {
|
||||
lineStyle:{
|
||||
color: "#fff"
|
||||
}
|
||||
},
|
||||
},
|
||||
yAxis: {
|
||||
name: "计算的天数",
|
||||
nameTextStyle: {
|
||||
color:"#fff"
|
||||
},
|
||||
axisLine: {
|
||||
lineStyle: {
|
||||
color: "#fff",
|
||||
}
|
||||
},
|
||||
axisTick: {
|
||||
lineStyle: {
|
||||
color: "#fff"
|
||||
}
|
||||
},
|
||||
axisLabel: {
|
||||
lineStyle:{
|
||||
color: "#fff"
|
||||
}
|
||||
},
|
||||
type: 'category',
|
||||
// data: days,
|
||||
splitArea: {
|
||||
show: true
|
||||
}
|
||||
},
|
||||
visualMap: {
|
||||
// min: 0,
|
||||
// max: 10,
|
||||
calculable: true,
|
||||
dimension: 2,
|
||||
orient: 'horizontal',
|
||||
left: 'center',
|
||||
bottom: '2%',
|
||||
textStyle: {
|
||||
color: "#fff"
|
||||
}
|
||||
},
|
||||
series: [{
|
||||
name: 'value',
|
||||
type: 'heatmap',
|
||||
// data: data,
|
||||
label: {
|
||||
normal: {
|
||||
show: true
|
||||
}
|
||||
},
|
||||
itemStyle: {
|
||||
emphasis: {
|
||||
shadowBlur: 10,
|
||||
shadowColor: 'rgba(0, 0, 0, 0.5)'
|
||||
}
|
||||
}
|
||||
}]
|
||||
};
|
||||
|
||||
export default function ({
|
||||
dataPlus,
|
||||
dataReduce,
|
||||
currentDataType,
|
||||
currentResType,
|
||||
currentHlyResType,
|
||||
resDay,
|
||||
resMA,
|
||||
currentHlyResWay
|
||||
}) {
|
||||
if (currentHlyResType == 0){
|
||||
|
||||
let sum_data = mergeData(dataPlus, dataReduce)
|
||||
let data
|
||||
if (currentDataType == 0)
|
||||
data = transformData(dataPlus)
|
||||
else if (currentDataType == 1)
|
||||
data = transformData(dataReduce)
|
||||
else if (currentDataType == 2)
|
||||
data = transformData(calcPercent(dataPlus, sum_data))
|
||||
else if (currentDataType == 3)
|
||||
data = transformData(calcPercent(dataReduce, sum_data))
|
||||
|
||||
|
||||
// VisualMap
|
||||
if (currentDataType == 2 || currentDataType == 3) {
|
||||
opt_3d_scatter.visualMap[0].max = 100
|
||||
opt_htmap.visualMap.max = 100
|
||||
} else {
|
||||
opt_3d_scatter.visualMap[0].max = getMaxInMatrix(matrixParseNumber(transformData(sum_data)))
|
||||
opt_htmap.visualMap.max = getMaxInMatrix(matrixParseNumber(transformData(sum_data)))
|
||||
}
|
||||
|
||||
if (currentResType == 0) {
|
||||
// 3D 散点图
|
||||
data = matrixParseNumber(data)
|
||||
opt_3d_scatter.series[0].data = cloneDeep(data)
|
||||
return cloneDeep(opt_3d_scatter)
|
||||
} else if (currentResType == 1) {
|
||||
// 热力图
|
||||
opt_htmap.xAxis.data = Array.from(new Set(matrixParseNumber(data).map(row => row[2])))
|
||||
opt_htmap.yAxis.data = Array.from(new Set(matrixParseNumber(data).map(row => row[0])))
|
||||
|
||||
opt_htmap.xAxis.data = opt_htmap.xAxis.data.sort((a,b) => a-b)
|
||||
opt_htmap.yAxis.data = opt_htmap.yAxis.data.sort((a,b) => a-b)
|
||||
|
||||
opt_htmap.series[0].data = matrixParseNumber(data).filter(e => {
|
||||
return e[1] == parseInt(resMA.replace("ma_", ""))
|
||||
}).map(row => {
|
||||
return [
|
||||
opt_htmap.xAxis.data.indexOf(row[2]),
|
||||
opt_htmap.yAxis.data.indexOf(row[0]),
|
||||
row[3]
|
||||
]
|
||||
})
|
||||
return cloneDeep(opt_htmap)
|
||||
}
|
||||
} else if (currentHlyResType == 1) {
|
||||
let data_up = undefined
|
||||
let data_down = undefined
|
||||
if (currentHlyResWay == 0) {
|
||||
data_up = require("@/data/hly_count_res_ma5_type_1_up.json")
|
||||
data_down = require("@/data/hly_count_res_ma5_type_1_down.json")
|
||||
} else if(currentHlyResWay == 1){
|
||||
data_up = require("@/data/hly_count_res_ma5_type_2_up.json")
|
||||
data_down = require("@/data/hly_count_res_ma5_type_2_down.json")
|
||||
}
|
||||
|
||||
let xAxis = Array.from(new Set(Object.keys(data_up).map(e => parseInt(e.slice(1))).concat(Object.keys(data_down).map(e => parseInt(e.slice(1))))));
|
||||
return {
|
||||
xAxis: {
|
||||
data: xAxis,
|
||||
type: 'category',
|
||||
axisLine: {
|
||||
lineStyle: {
|
||||
color: "#fff"
|
||||
}
|
||||
},
|
||||
axisTick: {
|
||||
|
||||
},
|
||||
axisLabel: {
|
||||
color: "#fff"
|
||||
}
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
axisLine: {
|
||||
lineStyle: {
|
||||
color: "#fff"
|
||||
}
|
||||
},
|
||||
axisTick: {
|
||||
|
||||
},
|
||||
axisLabel: {
|
||||
color: "#fff"
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
show: true,
|
||||
textStyle: {
|
||||
color: "#FFF"
|
||||
}
|
||||
},
|
||||
series: [data_up, data_down].map((data, index) => {
|
||||
return {
|
||||
name: index == 1? "上升":"下降",
|
||||
type: "bar",
|
||||
data: xAxis.map(key => {
|
||||
return data[`_${key}`]
|
||||
}),
|
||||
label:{
|
||||
show: true,
|
||||
position: "top"
|
||||
}
|
||||
}
|
||||
})
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function transformData(dic) {
|
||||
let res = []
|
||||
|
||||
Object.keys(dic).forEach(sum_key => {
|
||||
Object.keys(dic[sum_key]).forEach(ma_key => {
|
||||
Object.keys(dic[sum_key][ma_key]).forEach(score_key => {
|
||||
res.push([sum_key, ma_key, score_key, dic[sum_key][ma_key][score_key]])
|
||||
})
|
||||
})
|
||||
})
|
||||
return res
|
||||
}
|
||||
|
||||
function mergeData(a, b) {
|
||||
const res = cloneDeep(a)
|
||||
Object.keys(a).forEach(sum_key => {
|
||||
Object.keys(a[sum_key]).forEach(ma_key => {
|
||||
Object.keys(a[sum_key][ma_key]).forEach(score_key => {
|
||||
if (b[sum_key] && b[sum_key][ma_key] && b[sum_key][ma_key][score_key]) {
|
||||
res[sum_key][ma_key][score_key] = a[sum_key][ma_key][score_key] + b[sum_key][ma_key][score_key]
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
return res
|
||||
}
|
||||
|
||||
function calcPercent(a, b) {
|
||||
const res = cloneDeep(a)
|
||||
Object.keys(a).forEach(sum_key => {
|
||||
Object.keys(a[sum_key]).forEach(ma_key => {
|
||||
Object.keys(a[sum_key][ma_key]).forEach(score_key => {
|
||||
if (b[sum_key] && b[sum_key][ma_key] && b[sum_key][ma_key][score_key]) {
|
||||
res[sum_key][ma_key][score_key] = (a[sum_key][ma_key][score_key] / b[sum_key][ma_key][score_key] * 100).toFixed(3)
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
return res
|
||||
}
|
||||
|
||||
function matrixParseNumber(m) {
|
||||
return m.map(row => {
|
||||
return row.slice(0, 3).map(val => {
|
||||
return parseFloat(val.replace("sum_", "").replace("ma_", "").replace("_", ""))
|
||||
}).concat(parseFloat(row[3]))
|
||||
})
|
||||
}
|
||||
|
||||
function getMaxInMatrix(dic) {
|
||||
// let TEMP_MAX = -Infinity
|
||||
// return innerFuc(dic)
|
||||
// function innerFuc(dic) {
|
||||
// if (Object.prototype.toString.call(dic) == "[Object Object]") {
|
||||
// Object.keys(dic).forEach(e => {
|
||||
// return innerFuc(dic[e])
|
||||
// })
|
||||
// } else {
|
||||
// if (e > TEMP_MAX) TEMP_MAX = e
|
||||
// }
|
||||
// }
|
||||
let max = -Infinity
|
||||
dic.forEach(row => {
|
||||
if (row[3] > max)
|
||||
max = row[3]
|
||||
})
|
||||
return max
|
||||
}
|
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 6.7 KiB |
@ -0,0 +1,253 @@
|
||||
<script>
|
||||
import interact from "interactjs";
|
||||
import { throttle } from "lodash";
|
||||
// import { events } from '@interactjs/utils';
|
||||
export default {
|
||||
name: "ct-drag-resize",
|
||||
// funtional: false,
|
||||
props: {
|
||||
ww: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
hh: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
x: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
y: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
resizable: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
moveable: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
identify: {
|
||||
type: String,
|
||||
default: ""
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.$nextTick(() => {
|
||||
// const isHittingParentBound = self => {
|
||||
// if (self.left < 0) {
|
||||
// self.left = 0;
|
||||
// return true;
|
||||
// } else if (self.top < 0) {
|
||||
// self.top = 0;
|
||||
// return true;
|
||||
// } else {
|
||||
// return false;
|
||||
// }
|
||||
// };
|
||||
|
||||
const self = this;
|
||||
interact(this.$el)
|
||||
.resizable({
|
||||
inertia: false,
|
||||
edges: {
|
||||
top: false,
|
||||
left: false,
|
||||
bottom: true,
|
||||
right: true
|
||||
}
|
||||
})
|
||||
.on(
|
||||
"resizemove",
|
||||
throttle(({ rect: { width, height } }) => {
|
||||
self.height = height;
|
||||
self.width = width;
|
||||
self.$emit("resizemove", { width, height });
|
||||
}, 16)
|
||||
)
|
||||
.draggable({
|
||||
// inertia: false,
|
||||
// modifiers: [
|
||||
// interact.modifiers.restrictRect({
|
||||
// restriction: "parent",
|
||||
// endOnly: true
|
||||
// })
|
||||
// ],
|
||||
// autoScroll: true,
|
||||
// onmove: self.dragMoveListener
|
||||
listeners: {
|
||||
start() {
|
||||
const path = event.path;
|
||||
const classNamesInPath = path.reduce((res, { classList }) => {
|
||||
if (!classList) return res;
|
||||
return res.concat(classList.value.split(" "));
|
||||
}, []);
|
||||
|
||||
const dragCancelClassName = "chart-output-content";
|
||||
const dragCancelClassNameIndex = classNamesInPath.indexOf(
|
||||
dragCancelClassName
|
||||
);
|
||||
|
||||
self.isDragCancel = dragCancelClassNameIndex !== -1;
|
||||
},
|
||||
move: ({ target, dx, dy }) => {
|
||||
if (self.isDragCancel) return;
|
||||
// if (isHittingParentBound(self)) return;
|
||||
var x = (parseFloat(target.getAttribute("data-x")) || 0) + dx;
|
||||
var y = (parseFloat(target.getAttribute("data-y")) || 0) + dy;
|
||||
self.left += x;
|
||||
self.top += y;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
dragMoveListener(event) {
|
||||
if (!this.moveable) return;
|
||||
var target = event.target;
|
||||
// keep the dragged position in the data-x/data-y attributes
|
||||
var x = (parseFloat(target.getAttribute("data-x")) || 0) + event.dx;
|
||||
var y = (parseFloat(target.getAttribute("data-y")) || 0) + event.dy;
|
||||
|
||||
this.left = x + this.x;
|
||||
this.top = y + this.y;
|
||||
|
||||
// update the posiion attributes
|
||||
target.setAttribute("data-x", x);
|
||||
target.setAttribute("data-y", y);
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
hlyres_force_position() {
|
||||
return this.$store.getters["hly/forceResPos"]
|
||||
},
|
||||
hlyscore_force_position() {
|
||||
return this.$store.getters["hly/forcePos"]
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
top: this.y,
|
||||
left: this.x,
|
||||
width: this.w,
|
||||
height: this.h,
|
||||
isDragCancel: false
|
||||
};
|
||||
},
|
||||
render() {
|
||||
const {
|
||||
hh,
|
||||
ww,
|
||||
top,
|
||||
left,
|
||||
height,
|
||||
width,
|
||||
resizable,
|
||||
hlyres_force_position,
|
||||
hlyscore_force_position
|
||||
} = this;
|
||||
|
||||
let fineHeight = height ? `${height}px` : `${hh}px`,
|
||||
fineWidth = width ? `${width}px` : `${ww}px`,
|
||||
fineLeft = `${left}px`,
|
||||
fineTop = `${top}px`;
|
||||
|
||||
if (this.identify == "echarts2") {
|
||||
if (hlyres_force_position.max) {
|
||||
fineWidth = "100vw";
|
||||
fineHeight = "100vh";
|
||||
fineLeft = "0";
|
||||
fineTop = "0";
|
||||
}
|
||||
if (hlyres_force_position.min) {
|
||||
fineWidth = "90px";
|
||||
fineHeight = "50px";
|
||||
fineLeft = "10px";
|
||||
fineTop = "10px";
|
||||
}
|
||||
}
|
||||
if (this.identify == "echarts") {
|
||||
if (hlyscore_force_position.max) {
|
||||
fineWidth = "100vw";
|
||||
fineHeight = "100vh";
|
||||
fineLeft = "0";
|
||||
fineTop = "0";
|
||||
}
|
||||
if (hlyscore_force_position.min) {
|
||||
fineWidth = "90px";
|
||||
fineHeight = "50px";
|
||||
fineLeft = "10px";
|
||||
fineTop = "70px";
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
class={{ "ct-drag-resize": true }}
|
||||
style={{
|
||||
width: fineWidth,
|
||||
height: fineHeight,
|
||||
left: fineLeft,
|
||||
top: fineTop,
|
||||
position: "absolute"
|
||||
}}
|
||||
>
|
||||
{this.$slots.default}
|
||||
{resizable ? <div class="cdr-handle cdr-handle-br"></div> : ""}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.ct-drag-resize {
|
||||
position: relative;
|
||||
user-select: none;
|
||||
touch-action: none;
|
||||
padding: 3px;
|
||||
|
||||
&:hover {
|
||||
cursor: move;
|
||||
.cdr-handle {
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
.cdr-handle {
|
||||
position: absolute;
|
||||
border: 1px solid rgba(0, 0, 0, 0.4);
|
||||
border-radius: 50%;
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
transform: scale(0.6);
|
||||
&:hover {
|
||||
transform: scale(1.4);
|
||||
}
|
||||
&.cdr-handle-tl {
|
||||
top: -5px;
|
||||
left: -5px;
|
||||
cursor: nw-resize;
|
||||
}
|
||||
&.cdr-handle-tr {
|
||||
top: -5px;
|
||||
right: -5px;
|
||||
cursor: ne-resize;
|
||||
}
|
||||
&.cdr-handle-bl {
|
||||
bottom: -5px;
|
||||
left: -5px;
|
||||
cursor: sw-resize;
|
||||
}
|
||||
&.cdr-handle-br {
|
||||
bottom: -5px;
|
||||
right: -5px;
|
||||
cursor: se-resize;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
@ -0,0 +1,58 @@
|
||||
<template>
|
||||
<div class="hello">
|
||||
<h1>{{ msg }}</h1>
|
||||
<p>
|
||||
For a guide and recipes on how to configure / customize this project,<br>
|
||||
check out the
|
||||
<a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
|
||||
</p>
|
||||
<h3>Installed CLI Plugins</h3>
|
||||
<ul>
|
||||
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" target="_blank" rel="noopener">babel</a></li>
|
||||
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint" target="_blank" rel="noopener">eslint</a></li>
|
||||
</ul>
|
||||
<h3>Essential Links</h3>
|
||||
<ul>
|
||||
<li><a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a></li>
|
||||
<li><a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a></li>
|
||||
<li><a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a></li>
|
||||
<li><a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a></li>
|
||||
<li><a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a></li>
|
||||
</ul>
|
||||
<h3>Ecosystem</h3>
|
||||
<ul>
|
||||
<li><a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a></li>
|
||||
<li><a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a></li>
|
||||
<li><a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtools</a></li>
|
||||
<li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a></li>
|
||||
<li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'HelloWorld',
|
||||
props: {
|
||||
msg: String
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||||
<style scoped>
|
||||
h3 {
|
||||
margin: 40px 0 0;
|
||||
}
|
||||
ul {
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
}
|
||||
li {
|
||||
display: inline-block;
|
||||
margin: 0 10px;
|
||||
}
|
||||
a {
|
||||
color: #42b983;
|
||||
}
|
||||
</style>
|
@ -0,0 +1 @@
|
||||
{"_5": 1033749, "_7": 1051246, "_9": 1055143, "_10": 1052648, "_11": 1047408, "_12": 1040868, "_6": 1053234, "_8": 1056156}
|
@ -0,0 +1 @@
|
||||
{"_5": 721152, "_6": 688496, "_7": 682389, "_8": 678305, "_9": 682749, "_10": 683570, "_11": 681318, "_12": 680672}
|
@ -0,0 +1 @@
|
||||
{"_5": 158387, "_6": 75437, "_7": 36881, "_8": 19231, "_9": 10873, "_10": 6797, "_11": 4612, "_12": 3317}
|
@ -0,0 +1 @@
|
||||
{"_5": 28435, "_6": 13959, "_7": 6385, "_8": 2659, "_9": 1218, "_10": 611, "_11": 353, "_12": 240}
|
@ -0,0 +1,32 @@
|
||||
import Vue from 'vue'
|
||||
import App from './App.vue'
|
||||
import router from './router'
|
||||
import axios from 'axios'
|
||||
import store from './store'
|
||||
Vue.prototype.$axios = axios;
|
||||
|
||||
// element
|
||||
import {
|
||||
Button,
|
||||
Select,
|
||||
Tooltip,
|
||||
Option,
|
||||
Switch,
|
||||
} from 'element-ui';
|
||||
Vue.use(Button)
|
||||
Vue.use(Select)
|
||||
Vue.use(Tooltip)
|
||||
Vue.use(Option)
|
||||
Vue.use(Switch)
|
||||
|
||||
// ant-design
|
||||
import { message } from 'ant-design-vue';
|
||||
Vue.prototype.$message = message;
|
||||
|
||||
Vue.config.productionTip = false
|
||||
|
||||
new Vue({
|
||||
router,
|
||||
store,
|
||||
render: h => h(App),
|
||||
}).$mount('#app')
|
@ -0,0 +1,34 @@
|
||||
<template>
|
||||
<div id="not-found">
|
||||
<h2>404 NOT FOUND</h2>
|
||||
<hr>
|
||||
<span>Change Code And Try Again</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
#not-found {
|
||||
width: 30%;
|
||||
margin: 0 auto;
|
||||
// display: flex;
|
||||
padding: 120px 100px;
|
||||
text-align: center;
|
||||
font-size: 1rem;
|
||||
color: #bdbdbd;
|
||||
|
||||
hr {
|
||||
margin: 10px;
|
||||
transform: scaleY(0.5);
|
||||
}
|
||||
h2 {
|
||||
color: #505050;
|
||||
}
|
||||
|
||||
}
|
||||
</style>
|
@ -0,0 +1,606 @@
|
||||
<script>
|
||||
import Echarts from "vue-echarts";
|
||||
import SettingPanel from "./SettingPanel";
|
||||
import DragResize from "@/components/DragResize";
|
||||
import EmptyPage from "../EmptyPage";
|
||||
|
||||
import "echarts/";
|
||||
require("echarts-gl");
|
||||
|
||||
import { debounce, cloneDeep } from "lodash";
|
||||
import { Loading } from "element-ui";
|
||||
|
||||
const codeList = require("@/data/code_list.js").default;
|
||||
// const optProcess = require("@/assets/chartOpt/c0001.js");
|
||||
export default {
|
||||
name: "hlyDetail",
|
||||
components: {
|
||||
Echarts,
|
||||
SettingPanel,
|
||||
DragResize,
|
||||
EmptyPage
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
ww: 800,
|
||||
hh: 600,
|
||||
x: 100,
|
||||
y: 100,
|
||||
moveable: true,
|
||||
opt: {},
|
||||
resOpt: {},
|
||||
loading: false,
|
||||
storedData: undefined,
|
||||
currentActive: "echarts2"
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
code() {
|
||||
// this.updateOpt(this.$route.params.code)
|
||||
let code = this.$route.params.code;
|
||||
this.processByCode(code);
|
||||
return code;
|
||||
},
|
||||
ma() {
|
||||
return this.$store.getters["hly/ma"];
|
||||
},
|
||||
daySum() {
|
||||
return this.$store.getters["hly/daySum"];
|
||||
},
|
||||
currentDataType() {
|
||||
return this.$store.getters["hly/currentDataType"];
|
||||
},
|
||||
currentHlyResType() {
|
||||
return this.$store.getters["hly/currentHlyResType"];
|
||||
},
|
||||
currentHlyResWay() {
|
||||
return this.$store.getters["hly/currentHlyResWay"];
|
||||
},
|
||||
currentResType() {
|
||||
return this.$store.getters["hly/currentResType"];
|
||||
},
|
||||
showCount() {
|
||||
let show = this.$store.getters["hly/showCount"];
|
||||
if (show) this.processResOpt();
|
||||
return show;
|
||||
},
|
||||
resMA() {
|
||||
return this.$store.getters["hly/resMA"];
|
||||
},
|
||||
resDay() {
|
||||
return this.$store.getters["hly/resDay"];
|
||||
},
|
||||
selectedZhiBiao() {
|
||||
return this.$store.getters["hly/selectedZhiBiao"];
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.resetRes();
|
||||
},
|
||||
watch: {
|
||||
daySum(val) {
|
||||
this.processByCode(this.code);
|
||||
},
|
||||
ma(val) {
|
||||
this.processByCode(this.code);
|
||||
},
|
||||
selectedZhiBiao(val) {
|
||||
this.processByCode(this.code);
|
||||
},
|
||||
currentDataType(val) {
|
||||
this.processResOpt();
|
||||
},
|
||||
currentHlyResType(val) {
|
||||
this.processResOpt();
|
||||
},
|
||||
currentHlyResWay(val) {
|
||||
this.processResOpt();
|
||||
},
|
||||
currentResType(val) {
|
||||
this.processResOpt();
|
||||
},
|
||||
showCount(val) {
|
||||
if (val) this.processResOpt();
|
||||
this.loading = true;
|
||||
},
|
||||
resMA() {
|
||||
this.processResOpt();
|
||||
},
|
||||
resDay() {
|
||||
this.processResOpt();
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleResize: debounce((e, vm, target) => {
|
||||
vm.$refs[target].resize();
|
||||
vm.currentActive = target;
|
||||
}, 10),
|
||||
processResOpt() {
|
||||
this.loading = true;
|
||||
const promisedOptProcesser = () => import("@/assets/chartOpt/c0002.js");
|
||||
promisedOptProcesser()
|
||||
.then(res => {
|
||||
const optProcessor = res.default;
|
||||
const newOpt = optProcessor({
|
||||
dataPlus: require("@/data/hly_count_res_plus.json"),
|
||||
dataReduce: require("@/data/hly_count_res_reduce.json"),
|
||||
currentDataType: this.currentDataType,
|
||||
currentResType: this.currentResType,
|
||||
currentHlyResType: this.currentHlyResType,
|
||||
resDay: this.resDay,
|
||||
resMA: this.resMA,
|
||||
currentHlyResWay: this.currentHlyResWay
|
||||
});
|
||||
this.resOpt = cloneDeep(newOpt);
|
||||
this.loading = false;
|
||||
})
|
||||
.catch(e => {
|
||||
this.$message.error(e);
|
||||
});
|
||||
},
|
||||
async processByCode(code) {
|
||||
this.loading = true;
|
||||
let data = [];
|
||||
|
||||
if (
|
||||
this.storedData !== undefined &&
|
||||
this.storedData.length > 0 &&
|
||||
this.storedData[0]["股票代码"].slice(1) == code
|
||||
) {
|
||||
data = this.storedData;
|
||||
} else {
|
||||
let res = await this.$axios.get("http://stock.catsjuice.top/api/hly", {
|
||||
params: {
|
||||
code: code
|
||||
}
|
||||
});
|
||||
data = res.data.data;
|
||||
this.storedData = data;
|
||||
}
|
||||
|
||||
let zljcData = [];
|
||||
if (
|
||||
this.storedZLJC !== undefined &&
|
||||
this.storedZLJC.length > 0 &&
|
||||
this.storedZLJC[0].code == code
|
||||
) {
|
||||
zljcData = this.storedZLJC;
|
||||
} else {
|
||||
let res = await this.$axios.get("http://stock.catsjuice.top/api/zljc", {
|
||||
params: {
|
||||
code
|
||||
}
|
||||
});
|
||||
zljcData = res.data.data
|
||||
this.storedZLJC = zljcData
|
||||
this.storedZLJC[0].code = code
|
||||
}
|
||||
|
||||
const promisedOptProcesser = () => import("@/assets/chartOpt/c0001.js");
|
||||
promisedOptProcesser().then(res => {
|
||||
const optProcessor = res.default;
|
||||
const newOpt = optProcessor({
|
||||
data,
|
||||
zljcData,
|
||||
daySum: this.daySum,
|
||||
ma: this.ma,
|
||||
selectedZhiBiao: this.selectedZhiBiao
|
||||
});
|
||||
|
||||
this.opt = cloneDeep(newOpt);
|
||||
this.$store.commit("hly/UPDATE", {
|
||||
constant: "selectedData",
|
||||
value: data
|
||||
});
|
||||
});
|
||||
this.loading = false;
|
||||
},
|
||||
|
||||
smallest() {
|
||||
this.ww = 50;
|
||||
this.hh = 50;
|
||||
this.x = 0;
|
||||
this.y = 0;
|
||||
},
|
||||
|
||||
switchCurrentActive(tar) {
|
||||
this.currentActive = tar;
|
||||
},
|
||||
|
||||
resetRes() {
|
||||
this.$store.commit("hly/RESET_RES");
|
||||
},
|
||||
|
||||
maxOrExtendResWindow() {
|
||||
this.$store.commit("hly/UPDATE", {
|
||||
constant: "forceResPos",
|
||||
value: {
|
||||
max: !this.$store.getters["hly/forceResPos"].max,
|
||||
min: false
|
||||
}
|
||||
});
|
||||
let vm = this;
|
||||
setTimeout(() => {
|
||||
vm.$refs["echartsRes"].resize();
|
||||
}, 150);
|
||||
},
|
||||
maxOrExtendWindow() {
|
||||
this.$store.commit("hly/UPDATE", {
|
||||
constant: "forcePos",
|
||||
value: {
|
||||
max: !this.$store.getters["hly/forcePos"].max,
|
||||
min: false
|
||||
}
|
||||
});
|
||||
|
||||
let vm = this;
|
||||
setTimeout(() => {
|
||||
vm.$refs.echarts.resize();
|
||||
}, 150);
|
||||
},
|
||||
minResWindow() {
|
||||
if (this.$store.getters["hly/forceResPos"].min) {
|
||||
this.$store.commit("hly/UPDATE", {
|
||||
constant: "forceResPos",
|
||||
value: {
|
||||
max: false,
|
||||
min: false
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this.$store.commit("hly/UPDATE", {
|
||||
constant: "forceResPos",
|
||||
value: {
|
||||
max: false,
|
||||
min: true
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
minWindow() {
|
||||
if (this.$store.getters["hly/forcePos"]) {
|
||||
this.$store.commit("hly/UPDATE", {
|
||||
constant: "forcePos",
|
||||
value: {
|
||||
max: false,
|
||||
min: false
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this.$store.commit("hly/UPDATE", {
|
||||
constant: "forcePos",
|
||||
value: {
|
||||
max: false,
|
||||
min: true
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
recoverResWindow() {
|
||||
let f = this.$store.getters["hly/forceResPos"];
|
||||
if (!f.max || !f.min) return;
|
||||
this.$store.commit("hly/UPDATE", {
|
||||
constant: "forceResPos",
|
||||
value: {
|
||||
max: false,
|
||||
min: false
|
||||
}
|
||||
});
|
||||
},
|
||||
recoverWindow() {
|
||||
let f = this.$store.getters["hly/forcePos"];
|
||||
if (!f.max || !f.min) return;
|
||||
this.$store.commit("hly/UPDATE", {
|
||||
constant: "forcePos",
|
||||
value: {
|
||||
max: false,
|
||||
min: false
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
render() {
|
||||
const { moveable, handleResize, code, ww, hh, x, y } = this;
|
||||
const initOptions = {
|
||||
render: "canvas"
|
||||
};
|
||||
if (codeList.filter(e => e === code).length == 0) return <empty-page />;
|
||||
|
||||
let countResult = (
|
||||
<transition
|
||||
enter-active-class="animated fadeIn"
|
||||
leave-active-class="animated fadeOutWithouDelay"
|
||||
>
|
||||
<drag-resize
|
||||
style={`
|
||||
${this.currentActive == "echarts2" ? "z-index:999;" : ""}
|
||||
`}
|
||||
ww={800}
|
||||
hh={800}
|
||||
x={50}
|
||||
y={50}
|
||||
identify="echarts2"
|
||||
resizable={true}
|
||||
initOptions={initOptions}
|
||||
autoresize
|
||||
vOn:resizemove={e => handleResize(e, this, "echartsRes")}
|
||||
>
|
||||
<div
|
||||
id="print-panel"
|
||||
style="background-color:rgb(33,32,45);"
|
||||
onMousedown={e => this.switchCurrentActive("echarts2")}
|
||||
>
|
||||
<div class="drag" vOn:click={this.recoverResWindow}>
|
||||
<span class="chart-output-content">
|
||||
<span></span>
|
||||
<span></span>
|
||||
</span>
|
||||
<span
|
||||
class="chart-output-content"
|
||||
vOn:click={this.maxOrExtendResWindow}
|
||||
></span>
|
||||
<span class="chart-output-content" vOn:click={this.minResWindow}>
|
||||
<span></span>
|
||||
</span>
|
||||
</div>
|
||||
<echarts
|
||||
id="echats"
|
||||
class="chart-output-content"
|
||||
initOptions={initOptions}
|
||||
options={this.resOpt}
|
||||
autoresize
|
||||
ref="echartsRes"
|
||||
/>
|
||||
</div>
|
||||
</drag-resize>
|
||||
</transition>
|
||||
);
|
||||
return (
|
||||
<div class="row">
|
||||
<drag-resize
|
||||
ww={ww}
|
||||
hh={hh}
|
||||
x={x}
|
||||
y={y}
|
||||
identify="echarts"
|
||||
resizable={true}
|
||||
initOptions={initOptions}
|
||||
moveable={moveable}
|
||||
style={this.currentActive == "echarts" ? "z-index:999;" : ""}
|
||||
vOn:resizemove={e => handleResize(e, this, "echarts")}
|
||||
>
|
||||
<div
|
||||
id="print-panel"
|
||||
onMousedown={e => this.switchCurrentActive("echarts")}
|
||||
>
|
||||
<div class="drag" vOn:click={this.recoverWindow}>
|
||||
<span class="chart-output-content">
|
||||
<span></span>
|
||||
<span></span>
|
||||
</span>
|
||||
<span
|
||||
class="chart-output-content"
|
||||
vOn:click={this.maxOrExtendWindow}
|
||||
></span>
|
||||
<span class="chart-output-content" vOn:click={this.minWindow}>
|
||||
<span></span>
|
||||
</span>
|
||||
</div>
|
||||
<echarts
|
||||
id="echats"
|
||||
class="chart-output-content"
|
||||
initOptions={initOptions}
|
||||
options={this.opt}
|
||||
ref="echarts"
|
||||
/>
|
||||
</div>
|
||||
</drag-resize>
|
||||
|
||||
{this.showCount ? countResult : ""}
|
||||
|
||||
<setting-panel />
|
||||
<transition
|
||||
enter-active-class="animated slideInDown"
|
||||
leave-active-class="animated fadeOut"
|
||||
>
|
||||
{this.loading ? (
|
||||
<div class="loading">
|
||||
<span>正在加载...</span>
|
||||
<span></span>
|
||||
</div>
|
||||
) : (
|
||||
""
|
||||
)}
|
||||
</transition>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
@drag-height: 50px;
|
||||
|
||||
.row {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
#print-panel {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #fff;
|
||||
box-shadow: 0px 0px 15px rgba(0, 0, 0, 0.1);
|
||||
border-radius: 5px;
|
||||
overflow: hidden;
|
||||
#echats {
|
||||
width: 100%;
|
||||
height: ~"calc(100% - @{drag-height})";
|
||||
box-shadow: 0px -1px 10px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
}
|
||||
.drag {
|
||||
width: 100%;
|
||||
background-color: #d3d6e0;
|
||||
height: @drag-height;
|
||||
// box-shadow: 0px 10px 10px rgba(0,0,0,.1) inset;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-direction: row;
|
||||
padding-left: 10px;
|
||||
overflow: hidden;
|
||||
span {
|
||||
display: block;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin: 0 2px;
|
||||
border-radius: 50%;
|
||||
background-color: aqua;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease-in-out;
|
||||
position: relative;
|
||||
flex-shrink: 0;
|
||||
|
||||
&:hover {
|
||||
box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
&:nth-child(1) {
|
||||
background-color: #cd6155;
|
||||
|
||||
& > span {
|
||||
position: absolute;
|
||||
width: 60%;
|
||||
height: 1px;
|
||||
background-color: #fff;
|
||||
transform-origin: center;
|
||||
margin-top: 50%;
|
||||
margin-left: 20%;
|
||||
opacity: 0;
|
||||
top: -1px;
|
||||
&:nth-child(1) {
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
&:nth-child(2) {
|
||||
transform: rotate(-45deg);
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
background-color: #832f26;
|
||||
& > span {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
&:nth-child(2) {
|
||||
background-color: #f5b041;
|
||||
&:hover {
|
||||
background-color: #d39430;
|
||||
}
|
||||
}
|
||||
&:nth-child(3) {
|
||||
background-color: #45b39d;
|
||||
|
||||
span {
|
||||
width: 66%;
|
||||
height: 2px;
|
||||
background-color: #fff;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 17%;
|
||||
margin: 0;
|
||||
margin-top: -1px;
|
||||
opacity: 0;
|
||||
}
|
||||
&:hover {
|
||||
background-color: #349e89;
|
||||
& > span {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.loading {
|
||||
transition: all 0.3s ease-in-out;
|
||||
position: absolute;
|
||||
top: 70px;
|
||||
left: 50%;
|
||||
margin-left: -100px;
|
||||
box-shadow: 0px 2px 8px rgba(0, 0, 0, 0.1);
|
||||
width: 200px;
|
||||
height: 55px;
|
||||
border-radius: 5px;
|
||||
background-color: #fff;
|
||||
z-index: 9999;
|
||||
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
span {
|
||||
display: inline-block;
|
||||
font-size: 0.8rem;
|
||||
|
||||
&:nth-child(2) {
|
||||
border: 2px solid transparent;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border-radius: 50%;
|
||||
border-top: 2px solid rgb(78, 78, 78);
|
||||
border-right: 2px solid rgb(78, 78, 78);
|
||||
margin-left: 20px;
|
||||
animation: rotate 1s linear 0s infinite normal;
|
||||
}
|
||||
@keyframes rotate {
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.slideInDown {
|
||||
animation: slideInDown 0.2s ease 0s 1;
|
||||
}
|
||||
@keyframes slideInDown {
|
||||
from {
|
||||
transform: translateY(-55px);
|
||||
}
|
||||
to {
|
||||
transform: translateY(0px);
|
||||
}
|
||||
}
|
||||
.fadeOut {
|
||||
animation: fadeOut 0.5s ease 0.2s 1 forwards;
|
||||
}
|
||||
.fadeOutWithouDelay {
|
||||
animation: fadeOut 0.5s ease 0s 1 forwards;
|
||||
}
|
||||
@keyframes fadeOut {
|
||||
0% {
|
||||
opacity: 1;
|
||||
transform: translateY(0px);
|
||||
}
|
||||
100% {
|
||||
transform: translateY(-10px) scale(0.9);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
.fadeIn {
|
||||
animation: fadeIn 0.5s ease 0s 1 forwards;
|
||||
}
|
||||
@keyframes fadeIn {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translateY(-10px) scale(0.9);
|
||||
}
|
||||
100% {
|
||||
transform: translateY(0px);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -0,0 +1,371 @@
|
||||
<template>
|
||||
<div id="hly-list-root">
|
||||
<div class="loading" v-if="this.loading">
|
||||
<span>正在加载...</span>
|
||||
<span></span>
|
||||
</div>
|
||||
<div class="card">
|
||||
<header>
|
||||
<section>
|
||||
<!-- 选择筛选方式 -->
|
||||
<el-select style="margin-right:10px;" v-model="query" filterable placeholder="选择筛选的方式">
|
||||
<el-option
|
||||
v-for="item in queryOpt"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
></el-option>
|
||||
</el-select>
|
||||
|
||||
<!-- 筛选综合选项 -->
|
||||
<el-select
|
||||
style="margin-right:10px;"
|
||||
v-model="currentHlyZLJCDate"
|
||||
filterable
|
||||
placeholder="根据日期筛选"
|
||||
v-if="query == 2"
|
||||
>
|
||||
<el-option label="全部日期" :value="0"></el-option>
|
||||
<el-option
|
||||
v-for="item in hly_ZLJC_dates_opt"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
></el-option>
|
||||
</el-select>
|
||||
|
||||
<!-- 筛选得分最高的 -->
|
||||
<el-select
|
||||
style="margin-right:10px;"
|
||||
v-model="currentDate"
|
||||
filterable
|
||||
placeholder="根据日期筛选"
|
||||
v-if="query == 0"
|
||||
>
|
||||
<el-option label="全部日期" :value="0"></el-option>
|
||||
<el-option
|
||||
v-for="item in datesOpt"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
></el-option>
|
||||
</el-select>
|
||||
|
||||
<!-- 筛选得分稳定增加的 -->
|
||||
<el-select
|
||||
style="margin-right:10px;"
|
||||
v-model="raiseDate"
|
||||
filterable
|
||||
placeholder="根据日期筛选"
|
||||
v-if="query == 1"
|
||||
>
|
||||
<el-option label="全部日期" :value="0"></el-option>
|
||||
<el-option
|
||||
v-for="item in raiseDatesOpt"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
></el-option>
|
||||
</el-select>
|
||||
|
||||
<!-- 筛选得分稳定增加的 (筛选天数)-->
|
||||
<el-select
|
||||
style="margin-right:10px;"
|
||||
v-model="day"
|
||||
filterable
|
||||
placeholder="筛选连续打分天数"
|
||||
v-if="query == 1 && raiseDate != 0"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in days"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<el-select v-model="value" filterable placeholder="选择代码">
|
||||
<el-option
|
||||
v-for="item in options"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
></el-option>
|
||||
</el-select>
|
||||
<el-button
|
||||
style="margin:0px 10px;"
|
||||
@click="jpToDetail"
|
||||
:disabled="!this.value"
|
||||
type="primary"
|
||||
>Go!</el-button>
|
||||
</section>
|
||||
</header>
|
||||
|
||||
<div id="main">
|
||||
<div
|
||||
:class="['code', opt.value==value?'ckd':'']"
|
||||
v-for="opt in options"
|
||||
:key="opt.value"
|
||||
@click="value=opt.value"
|
||||
>{{ opt.value }}</div>
|
||||
|
||||
<div v-for="i in 100" :key="i" class="fill"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import codes from "@/data/code_list.js";
|
||||
import { cloneDeep } from "lodash";
|
||||
export default {
|
||||
name: "codelist",
|
||||
data() {
|
||||
return {
|
||||
value: undefined,
|
||||
currentDate: 0,
|
||||
raiseDate: 0,
|
||||
loading: false,
|
||||
queryOpt: [
|
||||
{ label: "根据日期筛选得分最高的", value: 0 },
|
||||
{ label: "根据日期筛选得分稳定增加的", value: 1 },
|
||||
{ label: "根据 hly 打分和 ZLJC ", value: 2 }
|
||||
],
|
||||
query: 0,
|
||||
day: undefined,
|
||||
currentHlyZLJCDate: 0
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
options() {
|
||||
let opt;
|
||||
if (this.query == 0) {
|
||||
if (this.currentDate == 0) {
|
||||
opt = codes.map(code => {
|
||||
return { label: code, value: code };
|
||||
});
|
||||
} else {
|
||||
opt = this.queryByDate[this.currentDate].map(code => {
|
||||
return { label: code, value: code };
|
||||
});
|
||||
}
|
||||
} else if (this.query == 1) {
|
||||
if (this.raiseDate == 0) {
|
||||
opt = codes.map(code => {
|
||||
return { label: code, value: code };
|
||||
});
|
||||
} else {
|
||||
if (this.day) {
|
||||
if (!this.queryByDateRaise[this.raiseDate][this.day]) {
|
||||
this.day = undefined;
|
||||
opt = codes.map(code => {
|
||||
return { label: code, value: code };
|
||||
});
|
||||
}
|
||||
opt = this.queryByDateRaise[this.raiseDate][this.day].map(code => {
|
||||
return { label: code, value: code };
|
||||
});
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
} else if (this.query == 2) {
|
||||
if (this.currentHlyZLJCDate == 0) {
|
||||
opt = codes.map(code => {
|
||||
return { label: code, value: code };
|
||||
});
|
||||
} else {
|
||||
return this.hlyZLJCRes[this.currentHlyZLJCDate].map(code => {
|
||||
return { label: code, value: code };
|
||||
});
|
||||
}
|
||||
}
|
||||
// this.loading = false;
|
||||
|
||||
return opt;
|
||||
},
|
||||
queryByDate() {
|
||||
return require("@/data/hly_count_res_max_2_group_by_date.json");
|
||||
},
|
||||
|
||||
queryByDateRaise() {
|
||||
return require("@/data/up_res_group_by_date_strict_mode.json");
|
||||
},
|
||||
hlyZLJCRes() {
|
||||
return require("@/data/hly_and_zljc_res.json");
|
||||
},
|
||||
|
||||
datesOpt() {
|
||||
return Object.keys(this.queryByDate)
|
||||
.sort((a, b) => {
|
||||
return (
|
||||
parseInt(b.split("-").join("")) - parseInt(a.split("-").join(""))
|
||||
);
|
||||
})
|
||||
.map(date => {
|
||||
return { label: date, value: date };
|
||||
});
|
||||
},
|
||||
|
||||
raiseDatesOpt() {
|
||||
return Object.keys(this.queryByDateRaise)
|
||||
.sort((a, b) => {
|
||||
return (
|
||||
parseInt(b.split("-").join("")) - parseInt(a.split("-").join(""))
|
||||
);
|
||||
})
|
||||
.map(date => {
|
||||
return { label: date, value: date };
|
||||
});
|
||||
},
|
||||
|
||||
days() {
|
||||
return Object.keys(this.queryByDateRaise[this.raiseDate]).map(day => {
|
||||
return { label: `sum_${day.slice(1)}`, value: day };
|
||||
});
|
||||
},
|
||||
hly_ZLJC_dates_opt() {
|
||||
return Object.keys(this.hlyZLJCRes)
|
||||
.sort((a, b) => {
|
||||
return (
|
||||
parseInt(b.split("-").join("")) - parseInt(a.split("-").join(""))
|
||||
);
|
||||
})
|
||||
.map(date => {
|
||||
return { label: date, value: date };
|
||||
});
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
jpToDetail() {
|
||||
this.$router.push({ path: `/hly/${this.value}` });
|
||||
},
|
||||
confirmQuery() {
|
||||
console.log(this.raiseDate, this.day);
|
||||
// this.option = this.queryByDateRaise[this.raiseDate][this.day].map(code => {
|
||||
// return { label: code, value: code}
|
||||
// })
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
#hly-list-root {
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
background-color: #f6f6f6;
|
||||
|
||||
.card {
|
||||
height: 90vh;
|
||||
margin: 0px auto;
|
||||
margin-top: 5vh;
|
||||
padding: 0;
|
||||
border-radius: 5px;
|
||||
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1);
|
||||
overflow: hidden;
|
||||
@media screen and(max-width: 1000px) {
|
||||
width: 90%;
|
||||
}
|
||||
@media screen and(min-width: 1300px) {
|
||||
width: 1200px;
|
||||
}
|
||||
background-color: #fff;
|
||||
|
||||
header {
|
||||
margin-top: 10px;
|
||||
margin-bottom: 20px;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 10px 50px;
|
||||
}
|
||||
#main {
|
||||
width: 90%;
|
||||
margin-left: 5%;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
overflow-y: scroll;
|
||||
// background-color: aquamarine;
|
||||
height: ~"calc(100% - 120px)";
|
||||
padding-bottom: 100px;
|
||||
box-sizing: content-box;
|
||||
align-content: flex-start !important;
|
||||
justify-content: space-around;
|
||||
.code {
|
||||
width: 80px;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
cursor: pointer;
|
||||
margin: 5px;
|
||||
font-size: 0.8rem;
|
||||
// font-weight: bold;
|
||||
transition: all 0.3s ease-in-out;
|
||||
text-align: center;
|
||||
background-color: #f6f6f6;
|
||||
border-radius: 5px;
|
||||
justify-content: flex-start;
|
||||
flex-shrink: 0;
|
||||
&:hover,
|
||||
&.ckd {
|
||||
background-color: rgb(102, 177, 255);
|
||||
color: #fff;
|
||||
font-weight: bold;
|
||||
box-shadow: 0px 0px 10px rgba(102, 177, 255, 0.5);
|
||||
}
|
||||
}
|
||||
.fill {
|
||||
width: 80px;
|
||||
height: 2px;
|
||||
flex-shrink: 0;
|
||||
margin: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.loading {
|
||||
transition: all 0.3s ease-in-out;
|
||||
position: absolute;
|
||||
top: 70px;
|
||||
left: 50%;
|
||||
margin-left: -100px;
|
||||
box-shadow: 0px 2px 8px rgba(0, 0, 0, 0.1);
|
||||
width: 200px;
|
||||
height: 55px;
|
||||
border-radius: 5px;
|
||||
background-color: #fff;
|
||||
z-index: 9999;
|
||||
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
span {
|
||||
display: inline-block;
|
||||
font-size: 0.8rem;
|
||||
|
||||
&:nth-child(2) {
|
||||
border: 2px solid transparent;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border-radius: 50%;
|
||||
border-top: 2px solid rgb(78, 78, 78);
|
||||
border-right: 2px solid rgb(78, 78, 78);
|
||||
margin-left: 20px;
|
||||
animation: rotate 1s linear 0s infinite normal;
|
||||
}
|
||||
@keyframes rotate {
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
@ -0,0 +1,25 @@
|
||||
import Vue from 'vue'
|
||||
import Router from 'vue-router'
|
||||
|
||||
Vue.use(Router)
|
||||
|
||||
export default new Router({
|
||||
// mode: 'hash',
|
||||
base: process.env.BASE_URL,
|
||||
routes: [
|
||||
{
|
||||
path: '',
|
||||
redirect: '/hly/list',
|
||||
},
|
||||
{
|
||||
path: '/hly/list',
|
||||
name: 'hlylist',
|
||||
component: () => import( /* webpackChunkName: "code-list" */ '@/pages/HlyList')
|
||||
},
|
||||
{
|
||||
path: '/hly/:code',
|
||||
name: 'hlyDetail',
|
||||
component: () => import( /* webpackChunkName: "hly-detail" */ '@/pages/HlyDetail')
|
||||
},
|
||||
]
|
||||
})
|
@ -0,0 +1,41 @@
|
||||
import Vue from 'vue'
|
||||
import Vuex from 'vuex'
|
||||
|
||||
Vue.use(Vuex)
|
||||
|
||||
|
||||
const state = {
|
||||
|
||||
}
|
||||
|
||||
const getters = {}
|
||||
for (const constantName in state) {
|
||||
if (state.hasOwnProperty(constantName)) {
|
||||
getters[constantName] = state => {
|
||||
return state[constantName];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const mutations = {
|
||||
|
||||
}
|
||||
|
||||
|
||||
const modulesFiles = require.context('./modules', true, /\.js$/)
|
||||
|
||||
|
||||
const modules = modulesFiles.keys().reduce((modules, modulePath) => {
|
||||
// set './app.js' => 'app'
|
||||
const moduleName = modulePath.replace(/^\.\/(.*)\.\w+$/, '$1')
|
||||
const value = modulesFiles(modulePath)
|
||||
modules[moduleName] = value.default
|
||||
return modules
|
||||
}, {})
|
||||
export default new Vuex.Store({
|
||||
state,
|
||||
getters,
|
||||
mutations,
|
||||
// actions,
|
||||
modules,
|
||||
})
|
@ -0,0 +1,60 @@
|
||||
const state = {
|
||||
daySum: 7,
|
||||
selectedData: [],
|
||||
ma: [],
|
||||
showCount: false,
|
||||
currentDataType: 0,
|
||||
currentResType: 0,
|
||||
currentHlyResType: 0,
|
||||
currentHlyResWay: 0,
|
||||
resMA: undefined,
|
||||
resDay: undefined,
|
||||
forceResPos: {
|
||||
max: false,
|
||||
min: false,
|
||||
},
|
||||
forcePos: {
|
||||
max: false,
|
||||
min: false
|
||||
},
|
||||
selectedZhiBiao: 0,
|
||||
}
|
||||
|
||||
const getters = {}
|
||||
for (const constantName in state) {
|
||||
if (state.hasOwnProperty(constantName)) {
|
||||
getters[constantName] = state => {
|
||||
return state[constantName];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const mutations = {
|
||||
'UPDATE'(state, {
|
||||
constant,
|
||||
value
|
||||
}) {
|
||||
state[constant] = value;
|
||||
},
|
||||
'RESET_RES'(state) {
|
||||
state["showCount"] = false;
|
||||
state["currentDataType"] = 0;
|
||||
state["currentResType"] = 0;
|
||||
state["resMA"] = undefined;
|
||||
state["resDay"] = undefined;
|
||||
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
const actions = {
|
||||
|
||||
}
|
||||
|
||||
export default {
|
||||
namespaced: true,
|
||||
state,
|
||||
getters,
|
||||
mutations,
|
||||
actions
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
// vue.config.js
|
||||
module.exports = {
|
||||
publicPath:"./",
|
||||
// 输出文件目录
|
||||
outputDir: 'dist',
|
||||
devServer: {
|
||||
proxy: 'http://localhost:3000'
|
||||
},
|
||||
chainWebpack: config => {
|
||||
// json5 Loader
|
||||
config.module
|
||||
.rule('json5')
|
||||
.test(/\.json5$/)
|
||||
.use('json5-loader')
|
||||
.loader('json5-loader')
|
||||
.end()
|
||||
},
|
||||
transpileDependencies: [
|
||||
'vue-echarts',
|
||||
'resize-detector'
|
||||
],
|
||||
runtimeCompiler: false,
|
||||
css: {
|
||||
loaderOptions: {
|
||||
less: {
|
||||
javascriptEnabled: true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,2 @@
|
||||
node_modules
|
||||
public/dayline
|
@ -0,0 +1,57 @@
|
||||
var createError = require('http-errors');
|
||||
var express = require('express');
|
||||
var path = require('path');
|
||||
var cookieParser = require('cookie-parser');
|
||||
var logger = require('morgan');
|
||||
var ejs = require('ejs');
|
||||
|
||||
var indexRouter = require('./routes/index');
|
||||
var ApiRouter = require('./routes/api');
|
||||
|
||||
var app = express();
|
||||
|
||||
// view engine setup
|
||||
app.set('views', path.join(__dirname, '/src/views'));
|
||||
app.engine('html', require('ejs').__express);
|
||||
app.set('view engine', 'html');
|
||||
|
||||
app.all('*', function (req, res, next) {
|
||||
res.header('Access-Control-Allow-Origin', '*');
|
||||
//Access-Control-Allow-Headers ,可根据浏览器的F12查看,把对应的粘贴在这里就行
|
||||
res.header('Access-Control-Allow-Headers', 'Content-Type');
|
||||
res.header('Access-Control-Allow-Methods', '*');
|
||||
// res.header('Content-Type', 'application/json;charset=utf-8');
|
||||
next();
|
||||
});
|
||||
|
||||
// view engine setup
|
||||
app.set('views', path.join(__dirname, 'views'));
|
||||
app.set('view engine', 'jade');
|
||||
|
||||
app.use(logger('dev'));
|
||||
app.use(express.json());
|
||||
app.use(express.urlencoded({ extended: false }));
|
||||
app.use(cookieParser());
|
||||
// app.use(express.static(path.join(__dirname, 'public')));
|
||||
|
||||
app.use("/", express.static('public/stock/'))
|
||||
// app.use('/', indexRouter);
|
||||
app.use('/api', ApiRouter);
|
||||
|
||||
// catch 404 and forward to error handler
|
||||
app.use(function(req, res, next) {
|
||||
next(createError(404));
|
||||
});
|
||||
|
||||
// error handler
|
||||
app.use(function(err, req, res, next) {
|
||||
// set locals, only providing error in development
|
||||
res.locals.message = err.message;
|
||||
res.locals.error = req.app.get('env') === 'development' ? err : {};
|
||||
|
||||
// render the error page
|
||||
res.status(err.status || 500);
|
||||
res.render('error');
|
||||
});
|
||||
|
||||
module.exports = app;
|
@ -0,0 +1,90 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var app = require('../app');
|
||||
var debug = require('debug')('server:server');
|
||||
var http = require('http');
|
||||
|
||||
/**
|
||||
* Get port from environment and store in Express.
|
||||
*/
|
||||
|
||||
var port = normalizePort(process.env.PORT || '3000');
|
||||
app.set('port', port);
|
||||
|
||||
/**
|
||||
* Create HTTP server.
|
||||
*/
|
||||
|
||||
var server = http.createServer(app);
|
||||
|
||||
/**
|
||||
* Listen on provided port, on all network interfaces.
|
||||
*/
|
||||
|
||||
server.listen(port);
|
||||
server.on('error', onError);
|
||||
server.on('listening', onListening);
|
||||
|
||||
/**
|
||||
* Normalize a port into a number, string, or false.
|
||||
*/
|
||||
|
||||
function normalizePort(val) {
|
||||
var port = parseInt(val, 10);
|
||||
|
||||
if (isNaN(port)) {
|
||||
// named pipe
|
||||
return val;
|
||||
}
|
||||
|
||||
if (port >= 0) {
|
||||
// port number
|
||||
return port;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Event listener for HTTP server "error" event.
|
||||
*/
|
||||
|
||||
function onError(error) {
|
||||
if (error.syscall !== 'listen') {
|
||||
throw error;
|
||||
}
|
||||
|
||||
var bind = typeof port === 'string'
|
||||
? 'Pipe ' + port
|
||||
: 'Port ' + port;
|
||||
|
||||
// handle specific listen errors with friendly messages
|
||||
switch (error.code) {
|
||||
case 'EACCES':
|
||||
console.error(bind + ' requires elevated privileges');
|
||||
process.exit(1);
|
||||
break;
|
||||
case 'EADDRINUSE':
|
||||
console.error(bind + ' is already in use');
|
||||
process.exit(1);
|
||||
break;
|
||||
default:
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Event listener for HTTP server "listening" event.
|
||||
*/
|
||||
|
||||
function onListening() {
|
||||
var addr = server.address();
|
||||
var bind = typeof addr === 'string'
|
||||
? 'pipe ' + addr
|
||||
: 'port ' + addr.port;
|
||||
debug('Listening on ' + bind);
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
{
|
||||
"name": "server",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"start": "node ./bin/www"
|
||||
},
|
||||
"dependencies": {
|
||||
"cookie-parser": "~1.4.4",
|
||||
"debug": "~2.6.9",
|
||||
"express": "~4.16.1",
|
||||
"http-errors": "~1.6.3",
|
||||
"jade": "~1.11.0",
|
||||
"morgan": "~1.9.1"
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||
<title>Document</title>
|
||||
</head>
|
||||
<body>
|
||||
Hello Express
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1 @@
|
||||
*{margin:0;padding:0}html,html body,html body #app{width:100%;height:100%}html body #app{background-color:#f6f6f6}
|
@ -0,0 +1 @@
|
||||
#hly-list-root[data-v-562aeba9]{width:100vw;height:100vh;overflow:hidden;background-color:#f6f6f6}#hly-list-root .card[data-v-562aeba9]{height:90vh;margin:0 auto;margin-top:5vh;padding:0;border-radius:5px;-webkit-box-shadow:0 0 10px rgba(0,0,0,.1);box-shadow:0 0 10px rgba(0,0,0,.1);overflow:hidden;background-color:#fff}@media screen and (max-width:1000px){#hly-list-root .card[data-v-562aeba9]{width:90%}}@media screen and (min-width:1000px){#hly-list-root .card[data-v-562aeba9]{width:900px}}#hly-list-root .card header[data-v-562aeba9]{width:100%;height:120px;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}#hly-list-root .card main[data-v-562aeba9]{width:90%;margin-left:5%;display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;cursor:pointer;overflow-y:scroll;height:calc(100% - 120px);padding-bottom:100px;-webkit-box-sizing:border-box;box-sizing:border-box}#hly-list-root .card main .code[data-v-562aeba9]{width:80px;height:40px;line-height:40px;margin:5px;font-size:.8rem;-webkit-transition:all .3s ease-in-out;transition:all .3s ease-in-out;text-align:center;background-color:#f6f6f6;border-radius:5px;-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start}#hly-list-root .card main .code.ckd[data-v-562aeba9],#hly-list-root .card main .code[data-v-562aeba9]:hover{background-color:#66b1ff;color:#fff;font-weight:700;-webkit-box-shadow:0 0 10px rgba(102,177,255,.5);box-shadow:0 0 10px rgba(102,177,255,.5)}
|
After Width: | Height: | Size: 4.2 KiB |
After Width: | Height: | Size: 1.2 KiB |
@ -0,0 +1 @@
|
||||
<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1"><link rel=icon href=favicon.ico><title>display</title><link href=css/code-list.d495dc67.css rel=prefetch><link href=css/hly-detail.245d424a.css rel=prefetch><link href=js/chunk-18a60fce.d9e66e9a.js rel=prefetch><link href=js/chunk-451923cc.446b3203.js rel=prefetch><link href=js/code-list.0806274d.js rel=prefetch><link href=js/code-list~hly-detail.8a3fa682.js rel=prefetch><link href=js/hly-detail.47873170.js rel=prefetch><link href=css/app.65bf6211.css rel=preload as=style><link href=css/chunk-vendors.1dc9a07f.css rel=preload as=style><link href=js/app.28524da7.js rel=preload as=script><link href=js/chunk-vendors.423e90cd.js rel=preload as=script><link href=css/chunk-vendors.1dc9a07f.css rel=stylesheet><link href=css/app.65bf6211.css rel=stylesheet></head><body><noscript><strong>We're sorry but display doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id=app></div><script src=js/chunk-vendors.423e90cd.js></script><script src=js/app.28524da7.js></script></body></html>
|