siat 3.0.38__py3-none-any.whl → 3.0.41__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/common.py +27 -12
- siat/exchange_bond_china.pickle +0 -0
- siat/fund_china.pickle +0 -0
- siat/risk_adjusted_return2.py +11 -6
- siat/sector_china.py +227 -76
- siat/security_prices.py +8 -0
- siat/stock.py +1 -1
- siat/stock_info.pickle +0 -0
- siat/stock_technical.py +8 -3
- siat/translate.py +503 -150
- {siat-3.0.38.dist-info → siat-3.0.41.dist-info}/METADATA +1 -1
- {siat-3.0.38.dist-info → siat-3.0.41.dist-info}/RECORD +14 -14
- {siat-3.0.38.dist-info → siat-3.0.41.dist-info}/WHEEL +1 -1
- {siat-3.0.38.dist-info → siat-3.0.41.dist-info}/top_level.txt +0 -0
siat/sector_china.py
CHANGED
@@ -672,11 +672,13 @@ def industry_sw_list_all():
|
|
672
672
|
import pandas as pd
|
673
673
|
import akshare as ak
|
674
674
|
|
675
|
-
symboltypes=["市场表征", "一级行业", "二级行业", "风格指数"]
|
676
|
-
indextypecodes=['F','
|
675
|
+
symboltypes=["市场表征", "一级行业", "二级行业", "风格指数","大类风格指数","金创指数"]
|
676
|
+
indextypecodes=['F','1','2','S','B','C']
|
677
677
|
industry=pd.DataFrame()
|
678
678
|
for s in symboltypes:
|
679
|
-
|
679
|
+
try:
|
680
|
+
dft = ak.index_realtime_sw(symbol=s)
|
681
|
+
except: continue
|
680
682
|
|
681
683
|
pos=symboltypes.index(s)
|
682
684
|
dft['指数类别代码']=indextypecodes[pos]
|
@@ -742,8 +744,8 @@ def display_industry_sw(sw_level='1',numberPerLine=4,colalign='left'):
|
|
742
744
|
"""
|
743
745
|
按照类别打印申万行业列表,名称(代码),每行5个, 套壳函数
|
744
746
|
"""
|
745
|
-
itype_list=['
|
746
|
-
sw_level_list=['1','2','3','F','S']
|
747
|
+
itype_list=['1','2','3','F','S','B','C']
|
748
|
+
sw_level_list=['1','2','3','F','S','B','C']
|
747
749
|
pos=sw_level_list.index(sw_level)
|
748
750
|
itype=itype_list[pos]
|
749
751
|
|
@@ -754,30 +756,30 @@ def display_industry_sw(sw_level='1',numberPerLine=4,colalign='left'):
|
|
754
756
|
|
755
757
|
|
756
758
|
if __name__=='__main__':
|
757
|
-
itype='
|
759
|
+
itype='1'
|
758
760
|
numberPerLine=5
|
759
761
|
colalign='left'
|
760
762
|
|
761
|
-
print_industry_sw(itype='
|
763
|
+
print_industry_sw(itype='1',numberPerLine=5,colalign='right')
|
762
764
|
|
763
|
-
def print_industry_sw(itype='
|
765
|
+
def print_industry_sw(itype='1',numberPerLine=5,colalign='left'):
|
764
766
|
"""
|
765
767
|
功能:按照类别打印申万行业列表,名称(代码)
|
766
|
-
行业分级itype:F
|
768
|
+
行业分级itype:F=市场表征, 1=一级行业, 2=二级行业, 3=三级行业, S="风格指数",B=大类风格,C=金创
|
767
769
|
"""
|
768
770
|
df=industry_sw_list()
|
769
771
|
df1=df[df['type']==itype]
|
770
772
|
df1['name_code']=df1.apply(lambda x: x['name']+'('+x['code']+'.SW'+')',axis=1)
|
771
773
|
|
772
|
-
symboltypes=["市场表征", "一级行业", "二级行业", "三级行业", "风格指数"]
|
773
|
-
indextypecodes=['F','
|
774
|
+
symboltypes=["市场表征", "一级行业", "二级行业", "三级行业", "风格指数", "大类风格指数","金创指数"]
|
775
|
+
indextypecodes=['F','1','2','3','S','B','C']
|
774
776
|
pos=indextypecodes.index(itype)
|
775
777
|
iname=symboltypes[pos]
|
776
778
|
|
777
779
|
ilist=list(df1['name_code'])
|
778
780
|
print("\n*** 申万行业分类:"+iname+",共计"+str(len(ilist))+'个行业(板块)')
|
779
781
|
|
780
|
-
if itype=='
|
782
|
+
if itype=='2': numberPerLine=4
|
781
783
|
if itype=='3': numberPerLine=3
|
782
784
|
|
783
785
|
printInLine_md(ilist,numberPerLine=numberPerLine,colalign=colalign)
|
@@ -942,17 +944,17 @@ if __name__=='__main__':
|
|
942
944
|
start='2018-1-1'
|
943
945
|
end='2022-10-31'
|
944
946
|
measure='Exp Ret%'
|
945
|
-
itype='
|
947
|
+
itype='1'
|
946
948
|
graph=True
|
947
949
|
axisamp=0.8
|
948
950
|
|
949
951
|
def industry_ranking_sw(start,end,measure='Exp Ret%', \
|
950
|
-
itype='
|
952
|
+
itype='1',period="day", \
|
951
953
|
graph=True,axisamp=0.8):
|
952
954
|
"""
|
953
955
|
完整版,全流程
|
954
956
|
功能:模板,遍历某类申万指数,计算某项业绩指标,汇集排序
|
955
|
-
itype: F表征指数,
|
957
|
+
itype: F表征指数,n=1/2/3行业指数,S风格指数,B大类风格指数,C金创指数
|
956
958
|
period="day"; choice of {"day", "week", "month"}
|
957
959
|
绘图:柱状图,可选
|
958
960
|
"""
|
@@ -973,11 +975,17 @@ def industry_ranking_sw(start,end,measure='Exp Ret%', \
|
|
973
975
|
df=pd.DataFrame(columns=['date','ticker','start','end','item','value'])
|
974
976
|
|
975
977
|
print("\nSearching industry prices, it may take great time, please wait ...")
|
978
|
+
|
979
|
+
fail_list=[]
|
976
980
|
for i in ilist:
|
977
981
|
|
978
982
|
print(" Processing industry",i,"\b, please wait ...")
|
979
983
|
#抓取指数价格,选取期间范围
|
980
|
-
|
984
|
+
try:
|
985
|
+
dft = ak.index_hist_sw(symbol=i,period="day")
|
986
|
+
except:
|
987
|
+
fail_list=fail_list+[i]
|
988
|
+
continue
|
981
989
|
|
982
990
|
dft['ticker']=dft['代码']
|
983
991
|
dft['date']=dft['日期'].apply(lambda x: pd.to_datetime(x))
|
@@ -1017,7 +1025,7 @@ def industry_ranking_sw(start,end,measure='Exp Ret%', \
|
|
1017
1025
|
df['name']=df['ticker'].apply(lambda x: industry_sw_name(x))
|
1018
1026
|
df.set_index('name',inplace=True)
|
1019
1027
|
colname='value'
|
1020
|
-
titletxt="
|
1028
|
+
titletxt="行业分析:业绩排名"
|
1021
1029
|
import datetime; today=datetime.date.today()
|
1022
1030
|
footnote0=ectranslate(measure)+' ==>\n'
|
1023
1031
|
footnote1='申万行业分类,观察期:'+start+'至'+iend+'\n'
|
@@ -1026,6 +1034,13 @@ def industry_ranking_sw(start,end,measure='Exp Ret%', \
|
|
1026
1034
|
|
1027
1035
|
plot_barh(df,colname,titletxt,footnote,axisamp=axisamp)
|
1028
1036
|
#plot_barh2(df,colname,titletxt,footnote)
|
1037
|
+
|
1038
|
+
if len(fail_list) > 0:
|
1039
|
+
print(" Unable to retrieve",len(fail_list),"industry(ies) as follows:")
|
1040
|
+
if len(fail_list) >= 10:
|
1041
|
+
printInLine_md(fail_list,numberPerLine=10,colalign='left',font_size='16px')
|
1042
|
+
else:
|
1043
|
+
printInLine_md(fail_list,numberPerLine=len(fail_list),colalign='left',font_size='16px')
|
1029
1044
|
|
1030
1045
|
return df
|
1031
1046
|
|
@@ -1033,7 +1048,7 @@ if __name__=='__main__':
|
|
1033
1048
|
start='2018-1-1'
|
1034
1049
|
end='2022-10-31'
|
1035
1050
|
measure='Exp Ret%'
|
1036
|
-
itype='
|
1051
|
+
itype='1'
|
1037
1052
|
graph=True
|
1038
1053
|
axisamp=0.8
|
1039
1054
|
|
@@ -1122,7 +1137,7 @@ def industry_ranking_sw2(industrylist,start,end,measure='Exp Ret%', \
|
|
1122
1137
|
df.dropna(inplace=True)
|
1123
1138
|
|
1124
1139
|
colname='value'
|
1125
|
-
titletxt="
|
1140
|
+
titletxt="行业分析:业绩排名"
|
1126
1141
|
import datetime; today=datetime.date.today()
|
1127
1142
|
footnote0=ectranslate(measure)+' ==>\n'
|
1128
1143
|
footnote1='申万行业分类,观察期:'+start+'至'+iend+'\n'
|
@@ -1142,20 +1157,20 @@ if __name__=='__main__':
|
|
1142
1157
|
period="day"
|
1143
1158
|
industry_list='all'
|
1144
1159
|
|
1145
|
-
def get_industry_sw(itype='
|
1160
|
+
def get_industry_sw(itype='1',period="day",industry_list='all'):
|
1146
1161
|
"""
|
1147
1162
|
功能:遍历某类申万指数,下载数据
|
1148
|
-
itype: F表征指数,
|
1163
|
+
itype: F表征指数,n=1/2/3行业指数,S风格指数,B大类风格,C金创类
|
1149
1164
|
period="day"; choice of {"day", "week", "month"}
|
1150
1165
|
industry_list: 允许选择部分行业
|
1151
1166
|
"""
|
1152
1167
|
|
1153
1168
|
#检查itype的合理性
|
1154
|
-
typelist=['F','
|
1169
|
+
typelist=['F','1','2','3','S','B','C','A']
|
1155
1170
|
if not (itype in typelist):
|
1156
1171
|
print(" #Error(get_industry_sw): unsupported industry category",itype)
|
1157
1172
|
print(" Supported industry category",typelist)
|
1158
|
-
print(" F: Featured,
|
1173
|
+
print(" F: Featured, n-Level n Industry, S-Styled, B- Big Styled, C- Financial Innovation, A-All (more time))")
|
1159
1174
|
return None
|
1160
1175
|
|
1161
1176
|
#获得指数代码
|
@@ -1176,7 +1191,7 @@ def get_industry_sw(itype='I',period="day",industry_list='all'):
|
|
1176
1191
|
import datetime
|
1177
1192
|
df=pd.DataFrame()
|
1178
1193
|
|
1179
|
-
print("
|
1194
|
+
print(" Searching industry information, please wait ...")
|
1180
1195
|
num=len(ilist)
|
1181
1196
|
if num <= 10:
|
1182
1197
|
steps=5
|
@@ -1184,6 +1199,7 @@ def get_industry_sw(itype='I',period="day",industry_list='all'):
|
|
1184
1199
|
steps=10
|
1185
1200
|
|
1186
1201
|
total=len(ilist)
|
1202
|
+
fail_list=[]
|
1187
1203
|
for i in ilist:
|
1188
1204
|
|
1189
1205
|
#print(" Retrieving information for industry",i)
|
@@ -1192,7 +1208,8 @@ def get_industry_sw(itype='I',period="day",industry_list='all'):
|
|
1192
1208
|
try:
|
1193
1209
|
dft = ak.index_hist_sw(symbol=i,period="day")
|
1194
1210
|
except:
|
1195
|
-
print(" #Warning(get_industry_sw): unsupported industry",i)
|
1211
|
+
#print(" #Warning(get_industry_sw): unsupported industry",i)
|
1212
|
+
fail_list=fail_list+[i]
|
1196
1213
|
continue
|
1197
1214
|
|
1198
1215
|
dft['ticker']=dft['代码']
|
@@ -1217,8 +1234,19 @@ def get_industry_sw(itype='I',period="day",industry_list='all'):
|
|
1217
1234
|
print_progress_percent(current,total,steps=steps,leading_blanks=2)
|
1218
1235
|
|
1219
1236
|
#num=list(set(list(df['ticker'])))
|
1220
|
-
|
1237
|
+
if len(fail_list)==0:
|
1238
|
+
print(" Successfully retrieved",len(df),"records in",len(ilist),"industries")
|
1239
|
+
else:
|
1240
|
+
print("\n Successfully retrieved",len(df),"records in",len(ilist),"industries")
|
1221
1241
|
#print(" Successfully retrieved",len(df),"records in",num,"industries")
|
1242
|
+
|
1243
|
+
if len(fail_list) > 0:
|
1244
|
+
print(" Failed to retrieve",len(fail_list),"industry(ies) as follows:")
|
1245
|
+
if len(fail_list) >= 10:
|
1246
|
+
printInLine_md(fail_list,numberPerLine=10,colalign='left',font_size='16px')
|
1247
|
+
else:
|
1248
|
+
printInLine_md(fail_list,numberPerLine=len(fail_list),colalign='left',font_size='16px')
|
1249
|
+
|
1222
1250
|
return df
|
1223
1251
|
|
1224
1252
|
|
@@ -1260,15 +1288,15 @@ def get_industry_sw2(industry_list,period="day"):
|
|
1260
1288
|
steps=10
|
1261
1289
|
|
1262
1290
|
total=len(ilist)
|
1291
|
+
fail_list=[]
|
1263
1292
|
for i in ilist:
|
1264
|
-
|
1265
1293
|
#print(" Retrieving information for industry",i)
|
1266
|
-
|
1267
1294
|
#抓取指数价格
|
1268
1295
|
try:
|
1269
1296
|
dft = ak.index_hist_sw(symbol=i,period="day")
|
1270
1297
|
except:
|
1271
|
-
print(" #Warning(get_industry_sw): unsupported industry",i)
|
1298
|
+
#print(" #Warning(get_industry_sw): unsupported industry",i)
|
1299
|
+
fail_list=fail_list+[i]
|
1272
1300
|
continue
|
1273
1301
|
|
1274
1302
|
dft['ticker']=dft['代码']
|
@@ -1293,8 +1321,19 @@ def get_industry_sw2(industry_list,period="day"):
|
|
1293
1321
|
print_progress_percent(current,total,steps=steps,leading_blanks=2)
|
1294
1322
|
|
1295
1323
|
#num=list(set(list(df['ticker'])))
|
1296
|
-
|
1324
|
+
if len(fail_list) > 0:
|
1325
|
+
print("\n Successfully retrieved",len(df),"records in",len(ilist),"industries")
|
1326
|
+
else:
|
1327
|
+
print(" Successfully retrieved",len(df),"records in",len(ilist),"industries")
|
1297
1328
|
#print(" Successfully retrieved",len(df),"records in",num,"industries")
|
1329
|
+
if len(fail_list) > 0:
|
1330
|
+
print(" Failed to retrieve",len(fail_list),"industry(ies) as follows:")
|
1331
|
+
if len(fail_list) >= 10:
|
1332
|
+
printInLine_md(fail_list,numberPerLine=10,colalign='left',font_size='16px')
|
1333
|
+
else:
|
1334
|
+
printInLine_md(fail_list,numberPerLine=len(fail_list),colalign='left',font_size='16px')
|
1335
|
+
|
1336
|
+
|
1298
1337
|
return df
|
1299
1338
|
|
1300
1339
|
#==============================================================================
|
@@ -1336,7 +1375,7 @@ def calc_industry_sw(df,start,end):
|
|
1336
1375
|
idf=pd.DataFrame()
|
1337
1376
|
idfall=pd.DataFrame()
|
1338
1377
|
|
1339
|
-
print("
|
1378
|
+
print(" Calculating industry performance, please wait ...")
|
1340
1379
|
num=len(ilist)
|
1341
1380
|
if num <= 10:
|
1342
1381
|
steps=5
|
@@ -1413,7 +1452,7 @@ if __name__=='__main__':
|
|
1413
1452
|
|
1414
1453
|
def rank_industry_sw(idf,measure='Exp Ret%',industries=[], \
|
1415
1454
|
graph=True,axisamp=0.8,px=False,maxitems=32, \
|
1416
|
-
|
1455
|
+
printout=False,facecolor='papayawhip',font_size='16px'):
|
1417
1456
|
"""
|
1418
1457
|
功能:遍历某类申万指数的某项业绩指标,汇集排序
|
1419
1458
|
绘图:水平柱状图
|
@@ -1483,11 +1522,18 @@ def rank_industry_sw(idf,measure='Exp Ret%',industries=[], \
|
|
1483
1522
|
gdf2.reset_index(inplace=True)
|
1484
1523
|
gdf2.index=gdf2.index+1
|
1485
1524
|
gdf2.columns=['行业名称','行业代码',ectranslate(measure),'开始日期','结束日期']
|
1486
|
-
|
1525
|
+
"""
|
1487
1526
|
print("***",titletxt,'\n')
|
1488
1527
|
alignlist=['center']+['left']*(len(list(gdf2))-1)
|
1489
1528
|
print(gdf2.to_markdown(index=True,tablefmt='plain',colalign=alignlist))
|
1529
|
+
"""
|
1530
|
+
#确定表格字体大小
|
1531
|
+
titile_font_size=font_size
|
1532
|
+
heading_font_size=data_font_size=str(int(font_size.replace('px',''))-1)+'px'
|
1490
1533
|
|
1534
|
+
df_display_CSS(gdf2,titletxt=titletxt,footnote=footnote,facecolor=facecolor, \
|
1535
|
+
titile_font_size=titile_font_size,heading_font_size=heading_font_size, \
|
1536
|
+
data_font_size=data_font_size)
|
1491
1537
|
|
1492
1538
|
if graph:
|
1493
1539
|
if (len(gdf1) <= maxitems):
|
@@ -1523,12 +1569,12 @@ if __name__=='__main__':
|
|
1523
1569
|
measure='Exp Ret%'
|
1524
1570
|
start='2020-11-1'
|
1525
1571
|
end='2022-10-31'
|
1526
|
-
itype='
|
1572
|
+
itype='1'
|
1527
1573
|
period="day"
|
1528
1574
|
graph=True
|
1529
1575
|
|
1530
1576
|
def compare_mindustry_sw(industry_list,measure,start,end, \
|
1531
|
-
itype='
|
1577
|
+
itype='1',period="day",graph=True,printout=False,sortby='tpw_mean'):
|
1532
1578
|
"""
|
1533
1579
|
功能:比较多个行业industry_list某个指标measure在时间段start/end的时间序列趋势
|
1534
1580
|
industry_list: 至少有两项,若太多了则生成的曲线过于密集
|
@@ -1639,8 +1685,8 @@ def compare_mindustry_sw(industry_list,measure,start,end, \
|
|
1639
1685
|
else:
|
1640
1686
|
pass
|
1641
1687
|
|
1642
|
-
title_txt=
|
1643
|
-
additional_note="
|
1688
|
+
title_txt=title_txt+':'+y_label+','+sortby_txt
|
1689
|
+
additional_note="注:列表仅显示有星号标记或特定数量的证券。"
|
1644
1690
|
footnote='比较期间:'+start+'至'+end
|
1645
1691
|
ds=descriptive_statistics(df2,title_txt,additional_note+footnote,decimals=4, \
|
1646
1692
|
sortby=sortby,recommend_only=False)
|
@@ -1793,7 +1839,7 @@ if __name__=='__main__':
|
|
1793
1839
|
measure='Exp Ret%'
|
1794
1840
|
start='2020-11-1'
|
1795
1841
|
end='2022-10-31'
|
1796
|
-
itype='
|
1842
|
+
itype='1'
|
1797
1843
|
period="day"
|
1798
1844
|
graph=True
|
1799
1845
|
|
@@ -2094,12 +2140,12 @@ def get_industry_data_sw(start,end,sw_level='1'):
|
|
2094
2140
|
功能:获得申万行业历史数据, 套壳函数
|
2095
2141
|
start: 开始日期
|
2096
2142
|
end: 结束日期
|
2097
|
-
sw_level: '1', '2', '3', 'F', 'S'
|
2143
|
+
sw_level: '1', '2', '3', 'F', 'S', 'B', 'C'
|
2098
2144
|
|
2099
2145
|
返回:idf, idfall,供进一步分析使用。
|
2100
2146
|
"""
|
2101
|
-
itype_list=['
|
2102
|
-
sw_level_list=['1','2','3','F','S']
|
2147
|
+
itype_list=['1','2','3','F','S', 'B', 'C']
|
2148
|
+
sw_level_list=['1','2','3','F','S', 'B', 'C']
|
2103
2149
|
pos=sw_level_list.index(sw_level)
|
2104
2150
|
itype=itype_list[pos]
|
2105
2151
|
|
@@ -2112,11 +2158,11 @@ if __name__ =="__main__":
|
|
2112
2158
|
|
2113
2159
|
# 新冠疫情三年
|
2114
2160
|
start='2023-1-1'; end='2023-4-10'
|
2115
|
-
itype='
|
2161
|
+
itype='F'
|
2116
2162
|
|
2117
|
-
idf,idfall=get_industry_info_sw(start,end,itype='
|
2163
|
+
idf,idfall=get_industry_info_sw(start,end,itype='1')
|
2118
2164
|
|
2119
|
-
def get_industry_info_sw(start,end,itype='
|
2165
|
+
def get_industry_info_sw(start,end,itype='1'):
|
2120
2166
|
"""
|
2121
2167
|
功能:获得申万行业历史数据
|
2122
2168
|
start: 开始日期
|
@@ -2190,7 +2236,8 @@ if __name__ =="__main__":
|
|
2190
2236
|
|
2191
2237
|
def rank_msecurity_performance(tickers,start,end, \
|
2192
2238
|
measures=['Exp Ret%'], \
|
2193
|
-
market_index='000001.SS',window=252,colalign='right'
|
2239
|
+
market_index='000001.SS',window=252,colalign='right', \
|
2240
|
+
facecolor='papayawhip',font_size='16px'):
|
2194
2241
|
"""
|
2195
2242
|
功能:列示多只股票多个指标的对比,从高到低
|
2196
2243
|
|
@@ -2264,6 +2311,7 @@ def rank_msecurity_performance(tickers,start,end, \
|
|
2264
2311
|
df1.reset_index(inplace=True)
|
2265
2312
|
df1.rename(columns={'index':'股票'},inplace=True)
|
2266
2313
|
|
2314
|
+
"""
|
2267
2315
|
alignlist=['left']+[colalign]*(len(allmeasures)-1)
|
2268
2316
|
|
2269
2317
|
print("\n*** 股票多重指标比较:按夏普比率降序排列\n")
|
@@ -2273,6 +2321,22 @@ def rank_msecurity_performance(tickers,start,end, \
|
|
2273
2321
|
print(" 表中的夏普比率/索替诺比率/阿尔法值均为TTM滚动值")
|
2274
2322
|
import datetime; today=datetime.date.today()
|
2275
2323
|
print(" 数据来源:新浪财经/东方财富,"+str(today)+'统计')
|
2324
|
+
"""
|
2325
|
+
titletxt="股票多重指标分析:按夏普比率降序排列"
|
2326
|
+
footnote1="观察期:"+start+'至'+end+',表中数据为'+end+'快照'
|
2327
|
+
footnote2="表中的夏普比率/索替诺比率/阿尔法值均为TTM滚动值"
|
2328
|
+
import datetime; todaydt=datetime.date.today()
|
2329
|
+
footnote3="数据来源:新浪财经/东方财富,"+str(todaydt)+'统计'
|
2330
|
+
footnote=footnote1+'\n'+footnote2+'n'+footnote3
|
2331
|
+
|
2332
|
+
#确定表格字体大小
|
2333
|
+
titile_font_size=font_size
|
2334
|
+
heading_font_size=data_font_size=str(int(font_size.replace('px',''))-1)+'px'
|
2335
|
+
|
2336
|
+
df_display_CSS(fsdf6,titletxt=titletxt,footnote=footnote,facecolor=facecolor, \
|
2337
|
+
titile_font_size=titile_font_size,heading_font_size=heading_font_size, \
|
2338
|
+
data_font_size=data_font_size)
|
2339
|
+
|
2276
2340
|
|
2277
2341
|
return df1
|
2278
2342
|
#==============================================================================
|
@@ -2283,7 +2347,7 @@ if __name__=='__main__':
|
|
2283
2347
|
end='2023-3-22'
|
2284
2348
|
info_type='Close'
|
2285
2349
|
|
2286
|
-
df=get_industry_sw('
|
2350
|
+
df=get_industry_sw('1')
|
2287
2351
|
df=industry_correlation_sw(df,tickers,start,end,info_type='Close')
|
2288
2352
|
|
2289
2353
|
def cm2inch(x,y):
|
@@ -2440,7 +2504,8 @@ if __name__=='__main__':
|
|
2440
2504
|
top=10
|
2441
2505
|
printout=True
|
2442
2506
|
|
2443
|
-
def mixed_industry_stocks(industries=['煤炭','医药生物'],top=10,printout=True
|
2507
|
+
def mixed_industry_stocks(industries=['煤炭','医药生物'],top=10,printout=True, \
|
2508
|
+
facecolor='papayawhip',font_size='16px'):
|
2444
2509
|
"""
|
2445
2510
|
功能:将不同行业指数(industries)中的前top个(按指数内权重降序)成分股合成为字典,等权重
|
2446
2511
|
"""
|
@@ -2475,16 +2540,27 @@ def mixed_industry_stocks(industries=['煤炭','医药生物'],top=10,printout=T
|
|
2475
2540
|
df_print=df[['序号','证券名称','证券代码','初始权重','行业名称','行业代码']]
|
2476
2541
|
|
2477
2542
|
if printout:
|
2478
|
-
alignlist=['center']+['center']*(len(list(df_print))-1)
|
2543
|
+
#alignlist=['center']+['center']*(len(list(df_print))-1)
|
2479
2544
|
|
2480
2545
|
if len(industries) > 1:
|
2481
|
-
print("\n*** 混合行业投资组合的成分股:初始等权重\n")
|
2546
|
+
#print("\n*** 混合行业投资组合的成分股:初始等权重\n")
|
2547
|
+
titletxt="多行业投资组合的成分股:初始等权重"
|
2482
2548
|
else:
|
2483
|
-
print("\n*** 单一行业投资组合的成分股:初始等权重\n")
|
2549
|
+
#print("\n*** 单一行业投资组合的成分股:初始等权重\n")
|
2550
|
+
titletxt="单一行业投资组合的成分股:初始等权重"
|
2484
2551
|
|
2485
|
-
print(df_print.to_markdown(index=False,tablefmt='plain',colalign=alignlist))
|
2486
|
-
import datetime;
|
2487
|
-
print("\n*** 数据来源:申万宏源,统计日期:"+str(today))
|
2552
|
+
#print(df_print.to_markdown(index=False,tablefmt='plain',colalign=alignlist))
|
2553
|
+
import datetime; todaydt=datetime.date.today()
|
2554
|
+
#print("\n*** 数据来源:申万宏源,统计日期:"+str(today))
|
2555
|
+
footnote="数据来源:申万宏源,统计日期:"+str(todaydt)
|
2556
|
+
|
2557
|
+
#确定表格字体大小
|
2558
|
+
titile_font_size=font_size
|
2559
|
+
heading_font_size=data_font_size=str(int(font_size.replace('px',''))-1)+'px'
|
2560
|
+
|
2561
|
+
df_display_CSS(df_print,titletxt=titletxt,footnote=footnote,facecolor=facecolor, \
|
2562
|
+
titile_font_size=titile_font_size,heading_font_size=heading_font_size, \
|
2563
|
+
data_font_size=data_font_size)
|
2488
2564
|
|
2489
2565
|
# 生成成分股字典
|
2490
2566
|
stock_dict=df.set_index(['证券代码'])['初始权重'].to_dict()
|
@@ -2503,8 +2579,7 @@ def find_peers_china(industry='',top=20,rank=20,sw_level='2'):
|
|
2503
2579
|
"""
|
2504
2580
|
功能:
|
2505
2581
|
当industry = '',显示申万二级行业分类
|
2506
|
-
|
2507
|
-
sw_level:申万一级行业'1',二级行业'2',三级行业'3',其他'F'和'S'
|
2582
|
+
sw_level:申万一级行业'1',二级行业'2',三级行业'3',其他'F'、'S'、'B'、'C'
|
2508
2583
|
"""
|
2509
2584
|
|
2510
2585
|
# 避免混淆
|
@@ -2513,8 +2588,8 @@ def find_peers_china(industry='',top=20,rank=20,sw_level='2'):
|
|
2513
2588
|
|
2514
2589
|
# 默认情形处理
|
2515
2590
|
if industry == '':
|
2516
|
-
itype_list=['
|
2517
|
-
sw_level_list=['1','2','3','F','S']
|
2591
|
+
itype_list=['1','2','3','F','S','B','C']
|
2592
|
+
sw_level_list=['1','2','3','F','S','B','C']
|
2518
2593
|
pos=sw_level_list.index(sw_level)
|
2519
2594
|
itype=itype_list[pos]
|
2520
2595
|
|
@@ -2612,7 +2687,13 @@ def get_sw_index(ticker,start,end):
|
|
2612
2687
|
|
2613
2688
|
import akshare as ak
|
2614
2689
|
import pandas as pd
|
2615
|
-
|
2690
|
+
|
2691
|
+
try:
|
2692
|
+
dft = ak.index_hist_sw(symbol=symbol,period="day")
|
2693
|
+
except:
|
2694
|
+
print(" #Error(get_sw_index): failed to retrieve info for Shenwan industry index",symbol)
|
2695
|
+
return None
|
2696
|
+
|
2616
2697
|
dft['ticker']=dft['代码'].apply(lambda x: x+'.SW')
|
2617
2698
|
|
2618
2699
|
dft['name']=dft['代码'].apply(lambda x:industry_sw_name(x))
|
@@ -2636,6 +2717,7 @@ def get_sw_index(ticker,start,end):
|
|
2636
2717
|
dft4.sort_index(inplace=True)
|
2637
2718
|
|
2638
2719
|
df=dft4
|
2720
|
+
|
2639
2721
|
return df
|
2640
2722
|
|
2641
2723
|
#==============================================================================
|
@@ -2722,19 +2804,26 @@ if __name__ =="__main__":
|
|
2722
2804
|
printout='smart'
|
2723
2805
|
|
2724
2806
|
|
2725
|
-
def industry_scan_china(sw_level='F',
|
2807
|
+
def industry_scan_china(sw_level='F', \
|
2726
2808
|
start='MRY',end='default', \
|
2727
|
-
|
2728
|
-
|
2729
|
-
|
2730
|
-
|
2731
|
-
|
2732
|
-
|
2809
|
+
RF=0, \
|
2810
|
+
printout='smart', \
|
2811
|
+
facecolor='papayawhip',font_size='16px'):
|
2812
|
+
"""
|
2813
|
+
功能:扫描申万行业指数,按照投资收益率排名
|
2814
|
+
申万行业分类sw_level:F--市场表征(默认),S--投资风格(策略),B--大类风格,C--金创,
|
2815
|
+
1--一级行业,2--二级行业,3--三级行业
|
2816
|
+
评估期间start与end:允许MRM/MRQ/MRY(默认)/YTD/L3Y(近三年)/L5Y(近五年)
|
2817
|
+
RF:年化无风险收益率,默认0,可参照一年期国债收益率
|
2818
|
+
筛选方式printout:smart--收益前10名与后10名(默认),winner--仅限收益为正的行业,
|
2819
|
+
loser--仅限收益为负的行业,50--收益前50名,-10--收益后10名,all--所有行业
|
2733
2820
|
"""
|
2734
|
-
|
2821
|
+
indicator='Exp Ret%'
|
2822
|
+
|
2823
|
+
print(" Collecting industry info, it may take very long time ... ...")
|
2735
2824
|
|
2736
2825
|
# 检查申万行业
|
2737
|
-
sw_level_list=['1','2','3','F','S']
|
2826
|
+
sw_level_list=['1','2','3','F','S','B','C']
|
2738
2827
|
if sw_level not in sw_level_list:
|
2739
2828
|
print(" #Warning(industry_scan_china): invalid Shenwan industry types for",sw_level)
|
2740
2829
|
print(" Valid Shenwan industry types:",end='')
|
@@ -2751,7 +2840,11 @@ def industry_scan_china(sw_level='F',indicator='Exp Ret%', \
|
|
2751
2840
|
return None
|
2752
2841
|
|
2753
2842
|
|
2754
|
-
#
|
2843
|
+
# 检查日期:
|
2844
|
+
fromdate,todate=start_end_preprocess(start,end)
|
2845
|
+
import datetime as dt; todaydt=dt.date.today().strftime('%Y-%m-%d')
|
2846
|
+
"""
|
2847
|
+
#截至日期
|
2755
2848
|
import datetime as dt; todaydt=dt.date.today().strftime('%Y-%m-%d')
|
2756
2849
|
end=end.lower()
|
2757
2850
|
if end in ['default','today']:
|
@@ -2761,7 +2854,6 @@ def industry_scan_china(sw_level='F',indicator='Exp Ret%', \
|
|
2761
2854
|
if not validdate:
|
2762
2855
|
print(" #Warning(industry_scan_china): invalid date for",end)
|
2763
2856
|
todate=todaydt
|
2764
|
-
|
2765
2857
|
# 检查日期:开始日期
|
2766
2858
|
start=start.lower()
|
2767
2859
|
if start in ['default','mrm']: # 默认近一个月
|
@@ -2781,9 +2873,9 @@ def industry_scan_china(sw_level='F',indicator='Exp Ret%', \
|
|
2781
2873
|
if not validdate:
|
2782
2874
|
print(" #Warning(industry_scan_china): invalid date for",start,"/b, set to MRM")
|
2783
2875
|
fromdate=date_adjust(todate,adjust=-31)
|
2784
|
-
|
2876
|
+
"""
|
2785
2877
|
# 获取申万行业类别内部标识
|
2786
|
-
itype_list=['
|
2878
|
+
itype_list=['1','2','3','F','S','B','C']
|
2787
2879
|
pos=sw_level_list.index(sw_level)
|
2788
2880
|
itype=itype_list[pos]
|
2789
2881
|
|
@@ -2802,8 +2894,12 @@ def industry_scan_china(sw_level='F',indicator='Exp Ret%', \
|
|
2802
2894
|
# 计算基础数据,本步骤所需时间较长
|
2803
2895
|
idf,idfall=calc_industry_sw(df,fromdate,todate)
|
2804
2896
|
|
2805
|
-
|
2806
|
-
|
2897
|
+
RF_daily=RF/365*100 #百分数
|
2898
|
+
#RF_daily=RF/365
|
2899
|
+
RF_days=RF_daily * calculate_days(fromdate, todate)
|
2900
|
+
|
2901
|
+
idf['sharpe']=(idf['Exp Ret%']-RF_days) / idf['Exp Ret Volatility%']
|
2902
|
+
idf['sortino']=(idf['Exp Ret%']-RF_days) / idf['Exp Ret LPSD%']
|
2807
2903
|
|
2808
2904
|
# 排序
|
2809
2905
|
idf.sort_values(indicator,ascending=False,inplace=True)
|
@@ -2858,12 +2954,67 @@ def industry_scan_china(sw_level='F',indicator='Exp Ret%', \
|
|
2858
2954
|
inplace=True)
|
2859
2955
|
|
2860
2956
|
# 显示
|
2861
|
-
|
2862
|
-
|
2957
|
+
if sw_level=='F':
|
2958
|
+
sw_level_txt='申万市场表征指数'
|
2959
|
+
elif sw_level=='S':
|
2960
|
+
sw_level_txt='申万投资风格指数'
|
2961
|
+
elif sw_level=='B':
|
2962
|
+
sw_level_txt='申万大类风格指数'
|
2963
|
+
elif sw_level=='C':
|
2964
|
+
sw_level_txt='申万金创指数'
|
2965
|
+
elif sw_level=='1':
|
2966
|
+
sw_level_txt='申万一级行业'
|
2967
|
+
elif sw_level=='2':
|
2968
|
+
sw_level_txt='申万二级行业'
|
2969
|
+
elif sw_level=='3':
|
2970
|
+
sw_level_txt='申万三级行业'
|
2971
|
+
else:
|
2972
|
+
sw_level_txt='未知类别'
|
2973
|
+
|
2974
|
+
if printout=='all':
|
2975
|
+
printout_txt='所有指数'
|
2976
|
+
elif printout=='smart':
|
2977
|
+
printout_txt='收益最高最低者各十名'
|
2978
|
+
if len(df2) <=20:
|
2979
|
+
printout_txt='所有指数'
|
2980
|
+
elif printout=='winner':
|
2981
|
+
printout_txt='收益为正者'
|
2982
|
+
elif printout=='loser':
|
2983
|
+
printout_txt='收益为负者'
|
2984
|
+
else:
|
2985
|
+
try:
|
2986
|
+
num=int(printout)
|
2987
|
+
if len(df2) > abs(num):
|
2988
|
+
if num > 0:
|
2989
|
+
printout_txt='收益前'+printout+"名"
|
2990
|
+
else:
|
2991
|
+
printout_txt='收益后'+str(abs(num))+"名"
|
2992
|
+
else:
|
2993
|
+
printout_txt='所有指数'
|
2994
|
+
except:
|
2995
|
+
printout_txt='未知筛选方式'
|
2996
|
+
|
2997
|
+
#titletxt="申万行业业绩排行榜:"+sw_level_txt+',共'+str(len(df_prt))+"个指数符合条件"
|
2998
|
+
titletxt="行业业绩排行榜:"+sw_level_txt+',筛选方式:'+printout_txt
|
2999
|
+
#print("\n***",titletxt,'\n')
|
3000
|
+
"""
|
2863
3001
|
alignlist=['center']+['left']*(len(list(df_prt))-1)
|
2864
3002
|
print(df_prt.to_markdown(index=True,tablefmt='plain',colalign=alignlist))
|
3003
|
+
"""
|
3004
|
+
#print("\n *** 数据来源:综合申万宏源/东方财富/新浪财经,",todaydt,"\b;分析期间:",fromdate+'至'+todate)
|
3005
|
+
#footnote1="筛选方式:all-所有,smart-收益最高最低各10个,winner-收益为正,loser-收益为负"
|
3006
|
+
footnote2="数据来源:综合申万宏源/东方财富/新浪财经,"+str(fromdate)+'至'+str(todate)+"。"+str(todaydt)+"统计"
|
3007
|
+
#footnote=footnote1+'\n'+footnote2
|
3008
|
+
footnote=footnote2
|
3009
|
+
|
3010
|
+
#确定表格字体大小
|
3011
|
+
titile_font_size=font_size
|
3012
|
+
heading_font_size=data_font_size=str(int(font_size.replace('px',''))-1)+'px'
|
2865
3013
|
|
2866
|
-
|
3014
|
+
df_display_CSS(df_prt,titletxt=titletxt,footnote=footnote,facecolor=facecolor, \
|
3015
|
+
first_col_align='left',second_col_align='left', \
|
3016
|
+
titile_font_size=titile_font_size,heading_font_size=heading_font_size, \
|
3017
|
+
data_font_size=data_font_size)
|
2867
3018
|
|
2868
3019
|
return df2
|
2869
3020
|
|