siat 3.8.28__py3-none-any.whl → 3.8.30__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- siat/economy2.py +132 -28
- siat/grafix.py +70 -25
- siat/valuation_china.py +288 -1
- {siat-3.8.28.dist-info → siat-3.8.30.dist-info}/METADATA +10 -2
- {siat-3.8.28.dist-info → siat-3.8.30.dist-info}/RECORD +8 -8
- {siat-3.8.28.dist-info → siat-3.8.30.dist-info}/WHEEL +1 -1
- {siat-3.8.28.dist-info → siat-3.8.30.dist-info}/LICENSE +0 -0
- {siat-3.8.28.dist-info → siat-3.8.30.dist-info}/top_level.txt +0 -0
siat/economy2.py
CHANGED
@@ -360,6 +360,8 @@ if __name__ =="__main__":
|
|
360
360
|
indicator="NY.GDP.MKTP.KN"
|
361
361
|
indicator="GC.XPN.TOTL.GD.ZS"
|
362
362
|
|
363
|
+
indicator='GC.GDP.COMP.ZS' # 自制指标
|
364
|
+
|
363
365
|
start='2010'; end='2025'; power=3
|
364
366
|
|
365
367
|
zeroline=False
|
@@ -380,7 +382,7 @@ def economy_indicator_wb(ticker='CN',indicator='NY.GDP.MKTP.KN', \
|
|
380
382
|
attention_point='',attention_point_area='', \
|
381
383
|
average_value=False, \
|
382
384
|
datatag=False,power=0,graph=True, \
|
383
|
-
mark_top=
|
385
|
+
mark_start=False,mark_top=False,mark_bottom=False,mark_end=True, \
|
384
386
|
facecolor='whitesmoke',loc='best',maxticks=30):
|
385
387
|
"""
|
386
388
|
===========================================================================
|
@@ -406,6 +408,15 @@ def economy_indicator_wb(ticker='CN',indicator='NY.GDP.MKTP.KN', \
|
|
406
408
|
输出:图形
|
407
409
|
返回值:数据表
|
408
410
|
"""
|
411
|
+
import pandas as pd
|
412
|
+
|
413
|
+
# 自制指标
|
414
|
+
sm_ind_list=['GC.GDP.COMP.ZS']
|
415
|
+
if indicator in sm_ind_list:
|
416
|
+
sm_ind_flag=True
|
417
|
+
else:
|
418
|
+
sm_ind_flag=False
|
419
|
+
|
409
420
|
# 检测指标是否存在,并取得指标名称
|
410
421
|
indicator_name=indicator_name_wb(indicator)
|
411
422
|
if indicator_name == indicator:
|
@@ -416,11 +427,36 @@ def economy_indicator_wb(ticker='CN',indicator='NY.GDP.MKTP.KN', \
|
|
416
427
|
start,end=start_end_preprocess(start,end)
|
417
428
|
|
418
429
|
# 下载数据
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
430
|
+
if not sm_ind_flag:
|
431
|
+
try:
|
432
|
+
pricedf=wb.download(indicator=indicator,country=ticker,start=start,end=end)
|
433
|
+
except:
|
434
|
+
print(f" #Error(economy_indicator_wb): {indicator} not available for {ticker}")
|
435
|
+
return None
|
436
|
+
elif indicator == 'GC.GDP.COMP.ZS': # 针对自制指标
|
437
|
+
indtmp1='NY.GDP.FCST.CN' # Compensation of employees (current LCU),CN无数据!
|
438
|
+
indtmp2='NY.GDP.MKTP.CN' # GDP (current LCU)
|
439
|
+
try:
|
440
|
+
pricetmp1=wb.download(indicator=indtmp1,country=ticker,start=start,end=end)
|
441
|
+
except:
|
442
|
+
print(f" #Error(economy_indicator_wb): element {indtmp1} not available for {ticker}")
|
443
|
+
return None
|
444
|
+
try:
|
445
|
+
pricetmp2=wb.download(indicator=indtmp2,country=ticker,start=start,end=end)
|
446
|
+
except:
|
447
|
+
print(f" #Error(economy_indicator_wb): element {indtmp2} not available for {ticker}")
|
448
|
+
return None
|
449
|
+
|
450
|
+
# 算法=indtmp1 / indtmp2 * 100
|
451
|
+
pricetmp=pd.merge(pricetmp1,pricetmp2,how='inner',left_on=['country','year'],
|
452
|
+
right_on=['country','year'])
|
453
|
+
pricetmp[indicator]=pricetmp.apply(lambda x: round(x[indtmp1]/x[indtmp2]*100,2),axis=1)
|
454
|
+
pricetmp['country']=pricetmp.index[0][0]
|
455
|
+
pricetmp['year']=pricetmp.index
|
456
|
+
pricetmp['year']=pricetmp['year'].apply(lambda x: x[1])
|
457
|
+
|
458
|
+
pricedf=pricetmp[['country','year',indicator]]
|
459
|
+
pricedf.reset_index(drop=True,inplace=True)
|
424
460
|
|
425
461
|
# 是否返回None
|
426
462
|
if pricedf is None:
|
@@ -432,10 +468,14 @@ def economy_indicator_wb(ticker='CN',indicator='NY.GDP.MKTP.KN', \
|
|
432
468
|
return None
|
433
469
|
# 是否返回数据表但内容均为NaN
|
434
470
|
if pricedf[indicator].isnull().all():
|
435
|
-
print(f" #Error(economy_indicator_wb): empty data found on {indicator} in {ticker}")
|
471
|
+
print(f" #Error(economy_indicator_wb): all empty data found on {indicator} in {ticker}")
|
436
472
|
return None
|
437
|
-
|
438
|
-
pricedf.
|
473
|
+
# 判断非空值的个数
|
474
|
+
if pricedf[indicator].count() == 1:
|
475
|
+
print(f" #Warning(economy_indicator_wb): only 1 non-empty data found on {indicator} in {ticker}")
|
476
|
+
#return None
|
477
|
+
|
478
|
+
pricedf.reset_index(drop=True,inplace=True)
|
439
479
|
pricedf.set_index('year',inplace=True)
|
440
480
|
pricedf.rename(columns={indicator:indicator_name},inplace=True)
|
441
481
|
country=pricedf['country'].values[0]
|
@@ -475,10 +515,6 @@ def economy_indicator_wb(ticker='CN',indicator='NY.GDP.MKTP.KN', \
|
|
475
515
|
erdf3[indicator_name]=erdf3[indicator_name].apply(lambda x: round(x/unit_amount,2))
|
476
516
|
|
477
517
|
# 绘图
|
478
|
-
"""
|
479
|
-
if not graph:
|
480
|
-
return erdf3
|
481
|
-
"""
|
482
518
|
# 判断是否绘制零线
|
483
519
|
if ind_max * ind_min <0:
|
484
520
|
zeroline=True
|
@@ -510,7 +546,8 @@ def economy_indicator_wb(ticker='CN',indicator='NY.GDP.MKTP.KN', \
|
|
510
546
|
average_value=average_value, \
|
511
547
|
attention_value=attention_value,attention_value_area=attention_value_area, \
|
512
548
|
attention_point=attention_point,attention_point_area=attention_point_area, \
|
513
|
-
mark_top=mark_top,mark_bottom=mark_bottom,
|
549
|
+
mark_top=mark_top,mark_bottom=mark_bottom, \
|
550
|
+
mark_start=mark_start,mark_end=mark_end, \
|
514
551
|
facecolor=facecolor,loc=loc,maxticks=30,translate=translate)
|
515
552
|
except Exception as e:
|
516
553
|
# 捕获所有异常
|
@@ -553,7 +590,7 @@ def economy_mindicators_wb(ticker='CN',indicator=['NY.GDP.MKTP.CN','NY.GDP.MKTP.
|
|
553
590
|
graph=True,smooth=False,loc='best',facecolor='whitesmoke', \
|
554
591
|
date_range=False,date_freq=False, \
|
555
592
|
annotate=False,annotate_value=False, \
|
556
|
-
mark_top=False,mark_bottom=False,mark_end=False, \
|
593
|
+
mark_start=False,mark_top=False,mark_bottom=False,mark_end=False, \
|
557
594
|
maxticks=30,translate=False):
|
558
595
|
"""
|
559
596
|
===========================================================================
|
@@ -573,7 +610,7 @@ def economy_mindicators_wb(ticker='CN',indicator=['NY.GDP.MKTP.CN','NY.GDP.MKTP.
|
|
573
610
|
facecolor:画布背景颜色,默认'whitesmoke'
|
574
611
|
annotate:是否在曲线末端标注,默认否False
|
575
612
|
annotate_value:是否标注曲线末端值,默认否False
|
576
|
-
mark_top, mark_bottom, mark_end
|
613
|
+
mark_start, mark_top, mark_bottom, mark_end:是否标注起始值、最大、最小、末端值,默认否
|
577
614
|
maxticks=30:限制横轴刻度最大数量
|
578
615
|
|
579
616
|
date_range=False:指定开始结束日期绘图
|
@@ -720,7 +757,8 @@ def economy_mindicators_wb(ticker='CN',indicator=['NY.GDP.MKTP.CN','NY.GDP.MKTP.
|
|
720
757
|
attention_value=attention_value,attention_value_area=attention_value_area, \
|
721
758
|
attention_point=attention_point,attention_point_area=attention_point_area, \
|
722
759
|
annotate=annotate,annotate_value=annotate_value, \
|
723
|
-
mark_top=mark_top,mark_bottom=mark_bottom,mark_end=mark_end,
|
760
|
+
mark_start=mark_start,mark_top=mark_top,mark_bottom=mark_bottom,mark_end=mark_end, \
|
761
|
+
facecolor=facecolor, \
|
724
762
|
band_area=band_area,loc=loc,maxticks=maxticks,translate=translate)
|
725
763
|
|
726
764
|
return pricedf
|
@@ -758,7 +796,7 @@ def economy_mtickers_wb(ticker=['CN','US','JP'],indicator='NY.GDP.MKTP.PP.CD', \
|
|
758
796
|
band_area='',loc='best', \
|
759
797
|
annotate=False,annotate_value=False, \
|
760
798
|
smooth=False, \
|
761
|
-
mark_top=True,mark_bottom=True,mark_end=False, \
|
799
|
+
mark_start=False,mark_top=True,mark_bottom=True,mark_end=False, \
|
762
800
|
maxticks=30,translate=False):
|
763
801
|
"""
|
764
802
|
===========================================================================
|
@@ -969,7 +1007,8 @@ def economy_mtickers_wb(ticker=['CN','US','JP'],indicator='NY.GDP.MKTP.PP.CD', \
|
|
969
1007
|
attention_value=attention_value,attention_value_area=attention_value_area, \
|
970
1008
|
attention_point=attention_point,attention_point_area=attention_point_area, \
|
971
1009
|
annotate=annotate,annotate_value=annotate_value,plus_sign=plus_sign, \
|
972
|
-
mark_top=mark_top,mark_bottom=mark_bottom,mark_end=mark_end,
|
1010
|
+
mark_start=mark_start,mark_top=mark_top,mark_bottom=mark_bottom,mark_end=mark_end, \
|
1011
|
+
facecolor=facecolor, \
|
973
1012
|
maxticks_enable=False,maxticks=10, \
|
974
1013
|
translate=translate)
|
975
1014
|
|
@@ -982,7 +1021,7 @@ def economy_trend2(ticker='CN',indicator='NY.GDP.MKTP.KN', \
|
|
982
1021
|
start='L10Y',end='today',translate=False, \
|
983
1022
|
attention_value='',attention_value_area='', \
|
984
1023
|
attention_point='',attention_point_area='', \
|
985
|
-
mark_top=False,mark_bottom=False,mark_end=False, \
|
1024
|
+
mark_start=False,mark_top=False,mark_bottom=False,mark_end=False, \
|
986
1025
|
graph=True,facecolor='whitesmoke',loc='best',maxticks=30, \
|
987
1026
|
|
988
1027
|
zeroline=False,average_value=False, \
|
@@ -1009,7 +1048,7 @@ def economy_trend2(ticker='CN',indicator='NY.GDP.MKTP.KN', \
|
|
1009
1048
|
attention_point:横轴关注值或其列表,默认无''
|
1010
1049
|
attention_point_area:横轴关注值区间强调,默认无''
|
1011
1050
|
graph:是否绘图,默认是True
|
1012
|
-
mark_top, mark_bottom, mark_end
|
1051
|
+
mark_start, mark_top, mark_bottom, mark_end:是否标记开始点、最高、最低和末端点:默认否False
|
1013
1052
|
facecolor:背景颜色,默认'whitesmoke'
|
1014
1053
|
loc:图例位置,默认自动'best'
|
1015
1054
|
|
@@ -1082,7 +1121,8 @@ def economy_trend2(ticker='CN',indicator='NY.GDP.MKTP.KN', \
|
|
1082
1121
|
attention_value_area=attention_value_area, \
|
1083
1122
|
attention_point=attention_point, \
|
1084
1123
|
attention_point_area=attention_point_area, \
|
1085
|
-
mark_top=mark_top,mark_bottom=mark_bottom,
|
1124
|
+
mark_top=mark_top,mark_bottom=mark_bottom, \
|
1125
|
+
mark_start=mark_start,mark_end=mark_end, \
|
1086
1126
|
graph=graph,facecolor=facecolor,loc=loc,maxticks=maxticks, \
|
1087
1127
|
|
1088
1128
|
power=power,average_value=average_value, \
|
@@ -1097,7 +1137,8 @@ def economy_trend2(ticker='CN',indicator='NY.GDP.MKTP.KN', \
|
|
1097
1137
|
attention_value_area=attention_value_area, \
|
1098
1138
|
attention_point=attention_point, \
|
1099
1139
|
attention_point_area=attention_point_area, \
|
1100
|
-
mark_top=mark_top,mark_bottom=mark_bottom,
|
1140
|
+
mark_top=mark_top,mark_bottom=mark_bottom, \
|
1141
|
+
mark_start=mark_start,mark_end=mark_end, \
|
1101
1142
|
graph=graph,loc=loc,facecolor=facecolor,maxticks=maxticks, \
|
1102
1143
|
band_area=band_area, \
|
1103
1144
|
annotate=annotate,annotate_value=annotate_value,smooth=smooth, \
|
@@ -1115,7 +1156,8 @@ def economy_trend2(ticker='CN',indicator='NY.GDP.MKTP.KN', \
|
|
1115
1156
|
attention_value_area=attention_value_area, \
|
1116
1157
|
attention_point=attention_point, \
|
1117
1158
|
attention_point_area=attention_point_area, \
|
1118
|
-
mark_top=mark_top,mark_bottom=mark_bottom,
|
1159
|
+
mark_top=mark_top,mark_bottom=mark_bottom, \
|
1160
|
+
mark_start=mark_start,mark_end=mark_end, \
|
1119
1161
|
graph=graph,facecolor=facecolor,loc=loc,maxticks=maxticks, \
|
1120
1162
|
|
1121
1163
|
annotate=annotate,annotate_value=annotate_value,smooth=smooth, \
|
@@ -1505,13 +1547,23 @@ def economic_translate(indicator):
|
|
1505
1547
|
'Exports of goods and services (% of GDP)',
|
1506
1548
|
'Exports of goods and services (% of GDP)'],
|
1507
1549
|
|
1550
|
+
['NE.IMP.GNFS.CD','进口商品和服务总金额(美元现价)',
|
1551
|
+
'Imports of goods and services (current US$)',
|
1552
|
+
'Imports of goods and services (current US$)'],
|
1553
|
+
|
1554
|
+
['NE.EXP.GNFS.CD','出口商品和服务总金额(美元现价)',
|
1555
|
+
'Exports of goods and services (current US$)',
|
1556
|
+
'Exports of goods and services (current US$)'],
|
1557
|
+
|
1508
1558
|
['NE.IMP.GNFS.ZS','进口商品和服务占GDP%',
|
1509
1559
|
'Imports of goods and services (% of GDP)',
|
1510
1560
|
'Imports of goods and services (% of GDP)'],
|
1511
1561
|
|
1512
|
-
|
1513
|
-
|
1514
|
-
|
1562
|
+
['NE.TRD.GNFS.ZS','国际贸易占GDP%',
|
1563
|
+
'Trade % of GDP',
|
1564
|
+
'Trade % of GDP'],
|
1565
|
+
# 用来分析一个国家对国际贸易的依赖程度。
|
1566
|
+
# 高贸易占比通常表明一个国家的经济结构以出口和进口为主,而低贸易占比可能表明经济更依赖国内消费或投资。
|
1515
1567
|
|
1516
1568
|
# 贫困和贫富分化========================================================
|
1517
1569
|
['SI.POV.GINI','基尼指数',
|
@@ -1520,8 +1572,60 @@ def economic_translate(indicator):
|
|
1520
1572
|
# 基尼指数:0-100,用于衡量收入或财富分配的不平等程度。
|
1521
1573
|
# 0表示完全平等,100表示完全不平等。基尼系数高通常意味着贫富差距较大。
|
1522
1574
|
# 注意不是基尼系数(0-1)。
|
1575
|
+
|
1576
|
+
# 薪酬=================================================================
|
1577
|
+
['GC.GDP.COMP.ZS','劳动者薪酬占GDP%',
|
1578
|
+
'Compensation of employees (% of GDP)',
|
1579
|
+
'Compensation of employees (% of GDP)'],
|
1580
|
+
# 自制指标:= GC.XPN.COMP.ZS: Compensation of employees (% of expense)
|
1581
|
+
# x GC.XPN.TOTL.GD.ZS: Expense (% of GDP) / 100。
|
1582
|
+
# 或 = GC.XPN.COMP.CN: Compensation of employees (current LCU)
|
1583
|
+
# / NY.GDP.MKTP.CN: GDP (current LCU) * 100.
|
1584
|
+
|
1585
|
+
# 储蓄=================================================================
|
1586
|
+
['NY.GNS.ICTR.ZS','国民储蓄总额占GDP%',
|
1587
|
+
'Gross savings (% of GDP)',
|
1588
|
+
'Gross savings (% of GDP)'],
|
1589
|
+
# 国民储蓄:一国居民和政府的总储蓄,包含国内储蓄和来自国外的净收入
|
1590
|
+
# 包含国际要素:计入来自国外的净要素收入(如投资收益、侨汇)。
|
1523
1591
|
|
1592
|
+
['NY.GDS.TOTL.ZS','国内储蓄总额占GDP%',
|
1593
|
+
'Gross Domestic Savings (% of GDP)',
|
1594
|
+
'Gross Domestic Savings (% of GDP)'],
|
1595
|
+
# 国内储蓄:仅统计国内经济主体(家庭、企业、政府)的储蓄,不包含国外净收入。
|
1596
|
+
# 仅限国内:不涉及国际收入或支出。
|
1597
|
+
|
1598
|
+
# 投资=================================================================
|
1599
|
+
['NE.GDI.TOTL.ZS','总资本形成占GDP%',
|
1600
|
+
'Gross capital formation (% of GDP)',
|
1601
|
+
'Gross capital formation (% of GDP)'],
|
1602
|
+
# 又名Gross domestic investment国内总投资,包括政府、企业和家庭的投资
|
1603
|
+
|
1604
|
+
['NE.GDI.FTOT.ZS','总固定资本形成占GDP%',
|
1605
|
+
'Gross fixed capital formation (% of GDP)',
|
1606
|
+
'Gross fixed capital formation (% of GDP)'],
|
1607
|
+
# 又名Gross domestic fixed investment国内固定资产总投资,包括政府、企业和家庭的投资
|
1608
|
+
|
1609
|
+
['BX.KLT.DINV.WD.GD.ZS','外国直接投资净额占GDP%',
|
1610
|
+
'Foreign direct investment, net inflows (% of GDP)',
|
1611
|
+
'Foreign direct investment, net inflows (% of GDP)'],
|
1612
|
+
# 等于FDI流入 - FDI流出
|
1613
|
+
|
1614
|
+
# 政府财政==============================================================
|
1615
|
+
['GC.REV.XGRT.GD.ZS','政府总收入(不含国际赠款)占GDP%',
|
1616
|
+
'Revenue, excluding grant (% of GDP)',
|
1617
|
+
'Revenue, excluding grant (% of GDP)'],
|
1618
|
+
# 包括税收和非税收入
|
1619
|
+
|
1620
|
+
['SH.XPD.GHED.GD.ZS','政府卫生支出占GDP%',
|
1621
|
+
'Government health expenditure (% of GDP)',
|
1622
|
+
'Domestic general government health expenditure (% of GDP)'],
|
1623
|
+
# 包括税收和非税收入
|
1524
1624
|
|
1625
|
+
['SH.XPD.GHED.CH.ZS','政府卫生支出占当前卫生支出%',
|
1626
|
+
'Government health expenditure (% of health expenditure)',
|
1627
|
+
'Domestic general government health expenditure (% of current health expenditure)'],
|
1628
|
+
# 包括税收和非税收入
|
1525
1629
|
|
1526
1630
|
|
1527
1631
|
|
@@ -1540,7 +1644,7 @@ def economic_translate(indicator):
|
|
1540
1644
|
|
1541
1645
|
found=False; result=indicator
|
1542
1646
|
try:
|
1543
|
-
dict_word=trans_dict[trans_dict['indicator']==indicator]
|
1647
|
+
dict_word=trans_dict[trans_dict['indicator']==indicator.upper()]
|
1544
1648
|
found=True
|
1545
1649
|
except:
|
1546
1650
|
#未查到翻译词汇,返回原词
|
siat/grafix.py
CHANGED
@@ -106,7 +106,7 @@ if __name__ =="__main__":
|
|
106
106
|
power=0
|
107
107
|
zeroline=False
|
108
108
|
average_value=False
|
109
|
-
resample_freq='
|
109
|
+
resample_freq='D'
|
110
110
|
loc='best'
|
111
111
|
date_range=False
|
112
112
|
date_freq=False
|
@@ -122,9 +122,9 @@ def plot_line(df0,colname,collabel,ylabeltxt,titletxt,footnote,datatag=False, \
|
|
122
122
|
attention_point='',attention_point_area='', \
|
123
123
|
average_value=False, \
|
124
124
|
|
125
|
-
resample_freq='
|
125
|
+
resample_freq='D',loc='best', \
|
126
126
|
date_range=False,date_freq=False,date_fmt='%Y-%m-%d', \
|
127
|
-
mark_top=True,mark_bottom=True,mark_end=True, \
|
127
|
+
mark_start=False,mark_top=True,mark_bottom=True,mark_end=True, \
|
128
128
|
facecolor='whitesmoke',maxticks=15,translate=False):
|
129
129
|
"""
|
130
130
|
功能:绘制折线图。如果power=0不绘制趋势图,否则绘制多项式趋势图
|
@@ -203,7 +203,7 @@ def plot_line(df0,colname,collabel,ylabeltxt,titletxt,footnote,datatag=False, \
|
|
203
203
|
|
204
204
|
#绘制数据标签
|
205
205
|
if datatag:
|
206
|
-
mark_top=False; mark_bottom=False; mark_end=False
|
206
|
+
mark_start=False; mark_top=False; mark_bottom=False; mark_end=False
|
207
207
|
for x, y in zip(df.index, df[colname]):
|
208
208
|
plt.text(x,y*1.001,'%.2f' % y,ha='center',va='bottom',color='black')
|
209
209
|
|
@@ -243,6 +243,19 @@ def plot_line(df0,colname,collabel,ylabeltxt,titletxt,footnote,datatag=False, \
|
|
243
243
|
plt.text(x,y1,s % y,ha='right',va='bottom',color='seagreen')
|
244
244
|
plt.scatter(x,y, color='seagreen',marker='8',s=70)
|
245
245
|
|
246
|
+
#标记曲线开始数值
|
247
|
+
if mark_start:
|
248
|
+
df_start=df.head(1)
|
249
|
+
y_start = df_start[colname].min() # 开始的y坐标
|
250
|
+
x_start = df_start[colname].idxmin() # 开始值的x坐标
|
251
|
+
|
252
|
+
#y1=str(int(y_end)) if y_end >= 100 else str(round(y_end,2))
|
253
|
+
y1=str(round(y_start,1)) if abs(y_start) >= 100 else str(round(y_start,2)) if abs(y_start) >= 1 else str(round(y_start,3))
|
254
|
+
plt.annotate(text=y1,
|
255
|
+
xy=(x_start, y_start),
|
256
|
+
xytext=(x_start, y_start*0.998),fontsize=annotate_size,ha='right',va='center')
|
257
|
+
# 特别注意:这里的left/right与实际图示的方向正好相反!!!
|
258
|
+
|
246
259
|
#标记曲线末端数值
|
247
260
|
if mark_end:
|
248
261
|
df_end=df.tail(1)
|
@@ -253,7 +266,7 @@ def plot_line(df0,colname,collabel,ylabeltxt,titletxt,footnote,datatag=False, \
|
|
253
266
|
y1=str(round(y_end,1)) if abs(y_end) >= 100 else str(round(y_end,2)) if abs(y_end) >= 1 else str(round(y_end,3))
|
254
267
|
plt.annotate(text=' '+y1,
|
255
268
|
xy=(x_end, y_end),
|
256
|
-
xytext=(x_end, y_end),fontsize=annotate_size)
|
269
|
+
xytext=(x_end, y_end*0.998),fontsize=annotate_size,ha='left',va='center')
|
257
270
|
|
258
271
|
#是否绘制水平线
|
259
272
|
if isinstance(zeroline,bool):#若zeroline为True
|
@@ -340,13 +353,15 @@ def plot_line(df0,colname,collabel,ylabeltxt,titletxt,footnote,datatag=False, \
|
|
340
353
|
plt.fill_betweenx(yaxis_data,apa_list[0],apa_list[1],color='powderblue',alpha=0.5)
|
341
354
|
|
342
355
|
if average_value:
|
343
|
-
av=df[colname].mean()
|
344
|
-
plt.axhline(y=av,ls="dashed",c="blueviolet",linewidth=2,label=text_lang("均值","Mean"))
|
345
356
|
haveLegend=True
|
357
|
+
|
358
|
+
av=df[colname].mean()
|
346
359
|
#av=str(round(av,2)) if av < 100 else str(int(av))
|
347
|
-
av=str(int(av)) if abs(av) >= 100 else str(round(av,2)) if abs(av) >= 10 else str(round(av,3))
|
360
|
+
#av=str(int(av)) if abs(av) >= 100 else str(round(av,2)) if abs(av) >= 10 else str(round(av,3))
|
361
|
+
avstr=str(int(av)) if abs(av) >= 100 else str(round(av,2)) if abs(av) >= 10 else str(round(av,3))
|
362
|
+
plt.axhline(y=av,ls="dashed",c="blueviolet",linewidth=2,label=text_lang("本期间均值","Periodic mean")+avstr)
|
348
363
|
#footnote=footnote + ",均值"+av
|
349
|
-
footnote=text_lang("注:期间均值","Note: Periodic mean ")+av+"; "+footnote
|
364
|
+
#footnote=text_lang("注:期间均值","Note: Periodic mean ")+av+"; "+footnote
|
350
365
|
|
351
366
|
#绘制趋势线
|
352
367
|
#print("--Debug(plot_line): power=",power)
|
@@ -412,7 +427,7 @@ if __name__ =="__main__":
|
|
412
427
|
twinx=False
|
413
428
|
yline=999
|
414
429
|
xline=999
|
415
|
-
resample_freq='
|
430
|
+
resample_freq='D'
|
416
431
|
|
417
432
|
def plot_line2(df1,ticker1,colname1,label1, \
|
418
433
|
df2,ticker2,colname2,label2, \
|
@@ -421,7 +436,7 @@ def plot_line2(df1,ticker1,colname1,label1, \
|
|
421
436
|
zeroline=False,twinx=False, \
|
422
437
|
yline=999,attention_value_area='', \
|
423
438
|
xline=999,attention_point_area='', \
|
424
|
-
resample_freq='
|
439
|
+
resample_freq='D',loc1='best',loc2='best', \
|
425
440
|
color1='red',color2='blue',facecolor='whitesmoke', \
|
426
441
|
maxticks=20):
|
427
442
|
"""
|
@@ -480,7 +495,7 @@ def plot2_line2(df1,ticker1,colname1,label1, \
|
|
480
495
|
zeroline=False,twinx=False, \
|
481
496
|
yline=999,attention_value_area='', \
|
482
497
|
xline=999,attention_point_area='', \
|
483
|
-
resample_freq='
|
498
|
+
resample_freq='D',loc1='best',loc2='best', \
|
484
499
|
date_range=False,date_freq=False,date_fmt='%Y-%m-%d', \
|
485
500
|
color1='red',color2='blue',facecolor='whitesmoke', \
|
486
501
|
maxticks=20):
|
@@ -547,7 +562,7 @@ def plot_line2_coaxial(df01,ticker1,colname1,label1, \
|
|
547
562
|
power=0,datatag1=False,datatag2=False,zeroline=False, \
|
548
563
|
yline=999,attention_value_area='', \
|
549
564
|
xline=999,attention_point_area='', \
|
550
|
-
resample_freq='
|
565
|
+
resample_freq='D', \
|
551
566
|
loc1='best',loc2='best', \
|
552
567
|
color1='red',color2='blue',facecolor='whitesmoke', \
|
553
568
|
ticker_type='auto',maxticks=15):
|
@@ -760,7 +775,10 @@ def plot_line2_coaxial(df01,ticker1,colname1,label1, \
|
|
760
775
|
|
761
776
|
# 使用 AutoDateLocator 自动选择最佳间隔,目的是显示最后一个日期,亲测有效!!!
|
762
777
|
import matplotlib.dates as mdates
|
763
|
-
|
778
|
+
try:
|
779
|
+
ax.xaxis.set_major_locator(mdates.AutoDateLocator(maxticks=maxticks))
|
780
|
+
except:
|
781
|
+
pass
|
764
782
|
|
765
783
|
plt.gcf().autofmt_xdate(ha="center") # 优化标注(自动倾斜)
|
766
784
|
try:
|
@@ -802,7 +820,7 @@ def plot_line2_coaxial2(df01,ticker1,colname1,label1, \
|
|
802
820
|
power=0,datatag1=False,datatag2=False,zeroline=False, \
|
803
821
|
yline=999,attention_value_area='', \
|
804
822
|
xline=999,attention_point_area='', \
|
805
|
-
resample_freq='
|
823
|
+
resample_freq='D', \
|
806
824
|
loc1='best',loc2='best', \
|
807
825
|
date_range=False,date_freq=False,date_fmt='%Y-%m-%d', \
|
808
826
|
color1='red',color2='blue',facecolor='whitesmoke', \
|
@@ -1060,7 +1078,7 @@ def plot_line2_coaxial2(df01,ticker1,colname1,label1, \
|
|
1060
1078
|
def plot_line2_twinx(df01,ticker1,colname1,label1, \
|
1061
1079
|
df02,ticker2,colname2,label2, \
|
1062
1080
|
titletxt,footnote,power=0,datatag1=False,datatag2=False, \
|
1063
|
-
resample_freq='
|
1081
|
+
resample_freq='D', \
|
1064
1082
|
xline=999,attention_point_area='', \
|
1065
1083
|
loc1='upper left',loc2='lower left', \
|
1066
1084
|
color1='red',color2='blue',facecolor='whitesmoke', \
|
@@ -1289,7 +1307,7 @@ def plot_line2_twinx2(df01,ticker1,colname1,label1, \
|
|
1289
1307
|
df02,ticker2,colname2,label2, \
|
1290
1308
|
titletxt,footnote,power=0,datatag1=False,datatag2=False, \
|
1291
1309
|
xline=999,attention_point_area='', \
|
1292
|
-
resample_freq='
|
1310
|
+
resample_freq='D',loc1='upper left',loc2='lower left', \
|
1293
1311
|
date_range=False,date_freq=False,date_fmt='%Y-%m-%d', \
|
1294
1312
|
color1='red',color2='blue',facecolor='whitesmoke', \
|
1295
1313
|
ticker_type='auto', \
|
@@ -1532,7 +1550,7 @@ if __name__ =="__main__":
|
|
1532
1550
|
axhline_value=0; axhline_label=''
|
1533
1551
|
title_txt='Title'
|
1534
1552
|
data_label=False
|
1535
|
-
resample_freq='
|
1553
|
+
resample_freq='D'; smooth=True
|
1536
1554
|
linewidth=1.5
|
1537
1555
|
loc='best'
|
1538
1556
|
annotate=True; annotate_value=True
|
@@ -1545,12 +1563,12 @@ if __name__ =="__main__":
|
|
1545
1563
|
|
1546
1564
|
|
1547
1565
|
def draw_lines(df0,y_label,x_label,axhline_value,axhline_label,title_txt, \
|
1548
|
-
data_label=
|
1566
|
+
data_label=False,resample_freq='D',smooth=False,linewidth=1.5, \
|
1549
1567
|
band_area='',loc='best', \
|
1550
1568
|
annotate=False,annotate_value=False,plus_sign=False, \
|
1551
1569
|
attention_value='',attention_value_area='', \
|
1552
1570
|
attention_point='',attention_point_area='', \
|
1553
|
-
mark_top=False,mark_bottom=False,mark_end=False, \
|
1571
|
+
mark_start=False,mark_top=False,mark_bottom=False,mark_end=False, \
|
1554
1572
|
ticker_type='auto',facecolor='whitesmoke', \
|
1555
1573
|
maxticks_enable=True,maxticks=15, \
|
1556
1574
|
translate=False):
|
@@ -1738,6 +1756,19 @@ def draw_lines(df0,y_label,x_label,axhline_value,axhline_label,title_txt, \
|
|
1738
1756
|
plt.text(x,y1,s % y,ha='right',va='bottom',color=last_line_color)
|
1739
1757
|
plt.scatter(x,y, color='seagreen',marker='8',s=70)
|
1740
1758
|
|
1759
|
+
#标记曲线开始数值
|
1760
|
+
if mark_start and (c not in ["平均值","中位数"]):
|
1761
|
+
df_end=dfg.head(1)
|
1762
|
+
y_end = df_end[c].min() # 开始的y坐标
|
1763
|
+
x_end = df_end[c].idxmin() # 开始值的x坐标
|
1764
|
+
|
1765
|
+
#y1=str(int(y_end)) if y_end >= 100 else str(round(y_end,2))
|
1766
|
+
y1=str(round(y_end,1)) if abs(y_end) >= 100 else str(round(y_end,2)) if abs(y_end) >= 1 else str(round(y_end,3))
|
1767
|
+
plt.annotate(text=' '+y1,
|
1768
|
+
xy=(x_end, y_end),
|
1769
|
+
xytext=(x_end, y_end*0.998),fontsize=annotate_size,
|
1770
|
+
color=last_line_color,ha='right',va='center')
|
1771
|
+
|
1741
1772
|
#标记曲线末端数值
|
1742
1773
|
if mark_end and (c not in ["平均值","中位数"]):
|
1743
1774
|
df_end=dfg.tail(1)
|
@@ -1748,8 +1779,8 @@ def draw_lines(df0,y_label,x_label,axhline_value,axhline_label,title_txt, \
|
|
1748
1779
|
y1=str(round(y_end,1)) if abs(y_end) >= 100 else str(round(y_end,2)) if abs(y_end) >= 1 else str(round(y_end,3))
|
1749
1780
|
plt.annotate(text=' '+y1,
|
1750
1781
|
xy=(x_end, y_end),
|
1751
|
-
xytext=(x_end, y_end),fontsize=annotate_size,
|
1752
|
-
color=last_line_color)
|
1782
|
+
xytext=(x_end, y_end*0.998),fontsize=annotate_size,
|
1783
|
+
color=last_line_color,ha='left',va='center')
|
1753
1784
|
|
1754
1785
|
#用于关注值的颜色列表
|
1755
1786
|
atv_color_list=["lightgray","paleturquoise","wheat","khaki","lightsage","hotpink","mediumslateblue"]
|
@@ -1950,7 +1981,7 @@ def draw_lines2(df0,y_label,x_label,axhline_value,axhline_label,title_txt, \
|
|
1950
1981
|
#指定两个横轴之间的区域
|
1951
1982
|
attention_point_area='', \
|
1952
1983
|
annotate=False,annotate_value=False, \
|
1953
|
-
mark_top=False,mark_bottom=False,mark_end=False, \
|
1984
|
+
mark_start=False,mark_top=False,mark_bottom=False,mark_end=False, \
|
1954
1985
|
facecolor='whitesmoke',maxticks=20,translate=False):
|
1955
1986
|
"""
|
1956
1987
|
函数功能:根据df的内容绘制折线图
|
@@ -1973,6 +2004,7 @@ def draw_lines2(df0,y_label,x_label,axhline_value,axhline_label,title_txt, \
|
|
1973
2004
|
band_area='':默认为空,否则为列表,第1个值为带状区域上边沿字段,第2个值为带状区域下边沿字段
|
1974
2005
|
"""
|
1975
2006
|
import pandas as pd
|
2007
|
+
|
1976
2008
|
DEBUG=False
|
1977
2009
|
if DEBUG:
|
1978
2010
|
print(f"band_area={band_area}")
|
@@ -2115,6 +2147,19 @@ def draw_lines2(df0,y_label,x_label,axhline_value,axhline_label,title_txt, \
|
|
2115
2147
|
xy=(x_end, y_end),
|
2116
2148
|
xytext=(x_end, y_end),fontsize=annotate_size,
|
2117
2149
|
color=last_line_color)
|
2150
|
+
|
2151
|
+
#标记曲线开始数值
|
2152
|
+
if mark_start:
|
2153
|
+
df_start=df.head(1)
|
2154
|
+
y_start = df_start[c].min() # 开始的y坐标
|
2155
|
+
x_start = df_start[c].idxmin() # 开始值的x坐标
|
2156
|
+
|
2157
|
+
#y1=str(int(y_end)) if y_end >= 100 else str(round(y_end,2))
|
2158
|
+
y1=str(round(y_start,1)) if abs(y_start) >= 100 else str(round(y_start,2)) if abs(y_start) >= 1 else str(round(y_start,3))
|
2159
|
+
plt.annotate(text=y1,
|
2160
|
+
xy=(x_start, y_start),
|
2161
|
+
xytext=(x_start, y_start*0.998),fontsize=annotate_size,ha='right',va='center')
|
2162
|
+
# 特别注意:这里的left/right与实际图示的方向正好相反!!!
|
2118
2163
|
|
2119
2164
|
#处理布林带的mark_end,仅标记上中下线
|
2120
2165
|
if mark_end & (c in collist3):
|
@@ -2395,7 +2440,7 @@ if __name__=='__main__':
|
|
2395
2440
|
#==============================================================================
|
2396
2441
|
def plot_2lines(df01,colname1,label1, \
|
2397
2442
|
df02,colname2,label2, \
|
2398
|
-
ylabeltxt,titletxt,footnote,hline=0,vline=0,resample_freq='
|
2443
|
+
ylabeltxt,titletxt,footnote,hline=0,vline=0,resample_freq='D', \
|
2399
2444
|
date_range=False,date_freq=False,date_fmt='%Y-%m-%d', \
|
2400
2445
|
facecolor='whitesmoke', \
|
2401
2446
|
maxticks=15):
|
@@ -2584,7 +2629,7 @@ def df_smooth(df):
|
|
2584
2629
|
|
2585
2630
|
|
2586
2631
|
#==============================================================================
|
2587
|
-
def df_smooth_manual(df,method='linear',resample_freq='
|
2632
|
+
def df_smooth_manual(df,method='linear',resample_freq='D',order=3):
|
2588
2633
|
"""
|
2589
2634
|
功能:对df中的第一个数值列样本进行插值,以便绘制的折线图相对平滑。
|
2590
2635
|
要求:df的索引为pandas的datetime日期型
|
siat/valuation_china.py
CHANGED
@@ -182,6 +182,293 @@ if __name__ =="__main__":
|
|
182
182
|
df=get_valuation_market_china(start,end,measure='pe',method='lyr',value='value',statistic='median')
|
183
183
|
|
184
184
|
#==============================================================================
|
185
|
+
if __name__ =="__main__":
|
186
|
+
start='2024-1-1'; end='2025-3-31'
|
187
|
+
indicator='pe'
|
188
|
+
method='ttm'
|
189
|
+
value='value'
|
190
|
+
statistic='median'
|
191
|
+
|
192
|
+
indicator=['pb','pe']
|
193
|
+
method=['lyr','ttm']
|
194
|
+
value=['value','quantile']
|
195
|
+
statistic=['median','equal-weighted']
|
196
|
+
|
197
|
+
twinx=False; loc1='best'; loc2='best'
|
198
|
+
power=0; twinx=False; average_value=True
|
199
|
+
annotate=False; annotate_value=False; plus_sign=True
|
200
|
+
mark_top=False; mark_bottom=False; mark_end=False
|
201
|
+
|
202
|
+
loc1='upper left'; loc2='lower right'
|
203
|
+
facecolor='whitesmoke'; maxticks=20
|
204
|
+
|
205
|
+
|
206
|
+
|
207
|
+
def valuation_china(start='MRY',end='today',indicator='pe', \
|
208
|
+
method='lyr',value='value',statistic='median', \
|
209
|
+
average_value=False,show_index=False, \
|
210
|
+
power=0,twinx=False, \
|
211
|
+
|
212
|
+
band_area='', \
|
213
|
+
attention_value='',attention_value_area='', \
|
214
|
+
attention_point='',attention_point_area='', \
|
215
|
+
|
216
|
+
annotate=False,annotate_value=False,plus_sign=True, \
|
217
|
+
mark_start=False,mark_top=False,mark_bottom=False,mark_end=False, \
|
218
|
+
|
219
|
+
loc1='upper left',loc2='lower right', \
|
220
|
+
facecolor='whitesmoke', \
|
221
|
+
maxticks=20):
|
222
|
+
"""
|
223
|
+
===========================================================================
|
224
|
+
功能:比较中国全A股市场的估值指标变化趋势
|
225
|
+
start: 开始日期,格式YYYY-MM-DD。
|
226
|
+
或者简写版,例如'MRY'近1年、'L3Y'表示近3年等。
|
227
|
+
end: 结束日期,默认今天。
|
228
|
+
|
229
|
+
indicator: 估值指标市盈率'pe'或市净率'pb',或其组合。不支持股息率
|
230
|
+
method: 滚动'ttm或静态取样'lyr',或其组合
|
231
|
+
value: 直接采用估值指标数值'value'或分位数'quantile',或其组合
|
232
|
+
statistic: 采用中位数'median'或等权均值'equal-weighted',或其组合
|
233
|
+
twinx:是否使用双轴绘图法,默认否False。
|
234
|
+
如果同时选择了市盈率'pe'或市净率'pb',建议打开该选项True。
|
235
|
+
loc1/loc2:图例1/2的位置,默认自动决定'best'。
|
236
|
+
如果自动位置不理想,可以手动设置位置。
|
237
|
+
"""
|
238
|
+
print(" Working on valuating China stock market ... ...")
|
239
|
+
|
240
|
+
import pandas as pd
|
241
|
+
#处理日期
|
242
|
+
start,end=start_end_preprocess(start,end)
|
243
|
+
|
244
|
+
# 情形1:双indicator:双指标,PE+PB
|
245
|
+
if isinstance(indicator,list) and len(indicator) >= 2:
|
246
|
+
indicator=indicator[:2]
|
247
|
+
if isinstance(method,list): method=method[0]
|
248
|
+
|
249
|
+
if isinstance(value,list): value=value[0]
|
250
|
+
if isinstance(statistic,list): statistic=statistic[0]
|
251
|
+
|
252
|
+
df=None
|
253
|
+
for i in indicator:
|
254
|
+
if 'pb' != i.lower():
|
255
|
+
dftmp=get_valuation_market_china(start,end,measure=i.lower(), \
|
256
|
+
method=method, \
|
257
|
+
value=value,statistic=statistic)
|
258
|
+
else:
|
259
|
+
# pb不支持ttm
|
260
|
+
dftmp=get_valuation_market_china(start,end,measure=i.lower(), \
|
261
|
+
method='lyr', \
|
262
|
+
value=value,statistic=statistic)
|
263
|
+
|
264
|
+
val_desc=dftmp['desc'].values[0]
|
265
|
+
method_desc=dftmp['method'].values[0]
|
266
|
+
"""
|
267
|
+
if method_desc == 'lyr': val_desc=val_desc+'静态'
|
268
|
+
elif method_desc == 'ttm':
|
269
|
+
#val_desc=val_desc+'动态'
|
270
|
+
val_desc=val_desc
|
271
|
+
if value == 'value': val_desc=val_desc+'数值'
|
272
|
+
elif value == 'quantile': val_desc=val_desc+'分位数'
|
273
|
+
"""
|
274
|
+
dftmp[val_desc]=dftmp['field']
|
275
|
+
dftmp2=dftmp[[val_desc]]
|
276
|
+
|
277
|
+
if df is None:
|
278
|
+
df=dftmp2
|
279
|
+
else:
|
280
|
+
df=pd.merge(df,dftmp2,left_index=True,right_index=True)
|
281
|
+
|
282
|
+
# 情形2:单indicator+双method:ttm+lyr(仅适用于pe;pb仅适用lyr);
|
283
|
+
elif isinstance(method,list) and len(method) >= 2:
|
284
|
+
method=method[:2]
|
285
|
+
if isinstance(indicator,list): indicator=indicator[0]
|
286
|
+
|
287
|
+
if isinstance(value,list): value=value[0]
|
288
|
+
if isinstance(statistic,list): statistic=statistic[0]
|
289
|
+
|
290
|
+
df=None
|
291
|
+
for i in method:
|
292
|
+
if (indicator.lower() == 'pe') or \
|
293
|
+
(indicator.lower() == 'pb' and i.lower() == 'lyr'):
|
294
|
+
dftmp=get_valuation_market_china(start,end,measure=indicator.lower(), \
|
295
|
+
method=i.lower(), \
|
296
|
+
value=value,statistic=statistic)
|
297
|
+
|
298
|
+
val_desc=dftmp['desc'].values[0]
|
299
|
+
method_desc=dftmp['method'].values[0]
|
300
|
+
"""
|
301
|
+
if method_desc == 'lyr': val_desc=val_desc+'静态'
|
302
|
+
elif method_desc == 'ttm':
|
303
|
+
#val_desc=val_desc+'动态'
|
304
|
+
val_desc=val_desc
|
305
|
+
if value == 'value': val_desc=val_desc+'数值'
|
306
|
+
elif value == 'quantile': val_desc=val_desc+'分位数'
|
307
|
+
"""
|
308
|
+
dftmp[val_desc]=dftmp['field']
|
309
|
+
dftmp2=dftmp[[val_desc]]
|
310
|
+
|
311
|
+
if df is None:
|
312
|
+
df=dftmp2
|
313
|
+
else:
|
314
|
+
df=pd.merge(df,dftmp2,left_index=True,right_index=True)
|
315
|
+
|
316
|
+
# 情形3:单indicator+单method+双value;
|
317
|
+
elif isinstance(value,list) and len(value) >= 2:
|
318
|
+
value=value[:2]
|
319
|
+
if isinstance(indicator,list): indicator=indicator[0]
|
320
|
+
if isinstance(method,list): method=method[0]
|
321
|
+
if indicator == 'pb': method='lyr'
|
322
|
+
|
323
|
+
if isinstance(statistic,list): statistic=statistic[0]
|
324
|
+
|
325
|
+
df=None
|
326
|
+
for i in value:
|
327
|
+
dftmp=get_valuation_market_china(start,end,measure=indicator.lower(), \
|
328
|
+
method=method.lower(), \
|
329
|
+
value=i.lower(),statistic=statistic)
|
330
|
+
|
331
|
+
val_desc=dftmp['desc'].values[0]
|
332
|
+
method_desc=dftmp['method'].values[0]
|
333
|
+
"""
|
334
|
+
if method_desc == 'lyr': val_desc=val_desc+'静态'
|
335
|
+
elif method_desc == 'ttm':
|
336
|
+
#val_desc=val_desc+'动态'
|
337
|
+
val_desc=val_desc
|
338
|
+
if value == 'value': val_desc=val_desc+'数值'
|
339
|
+
elif value == 'quantile': val_desc=val_desc+'分位数'
|
340
|
+
"""
|
341
|
+
dftmp[val_desc]=dftmp['field']
|
342
|
+
dftmp2=dftmp[[val_desc]]
|
343
|
+
|
344
|
+
if df is None:
|
345
|
+
df=dftmp2
|
346
|
+
else:
|
347
|
+
df=pd.merge(df,dftmp2,left_index=True,right_index=True)
|
348
|
+
|
349
|
+
# 数值与分位数差距较大,使用twinx=True
|
350
|
+
twinx=True
|
351
|
+
|
352
|
+
# 情形4:单indicator+单method+单value+双statistic;
|
353
|
+
elif isinstance(statistic,list) and len(statistic) >= 2:
|
354
|
+
statistic=statistic[:2]
|
355
|
+
if isinstance(indicator,list): indicator=indicator[0]
|
356
|
+
if isinstance(method,list): method=method[0]
|
357
|
+
if indicator == 'pb': method='lyr'
|
358
|
+
|
359
|
+
df=None
|
360
|
+
for i in statistic:
|
361
|
+
dftmp=get_valuation_market_china(start,end,measure=indicator.lower(), \
|
362
|
+
method=method.lower(), \
|
363
|
+
value=value.lower(),statistic=i.lower())
|
364
|
+
|
365
|
+
val_desc=dftmp['desc'].values[0]
|
366
|
+
method_desc=dftmp['method'].values[0]
|
367
|
+
"""
|
368
|
+
if method_desc == 'lyr': val_desc=val_desc+'静态'
|
369
|
+
elif method_desc == 'ttm':
|
370
|
+
#val_desc=val_desc+'动态'
|
371
|
+
val_desc=val_desc
|
372
|
+
if value == 'value': val_desc=val_desc+'数值'
|
373
|
+
elif value == 'quantile': val_desc=val_desc+'分位数'
|
374
|
+
"""
|
375
|
+
dftmp[val_desc]=dftmp['field']
|
376
|
+
dftmp2=dftmp[[val_desc]]
|
377
|
+
|
378
|
+
if df is None:
|
379
|
+
df=dftmp2
|
380
|
+
else:
|
381
|
+
df=pd.merge(df,dftmp2,left_index=True,right_index=True)
|
382
|
+
|
383
|
+
# 情形5:单indicator+单method+单value+单statistic;
|
384
|
+
else:
|
385
|
+
if isinstance(indicator,list): indicator=indicator[0]
|
386
|
+
if isinstance(method,list): method=method[0]
|
387
|
+
if indicator == 'pb': method='lyr'
|
388
|
+
|
389
|
+
if isinstance(value,list): value=value[0]
|
390
|
+
if isinstance(statistic,list): statistic=statistic[0]
|
391
|
+
|
392
|
+
dftmp=get_valuation_market_china(start,end,measure=indicator.lower(), \
|
393
|
+
method=method.lower(), \
|
394
|
+
value=value.lower(),statistic=statistic.lower())
|
395
|
+
|
396
|
+
val_desc=dftmp['desc'].values[0]
|
397
|
+
method_desc=dftmp['method'].values[0]
|
398
|
+
"""
|
399
|
+
if method_desc == 'lyr': val_desc=val_desc+'静态'
|
400
|
+
elif method_desc == 'ttm':
|
401
|
+
#val_desc=val_desc+'动态'
|
402
|
+
val_desc=val_desc
|
403
|
+
if value == 'value': val_desc=val_desc+'数值'
|
404
|
+
elif value == 'quantile': val_desc=val_desc+'分位数'
|
405
|
+
"""
|
406
|
+
dftmp[val_desc]=dftmp['field']
|
407
|
+
if show_index:
|
408
|
+
index_desc=dftmp['index name'].values[0]
|
409
|
+
dftmp[index_desc]=dftmp['index']
|
410
|
+
df=dftmp[[val_desc,index_desc]]
|
411
|
+
|
412
|
+
# 指数与指标差异大,设定twinx=True
|
413
|
+
twinx=True
|
414
|
+
else:
|
415
|
+
df=dftmp[[val_desc]]
|
416
|
+
|
417
|
+
# 绘图
|
418
|
+
import datetime; todaydt = datetime.date.today()
|
419
|
+
sourcetxt=text_lang("数据来源:legulegu","Data source: legulegu")
|
420
|
+
footnote=sourcetxt+', '+str(todaydt)
|
421
|
+
|
422
|
+
if show_index:
|
423
|
+
# 显示股票市场指数
|
424
|
+
twinx=True
|
425
|
+
|
426
|
+
titletxt=text_lang("中国A股市场估值趋势","China A-share Market Valuation")
|
427
|
+
ylabeltxt=text_lang("估值指标","Valuation Indicator")
|
428
|
+
|
429
|
+
if len(list(df)) == 1:
|
430
|
+
colname=collabel=list(df)[0]
|
431
|
+
#titletxt=titletxt+': '+colname
|
432
|
+
ylabeltxt=colname
|
433
|
+
plot_line(df,colname,collabel,ylabeltxt,titletxt,footnote, \
|
434
|
+
power=power, \
|
435
|
+
attention_value=attention_value,attention_value_area=attention_value_area, \
|
436
|
+
attention_point=attention_point,attention_point_area=attention_point_area, \
|
437
|
+
average_value=average_value, \
|
438
|
+
|
439
|
+
loc=loc1, \
|
440
|
+
mark_start=True,mark_top=True,mark_bottom=True,mark_end=mark_end, \
|
441
|
+
facecolor=facecolor,maxticks=maxticks)
|
442
|
+
|
443
|
+
elif twinx and len(list(df)) >= 2:
|
444
|
+
ticker1=ticker2=''
|
445
|
+
colname1=label1=list(df)[0]; df1=df[[colname1]]
|
446
|
+
colname2=label2=list(df)[1]; df2=df[[colname2]]
|
447
|
+
|
448
|
+
plot_line2(df1,ticker1,colname1,label1, \
|
449
|
+
df2,ticker2,colname2,label2, \
|
450
|
+
ylabeltxt,titletxt,footnote, \
|
451
|
+
power=power,datatag1=False,datatag2=False,yscalemax=5, \
|
452
|
+
zeroline=False,twinx=twinx, \
|
453
|
+
yline=999,attention_value_area='', \
|
454
|
+
xline=999,attention_point_area='', \
|
455
|
+
resample_freq='H',loc1=loc1,loc2=loc2, \
|
456
|
+
color1='red',color2='blue',facecolor='whitesmoke', \
|
457
|
+
maxticks=maxticks)
|
458
|
+
else:
|
459
|
+
x_label=footnote
|
460
|
+
axhline_value=0; axhline_label=''
|
461
|
+
draw_lines(df,ylabeltxt,x_label,axhline_value,axhline_label,titletxt, \
|
462
|
+
band_area=band_area,loc=loc1, \
|
463
|
+
attention_value=attention_value,attention_value_area=attention_value_area, \
|
464
|
+
attention_point=attention_point,attention_point_area=attention_point_area, \
|
465
|
+
annotate=annotate,annotate_value=annotate_value,plus_sign=False, \
|
466
|
+
mark_top=mark_top,mark_bottom=mark_bottom,mark_end=mark_end, \
|
467
|
+
facecolor=facecolor,maxticks_enable=True,maxticks=maxticks)
|
468
|
+
|
469
|
+
return df
|
470
|
+
|
471
|
+
|
185
472
|
if __name__ =="__main__":
|
186
473
|
start='2020-1-1'; end='2022-10-9'
|
187
474
|
measures=['pb','pe']; methods='lyr'; values='value'; statistics='median'
|
@@ -261,7 +548,7 @@ def valuation_market_china(start='MRY',end='today',measures=['pe','pb'], \
|
|
261
548
|
|
262
549
|
import datetime
|
263
550
|
today = datetime.date.today()
|
264
|
-
footnote="数据来源:
|
551
|
+
footnote="数据来源: legulegu,"+str(today)
|
265
552
|
|
266
553
|
#获取指标1
|
267
554
|
df1=get_valuation_market_china(start,end,measure=measures1,method=methods1,value=values1,statistic=statistics1)
|
@@ -1,6 +1,6 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.2
|
2
2
|
Name: siat
|
3
|
-
Version: 3.8.
|
3
|
+
Version: 3.8.30
|
4
4
|
Summary: Securities Investment Analysis Tools (siat)
|
5
5
|
Home-page: https://pypi.org/project/siat/
|
6
6
|
Author: Prof. WANG Dehong, International Business School, Beijing Foreign Studies University
|
@@ -40,6 +40,14 @@ Requires-Dist: translators
|
|
40
40
|
Requires-Dist: nbconvert
|
41
41
|
Requires-Dist: ipywidgets
|
42
42
|
Requires-Dist: playwright
|
43
|
+
Dynamic: author
|
44
|
+
Dynamic: author-email
|
45
|
+
Dynamic: description
|
46
|
+
Dynamic: description-content-type
|
47
|
+
Dynamic: home-page
|
48
|
+
Dynamic: license
|
49
|
+
Dynamic: requires-dist
|
50
|
+
Dynamic: summary
|
43
51
|
|
44
52
|
|
45
53
|
# What is siat?
|
@@ -30,7 +30,7 @@ siat/cryptocurrency_test.py,sha256=3AikTNJ7j-HwLGLIYEfyXZ3bLVuLeru9mwiwHQi2SdA,2
|
|
30
30
|
siat/derivative.py,sha256=qV8n09799eqLc26ojR6vN5n_X-xd7rGwdYjgq-wBih8,41483
|
31
31
|
siat/economy-20230125.py,sha256=vxZZlPnLkh7SpGMVEPLwxjt0yYLSVmdZrO-s2NYLyoM,73848
|
32
32
|
siat/economy.py,sha256=BFVQDxOTbuizyumpCgpZIauH6sqnwUXebpqRMmQCzys,84198
|
33
|
-
siat/economy2.py,sha256=
|
33
|
+
siat/economy2.py,sha256=tdfbDXfv_rI4FjeQEgMwcKnoGNRL_1U2vkrnAPgRmAs,81019
|
34
34
|
siat/economy_test.py,sha256=6vjNlPz7W125pJb7simCddobSEp3jmLIMvVkLRZ7zW8,13339
|
35
35
|
siat/esg.py,sha256=GMhaonIKtvOK83rhpQUH5aJt2OL3HQBSVfD__Yw-0oo,19040
|
36
36
|
siat/esg_test.py,sha256=Z9m6GUt8O7oHZSEG9aDYpGdvvrv2AiRJdHTiU6jqmZ0,2944
|
@@ -64,7 +64,7 @@ siat/future_china.py,sha256=F-HsIf2Op8Z22RzTjet1g8COzldgnMjFNSXsAkeGyWo,17595
|
|
64
64
|
siat/future_china_test.py,sha256=BrSzmDVaOHki6rntOtosmRn-6dkfOBuLulJNqh7MOpc,1163
|
65
65
|
siat/global_index_test.py,sha256=hnFp3wqqzzL-kAP8mgxDZ54Bd5Ijf6ENi5YJlGBgcXw,2402
|
66
66
|
siat/google_authenticator.py,sha256=ZUbZR8OW0IAKDbcYtlqGqIpZdERpFor9NccFELxg9yI,1637
|
67
|
-
siat/grafix.py,sha256=
|
67
|
+
siat/grafix.py,sha256=MIaNkxxt_n9zoYafsidPhn9xdX0rwjKHbbsNMhkYj0Q,119901
|
68
68
|
siat/grafix_test.py,sha256=kXvcpLgQNO7wd30g_bWljLj5UH7bIVI0_dUtXbfiKR0,3150
|
69
69
|
siat/holding_risk.py,sha256=uWRtMMJqKr-puQn26g6Fq5N3mFB70c0B99zLQug8hAo,30774
|
70
70
|
siat/holding_risk_test.py,sha256=FRlw_9wFG98BYcg_cSj95HX5WZ1TvkGaOUdXD7-V86s,474
|
@@ -140,12 +140,12 @@ siat/translate_20240606.py,sha256=63IyHWEU3Uz9mjwyuAX3fqY4nUMdwh0ICQAgmgPXP7Y,21
|
|
140
140
|
siat/translate_241003_keep.py,sha256=un7Fqe1v35MXsja5exZgjmLzrZtt66NARZIGlyFuGGU,218747
|
141
141
|
siat/universal_test.py,sha256=CDAOffW1Rvs-TcNN5giWVvHMlch1w4dp-w5SIV9jXL0,3936
|
142
142
|
siat/valuation.py,sha256=K7epQC_UtELjRR5cyjJp4gskSyJMxXy-jHIAS0SUEj8,51801
|
143
|
-
siat/valuation_china.py,sha256=
|
143
|
+
siat/valuation_china.py,sha256=DURa9uplp7B9tgjWvEQVTRQPqFNpRGWnLdTXQHePrB0,83115
|
144
144
|
siat/valuation_market_china_test.py,sha256=gbJ0ioauuo4koTPH6WKUkqcXiQPafnbhU5eKJ6lpdLA,1571
|
145
145
|
siat/var_model_validation.py,sha256=R0caWnuZarrRg9939hxh3vJIIpIyPfvelYmzFNZtPbo,14910
|
146
146
|
siat/yf_name.py,sha256=laNKMTZ9hdenGX3IZ7G0a2RLBKEWtUQJFY9CWuk_fp8,24058
|
147
|
-
siat-3.8.
|
148
|
-
siat-3.8.
|
149
|
-
siat-3.8.
|
150
|
-
siat-3.8.
|
151
|
-
siat-3.8.
|
147
|
+
siat-3.8.30.dist-info/LICENSE,sha256=NTEMMROY9_4U1szoKC3N2BLHcDd_o5uTgqdVH8tbApw,1071
|
148
|
+
siat-3.8.30.dist-info/METADATA,sha256=VTBGp1ahs79HhChoP4vHnzBxdz2PAELL72yzNp4XYI0,8321
|
149
|
+
siat-3.8.30.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
150
|
+
siat-3.8.30.dist-info/top_level.txt,sha256=r1cVyL7AIKqeAmEJjNR8FMT20OmEzufDstC2gv3NvEY,5
|
151
|
+
siat-3.8.30.dist-info/RECORD,,
|
File without changes
|
File without changes
|