siat 3.4.37__py3-none-any.whl → 3.5.1__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 +111 -0
- siat/grafix.py +15 -2
- siat/risk_adjusted_return2.py +50 -40
- siat/sector_china.py +351 -114
- siat/security_price2.py +1 -0
- siat/security_prices.py +44 -11
- siat/security_trend2.py +16 -7
- siat/stock.py +68 -32
- siat/stock_technical.py +6 -6
- siat/translate.py +411 -161
- siat/translate_241003_keep.py +4300 -0
- {siat-3.4.37.dist-info → siat-3.5.1.dist-info}/METADATA +1 -1
- {siat-3.4.37.dist-info → siat-3.5.1.dist-info}/RECORD +16 -15
- {siat-3.4.37.dist-info → siat-3.5.1.dist-info}/WHEEL +1 -1
- {siat-3.4.37.dist-info → siat-3.5.1.dist-info}/LICENSE +0 -0
- {siat-3.4.37.dist-info → siat-3.5.1.dist-info}/top_level.txt +0 -0
siat/sector_china.py
CHANGED
@@ -731,7 +731,7 @@ def sector_position_china(ticker,sector="new_dlhy"):
|
|
731
731
|
|
732
732
|
#==============================================================================
|
733
733
|
|
734
|
-
def invest_concept_china(num=10):
|
734
|
+
def invest_concept_china(num=10,max_sleep=30):
|
735
735
|
"""
|
736
736
|
废弃!
|
737
737
|
功能:汇总投资概念股票名单,排行
|
@@ -755,7 +755,7 @@ def invest_concept_china(num=10):
|
|
755
755
|
|
756
756
|
import pandas as pd
|
757
757
|
totaldf=pd.DataFrame()
|
758
|
-
import time
|
758
|
+
import time; import random
|
759
759
|
i=0
|
760
760
|
#新浪财经有反爬虫,这个循环做不下去
|
761
761
|
for c in clist:
|
@@ -769,7 +769,10 @@ def invest_concept_china(num=10):
|
|
769
769
|
print(', failed:-(')
|
770
770
|
#continue
|
771
771
|
#等待一会儿,避免被禁访问
|
772
|
-
time.sleep(
|
772
|
+
#time.sleep(max_sleep)
|
773
|
+
random_int=random.randint(1,max_sleep)
|
774
|
+
time.sleep(random_int)
|
775
|
+
|
773
776
|
i=i+1
|
774
777
|
if i % 20 == 0:
|
775
778
|
print(int(i/cnum*100),'\b%',end=' ')
|
@@ -804,7 +807,7 @@ def invest_concept_china(num=10):
|
|
804
807
|
#==============================================================================
|
805
808
|
def industry_sw_list_all():
|
806
809
|
"""
|
807
|
-
功能:输出申万指数所有代码df
|
810
|
+
功能:输出申万指数所有代码df。动态,每次重新获取,自动更新!
|
808
811
|
输入:
|
809
812
|
输出:df,包括市场表征指数F,一级行业指数I,二级行业T,风格指数S,三级行业3
|
810
813
|
"""
|
@@ -816,6 +819,7 @@ def industry_sw_list_all():
|
|
816
819
|
industry=pd.DataFrame()
|
817
820
|
for s in symboltypes:
|
818
821
|
try:
|
822
|
+
#目前有问题!
|
819
823
|
dft = ak.index_realtime_sw(symbol=s)
|
820
824
|
except: continue
|
821
825
|
|
@@ -944,38 +948,62 @@ if __name__=='__main__':
|
|
944
948
|
iname='食品饮料'
|
945
949
|
iname='银行'
|
946
950
|
iname='汽车'
|
951
|
+
iname='高价股指数'
|
952
|
+
iname='申万A指'
|
953
|
+
iname='大类风格-医药医疗'
|
954
|
+
|
947
955
|
numberPerLine=5
|
948
956
|
colalign='right'
|
949
957
|
|
950
958
|
print_industry_component_sw(iname,numberPerLine=5,colalign='right')
|
951
959
|
|
952
|
-
def print_industry_component_sw(iname,numberPerLine=5,colalign='left',
|
960
|
+
def print_industry_component_sw(iname,numberPerLine=5,colalign='left', \
|
961
|
+
printout=True,return_result=False):
|
953
962
|
"""
|
954
963
|
打印申万行业的成分股,名称(代码)
|
955
964
|
"""
|
956
965
|
try:
|
957
966
|
icode=industry_sw_code(iname)
|
958
967
|
except:
|
959
|
-
print(" #Warning(print_industry_component_sw):
|
960
|
-
|
968
|
+
print(" #Warning(print_industry_component_sw): failed to find index name for",iname)
|
969
|
+
if return_result:
|
970
|
+
return []
|
971
|
+
else:
|
972
|
+
return
|
973
|
+
|
974
|
+
if icode=='':
|
975
|
+
print(" #Warning(print_industry_component_sw): relevent index code not found for",iname)
|
976
|
+
if return_result:
|
977
|
+
return []
|
978
|
+
else:
|
979
|
+
return
|
980
|
+
|
981
|
+
clist,cdf=industry_stock_sw(icode,top=1000)
|
982
|
+
if clist is None:
|
983
|
+
if return_result:
|
984
|
+
print(" #Warning(print_industry_component_sw): no component stock found for",iname)
|
985
|
+
return []
|
986
|
+
else:
|
987
|
+
return
|
961
988
|
|
962
|
-
clist,cdf=industry_stock_sw(icode,top=1000)
|
963
|
-
|
964
989
|
#cdf['icode']=cdf['证券代码'].apply(lambda x: x+'.SS' if x[:1] in ['6'] else (x+'.SZ' if x[:1] in ['0','3'] else x+'.BJ' ))
|
965
990
|
cdf['icode']=cdf['证券代码']
|
966
991
|
|
967
992
|
# 删除'证券名称'为None的行
|
968
993
|
cdf=cdf.mask(cdf.eq('None')).dropna()
|
969
|
-
cdf['name_code']=cdf.apply(lambda x: x['证券名称']+'('+x['icode']+')',axis=1)
|
970
994
|
|
971
|
-
|
972
|
-
|
995
|
+
# 合成证券名称与代码
|
996
|
+
cdf['name_code']=cdf.apply(lambda x: x['证券名称']+'('+x['icode']+')',axis=1)
|
973
997
|
ilist=list(cdf['name_code'])
|
974
998
|
|
975
|
-
|
976
|
-
|
977
|
-
|
978
|
-
|
999
|
+
if printout:
|
1000
|
+
#标题
|
1001
|
+
import datetime as dt; stoday=dt.date.today()
|
1002
|
+
|
1003
|
+
titletxt=iname+"("+icode+")行业/板块成分股:计"+str(len(ilist))+'只,按行业指数权重降序排列,'+str(stoday)
|
1004
|
+
print("\n"+titletxt,end='')
|
1005
|
+
#表格
|
1006
|
+
printInLine_md(ilist,numberPerLine=numberPerLine,colalign=colalign)
|
979
1007
|
|
980
1008
|
if return_result:
|
981
1009
|
return ilist
|
@@ -1025,6 +1053,8 @@ def print_industry_component_sw2(icode,numberPerLine=5,colalign='left'):
|
|
1025
1053
|
|
1026
1054
|
#==============================================================================
|
1027
1055
|
if __name__=='__main__':
|
1056
|
+
iname='大类风格--医药医疗'
|
1057
|
+
|
1028
1058
|
industry_sw_code('光伏设备')
|
1029
1059
|
|
1030
1060
|
def industry_sw_code(iname):
|
@@ -1108,7 +1138,10 @@ def industry_ranking_sw(start,end,measure='Exp Ret%', \
|
|
1108
1138
|
"""
|
1109
1139
|
完整版,全流程
|
1110
1140
|
功能:模板,遍历某类申万指数,计算某项业绩指标,汇集排序
|
1111
|
-
itype:
|
1141
|
+
itype:
|
1142
|
+
股票类指数:F表征指数,n=1/2/3行业指数,S风格指数,B大类风格指数,C金创指数?
|
1143
|
+
基金类指数:J1/2/3基础一二三级,JF特色指数
|
1144
|
+
|
1112
1145
|
period="day"; choice of {"day", "week", "month"}
|
1113
1146
|
绘图:柱状图,可选
|
1114
1147
|
"""
|
@@ -1133,13 +1166,22 @@ def industry_ranking_sw(start,end,measure='Exp Ret%', \
|
|
1133
1166
|
fail_list=[]
|
1134
1167
|
for i in ilist:
|
1135
1168
|
|
1136
|
-
print(" Processing
|
1169
|
+
print(" Processing index",i,"\b, please wait ...")
|
1137
1170
|
#抓取指数价格,选取期间范围
|
1138
1171
|
try:
|
1139
1172
|
dft = ak.index_hist_sw(symbol=i,period="day")
|
1140
1173
|
except:
|
1141
|
-
|
1142
|
-
|
1174
|
+
try:
|
1175
|
+
dft = ak.index_hist_fund_sw(symbol=i,period="day")
|
1176
|
+
dft['代码']=i
|
1177
|
+
dft['收盘']=dft['收盘指数']
|
1178
|
+
dft['开盘']=dft['收盘指数']
|
1179
|
+
dft['最高']=dft['收盘指数']
|
1180
|
+
dft['最低']=dft['收盘指数']
|
1181
|
+
dft['成交量']=0; dft['成交额']=0
|
1182
|
+
except:
|
1183
|
+
fail_list=fail_list+[i]
|
1184
|
+
continue
|
1143
1185
|
|
1144
1186
|
dft['ticker']=dft['代码']
|
1145
1187
|
dft['date']=dft['日期'].apply(lambda x: pd.to_datetime(x))
|
@@ -1179,10 +1221,10 @@ def industry_ranking_sw(start,end,measure='Exp Ret%', \
|
|
1179
1221
|
df['name']=df['ticker'].apply(lambda x: industry_sw_name(x))
|
1180
1222
|
df.set_index('name',inplace=True)
|
1181
1223
|
colname='value'
|
1182
|
-
titletxt="
|
1224
|
+
titletxt="行业/指数分析:业绩排名"
|
1183
1225
|
import datetime; today=datetime.date.today()
|
1184
1226
|
footnote0=ectranslate(measure)+' ==>\n'
|
1185
|
-
footnote1='
|
1227
|
+
footnote1='申万行业/指数分类,观察期:'+start+'至'+iend+'\n'
|
1186
1228
|
footnote2="数据来源: 申万宏源, "+str(today)
|
1187
1229
|
footnote=footnote0+footnote1+footnote2
|
1188
1230
|
|
@@ -1190,11 +1232,12 @@ def industry_ranking_sw(start,end,measure='Exp Ret%', \
|
|
1190
1232
|
#plot_barh2(df,colname,titletxt,footnote)
|
1191
1233
|
|
1192
1234
|
if len(fail_list) > 0:
|
1193
|
-
print(" Unable to retrieve",len(fail_list),"industry(ies) as follows:")
|
1235
|
+
print(" Unable to retrieve",len(fail_list),"industry(ies) as follows:",end='')
|
1194
1236
|
if len(fail_list) >= 10:
|
1195
1237
|
printInLine_md(fail_list,numberPerLine=10,colalign='left',font_size='16px')
|
1196
1238
|
else:
|
1197
1239
|
printInLine_md(fail_list,numberPerLine=len(fail_list),colalign='left',font_size='16px')
|
1240
|
+
print('') #空一行
|
1198
1241
|
|
1199
1242
|
return df
|
1200
1243
|
|
@@ -1247,8 +1290,17 @@ def industry_ranking_sw2(industrylist,start,end,measure='Exp Ret%', \
|
|
1247
1290
|
try:
|
1248
1291
|
dft = ak.index_hist_sw(symbol=i,period="day")
|
1249
1292
|
except:
|
1250
|
-
|
1251
|
-
|
1293
|
+
try:
|
1294
|
+
dft = ak.index_hist_fund_sw(symbol=i,period="day")
|
1295
|
+
dft['代码']=i
|
1296
|
+
dft['收盘']=dft['收盘指数']
|
1297
|
+
dft['开盘']=dft['收盘指数']
|
1298
|
+
dft['最高']=dft['收盘指数']
|
1299
|
+
dft['最低']=dft['收盘指数']
|
1300
|
+
dft['成交量']=0; dft['成交额']=0
|
1301
|
+
except:
|
1302
|
+
print(" #Warning(industry_ranking_sw2): index not found for",i)
|
1303
|
+
continue
|
1252
1304
|
|
1253
1305
|
dft['ticker']=dft['代码']
|
1254
1306
|
dft['date']=dft['日期'].apply(lambda x: pd.to_datetime(x))
|
@@ -1291,10 +1343,10 @@ def industry_ranking_sw2(industrylist,start,end,measure='Exp Ret%', \
|
|
1291
1343
|
df.dropna(inplace=True)
|
1292
1344
|
|
1293
1345
|
colname='value'
|
1294
|
-
titletxt="
|
1346
|
+
titletxt="行业/指数分析:业绩排名"
|
1295
1347
|
import datetime; today=datetime.date.today()
|
1296
1348
|
footnote0=ectranslate(measure)+' ==>\n'
|
1297
|
-
footnote1='
|
1349
|
+
footnote1='申万行业/指数分类,观察期:'+start+'至'+iend+'\n'
|
1298
1350
|
footnote2="数据来源: 申万宏源, "+str(today)
|
1299
1351
|
footnote=footnote0+footnote1+footnote2
|
1300
1352
|
|
@@ -1311,10 +1363,13 @@ if __name__=='__main__':
|
|
1311
1363
|
period="day"
|
1312
1364
|
industry_list='all'
|
1313
1365
|
|
1314
|
-
def get_industry_sw(itype='1',period="day",industry_list='all',max_sleep=
|
1366
|
+
def get_industry_sw(itype='1',period="day",industry_list='all',max_sleep=30):
|
1315
1367
|
"""
|
1316
1368
|
功能:遍历某类申万指数,下载数据
|
1317
|
-
itype:
|
1369
|
+
itype:
|
1370
|
+
股票类指数:F表征指数,n=1/2/3行业指数,S风格指数,B大类风格指数,C金创指数?
|
1371
|
+
基金类指数:J1/2/3基础一二三级,JF特色指数
|
1372
|
+
|
1318
1373
|
period="day"; choice of {"day", "week", "month"}
|
1319
1374
|
industry_list: 允许选择部分行业
|
1320
1375
|
"""
|
@@ -1345,7 +1400,7 @@ def get_industry_sw(itype='1',period="day",industry_list='all',max_sleep=15):
|
|
1345
1400
|
import datetime; import random; import time
|
1346
1401
|
df=pd.DataFrame()
|
1347
1402
|
|
1348
|
-
print("
|
1403
|
+
print(" Searching industry data, it takes time, please wait ...")
|
1349
1404
|
num=len(ilist)
|
1350
1405
|
if num <= 10:
|
1351
1406
|
steps=5
|
@@ -1362,9 +1417,18 @@ def get_industry_sw(itype='1',period="day",industry_list='all',max_sleep=15):
|
|
1362
1417
|
try:
|
1363
1418
|
dft = ak.index_hist_sw(symbol=i,period="day")
|
1364
1419
|
except:
|
1365
|
-
|
1366
|
-
|
1367
|
-
|
1420
|
+
try:
|
1421
|
+
dft = ak.index_hist_fund_sw(symbol=i,period="day")
|
1422
|
+
dft['代码']=i
|
1423
|
+
dft['收盘']=dft['收盘指数']
|
1424
|
+
dft['开盘']=dft['收盘指数']
|
1425
|
+
dft['最高']=dft['收盘指数']
|
1426
|
+
dft['最低']=dft['收盘指数']
|
1427
|
+
dft['成交量']=0; dft['成交额']=0
|
1428
|
+
except:
|
1429
|
+
#print(" #Warning(get_industry_sw): unsupported industry",i)
|
1430
|
+
fail_list=fail_list+[i]
|
1431
|
+
continue
|
1368
1432
|
|
1369
1433
|
dft['ticker']=dft['代码']
|
1370
1434
|
dft['date']=dft['日期'].apply(lambda x: pd.to_datetime(x))
|
@@ -1393,11 +1457,8 @@ def get_industry_sw(itype='1',period="day",industry_list='all',max_sleep=15):
|
|
1393
1457
|
time.sleep(random_int)
|
1394
1458
|
|
1395
1459
|
#num=list(set(list(df['ticker'])))
|
1396
|
-
if len(
|
1397
|
-
print(" Successfully retrieved",len(df),"records in",len(ilist),"industries")
|
1398
|
-
else:
|
1399
|
-
print("\n Successfully retrieved",len(df),"records in",len(ilist),"industries")
|
1400
|
-
#print(" Successfully retrieved",len(df),"records in",num,"industries")
|
1460
|
+
if len(df)>0:
|
1461
|
+
print(" Successfully retrieved",len(df),"records in",len(ilist)-len(fail_list),"industries")
|
1401
1462
|
|
1402
1463
|
if len(fail_list) > 0:
|
1403
1464
|
print(" Failed to retrieve",len(fail_list),"industry(ies) as follows:")
|
@@ -1421,7 +1482,7 @@ if __name__=='__main__':
|
|
1421
1482
|
industry_list=['850831.SW','801785.SW','801737.SW','801194.SW',
|
1422
1483
|
'801784.SW','801783.SW','801782.SW']
|
1423
1484
|
|
1424
|
-
def get_industry_sw2(industry_list,period="day",max_sleep=
|
1485
|
+
def get_industry_sw2(industry_list,period="day",max_sleep=30):
|
1425
1486
|
"""
|
1426
1487
|
功能:遍历指定的申万指数列表,下载数据
|
1427
1488
|
period="day"; choice of {"day", "week", "month"}
|
@@ -1454,9 +1515,18 @@ def get_industry_sw2(industry_list,period="day",max_sleep=15):
|
|
1454
1515
|
try:
|
1455
1516
|
dft = ak.index_hist_sw(symbol=i,period="day")
|
1456
1517
|
except:
|
1457
|
-
|
1458
|
-
|
1459
|
-
|
1518
|
+
try:
|
1519
|
+
dft = ak.index_hist_fund_sw(symbol=i,period="day")
|
1520
|
+
dft['代码']=i
|
1521
|
+
dft['收盘']=dft['收盘指数']
|
1522
|
+
dft['开盘']=dft['收盘指数']
|
1523
|
+
dft['最高']=dft['收盘指数']
|
1524
|
+
dft['最低']=dft['收盘指数']
|
1525
|
+
dft['成交量']=0; dft['成交额']=0
|
1526
|
+
except:
|
1527
|
+
#print(" #Warning(get_industry_sw): unsupported industry",i)
|
1528
|
+
fail_list=fail_list+[i]
|
1529
|
+
continue
|
1460
1530
|
|
1461
1531
|
dft['ticker']=dft['代码']
|
1462
1532
|
dft['date']=dft['日期'].apply(lambda x: pd.to_datetime(x))
|
@@ -1484,11 +1554,9 @@ def get_industry_sw2(industry_list,period="day",max_sleep=15):
|
|
1484
1554
|
time.sleep(random_int)
|
1485
1555
|
|
1486
1556
|
#num=list(set(list(df['ticker'])))
|
1487
|
-
if len(
|
1488
|
-
print("\n Successfully retrieved",len(df),"records in",len(ilist),"industries")
|
1489
|
-
|
1490
|
-
print(" Successfully retrieved",len(df),"records in",len(ilist),"industries")
|
1491
|
-
#print(" Successfully retrieved",len(df),"records in",num,"industries")
|
1557
|
+
if len(df) > 0:
|
1558
|
+
print("\n Successfully retrieved",len(df),"records in",len(ilist)-len(fail_list),"industries")
|
1559
|
+
|
1492
1560
|
if len(fail_list) > 0:
|
1493
1561
|
print(" Failed to retrieve",len(fail_list),"industry(ies) as follows:")
|
1494
1562
|
if len(fail_list) >= 10:
|
@@ -1501,8 +1569,8 @@ def get_industry_sw2(industry_list,period="day",max_sleep=15):
|
|
1501
1569
|
|
1502
1570
|
#==============================================================================
|
1503
1571
|
if __name__=='__main__':
|
1504
|
-
start='
|
1505
|
-
end='
|
1572
|
+
start='2023-8-31'
|
1573
|
+
end='2024-9-30'
|
1506
1574
|
df=get_industry_sw('F')
|
1507
1575
|
|
1508
1576
|
def calc_industry_sw(df,start,end):
|
@@ -1514,7 +1582,7 @@ def calc_industry_sw(df,start,end):
|
|
1514
1582
|
#检查日期的合理性
|
1515
1583
|
result,start1,end1=check_period(start,end)
|
1516
1584
|
if not result:
|
1517
|
-
print(" #
|
1585
|
+
print(" #Warning(calc_industry_sw): invalid date period",start,end)
|
1518
1586
|
return None
|
1519
1587
|
|
1520
1588
|
#屏蔽函数内print信息输出的类
|
@@ -1672,10 +1740,10 @@ def rank_industry_sw(idf,measure='Exp Ret%',industries=[], \
|
|
1672
1740
|
gdf1=gdf
|
1673
1741
|
|
1674
1742
|
if printout or graph:
|
1675
|
-
titletxt="
|
1743
|
+
titletxt="行业板块/指数分析:最新业绩排名"
|
1676
1744
|
import datetime; today=datetime.date.today()
|
1677
1745
|
footnote0=ectranslate(measure)+' -->\n\n'
|
1678
|
-
footnote1='
|
1746
|
+
footnote1='申万行业/指数分类,'+iend+'快照'
|
1679
1747
|
footnote2='观察期:'+istart+'至'+iend+','
|
1680
1748
|
footnote3="数据来源: 申万宏源, "+str(today)+'统计'
|
1681
1749
|
footnote=footnote0+footnote1+'\n'+footnote2+footnote3
|
@@ -1684,7 +1752,7 @@ def rank_industry_sw(idf,measure='Exp Ret%',industries=[], \
|
|
1684
1752
|
gdf2=gdf1.sort_values(by=measure,ascending=False)
|
1685
1753
|
gdf2.reset_index(inplace=True)
|
1686
1754
|
gdf2.index=gdf2.index+1
|
1687
|
-
gdf2.columns=['
|
1755
|
+
gdf2.columns=['行业/指数名称','行业/指数代码',ectranslate(measure),'开始日期','结束日期']
|
1688
1756
|
"""
|
1689
1757
|
print("***",titletxt,'\n')
|
1690
1758
|
alignlist=['center']+['left']*(len(list(gdf2))-1)
|
@@ -1705,7 +1773,7 @@ def rank_industry_sw(idf,measure='Exp Ret%',industries=[], \
|
|
1705
1773
|
footnote=footnote0+footnote1+'\n'+footnote2+footnote3
|
1706
1774
|
plot_barh(gdf1,colname,titletxt,footnote,axisamp=axisamp)
|
1707
1775
|
else: #使用plotly_express
|
1708
|
-
titletxt="
|
1776
|
+
titletxt="行业板块/指数业绩排名:"+ectranslate(measure)
|
1709
1777
|
footnote=footnote1+'。'+footnote2+footnote3
|
1710
1778
|
plot_barh2(gdf1,colname,titletxt,footnote)
|
1711
1779
|
else:
|
@@ -1772,6 +1840,11 @@ def compare_mindustry_sw(industry_list,measure,start,end, \
|
|
1772
1840
|
|
1773
1841
|
#获取数据
|
1774
1842
|
ddf=get_industry_sw(itype=itype,period=period,industry_list=industry_list)
|
1843
|
+
found=df_have_data(ddf)
|
1844
|
+
if not found=='Found':
|
1845
|
+
print(" #Warning(compare_mindustry_sw): data tentatively unavailable for group",itype)
|
1846
|
+
print(" Data is sometimes unavialble at certain tie points, eg public holidays")
|
1847
|
+
return None
|
1775
1848
|
|
1776
1849
|
#计算指标
|
1777
1850
|
_,idf=calc_industry_sw(ddf,start,end)
|
@@ -1815,13 +1888,13 @@ def compare_mindustry_sw(industry_list,measure,start,end, \
|
|
1815
1888
|
dfs1=dfs[(dfs.index >= istartpd) & (dfs.index <= iendpd)]
|
1816
1889
|
|
1817
1890
|
y_label=measure
|
1818
|
-
title_txt="
|
1891
|
+
title_txt="行业板块/指数分析:市场业绩趋势与评价"
|
1819
1892
|
import datetime; today = datetime.date.today()
|
1820
1893
|
if graph:
|
1821
1894
|
colname=measure
|
1822
1895
|
|
1823
1896
|
import datetime; today=datetime.date.today()
|
1824
|
-
footnote1='\n
|
1897
|
+
footnote1='\n申万行业/指数分类,观察期:'+istart+'至'+iend+'\n'
|
1825
1898
|
footnote2="数据来源: 申万宏源, "+str(today)+'统计'
|
1826
1899
|
footnote=footnote1+footnote2
|
1827
1900
|
|
@@ -1905,6 +1978,11 @@ def compare_mindustry_sw2(industry_list,measure,start,end, \
|
|
1905
1978
|
|
1906
1979
|
#获取数据
|
1907
1980
|
ddf=get_industry_sw2(industry_list=industry_list,period=period)
|
1981
|
+
found=df_have_data(ddf)
|
1982
|
+
if not found=='Found':
|
1983
|
+
print(" #Warning(compare_mindustry_sw): data tentatively unavailable for",industry_list)
|
1984
|
+
print(" Data is sometimes unavialble at certain tie points, eg public holidays")
|
1985
|
+
return None
|
1908
1986
|
|
1909
1987
|
#计算指标
|
1910
1988
|
_,idf=calc_industry_sw(ddf,start,end)
|
@@ -1948,13 +2026,13 @@ def compare_mindustry_sw2(industry_list,measure,start,end, \
|
|
1948
2026
|
dfs1=dfs[(dfs.index >= istartpd) & (dfs.index <= iendpd)]
|
1949
2027
|
|
1950
2028
|
y_label=measure
|
1951
|
-
title_txt="行业(板块)
|
2029
|
+
title_txt="行业(板块)/指数分析:市场业绩趋势与评价"
|
1952
2030
|
import datetime; today = datetime.date.today()
|
1953
2031
|
if graph:
|
1954
2032
|
colname=measure
|
1955
|
-
title_txt="行业(板块)
|
2033
|
+
title_txt="行业(板块)/指数分析:市场业绩趋势"
|
1956
2034
|
import datetime; today=datetime.date.today()
|
1957
|
-
footnote1='\n
|
2035
|
+
footnote1='\n申万行业/指数分类,观察期:'+istart+'至'+iend+'\n'
|
1958
2036
|
footnote2="数据来源: 申万宏源, "+str(today)+'统计'
|
1959
2037
|
footnote=footnote1+footnote2
|
1960
2038
|
|
@@ -2088,10 +2166,10 @@ def compare_industry_sw(idfall,industry_list,measure,graph=True):
|
|
2088
2166
|
if graph:
|
2089
2167
|
y_label=measure
|
2090
2168
|
colname=measure
|
2091
|
-
title_txt="
|
2169
|
+
title_txt="行业板块/指数分析:市场业绩趋势"
|
2092
2170
|
|
2093
2171
|
import datetime; today=datetime.date.today()
|
2094
|
-
footnote1='\n
|
2172
|
+
footnote1='\n申万行业/指数分类,观察期:'+istart+'至'+iend+'\n'
|
2095
2173
|
footnote2="数据来源: 申万宏源, "+str(today)+'统计'
|
2096
2174
|
footnote=footnote1+footnote2
|
2097
2175
|
|
@@ -2147,11 +2225,11 @@ def compare_industry_sw_sharpe(idfall,industries,base_return='Annual Ret%',graph
|
|
2147
2225
|
sdf=atmp[industrylist]
|
2148
2226
|
if graph:
|
2149
2227
|
y_label='夏普比率(基于'+ectranslate(base_return)+')'
|
2150
|
-
title_txt="
|
2228
|
+
title_txt="行业板块/指数分析:市场发展趋势"
|
2151
2229
|
|
2152
2230
|
istart=sdf.index[0].strftime('%Y-%m-%d')
|
2153
2231
|
iend=sdf.index[-1].strftime('%Y-%m-%d')
|
2154
|
-
footnote1='\n
|
2232
|
+
footnote1='\n申万行业/指数分类,观察期:'+istart+'至'+iend+'\n'
|
2155
2233
|
import datetime; today=datetime.date.today()
|
2156
2234
|
#footnote2="数据来源: 申万宏源, "+str(today)+'统计(未计入无风险利率)'
|
2157
2235
|
footnote2="数据来源: 申万宏源, "+str(today)+'统计'
|
@@ -2211,10 +2289,10 @@ def rank_industry_sw_sharpe(idfall,base_return='Exp Ret%',graph=True,axisamp=0.8
|
|
2211
2289
|
|
2212
2290
|
if graph:
|
2213
2291
|
colname=col
|
2214
|
-
titletxt="
|
2292
|
+
titletxt="行业板块/指数分析:最新业绩排名"
|
2215
2293
|
import datetime; today=datetime.date.today()
|
2216
2294
|
footnote0='夏普比率(基于'+ectranslate(base_return)+') -->\n\n'
|
2217
|
-
footnote1='
|
2295
|
+
footnote1='申万行业/指数分类,'+iend+'快照'
|
2218
2296
|
footnote2='观察期:'+istart+'至'+iend+','
|
2219
2297
|
footnote3="数据来源: 申万宏源, "+str(today)+'统计'
|
2220
2298
|
footnote=footnote0+footnote1+'\n'+footnote2+footnote3
|
@@ -2222,7 +2300,7 @@ def rank_industry_sw_sharpe(idfall,base_return='Exp Ret%',graph=True,axisamp=0.8
|
|
2222
2300
|
footnote=footnote0+footnote1+'\n'+footnote2+footnote3
|
2223
2301
|
plot_barh(dftail3,colname,titletxt,footnote,axisamp=axisamp)
|
2224
2302
|
else: #使用plotly_express
|
2225
|
-
titletxt="
|
2303
|
+
titletxt="行业板块/指数业绩排名:夏普比率(基于"+ectranslate(base_return)+')'
|
2226
2304
|
footnote=footnote1+'。'+footnote2+footnote3
|
2227
2305
|
plot_barh2(dftail3,colname,titletxt,footnote)
|
2228
2306
|
|
@@ -2235,6 +2313,8 @@ if __name__=='__main__':
|
|
2235
2313
|
industry='801193.SW'
|
2236
2314
|
industry='851811.SW'
|
2237
2315
|
industry='801181.SW'
|
2316
|
+
industry='801841.SW'
|
2317
|
+
|
2238
2318
|
top=5
|
2239
2319
|
df=industry_stock_sw(industry)
|
2240
2320
|
|
@@ -2257,10 +2337,14 @@ def industry_stock_sw(industry='801270.SW',top=5,printout=False):
|
|
2257
2337
|
try:
|
2258
2338
|
cdf = ak.index_component_sw(industry)
|
2259
2339
|
except:
|
2260
|
-
print(" #Warning(industry_stock_sw): failed to retrieve component
|
2261
|
-
print("
|
2340
|
+
print(" #Warning(industry_stock_sw): failed to retrieve component for index",industry)
|
2341
|
+
print(" Try solution: upgrade akshare, restart jupyter and try again")
|
2262
2342
|
return None,None
|
2263
2343
|
|
2344
|
+
#去重,保留最新日期的记录
|
2345
|
+
cdf.sort_values(by=['证券代码','计入日期'],ascending=[True,False],inplace=True)
|
2346
|
+
cdf.drop_duplicates(subset=['证券代码'],keep='first',inplace=True)
|
2347
|
+
|
2264
2348
|
# 删除'证券名称'为None的行
|
2265
2349
|
cdf=cdf.mask(cdf.eq('None')).dropna()
|
2266
2350
|
cdf_total=len(cdf)
|
@@ -2290,9 +2374,9 @@ def industry_stock_sw(industry='801270.SW',top=5,printout=False):
|
|
2290
2374
|
if printout:
|
2291
2375
|
if '.SW' not in industry:
|
2292
2376
|
industry=industry+'.SW'
|
2293
|
-
titletxt="
|
2377
|
+
titletxt="申万指数成分证券:"+industry_sw_name(industry)+'('+industry+')'
|
2294
2378
|
import datetime as dt; todaydt=str(dt.date.today())
|
2295
|
-
footnote="
|
2379
|
+
footnote="成分证券数量:"+str(cdf_total)+",申万宏源,"+str(todaydt)
|
2296
2380
|
|
2297
2381
|
#df_directprint(cdf1,title_txt,footnote)
|
2298
2382
|
df_display_CSS(cdf1,titletxt=titletxt,footnote=footnote,facecolor='papayawhip',decimals=3, \
|
@@ -2355,6 +2439,11 @@ def get_industry_info_sw(start,end,itype='1'):
|
|
2355
2439
|
print("\n*** Step 1:")
|
2356
2440
|
# 获取行业历史数据,本步骤所需时间较长
|
2357
2441
|
df=get_industry_sw(itype=itype)
|
2442
|
+
found=df_have_data(df)
|
2443
|
+
if not found=='Found':
|
2444
|
+
print(" #Warning(compare_mindustry_sw): data tentatively unavailable for group",itype)
|
2445
|
+
print(" Data is sometimes unavialble at certain time points, try again later")
|
2446
|
+
return None
|
2358
2447
|
|
2359
2448
|
print("\n*** Step 2:")
|
2360
2449
|
# 计算基础数据,本步骤所需时间较长
|
@@ -2389,6 +2478,11 @@ def get_industry_info_sw2(industry_list,start,end):
|
|
2389
2478
|
print("\n*** Step 1:")
|
2390
2479
|
# 获取行业历史数据,本步骤所需时间较长
|
2391
2480
|
df=get_industry_sw2(industry_list)
|
2481
|
+
found=df_have_data(df)
|
2482
|
+
if not found=='Found':
|
2483
|
+
print(" #Warning(compare_mindustry_sw): data tentatively unavailable for",industry_list)
|
2484
|
+
print(" Data is sometimes unavialble at certain time points, try again later")
|
2485
|
+
return None
|
2392
2486
|
|
2393
2487
|
print("\n*** Step 2:")
|
2394
2488
|
# 计算基础数据,本步骤所需时间较长
|
@@ -2653,7 +2747,7 @@ def industry_correlation_sw(df,tickers,start,end, \
|
|
2653
2747
|
elif pv< 0.001:
|
2654
2748
|
ax1.text(n+widthx,m+widthy,'***',ha = 'center',color = 'k',fontdict=font_dict)
|
2655
2749
|
|
2656
|
-
plt.title("
|
2750
|
+
plt.title("行业板块/指数"+info_type_cn+"之间的相关性")
|
2657
2751
|
plt.tick_params(labelsize=corr_size)
|
2658
2752
|
|
2659
2753
|
footnote1="\n显著性数值:***非常显著(<0.001),**很显著(<0.01),*显著(<0.05),其余为不显著"
|
@@ -2661,7 +2755,7 @@ def industry_correlation_sw(df,tickers,start,end, \
|
|
2661
2755
|
|
2662
2756
|
footnote3="\n观察期间: "+start+'至'+end
|
2663
2757
|
import datetime as dt; stoday=dt.date.today()
|
2664
|
-
footnote4=";来源:Sina/EM,"+str(stoday)+"
|
2758
|
+
footnote4=";来源:Sina/EM,"+str(stoday)+";基于申万行业/指数分类"
|
2665
2759
|
|
2666
2760
|
fontxlabel={'size':corr_size}
|
2667
2761
|
plt.xlabel(footnote1+footnote2+footnote3+footnote4,fontxlabel)
|
@@ -2865,8 +2959,17 @@ def get_sw_index(ticker,start,end):
|
|
2865
2959
|
try:
|
2866
2960
|
dft = ak.index_hist_sw(symbol=symbol,period="day")
|
2867
2961
|
except:
|
2868
|
-
|
2869
|
-
|
2962
|
+
try:
|
2963
|
+
dft = ak.index_hist_fund_sw(symbol=symbol,period="day")
|
2964
|
+
dft['代码']=symbol
|
2965
|
+
dft['收盘']=dft['收盘指数']
|
2966
|
+
dft['开盘']=dft['收盘指数']
|
2967
|
+
dft['最高']=dft['收盘指数']
|
2968
|
+
dft['最低']=dft['收盘指数']
|
2969
|
+
dft['成交量']=0; dft['成交额']=0
|
2970
|
+
except:
|
2971
|
+
print(" #Error(get_sw_index): failed to retrieve index",symbol)
|
2972
|
+
return None
|
2870
2973
|
|
2871
2974
|
dft['ticker']=dft['代码'].apply(lambda x: x+'.SW')
|
2872
2975
|
|
@@ -2979,7 +3082,8 @@ if __name__ =="__main__":
|
|
2979
3082
|
|
2980
3083
|
|
2981
3084
|
def industry_scan_china(sw_level='F', \
|
2982
|
-
indicator='Exp Ret%', \
|
3085
|
+
indicator='Exp Adj Ret%', \
|
3086
|
+
base_return='Exp Adj Ret%', \
|
2983
3087
|
start='MRY',end='default', \
|
2984
3088
|
RF=0, \
|
2985
3089
|
printout='smart', \
|
@@ -2989,16 +3093,25 @@ def industry_scan_china(sw_level='F', \
|
|
2989
3093
|
申万行业分类sw_level:F--市场表征(默认),S--投资风格(策略),B--大类风格,C--金创,
|
2990
3094
|
1--一级行业,2--二级行业,3--三级行业
|
2991
3095
|
评估期间start与end:允许MRM/MRQ/MRY(默认)/YTD/L3Y(近三年)/L5Y(近五年)
|
3096
|
+
base_return:计算sharpe和sortino比率使用的收益率类型。
|
3097
|
+
当indicator不是sharpe或sortino比率时,base_return需要与indicator保持一致。
|
2992
3098
|
RF:年化无风险收益率,默认0,可参照一年期国债收益率
|
2993
3099
|
筛选方式printout:smart--收益前10名与后10名(默认),winner--仅限收益为正的行业,
|
2994
3100
|
loser--仅限收益为负的行业,50--收益前50名,-10--收益后10名,all--所有行业
|
2995
3101
|
"""
|
2996
3102
|
#indicator='Exp Ret%'
|
2997
3103
|
|
2998
|
-
print("
|
3104
|
+
#print(" Evaluating industry performance, it may take up to hours ... ...")
|
3105
|
+
|
3106
|
+
#节省获取数据的量和时间
|
3107
|
+
if start=='MRY' and end=='default': #默认参数
|
3108
|
+
if 'Weekly' in indicator or 'Weekly' in base_return:
|
3109
|
+
start='MRM'
|
3110
|
+
if 'Monthly' in indicator or 'Monthly' in base_return:
|
3111
|
+
start='MRQ'
|
2999
3112
|
|
3000
3113
|
# 检查申万行业
|
3001
|
-
sw_level_list=['1','2','3','F','S','B','C']
|
3114
|
+
sw_level_list=['1','2','3','F','S','B','C','J1','J2','J3','JF']
|
3002
3115
|
if sw_level not in sw_level_list:
|
3003
3116
|
print(" #Warning(industry_scan_china): invalid Shenwan industry types for",sw_level)
|
3004
3117
|
print(" Valid Shenwan industry types:",end='')
|
@@ -3006,14 +3119,38 @@ def industry_scan_china(sw_level='F', \
|
|
3006
3119
|
return None
|
3007
3120
|
|
3008
3121
|
# 检查支持的指标
|
3009
|
-
|
3010
|
-
'
|
3122
|
+
base_return_list=['Exp Ret%','Exp Ret Volatility%','Exp Ret LPSD%', \
|
3123
|
+
'Exp Adj Ret%','Exp Adj Ret Volatility%','Exp Adj Ret LPSD%', \
|
3124
|
+
|
3125
|
+
'Annual Ret%','Annual Ret Volatility%','Annual Ret LPSD%', \
|
3126
|
+
'Annual Adj Ret%','Annual Adj Ret Volatility%','Annual Adj Ret LPSD%', \
|
3127
|
+
|
3128
|
+
'Quarterly Ret%','Quarterly Ret Volatility%','Quarterly Ret LPSD%', \
|
3129
|
+
'Quarterly Adj Ret%','Quarterly Adj Ret Volatility%','Quarterly Adj Ret LPSD%', \
|
3130
|
+
|
3131
|
+
'Monthly Ret%','Monthly Ret Volatility%','Monthly Ret LPSD%', \
|
3132
|
+
'Monthly Adj Ret%','Monthly Adj Ret Volatility%','Monthly Adj Ret LPSD%', \
|
3133
|
+
|
3134
|
+
'Weekly Ret%','Weekly Ret Volatility%','Weekly Ret LPSD%', \
|
3135
|
+
'Weekly Adj Ret%','Weekly Adj Ret Volatility%','Weekly Adj Ret LPSD%', \
|
3136
|
+
]
|
3137
|
+
if base_return not in base_return_list:
|
3138
|
+
print(" #Warning(industry_scan_china): unsupported base return type for",base_return)
|
3139
|
+
print(" Supported base return:")
|
3140
|
+
printlist(base_return_list,numperline=5,beforehand=' ',separator=', ')
|
3141
|
+
return None
|
3142
|
+
|
3143
|
+
|
3144
|
+
indicator_list=base_return_list + ['sharpe','sortino']
|
3145
|
+
|
3146
|
+
if indicator.lower() in ['sharpe','sortino']:
|
3147
|
+
indicator=indicator.lower()
|
3148
|
+
|
3011
3149
|
if indicator not in indicator_list:
|
3012
3150
|
print(" #Warning(industry_scan_china): unsupported indicator for",indicator)
|
3013
3151
|
print(" Supported indicators:")
|
3014
3152
|
printlist(indicator_list,numperline=5,beforehand=' ',separator=', ')
|
3015
3153
|
return None
|
3016
|
-
|
3017
3154
|
|
3018
3155
|
# 检查日期:
|
3019
3156
|
fromdate,todate=start_end_preprocess(start,end)
|
@@ -3050,7 +3187,8 @@ def industry_scan_china(sw_level='F', \
|
|
3050
3187
|
fromdate=date_adjust(todate,adjust=-31)
|
3051
3188
|
"""
|
3052
3189
|
# 获取申万行业类别内部标识
|
3053
|
-
itype_list=['1','2','3','F','S','B','C']
|
3190
|
+
#itype_list=['1','2','3','F','S','B','C']
|
3191
|
+
itype_list=sw_level_list
|
3054
3192
|
pos=sw_level_list.index(sw_level)
|
3055
3193
|
itype=itype_list[pos]
|
3056
3194
|
|
@@ -3060,21 +3198,68 @@ def industry_scan_china(sw_level='F', \
|
|
3060
3198
|
|
3061
3199
|
# 循环获取行业指数,简单计算指数增长率,排序
|
3062
3200
|
#print(" Retrieving industry info, which may need up to hours, take a break ...")
|
3063
|
-
print("\n *** Step 1: Retrieving information")
|
3201
|
+
#print("\n *** Step 1: Retrieving industry information")
|
3202
|
+
print(" *** Step 1: ")
|
3064
3203
|
# 获取行业历史数据,本步骤所需时间较长
|
3065
3204
|
df=get_industry_sw(itype=itype)
|
3205
|
+
found=df_have_data(df)
|
3206
|
+
if not found=='Found':
|
3207
|
+
print(" #Warning(compare_mindustry_sw): data tentatively unavailable for group",itype)
|
3208
|
+
print(" Data is sometimes unavialble at certain time points, try again later")
|
3209
|
+
return None
|
3066
3210
|
|
3067
3211
|
# 计算指标
|
3068
|
-
print("\n *** Step 2: Computing indicators")
|
3212
|
+
#print("\n *** Step 2: Computing performance indicators")
|
3213
|
+
print("\n *** Step 2: ")
|
3069
3214
|
# 计算基础数据,本步骤所需时间较长
|
3070
3215
|
idf,idfall=calc_industry_sw(df,fromdate,todate)
|
3071
3216
|
|
3072
|
-
|
3073
|
-
|
3074
|
-
|
3075
|
-
|
3076
|
-
|
3077
|
-
|
3217
|
+
#设置base_return:非['sharpe','sortino']时
|
3218
|
+
if not indicator in ['sharpe','sortino']:
|
3219
|
+
#以下的判断顺序不可轻易改变
|
3220
|
+
if 'Ret Volatility%' in indicator:
|
3221
|
+
base_return=indicator.replace('Ret Volatility%','Ret%')
|
3222
|
+
elif 'Ret Volatility' in indicator:
|
3223
|
+
base_return=indicator.replace('Ret Volatility','Ret')
|
3224
|
+
elif 'Ret LPSD%' in indicator:
|
3225
|
+
base_return=indicator.replace('Ret LPSD%','Ret%')
|
3226
|
+
elif 'Ret LPSD' in indicator:
|
3227
|
+
base_return=indicator.replace('Ret LPSD','Ret')
|
3228
|
+
else:
|
3229
|
+
base_return=indicator
|
3230
|
+
|
3231
|
+
|
3232
|
+
#计算期间内的无风险收益率:RF为小数,而idf中的收益率为百分数
|
3233
|
+
if '%' in base_return:
|
3234
|
+
RFS=RF*100 #百分数
|
3235
|
+
|
3236
|
+
base_return_volatility=base_return.replace('Ret%','Ret Volatility%')
|
3237
|
+
base_return_lpsd=base_return.replace('Ret%','Ret LPSD%')
|
3238
|
+
else:
|
3239
|
+
RFS=RF
|
3240
|
+
|
3241
|
+
base_return_volatility=base_return.replace('Ret','Ret Volatility')
|
3242
|
+
base_return_lpsd=base_return.replace('Ret','Ret LPSD')
|
3243
|
+
|
3244
|
+
if 'Exp' in base_return:
|
3245
|
+
RF_daily=RFS/365
|
3246
|
+
RF_days=RF_daily * calculate_days(fromdate, todate)
|
3247
|
+
|
3248
|
+
elif 'Annual' in base_return:
|
3249
|
+
RF_days=RFS
|
3250
|
+
|
3251
|
+
elif 'Quarterly' in base_return:
|
3252
|
+
RF_days=RFS/4
|
3253
|
+
|
3254
|
+
elif 'Monthly' in base_return:
|
3255
|
+
RF_days=RFS/12
|
3256
|
+
|
3257
|
+
elif 'Weekly' in base_return:
|
3258
|
+
RF_days=RFS/52
|
3259
|
+
|
3260
|
+
idf['sharpe']=(idf[base_return]-RF_days) / idf[base_return_volatility]
|
3261
|
+
idf['sortino']=(idf[base_return]-RF_days) / idf[base_return_lpsd]
|
3262
|
+
|
3078
3263
|
|
3079
3264
|
# 排序
|
3080
3265
|
idf.sort_values(indicator,ascending=False,inplace=True)
|
@@ -3107,9 +3292,9 @@ def industry_scan_china(sw_level='F', \
|
|
3107
3292
|
if printout=='all':
|
3108
3293
|
df_prt=df2
|
3109
3294
|
elif printout=='winner':
|
3110
|
-
df_prt=df2[df2[
|
3295
|
+
df_prt=df2[df2[indicator] > 0]
|
3111
3296
|
elif printout=='loser':
|
3112
|
-
df_prt=df2[df2[
|
3297
|
+
df_prt=df2[df2[indicator] <= 0]
|
3113
3298
|
else:
|
3114
3299
|
try:
|
3115
3300
|
printoutd=int(printout)
|
@@ -3121,10 +3306,10 @@ def industry_scan_china(sw_level='F', \
|
|
3121
3306
|
pass
|
3122
3307
|
|
3123
3308
|
# 标题改中文
|
3124
|
-
df_prt.rename(columns={'Industry Code':'
|
3125
|
-
|
3126
|
-
|
3127
|
-
|
3309
|
+
df_prt.rename(columns={'Industry Code':'代码','Industry Name':'名称', \
|
3310
|
+
base_return:ectranslate(base_return), \
|
3311
|
+
base_return_volatility:ectranslate(base_return_volatility), \
|
3312
|
+
base_return_lpsd:ectranslate(base_return_lpsd), \
|
3128
3313
|
'sharpe':'夏普比率','sortino':'索替诺比率'}, \
|
3129
3314
|
inplace=True)
|
3130
3315
|
|
@@ -3143,6 +3328,14 @@ def industry_scan_china(sw_level='F', \
|
|
3143
3328
|
sw_level_txt='申万二级行业'
|
3144
3329
|
elif sw_level=='3':
|
3145
3330
|
sw_level_txt='申万三级行业'
|
3331
|
+
elif sw_level=='J1':
|
3332
|
+
sw_level_txt='申万基金基础一级指数'
|
3333
|
+
elif sw_level=='J2':
|
3334
|
+
sw_level_txt='申万基金基础二级指数'
|
3335
|
+
elif sw_level=='J3':
|
3336
|
+
sw_level_txt='申万基金基础三级指数'
|
3337
|
+
elif sw_level=='JF':
|
3338
|
+
sw_level_txt='申万基金特色指数'
|
3146
3339
|
else:
|
3147
3340
|
sw_level_txt='未知类别'
|
3148
3341
|
|
@@ -3161,9 +3354,9 @@ def industry_scan_china(sw_level='F', \
|
|
3161
3354
|
num=int(printout)
|
3162
3355
|
if len(df2) > abs(num):
|
3163
3356
|
if num > 0:
|
3164
|
-
printout_txt='
|
3357
|
+
printout_txt='收益排名前'+printout+"名"
|
3165
3358
|
else:
|
3166
|
-
printout_txt='
|
3359
|
+
printout_txt='收益排名后'+str(abs(num))+"名"
|
3167
3360
|
else:
|
3168
3361
|
printout_txt='所有指数'
|
3169
3362
|
except:
|
@@ -3171,7 +3364,7 @@ def industry_scan_china(sw_level='F', \
|
|
3171
3364
|
|
3172
3365
|
#titletxt="申万行业业绩排行榜:"+sw_level_txt+',共'+str(len(df_prt))+"个指数符合条件"
|
3173
3366
|
#titletxt="行业业绩排行榜:"+sw_level_txt+','+ectranslate(indicator)+',筛选方式:'+printout_txt
|
3174
|
-
titletxt="
|
3367
|
+
titletxt="申万宏源行业/指数业绩龙虎榜:"+sw_level_txt+','+printout_txt
|
3175
3368
|
#print("\n***",titletxt,'\n')
|
3176
3369
|
"""
|
3177
3370
|
alignlist=['center']+['left']*(len(list(df_prt))-1)
|
@@ -3179,28 +3372,34 @@ def industry_scan_china(sw_level='F', \
|
|
3179
3372
|
"""
|
3180
3373
|
#print("\n *** 数据来源:综合申万宏源/东方财富/新浪财经,",todaydt,"\b;分析期间:",fromdate+'至'+todate)
|
3181
3374
|
#footnote1="筛选方式:all-所有,smart-收益最高最低各10个,winner-收益为正,loser-收益为负"
|
3182
|
-
|
3183
|
-
|
3184
|
-
footnote=footnote2
|
3375
|
+
footnote1="注:夏普/索梯诺比率基于"+ectranslate(base_return)+",年化无风险利率"+str(round(RF*100,4))+'%'
|
3376
|
+
footnote2="评估期间:"+str(fromdate)+'至'+str(todate)+",数据来源:申万宏源,"+str(todaydt)+"制表"
|
3377
|
+
footnote=footnote1+'\n'+footnote2
|
3378
|
+
#footnote=footnote2
|
3185
3379
|
|
3186
3380
|
#确定表格字体大小
|
3187
3381
|
titile_font_size=font_size
|
3188
3382
|
heading_font_size=data_font_size=str(int(font_size.replace('px',''))-1)+'px'
|
3189
3383
|
|
3190
3384
|
df_prt['序号']=df_prt.index
|
3191
|
-
if indicator=='
|
3192
|
-
df_prt=df_prt[['序号','
|
3193
|
-
|
3194
|
-
df_prt=df_prt[['序号','行业名称','行业代码','投资收益波动率%','投资收益率%','投资收益损失风险%','夏普比率','索替诺比率']]
|
3195
|
-
elif indicator=='Exp Ret LPSD%':
|
3196
|
-
df_prt=df_prt[['序号','行业名称','行业代码','投资收益损失风险%','投资收益波动率%','投资收益率%','夏普比率','索替诺比率']]
|
3197
|
-
elif indicator=='sharpe':
|
3198
|
-
df_prt=df_prt[['序号','行业名称','行业代码','夏普比率','索替诺比率','投资收益率%','投资收益波动率%','投资收益损失风险%']]
|
3385
|
+
if indicator=='sharpe':
|
3386
|
+
df_prt=df_prt[['序号','名称','代码','夏普比率','索替诺比率', \
|
3387
|
+
ectranslate(base_return),ectranslate(base_return_volatility),ectranslate(base_return_lpsd)]]
|
3199
3388
|
elif indicator=='sortino':
|
3200
|
-
df_prt=df_prt[['序号','
|
3201
|
-
|
3202
|
-
|
3389
|
+
df_prt=df_prt[['序号','名称','代码','索替诺比率','夏普比率', \
|
3390
|
+
ectranslate(base_return),ectranslate(base_return_volatility),ectranslate(base_return_lpsd)]]
|
3391
|
+
|
3392
|
+
elif 'Volatility' in indicator:
|
3393
|
+
df_prt=df_prt[['序号','名称','代码',ectranslate(base_return_volatility),ectranslate(base_return_lpsd), \
|
3394
|
+
ectranslate(base_return),'夏普比率','索替诺比率']]
|
3395
|
+
elif 'LPSD' in indicator:
|
3396
|
+
df_prt=df_prt[['序号','名称','代码',ectranslate(base_return_lpsd),ectranslate(base_return_volatility), \
|
3397
|
+
ectranslate(base_return),'夏普比率','索替诺比率']]
|
3398
|
+
else:
|
3399
|
+
df_prt=df_prt[['序号','名称','代码',ectranslate(base_return), \
|
3400
|
+
ectranslate(base_return_volatility),ectranslate(base_return_lpsd),'夏普比率','索替诺比率']]
|
3203
3401
|
|
3402
|
+
#显示表格
|
3204
3403
|
df_display_CSS(df_prt,titletxt=titletxt,footnote=footnote,facecolor=facecolor, \
|
3205
3404
|
first_col_align='center',second_col_align='left', \
|
3206
3405
|
last_col_align='center',other_col_align='center', \
|
@@ -3233,12 +3432,12 @@ if __name__=='__main__':
|
|
3233
3432
|
|
3234
3433
|
find_industry_sw(ticker)
|
3235
3434
|
|
3236
|
-
def find_industry_sw(ticker,level='1',ticker_order=True,max_sleep=
|
3435
|
+
def find_industry_sw(ticker,level='1',ticker_order=True,max_sleep=30):
|
3237
3436
|
"""
|
3238
3437
|
功能:寻找一只或一组股票所属的申万行业,支持股票代码和股票名称。
|
3239
3438
|
level='1':默认只查找申万1级行业,以便节省时间
|
3240
3439
|
ticker_order=True:默认输出结果按照ticker中的顺序,而非按照所属行业排序
|
3241
|
-
max_sleep
|
3440
|
+
max_sleep:为防止反爬虫,默认每次爬虫后睡眠最多几秒钟
|
3242
3441
|
"""
|
3243
3442
|
print(" Searching shenwan industries for securities ... ...")
|
3244
3443
|
|
@@ -3755,4 +3954,42 @@ def stock_peers_sw(ticker):
|
|
3755
3954
|
print(footnote)
|
3756
3955
|
return
|
3757
3956
|
|
3957
|
+
#==============================================================================
|
3958
|
+
if __name__ == '__main__':
|
3959
|
+
sw_index=['绩优股指数','大盘指数','中市盈率指数','高市净率指数',]
|
3960
|
+
sw_index=['大类风格-先进制造','大类风格--医药医疗']
|
3961
|
+
|
3962
|
+
index_intersection_sw(sw_index)
|
3963
|
+
|
3964
|
+
def index_intersection_sw(sw_index=[]):
|
3965
|
+
#寻找多个申万指数中共同的成分股
|
3966
|
+
if len(sw_index)==0:
|
3967
|
+
print(" #Warning(stock_intersection_sw): no index found for intersection")
|
3968
|
+
return
|
3969
|
+
|
3970
|
+
if isinstance(sw_index,str):
|
3971
|
+
sw_index=[sw_index]
|
3972
|
+
|
3973
|
+
result_list=[]
|
3974
|
+
for i in sw_index:
|
3975
|
+
try:
|
3976
|
+
ilist=print_industry_component_sw(i,printout=False,return_result=True)
|
3977
|
+
except:
|
3978
|
+
print(" #Warning(stock_intersection_sw): failed to find component for index",i)
|
3979
|
+
continue
|
3980
|
+
|
3981
|
+
if len(result_list)==0:
|
3982
|
+
result_list=[ilist]
|
3983
|
+
else:
|
3984
|
+
result_list=result_list+[ilist]
|
3985
|
+
|
3986
|
+
list_intersection(result_list)
|
3987
|
+
|
3988
|
+
return
|
3989
|
+
#==============================================================================
|
3990
|
+
#==============================================================================
|
3991
|
+
#==============================================================================
|
3992
|
+
#==============================================================================
|
3993
|
+
#==============================================================================
|
3994
|
+
#==============================================================================
|
3758
3995
|
|