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/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','I','T','S']
675
+ symboltypes=["市场表征", "一级行业", "二级行业", "风格指数","大类风格指数","金创指数"]
676
+ indextypecodes=['F','1','2','S','B','C']
677
677
  industry=pd.DataFrame()
678
678
  for s in symboltypes:
679
- dft = ak.index_realtime_sw(symbol=s)
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=['I','T','3','F','S']
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='I'
759
+ itype='1'
758
760
  numberPerLine=5
759
761
  colalign='left'
760
762
 
761
- print_industry_sw(itype='I',numberPerLine=5,colalign='right')
763
+ print_industry_sw(itype='1',numberPerLine=5,colalign='right')
762
764
 
763
- def print_industry_sw(itype='I',numberPerLine=5,colalign='left'):
765
+ def print_industry_sw(itype='1',numberPerLine=5,colalign='left'):
764
766
  """
765
767
  功能:按照类别打印申万行业列表,名称(代码)
766
- 行业分级itype:F="市场表征", I="一级行业", T="二级行业", 3="三级行业", S="风格指数"
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','I','T','3','S']
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=='T': numberPerLine=4
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='I'
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='I',period="day", \
952
+ itype='1',period="day", \
951
953
  graph=True,axisamp=0.8):
952
954
  """
953
955
  完整版,全流程
954
956
  功能:模板,遍历某类申万指数,计算某项业绩指标,汇集排序
955
- itype: F表征指数,I行业指数,S风格指数
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
- dft = ak.index_hist_sw(symbol=i,period="day")
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='I'
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='I',period="day",industry_list='all'):
1160
+ def get_industry_sw(itype='1',period="day",industry_list='all'):
1146
1161
  """
1147
1162
  功能:遍历某类申万指数,下载数据
1148
- itype: F表征指数,I行业指数,S风格指数
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','I','T','3','S','A']
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, I-Industry, S-Styled, A-All (more time))")
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(" *** Searching industry information, please wait ...")
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
- print(" Successfully retrieved",len(df),"records in",len(ilist),"industries")
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
- print(" Successfully retrieved",len(df),"records in",len(ilist),"industries")
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(" *** Calculating industry performance, please wait ...")
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
- printout=False):
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='I'
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='I',period="day",graph=True,printout=False,sortby='tpw_mean'):
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='*** '+title_txt+':'+y_label+','+sortby_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='I'
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=['I','T','3','F','S']
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='T'
2161
+ itype='F'
2116
2162
 
2117
- idf,idfall=get_industry_info_sw(start,end,itype='I')
2163
+ idf,idfall=get_industry_info_sw(start,end,itype='1')
2118
2164
 
2119
- def get_industry_info_sw(start,end,itype='I'):
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('I')
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; today=datetime.date.today()
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=['I','T','3','F','S']
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
- dft = ak.index_hist_sw(symbol=symbol,period="day")
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',indicator='Exp Ret%', \
2807
+ def industry_scan_china(sw_level='F', \
2726
2808
  start='MRY',end='default', \
2727
- printout='smart'):
2728
- """
2729
- 功能:扫描申万行业指数,默认一级行业分类
2730
- 时间区间:start与end,允许MRM/MRQ/MRY/YTD/LTY(近三年)/LFY(近五年)
2731
- 显示:smart--指数增长前五名与后五名,'winner'--仅限增长的行业,'loser'--仅限下降的行业,
2732
- '50'--前50名,'-10'--后10名,'all'--所有行业
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
- print(" Scanning Shenwan industry performance, which may take up to several hours ...")
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=['I','T','3','F','S']
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
- idf['sharpe']=idf['Exp Ret%'] / idf['Exp Ret Volatility%']
2806
- idf['sortino']=idf['Exp Ret%'] / idf['Exp Ret LPSD%']
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
- titletxt="申万行业业绩指标排行榜:"+"层级/类别"+sw_level+',共'+str(len(idf))+"个指数"
2862
- print("\n***",titletxt,'\n')
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
- print("\n *** 数据来源:综合申万宏源/东方财富/新浪财经,",todaydt,"\b;分析期间:",fromdate+'至'+todate)
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