siat 3.2.20__py3-none-any.whl → 3.2.30__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- siat/allin.py +3 -0
- siat/common.py +32 -7
- siat/grafix.py +41 -7
- siat/luchy_draw.py +252 -0
- siat/market_china.py +171 -0
- siat/risk_adjusted_return2.py +22 -13
- siat/security_trend2.py +3 -2
- siat/stock.py +45 -12
- siat/stock_technical.py +137 -78
- siat/translate.py +13 -0
- {siat-3.2.20.dist-info → siat-3.2.30.dist-info}/METADATA +1 -1
- {siat-3.2.20.dist-info → siat-3.2.30.dist-info}/RECORD +14 -13
- {siat-3.2.20.dist-info → siat-3.2.30.dist-info}/WHEEL +0 -0
- {siat-3.2.20.dist-info → siat-3.2.30.dist-info}/top_level.txt +0 -0
siat/allin.py
CHANGED
siat/common.py
CHANGED
@@ -1620,7 +1620,7 @@ def print_progress_percent2(current,total_list,steps=5,leading_blanks=4):
|
|
1620
1620
|
pct=pct_list[pos]
|
1621
1621
|
|
1622
1622
|
if pct=="100%":
|
1623
|
-
print("100%
|
1623
|
+
print("100% wrapping up ...")
|
1624
1624
|
else:
|
1625
1625
|
print(pct,end=' ')
|
1626
1626
|
|
@@ -2182,10 +2182,27 @@ def descriptive_statistics2(df,titletxt,footnote,decimals=4,sortby='tpw_mean', \
|
|
2182
2182
|
print(" #Error(descriptive_statistics2): zero data found")
|
2183
2183
|
return
|
2184
2184
|
|
2185
|
+
#为避免nan的影响,对nan进行填充
|
2186
|
+
df.fillna(method='bfill',inplace=True)
|
2187
|
+
df.fillna(method='ffill',inplace=True)
|
2188
|
+
|
2189
|
+
#转换字符为数值
|
2190
|
+
import pandas as pd
|
2191
|
+
for c in list(df):
|
2192
|
+
try:
|
2193
|
+
df[c] = pd.to_numeric(df[c], errors='coerce')
|
2194
|
+
except:
|
2195
|
+
continue
|
2196
|
+
|
2197
|
+
dfn=df.select_dtypes(include='number')
|
2198
|
+
if dfn.empty:
|
2199
|
+
print(" #Error(descriptive_statistics2): no numeric columns found to describe")
|
2200
|
+
return
|
2201
|
+
|
2185
2202
|
# 计算短期趋势
|
2186
2203
|
df20=df.tail(trailing)
|
2187
2204
|
|
2188
|
-
ds=df.describe(include='
|
2205
|
+
ds=df.describe(include='number',percentiles=[.5])
|
2189
2206
|
dst=ds.T
|
2190
2207
|
cols=['min','max','50%','mean','std']
|
2191
2208
|
|
@@ -2952,6 +2969,10 @@ def df_preprocess(dfs,measure,axhline_label,x_label,y_label, \
|
|
2952
2969
|
"""
|
2953
2970
|
功能:对于dfs中的数据进行预处理变换,以便克服数量级压制现象更好地展现多条曲线的趋势
|
2954
2971
|
"""
|
2972
|
+
#填充空值,防止后续处理出错
|
2973
|
+
dfs.fillna(method='ffill') #使用前一个非NaN值填充(向下填充)
|
2974
|
+
dfs.fillna(method='bfill') #使用下一个非NaN值填充(向上填充)
|
2975
|
+
|
2955
2976
|
plus_sign=False
|
2956
2977
|
|
2957
2978
|
preprocess1=preprocess.lower()
|
@@ -2999,8 +3020,10 @@ def df_preprocess(dfs,measure,axhline_label,x_label,y_label, \
|
|
2999
3020
|
# 从头寻找第一个非空数值
|
3000
3021
|
import numpy as np
|
3001
3022
|
for n in range(0,len(dfs2)):
|
3002
|
-
|
3003
|
-
|
3023
|
+
try:
|
3024
|
+
checknan=np.isnan(dfs2[c][n])
|
3025
|
+
except: continue
|
3026
|
+
if checknan: continue
|
3004
3027
|
else:
|
3005
3028
|
cmean=dfs2[c][n] #使用第一个非空值
|
3006
3029
|
break
|
@@ -3011,8 +3034,9 @@ def df_preprocess(dfs,measure,axhline_label,x_label,y_label, \
|
|
3011
3034
|
scalingOptionText=text_lang('百分比','percentage')
|
3012
3035
|
else:
|
3013
3036
|
scalingOptionText=text_lang('变化率%','change%')
|
3014
|
-
|
3015
|
-
|
3037
|
+
try:
|
3038
|
+
meanlist=meanlist+[cmean]
|
3039
|
+
except: continue
|
3016
3040
|
|
3017
3041
|
#print(cmean,cstd,dfs2[c])
|
3018
3042
|
|
@@ -3765,7 +3789,8 @@ if __name__=='__main__':
|
|
3765
3789
|
upgrade_siat()
|
3766
3790
|
|
3767
3791
|
def upgrade_siat(module_list=['siat','akshare','pandas','pandas_datareader', \
|
3768
|
-
'yfinance','yahooquery','urllib3','tabulate','twine',
|
3792
|
+
'yfinance','yahooquery','urllib3','tabulate','twine', \
|
3793
|
+
'mplfinance','openpyxl','pip'], \
|
3769
3794
|
pipcmd="pip install --upgrade",alternative=""):
|
3770
3795
|
"""
|
3771
3796
|
功能:一次性升级siat及其相关插件
|
siat/grafix.py
CHANGED
@@ -1390,20 +1390,35 @@ def draw_lines2(df0,y_label,x_label,axhline_value,axhline_label,title_txt, \
|
|
1390
1390
|
collist=df.columns.values.tolist()
|
1391
1391
|
collist3=collist[:3] #专用于绘制布林带,取前3个字段
|
1392
1392
|
|
1393
|
+
if lslist==[]:
|
1394
|
+
lslist=['-','--','-.',':','-','--','-.',':','-','--','-.',':','-','--','-.',':',]
|
1395
|
+
if colorlist==[]:
|
1396
|
+
colorlist=['blue','tomato','green','chocolate','darksage','cyan','blueviolet','violet','darkcyan','gold','wheat','silver','darkred','brown','coral','pink',]
|
1397
|
+
|
1393
1398
|
#绘制折线图
|
1394
1399
|
for c in collist:
|
1395
1400
|
pos=collist.index(c)
|
1396
1401
|
try:
|
1397
1402
|
lcolor=colorlist[pos]
|
1403
|
+
except:
|
1404
|
+
lcolor=''
|
1405
|
+
try:
|
1398
1406
|
lls=lslist[pos]
|
1407
|
+
except:
|
1408
|
+
lls=''
|
1409
|
+
try:
|
1399
1410
|
llw=lwlist[pos]
|
1400
1411
|
except:
|
1401
|
-
|
1402
|
-
|
1403
|
-
|
1404
|
-
else:
|
1412
|
+
llw=linewidth_adjust(df)
|
1413
|
+
|
1414
|
+
if (lcolor !='') and (lls !=''):
|
1405
1415
|
plt.plot(df[c],label=c,linewidth=llw,ls=lls,color=lcolor)
|
1406
|
-
|
1416
|
+
elif (lcolor !=''):
|
1417
|
+
plt.plot(df[c],label=c,linewidth=llw,color=lcolor)
|
1418
|
+
else:
|
1419
|
+
plt.plot(df[c],label=c,linewidth=llw)
|
1420
|
+
|
1421
|
+
lines = plt.gca().lines; last_line_color = lines[-1].get_color()
|
1407
1422
|
|
1408
1423
|
#为折线加数据标签
|
1409
1424
|
if data_label==True:
|
@@ -1474,8 +1489,27 @@ def draw_lines2(df0,y_label,x_label,axhline_value,axhline_label,title_txt, \
|
|
1474
1489
|
|
1475
1490
|
#绘制带状区域
|
1476
1491
|
if band_area != '' and isinstance(band_area,list) and len(band_area)>=2:
|
1477
|
-
|
1478
|
-
|
1492
|
+
upper_line=band_area[0]; lower_line=band_area[1]
|
1493
|
+
if upper_line not in collist:
|
1494
|
+
upper_line=ectranslate(upper_line)
|
1495
|
+
lower_line=ectranslate(lower_line)
|
1496
|
+
|
1497
|
+
if upper_line not in collist:
|
1498
|
+
upper_line=ticker_name(upper_line)
|
1499
|
+
lower_line=ticker_name(lower_line)
|
1500
|
+
|
1501
|
+
if upper_line not in collist:
|
1502
|
+
upper_line=None
|
1503
|
+
lower_line=None
|
1504
|
+
|
1505
|
+
if not (upper_line is None) and not (lower_line is None):
|
1506
|
+
"""
|
1507
|
+
plt.fill_between(df.index,df[upper_line],df[lower_line],color='moccasin',alpha=0.5,label='',where=df[upper_line]>=df[lower_line])
|
1508
|
+
plt.fill_between(df.index,df[upper_line],df[lower_line],color='aquamarine',alpha=0.5,label='',where=df[upper_line]<=df[lower_line])
|
1509
|
+
"""
|
1510
|
+
plt.fill_between(df.index,df[upper_line],df[lower_line],color='aquamarine',alpha=0.5,label='')
|
1511
|
+
|
1512
|
+
|
1479
1513
|
#绘制水平辅助线
|
1480
1514
|
if axhline_label !="":
|
1481
1515
|
if "零线" in axhline_label:
|
siat/luchy_draw.py
ADDED
@@ -0,0 +1,252 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
"""
|
4
|
+
本模块功能:幸运抽奖,仅限课堂案例演示用
|
5
|
+
创建日期:2024年6月29日
|
6
|
+
最新修订日期:
|
7
|
+
作者:王德宏 (WANG Dehong, Peter)
|
8
|
+
作者单位:北京外国语大学国际商学院
|
9
|
+
用途限制:仅限研究与教学使用,不可商用!商用需要额外授权。
|
10
|
+
特别声明:作者不对使用本工具进行证券投资导致的任何损益负责!
|
11
|
+
"""
|
12
|
+
|
13
|
+
#==============================================================================
|
14
|
+
#关闭所有警告
|
15
|
+
import warnings; warnings.filterwarnings('ignore')
|
16
|
+
import warnings; warnings.filterwarnings('ignore')
|
17
|
+
|
18
|
+
import pandas as pd
|
19
|
+
import pickle
|
20
|
+
import random
|
21
|
+
import datetime
|
22
|
+
import time
|
23
|
+
|
24
|
+
#==============================================================================
|
25
|
+
if __name__=='__main__':
|
26
|
+
text="A B C"
|
27
|
+
text_color='red'
|
28
|
+
text_size=12
|
29
|
+
delay=1
|
30
|
+
|
31
|
+
typewriter(text,text_color='red',text_size=12,delay=1)
|
32
|
+
|
33
|
+
def typewriter(text,text_color='blue',text_size=12,delay=1):
|
34
|
+
from IPython.display import display_html
|
35
|
+
|
36
|
+
text_html="<center><font size="+str(text_size)+" color="+text_color+">"+text
|
37
|
+
display_html(text_html, raw=True)
|
38
|
+
|
39
|
+
return
|
40
|
+
|
41
|
+
#==============================================================================
|
42
|
+
|
43
|
+
def pickle_write(df,pickle_path):
|
44
|
+
with open(pickle_path, 'wb') as pickle_file:
|
45
|
+
# 使用pickle模块的dump函数写入对象
|
46
|
+
pickle.dump(df,pickle_file)
|
47
|
+
|
48
|
+
if __name__=='__main__':
|
49
|
+
file_path="S:\北外工作-24春\小学期-人大\学生名单\student_list.xlsx"
|
50
|
+
pickle_path="student_list.pkl"
|
51
|
+
skiprows=1
|
52
|
+
column='Name'
|
53
|
+
|
54
|
+
namelist_get(file_path,skiprows=1,column='Name',pickle_path="student_list.pkl")
|
55
|
+
|
56
|
+
def lucky_draw_initialize(file_path,skiprows=1,column='Name',pickle_path="student_list.pkl"):
|
57
|
+
"""
|
58
|
+
功能:读入带有指定路径的Excel文件file_path,跳过前skiprows行
|
59
|
+
Excel文件结构:抽奖名单字段为'Name',字段位于第2行
|
60
|
+
输出:存入pickle文件student_list.pkl
|
61
|
+
"""
|
62
|
+
|
63
|
+
df = pd.read_excel(file_path,skiprows=skiprows)
|
64
|
+
|
65
|
+
df1=df[[column]].copy()
|
66
|
+
|
67
|
+
todaydt = str(datetime.date.today())
|
68
|
+
df1['Date']=todaydt
|
69
|
+
df1['Lucky']=0
|
70
|
+
df1['Absent']=0
|
71
|
+
df1['Answer']=0
|
72
|
+
|
73
|
+
#排序
|
74
|
+
df1.sort_values(by=[column,'Date','Lucky','Absent','Answer'],inplace=True)
|
75
|
+
df1.reset_index(drop=True,inplace=True)
|
76
|
+
|
77
|
+
pickle_write(df1,pickle_path)
|
78
|
+
|
79
|
+
return
|
80
|
+
|
81
|
+
#==============================================================================
|
82
|
+
if __name__=='__main__':
|
83
|
+
pickle_path="student_list.pkl"
|
84
|
+
|
85
|
+
df=pickle_read(pickle_path)
|
86
|
+
|
87
|
+
def pickle_read(pickle_path="student_list.pkl"):
|
88
|
+
with open(pickle_path,'rb') as pickle_file:
|
89
|
+
df = pickle.load(pickle_file)
|
90
|
+
return df
|
91
|
+
|
92
|
+
#==============================================================================
|
93
|
+
|
94
|
+
|
95
|
+
|
96
|
+
def pickle_append(df,column='Name',pickle_path="student_list.pkl"):
|
97
|
+
df_tmp=pickle_read(pickle_path)
|
98
|
+
df_new=pd.concat([df_tmp,df])
|
99
|
+
|
100
|
+
df_new.sort_values(by=[column,'Date'],inplace=True)
|
101
|
+
|
102
|
+
pickle_write(df_new,pickle_path)
|
103
|
+
|
104
|
+
return
|
105
|
+
|
106
|
+
#==============================================================================
|
107
|
+
if __name__=='__main__':
|
108
|
+
alist=["A","B","C","D"]
|
109
|
+
|
110
|
+
for i in range(4):
|
111
|
+
print(random_select(alist))
|
112
|
+
|
113
|
+
|
114
|
+
def random_select(alist):
|
115
|
+
return random.choice(alist)
|
116
|
+
|
117
|
+
#==============================================================================
|
118
|
+
|
119
|
+
if __name__=='__main__':
|
120
|
+
prompt="Is the lucky person here in class?"
|
121
|
+
|
122
|
+
read_yes_no(prompt)
|
123
|
+
|
124
|
+
|
125
|
+
def read_yes_no(prompt, default=None):
|
126
|
+
if default is None:
|
127
|
+
prompt += " [yes/no] "
|
128
|
+
else:
|
129
|
+
prompt += " [yes/no] (default: %s) " % ('yes' if default else 'no')
|
130
|
+
while True:
|
131
|
+
user_input = input(prompt).lower()
|
132
|
+
if user_input in ['', 'yes', 'y', 'true']:
|
133
|
+
return True
|
134
|
+
elif user_input in ['no', 'n', 'false']:
|
135
|
+
return False
|
136
|
+
elif user_input == '' and default is not None:
|
137
|
+
return default
|
138
|
+
else:
|
139
|
+
print("Please enter 'yes' or 'no' (or 'y'/'n').")
|
140
|
+
|
141
|
+
return
|
142
|
+
|
143
|
+
#==============================================================================
|
144
|
+
if __name__=='__main__':
|
145
|
+
draw_limit=2
|
146
|
+
absent_limit=2
|
147
|
+
column='Name'
|
148
|
+
pickle_path="student_list.pkl"
|
149
|
+
|
150
|
+
lucky_draw()
|
151
|
+
df=pickle_read(pickle_path)
|
152
|
+
|
153
|
+
|
154
|
+
def lucky_draw(draw_limit=2,absent_limit=2,column='Name',pickle_path="student_list.pkl"):
|
155
|
+
"""
|
156
|
+
draw_limit=2:整个课程每人最多2次抽签机会
|
157
|
+
absent_limit=2:整个课程每人最多缺席2次,超过就丧失抽签资格
|
158
|
+
"""
|
159
|
+
df=pickle_read(pickle_path)
|
160
|
+
|
161
|
+
alist=list(set(list(df[column])))
|
162
|
+
|
163
|
+
found=False
|
164
|
+
todaydt = str(datetime.date.today())
|
165
|
+
prompt="*** Is the lucky person here on site?"
|
166
|
+
prompt2="*** Do you expect to pass?"
|
167
|
+
|
168
|
+
while True:
|
169
|
+
while True:
|
170
|
+
aname=random_select(alist)
|
171
|
+
|
172
|
+
adf=df[df[column]==aname]
|
173
|
+
atimes=adf['Lucky'].sum()
|
174
|
+
aonsite=adf['Absent'].sum()
|
175
|
+
|
176
|
+
if atimes < draw_limit and aonsite <= absent_limit:
|
177
|
+
#检查今日是否被抽中过
|
178
|
+
drew_today=False
|
179
|
+
try:
|
180
|
+
adf_today=adf[adf['Date']==todaydt]
|
181
|
+
if len(adf_today) > 0:
|
182
|
+
if adf_today['Lucky'].sum() > 0 or adf_today['Absent'].sum() > 0:
|
183
|
+
drew_today=True
|
184
|
+
except: pass
|
185
|
+
|
186
|
+
if not drew_today:
|
187
|
+
found=True
|
188
|
+
break
|
189
|
+
else: continue
|
190
|
+
else:
|
191
|
+
continue
|
192
|
+
|
193
|
+
if not found:
|
194
|
+
print("Congratulations! all person has been lucky for",limit,"times")
|
195
|
+
else:
|
196
|
+
"""
|
197
|
+
print("\nThe lucky person is ",end='')
|
198
|
+
typewriter(aname,delay=1)
|
199
|
+
"""
|
200
|
+
typewriter(text=aname,text_color='blue',text_size=12,delay=1)
|
201
|
+
|
202
|
+
#print('')
|
203
|
+
onsite=read_yes_no(prompt)
|
204
|
+
#是否到场
|
205
|
+
if onsite: absent=0
|
206
|
+
else: absent=1
|
207
|
+
|
208
|
+
onpass=False; answer=0
|
209
|
+
if onsite:
|
210
|
+
onpass=read_yes_no(prompt2)
|
211
|
+
#是否pass
|
212
|
+
if onpass: answer=0
|
213
|
+
else: answer=1
|
214
|
+
|
215
|
+
#只要抽中,不论是否到场都记录
|
216
|
+
row=pd.Series({column:aname,'Date':todaydt,'Lucky':1,'Absent':absent,'Answer':answer})
|
217
|
+
try:
|
218
|
+
df=df.append(row,ignore_index=True)
|
219
|
+
except:
|
220
|
+
df=df._append(row,ignore_index=True)
|
221
|
+
|
222
|
+
if onsite and not onpass:
|
223
|
+
#到场且不pass,结束本轮抽签
|
224
|
+
break
|
225
|
+
else:
|
226
|
+
#未到场或pass,继续抽签
|
227
|
+
continue
|
228
|
+
|
229
|
+
df.sort_values(by=[column,'Date'],inplace=True)
|
230
|
+
pickle_write(df,pickle_path)
|
231
|
+
|
232
|
+
return
|
233
|
+
|
234
|
+
#==============================================================================
|
235
|
+
#==============================================================================
|
236
|
+
#==============================================================================
|
237
|
+
#==============================================================================
|
238
|
+
|
239
|
+
|
240
|
+
|
241
|
+
|
242
|
+
|
243
|
+
|
244
|
+
|
245
|
+
|
246
|
+
|
247
|
+
|
248
|
+
#==============================================================================#==============================================================================
|
249
|
+
#==============================================================================#==============================================================================
|
250
|
+
#==============================================================================#==============================================================================
|
251
|
+
|
252
|
+
#==============================================================================
|
siat/market_china.py
CHANGED
@@ -904,6 +904,177 @@ def market_detail_china2table(df,titletxt,firstColSpecial=True,leftColAlign='l',
|
|
904
904
|
return
|
905
905
|
|
906
906
|
#==============================================================================
|
907
|
+
#==============================================================================
|
908
|
+
if __name__=='__main__':
|
909
|
+
category='price'
|
910
|
+
category='valuation'
|
911
|
+
|
912
|
+
facecolor='papayawhip'
|
913
|
+
decimals=2
|
914
|
+
font_size='16px'
|
915
|
+
|
916
|
+
df1=market_detail_china(category='price')
|
917
|
+
df1=market_detail_china(category='price')
|
918
|
+
|
919
|
+
def market_detail_china2(category='price',
|
920
|
+
facecolor='papayawhip',
|
921
|
+
decimals=2,
|
922
|
+
font_size='22px'):
|
923
|
+
"""
|
924
|
+
功能:给出中国当前最新的三大股票交易所的更多细节,合成
|
925
|
+
输出:构造表格型数据框df,利用CSS格式输出
|
926
|
+
数据来源:em东方财富
|
927
|
+
"""
|
928
|
+
#确定表格字体大小
|
929
|
+
titile_font_size=font_size
|
930
|
+
heading_font_size=data_font_size=str(int(font_size.replace('px',''))-2)+'px'
|
931
|
+
|
932
|
+
# 检查信息类别
|
933
|
+
category1=category.upper()
|
934
|
+
catelist=["PRICE","VOLUME","RETURN","VALUATION"]
|
935
|
+
catenamelist=["当前股价","当前成交量","近期投资回报","市值与估值"]
|
936
|
+
if not (category1 in catelist):
|
937
|
+
print(" #Error(market_detail_china2): invalid category",category)
|
938
|
+
print(" Valid category",catelist)
|
939
|
+
return None
|
940
|
+
|
941
|
+
# 合并三大交易所
|
942
|
+
import pandas as pd
|
943
|
+
df=pd.DataFrame()
|
944
|
+
exchlist=["SSE","SZSE","BJSE"]
|
945
|
+
for e in exchlist:
|
946
|
+
dft=market_detail_exchange_china(exchange=e,category=category)
|
947
|
+
if dft is None:
|
948
|
+
print(" #Warning(market_detail_china): info inaccessible for",e,"\b, try later")
|
949
|
+
#return None
|
950
|
+
continue
|
951
|
+
if len(dft)==0:
|
952
|
+
print(" #Warning(market_detail_china): zero info found for",e,"\b, try later")
|
953
|
+
continue
|
954
|
+
|
955
|
+
if len(df)==0:
|
956
|
+
df=dft
|
957
|
+
else:
|
958
|
+
df=pd.merge(df,dft,left_index=True,right_index=True)
|
959
|
+
|
960
|
+
if len(df)==0:
|
961
|
+
print(" #Warning(market_detail_china2): zero info found for",exchlist,"\b, try later")
|
962
|
+
return None
|
963
|
+
|
964
|
+
# 处理索引字段
|
965
|
+
newcollist=['项目']+list(df)
|
966
|
+
df['项目']=df.index
|
967
|
+
df=df[newcollist]
|
968
|
+
|
969
|
+
# 将空缺值替换为空格
|
970
|
+
df.fillna('',inplace=True)
|
971
|
+
|
972
|
+
import datetime as dt
|
973
|
+
nowstr0=str(dt.datetime.now())
|
974
|
+
nowstr=nowstr0[:19]
|
975
|
+
|
976
|
+
# 前置空格个数
|
977
|
+
heading=' '*1
|
978
|
+
|
979
|
+
if category1=='PRICE':
|
980
|
+
titletxt="中国三大股票交易所横向对比:股价与涨跌"
|
981
|
+
|
982
|
+
ft0=heading+"信息来源:东方财富,统计时间:"+nowstr+"\n"
|
983
|
+
ft1=heading+"注释:\n"
|
984
|
+
ft2=heading+"☆可交易股票数量:将随着股票停复牌情况变化\n"
|
985
|
+
ft3=heading+"☆昨日指的是上一个交易日\n"
|
986
|
+
ft4=heading+"☆涨速:平均每分钟股价变化率,表示股价变化速度\n"
|
987
|
+
ft5=heading+"☆5分钟涨跌:最新5分钟内股价的涨跌幅度\n"
|
988
|
+
ft6=heading+"☆振幅:最高最低价差绝对值/昨收,表示股价变化活跃程度\n"
|
989
|
+
ft7=heading+"☆涨跌幅:(最新价-昨收)/昨收,表示相对昨日的变化程度\n"
|
990
|
+
ft8=heading+"☆涨跌额:最新价-昨收,表示相对昨日的变化金额\n"
|
991
|
+
|
992
|
+
ft9=heading+"☆使用实时数据,不同日期/每天不同时刻统计的结果可能不同\n"
|
993
|
+
ft10=heading+"☆若在非交易日或开市前后短期内统计,数据可能出现空缺\n"
|
994
|
+
|
995
|
+
footnote=ft0+ft1+ft2+ft3+ft4+ft5+ft6+ft7+ft8+ft9+ft10
|
996
|
+
|
997
|
+
df_display_CSS(df,titletxt=titletxt,footnote=footnote,facecolor=facecolor, \
|
998
|
+
first_col_align='left',second_col_align='right', \
|
999
|
+
last_col_align='right',other_col_align='right', \
|
1000
|
+
titile_font_size=titile_font_size, \
|
1001
|
+
heading_font_size=heading_font_size, \
|
1002
|
+
data_font_size=data_font_size)
|
1003
|
+
|
1004
|
+
|
1005
|
+
if category1=='VOLUME':
|
1006
|
+
titletxt="中国三大股票交易所横向对比:成交状况"
|
1007
|
+
|
1008
|
+
ft0=heading+"信息来源:东方财富,统计时间:"+nowstr+"\n"
|
1009
|
+
ft1=heading+"注:\n"
|
1010
|
+
ft2=heading+"☆可交易股票数量:将随着股票停复牌情况变化\n"
|
1011
|
+
ft3=heading+"☆成交量:当前成交股数,表示交易活跃度\n"
|
1012
|
+
ft4=heading+"☆成交额:当前开市后的累计成交金额\n"
|
1013
|
+
ft5=heading+"☆换手率:成交量/流通股数,表示成交量占比\n"
|
1014
|
+
ft6=heading+"☆量比:当前每分钟成交量/过去5个交易日均值,表示成交量变化\n"
|
1015
|
+
|
1016
|
+
ft9=heading+"☆使用实时数据,不同日期/每天不同时刻统计的结果可能不同\n"
|
1017
|
+
ft10=heading+"☆若在非开市时间或开市前后短期内统计,数据可能出现空缺\n"
|
1018
|
+
|
1019
|
+
footnote=ft0+ft1+ft2+ft3+ft4+ft5+ft6 + ft9+ft10
|
1020
|
+
|
1021
|
+
df_display_CSS(df,titletxt=titletxt,footnote=footnote,facecolor=facecolor, \
|
1022
|
+
first_col_align='left',second_col_align='right', \
|
1023
|
+
last_col_align='right',other_col_align='right', \
|
1024
|
+
titile_font_size=titile_font_size, \
|
1025
|
+
heading_font_size=heading_font_size, \
|
1026
|
+
data_font_size=data_font_size)
|
1027
|
+
|
1028
|
+
|
1029
|
+
if category1=='RETURN':
|
1030
|
+
titletxt="中国三大股票交易所横向对比:投资回报"
|
1031
|
+
|
1032
|
+
ft0=heading+"信息来源:东方财富,统计时间:"+nowstr+"\n"
|
1033
|
+
ft1=heading+"注:\n"
|
1034
|
+
ft2=heading+"☆可交易股票数量:将随着股票停复牌情况变化\n"
|
1035
|
+
ft3=heading+"☆MRQ:最近一个季度的滚动数据\n"
|
1036
|
+
ft4=heading+"☆YTD:今年以来的累计情况\n"
|
1037
|
+
|
1038
|
+
ft9=heading+"☆使用实时数据,不同日期/每天不同时刻统计的结果可能不同\n"
|
1039
|
+
ft10=heading+"☆若在非开市时间或开市前后短期内统计,数据可能出现空缺\n"
|
1040
|
+
|
1041
|
+
footnote=ft0+ft1+ft2+ft3+ft4 + ft9+ft10
|
1042
|
+
|
1043
|
+
df_display_CSS(df,titletxt=titletxt,footnote=footnote,facecolor=facecolor, \
|
1044
|
+
first_col_align='left',second_col_align='right', \
|
1045
|
+
last_col_align='right',other_col_align='right', \
|
1046
|
+
titile_font_size=titile_font_size, \
|
1047
|
+
heading_font_size=heading_font_size, \
|
1048
|
+
data_font_size=data_font_size)
|
1049
|
+
|
1050
|
+
|
1051
|
+
if category1=='VALUATION':
|
1052
|
+
titletxt="中国三大股票交易所横向对比:市值与估值"
|
1053
|
+
|
1054
|
+
ft0=heading+"信息来源:东方财富,统计时间:"+nowstr+"\n"
|
1055
|
+
ft1=heading+"注:\n"
|
1056
|
+
ft2=heading+"☆可交易股票数量:将随着股票停复牌情况变化\n"
|
1057
|
+
ft3=heading+"☆市盈率:这里为动态市盈率,即市盈率TTM,过去12个月的连续变化\n"
|
1058
|
+
ft4=heading+"☆市净率:这里为静态市净率\n"
|
1059
|
+
ft5=heading+"☆标准差/均值=标准差(数值)/均值,提升可比性\n"
|
1060
|
+
|
1061
|
+
ft9=heading+"☆使用实时数据,不同日期/每天不同时刻统计的结果可能不同\n"
|
1062
|
+
ft10=heading+"☆若在非开市时间或开市前后短期内统计,数据可能出现空缺\n"
|
1063
|
+
|
1064
|
+
footnote=ft0+ft1+ft2+ft3+ft4+ft5 + ft9+ft10
|
1065
|
+
|
1066
|
+
df_display_CSS(df,titletxt=titletxt,footnote=footnote,facecolor=facecolor, \
|
1067
|
+
first_col_align='left',second_col_align='right', \
|
1068
|
+
last_col_align='right',other_col_align='right', \
|
1069
|
+
titile_font_size=titile_font_size, \
|
1070
|
+
heading_font_size=heading_font_size, \
|
1071
|
+
data_font_size=data_font_size)
|
1072
|
+
|
1073
|
+
|
1074
|
+
return df
|
1075
|
+
|
1076
|
+
#==============================================================================
|
1077
|
+
|
907
1078
|
#==============================================================================
|
908
1079
|
#==============================================================================
|
909
1080
|
#==============================================================================
|
siat/risk_adjusted_return2.py
CHANGED
@@ -699,17 +699,22 @@ if __name__=='__main__':
|
|
699
699
|
ticker=["600519.SS","000858.SZ"]
|
700
700
|
ticker={'Market':('US','^SPX','中概教培组合'),'EDU':0.7,'TAL':0.3}
|
701
701
|
|
702
|
-
|
703
|
-
end="2024-3-15"
|
704
|
-
rar='sharpe'
|
705
|
-
ret_type="Monthly Ret%"
|
706
|
-
RF=0.01759
|
707
|
-
regression_period=365
|
702
|
+
ticker=['601628.SS','601319.SS','601318.SS','00966.HK']
|
708
703
|
|
709
|
-
|
710
|
-
|
711
|
-
|
704
|
+
start="2023-6-27"
|
705
|
+
end="2024-6-27"
|
706
|
+
rar='sharpe'
|
707
|
+
RF=0.01692
|
708
|
+
printout=True
|
709
|
+
|
710
|
+
ret_type="Annual Ret%"; regression_period=365
|
711
|
+
graph=True; loc1='best'
|
712
|
+
axhline_value=0; axhline_label=''
|
713
|
+
sortby='tpw_mean'; trailing=7; trend_threshhold=0.01
|
714
|
+
annotate=False; annotate_value=False
|
715
|
+
mark_top=False; mark_bottom=False; mark_end=False
|
712
716
|
mktidx='auto'; source='auto'
|
717
|
+
style_print=True; ticker_type='auto';facecolor='whitesmoke'
|
713
718
|
|
714
719
|
rars=compare_mticker_1rar(ticker=["600519.SS","000858.SZ"],start="2024-1-1",end="2024-6-16",rar='sharpe',printout=True)
|
715
720
|
|
@@ -719,7 +724,7 @@ def compare_mticker_1rar(ticker,start,end,rar='sharpe', \
|
|
719
724
|
axhline_value=0,axhline_label='', \
|
720
725
|
printout=False,sortby='tpw_mean',trailing=7,trend_threshhold=0.01, \
|
721
726
|
annotate=False,annotate_value=False, \
|
722
|
-
|
727
|
+
mark_top=False,mark_bottom=False,mark_end=False, \
|
723
728
|
mktidx='auto',source='auto', \
|
724
729
|
style_print=True,ticker_type='auto',facecolor='whitesmoke'):
|
725
730
|
"""
|
@@ -781,6 +786,10 @@ def compare_mticker_1rar(ticker,start,end,rar='sharpe', \
|
|
781
786
|
|
782
787
|
#仅用于绘图和制表
|
783
788
|
df1=df.copy()
|
789
|
+
#进行空缺值填充,以便绘图连续
|
790
|
+
df1.fillna(method='bfill',inplace=True)
|
791
|
+
df1.fillna(method='ffill',inplace=True)
|
792
|
+
|
784
793
|
for c in list(df1):
|
785
794
|
if df1[c].max() > axhline_value and df1[c].min() < axhline_value:
|
786
795
|
axhline_label='零线' #显示零线,但不标注图例
|
@@ -817,7 +826,7 @@ def compare_mticker_1rar(ticker,start,end,rar='sharpe', \
|
|
817
826
|
facecolor=facecolor,loc=loc1)
|
818
827
|
|
819
828
|
#制表
|
820
|
-
recommenddf=pd.DataFrame()
|
829
|
+
#recommenddf=pd.DataFrame()
|
821
830
|
if printout:
|
822
831
|
if sortby=='tpw_mean':
|
823
832
|
sortby_txt='按推荐标记+近期优先加权平均值降序排列'
|
@@ -837,8 +846,8 @@ def compare_mticker_1rar(ticker,start,end,rar='sharpe', \
|
|
837
846
|
footnote7="近期优先趋势和星号为风险调整收益指标加趋势等多项因素综合研判,最多五颗星"
|
838
847
|
footnotey=footnote6+'\n'+footnote7+'\n'+footnotex
|
839
848
|
|
840
|
-
|
841
|
-
df1.dropna(inplace=True,axis=1)
|
849
|
+
#不能简单删除含有Nan的行,否则导致清空df1,应该进行填充
|
850
|
+
#df1.dropna(inplace=True,axis=1)
|
842
851
|
recommenddf=descriptive_statistics2(df1,title_txt,footnotey,decimals=4, \
|
843
852
|
sortby=sortby,recommend_only=True,trailing=trailing, \
|
844
853
|
trend_threshhold=trend_threshhold, \
|