siat 3.7.8__py3-none-any.whl → 3.7.9__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/fin_stmt2_yahoo.py CHANGED
@@ -19,6 +19,8 @@ SIAT:Security Investment Analysis Tool
19
19
  import warnings; warnings.filterwarnings('ignore')
20
20
 
21
21
  from siat.common import *
22
+ from siat.translate import *
23
+
22
24
  import pandas as pd
23
25
  import numpy as np
24
26
  #==============================================================================
@@ -36,11 +38,11 @@ if __name__=='__main__':
36
38
  symbol='601398.SS'
37
39
  symbol='601328.SS'
38
40
 
39
- max_count=3
40
- max_sleep=30
41
-
42
41
  report_type="balance sheet"
43
- printout=True
42
+ report_period="all"
43
+ max_count=3; max_sleep=30
44
+ fix_entry=False; printout=False
45
+ auto_language=True
44
46
 
45
47
  bsdf_raw=get_1statement_yahoo2(symbol,report_type="balance sheet",fix_entry=False)
46
48
  bsdf_fix=get_1statement_yahoo2(symbol,report_type="balance sheet",fix_entry=True)
@@ -53,23 +55,27 @@ if __name__=='__main__':
53
55
 
54
56
 
55
57
  def get_1statement_yahoo2(symbol,report_type="balance sheet", \
56
- report_period="all", \
58
+ report_period="annual", \
57
59
  max_count=3,max_sleep=30, \
58
- fix_entry=True,printout=False):
60
+ fix_entry=False,printout=False, \
61
+ auto_language=False,language_engine='baidu', \
62
+ entry_split=True,split_improve=True):
59
63
  """
60
64
  功能:获取雅虎财经上一只股票所有的年度和季度资产负债表,采用contains匹配法
61
65
 
62
66
  参数:
63
67
  symbol:股票代码,五位港股需要转换为四位
64
68
  report_type:需要抓取的财报类型,默认资产负债表"balance sheet"
65
- report_period:财报期间,默认年报+季报all,可选单纯年报(annual)或单纯季报(quarterly)
69
+ report_period:财报期间,默认年报,可选年报+季报(all)或单纯季报(quarterly)
66
70
  max_count:抓取失败时的总尝试次数,默认3
67
71
  max_sleep=30:抓取失败时再次尝试间隔的随机秒数最大值
68
- fix_entry:是否对重点科目进行检查和填充,默认是True
69
- printout:是否打印赚取到的财报,默认否False
72
+ fix_entry:是否对重点科目进行检查和填充,默认是False
73
+ printout:是否打印抓取到的财报,默认否False
74
+ auto_language:是否自动进行翻译,默认否False,自动翻译True
70
75
 
71
76
  返回值:成功时返回df,失败时返回None
72
77
  """
78
+
73
79
  report_type=report_type.lower()
74
80
  if 'balance' in report_type:
75
81
  report_type="balance sheet"
@@ -92,7 +98,7 @@ def get_1statement_yahoo2(symbol,report_type="balance sheet", \
92
98
  try:
93
99
  stock = Ticker(symbol)
94
100
  except:
95
- print(" #Warning(get_1statement_yahoo2): Yahoo Finance currently unaccessable")
101
+ print(" #Warning(get_1statement_yahoo2): currently unaccessable to Yahoo")
96
102
  return None
97
103
 
98
104
  if contains_any(report_period,['all','annual']):
@@ -102,6 +108,8 @@ def get_1statement_yahoo2(symbol,report_type="balance sheet", \
102
108
  stmta=stock.balance_sheet() # Defaults to Annual
103
109
  elif report_type=="income statement":
104
110
  stmta=stock.income_statement()
111
+ #去掉TTM,数据不全
112
+ stmta=stmta[stmta['periodType'] != 'TTM']
105
113
  else:
106
114
  stmta=stock.cash_flow()
107
115
 
@@ -130,6 +138,8 @@ def get_1statement_yahoo2(symbol,report_type="balance sheet", \
130
138
  stmtq=stock.balance_sheet(frequency="q") # Defaults to Annual
131
139
  elif report_type=="income statement":
132
140
  stmtq=stock.income_statement(frequency="q")
141
+ #去掉TTM,数据不全
142
+ stmtq=stmtq[stmtq['periodType'] != 'TTM']
133
143
  else:
134
144
  stmtq=stock.cash_flow(frequency="q")
135
145
 
@@ -152,7 +162,7 @@ def get_1statement_yahoo2(symbol,report_type="balance sheet", \
152
162
  print(" #Error(get_1statement_yahoo2): retrieved no periodic reports for",symbol)
153
163
  return None
154
164
 
155
- #合并后排序+去重
165
+ #合并后排序+去重:季报中可能还含有年报
156
166
  stmt.sort_values(by=['asOfDate','periodType'],inplace=True)
157
167
  #去掉重复记录: 保留年报数据项多,去掉数据项少的季报
158
168
  stmt.drop_duplicates(subset=['asOfDate'],keep='first',inplace=True)
@@ -185,7 +195,9 @@ def get_1statement_yahoo2(symbol,report_type="balance sheet", \
185
195
 
186
196
  #是否打印供检查
187
197
  if printout:
188
- print_stmt_yahoo2(stmt,title_prefix=report_type.title())
198
+ print_stmt_yahoo2(stmt,title_prefix=report_type.title(), \
199
+ auto_language=auto_language,language_engine=language_engine, \
200
+ entry_split=entry_split,split_improve=split_improve)
189
201
 
190
202
  return stmt
191
203
 
@@ -454,13 +466,27 @@ def check_fill_cfs_yahoo(stmt):
454
466
  if __name__=='__main__':
455
467
  from yahooquery import Ticker
456
468
  stock = Ticker("AAPL")
457
- stmt=stock.cash_flow()
469
+ stmt=stock.income_statement()
458
470
 
471
+ stmt=get_financial_statements2_yahoo('JD',printout=False)
472
+
473
+ title_prefix="Balance Sheet"
459
474
  title_prefix="Cash Flow Statement"
475
+ title_prefix="Integrated Financial Statements"
476
+
477
+ auto_language=True
478
+ entry_split=True
479
+ split_improve=True
480
+ language_engine=['baidu','sogou','bing','google']
481
+
482
+ stmt=get_financial_statements2_yahoo('JD',printout=False)
460
483
 
461
484
  print_stmt_yahoo2(stmt,title_prefix)
462
485
 
463
- def print_stmt_yahoo2(stmt,title_prefix):
486
+ def print_stmt_yahoo2(stmt,title_prefix, \
487
+ auto_language=True, \
488
+ #language_engine=['google','bing','sogou'], \
489
+ entry_split=True,split_improve=True):
464
490
  """
465
491
 
466
492
  功能:打印雅虎抓取的财报
@@ -487,6 +513,7 @@ def print_stmt_yahoo2(stmt,title_prefix):
487
513
  for c in cols1:
488
514
  stmtprt1[c]=stmtprt1[c].apply(lambda x: round(x/million,2))
489
515
 
516
+ #科目分词处理与翻译
490
517
  stmtprt2=stmtprt1.T
491
518
  cols=list(stmtprt2)
492
519
  cols.sort(reverse=True)
@@ -494,14 +521,89 @@ def print_stmt_yahoo2(stmt,title_prefix):
494
521
  stmtprt2['Item']=stmtprt2.index
495
522
  stmtprt2=stmtprt2[['Item']+cols]
496
523
 
497
- titletxt=f"{symbol}: {title_prefix}, in {currencyCode} millions"
498
- footnote="Note: 12M indicates annual report, 3M quaterly reports"
499
- df_display_CSS(stmtprt2,titletxt=titletxt,footnote=footnote, \
500
- facecolor='papayawhip',decimals=2, \
501
- first_col_align='left',second_col_align='right', \
502
- last_col_align='right',other_col_align='right', \
503
- titile_font_size='15px',heading_font_size='11px', \
504
- data_font_size='11px',footnote_font_size='13px')
524
+ lang=check_language()
525
+
526
+ #科目分词,语言处理:英文
527
+ title_prefix=title_prefix.title()
528
+ titletxt=f"{ticker_name(symbol)}: {title_prefix}, in {currencyCode} millions"
529
+
530
+ footnote1="Note: 12M = annual report, 3M = quaterly reports"
531
+ import datetime as dt; todaydt=dt.date.today()
532
+ footnote2=", data source: Yahoo, "+str(todaydt)
533
+ footnote=footnote1 + footnote2
534
+
535
+ if (auto_language and lang=='English') or entry_split:
536
+ item_dict=dict(stmtprt2['Item'])
537
+ item_list=list(stmtprt2['Item'])
538
+ for i in item_list:
539
+ i2=words_split_yahoo(i,split_improve=split_improve)
540
+ item_dict[i]=i2
541
+ stmtprt2['Item']=stmtprt2['Item'].apply(lambda x: item_dict[x])
542
+
543
+
544
+ #语言处理:中文
545
+ if 'balance' in title_prefix.lower():
546
+ title_prefix_cn="资产负债表"
547
+ elif 'income' in title_prefix.lower():
548
+ title_prefix_cn="利润表"
549
+ elif 'cash' in title_prefix.lower():
550
+ title_prefix_cn="现金流量表"
551
+ else:
552
+ title_prefix_cn="三大报表综合"
553
+ title_cn=f"{ticker_name(symbol)}: {title_prefix_cn}, 单位:百万{currencyCode}"
554
+
555
+ footnote1_cn="注:12M表示年报,3M表示季报"
556
+ footnote2_cn=",数据来源:雅虎,"+str(todaydt)
557
+ footnote_cn=footnote1_cn + footnote2_cn
558
+
559
+ if auto_language and lang=='Chinese':
560
+ print(f" Translating into {lang} using AI, just for reference ...")
561
+
562
+ item_dict=dict(stmtprt2['Item'])
563
+ item_list=list(stmtprt2['Item'])
564
+ for i in item_list:
565
+ print_progress_percent2(i,item_list,steps=10,leading_blanks=4)
566
+
567
+ #i2=lang_auto2(i,language_engine=language_engine)
568
+ i2=lang_auto2(i)
569
+ #i2=lang_auto(i)
570
+ item_dict[i]=i2
571
+
572
+ stmtprt2['Item']=stmtprt2['Item'].apply(lambda x: x+'('+item_dict[x]+')')
573
+ """
574
+ if 'bilingual' in str(auto_language).lower():
575
+ stmtprt2['Item']=stmtprt2['Item'].apply(lambda x: x+'('+item_dict[x]+')')
576
+ else:
577
+ stmtprt2['Item']=stmtprt2['Item'].apply(lambda x: item_dict[x])
578
+ """
579
+
580
+ #语言合成
581
+ titletxt=text_lang(title_cn,titletxt)
582
+ footnote=text_lang(footnote_cn,footnote)
583
+
584
+ #删除全为零或空值的行:未做到!
585
+ stmtprt3=stmtprt2.copy()
586
+ cols3=list(stmtprt3)
587
+
588
+ stmtprt3.set_index('Item',inplace=True)
589
+ stmtprt3.replace(0,np.nan,inplace=True)
590
+ stmtprt3.dropna(how='all',axis=1,inplace=True)
591
+ stmtprt3['Item']=stmtprt3.index
592
+ stmtprt3=stmtprt3[cols3]
593
+
594
+ #检测Item是否存在重复值,若存在则df_display_CSS会失败
595
+ index1=stmtprt3[stmtprt3[["Item"]].duplicated(keep="last")].index
596
+ index2=stmtprt3[stmtprt3[["Item"]].duplicated(keep="first")].index
597
+ if not len(index1)==0 and not len(index2)==0:
598
+ cross_index=stmtprt3.loc[index1 | index2,:]
599
+ print(" Unable to display becos of duplicate items [{list(cross_index['Item'])}]")
600
+ else:
601
+ df_display_CSS(stmtprt3,titletxt=titletxt,footnote=footnote, \
602
+ facecolor='papayawhip',decimals=2, \
603
+ first_col_align='left',second_col_align='right', \
604
+ last_col_align='right',other_col_align='right', \
605
+ titile_font_size='15px',heading_font_size='10px', \
606
+ data_font_size='10px',footnote_font_size='13px')
505
607
 
506
608
  return
507
609
 
@@ -562,7 +664,7 @@ if __name__=='__main__':
562
664
  ticker='AAPL'
563
665
  ticker='00700.HK'
564
666
 
565
- report_period="all"
667
+ report_period="annual"
566
668
  max_count=3; max_sleep=30
567
669
  pre_fix_entry=False; post_fix_entry=True
568
670
  pre_printout=False; printout=True
@@ -570,13 +672,34 @@ if __name__=='__main__':
570
672
  fsdf=get_financial_statements2_yahoo(ticker)
571
673
 
572
674
  def get_financial_statements2_yahoo(ticker, \
573
- report_period="all", \
675
+ report_period="annual", \
574
676
  max_count=3,max_sleep=30, \
575
677
  pre_fix_entry=False,post_fix_entry=True, \
678
+ auto_language=False, \
679
+ #language_engine=['baidu','sogou','bing','google'], \
680
+ entry_split=True,split_improve=False, \
576
681
  pre_printout=False,printout=False):
577
682
  """
683
+
578
684
  功能:获取雅虎财经上一只股票所有的年度和季度财务报表
685
+ 参数:
686
+ ticker:一只股票的代码
687
+ report_period:报告期间,默认年报"annual",可选季报"quarterly"或所有"all"
688
+ max_count:爬虫失败时的最大尝试次数,默认3
689
+ max_sleep:每次抓取数据的时间间隔,规避反爬虫,默认30秒
690
+ pre_fix_entry:抓取资产负债表、利润表、现金流量表时是否单独修复科目数据,默认否False
691
+ post_fix_entry:抓取资产负债表、利润表、现金流量表后是否统一修复科目数据,默认是True
692
+ auto_language:是否自动翻译科目语言,默认否False
693
+ language_engine:语言翻译引擎,默认'baidu',可选必应"bing"、谷歌"google"等
694
+ entry_split:抓取数据后是否分拆科目名称单词,默认否False
695
+ split_improve:抓取数据后分拆科目单词时是否调整,默认否False
696
+ pre_printout:抓取资产负债表、利润表和现金流量表时是否单独显示,默认否False
697
+ printout:抓取资产负债表、利润表和现金流量表后是否统一显示,默认否False
579
698
  """
699
+ # 测试雅虎连通性
700
+ if not test_yahoo_access():
701
+ print(" Sorry, data source yahoo is inaccessible")
702
+ return None
580
703
 
581
704
  # 变换港股代码5位-->4位
582
705
  result,prefix,suffix=split_prefix_suffix(ticker)
@@ -591,6 +714,9 @@ def get_financial_statements2_yahoo(ticker, \
591
714
  report_period=report_period, \
592
715
  max_count=max_count,max_sleep=max_sleep, \
593
716
  fix_entry=pre_fix_entry, \
717
+ auto_language=False, \
718
+ #language_engine=language_engine, \
719
+ entry_split=entry_split,split_improve=split_improve, \
594
720
  printout=pre_printout)
595
721
 
596
722
 
@@ -599,6 +725,9 @@ def get_financial_statements2_yahoo(ticker, \
599
725
  report_period=report_period, \
600
726
  max_count=max_count,max_sleep=max_sleep, \
601
727
  fix_entry=pre_fix_entry, \
728
+ auto_language=False, \
729
+ #language_engine=language_engine, \
730
+ entry_split=entry_split,split_improve=split_improve, \
602
731
  printout=pre_printout)
603
732
 
604
733
 
@@ -607,6 +736,9 @@ def get_financial_statements2_yahoo(ticker, \
607
736
  report_period=report_period, \
608
737
  max_count=max_count,max_sleep=max_sleep, \
609
738
  fix_entry=pre_fix_entry, \
739
+ auto_language=False, \
740
+ #language_engine=language_engine, \
741
+ entry_split=entry_split,split_improve=split_improve, \
610
742
  printout=pre_printout)
611
743
 
612
744
  #=====三表合并
@@ -618,19 +750,30 @@ def get_financial_statements2_yahoo(ticker, \
618
750
  df=pd.merge(df_bs_is,df_cfs,on=head_cols)
619
751
  df['ticker']=ticker
620
752
 
753
+ #合并后删除重复列
754
+ df.rename(columns={'NetIncome_x':'NetIncome'},inplace=True)
755
+ try:
756
+ del df['NetIncome_y']
757
+ except:
758
+ pass
759
+
621
760
  #合成后填充缺失项
622
761
  if post_fix_entry:
623
762
  df1=check_fill_fs_yahoo(df)
624
763
  else:
625
764
  df1=df
626
765
 
627
- print(f" Successfully retrieved financial statements of {ticker}")
766
+ #print(f" Successfully retrieved 3 financial statements of {ticker}")
628
767
 
629
768
  if printout:
630
769
  df2=df1.copy()
631
- df2.replace(0,np.nan,inplace=True)
632
770
  title_prefix="Comprehensive Financial Statement"
633
- print_stmt_yahoo2(df2,title_prefix)
771
+
772
+ print_stmt_yahoo2(df2,title_prefix="Integrated Financial Statements", \
773
+ auto_language=auto_language, \
774
+ #language_engine=language_engine, \
775
+ entry_split=entry_split,split_improve=split_improve)
776
+
634
777
 
635
778
  return df1
636
779
 
@@ -668,16 +811,16 @@ def check_fill_fs_yahoo(stmt):
668
811
 
669
812
  """
670
813
  最终获得的表结构:
671
- ['asOfDate',
672
- 'periodType',
814
+ ['asOfDate(截止日期)',
815
+ 'periodType(期间类型)',
673
816
 
674
817
  'AccountsPayable(应付账款)',
675
818
  'AccountsReceivable(应收账款)',
676
819
  'AccumulatedDepreciation(累计折旧)',
677
- 'AdditionalPaidInCapital(资本公积,资本溢价,附加资本;paid-in capital:实收资本;缴入资本)',
820
+ 'AdditionalPaidInCapital(资本公积,资本溢价;paid-in capital:实收资本;缴入资本)',
678
821
  'AllowanceForDoubtfulAccountsReceivable(备抵应收呆帐)',
679
822
  'AvailableForSaleSecurities(可供出售金融资产;trading securities: 交易性金融资产)',
680
- 'BuildingsAndImprovements(建筑物改良)',
823
+ 'BuildingsAndImprovements(建筑物及其改良)',
681
824
  'CapitalStock(股本)',
682
825
  'CashAndCashEquivalents(现金及现金等价物)',
683
826
  'CashCashEquivalentsAndShortTermInvestments(现金、现金等价物及短期投资)',
@@ -696,16 +839,16 @@ def check_fill_fs_yahoo(stmt):
696
839
  'InventoriesAdjustmentsAllowances(存货调整备抵)',
697
840
  'Inventory(存货)',
698
841
  'InvestedCapital(投入资本)',
699
- 'InvestmentinFinancialAssets(金融资产投资?)',
700
- 'LandAndImprovements(土地改良)',
701
- 'MachineryFurnitureEquipment(机械家具设备?)',
702
- 'MinorityInterest(少数股东损益?)',
842
+ 'InvestmentinFinancialAssets(金融资产投资)',
843
+ 'LandAndImprovements(土地及其改良)',
844
+ 'MachineryFurnitureEquipment(机械家具设备)',
845
+ 'MinorityInterest(少数股东利益)',
703
846
  'NetPPE(固定资产净值)',
704
847
  'NetTangibleAssets(有形资产净值)',
705
848
  'NonCurrentDeferredAssets(非流动递延资产)',
706
- 'NonCurrentDeferredTaxesAssets(非流动递延税项资产?)',
707
- 'NonCurrentDeferredTaxesLiabilities(非流动递延税金负债?)',
708
- 'OrdinarySharesNumber(普通股数量?)',
849
+ 'NonCurrentDeferredTaxesAssets(非流动递延税项资产)',
850
+ 'NonCurrentDeferredTaxesLiabilities(非流动递延税金负债)',
851
+ 'OrdinarySharesNumber(普通股?)',
709
852
  'OtherCurrentAssets(其他流动资产)',
710
853
  'OtherCurrentLiabilities(其他流动负债)',
711
854
  'OtherEquityInterest(其他股权)',
@@ -715,8 +858,8 @@ def check_fill_fs_yahoo(stmt):
715
858
  'OtherProperties(?)',
716
859
  'OtherReceivables(其他应收款)',
717
860
  'Payables(应付款项)',
718
- 'PrepaidAssets(预付资产;预付费用)',
719
- 'Properties(财产?)',
861
+ 'PrepaidAssets(预付资产)',
862
+ 'Properties(财产?物业?)',
720
863
  'RawMaterials(原材料)',
721
864
  'RetainedEarnings(留存收益)',
722
865
  'ShareIssued(股票发行)',
@@ -724,33 +867,33 @@ def check_fill_fs_yahoo(stmt):
724
867
  'TangibleBookValue(有形资产账面价值)',
725
868
  'TotalAssets(总资产)',
726
869
  'TotalCapitalization(资本总额?)',
727
- 'TotalEquityGrossMinorityInterest(少数股东权益总额)',
728
- 'TotalLiabilitiesNetMinorityInterest(?)',
870
+ 'TotalEquityGrossMinorityInterest(权益与少数股东利益总额)',
871
+ 'TotalLiabilitiesNetMinorityInterest(扣除少数股东利益的总负债)',
729
872
  'TotalNonCurrentAssets(非流动资产总额)',
730
- 'TotalNonCurrentLiabilitiesNetMinorityInterest(?)',
873
+ 'TotalNonCurrentLiabilitiesNetMinorityInterest(扣除少数股东利益的非流动负债总额)',
731
874
  'TotalTaxPayable(应缴税款总额)',
732
- 'TradeandOtherPayablesNonCurrent(?)',
875
+ 'TradeandOtherPayablesNonCurrent(贸易与其他非流动应付款)',
733
876
  'WorkInProcess(在制品)',
734
877
  'WorkingCapital(营运资本)',
735
878
  'Amortization(摊销)',
736
879
 
737
- 'BasicAverageShares(未稀释的平均股数?)',
738
- 'BasicEPS( 基本每股收益,指属于普通股股东的当期净利润,除以发行在外普通股的加权平均数,可按存在月数加权)',
739
- 'CostOfRevenue(主营业务成本,营收成本)',
880
+ 'BasicAverageShares(未稀释的平均股数)',
881
+ 'BasicEPS(基本每股收益,指属于普通股股东的当期净利润,除以发行在外普通股的加权平均数,可按存在月数加权)',
882
+ 'CostOfRevenue(收入成本,营收成本)',
740
883
  'DepreciationAndAmortizationInIncomeStatement(损益表中的折旧和摊销)',
741
884
  'DepreciationIncomeStatement(损益表中的折旧)',
742
- 'DilutedAverageShares(稀释后平均股数?)',
885
+ 'DilutedAverageShares(稀释后的平均股数)',
743
886
  'DilutedEPS(考虑了可转换债券和股票期权可能行权对于流通在外股数的影响)',
744
887
  'EBIT(息税前利润)',
745
888
  'EBITDA(未计利息、税项、折旧及摊销前的利润)',
746
889
  'GeneralAndAdministrativeExpense(一般管理费用)',
747
- 'GrossProfit(营业毛利)',
890
+ 'GrossProfit(毛利润)',
748
891
  'ImpairmentOfCapitalAssets(资本资产减值)',
749
892
  'InterestExpense(利息费用)',
750
893
  'InterestExpenseNonOperating(非经营性利息费用)',
751
894
  'InterestIncome(利息收益)',
752
895
  'InterestIncomeNonOperating(非经营性利息收入)',
753
- 'MinorityInterests(少数股东权益)',
896
+ 'MinorityInterests(少数股东利益)',
754
897
  'NetIncome(净利润)',
755
898
  'NetIncomeCommonStockholders(归属于普通股股东的净利润,用于计算EPS和PE)',
756
899
  'NetIncomeContinuousOperations(扣非后净利润)',
@@ -758,45 +901,45 @@ def check_fill_fs_yahoo(stmt):
758
901
  'NetIncomeFromContinuingOperationNetMinorityInterest(不归属少数股东的扣非后净利润?)',
759
902
  'NetIncomeIncludingNoncontrollingInterests(包括非控股权的净收入?)',
760
903
  'NetInterestIncome(净利息收入)',
761
- 'NetNonOperatingInterestIncomeExpense(?)',
762
- 'NormalizedEBITDA(调整后EBITDA?)',
763
- 'NormalizedIncome(调整后利润?)',
904
+ 'NetNonOperatingInterestIncomeExpense(非营业外利息收入费用净值)',
905
+ 'NormalizedEBITDA(调整后EBITDA',
906
+ 'NormalizedIncome(调整后利润)',
764
907
  'OperatingExpense(营业费用)',
765
908
  'OperatingIncome(营业利润)',
766
909
  'OperatingRevenue(营业收入)',
767
- 'OtherNonOperatingIncomeExpenses(其他营业外收入支出?)',
910
+ 'OtherNonOperatingIncomeExpenses(其他营业外收入支出)',
768
911
  'OtherOperatingExpenses(其它营业费用)',
769
912
  'OtherSpecialCharges(其他特殊费用)',
770
913
  'OtherunderPreferredStockDividend(优先股股利下的其他项目)',
771
914
  'PretaxIncome(税前利润)',
772
- 'ReconciledCostOfRevenue(对账后的经营收入成本?)',
915
+ 'ReconciledCostOfRevenue(对账后的经营收入成本)',
773
916
  'ReconciledDepreciation(对账后的折旧)',
774
- 'RentAndLandingFees(租金及土地费用?)',
775
- 'RentExpenseSupplemental(补充租金费用?)',
917
+ 'RentAndLandingFees(租金及土地费用)',
918
+ 'RentExpenseSupplemental(补充租金费用)',
776
919
  'ResearchAndDevelopment(研发费用)',
777
920
  'SellingAndMarketingExpense(销售和市场营销费用)',
778
921
  'SellingGeneralAndAdministration(销售及一般管理费用)',
779
922
  'SpecialIncomeCharges(特殊收入的手续费)',
780
923
  'TaxEffectOfUnusualItems(非常项目的税收影响)',
781
- 'TaxProvision(税金?)',
782
- 'TaxRateForCalcs(计算用的税率)',
924
+ 'TaxProvision(税金计提)',
925
+ 'TaxRateForCalcs(Calcs计算用的税率)',
783
926
  'TotalExpenses(总费用)',
784
927
  'TotalOperatingIncomeAsReported(报告的总营业利润)',
785
928
  'TotalOtherFinanceCost(其他财务成本合计)',
786
929
  'TotalRevenue(总收入)',
787
930
  'TotalUnusualItems(非经常性项目总计)',
788
931
  'TotalUnusualItemsExcludingGoodwill(不包括商誉的非经常项目合计)',
789
- 'WriteOff(冲销?)',
932
+ 'WriteOff(冲销,核销)',
790
933
 
791
934
  'BeginningCashPosition(期初现金头寸)',
792
935
  'CapitalExpenditure(资本支出)',
793
936
  'CashDividendsPaid(现金股利支付)',
794
- 'ChangeInCashSupplementalAsReported(现金补充变更报告?)',
937
+ 'ChangeInCashSupplementalAsReported(报告的补充现金变更)',
795
938
  'ChangeInInventory(存货变化)',
796
939
  'ChangeInWorkingCapital(营运资本的变动额)',
797
940
  'DepreciationAndAmortization(折旧摊销)',
798
941
  'EndCashPosition(期末现金头寸)',
799
- 'FreeCashFlow(自有现金流)',
942
+ 'FreeCashFlow(自由现金流)',
800
943
  'InvestingCashFlow(投资现金流)',
801
944
  'NetOtherFinancingCharges(其他融资费用净额)',
802
945
  'NetOtherInvestingChanges(其他投资变动净额)',
@@ -807,12 +950,12 @@ def check_fill_fs_yahoo(stmt):
807
950
 
808
951
  #==============================================================================
809
952
  if __name__ == '__main__':
810
- fsdf=get_financial_statements('601398.SS')
953
+ fsdf=get_financial_statements2_yahoo('AAPL')
811
954
  account_entry='TotalAssets'
812
955
 
813
956
  fsdf1=fs_entry_begin(fsdf,account_entry='TotalAssets',suffix='_begin')
814
957
 
815
- def fs_entry_begin(fsdf,account_entry='TotalAssets',suffix='_begin'):
958
+ def fs_entry_begin_yahoo(fsdf,account_entry='TotalAssets',suffix='_begin'):
816
959
  """
817
960
  功能:以上年年报期末科目数值作为本期年报和季报的期初,仅适用于雅虎财报!
818
961
  """
siat/financials2.py CHANGED
@@ -104,17 +104,38 @@ def fs_analysis(tickers,fsdates=[],analysis_type='balance sheet', \
104
104
  category='profile',business_period='annual', \
105
105
  scale1=10,scale2=10,dupont_sort='PM',
106
106
  printout=True, \
107
- entry_sort=False, \
107
+ #entry_sort=False, \
108
108
  facecolor='papayawhip',font_size='16px'
109
109
  ):
110
110
  """
111
- 功能:tickers为股票列表,fsdates为财报日期,可为单个日期或日期列表
111
+
112
+ 功能:分析境外上市公司财报信息
113
+
114
+ 参数:
115
+ tickers:股票列表,对比分析时需要多个股票,单列财报时仅取第一个股票
116
+ fsdates:财报日期,可为单个日期或日期列表,注意境外上市公司财报日期与中国大陆的不同
117
+
118
+ analysis_type:分析类型,可为企业概况('profile')、资产负债表简表('balance sheet')、
119
+ 利润表简表('income statement')、现金流量表简表('cash flow')、财报概况('financial summary')、
120
+ 财务比率('financial indicator')、杜邦分析('dupont identity')
121
+
122
+ category:企业概况分类,,仅当analysis_type='profile'时有效,
123
+ 可为基本信息'profile'、高管概况('officers')、分红('dividend')、股票分拆('split')、市场表现('market')、
124
+ 财务状况('financial')、一般风险('risk')、ESG风险('esg')
125
+
126
+ business_period:业务期间类型,可为季报'quarterly',年报'annual'、最近的6次报告'recent', 所有'all'
127
+ scale1:仅用于杜邦分析,放大倍数(以便缩小与EM之间的数量级差异),用于Profit Margin,默认10
128
+ scale2:仅用于杜邦分析,放大倍数,用于Total Asset Turnover,默认10
129
+ dupont_sort:仅用于杜邦分析,用于排序指标,默认净利润率'PM',还可为总资产周转率'TAT'或权益乘数'EM'
130
+ printout:是否显示数据表,默认是True
131
+ facecolor:背景颜色,默认小麦黄'papayawhip'
132
+ font_size:标题字体大小,默认'16px'
133
+
112
134
  注意1:仅从雅虎财经获取数据
113
135
  注意2:不同经济体上市公司报表币种可能不同,金额项目仅进行同公司对比,不进行公司间对比
114
- 注意3:公司间仅对比财务比率
136
+ 注意3:公司间仅对比财务比率和杜邦分析
115
137
  注意4:不同经济体上市公司年报季报日期不同,需要列示报表日期和类型(年报或季报)
116
-
117
- business_period:取季报'quarterly',年报'annual',最近的6次报告'recent', 所有'all'
138
+
118
139
  """
119
140
  import numpy as np
120
141
 
@@ -177,9 +198,11 @@ def fs_analysis(tickers,fsdates=[],analysis_type='balance sheet', \
177
198
  info=get_stock_profile(tickers,info_type=category)
178
199
 
179
200
  elif contains_any(category,['risk']):
201
+ #这里的是风险指标,数值越大风险越高,数值越小越好
180
202
  category='risk_general'
181
203
  info=get_stock_profile(tickers,info_type=category)
182
204
  elif contains_any(category,['esg']):
205
+ #这里的ESG为风险指标,数值越大风险越高,数值越小越好
183
206
  category='risk_esg'
184
207
  info=get_stock_profile(tickers,info_type=category)
185
208
  else:
@@ -200,7 +223,7 @@ def fs_analysis(tickers,fsdates=[],analysis_type='balance sheet', \
200
223
  # 分析资产负债表
201
224
  fsdf=get_balance_sheet(symbol=tickers)
202
225
  if fsdf is None:
203
- print(" #Warning(fs_analysis): financial info unaccessible for",tickers,"\b, which needs connection to Yahoo Finance")
226
+ print(" #Warning(fs_analysis): financial info unaccessible for",tickers,"\b, which needs connection to Yahoo")
204
227
  return None
205
228
 
206
229
  fsdf['reportDate']=fsdf['asOfDate'].apply(lambda x: x.strftime('%y-%m-%d'))
@@ -245,7 +268,7 @@ def fs_analysis(tickers,fsdates=[],analysis_type='balance sheet', \
245
268
  fsdf4.replace(0,'---',inplace=True)
246
269
 
247
270
  #titletxt="\n***** "+ticker_name(tickers)+": BALANCE SHEET"+' *****\n'
248
- titletxt=ticker_name(tickers,'stock')+": BALANCE SHEET"
271
+ titletxt=ticker_name(tickers,'stock')+text_lang(":资产负债简表",": BALANCE SHEET")
249
272
  #print(titletxt)
250
273
  """
251
274
  tablefmt_list=["plain","simple","github","grid","simple_grid","rounded_grid", \
@@ -347,7 +370,7 @@ def fs_analysis(tickers,fsdates=[],analysis_type='balance sheet', \
347
370
  fsdf4.replace(0,'---',inplace=True)
348
371
 
349
372
  #titletxt="\n***** "+ticker_name(tickers)+": INCOME STATEMENTS"+' *****\n'
350
- titletxt=ticker_name(tickers,'stock')+": INCOME STATEMENTS"
373
+ titletxt=ticker_name(tickers,'stock')+text_lang(":利润简表",": INCOME STATEMENTS")
351
374
  #print(titletxt)
352
375
 
353
376
  collist=list(fsdf4)
@@ -427,7 +450,7 @@ def fs_analysis(tickers,fsdates=[],analysis_type='balance sheet', \
427
450
  fsdf4.replace(0,'---',inplace=True)
428
451
 
429
452
  #titletxt="\n***** "+ticker_name(tickers)+": CASHFLOW STATEMENTS"+' *****\n'
430
- titletxt=ticker_name(tickers,'stock')+": CASHFLOW STATEMENTS"
453
+ titletxt=ticker_name(tickers,'stock')+text_lang(":现金流量简表",": CASHFLOW STATEMENTS")
431
454
  #print(titletxt)
432
455
 
433
456
  collist=list(fsdf4)
@@ -536,7 +559,7 @@ def fs_analysis(tickers,fsdates=[],analysis_type='balance sheet', \
536
559
  fsdf4.replace(0,'---',inplace=True)
537
560
 
538
561
  #titletxt="\n***** "+ticker_name(tickers)+": FINANCIAL STATEMENT SUMMARY"+' *****\n'
539
- titletxt=ticker_name(tickers,'stock')+": FINANCIAL STATEMENT SUMMARY"
562
+ titletxt=ticker_name(tickers,'stock')+text_lang(":财报摘要",": FINANCIAL STATEMENT SUMMARY")
540
563
  #print(titletxt)
541
564
 
542
565
  collist=list(fsdf4)
@@ -638,7 +661,7 @@ def fs_analysis(tickers,fsdates=[],analysis_type='balance sheet', \
638
661
  fsdf4.replace(0,'---',inplace=True)
639
662
 
640
663
  #titletxt="\n***** PEER COMPARISON OF FINANCIAL STATEMENT SUMMARY *****\n"
641
- titletxt="FINANCIAL STATEMENT SUMMARY: PEER COMPARISON"
664
+ titletxt=text_lang("财报摘要对比","FINANCIAL STATEMENT SUMMARY: COMPARISON")
642
665
  #print(titletxt)
643
666
 
644
667
  collist=list(fsdf4)
@@ -746,7 +769,7 @@ def fs_analysis(tickers,fsdates=[],analysis_type='balance sheet', \
746
769
  fsdf4.replace(0,'---',inplace=True)
747
770
 
748
771
  #titletxt="\n***** "+ticker_name(tickers)+": FINANCIAL INDICATORS"+' *****\n'
749
- titletxt=ticker_name(tickers,'stock')+": FINANCIAL INDICATORS"
772
+ titletxt=ticker_name(tickers,'stock')+text_lang(":财务比率",": FINANCIAL INDICATORS")
750
773
  #print(titletxt)
751
774
 
752
775
  collist=list(fsdf4)
@@ -849,7 +872,7 @@ def fs_analysis(tickers,fsdates=[],analysis_type='balance sheet', \
849
872
  fsdf4.replace(0,'---',inplace=True)
850
873
 
851
874
  #titletxt="\n***** PEER COMPARISON OF FINANCIAL INDICATORS *****\n"
852
- titletxt="FINANCIAL INDICATORS: PEER COMPARISON"
875
+ titletxt=text_lang("财务比率对比","FINANCIAL INDICATORS: COMPARISON")
853
876
  #print(titletxt)
854
877
 
855
878
  collist=list(fsdf4)
@@ -963,21 +986,21 @@ def fs_analysis(tickers,fsdates=[],analysis_type='balance sheet', \
963
986
  plt.ylabel("Items (Amplified)")
964
987
 
965
988
  footnote1="[Bar amplifier] "+name1+':x'+str(scale1)+','+name2+':x'+str(scale2)
966
- footnote2='Financial statement period: '+fin_period+'. Bar height does not indicate ROE value.'
989
+ footnote2='Statement period: '+fin_period+'. Bar height does not indicate ROE value.'
967
990
  footnote3="Data source: Yahoo Finance,"+todaydt
968
991
  footnote ='\n'+footnote1+'\n'+footnote2+'\n'+footnote3
969
992
  plt.xlabel(footnote,fontsize=10)
970
993
 
971
994
  plt.legend(loc='best',fontsize=10)
972
- plt.title("Dupont Identity Analysis")
995
+ plt.title(text_lang("杜邦分析对比","Dupont Identity Analysis"))
973
996
  plt.xlim([min(tick_pos)-w,max(tick_pos)+w])
974
997
 
975
- plt.gca().set_facecolor('whitesmoke')
998
+ plt.gca().set_facecolor(facecolor)
976
999
  plt.show()
977
1000
 
978
1001
  if printout:
979
1002
  #title_txt="\n***** Dupont Identity Fact Sheet *****\n"
980
- titletxt="Dupont Identity Fact Sheet"
1003
+ titletxt=text_lang("杜邦分析数据表","Dupont Identity Fact Sheet")
981
1004
  #print(titletxt)
982
1005
 
983
1006
  # 保留四位小数
@@ -998,7 +1021,7 @@ def fs_analysis(tickers,fsdates=[],analysis_type='balance sheet', \
998
1021
  footnote2="Data source: Yahoo Finance, "+str(todaydt)
999
1022
  footnote='Note:\n'+footnote1+'\n'+footnote2
1000
1023
  #print('\n',footnote1,'\b.',footnote2)
1001
- df_display_CSS(df,titletxt=titletxt,footnote=footnote,facecolor=facecolor, \
1024
+ df_display_CSS(df,titletxt=titletxt,footnote=footnote,facecolor=facecolor,decimals=4, \
1002
1025
  titile_font_size=titile_font_size,heading_font_size=heading_font_size, \
1003
1026
  data_font_size=data_font_size)
1004
1027
  return df2
siat/grafix.py CHANGED
@@ -1448,6 +1448,25 @@ def plot_line2_twinx2(df01,ticker1,colname1,label1, \
1448
1448
  return
1449
1449
 
1450
1450
  #==============================================================================
1451
+ if __name__ =="__main__":
1452
+ df0=security_trend(['PDD','JD'],annotate=True,graph=False)
1453
+
1454
+ y_label=''; x_label='Footnote'
1455
+ axhline_value=0; axhline_label=''
1456
+ title_txt='Title'
1457
+ data_label=False
1458
+ resample_freq='H'; smooth=True
1459
+ linewidth=1.5
1460
+ loc='best'
1461
+ annotate=True; annotate_value=True
1462
+ plus_sign=False
1463
+ attention_value=''; attention_value_area=''
1464
+ attention_point=''; attention_point_area=''
1465
+ mark_top=False; mark_bottom=False; mark_end=False
1466
+ ticker_type='auto'
1467
+ facecolor='whitesmoke'
1468
+
1469
+
1451
1470
  def draw_lines(df0,y_label,x_label,axhline_value,axhline_label,title_txt, \
1452
1471
  data_label=True,resample_freq='H',smooth=True,linewidth=1.5, \
1453
1472
  loc='best',annotate=False,annotate_value=False,plus_sign=False, \
@@ -1758,8 +1777,24 @@ def draw_lines(df0,y_label,x_label,axhline_value,axhline_label,title_txt, \
1758
1777
 
1759
1778
  # 若不绘制annotate,则绘制图例
1760
1779
  #if not annotate:
1761
- plt.legend(loc=loc,fontsize=legend_txt_size)
1780
+ #检查是否存在可绘制的标签,若有则绘制
1781
+ if DEBUG:
1782
+ have_label=False
1783
+ for line in plt.gca().lines:
1784
+ print(f" DEBUG: plt.gca().lines, line={line.get_label()}")
1785
+ if line.get_label() != '':
1786
+ have_label=True
1762
1787
 
1788
+ #plt.legend没有图例标签时会提示信息No artists...
1789
+ if not annotate or attention_value !='' or attention_point !='':
1790
+ plt.legend(loc=loc,fontsize=legend_txt_size)
1791
+
1792
+ """
1793
+ if any([line.get_label() != '' for line in plt.gca().lines]):
1794
+ tuli=plt.legend(loc=loc,fontsize=legend_txt_size)
1795
+ if DEBUG:
1796
+ print(f" DEBUG: result of plt.legend is {tuli}")
1797
+ """
1763
1798
  if plus_sign:
1764
1799
  # 尝试改变纵轴刻度格式:给正数添加正号+,以便突出显示增减幅度
1765
1800
  import matplotlib.ticker as ticker
@@ -2072,7 +2107,9 @@ def draw_lines2(df0,y_label,x_label,axhline_value,axhline_label,title_txt, \
2072
2107
  plt.gca().set_facecolor("whitesmoke")
2073
2108
 
2074
2109
  #if not annotate:
2075
- plt.legend(loc=loc,fontsize=legend_txt_size)
2110
+ #plt.legend没有图例标签时会提示信息No artists...
2111
+ if not annotate or attention_value !='' or attention_point !='':
2112
+ plt.legend(loc=loc,fontsize=legend_txt_size)
2076
2113
 
2077
2114
  #设置绘图风格:关闭网格虚线
2078
2115
  plt.rcParams['axes.grid']=False
siat/translate.py CHANGED
@@ -4554,6 +4554,306 @@ if __name__=='__main__':
4554
4554
  industry_sw_name(icode)
4555
4555
 
4556
4556
  #==============================================================================
4557
-
4557
+ #实现简单中英文短语互译
4558
+ #==============================================================================
4559
+ if __name__ == '__main__':
4560
+ chntext='市盈率'
4561
+ engtext="PE ratio"
4562
+ engtext="P/E ratio"
4563
+
4564
+ zh2en(chntext)
4565
+
4566
+ en2zh(engtext)
4567
+
4568
+
4569
+ def zh2en(text):
4570
+ '''英文转换成中文'''
4571
+
4572
+ from translate import Translator
4573
+ translator = Translator(from_lang="zh", to_lang="en")
4574
+ translation = translator.translate(text)
4575
+
4576
+ return translation
4577
+
4578
+ def en2zh(text):
4579
+ '''中文转换成英文'''
4580
+
4581
+ from translate import Translator
4582
+ translator = Translator(from_lang="en", to_lang="zh")
4583
+ translation = translator.translate(text)
4584
+
4585
+ return translation
4586
+
4587
+ if __name__ == '__main__':
4588
+ chntext='市盈率'
4589
+ engtext1="PE ratio"
4590
+ engtext2="P/E ratio"
4591
+
4592
+ lang_auto(chntext)
4593
+ lang_auto(engtext1)
4594
+ lang_auto(engtext2)
4595
+
4596
+ lang_auto(text)
4597
+
4598
+
4599
+ def lang_auto(text):
4600
+ '''转换字符串text至当前语言环境,基于translate'''
4601
+
4602
+ #注意:这个翻译模块只能每天提供有限单词翻译服务
4603
+ from translate import Translator
4604
+
4605
+ lang_env=check_language()
4606
+ lang_text=detect_language(text)
4607
+
4608
+ #字符串语言与当前环境语言相同,无需翻译,节省运行时间
4609
+ if lang_env==lang_text:
4610
+ return text
4611
+
4612
+ provider_list=['mymemory']
4613
+
4614
+ if lang_env=='Chinese':
4615
+ #translator = Translator(from_lang="en", to_lang="zh")
4616
+ #translator = Translator(to_lang="zh")
4617
+ translator = Translator(to_lang="zh",provider="mymemory")
4618
+ elif lang_env=='English':
4619
+ translator = Translator(to_lang="en")
4620
+ else:
4621
+ return text
4622
+
4623
+ translation = translator.translate(text)
4624
+
4625
+ return translation
4626
+
4627
+ if __name__ == '__main__':
4628
+ text='市盈率'
4629
+ text='贵州茅台'
4630
+ text='五粮液'
4631
+ text='Dividend Payout Ratio'
4632
+ text='asOfDate'
4633
+ text='Cash And Cash Equivalents'
4634
+ text='AccountsReceivableNetSalesAllowance'
4635
+ text='Accounts Receivable Net of Sales Allowance'
4636
+ text='Accounts Payable'
4637
+
4638
+ language_detect=True
4639
+ language_engine=['google','baidu','bing']
4640
+
4641
+ chntext='市盈率'
4642
+ engtext1="PE ratio"
4643
+ engtext2="P/E ratio"
4644
+
4645
+ lang_auto2(text)
4646
+ lang_auto2(text,language_detect=True)
4647
+
4648
+ lang_auto2(chntext)
4649
+ lang_auto2(engtext1)
4650
+ lang_auto2(engtext2)
4651
+
4652
+
4653
+ def lang_auto2(text,language_detect=True,language_engine=['alibaba','google','bing','sogou']):
4654
+ '''转换字符串text至当前语言环境,基于translators,可指定翻译服务器,准确度更高'''
4655
+
4656
+ import translators as ts
4657
+
4658
+ lang_env=check_language()
4659
+
4660
+ if language_detect:
4661
+ lang_text=detect_language(text)
4662
+
4663
+ #字符串语言与当前环境语言相同,无需翻译,节省运行时间
4664
+ if lang_env==lang_text:
4665
+ return text
4666
+
4667
+ success=False
4668
+ if lang_env=='Chinese':
4669
+ #translator支持baidu/bing/google
4670
+ if isinstance(language_engine,str):
4671
+ language_engine=[language_engine]
4672
+
4673
+ for le in language_engine:
4674
+ try:
4675
+ translation = ts.translate_text(text,from_language='en',to_language='zh', translator=le)
4676
+ success=True
4677
+ break
4678
+ except:
4679
+ continue
4680
+ elif lang_env=='English':
4681
+ for le in language_engine:
4682
+ try:
4683
+ translation = ts.translate_text(text,from_language='zh',to_language='en', translator=le)
4684
+ success=True
4685
+ break
4686
+ except:
4687
+ continue
4688
+ else:
4689
+ return text
4690
+
4691
+ if not success:
4692
+ translation = text
4693
+
4694
+ return translation
4695
+
4696
+
4697
+ if __name__ == '__main__':
4698
+ chntext='市盈率'
4699
+ engtext1="PE ratio"
4700
+
4701
+ detect_language(chntext)
4702
+ detect_language(engtext)
4703
+
4704
+ def detect_language(text):
4705
+ '''判断字符串text是中文还是英文'''
4706
+
4707
+ import re
4708
+ chinese_pattern = re.compile(r'[\u4e00-\u9fa5]')
4709
+ english_pattern = re.compile(r'[a-zA-Z]')
4710
+
4711
+ chinese_count = len(chinese_pattern.findall(text))
4712
+ english_count = len(english_pattern.findall(text))
4713
+ total_count = chinese_count + english_count
4714
+
4715
+ if total_count == 0:
4716
+ result='Unknown'
4717
+
4718
+ if chinese_count > english_count:
4719
+ result='Chinese'
4720
+ elif english_count > chinese_count:
4721
+ result='English'
4722
+ else:
4723
+ result='Both'
4724
+
4725
+ return result
4726
+
4727
+
4728
+ if __name__ == '__main__':
4729
+ text='DividendPayoutRatio'
4730
+ text='CashAndCashEquivalents'
4731
+ text='asOfDate'
4732
+
4733
+ text='GrossPPE'
4734
+
4735
+ text='Cash And Cash Equivalents'
4736
+
4737
+ words_split_yahoo(text)
4738
+
4739
+ def words_split_yahoo(text,split_improve=True):
4740
+ '''将雅虎英文财报术语拆分为带空格的词组'''
4741
+
4742
+
4743
+ #替换基于大写字母无法分词的短语
4744
+ text=text.replace("periodType","PeriodType")
4745
+ text=text.replace("Tradeand","TradeAnd")
4746
+
4747
+ words_list=[]
4748
+ start=0
4749
+
4750
+ for i in range(len(text)):
4751
+ c=text[i]
4752
+
4753
+ if (c>='A' and c<='Z') or c==' ':
4754
+ words_list=words_list+[text[start:i].strip(' ')]
4755
+ start=i
4756
+
4757
+ #添加最后一个单词
4758
+ words_list=words_list+[text[start:i+1]]
4759
+
4760
+ special_words=['and','of','in','at','as','for','non','from']
4761
+ words_list2=[]
4762
+ for w in words_list:
4763
+ if text.index(w) == 0:
4764
+ words_list2=words_list2+[w.title()]
4765
+ elif w.lower() in special_words:
4766
+ words_list2=words_list2+[w.lower()]
4767
+ else:
4768
+ words_list2=words_list2+[w]
4769
+
4770
+ text_new=''
4771
+ for w in words_list2:
4772
+ text_new=text_new+' '+w
4773
+
4774
+ #若出现多个空格则替换为单个空格
4775
+ import re
4776
+ text_new=re.sub(r' +', ' ', text_new)
4777
+
4778
+ #去掉首尾的空格
4779
+ text_new=text_new.strip(' ')
4780
+
4781
+
4782
+ #判断大写字母缩写合并
4783
+ prev_c1=''; prev_c2=''
4784
+ text_new2=''
4785
+ for c in text_new:
4786
+ if c>='A' and c<='Z':
4787
+ if prev_c1==' ' and (prev_c2>='A' and prev_c2<='Z'):
4788
+ text_new2=text_new2.strip(' ')+c
4789
+ else:
4790
+ text_new2=text_new2+c
4791
+ else:
4792
+ text_new2=text_new2+c
4793
+
4794
+ prev_c2=prev_c1; prev_c1=c
4795
+
4796
+ #弥补大写字母合并后继词的逻辑缺陷
4797
+ for upl in ['PPE']:
4798
+ text_new2=text_new2.replace(upl,upl+' ')
4799
+ text_new2=re.sub(r' +', ' ', text_new2)
4800
+ text_new2=text_new2.strip(' ')
4801
+
4802
+
4803
+ #替换缩写/简写/容易翻译出错的词,强行规避翻译错误。
4804
+ #注意:不影响未拆分科目名称,仅为翻译用途
4805
+ if split_improve:
4806
+ text_new3=text_new2.replace("PPE","Plant Property and Equipment")
4807
+
4808
+ text_new3=text_new3.replace("Treasury Shares Number","Treasury Shares")
4809
+ text_new3=text_new3.replace("Ordinary Shares Number","Ordinary Shares")
4810
+ text_new3=text_new3.replace(" Gross "," and ")
4811
+ text_new3=text_new3.replace("non Current","Non-current")
4812
+ text_new3=text_new3.replace("Non Current","Non-current")
4813
+ text_new3=text_new3.replace("Short Term","Short-term")
4814
+ text_new3=text_new3.replace("Long Term","Long-term")
4815
+ text_new3=text_new3.replace("Available for Sale","Available-for-sale")
4816
+
4817
+ text_new3=text_new3.replace(" Com "," Common ")
4818
+ text_new3=text_new3.replace(" Net "," Net of ")
4819
+ text_new3=text_new3.replace("Net Income","Net Profit")
4820
+
4821
+ text_new3=text_new3.replace("EBITDA","XXX")
4822
+ text_new3=text_new3.replace("EBIT","Earnings before Interest and Tax")
4823
+ text_new3=text_new3.replace("XXX","EBITDA")
4824
+
4825
+ text_new3=text_new3.replace("Tax Provision","Tax Accrued")
4826
+ text_new3=text_new3.replace("non Operating","Non-operating")
4827
+
4828
+ text_new3=text_new3.replace("Operating Income","Operating Profit")
4829
+ text_new3=text_new3.replace("Pretax Income","Pretax Profit")
4830
+
4831
+ text_new3=text_new3.replace("Current Provisions","Current Reserve")
4832
+
4833
+ text_new3=text_new3.replace("Duefrom ","Due from ")
4834
+ text_new3=text_new3.replace("Dueto ","Due to ")
4835
+
4836
+ text_new3=text_new3.replace("Investmentin ","Investment in ")
4837
+ text_new3=text_new3.replace("Diluted NIAvailto ","Diluted Net Profit Avail to ")
4838
+ text_new3=text_new3.replace(" Noncontrolling "," Non-controlling ")
4839
+ text_new3=text_new3.replace("Other Gand A","Other General and Administrative Expense")
4840
+ text_new3=text_new3.replace("Otherunder ","Other under ")
4841
+ text_new3=text_new3.replace("Mergern Acquisition","Merger and Acquisition")
4842
+ text_new3=text_new3.replace("Write Off","Write-off")
4843
+
4844
+ text_new3=text_new3.replace("Cash Flow From ","Cash Flow from ")
4845
+ text_new3=text_new3.replace("Cash From ","Cash Flow from ")
4846
+ text_new3=text_new3.replace(" From "," from ")
4847
+ text_new3=text_new3.replace("Provisionand","Provision and")
4848
+ text_new3=text_new3.replace("Write-offof","Write-off of")
4849
+ text_new3=text_new3.replace("non Cash","non-Cash")
4850
+ text_new3=text_new3.replace("Changein","Change in")
4851
+
4852
+ else:
4853
+ text_new3=text_new2
4854
+
4855
+ return text_new3
4856
+
4857
+ #==============================================================================
4558
4858
  #==============================================================================
4559
4859
  #==============================================================================
siat/valuation.py CHANGED
@@ -1259,7 +1259,7 @@ def print_valuation(df,indicator='PE',base='',facecolor='whitesmoke'):
1259
1259
  df4=df3[['证券名称',col_mean,'均值排名',col_latest_date,'排名@'+col_latest_date,col_mean_rel,col_latest_rel,'均值对比','对比@'+col_latest_date]]
1260
1260
 
1261
1261
  #titletxt="估值对比:"+ectranslate(indicator)+",降序排列"
1262
- titletxt="估值对比:{0}({1}),降序排列".format(ectranslate(indicator),indicator)
1262
+ titletxt="证券估值对比:{0}({1}),降序排列".format(ectranslate(indicator),indicator)
1263
1263
  """
1264
1264
  print("\n",titletxt,'\n')
1265
1265
  alignlist=['left','right','center','right','center']+['right']*(len(list(df4))-5)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: siat
3
- Version: 3.7.8
3
+ Version: 3.7.9
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
@@ -35,6 +35,8 @@ Requires-Dist: pendulum
35
35
  Requires-Dist: itables
36
36
  Requires-Dist: py-trans
37
37
  Requires-Dist: bottleneck
38
+ Requires-Dist: translate
39
+ Requires-Dist: translators
38
40
 
39
41
 
40
42
  # What is siat?
@@ -36,13 +36,13 @@ siat/event_study.py,sha256=Q_AdnJzxxL6udCjn5LP6rdhOngsDRWPu5udFkK1CJZw,32223
36
36
  siat/exchange_bond_china.pickle,sha256=zDqdPrFacQ0nqjP_SuF6Yy87EgijIRsFvFroW7FAYYY,1265092
37
37
  siat/fama_french.py,sha256=aUTC-67t_CEPbLk4u79woW_zfZ7OCP6Fo4z5EdWCSkQ,48051
38
38
  siat/fama_french_test.py,sha256=M4O23lBKsJxhWHRluwCb3l7HSEn3OFTjzGMpehcevRg,4678
39
- siat/fin_stmt2_yahoo.py,sha256=q4oNv-Wc30Kyuq_lRB0ZMINd33pusxQ3H2BecoFATqo,34297
39
+ siat/fin_stmt2_yahoo.py,sha256=LGmspk0nKyz4X87MtcovZXUfMQkAvrWINuxR4HQ8PI8,41178
40
40
  siat/financial_base.py,sha256=5u298_1OSlgLnDmhXxqvo4WgMM0JKSa_4jBYF-Ilx38,41097
41
41
  siat/financial_statements.py,sha256=xx0SMpFqAMKm6cj8uYeG2RpJE6G-RoJ3NWa33UyaVMk,25414
42
42
  siat/financial_statements_test.py,sha256=FLhx8JD-tVVWSBGux6AMz1jioXX4U4bp9DmgFHYXb_w,716
43
43
  siat/financials.py,sha256=6WOWYift3MpKkNBnvnBFASXy9nKKC6DzAr8rg2XyNtw,80646
44
44
  siat/financials2 - 副本.py,sha256=dKlNjIfKeoSy055fQ6E6TUj9HEoO5Ney9grD84J5kfk,14389
45
- siat/financials2.py,sha256=A6gjqbdNVgA0hloglhPlDR82mHjb3rSskD-s0T8LKg0,47289
45
+ siat/financials2.py,sha256=Se99o3nDn6Tvbpa-oYAWiIAQrQmEDrur2GkSXNElJIc,49125
46
46
  siat/financials_china.py,sha256=Y9QHyJKDgVbkb5L1f65BAiNxLIDmasRUN9_ju4Yby_c,191925
47
47
  siat/financials_china2.py,sha256=NZzpS1eCaxEClOhh8dvfdn88NhIULqeb9E0GUDUiG4U,92892
48
48
  siat/financials_china2_test.py,sha256=Erz5k4LyOplBBvYls2MypuqHpVNJ3daiLdyeJezNPu0,2722
@@ -62,7 +62,7 @@ siat/future_china.py,sha256=F-HsIf2Op8Z22RzTjet1g8COzldgnMjFNSXsAkeGyWo,17595
62
62
  siat/future_china_test.py,sha256=BrSzmDVaOHki6rntOtosmRn-6dkfOBuLulJNqh7MOpc,1163
63
63
  siat/global_index_test.py,sha256=hnFp3wqqzzL-kAP8mgxDZ54Bd5Ijf6ENi5YJlGBgcXw,2402
64
64
  siat/google_authenticator.py,sha256=ZUbZR8OW0IAKDbcYtlqGqIpZdERpFor9NccFELxg9yI,1637
65
- siat/grafix.py,sha256=EYgRBCfUTgJ9B5rTCzhO9UoABM1amTPUVXkOeKWpgGg,108806
65
+ siat/grafix.py,sha256=WH_-a-R-zyKhT4t4NM24gYZWKyvIexN9LfXVQf-1zxA,110166
66
66
  siat/grafix_test.py,sha256=kXvcpLgQNO7wd30g_bWljLj5UH7bIVI0_dUtXbfiKR0,3150
67
67
  siat/holding_risk.py,sha256=G3wpaewAKF9CwEqRpr4khyuDu9SU2EGyQUHdk7cmHOA,30693
68
68
  siat/holding_risk_test.py,sha256=FRlw_9wFG98BYcg_cSj95HX5WZ1TvkGaOUdXD7-V86s,474
@@ -133,17 +133,17 @@ siat/transaction_test.py,sha256=Z8g1LJCN4-mnUByXMUMoFmN0t105cbmsz2QmvSuIkbU,1858
133
133
  siat/translate-20230125.py,sha256=NPPSXhT38s5t9fzMvl_fvi4ckSB73ThLmZetVI-xGdU,117953
134
134
  siat/translate-20230206.py,sha256=-vtI125WyaJhmPotOpDAmclt_XnYVaWU9ByLWZ6FyYE,118133
135
135
  siat/translate-20230215.py,sha256=TJgtPE3n8IjljmZ4Pefy8dmHoNdFF-1zpML6BhA9FKE,121657
136
- siat/translate.py,sha256=aAWk9museEsdxDstXjEy_SXiEzvKD_6fDi0W4TrBiwI,241364
136
+ siat/translate.py,sha256=TJKbh9vU-ifEN1V9DnyojJ00qcT_fioooTAa8wrml_s,250970
137
137
  siat/translate_20240606.py,sha256=63IyHWEU3Uz9mjwyuAX3fqY4nUMdwh0ICQAgmgPXP7Y,215121
138
138
  siat/translate_241003_keep.py,sha256=un7Fqe1v35MXsja5exZgjmLzrZtt66NARZIGlyFuGGU,218747
139
139
  siat/universal_test.py,sha256=CDAOffW1Rvs-TcNN5giWVvHMlch1w4dp-w5SIV9jXL0,3936
140
- siat/valuation.py,sha256=DF-THR8AOPFtbMG58g9coqrfnzeBIhX3PW7ZhU6WbEo,50821
140
+ siat/valuation.py,sha256=XdfTivpr652hRnI6yaB9mpA0JlXFJphJsTqcw2_FnMM,50827
141
141
  siat/valuation_china.py,sha256=CVp1IwIsF3Om0J29RGkyxZLt4n9Ug-ua_RKhLwL9fUQ,69624
142
142
  siat/valuation_market_china_test.py,sha256=gbJ0ioauuo4koTPH6WKUkqcXiQPafnbhU5eKJ6lpdLA,1571
143
143
  siat/var_model_validation.py,sha256=R0caWnuZarrRg9939hxh3vJIIpIyPfvelYmzFNZtPbo,14910
144
144
  siat/yf_name.py,sha256=r0Q67cSMMlfebEkI9h9pdGlJCooEq7hw_3M5IUs4cSI,20081
145
- siat-3.7.8.dist-info/LICENSE,sha256=NTEMMROY9_4U1szoKC3N2BLHcDd_o5uTgqdVH8tbApw,1071
146
- siat-3.7.8.dist-info/METADATA,sha256=eDkDeMALXeeUIhn3YcgdI7vzLy2P4qCAR8ErzLuv5p4,8009
147
- siat-3.7.8.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
148
- siat-3.7.8.dist-info/top_level.txt,sha256=r1cVyL7AIKqeAmEJjNR8FMT20OmEzufDstC2gv3NvEY,5
149
- siat-3.7.8.dist-info/RECORD,,
145
+ siat-3.7.9.dist-info/LICENSE,sha256=NTEMMROY9_4U1szoKC3N2BLHcDd_o5uTgqdVH8tbApw,1071
146
+ siat-3.7.9.dist-info/METADATA,sha256=pyvIy9bezvnV0iI6yULlndis1yvpId_7ufTIqlsYF_A,8063
147
+ siat-3.7.9.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
148
+ siat-3.7.9.dist-info/top_level.txt,sha256=r1cVyL7AIKqeAmEJjNR8FMT20OmEzufDstC2gv3NvEY,5
149
+ siat-3.7.9.dist-info/RECORD,,
File without changes
File without changes