siat 3.9.22__py3-none-any.whl → 3.9.32__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/__init__.py CHANGED
@@ -40,7 +40,7 @@ if os == 'windows':
40
40
  srcfile=srcpath1+'/'+tagfile
41
41
  else:
42
42
  srcpath1=srcpath
43
- srcfile=srcpath1+'/'+file
43
+ srcfile=srcpath1+'/'+tagfile
44
44
 
45
45
  try:
46
46
  with open(srcfile,'rb') as file:
@@ -70,6 +70,6 @@ if not restart:
70
70
  else:
71
71
  with HiddenPrints():
72
72
  fix_package()
73
- print(" Please RESTART Python kernel and run this command again")
73
+ print(" Please RESTART Python kernel and then run this command again")
74
74
 
75
75
  #==============================================================================
siat/common.py CHANGED
@@ -3501,7 +3501,7 @@ if __name__=='__main__':
3501
3501
 
3502
3502
  test_website(url)
3503
3503
 
3504
- def test_website(url):
3504
+ def test_website(url="https://finance.yahoo.com"):
3505
3505
  """
3506
3506
  功能:测试一个网址是否可访问
3507
3507
  """
@@ -5000,6 +5000,79 @@ def shift_column_position(df,col_name,position=1):
5000
5000
 
5001
5001
  return df
5002
5002
  #==============================================================================
5003
+ if __name__ == '__main__':
5004
+ text='accountsReceivable'
5005
+ text='periodType'
5006
+ text='reportDate'
5007
+ text='currencyCode'
5008
+ text='BasicEPS'
5009
+ text='EBITDA'
5010
+ text='CashAndCashEquivalents'
5011
+ text='Debt to Asset'
5012
+
5013
+ text_separate(text)
5014
+
5015
+ def text_separate(text):
5016
+ """
5017
+ 功能:将连写在一起的专业术语拆分成为正常的形式
5018
+ 参数:
5019
+ text:待拆分短语,例如accountsReceivable
5020
+ 输出:拆分后短语,例如Accounts Receivable
5021
+ """
5022
+ DEBUG=False
5023
+
5024
+ if not text:
5025
+ return ""
5026
+
5027
+ articles={"and","from","in","on","the","of","to","for","not","non","as","per"}
5028
+
5029
+ words = []
5030
+ current_word = [text[0].upper()] # 首字母默认大写
5031
+ for i in range(1, len(text)):
5032
+ prev_char, curr_char = text[i-1], text[i]
5033
+
5034
+ # 分割条件:当前大写且前一个字符为小写,或当前大写后跟小写(保留连续大写)
5035
+ if (curr_char.isupper() and prev_char.islower()) or \
5036
+ (curr_char.isupper() and prev_char.isupper() and i < len(text)-1 and text[i+1].islower()):
5037
+ words.append(''.join(current_word))
5038
+ current_word = [curr_char]
5039
+ else:
5040
+ current_word.append(curr_char)
5041
+ words.append(''.join(current_word))
5042
+
5043
+ # 处理虚词:除首单词外,虚词首字母小写
5044
+ formatted_words = [words[0]]
5045
+ for word in words[1:]:
5046
+ lower_word = word.lower()
5047
+ formatted_words.append(lower_word if lower_word in articles else word)
5048
+
5049
+ words2=' '.join(formatted_words)
5050
+
5051
+ if DEBUG:
5052
+ print(f"BEFORE: {text}, AFTER: {words2}")
5053
+
5054
+ return words2
5055
+
5056
+ #==============================================================================
5057
+ if __name__ == '__main__':
5058
+ alist=['a','b','c']
5059
+ element='b'
5060
+ element='c'
5061
+
5062
+ last_in_list(element,alist)
5063
+
5064
+ def last_in_list(element,alist):
5065
+ """
5066
+ 功能:测试element是否alist的最后一个元素
5067
+ 参数:
5068
+ element:alist的元素,用于循环
5069
+ alist:列表,用于循环
5070
+ """
5071
+ result=False
5072
+ if alist.index(element) == len(alist)-1:
5073
+ result=True
5074
+
5075
+ return result
5003
5076
  #==============================================================================
5004
5077
  #==============================================================================
5005
5078
  #==============================================================================
@@ -53,7 +53,8 @@ def get_balance_sheet(symbol):
53
53
  stmta=stock.balance_sheet() # Defaults to Annual
54
54
  except:
55
55
  print(" Searching for annual report failed, recovering......")
56
- time.sleep(5)
56
+ sleep_random(max_sleep=60)
57
+
57
58
  try:
58
59
  stmta=stock.balance_sheet()
59
60
  except:
@@ -76,7 +77,8 @@ def get_balance_sheet(symbol):
76
77
  stmtq=stock.balance_sheet(frequency="q")
77
78
  except:
78
79
  print(" Searching for quarterly report failed, recovering......")
79
- time.sleep(5)
80
+ sleep_random(max_sleep=60)
81
+
80
82
  try:
81
83
  stmtq=stock.balance_sheet(frequency="q")
82
84
  except:
@@ -195,7 +197,7 @@ def get_income_statements(symbol):
195
197
  stmta=stock.income_statement() # Defaults to Annual
196
198
  except:
197
199
  print(" Searching for annual report failed, recovering......")
198
- time.sleep(5)
200
+ sleep_random(max_sleep=60)
199
201
  try:
200
202
  stmta=stock.income_statement()
201
203
  except:
@@ -218,7 +220,7 @@ def get_income_statements(symbol):
218
220
  stmtq=stock.income_statement(frequency="q")
219
221
  except:
220
222
  print(" Searching for quarterly report failed, recovering......")
221
- time.sleep(5)
223
+ sleep_random(max_sleep=60)
222
224
  try:
223
225
  stmtq=stock.income_statement(frequency="q")
224
226
  except:
@@ -310,7 +312,7 @@ def get_cashflow_statements(symbol):
310
312
  stmta=stock.cash_flow() # Defaults to Annual
311
313
  except:
312
314
  print(" Searching for annual report failed, recovering......")
313
- time.sleep(5)
315
+ sleep_random(max_sleep=60)
314
316
  try:
315
317
  stmta=stock.cash_flow()
316
318
  except:
@@ -333,7 +335,7 @@ def get_cashflow_statements(symbol):
333
335
  stmtq=stock.cash_flow(frequency="q")
334
336
  except:
335
337
  print(" Searching for quarterly report failed, recovering......")
336
- time.sleep(5)
338
+ sleep_random(max_sleep=60)
337
339
  try:
338
340
  stmtq=stock.cash_flow(frequency="q")
339
341
  except:
@@ -407,11 +409,11 @@ def get_financial_statements(ticker):
407
409
  fbs = get_balance_sheet(ticker)
408
410
  except:
409
411
  print(" Retrieving fin info failed, trying to recover...")
410
- import time; time.sleep(3)
412
+ sleep_random(max_sleep=60)
411
413
  try:
412
414
  fbs = get_balance_sheet(ticker)
413
415
  except:
414
- import time; time.sleep(5)
416
+ sleep_random(max_sleep=60)
415
417
  try:
416
418
  fbs = get_balance_sheet(ticker)
417
419
  except:
@@ -426,11 +428,11 @@ def get_financial_statements(ticker):
426
428
  fis = get_income_statements(ticker)
427
429
  except:
428
430
  print(" Failed, recovering...")
429
- import time; time.sleep(3)
431
+ sleep_random(max_sleep=60)
430
432
  try:
431
433
  fis = get_income_statements(ticker)
432
434
  except:
433
- import time; time.sleep(5)
435
+ sleep_random(max_sleep=60)
434
436
  try:
435
437
  fis = get_income_statements(ticker)
436
438
  except:
@@ -445,11 +447,11 @@ def get_financial_statements(ticker):
445
447
  fcf = get_cashflow_statements(ticker)
446
448
  except:
447
449
  print(" Failed, recovering...")
448
- import time; time.sleep(3)
450
+ sleep_random(max_sleep=60)
449
451
  try:
450
452
  fcf = get_cashflow_statements(ticker)
451
453
  except:
452
- import time; time.sleep(5)
454
+ sleep_random(max_sleep=60)
453
455
  try:
454
456
  fcf = get_cashflow_statements(ticker)
455
457
  except:
siat/financials.py CHANGED
@@ -1186,7 +1186,7 @@ def get_financial_rates(ticker):
1186
1186
  fsdf=get_financial_statements(ticker)
1187
1187
  except:
1188
1188
  print(" Failed to get financial statements of",ticker,"\b, recovering")
1189
- import time; time.sleep(5)
1189
+ sleep_random(max_sleep=60)
1190
1190
  try:
1191
1191
  fsdf=get_financial_statements(ticker)
1192
1192
  except:
siat/financials2.py CHANGED
@@ -103,6 +103,7 @@ if __name__=='__main__':
103
103
 
104
104
  def fs_analysis(tickers,fsdates=[],analysis_type='balance sheet', \
105
105
  category='profile',business_period='annual', \
106
+ items_included='all', \
106
107
  scale1=10,scale2=10,dupont_sort='PM',
107
108
  printout=True, \
108
109
  #entry_sort=False, \
@@ -125,6 +126,7 @@ def fs_analysis(tickers,fsdates=[],analysis_type='balance sheet', \
125
126
  财务状况('financial')、一般风险('risk')、ESG风险('esg')
126
127
 
127
128
  business_period:业务期间类型,可为季报'quarterly',默认年报'annual'、最近的6次报告'recent', 所有'all'
129
+ items_included:默认输出所有报表项目,可以列表形式选择其中一部分。
128
130
  scale1:仅用于杜邦分析,放大倍数(以便缩小与EM之间的数量级差异),用于Profit Margin,默认10
129
131
  scale2:仅用于杜邦分析,放大倍数,用于Total Asset Turnover,默认10
130
132
  dupont_sort:仅用于杜邦分析,用于排序指标,默认净利润率'PM',还可为总资产周转率'TAT'或权益乘数'EM'
@@ -179,7 +181,10 @@ def fs_analysis(tickers,fsdates=[],analysis_type='balance sheet', \
179
181
  注意4:不同经济体上市公司年报季报日期不同,需要列示报表日期和类型(年报或季报)
180
182
 
181
183
  """
184
+ DEBUG=False
185
+
182
186
  import numpy as np
187
+ import pandas as pd
183
188
 
184
189
  #屏蔽函数内print信息输出的类
185
190
  import os, sys
@@ -265,8 +270,11 @@ def fs_analysis(tickers,fsdates=[],analysis_type='balance sheet', \
265
270
  # 分析资产负债表
266
271
  fsdf=get_balance_sheet(symbol=tickers)
267
272
  if fsdf is None:
268
- #print(" #Warning(fs_analysis): financial info unaccessible for",tickers,"\b, which needs connection to Yahoo")
269
- print(" #Warning(fs_analysis): financial info unaccessible for",tickers)
273
+ print(f" #Warning(fs_analysis): failed to access financial info for {tickers}")
274
+ if test_yahoo_access():
275
+ print(f" Solution: if {tickers} are correct, then try again later")
276
+ else:
277
+ print(" Problem: no internet connection to Yahoo for retrieveing data")
270
278
  return None
271
279
 
272
280
  fsdf['reportDate']=fsdf['asOfDate'].apply(lambda x: x.strftime('%y-%m-%d'))
@@ -350,7 +358,22 @@ def fs_analysis(tickers,fsdates=[],analysis_type='balance sheet', \
350
358
  footnote2="Data source: Yahoo Finance, "+str(todaydt)
351
359
  footnote='Note:\n'+footnote1+'\n'+footnote2
352
360
  #print('\n',footnote1,'\n',footnote2)
353
- df_display_CSS(fsdf6,titletxt=titletxt,footnote=footnote,facecolor=facecolor, \
361
+
362
+ # 将Item科目名称拆分加空格和转大写
363
+ fsdf6['Item']=fsdf6['Item'].apply(lambda x: text_separate(x))
364
+
365
+ # 判断是否仅输出部分科目
366
+ if 'all' in items_included:
367
+ fsdf7=fsdf6
368
+ else:
369
+ mask=fsdf6['Item'].isin(items_included)
370
+ fsdf7=fsdf6[mask]
371
+ # 将Item列转为分类类型,指定顺序
372
+ fsdf7['Item'] = pd.Categorical(fsdf7['Item'], categories=items_included, ordered=True)
373
+ # 按分类顺序排序
374
+ fsdf7=fsdf7.sort_values(by='Item')
375
+
376
+ df_display_CSS(fsdf7,titletxt=titletxt,footnote=footnote,facecolor=facecolor, \
354
377
  titile_font_size=titile_font_size,heading_font_size=heading_font_size, \
355
378
  data_font_size=data_font_size)
356
379
 
@@ -371,6 +394,11 @@ def fs_analysis(tickers,fsdates=[],analysis_type='balance sheet', \
371
394
  fsdf=get_income_statements(symbol=tickers)
372
395
  if fsdf is None:
373
396
  print(" #Warning(fs_analysis): financial info unaccessible for",tickers)
397
+ if test_yahoo_access():
398
+ print(f" Solution: if {tickers} are correct, then try again later")
399
+ else:
400
+ print(" Problem: no internet connection to Yahoo for retrieveing data")
401
+
374
402
  return None
375
403
 
376
404
  fsdf['reportDate']=fsdf['asOfDate'].apply(lambda x: x.strftime('%y-%m-%d'))
@@ -431,7 +459,22 @@ def fs_analysis(tickers,fsdates=[],analysis_type='balance sheet', \
431
459
  footnote2="Data source: Yahoo Finance, "+str(todaydt)
432
460
  footnote='Note:\n'+footnote1+'\n'+footnote2
433
461
  #print('\n',footnote1,'\n',footnote2)
434
- df_display_CSS(fsdf6,titletxt=titletxt,footnote=footnote,facecolor=facecolor, \
462
+
463
+ # 将Item科目名称拆分加空格和转大写
464
+ fsdf6['Item']=fsdf6['Item'].apply(lambda x: text_separate(x))
465
+
466
+ # 判断是否仅输出部分科目
467
+ if 'all' in items_included:
468
+ fsdf7=fsdf6
469
+ else:
470
+ mask=fsdf6['Item'].isin(items_included)
471
+ fsdf7=fsdf6[mask]
472
+ # 将Item列转为分类类型,指定顺序
473
+ fsdf7['Item'] = pd.Categorical(fsdf7['Item'], categories=items_included, ordered=True)
474
+ # 按分类顺序排序
475
+ fsdf7=fsdf7.sort_values(by='Item')
476
+
477
+ df_display_CSS(fsdf7,titletxt=titletxt,footnote=footnote,facecolor=facecolor, \
435
478
  titile_font_size=titile_font_size,heading_font_size=heading_font_size, \
436
479
  data_font_size=data_font_size)
437
480
 
@@ -451,6 +494,11 @@ def fs_analysis(tickers,fsdates=[],analysis_type='balance sheet', \
451
494
  fsdf=get_cashflow_statements(symbol=tickers)
452
495
  if fsdf is None:
453
496
  print(" #Warning(fs_analysis): financial info unaccessible for",tickers)
497
+ if test_yahoo_access():
498
+ print(f" Solution: if {tickers} are correct, then try again later")
499
+ else:
500
+ print(" Problem: no internet connection to Yahoo for retrieveing data")
501
+
454
502
  return None
455
503
 
456
504
  fsdf['reportDate']=fsdf['asOfDate'].apply(lambda x: x.strftime('%y-%m-%d'))
@@ -511,7 +559,22 @@ def fs_analysis(tickers,fsdates=[],analysis_type='balance sheet', \
511
559
  footnote2="Data source: Yahoo Finance, "+str(todaydt)
512
560
  footnote='Note:\n'+footnote1+'\n'+footnote2
513
561
  #print('\n',footnote1,'\n',footnote2)
514
- df_display_CSS(fsdf6,titletxt=titletxt,footnote=footnote,facecolor=facecolor, \
562
+
563
+ # 将Item科目名称拆分加空格和转大写
564
+ fsdf6['Item']=fsdf6['Item'].apply(lambda x: text_separate(x))
565
+
566
+ # 判断是否仅输出部分科目
567
+ if 'all' in items_included:
568
+ fsdf7=fsdf6
569
+ else:
570
+ mask=fsdf6['Item'].isin(items_included)
571
+ fsdf7=fsdf6[mask]
572
+ # 将Item列转为分类类型,指定顺序
573
+ fsdf7['Item'] = pd.Categorical(fsdf7['Item'], categories=items_included, ordered=True)
574
+ # 按分类顺序排序
575
+ fsdf7=fsdf7.sort_values(by='Item')
576
+
577
+ df_display_CSS(fsdf7,titletxt=titletxt,footnote=footnote,facecolor=facecolor, \
515
578
  titile_font_size=titile_font_size,heading_font_size=heading_font_size, \
516
579
  data_font_size=data_font_size)
517
580
  return fsdf6
@@ -544,11 +607,16 @@ def fs_analysis(tickers,fsdates=[],analysis_type='balance sheet', \
544
607
 
545
608
  # 股票可为单只股票(单只股票深度分析)
546
609
  if isinstance(tickers,str):
547
- print(" Getting financial rates for financial summary of",tickers,"......")
610
+ print(" Getting financial rates for financial summary of",tickers,"...")
548
611
  with HiddenPrints():
549
612
  fsdf=get_financial_rates(tickers)
550
613
  if fsdf is None:
551
614
  print(" #Warning(fs_analysis): financial info unaccessible for",tickers)
615
+ if test_yahoo_access():
616
+ print(f" Solution: if {tickers} are correct, then try again later")
617
+ else:
618
+ print(" Problem: no internet connection to Yahoo for retrieveing data")
619
+
552
620
  return None
553
621
 
554
622
  fsdf['reportDate']=fsdf['asOfDate'].apply(lambda x: x.strftime('%y-%m-%d'))
@@ -623,7 +691,22 @@ def fs_analysis(tickers,fsdates=[],analysis_type='balance sheet', \
623
691
  footnote3="Data source: Yahoo Finance, "+todaydt
624
692
  footnote='Note:\n'+footnote1+'\n'+footnote2+'\n'+footnote3
625
693
  #print('\n',footnote1,'\n',footnote2,'\n',footnote3)
626
- df_display_CSS(fsdf6,titletxt=titletxt,footnote=footnote,facecolor=facecolor, \
694
+
695
+ # 将Item科目名称拆分加空格和转大写
696
+ fsdf6['Item']=fsdf6['Item'].apply(lambda x: text_separate(x))
697
+
698
+ # 判断是否仅输出部分科目
699
+ if 'all' in items_included:
700
+ fsdf7=fsdf6
701
+ else:
702
+ mask=fsdf6['Item'].isin(items_included)
703
+ fsdf7=fsdf6[mask]
704
+ # 将Item列转为分类类型,指定顺序
705
+ fsdf7['Item'] = pd.Categorical(fsdf7['Item'], categories=items_included, ordered=True)
706
+ # 按分类顺序排序
707
+ fsdf7=fsdf7.sort_values(by='Item')
708
+
709
+ df_display_CSS(fsdf7,titletxt=titletxt,footnote=footnote,facecolor=facecolor, \
627
710
  titile_font_size=titile_font_size,heading_font_size=heading_font_size, \
628
711
  data_font_size=data_font_size)
629
712
  return fsdf6
@@ -636,14 +719,20 @@ def fs_analysis(tickers,fsdates=[],analysis_type='balance sheet', \
636
719
  business_period=business_period.lower()
637
720
  fsdf=pd.DataFrame()
638
721
  for t in tickers:
639
- print(" Getting financial rates for financial summary of",t,"......")
722
+ print(" Getting financial rates for financial summary of",t,"...")
640
723
  with HiddenPrints():
641
724
  dftmp=get_financial_rates(t)
642
725
  if dftmp is None:
643
726
  print(" #Warning(fs_analysis): financial info unaccessible for",t)
644
- print(f" Solution: make sure {t} is correct, try again later")
727
+ if test_yahoo_access():
728
+ print(f" Solution: if {t} are correct, then try again later")
729
+ else:
730
+ print(" Problem: no internet connection to Yahoo for retrieveing data")
645
731
  return None
646
732
 
733
+ if not last_in_list(t,tickers):
734
+ sleep_random(max_sleep=60)
735
+
647
736
  if business_period=='recent':
648
737
  dftmp2=dftmp.tail(1)
649
738
  elif business_period=='annual':
@@ -725,8 +814,23 @@ def fs_analysis(tickers,fsdates=[],analysis_type='balance sheet', \
725
814
  footnote2="ROx/EM/turnover rates are based on periodic mean, others on end-term"
726
815
  footnote3="Data source: Yahoo Finance, "+str(todaydt)
727
816
  footnote='Note:\n'+footnote1+'\n'+footnote2+'\n'+footnote3
728
- #print('\n',footnote1,'\n',footnote2,'\n',footnote3)
729
- df_display_CSS(fsdf6,titletxt=titletxt,footnote=footnote,facecolor=facecolor, \
817
+ #print('\n',footnote1,'\n',footnote2,'\n',footnote3)
818
+
819
+ # 将Item科目名称拆分加空格和转大写
820
+ fsdf6['Item']=fsdf6['Item'].apply(lambda x: text_separate(x))
821
+
822
+ # 判断是否仅输出部分科目
823
+ if 'all' in items_included:
824
+ fsdf7=fsdf6
825
+ else:
826
+ mask=fsdf6['Item'].isin(items_included)
827
+ fsdf7=fsdf6[mask]
828
+ # 将Item列转为分类类型,指定顺序
829
+ fsdf7['Item'] = pd.Categorical(fsdf7['Item'], categories=items_included, ordered=True)
830
+ # 按分类顺序排序
831
+ fsdf7=fsdf7.sort_values(by='Item')
832
+
833
+ df_display_CSS(fsdf7,titletxt=titletxt,footnote=footnote,facecolor=facecolor, \
730
834
  titile_font_size=titile_font_size,heading_font_size=heading_font_size, \
731
835
  data_font_size=data_font_size)
732
836
  return fsdf6
@@ -760,11 +864,16 @@ def fs_analysis(tickers,fsdates=[],analysis_type='balance sheet', \
760
864
 
761
865
  # 股票可为单只股票(单只股票深度分析)
762
866
  if isinstance(tickers,str):
763
- print(" Getting financial rates for financial indicators of",tickers,"......")
867
+ print(" Getting financial rates for financial indicators of",tickers,"...")
764
868
  with HiddenPrints():
765
869
  fsdf=get_financial_rates(tickers)
766
870
  if fsdf is None:
767
871
  print(" #Warning(fs_analysis): financial info unaccessible for",tickers)
872
+ if test_yahoo_access():
873
+ print(f" Solution: if {tickers} are correct, then try again later")
874
+ else:
875
+ print(" Problem: no internet connection to Yahoo for retrieveing data")
876
+
768
877
  return None
769
878
 
770
879
  fsdf['reportDate']=fsdf['asOfDate'].apply(lambda x: x.strftime('%y-%m-%d'))
@@ -835,8 +944,23 @@ def fs_analysis(tickers,fsdates=[],analysis_type='balance sheet', \
835
944
  footnote2="ROx/EM/turnover rates are based on periodic mean, others on end-term"
836
945
  footnote3="Data source: Yahoo Finance, "+str(todaydt)
837
946
  footnote='Note:\n'+footnote1+'\n'+footnote2+'\n'+footnote3
838
- #print('\n',footnote1,'\n',footnote2,'\n',footnote3)
839
- df_display_CSS(fsdf6,titletxt=titletxt,footnote=footnote,facecolor=facecolor, \
947
+ #print('\n',footnote1,'\n',footnote2,'\n',footnote3)
948
+
949
+ # 将Item科目名称拆分加空格和转大写
950
+ fsdf6['Item']=fsdf6['Item'].apply(lambda x: text_separate(x))
951
+
952
+ # 判断是否仅输出部分科目
953
+ if 'all' in items_included:
954
+ fsdf7=fsdf6
955
+ else:
956
+ mask=fsdf6['Item'].isin(items_included)
957
+ fsdf7=fsdf6[mask]
958
+ # 将Item列转为分类类型,指定顺序
959
+ fsdf7['Item'] = pd.Categorical(fsdf7['Item'], categories=items_included, ordered=True)
960
+ # 按分类顺序排序
961
+ fsdf7=fsdf7.sort_values(by='Item')
962
+
963
+ df_display_CSS(fsdf7,titletxt=titletxt,footnote=footnote,facecolor=facecolor, \
840
964
  titile_font_size=titile_font_size,heading_font_size=heading_font_size, \
841
965
  data_font_size=data_font_size)
842
966
  return fsdf6
@@ -848,18 +972,28 @@ def fs_analysis(tickers,fsdates=[],analysis_type='balance sheet', \
848
972
 
849
973
  business_period=business_period.lower()
850
974
  fsdf=pd.DataFrame()
975
+ print(" Working on financial rates, it may take long time ...")
976
+
851
977
  for t in tickers:
852
- print(" Getting financial rates for financial indicators of",t,"......")
978
+ print(" Getting financial rates for financial indicators of",t,"...")
853
979
  with HiddenPrints():
854
980
  dftmp=get_financial_rates(t)
855
981
  if dftmp is None:
856
982
  print(" #Warning(fs_analysis): financial info unaccessible for",t)
983
+ if test_yahoo_access():
984
+ print(f" Solution: if {t} are correct, then try again later")
985
+ else:
986
+ print(" Problem: no internet connection to Yahoo for retrieveing data")
987
+
857
988
  return None
858
989
 
859
- if dftmp is None:
860
- print(" #Warning(fs_analysis): none of financial indicators found for stock",t)
990
+ if len(dftmp) == 0:
991
+ print(" #Warning(fs_analysis): zero financial indicators found for stock",t)
861
992
  continue
862
993
 
994
+ if not last_in_list(t,tickers):
995
+ sleep_random(max_sleep=60)
996
+
863
997
  if business_period=='recent':
864
998
  dftmp2=dftmp.tail(1)
865
999
  elif business_period=='annual':
@@ -938,8 +1072,26 @@ def fs_analysis(tickers,fsdates=[],analysis_type='balance sheet', \
938
1072
  footnote2="ROx/EM/turnover rates are based on periodic mean, others on end-term"
939
1073
  footnote3="Data source: Yahoo Finance, "+str(todaydt)
940
1074
  footnote='Note:\n'+footnote1+'\n'+footnote2+'\n'+footnote3
941
- #print('\n',footnote1,'\n',footnote2,'\n',footnote3)
942
- df_display_CSS(fsdf6,titletxt=titletxt,footnote=footnote,facecolor=facecolor, \
1075
+ #print('\n',footnote1,'\n',footnote2,'\n',footnote3)
1076
+
1077
+ # 将Item科目名称拆分加空格和转大写
1078
+ fsdf6['Item']=fsdf6['Item'].apply(lambda x: text_separate(x))
1079
+
1080
+ # 将Item科目名称拆分加空格和转大写
1081
+ fsdf6['Item']=fsdf6['Item'].apply(lambda x: text_separate(x))
1082
+
1083
+ # 判断是否仅输出部分科目
1084
+ if 'all' in items_included:
1085
+ fsdf7=fsdf6
1086
+ else:
1087
+ mask=fsdf6['Item'].isin(items_included)
1088
+ fsdf7=fsdf6[mask]
1089
+ # 将Item列转为分类类型,指定顺序
1090
+ fsdf7['Item'] = pd.Categorical(fsdf7['Item'], categories=items_included, ordered=True)
1091
+ # 按分类顺序排序
1092
+ fsdf7=fsdf7.sort_values(by='Item')
1093
+
1094
+ df_display_CSS(fsdf7,titletxt=titletxt,footnote=footnote,facecolor=facecolor, \
943
1095
  titile_font_size=titile_font_size,heading_font_size=heading_font_size, \
944
1096
  data_font_size=data_font_size)
945
1097
  return fsdf6
@@ -955,14 +1107,23 @@ def fs_analysis(tickers,fsdates=[],analysis_type='balance sheet', \
955
1107
 
956
1108
  business_period=business_period.lower()
957
1109
  fsdf=pd.DataFrame()
1110
+ print(" Working on dupont identity, it may take long time ...")
958
1111
  for t in tickers:
959
- print(" Getting financial rates for dupont identity of",t,"......")
1112
+ print(" Getting financial rates for dupont identity of",t,"...")
960
1113
  with HiddenPrints():
961
1114
  dftmp=get_financial_rates(t)
962
1115
  if dftmp is None:
963
1116
  print(" #Warning(fs_analysis): financial info unaccessible for",t)
1117
+ if test_yahoo_access():
1118
+ print(f" Solution: if {t} are correct, then try again later")
1119
+ else:
1120
+ print(" Problem: no internet connection to Yahoo for retrieveing data")
1121
+
964
1122
  return None
965
1123
 
1124
+ if not last_in_list(t,tickers):
1125
+ sleep_random(max_sleep=60)
1126
+
966
1127
  if business_period=='recent':
967
1128
  dftmp2=dftmp.tail(1)
968
1129
  elif business_period=='annual':
@@ -1070,7 +1231,11 @@ def fs_analysis(tickers,fsdates=[],analysis_type='balance sheet', \
1070
1231
  footnote1="Based on exchange's local accounting standards, EM/TAT are on periodic mean"
1071
1232
  footnote2="Data source: Yahoo Finance, "+str(todaydt)
1072
1233
  footnote='Note:\n'+footnote1+'\n'+footnote2
1073
- #print('\n',footnote1,'\b.',footnote2)
1234
+ #print('\n',footnote1,'\b.',footnote2)
1235
+
1236
+ # 将Item科目名称拆分加空格和转大写
1237
+ df['Item']=df['Item'].apply(lambda x: text_separate(x))
1238
+
1074
1239
  df_display_CSS(df,titletxt=titletxt,footnote=footnote,facecolor=facecolor,decimals=4, \
1075
1240
  titile_font_size=titile_font_size,heading_font_size=heading_font_size, \
1076
1241
  data_font_size=data_font_size)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: siat
3
- Version: 3.9.22
3
+ Version: 3.9.32
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
@@ -1,5 +1,5 @@
1
1
  siat/__init__ -20240701.py,sha256=gP5uajXnJesnH5SL0ZPwq_Qhv59AG1bs4qwZv26Fo2Y,2894
2
- siat/__init__.py,sha256=tpSBf8BYpWOzBDF2iNQ4tlVxjx7bmkVQ3kPUu9X3iog,2227
2
+ siat/__init__.py,sha256=LZKNrzk9Ibuzpox_Fy4zzxvAZLvtgVFeKMEY5go6ns0,2235
3
3
  siat/__init__.py.backup_20250214.py,sha256=pIo4CV3lNPKIhitmhIh_6aAfZrmzQWGNDcEnvZ7GXoc,3216
4
4
  siat/allin.py,sha256=--32Bt2Mfg7l38w7X9cLJCdWtYRB3tTtVHnS9WnqKDI,3035
5
5
  siat/alpha_vantage_test.py,sha256=tKr-vmuFH3CZAqwmISz6jzjPHzV1JJl3sPfZdz8aTfM,747
@@ -19,7 +19,7 @@ siat/capm_beta.py,sha256=cxXdRVBQBllhbfz1LeTJAIWvyRYhW54nhtNUXv4HwS0,29063
19
19
  siat/capm_beta2.py,sha256=wGF_HmK_AiGWjpSAx79XHIxDghtI_ueYozvh06-2JEQ,33707
20
20
  siat/capm_beta_test.py,sha256=ImR0c5mc4hIl714XmHztdl7qg8v1E2lycKyiqnFj6qs,1745
21
21
  siat/cmat_commons.py,sha256=Nj9Kf0alywaztVoMVeVVL_EZk5jRERJy8R8kBw88_Tg,38116
22
- siat/common.py,sha256=XDt269wDd8L_sd4FWqFw2N5bPA6v051c2YnIxIJ_2V0,181169
22
+ siat/common.py,sha256=J0qSvKtPS1gAfb2_GJNKxFkWJJaNbkQzg4fzaBvKwjM,183440
23
23
  siat/compare_cross.py,sha256=3iP9TH2h3w27F2ARZc7FjKcErYCzWRc-TPiymOyoVtw,24171
24
24
  siat/compare_cross_test.py,sha256=xra5XYmQGEtfIZL2h-GssdH2hLdFIhG3eoCrkDrL3gY,3473
25
25
  siat/concepts_iwencai.py,sha256=m1YEDtECRT6FqtzlKm91pt2I9d3Z_XoP59BtWdRdu8I,3061
@@ -40,11 +40,11 @@ siat/fama_french.py,sha256=aUTC-67t_CEPbLk4u79woW_zfZ7OCP6Fo4z5EdWCSkQ,48051
40
40
  siat/fama_french_test.py,sha256=M4O23lBKsJxhWHRluwCb3l7HSEn3OFTjzGMpehcevRg,4678
41
41
  siat/fin_stmt2_yahoo.py,sha256=LGmspk0nKyz4X87MtcovZXUfMQkAvrWINuxR4HQ8PI8,41178
42
42
  siat/financial_base.py,sha256=A1rV7XQOVFpCXCV-T6Ge0QeF897hINiu0olN1XWeaFk,41287
43
- siat/financial_statements.py,sha256=xx0SMpFqAMKm6cj8uYeG2RpJE6G-RoJ3NWa33UyaVMk,25414
43
+ siat/financial_statements.py,sha256=7cv0z3djnfWsbnvW04ScrWSjCLEyUFrbGgQ6NtclyD0,25512
44
44
  siat/financial_statements_test.py,sha256=FLhx8JD-tVVWSBGux6AMz1jioXX4U4bp9DmgFHYXb_w,716
45
- siat/financials.py,sha256=hcXcwozYhfMtW6cTE2bDp5R80-IEKAyUHFO6mJ87GXQ,86267
45
+ siat/financials.py,sha256=jIkK8nhjQa5Z1SLeJ2rSQsSBswMgredvX2lZ6-1-Y7E,86267
46
46
  siat/financials2 - 副本.py,sha256=dKlNjIfKeoSy055fQ6E6TUj9HEoO5Ney9grD84J5kfk,14389
47
- siat/financials2.py,sha256=Yp2ffv3vc7zFwnJhYljWXbuyOANDpsW5btXjUdMkbB8,51177
47
+ siat/financials2.py,sha256=xCxqubwCNdfS7WyIb5IXTFonMZfw8FM9F8TCIkAruhk,58795
48
48
  siat/financials_china.py,sha256=iHF3lEESTK9DLWLBHFpyxn3S_dO2sNBE89xqaVYpNCw,192459
49
49
  siat/financials_china2.py,sha256=VvkzkjZeH84zwypR7ReldgJeZ7jnNw0qkzebvWMPm10,94956
50
50
  siat/financials_china2_test.py,sha256=Erz5k4LyOplBBvYls2MypuqHpVNJ3daiLdyeJezNPu0,2722
@@ -145,8 +145,8 @@ siat/valuation_china.py,sha256=eSKIDckyjG8QkENlW_OKkqbQHno8pzDcomBO9iGNJVM,83079
145
145
  siat/valuation_market_china_test.py,sha256=gbJ0ioauuo4koTPH6WKUkqcXiQPafnbhU5eKJ6lpdLA,1571
146
146
  siat/var_model_validation.py,sha256=R0caWnuZarrRg9939hxh3vJIIpIyPfvelYmzFNZtPbo,14910
147
147
  siat/yf_name.py,sha256=laNKMTZ9hdenGX3IZ7G0a2RLBKEWtUQJFY9CWuk_fp8,24058
148
- siat-3.9.22.dist-info/LICENSE,sha256=NTEMMROY9_4U1szoKC3N2BLHcDd_o5uTgqdVH8tbApw,1071
149
- siat-3.9.22.dist-info/METADATA,sha256=a-vcD3uMrLpIc3q4vg40-_IKlNjvgWgzJCTwzhfNO7Y,8396
150
- siat-3.9.22.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
151
- siat-3.9.22.dist-info/top_level.txt,sha256=r1cVyL7AIKqeAmEJjNR8FMT20OmEzufDstC2gv3NvEY,5
152
- siat-3.9.22.dist-info/RECORD,,
148
+ siat-3.9.32.dist-info/LICENSE,sha256=NTEMMROY9_4U1szoKC3N2BLHcDd_o5uTgqdVH8tbApw,1071
149
+ siat-3.9.32.dist-info/METADATA,sha256=nrawbbVkm08ig_snc7NU6XTo8pCuFWPU2FmgDCBhKxk,8396
150
+ siat-3.9.32.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
151
+ siat-3.9.32.dist-info/top_level.txt,sha256=r1cVyL7AIKqeAmEJjNR8FMT20OmEzufDstC2gv3NvEY,5
152
+ siat-3.9.32.dist-info/RECORD,,
File without changes
File without changes