siat 2.11.13__py3-none-any.whl → 2.11.19__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/market_china.py CHANGED
@@ -773,15 +773,16 @@ def market_detail_china(category='price',prettytab=True,plttab=False, \
773
773
 
774
774
  print(heading,"信息来源:东方财富,","统计时间:",nowstr)
775
775
  print(heading,"注释:")
776
+ print(heading,"☆可交易股票数量:将随着股票停复牌情况变化")
776
777
  print(heading,"☆昨日指的是上一个交易日")
777
- print(heading,"☆使用实时数据,不同日期/每天不同时刻统计的结果可能不同")
778
- print(heading,"☆若在非开市时间或开市前后短期内统计,部分结果数据可能出现空缺")
779
778
  print(heading,"☆涨速:平均每分钟股价变化率,表示股价变化速度")
779
+ print(heading,"☆5分钟涨跌:最新5分钟内股价的涨跌幅度")
780
780
  print(heading,"☆振幅:最高最低价差绝对值/昨收,表示股价变化活跃程度")
781
781
  print(heading,"☆涨跌幅:(最新价-昨收)/昨收,表示相对昨日的变化程度")
782
782
  print(heading,"☆涨跌额:最新价-昨收,表示相对昨日的变化金额")
783
- print(heading,"☆5分钟涨跌:最新5分钟内股价的涨跌幅度")
784
- print(heading,"☆可交易股票数量:将随着股票停复牌情况变化")
783
+
784
+ print(heading,"☆使用实时数据,不同日期/每天不同时刻统计的结果可能不同")
785
+ print(heading,"☆若在非开市时间或开市前后短期内统计,部分结果数据可能出现空缺")
785
786
 
786
787
  if category1=='VOLUME':
787
788
  titletxt="中国三大股票交易所横向对比:成交状况"
@@ -793,14 +794,14 @@ def market_detail_china(category='price',prettytab=True,plttab=False, \
793
794
 
794
795
  print(heading,"信息来源:东方财富,","统计时间:",nowstr)
795
796
  print(heading,"注:")
796
- print(heading,"☆昨日指的是上一个交易日")
797
- print(heading,"☆使用实时数据,不同日期/每天不同时刻统计的结果可能不同")
798
- print(heading,"☆若在非开市时间或开市前后短期内统计,部分结果数据可能出现空缺")
799
- print(heading,"☆量比:当前平均每分钟成交量与过去5个交易日均值之比,表示当前成交量的变化")
797
+ print(heading,"☆可交易股票数量:将随着股票停复牌情况变化")
800
798
  print(heading,"☆成交量:当前成交股数,表示交易活跃度")
801
- print(heading,"☆换手率:成交量/流通股数,表示成交量占比")
802
799
  print(heading,"☆成交额:当前开市后的累计成交金额")
803
- print(heading,"☆可交易股票数量:将随着股票停复牌情况变化")
800
+ print(heading,"☆换手率:成交量/流通股数,表示成交量占比")
801
+ print(heading,"☆量比:当前平均每分钟成交量与过去5个交易日均值之比,表示当前成交量的变化")
802
+
803
+ print(heading,"☆使用实时数据,不同日期/每天不同时刻统计的结果可能不同")
804
+ print(heading,"☆若在非开市时间或开市前后短期内统计,部分结果数据可能出现空缺")
804
805
 
805
806
  if category1=='RETURN':
806
807
  titletxt="中国三大股票交易所横向对比:投资回报"
@@ -812,12 +813,12 @@ def market_detail_china(category='price',prettytab=True,plttab=False, \
812
813
 
813
814
  print(heading,"信息来源:东方财富,","统计时间:",nowstr)
814
815
  print(heading,"注:")
815
- print(heading,"☆昨日指的是上一个交易日")
816
+ print(heading,"☆可交易股票数量:将随着股票停复牌情况变化")
817
+ print(heading,"☆MRQ:最近一个季度的滚动数据")
818
+ print(heading,"☆YTD:今年以来的累计情况")
819
+
816
820
  print(heading,"☆使用实时数据,不同日期/每天不同时刻统计的结果可能不同")
817
821
  print(heading,"☆若在非开市时间或开市前后短期内统计,部分结果数据可能出现空缺")
818
- print(heading,"☆MRQ:最近一个季度,即最近60个交易日")
819
- print(heading,"☆YTD:今年以来的累计情况")
820
- print(heading,"☆可交易股票数量:将随着股票停复牌情况变化")
821
822
 
822
823
  if category1=='VALUATION':
823
824
  titletxt="中国三大股票交易所横向对比:市值与估值"
@@ -829,13 +830,13 @@ def market_detail_china(category='price',prettytab=True,plttab=False, \
829
830
 
830
831
  print(heading,"信息来源:东方财富,","统计时间:",nowstr)
831
832
  print(heading,"注:")
832
- print(heading,"☆昨日指的是上一个交易日")
833
+ print(heading,"☆可交易股票数量:将随着股票停复牌情况变化")
834
+ print(heading,"☆市盈率:这里为动态市盈率,即市盈率TTM,过去12个月的连续变化")
835
+ print(heading,"☆市净率:这里为静态市净率")
836
+
833
837
  print(heading,"☆使用实时数据,不同日期/每天不同时刻统计的结果可能不同")
834
838
  print(heading,"☆若在非开市时间或开市前后短期内统计,部分结果数据可能出现空缺")
835
839
  #print(heading,"☆标准差/均值=标准差(数值)/均值,提升可比性")
836
- print(heading,"☆市净率:这里为静态市盈率,按季/中/年报计算")
837
- print(heading,"☆市盈率:这里为动态市盈率,即市盈率TTM,过去12个月的连续变化")
838
- print(heading,"☆可交易股票数量:将随着股票停复牌情况变化")
839
840
 
840
841
  return df
841
842
 
siat/translate.py CHANGED
@@ -1023,10 +1023,12 @@ def codetranslate0(code):
1023
1023
  ['000832.SS','中证转债指数'],['399307.SZ','深证转债指数'],
1024
1024
  ['000116.SS','上证信用债指数'],['399413.SZ','国证转债综合指数'],
1025
1025
 
1026
- ['^GSPC','标普500指数'],['^DJI','道琼斯工业指数'],
1026
+ ['^GSPC','标普500指数'],['^SPX','标普500指数'],
1027
+ ['^DJI','道琼斯工业指数'],
1027
1028
  ['WISGP.SI','富时新加坡指数'], ['^STI','新加坡海峡时报指数'],
1028
1029
  ['^IXIC','纳斯达克综合指数'],['^FTSE','英国富时100指数'],
1029
- ['^N100','泛欧100指数'],['^FMIB','富时意大利指数'],
1030
+ ['^NKX','日经225指数'],['^N100','泛欧100指数'],
1031
+ ['^FMIB','富时意大利指数'],
1030
1032
  ['^TSX','多伦多综合指数'],['^MXX','墨西哥IPC指数'],
1031
1033
  ['^NDX','纳斯达克100指数'],['^BET','罗马尼亚布加勒斯特指数'],
1032
1034
  ['^BUX','匈牙利布达佩斯指数'],['^PX','捷克布拉格PX指数'],
siat/valuation.py CHANGED
@@ -22,6 +22,7 @@ from siat.translate import *
22
22
  from siat.stock import *
23
23
  from siat.security_prices import *
24
24
  from siat.sector_china import *
25
+ from siat.valuation_china import *
25
26
  from siat.grafix import *
26
27
 
27
28
  import pandas as pd
@@ -673,7 +674,7 @@ def funddb_name(code):
673
674
  ['HSCEI.HK','ESG120策略'],#中证ESG120策略指数从沪深300指数样本股中选取ESG得分较高的120只股票
674
675
  ['HSCEI.HK','恒生中国企业指数'],#中国企业以H股形式在香港联合交易所(「联交所」)上市
675
676
  ['930931.ZZ','港股通50(HKD)'],#港股通范围内的最大50家公司
676
- ['HSIII.HK','沪港深500'],#中证沪港深500指数, 沪港深交易所上市的互联互通范围内股票
677
+ ['HSIII.ZZ','沪港深500'],#中证沪港深500指数, 沪港深交易所上市的互联互通范围内股票
677
678
  ['HSIII.HK','恒生互联网科技业'],
678
679
  ['HSTECH.HK','恒生科技指数'],
679
680
  ['931637.ZZ','HKC互联网'],#中证港股通互联网指数, 港股通内互联网主题上市公司
@@ -691,6 +692,9 @@ def funddb_name(code):
691
692
  ['931468.ZZ','红利质量'],#中证红利质量指数,连续现金分红、股利支付率较高且具备较高盈利能力特征的上市公司股
692
693
  ['000922.ZZ','中证红利'],#中证红利指数以沪深A股中现金股息率高、分红比较稳定、具有一定规模及流动性的100只股票
693
694
  ['000825.ZZ','中证央企红利'],#中证中央企业红利指数,中央企业中现金股息率高、分红比较稳定、且有一定规模及流动性的30只股票
695
+ ['000969.ZZ','沪深300非周期'],
696
+ ['000821.ZZ','沪深300红利'],
697
+ ['000968.ZZ','沪深300周期'],
694
698
 
695
699
  ], columns=['eword','cword'])
696
700
 
@@ -775,7 +779,17 @@ def get_valuation(tickers,indicators,start,end):
775
779
 
776
780
  # 申万指数代码?
777
781
  if not gotit and (result and suffix in ['SW']):
778
- dft=get_index_valuation_funddb(t1,indicators1,start,end)
782
+ #dft=get_index_valuation_funddb(t1,indicators1,start,end)
783
+ indicator1=indicators1[0]
784
+ dft0=industry_valuation_history_sw(industry=t1,
785
+ start=start,end=end,
786
+ vtype=indicator1,
787
+ graph=False)
788
+ dft0[indicator1]=dft0[list(dft0)[0]]
789
+ dft0['name']=industry_sw_name(t1)
790
+ dft0['currency']=''
791
+ dft=dft0[[indicator1,'name','currency']]
792
+
779
793
  if dft is not None:
780
794
  gotit=True
781
795
  iname=industry_sw_name(t1)
@@ -809,6 +823,8 @@ def get_valuation(tickers,indicators,start,end):
809
823
  if not (df is None):
810
824
  #df.fillna(method='backfill',inplace=True)
811
825
  df.fillna(method='ffill',inplace=True)
826
+ else:
827
+ return None
812
828
 
813
829
  # 处理字段名称后面的_x/_y/_z
814
830
  df_collist=list(df)
@@ -824,6 +840,7 @@ def get_valuation(tickers,indicators,start,end):
824
840
  df1_collist=df1_collist+[cx] #列表中必须为元组
825
841
 
826
842
  df1.columns=pd.MultiIndex.from_tuples(df1_collist) #统一修改元组型列名
843
+ df1.dropna(inplace=True)
827
844
 
828
845
  return df1
829
846
 
siat/valuation_china.py CHANGED
@@ -442,24 +442,24 @@ if __name__=='__main__':
442
442
  graph=True
443
443
  loc='best'
444
444
 
445
- def industry_valuation_history_sw(industry,start,end,vtype='PE', \
445
+ def industry_valuation_history_sw_daily(industry,start,end,vtype='PE', \
446
446
  graph=True,loc='best'):
447
447
  """
448
- 功能:绘制一个申万行业的历史估值趋势
448
+ 功能:绘制一个申万行业的日历史估值趋势,不支持二级三级行业分类
449
449
  vtype: PE, PB, dividend
450
450
 
451
451
  """
452
452
  #检查日期期间
453
453
  result,start1,end1=check_period(start,end)
454
454
  if not result:
455
- print(" #Warning(industry_valuation_history_sw): invalid date period",start,end)
455
+ print(" #Warning(industry_valuation_history_sw_daily): invalid date period",start,end)
456
456
  return None
457
457
 
458
458
  #检查估值类型
459
459
  typelist=['pe','pb','dividend']
460
460
  vtypeu=vtype.lower()
461
461
  if not (vtypeu in typelist):
462
- print(" #Warning(industry_valuation_history_sw): unsupported valuation type",vtype)
462
+ print(" #Warning(industry_valuation_history_sw_daily): unsupported valuation type",vtype)
463
463
  print(" Supported types:",typelist)
464
464
  return None
465
465
 
@@ -475,7 +475,7 @@ def industry_valuation_history_sw(industry,start,end,vtype='PE', \
475
475
  # 不支持申万三级行业
476
476
  df = ak.index_value_hist_funddb(symbol=sindustry, indicator=vtypes)
477
477
  except:
478
- print(" #Warning(industry_valuation_history_sw): failed to fetch industry info for",industry)
478
+ print(" #Warning(industry_valuation_history_sw_daily): failed to fetch industry info for",industry)
479
479
  return None
480
480
 
481
481
  import pandas as pd
@@ -491,7 +491,7 @@ def industry_valuation_history_sw(industry,start,end,vtype='PE', \
491
491
  df2['平均值']=df2[vtypes].mean()
492
492
  df2['中位数']=df2[vtypes].median()
493
493
 
494
- titletxt="行业估值趋势:"+industry+','+vtypes
494
+ titletxt="行业估值趋势:"+industry_sw_name(industry)+','+vtypes
495
495
 
496
496
  footnote0="注:申万宏源行业指数,"
497
497
  footnote1=''
@@ -511,19 +511,372 @@ def industry_valuation_history_sw(industry,start,end,vtype='PE', \
511
511
  return df2
512
512
 
513
513
  if __name__=='__main__':
514
- df=industry_valuation_history_sw(industry,start,end,vtype='PE')
515
- df=industry_valuation_history_sw(industry,start,end,vtype='PB')
516
- df=industry_valuation_history_sw(industry,start,end,vtype='dividend')
514
+ df=industry_valuation_history_sw_daily(industry,start,end,vtype='PE')
515
+ df=industry_valuation_history_sw_daily(industry,start,end,vtype='PB')
516
+ df=industry_valuation_history_sw_daily(industry,start,end,vtype='dividend')
517
+
518
+ df=industry_valuation_history_sw_daily(industry='纺织服饰',start=start,end=end,vtype='PE')
519
+ df=industry_valuation_history_sw_daily(industry='纺织服饰',start=start,end=end,vtype='PB')
520
+ df=industry_valuation_history_sw_daily(industry='纺织服饰',start=start,end=end,vtype='dividend')
521
+
522
+ #==============================================================================
523
+ #==============================================================================
524
+ if __name__=='__main__':
525
+ adate='2023-12-14'
526
+
527
+ def get_last_friday(adate):
528
+ """
529
+ 功能:给定日期,找出上一个周五的日期,配合申万指数估值函数使用
530
+ """
531
+
532
+ result,fdate=check_date2(adate)
533
+ if not result:
534
+ return None
535
+
536
+ import pendulum
537
+ wrk=pendulum.parse(fdate).day_of_week
538
+
539
+ import datetime
540
+ todaydt = datetime.date.today().strftime('%Y-%m-%d')
541
+ if fdate > todaydt:
542
+ fdate=todaydt
543
+
544
+ if wrk==5:
545
+ if fdate != todaydt:
546
+ adj=-1
547
+ else:
548
+ adj=-(2+wrk)
549
+ elif wrk==6:
550
+ adj=-1
551
+ else:
552
+ adj=-(2+wrk)
553
+ last_fri=date_adjust(fdate,adjust=adj)
554
+
555
+ return last_fri
556
+
557
+ if __name__=='__main__':
558
+ start='2023-1-1'
559
+ end='2023-12-14'
560
+ get_all_friday(start,end)
561
+
562
+ def get_all_friday(start,end):
563
+ """
564
+ 功能:获取start和end之间所有的周五日期,配合申万指数估值函数使用
565
+ """
566
+ #import pandas as pd
567
+ start_fri=get_last_friday(start)
568
+ end_fri=get_last_friday(end)
569
+
570
+ import akshare as ak
571
+ wrk_df=ak.index_analysis_week_month_sw("week")
572
+ wrk_df['Date']=wrk_df['date'].apply(lambda x:x.strftime('%Y-%m-%d'))
573
+ frilist=list(wrk_df['Date'])
574
+
575
+ period_frilist=[]
576
+ for f in frilist:
577
+ if (f >= start_fri) and (f <= end_fri):
578
+ period_frilist=period_frilist+[f]
579
+
580
+ return period_frilist
581
+
582
+ #==============================================================================
583
+
584
+ if __name__=='__main__':
585
+ industry='食品饮料'
586
+ industry='白酒Ⅱ'
587
+ start='2023-10-1'
588
+ end='2023-12-15'
589
+ vtype='PE'
590
+
591
+ graph=True
592
+ loc='best'
593
+ df=industry_valuation_history_sw_weekly(industry,start,end,vtype)
594
+
595
+ def industry_valuation_history_sw_weekly(industry,start,end,vtype='PE', \
596
+ graph=True,loc='best'):
597
+ """
598
+ 功能:绘制一个申万行业的周历史估值趋势,支持申万"市场表征", "一级行业", "二级行业", "风格指数"
599
+ 不支持三级行业,若为非二级行业,转为industry_valuation_history_sw_daily函数处理日数据,专注处理二级行业周数据
600
+ vtype: PE, PB, dividend
601
+
602
+ """
603
+ #检查日期期间
604
+ result,start1,end1=check_period(start,end)
605
+ if not result:
606
+ print(" #Warning(industry_valuation_history_sw_weekly): invalid date period",start,end)
607
+ return None
608
+ fridays=get_all_friday(start,end)
609
+
610
+ #检查估值类型
611
+ typelist=['pe','pb','dividend']
612
+ vtypeu=vtype.lower()
613
+ if not (vtypeu in typelist):
614
+ print(" #Warning(industry_valuation_history_sw_weekly): unsupported valuation type",vtype)
615
+ print(" Supported types:",typelist)
616
+ return None
617
+
618
+ vtypelist=['pe','pb','dividend']
619
+ typelist=['市盈率','市净率','股息率']
620
+ pos=vtypelist.index(vtypeu)
621
+ vtypes=typelist[pos]
622
+
623
+ #分辨申万行业代码类别
624
+ sw_codes=industry_sw_list()
625
+ sw_codes['type_name']=''
626
+ sw_codes['type_name']=sw_codes.apply(lambda x: '市场表征' if x['type']=='F' else x['type_name'],axis=1)
627
+ sw_codes['type_name']=sw_codes.apply(lambda x: '一级行业' if x['type']=='I' else x['type_name'],axis=1)
628
+ sw_codes['type_name']=sw_codes.apply(lambda x: '二级行业' if x['type']=='T' else x['type_name'],axis=1)
629
+ sw_codes['type_name']=sw_codes.apply(lambda x: '风格指数' if x['type']=='S' else x['type_name'],axis=1)
630
+ sw_codes['type_name']=sw_codes.apply(lambda x: '三级行业' if x['type']=='3' else x['type_name'],axis=1)
631
+
632
+ industry1=industry.split('.')[0]
633
+ industry_name_flag=industry_code_flag=False
634
+ try:
635
+ type_name=sw_codes[sw_codes['name']==industry1]['type_name'].values[0]
636
+ industry_name_flag=True
637
+ except:
638
+ try:
639
+ type_name=sw_codes[sw_codes['code']==industry1]['type_name'].values[0]
640
+ industry_code_flag=True
641
+ except:
642
+ print(" #Error(industry_valuation_history_sw_weekly): Shenwan industry not found for",industry)
643
+ return None
644
+
645
+ if type_name=='三级行业':
646
+ print(" #Error(industry_valuation_history_sw_weekly): currently does not support Shenwan 3rd_level industry",industry)
647
+ return None
648
+
649
+ if not (type_name=='二级行业'):
650
+ df=industry_valuation_history_sw_daily(industry=industry,start=start,end=end,vtype=vtype, \
651
+ graph=graph,loc=loc)
652
+ return df
653
+
654
+ # 获取行业估值历史周数据
655
+ import pandas as pd
656
+ import akshare as ak
657
+ df=None
658
+ for f in fridays:
659
+ f1=f[:4]+f[5:7]+f[8:]
660
+ try:
661
+ dft=ak.index_analysis_weekly_sw(symbol=type_name, date=f1)
662
+ except:
663
+ continue
664
+
665
+ """
666
+ dft的结构:
667
+ ['指数代码','指数名称','发布日期','收盘指数','成交量','涨跌幅','换手率',
668
+ '市盈率','市净率','均价','成交额占比','流通市值','平均流通市值','股息率']
669
+ """
670
+
671
+ if not (dft is None):
672
+ if industry_name_flag:
673
+ dft2=dft[dft['指数名称']==industry1]
674
+ if industry_code_flag:
675
+ dft2=dft[dft['指数代码']==industry1]
676
+
677
+ if df is None:
678
+ df=dft2
679
+ else:
680
+ df=pd.concat([df,dft2])
681
+
682
+ df['date']=pd.to_datetime(df['发布日期'])
683
+ df.set_index('date',inplace=True)
684
+ df1=df[[vtypes]]
517
685
 
518
- df=industry_valuation_history_sw(industry='纺织服饰',start=start,end=end,vtype='PE')
519
- df=industry_valuation_history_sw(industry='纺织服饰',start=start,end=end,vtype='PB')
520
- df=industry_valuation_history_sw(industry='纺织服饰',start=start,end=end,vtype='dividend')
686
+ #筛选期间
687
+ #df2=df1[(df1.index >= start1) & (df1.index <= end1)]
688
+ df2=df1.dropna()
689
+
690
+ #绘图
691
+ if graph:
692
+ df2['平均值']=df2[vtypes].mean()
693
+ df2['中位数']=df2[vtypes].median()
694
+
695
+ titletxt="行业估值趋势:"+industry+','+vtypes
696
+
697
+ footnote0="注:申万宏源行业指数,"
698
+ footnote1=''
699
+ import datetime
700
+ today = datetime.date.today()
701
+ footnote2="数据来源: 申万宏源,"+str(today)
702
+ footnote=footnote0+footnote1+footnote2
703
+
704
+ colname=vtypes
705
+ collabel=vtypes
706
+ ylabeltxt=vtypes
707
+
708
+ draw_lines(df2,y_label=ylabeltxt,x_label=footnote, \
709
+ axhline_value=0,axhline_label='', \
710
+ title_txt=titletxt,data_label=False,resample_freq='D')
711
+
712
+ return df2
521
713
 
522
714
  #==============================================================================
715
+
716
+ if __name__=='__main__':
717
+ industry='食品饮料'
718
+ industry='白酒Ⅱ'
719
+ start='2023-10-1'
720
+ end='2023-12-15'
721
+ vtype='PE'
722
+
723
+ graph=True
724
+ loc='best'
725
+ df=industry_valuation_history_sw(industry,start,end,vtype)
726
+
727
+ def industry_valuation_history_sw(industry,start,end,vtype='PE', \
728
+ graph=True,loc='best'):
729
+ """
730
+ 功能:绘制一个申万行业的日历史估值趋势,支持申万"市场表征", "一级行业", "二级行业", "风格指数"
731
+ 不支持三级行业,若为非二级行业,转为industry_valuation_history_sw_daily函数处理日数据,专注处理二级行业日数据
732
+ vtype: PE, PB, dividend
733
+
734
+ """
735
+ #检查日期期间
736
+ result,start1,end1=check_period(start,end)
737
+ if not result:
738
+ print(" #Warning(industry_valuation_history_sw): invalid date period",start,end)
739
+ return None
740
+
741
+ #检查估值类型
742
+ typelist=['pe','pb','dividend']
743
+ vtypeu=vtype.lower()
744
+ if not (vtypeu in typelist):
745
+ print(" #Warning(industry_valuation_history_sw): unsupported valuation type",vtype)
746
+ print(" Supported types:",typelist)
747
+ return None
748
+
749
+ vtypelist=['pe','pb','dividend']
750
+ typelist=['市盈率','市净率','股息率']
751
+ pos=vtypelist.index(vtypeu)
752
+ vtypes=typelist[pos]
753
+
754
+ #分辨申万行业代码类别
755
+ sw_codes=industry_sw_list()
756
+ sw_codes['type_name']=''
757
+ sw_codes['type_name']=sw_codes.apply(lambda x: '市场表征' if x['type']=='F' else x['type_name'],axis=1)
758
+ sw_codes['type_name']=sw_codes.apply(lambda x: '一级行业' if x['type']=='I' else x['type_name'],axis=1)
759
+ sw_codes['type_name']=sw_codes.apply(lambda x: '二级行业' if x['type']=='T' else x['type_name'],axis=1)
760
+ sw_codes['type_name']=sw_codes.apply(lambda x: '风格指数' if x['type']=='S' else x['type_name'],axis=1)
761
+ sw_codes['type_name']=sw_codes.apply(lambda x: '三级行业' if x['type']=='3' else x['type_name'],axis=1)
762
+
763
+ industry1=industry.split('.')[0]
764
+ industry_name_flag=industry_code_flag=False
765
+ try:
766
+ type_name=sw_codes[sw_codes['name']==industry1]['type_name'].values[0]
767
+ industry_name_flag=True
768
+ except:
769
+ try:
770
+ type_name=sw_codes[sw_codes['code']==industry1]['type_name'].values[0]
771
+ industry_code_flag=True
772
+ except:
773
+ print(" #Error(industry_valuation_history_sw): Shenwan industry not found for",industry)
774
+ return None
775
+
776
+ if type_name=='三级行业':
777
+ print(" #Error(industry_valuation_history_sw): currently does not support Shenwan 3rd_level industry",industry)
778
+ return None
779
+
780
+ if not (type_name=='二级行业'):
781
+ df=industry_valuation_history_sw_daily(industry=industry,start=start,end=end,vtype=vtype, \
782
+ graph=graph,loc=loc)
783
+ return df
784
+
785
+ # 获取行业估值历史周数据
786
+ import pandas as pd
787
+ import akshare as ak
788
+ start2=start1.strftime('%Y-%m-%d')
789
+ end2 =end1.strftime('%Y-%m-%d')
790
+ pdate=end2
791
+ dstep=7
792
+ df=None
793
+ while (pdate >= start2) or (abs(date_delta(pdate,start2)) < dstep):
794
+ if pdate >= start2:
795
+ enddate=pdate
796
+ fromdate=date_adjust(pdate,adjust=-dstep)
797
+ else:
798
+ enddate=start2
799
+ fromdate=pdate
800
+
801
+ try:
802
+ fromdate1=fromdate[:4]+fromdate[5:7]+fromdate[8:10]
803
+ enddate1=enddate[:4]+enddate[5:7]+enddate[8:10]
804
+ dft=ak.index_analysis_daily_sw(symbol=type_name,start_date=fromdate1,end_date=enddate1)
805
+ except:
806
+ dft=None
807
+ """
808
+ try:
809
+ fromdate1=fromdate[:4]+fromdate[5:7]+fromdate[8:10]
810
+ enddate1=enddate[:4]+enddate[5:7]+enddate[8:10]
811
+ dft=ak.index_analysis_daily_sw(symbol=type_name,start_date=fromdate1,end_date=enddate1)
812
+ except:
813
+ continue
814
+ """
815
+ """
816
+ dft的结构:
817
+ ['指数代码','指数名称','发布日期','收盘指数','成交量','涨跌幅','换手率',
818
+ '市盈率','市净率','均价','成交额占比','流通市值','平均流通市值','股息率']
819
+ """
820
+
821
+ if not (dft is None):
822
+ if industry_name_flag:
823
+ dft2=dft[dft['指数名称']==industry1]
824
+ if industry_code_flag:
825
+ dft2=dft[dft['指数代码']==industry1]
826
+
827
+ if df is None:
828
+ df=dft2
829
+ else:
830
+ df=pd.concat([df,dft2])
831
+
832
+ # 开始下一轮循环
833
+ pdate=date_adjust(fromdate,adjust=-1)
834
+
835
+ df.sort_values('发布日期',ascending=True,inplace=True)
836
+ df.drop_duplicates(inplace=True)
837
+
838
+ #df=df[df.index >= start1]
839
+ #df.dropna(inplace=True)
840
+
841
+ df['date']=pd.to_datetime(df['发布日期'])
842
+ df.set_index('date',inplace=True)
843
+ df1=df[[vtypes]]
844
+
845
+ #筛选期间
846
+ #df2=df1[(df1.index >= start1) & (df1.index <= end1)]
847
+ df2=df1
848
+
849
+ #绘图
850
+ if graph:
851
+ df2['平均值']=df2[vtypes].mean()
852
+ df2['中位数']=df2[vtypes].median()
853
+
854
+ titletxt="行业估值趋势:"+industry+','+vtypes
855
+
856
+ footnote0="注:申万行业分类指数,"
857
+ footnote1=''
858
+ import datetime
859
+ today = datetime.date.today()
860
+ footnote2="数据来源: 申万宏源,"+str(today)
861
+ footnote=footnote0+footnote1+footnote2
862
+
863
+ colname=vtypes
864
+ collabel=vtypes
865
+ ylabeltxt=vtypes
866
+
867
+ draw_lines(df2,y_label=ylabeltxt,x_label=footnote, \
868
+ axhline_value=0,axhline_label='', \
869
+ title_txt=titletxt,data_label=False,resample_freq='D')
870
+
871
+ return df2
872
+
873
+ #==============================================================================
874
+ #==============================================================================
523
875
  if __name__=='__main__':
524
876
  industries=['食品饮料','纺织服饰']
525
- start='2021-1-1'
526
- end='2022-11-15'
877
+ industries=['银行','国有大型银行Ⅱ','股份制银行Ⅱ','城商行Ⅱ','农商行Ⅱ']
878
+ start='2023-12-1'
879
+ end='2023-12-15'
527
880
  vtypes='PE'
528
881
 
529
882
  industries='纺织服饰'
@@ -532,6 +885,8 @@ if __name__=='__main__':
532
885
  graph=True
533
886
  loc1='lower left'
534
887
  loc2='upper right'
888
+
889
+ df5=compare_industry_valuation_sw(industries,start,end,vtypes)
535
890
 
536
891
  def compare_industry_valuation_sw(industries,start,end,vtypes='PE', \
537
892
  graph=True,loc1='best',loc2='best'):
@@ -564,6 +919,8 @@ def compare_industry_valuation_sw(industries,start,end,vtypes='PE', \
564
919
  import pandas as pd
565
920
  df=pd.DataFrame()
566
921
  for i in industries:
922
+ # debug
923
+ print(" ...Searching valuation info for",i,'\b, which may take time ...')
567
924
  dft=industry_valuation_history_sw(i,start=start,end=end,vtype=vtype,graph=False)
568
925
  if not (dft is None):
569
926
  dft.rename(columns={vtypec:i},inplace=True)
@@ -1301,4 +1658,70 @@ def multi_ols(df,xList,y,industryDummies,yearDummies):
1301
1658
 
1302
1659
  return coefMatrix
1303
1660
 
1661
+ #==============================================================================
1662
+ #==============================================================================
1663
+ #==============================================================================
1664
+ if __name__=='__main__':
1665
+ sw_code='850831.SW'
1666
+ sw_code='801193.SW'
1667
+ indicator='PE'
1668
+ start='2023-1-1'
1669
+ end='2023-12-15'
1670
+ top=10
1671
+
1672
+ def valuation_industry_sw_generating(sw_code,indicator,start,end,top=5):
1673
+ """
1674
+ 功能:模拟申万行业指数的估值,PE/PB/股息率等
1675
+ sw_code:申万行业分类指数,各个级别
1676
+ start/end:开始/结束日期
1677
+ top:使用前几大成分股的估值进行合成
1678
+
1679
+ 注意:指数模拟出的估值曲线波动过大,缺乏实用价值!
1680
+ """
1681
+ import pandas as pd
1682
+ #查找申万行业指数成分股
1683
+ clist,cdf=industry_stock_sw(industry=sw_code,top=top)
1684
+
1685
+ #查找成分股的历史估值
1686
+ df=None
1687
+ for t in clist:
1688
+ dft=get_stock_valuation_cn_hk(ticker=t,indicators=indicator,start=start,end=end)
1689
+ dft[t]=dft[indicator]
1690
+ dft2=dft[[t]]
1691
+ if dft2 is None: continue
1692
+
1693
+ #将负数填充为0,不计入估值?整个成分股剔除?
1694
+ dft2[t]=dft2[t].apply(lambda x: 0 if x<0 else x)
1695
+
1696
+ if df is None:
1697
+ df=dft2
1698
+ else:
1699
+ df=pd.merge(df,dft2,how='outer',left_index=True,right_index=True)
1700
+
1701
+ #成分股权重
1702
+ weight=list(cdf['最新权重'])
1703
+
1704
+ #各行权重分别求和
1705
+ dfw=df.copy()
1706
+ collist=list(dfw)
1707
+ for c in collist:
1708
+ dfw[c]=dfw[c].apply(lambda x: 0 if x<=0 else 1)
1709
+ dfw['weight']=dfw.dot(weight)
1710
+ dfw2=dfw[['weight']]
1711
+
1712
+ #加权平均
1713
+ df['weighted_total']=df.dot(weight)
1714
+ df2=pd.merge(df,dfw2,left_index=True,right_index=True)
1715
+
1716
+ df2['weighted_avg']=df2['weighted_total']/df2['weight']
1717
+ df2['code']=sw_code
1718
+ df3=df2[['code','weighted_avg']]
1719
+
1720
+ #因有市盈率负数,不管如何处理都会导致加权平均后数值波动过大,不能实用
1721
+ return df3
1722
+
1723
+
1724
+
1725
+
1726
+
1304
1727
  #==============================================================================
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: siat
3
- Version: 2.11.13
3
+ Version: 2.11.19
4
4
  Summary: Securities Investment Analysis Tools (siat)
5
5
  Home-page: https://pypi.org/project/siat/
6
6
  Author: Prof. WANG Dehong, Business School, BFSU
@@ -28,6 +28,7 @@ Requires-Dist: ruamel-yaml
28
28
  Requires-Dist: prettytable
29
29
  Requires-Dist: graphviz
30
30
  Requires-Dist: luddite
31
+ Requires-Dist: pendulum
31
32
 
32
33
 
33
34
  This plug-in is designed to use with the author's textbooks on security investment,
@@ -61,7 +61,7 @@ siat/grafix_test.py,sha256=kXvcpLgQNO7wd30g_bWljLj5UH7bIVI0_dUtXbfiKR0,3150
61
61
  siat/holding_risk.py,sha256=Dh4zXEw-0hnbMNorbsRS142C8mUzq4NhFjYnauWu5tc,30548
62
62
  siat/holding_risk_test.py,sha256=FRlw_9wFG98BYcg_cSj95HX5WZ1TvkGaOUdXD7-V86s,474
63
63
  siat/local_debug_test.py,sha256=CDAOffW1Rvs-TcNN5giWVvHMlch1w4dp-w5SIV9jXL0,3936
64
- siat/market_china.py,sha256=4JZ0YPUSY97W392DCs0-aTrRpDz_3uqVbZ4gUeNN4R8,38036
64
+ siat/market_china.py,sha256=pwCjEqkNAcOrs4Ba5DIQ5WgyAC73ntOi-d7Cb29wOWk,37849
65
65
  siat/markowitz.py,sha256=gs_R-FiykUMXfTVS0r_HswLC6VFmdmQMcQh7dh285iM,96379
66
66
  siat/markowitz_ccb_test.py,sha256=xBkkoaNHdq9KSUrNuHGgKTdNYUvgi84kNYcf719eoyE,1593
67
67
  siat/markowitz_ef_test.py,sha256=wjNlICkgRIqnonPeSIHo4Mu2GRtb9dr21wDt2kMNEcI,4032
@@ -118,13 +118,13 @@ siat/transaction_test.py,sha256=Z8g1LJCN4-mnUByXMUMoFmN0t105cbmsz2QmvSuIkbU,1858
118
118
  siat/translate-20230125.py,sha256=NPPSXhT38s5t9fzMvl_fvi4ckSB73ThLmZetVI-xGdU,117953
119
119
  siat/translate-20230206.py,sha256=-vtI125WyaJhmPotOpDAmclt_XnYVaWU9ByLWZ6FyYE,118133
120
120
  siat/translate-20230215.py,sha256=TJgtPE3n8IjljmZ4Pefy8dmHoNdFF-1zpML6BhA9FKE,121657
121
- siat/translate.py,sha256=hBYeGEv5_4Mi-tKNVoJM2mNp_yDniXuU3g-tp1HJTD8,142546
121
+ siat/translate.py,sha256=zAemLG2s7wABKhZjM7esMfqH3tKX48O53sTEOLdilZI,142620
122
122
  siat/universal_test.py,sha256=CDAOffW1Rvs-TcNN5giWVvHMlch1w4dp-w5SIV9jXL0,3936
123
- siat/valuation.py,sha256=EbXyWdvr_hPw578TW-1xeACC6p4CKzLCsWkvP4-Kmzs,43299
124
- siat/valuation_china.py,sha256=SPJFU9J8WJhz_HOXgIAjoG8dZs1zSPS1BZxkjhA-D1w,52241
123
+ siat/valuation.py,sha256=3VKrO9b9xY9dOJGGuF0ZhytzB5d2pCx3kO3TtMml7mo,44025
124
+ siat/valuation_china.py,sha256=oEQRrktJNHiOG1mJSQN1aSSQAQrwrg-ppIHyNVjMjNg,67603
125
125
  siat/valuation_market_china_test.py,sha256=gbJ0ioauuo4koTPH6WKUkqcXiQPafnbhU5eKJ6lpdLA,1571
126
126
  siat/var_model_validation.py,sha256=zB_Skk_tmzIR15l6oAW3am4HBGVIG-eZ8gJhCdXZ8Qw,14859
127
- siat-2.11.13.dist-info/METADATA,sha256=oPnn20bzfQfpk3f6bNB-SqEyGAsajAroNYP77ghL1Tc,1354
128
- siat-2.11.13.dist-info/WHEEL,sha256=2wepM1nk4DS4eFpYrW1TTqPcoGNfHhhO_i5m4cOimbo,92
129
- siat-2.11.13.dist-info/top_level.txt,sha256=r1cVyL7AIKqeAmEJjNR8FMT20OmEzufDstC2gv3NvEY,5
130
- siat-2.11.13.dist-info/RECORD,,
127
+ siat-2.11.19.dist-info/METADATA,sha256=Mdm4x2u8FSNCFOkTSMVc-AcohE2iWXihxWC1tKD2vws,1379
128
+ siat-2.11.19.dist-info/WHEEL,sha256=2wepM1nk4DS4eFpYrW1TTqPcoGNfHhhO_i5m4cOimbo,92
129
+ siat-2.11.19.dist-info/top_level.txt,sha256=r1cVyL7AIKqeAmEJjNR8FMT20OmEzufDstC2gv3NvEY,5
130
+ siat-2.11.19.dist-info/RECORD,,
File without changes