siat 3.10.24__py3-none-any.whl → 3.10.75__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/bond.py CHANGED
@@ -201,12 +201,14 @@ if __name__=='__main__':
201
201
 
202
202
 
203
203
  #==============================================================================
204
- def interbank_bond_quote(num,option='1'):
204
+ def interbank_bond_quote(rank=10,option='1'):
205
205
  """
206
206
  功能:获得银行间债券市场现券报价
207
207
  输入:从头开始显示的个数num;选项option:默认1按照收益率从高到低排列,
208
208
  2按照发行时间从早到晚排列,3按照报价机构排列。其他选项按照默认排列。
209
209
  """
210
+ num=rank
211
+
210
212
  #抓取银行间市场债券报价
211
213
  import akshare as ak
212
214
  try:
@@ -230,8 +232,8 @@ def interbank_bond_quote(num,option='1'):
230
232
  df.sort_values(by=['报价机构'],ascending=[True],inplace=True)
231
233
  optiontxt=texttranslate("报价机构排序")
232
234
  #重新索引
233
- df.reset_index(drop=True)
234
-
235
+ df.reset_index(drop=True,inplace=True)
236
+ """
235
237
  print("\n"+texttranslate("中国银行间市场债券现券即时报价")+"("+optiontxt+texttranslate(",前")+str(num)+texttranslate("名)"))
236
238
  import pandas as pd
237
239
  pd.set_option('display.unicode.ambiguous_as_wide', True)
@@ -243,6 +245,14 @@ def interbank_bond_quote(num,option='1'):
243
245
  today = datetime.date.today().strftime("%Y-%m-%d")
244
246
  footnote="\n"+texttranslate("数据来源:中国银行间市场交易商协会(NAFMII),")+today
245
247
  print(footnote)
248
+ """
249
+ titletxt=texttranslate("中国银行间市场债券现券即时报价")+"("+optiontxt+texttranslate(",前")+str(num)+texttranslate("名)")
250
+ import datetime
251
+ todaydt = datetime.date.today().strftime("%Y-%m-%d")
252
+ footnote="\n"+texttranslate("数据来源:中国银行间市场交易商协会(NAFMII),")+str(todaydt)
253
+ df_display_CSS(df.head(num),titletxt=titletxt,footnote=footnote,facecolor='papayawhip',decimals=2, \
254
+ first_col_align='left',second_col_align='left', \
255
+ last_col_align='center',other_col_align='center')
246
256
 
247
257
  return df
248
258
 
@@ -383,7 +393,7 @@ if __name__=='__main__':
383
393
  num=10
384
394
  option='1'
385
395
 
386
- def interbank_bond_deal(num,option='1'):
396
+ def interbank_bond_deal(rank=10,option='1'):
387
397
  """
388
398
  功能:获得银行间债券市场现券成交行情
389
399
  输入:从头开始显示的个数num;选项option:默认1按照收益率从高到低排列,
@@ -391,6 +401,8 @@ def interbank_bond_deal(num,option='1'):
391
401
  5按照涨跌幅从低到高。
392
402
  其他选项按照默认排列。
393
403
  """
404
+ num=rank
405
+
394
406
  #抓取银行间市场债券报价,需要akshare-1.4.47版及以后
395
407
  import akshare as ak
396
408
  df=ak.bond_spot_deal()
@@ -492,17 +504,21 @@ def interbank_bond_deal(num,option='1'):
492
504
  else:
493
505
  df1=df[collist].tail(-num)
494
506
 
507
+ # 输出表格标题
495
508
  if lang == 'Chinese':
496
509
  if num > 0:
497
- print("\n=== 全国银行间债券市场现券成交状况当前快照("+optiontxt+",前"+str(num)+"名)\n")
510
+ #print("\n=== 全国银行间债券市场现券成交状况当前快照("+optiontxt+",前"+str(num)+"名)\n")
511
+ titletxt="全国银行间债券市场现券成交状况当前快照("+optiontxt+",前"+str(num)+"名)"
498
512
  else:
499
- print("\n=== 全国银行间债券市场现券成交状况当前快照("+optiontxt+",后"+str(-num)+"名)\n")
500
-
513
+ #print("\n=== 全国银行间债券市场现券成交状况当前快照("+optiontxt+",后"+str(-num)+"名)\n")
514
+ titletxt="全国银行间债券市场现券成交状况当前快照("+optiontxt+",后"+str(-num)+"名)"
501
515
  else:
502
516
  if num > 0:
503
- print("\n=== Interbank Bond Market: Deal Price ("+optiontxt+", Top "+str(num)+")\n")
517
+ #print("\n=== Interbank Bond Market: Deal Price ("+optiontxt+", Top "+str(num)+")\n")
518
+ titletxt="Interbank Bond Market: Deal Price ("+optiontxt+", Top "+str(num)+")"
504
519
  else:
505
- print("\n=== Interbank Bond Market: Deal Price ("+optiontxt+", Bottom "+str(-num)+")\n")
520
+ #print("\n=== Interbank Bond Market: Deal Price ("+optiontxt+", Bottom "+str(-num)+")\n")
521
+ titletxt="Interbank Bond Market: Deal Price ("+optiontxt+", Bottom "+str(-num)+")"
506
522
 
507
523
  """
508
524
  import pandas as pd
@@ -524,18 +540,24 @@ def interbank_bond_deal(num,option='1'):
524
540
  df1.reset_index(drop=True,inplace=True)
525
541
  df1.index=df1.index + 1
526
542
 
543
+ """
527
544
  numOfCol=len(list(df1))
528
545
  alignlist=['right','left']+['center']*(numOfCol - 1)
529
546
  print(df1.to_markdown(index=True,tablefmt='plain',colalign=alignlist))
530
-
547
+ """
531
548
  import datetime as dt
532
549
  nowstr0=str(dt.datetime.now())
533
550
  nowstr=nowstr0[:19]
534
551
 
535
552
  if lang == 'Chinese':
536
- print("\n*** 数据来源:全国银行间同业拆借中心,统计时间,",nowstr)
553
+ #print("\n*** 数据来源:全国银行间同业拆借中心,统计时间,",nowstr)
554
+ footnote="数据来源:全国银行间同业拆借中心,统计时间, "+str(nowstr)
537
555
  else:
538
- print("\n*** Data source:NAFMII. Delayed information,",nowstr)
556
+ #print("\n*** Data source:NAFMII. Delayed information,",nowstr)
557
+ footnote="Data source:NAFMII. Delayed information, "+str(nowstr)
558
+ df_display_CSS(df1,titletxt=titletxt,footnote=footnote,facecolor='papayawhip',decimals=2, \
559
+ first_col_align='left',second_col_align='center', \
560
+ last_col_align='center',other_col_align='center')
539
561
 
540
562
  return df
541
563
 
@@ -564,15 +586,18 @@ if __name__=='__main__':
564
586
  num=10
565
587
  option='1'
566
588
 
567
- def exchange_bond_deal(num,option='1'):
589
+ def exchange_bond_deal(rank=10,option='1'):
568
590
  """
569
591
  功能:获得沪深债券市场现券成交行情
570
- 输入:从头开始显示的个数num;选项option:默认1按照交易时间排列,
592
+ 输入:从头开始显示的个数num
593
+ 选项option:默认1按照交易时间排列,
571
594
  2按照发行时间从早到晚排列,3按照发行时间从晚到早排列,4按照涨跌幅从高到低,
572
595
  5按照涨跌幅从低到高,6按照成交量从高到低排列,7按照成交量从低到高排列。
573
596
  其他选项按照默认排列。
574
597
  """
575
- print(" Searching data, may take long time in low-speed network, please wait ...\n")
598
+ num=rank
599
+
600
+ print(" Searching data, may take long time ...")
576
601
  #定义标准输出关闭类,在Spyder中无效
577
602
  import os, sys
578
603
  class HiddenPrints:
@@ -671,22 +696,31 @@ def exchange_bond_deal(num,option='1'):
671
696
  '涨跌幅':'Change%','昨收':'Last Close','成交量':'Volume'})
672
697
 
673
698
  if lang=='Chinese':
674
- print("\n"+texttranslate("交易所市场债券成交价(")+optiontxt+texttranslate(",前")+str(num)+texttranslate("名)"))
699
+ #print("\n"+texttranslate("交易所市场债券成交价(")+optiontxt+texttranslate(",前")+str(num)+texttranslate("名)"))
700
+ titletxt=texttranslate("交易所市场债券成交价(")+optiontxt+texttranslate(",前")+str(num)+texttranslate("名)")
675
701
  else:
676
- print("\nExchange Bond Market: Deal Price ("+optiontxt+", Top"+str(num)+")\n")
677
-
702
+ #print("\nExchange Bond Market: Deal Price ("+optiontxt+", Top"+str(num)+")\n")
703
+ titletxt="Exchange Bond Market: Deal Price ("+optiontxt+", Top"+str(num)+")"
704
+
705
+ """
678
706
  pd.set_option('display.unicode.ambiguous_as_wide', True)
679
707
  pd.set_option('display.unicode.east_asian_width', True)
680
708
  pd.set_option('display.width', 200) # 设置打印宽度(**重要**)
681
709
  print(df2.head(num).to_string(index=False))
682
-
710
+ """
683
711
  import datetime
684
- today = datetime.date.today().strftime("%Y-%m-%d")
712
+ todaydt = datetime.date.today().strftime("%Y-%m-%d")
685
713
  if lang=='Chinese':
686
- footnote="\n"+texttranslate("数据来源:新浪财经,")+today
714
+ #footnote="\n"+texttranslate("数据来源:新浪财经,")+today
715
+ footnote=texttranslate("数据来源:新浪财经,")+str(todaydt)
687
716
  else:
688
- footnote="\n"+texttranslate("Source: Sina Finance, ")+today
689
- print(footnote)
717
+ #footnote="\n"+texttranslate("Source: Sina Finance, ")+today
718
+ footnote=texttranslate("Source: Sina Finance, ")+str(todaydt)
719
+ #print(footnote)
720
+
721
+ df_display_CSS(df2.head(num),titletxt=titletxt,footnote=footnote,facecolor='papayawhip',decimals=3, \
722
+ first_col_align='left',second_col_align='left', \
723
+ last_col_align='center',other_col_align='center')
690
724
 
691
725
  return df1
692
726
 
siat/capm_beta.py CHANGED
@@ -128,7 +128,7 @@ def prepare_capm_data(stkcd,mktidx,start,end):
128
128
  return R
129
129
 
130
130
  #==============================================================================
131
- def capm_beta(ticker,mktidx,start,end):
131
+ def capm_beta(ticker,mktidx,start,end='today'):
132
132
  """
133
133
  函数功能:计算一只股票的静态CAPM模型贝塔系数
134
134
  输入参数:
@@ -140,6 +140,7 @@ def capm_beta(ticker,mktidx,start,end):
140
140
  显示CAPM市场模型回归的alpha, beta, 以及显著性和拟合优度
141
141
  无返回数据
142
142
  """
143
+ start,end=start_end_preprocess(start,end)
143
144
 
144
145
  #读取股价并准备好收益率数据
145
146
  R=prepare_capm_data(ticker,mktidx,start,end)
siat/capm_beta2.py CHANGED
@@ -451,7 +451,7 @@ def compare_mticker_1beta(ticker,start,end, \
451
451
  annotate=annotate,annotate_value=annotate, \
452
452
  mark_top=mark_top,mark_bottom=mark_bottom, \
453
453
  mark_start=mark_start,mark_end=mark_end, \
454
- facecolor=facecolor,loc=loc)
454
+ facecolor=facecolor,loc=loc,precision=4)
455
455
 
456
456
  return df
457
457
 
@@ -590,7 +590,8 @@ def compare_1ticker_mRF(ticker,start,end, \
590
590
  annotate=annotate,annotate_value=annotate, \
591
591
  mark_top=mark_top,mark_bottom=mark_bottom, \
592
592
  mark_start=mark_start,mark_end=mark_end, \
593
- facecolor=facecolor,loc=loc)
593
+ facecolor=facecolor,loc=loc, \
594
+ precision=4)
594
595
 
595
596
  return df
596
597
 
@@ -723,7 +724,7 @@ def compare_1ticker_mregression_period(ticker,start,end, \
723
724
  annotate=annotate,annotate_value=annotate, \
724
725
  mark_top=mark_top,mark_bottom=mark_bottom, \
725
726
  mark_start=mark_start,mark_end=mark_end, \
726
- facecolor=facecolor,loc=loc)
727
+ facecolor=facecolor,loc=loc,precision=4)
727
728
 
728
729
  return df
729
730
 
@@ -749,6 +750,36 @@ if __name__=='__main__':
749
750
 
750
751
  betas=compare_beta_security(ticker,start,end,RF)
751
752
 
753
+ def compare_beta(ticker,start,end, \
754
+ adjust='qfq', \
755
+ RF=0,regression_period=365, \
756
+ attention_value='',attention_value_area='', \
757
+ attention_point='',attention_point_area='', \
758
+ band_area='', \
759
+ graph=True,facecolor='whitesmoke', \
760
+ annotate=False,annotate_value=False, \
761
+ mark_high=False,mark_low=False, \
762
+ mark_start=False,mark_end=False, \
763
+ mktidx='auto',source='auto', \
764
+ ticker_type='auto',loc="best"):
765
+ """
766
+ 功能:组合情况,可能多只股票、多个投资组合或投资组合与股票的混合,多个无风险收益率
767
+
768
+ """
769
+ df=compare_beta_security(ticker=ticker,start=start,end=end, \
770
+ adjust=adjust, \
771
+ RF=RF,regression_period=regression_period, \
772
+ attention_value=attention_value,attention_value_area=attention_value_area, \
773
+ attention_point=attention_point,attention_point_area=attention_point_area, \
774
+ band_area=band_area, \
775
+ graph=graph,facecolor=facecolor, \
776
+ annotate=annotate,annotate_value=annotate_value, \
777
+ mark_top=mark_high,mark_bottom=mark_low, \
778
+ mark_start=mark_start,mark_end=mark_end, \
779
+ mktidx=mktidx,source=source, \
780
+ ticker_type=ticker_type,loc=loc)
781
+
782
+
752
783
  def compare_beta_security(ticker,start,end, \
753
784
  adjust='qfq', \
754
785
  RF=0,regression_period=365, \
siat/common.py CHANGED
@@ -4918,7 +4918,13 @@ async def jupyter2pdf2(notebook_dir, notebook_file):
4918
4918
 
4919
4919
  import os
4920
4920
  from nbconvert import HTMLExporter
4921
- from playwright.async_api import async_playwright
4921
+
4922
+ try:
4923
+ from playwright.async_api import async_playwright
4924
+ except:
4925
+ print(" #Warning(jupyter2pdf2): playwright seems not fully installed yet")
4926
+ print(" [Solution] execute the command before re-run: playwright install")
4927
+ return
4922
4928
 
4923
4929
  html_file = ""
4924
4930
 
siat/economy.py CHANGED
@@ -1435,8 +1435,8 @@ def macro_trend(ticker,indicator,start='L10Y',end='today', \
1435
1435
  if 'YoY PPI' in indicator:
1436
1436
  attention_value=0
1437
1437
 
1438
- df=compare_economy(tickers=ticker,measures=indicator, \
1439
- fromdate=fromdate,todate=todate, \
1438
+ df=compare_economy(ticker=ticker,indicator=indicator, \
1439
+ start=fromdate,end=todate, \
1440
1440
  power=power,twinx=twinx, \
1441
1441
  yline=attention_value, \
1442
1442
  loc1=loc1,loc2=loc2,facecolor=facecolor)
@@ -1451,7 +1451,7 @@ def macro_trend(ticker,indicator,start='L10Y',end='today', \
1451
1451
  if 'YoY PPI' in indicator:
1452
1452
  attention_value=0
1453
1453
 
1454
- df=economy_trend(start=fromdate,end=todate,scope=ticker,factor=indicator, \
1454
+ df=economy_trend0(start=fromdate,end=todate,ticker=ticker,indicator=indicator, \
1455
1455
  datatag=datatag,power=power, \
1456
1456
  zeroline=zeroline,yline=attention_value,facecolor=facecolor)
1457
1457
  # 计算增长率
siat/fama_french.py CHANGED
@@ -32,14 +32,95 @@ if czxt in ['linux']: #website Jupyter
32
32
  # 解决保存图像时'-'显示为方块的问题
33
33
  plt.rcParams['axes.unicode_minus'] = False
34
34
  #==============================================================================
35
+ def convert2freq(df,new_freq='daily'):
36
+ """
37
+ 功能:将月度或年度频度的数据均匀化为日度数据
38
+ """
39
+ dfcols=list(df)
40
+
41
+ import pandas as pd
42
+ df['datetmp']=df.index
43
+ df['Date']=df['datetmp'].apply(lambda x: x.to_timestamp())
44
+ df.set_index('Date',inplace=True)
45
+ #df['Date']=df['date']
46
+ if not isinstance(df.index, pd.DatetimeIndex):
47
+ df.index = pd.to_datetime(df.index)
48
+
49
+ if new_freq == 'daily':
50
+ df = df.asfreq('D')
51
+ elif new_freq == 'monthly':
52
+ df = df.asfreq('M')
53
+ else:
54
+ df = df.asfreq('Y')
55
+
56
+ for c in dfcols:
57
+ df[c] = df[c].ffill()
58
+ df[c] = df[c].bfill()
59
+
60
+ df.drop(columns=['datetmp'], inplace=True)
61
+
62
+ #df=df[['Date']+dfcols]
63
+
64
+ return df
65
+ #==============================================================================
66
+
35
67
  if __name__=='__main__':
36
- start='2016-1-1'
37
- end='2020-12-31'
68
+ start='2025-1-1'
69
+ end='2025-6-13'
70
+
38
71
  scope='Europe'
39
72
  factor='Mom'
40
73
  freq='yearly'
74
+
75
+ scope='US'
76
+ factor='FF3'
77
+ freq='daily'
78
+
79
+ ff3d=get_ff_factors(start,end,scope,factor,freq='daily')
80
+ ff3mth=get_ff_factors(start,end,scope,factor,freq='monthly')
81
+ ff3y=get_ff_factors(start,end,scope,factor,freq='yearly')
41
82
 
42
- def get_ff_factors(start,end,scope='US',factor='FF3',freq='yearly'):
83
+ def get_ff_factors(start,end,scope='US',factor='FF3',freq='monthly'):
84
+ """
85
+ 功能:套壳函数get_ff_factors0,应对freq='daily'经常失败的变通方法
86
+ """
87
+ import pandas as pd
88
+ startpd=pd.to_datetime(start)
89
+ endpd=pd.to_datetime(end)
90
+
91
+ fff=get_ff_factors0(start=start,end=end,scope=scope,factor=factor,freq=freq)
92
+ if fff is None:
93
+ if freq == 'daily':
94
+ start1=date_adjust(start,adjust=-31)
95
+ end1=date_adjust(end,adjust=31)
96
+ fff=get_ff_factors0(start=start1,end=end1,scope=scope,factor=factor,freq='monthly')
97
+ if not (fff is None):
98
+ ff_factors0=convert2freq(fff,new_freq='daily')
99
+ ff_factors=ff_factors0[(ff_factors0.index >=startpd) & (ff_factors0.index <=endpd)]
100
+ else:
101
+ ff_factors=fff
102
+
103
+ elif freq == 'monthly':
104
+ start1=date_adjust(start,adjust=-365)
105
+ end1=date_adjust(end,adjust=365)
106
+ fff=get_ff_factors0(start=start1,end=end1,scope=scope,factor=factor,freq='yearly')
107
+ if not (fff is None):
108
+ ff_factors=convert2freq(fff,new_freq='monthly')
109
+ else:
110
+ ff_factors=fff
111
+
112
+ else:
113
+ start1=date_adjust(start,adjust=-365)
114
+ end1=date_adjust(end,adjust=365)
115
+ fff=get_ff_factors0(start=start1,end=end1,scope=scope,factor=factor,freq='yearly')
116
+ ff_factors=fff
117
+ else:
118
+ ff_factors=fff
119
+
120
+ return ff_factors
121
+
122
+
123
+ def get_ff_factors0(start,end,scope='US',factor='FF3',freq='yearly'):
43
124
  """
44
125
  【支持的因子种类(factor)】
45
126
  FF3: FF3各个因子
@@ -167,7 +248,7 @@ def get_ff_factors(start,end,scope='US',factor='FF3',freq='yearly'):
167
248
  try:
168
249
  ds = web.DataReader(symbol, source, start, end)
169
250
  except:
170
- print(" #Error(get_ff_factors): inaccessible to ff data source (time out)")
251
+ print(f" #Warning(get_ff_factors): time out to get {freq} data, working around ...")
171
252
  return None
172
253
 
173
254
  #提取希望的资产定价因子
@@ -887,7 +968,14 @@ if __name__=='__main__':
887
968
 
888
969
 
889
970
  #==============================================================================
890
-
971
+ if __name__=='__main__':
972
+ ticker='BIDU'
973
+ start='2025-1-1'
974
+ end='2025-5-30'
975
+ scope='US'
976
+ graph=True
977
+
978
+
891
979
  def reg_ff3_betas(ticker,start,end,scope='US',graph=True):
892
980
  """
893
981
  功能:测试一只股票对于FF3各个因子的系数大小、符号方向和显著性
@@ -1051,7 +1139,10 @@ def reg_ffc4_betas(ticker,start,end,scope='US',graph=True):
1051
1139
  #回归FF3模型
1052
1140
  import statsmodels.api as sm
1053
1141
  y=sample['dRet']
1054
- X=sample[['Mkt-RF','SMB','HML','MOM']]
1142
+ try:
1143
+ X=sample[['Mkt-RF','SMB','HML','MOM']]
1144
+ except:
1145
+ X=sample[['Mkt-RF','SMB','HML','Mom']]
1055
1146
  X1=sm.add_constant(X)
1056
1147
  results=sm.OLS(y,X1).fit()
1057
1148
 
@@ -1061,7 +1152,7 @@ def reg_ffc4_betas(ticker,start,end,scope='US',graph=True):
1061
1152
  #输出结果并绘制横向柱状图
1062
1153
  gparms=parms.iloc[[1,2,3,4]]
1063
1154
  if graph == True:
1064
- #print("\n",parms)
1155
+ print("\n",parms)
1065
1156
  title=ticker_name(ticker)+": FFC4模型的贝塔系数"
1066
1157
  plt.title(title,fontsize=12,fontweight='bold')
1067
1158
  plt.ylabel("贝塔系数",fontsize=12,fontweight='bold')
@@ -1178,7 +1269,7 @@ def reg_ff5_betas(ticker,start,end,scope='US',graph=True):
1178
1269
  #输出结果并绘制横向柱状图
1179
1270
  gparms=parms.iloc[[1,2,3,4,5]]
1180
1271
  if graph == True:
1181
- #print("\n",parms)
1272
+ print("\n",parms)
1182
1273
  title=ticker_name(ticker)+":FF5模型的贝塔系数"
1183
1274
  plt.title(title,fontsize=12,fontweight='bold')
1184
1275
  plt.ylabel("贝塔系数",fontsize=12,fontweight='bold')
siat/financials.py CHANGED
@@ -61,14 +61,19 @@ if czxt in ['linux']: #website Jupyter
61
61
  plt.rcParams['axes.unicode_minus'] = False
62
62
  #==============================================================================
63
63
  if __name__ == '__main__':
64
- tickers=['AAPL','MSFT']
65
- items=['Current Ratio','Quick Ratio']
64
+ ticker=['AAPL','MSFT']
65
+ indicator=['Current Ratio','Quick Ratio']
66
+
67
+ ticker=['BABA','JD']
68
+ indicator='Cashflow per Share'
69
+
66
70
  datatag=False
67
71
  power=0
68
72
  zeroline=False
69
73
  twinx=False
74
+ loc1=loc2='best'
70
75
 
71
- def compare_history(tickers,items, \
76
+ def compare_history(ticker,indicator, \
72
77
  datatag=False,power=0,zeroline=False,twinx=False, \
73
78
  loc1='best',loc2='best',graph=True):
74
79
  """
@@ -77,6 +82,9 @@ def compare_history(tickers,items, \
77
82
  zeroline=False:不绘制水平零线
78
83
  twinx=False:单纵轴
79
84
  """
85
+ tickers=ticker
86
+ items=indicator
87
+
80
88
  #检查power的范围是否合理
81
89
  if not (power in range(0,80)):
82
90
  print(" #Error(compare_history): invalid parameter, power =",power)
@@ -147,8 +155,12 @@ def compare_history(tickers,items, \
147
155
  #抓取数据
148
156
  info1=get_financial_rates(ticker1)
149
157
  if info1 is None:
150
- print(" #Error(compare_history): failed to retrieved info for",ticker1)
151
- return None,None
158
+ print(f" #Warning(compare_history): unable to get data for {ticker1}, retrying ...")
159
+ sleep_random(max_sleep=30)
160
+ info1=get_financial_rates(ticker1)
161
+ if info1 is None:
162
+ print(" #Error(compare_history): failed to retrieved financials for",ticker1)
163
+ return None,None
152
164
 
153
165
  cols1=['ticker','endDate','periodType',item1]
154
166
  df1=info1[cols1]
@@ -166,14 +178,18 @@ def compare_history(tickers,items, \
166
178
  item2=item1
167
179
  info2=get_financial_rates(ticker2)
168
180
  if info2 is None:
169
- print(" #Error(compare_history): failed to retrieved info for",ticker2)
170
- return None,None
181
+ print(f" #Warning(compare_history): unable to get data for {ticker2}, retrying ...")
182
+ sleep_random(max_sleep=30)
183
+ info2=get_financial_rates(ticker2)
184
+ if info2 is None:
185
+ print(" #Error(compare_history): failed to retrieved financials for",ticker2)
186
+ return None,None
171
187
 
172
188
  df2=info2[cols1]
173
189
  df2['date']=df2['endDate']
174
190
  df2.set_index('date',inplace=True)
175
191
 
176
- import datetime; today=datetime.date.today()
192
+ import datetime; todaydt=datetime.date.today()
177
193
  #绘图:T1I1,单折线
178
194
  if mode == 'T1I1'and graph:
179
195
  df=df1
@@ -183,7 +199,7 @@ def compare_history(tickers,items, \
183
199
  #titletxt=ticker_name(ticker1)+texttranslate(": 基于年(季)报的业绩历史")
184
200
  titletxt=ticker_name(ticker1)+": 财报业绩历史"
185
201
  #footnote=texttranslate("数据来源: 雅虎财经,")+' '+str(today)
186
- footnote="数据来源: 雅虎财经,"+' '+str(today)
202
+ footnote="数据来源: 雅虎财经,"+' '+str(todaydt)
187
203
 
188
204
  plot_line(df,colname,collabel,ylabeltxt,titletxt,footnote, \
189
205
  datatag=datatag,power=power,zeroline=zeroline,resample_freq='3M', \
@@ -245,10 +261,19 @@ def compare_history(tickers,items, \
245
261
  #titletxt=ticker_name(ticker1)+" vs "+ticker_name(ticker2)+texttranslate(": 基于年(季)报的业绩历史对比")
246
262
  titletxt=ticker_name(ticker1)+" vs "+ticker_name(ticker2)+": 财报业绩历史对比"
247
263
  #footnote=texttranslate("数据来源: 雅虎财经,")+' '+str(today)
248
- footnote="数据来源: 雅虎财经,"+' '+str(today)
264
+ footnote="数据来源: 雅虎财经,"+' '+str(todaydt)
249
265
 
250
- plot_line2(df1,ticker1,colname1,label1, \
251
- df2,ticker2,colname2,label2, \
266
+ #克服双线绘制时第2条线错乱问题:两个df日期强制取齐,能解决问题,但原因不明
267
+ tname1=ticker_name(ticker1)
268
+ df1.rename(columns={item1:tname1},inplace=True)
269
+ tname2=ticker_name(ticker2)
270
+ df2.rename(columns={item2:ticker_name(ticker2)},inplace=True)
271
+ df12=pd.merge(df1,df2,how='inner',left_index=True,right_index=True)
272
+ df1t=df12[[tname1]]
273
+ df2t=df12[[tname2]]
274
+
275
+ plot_line2(df1t,ticker1,tname1,label1, \
276
+ df2t,ticker2,tname2,label2, \
252
277
  ylabeltxt,titletxt,footnote, \
253
278
  power=power,zeroline=zeroline,twinx=twinx,resample_freq='3M', \
254
279
  loc1=loc1,loc2=loc2)
@@ -362,7 +387,7 @@ def compare_snapshot(ticker,indicator, \
362
387
 
363
388
  notfoundlist=[]
364
389
  total0=len(tickers)
365
- print(" Searching",itemk,"for specified stocks ...")
390
+ print(" Searching",itemk,"for designated companies ...")
366
391
  for t in tickers:
367
392
 
368
393
  current=tickers.index(t)
@@ -1970,7 +1995,7 @@ def compare_dupont(tickerlist,fsdate='latest', \
1970
1995
  """
1971
1996
  功能:获得tickerlist中每只股票的杜邦分析项目,绘制柱状叠加比较图
1972
1997
  tickerlist:股票代码列表,建议在10只以内
1973
- fsdate:财报日期,默认为最新一期季报/年报,也可规定具体日期,格式:YYYY-MM-DD
1998
+ fsdate:财报日期,默认为最新一期季报/年报,或具体日期,格式:YYYY-MM-DD
1974
1999
  scale1:用于放大销售净利率,避免与权益乘数数量级不一致导致绘图难看问题,可自行调整
1975
2000
  scale2:用于放大总资产周转率,避免与权益乘数数量级不一致导致绘图难看问题,可自行调整
1976
2001
  hatchlist:绘制柱状图的纹理,用于黑白打印时区分,可自定义,
@@ -2009,7 +2034,7 @@ def compare_dupont(tickerlist,fsdate='latest', \
2009
2034
  dpidflist,dpilist,fsdatelist,fstypelist=[],[],[],[]
2010
2035
  name1list,name2list,name3list,name4list,name5list,name6list=[],[],[],[],[],[]
2011
2036
  newtickerlist=[]
2012
- print("Working on DuPont factsheet for specified stocks ...")
2037
+ print(" Working on DuPont factsheet for specified stocks ...")
2013
2038
  for t in tickerlist:
2014
2039
  try:
2015
2040
  with HiddenPrints():
@@ -2017,12 +2042,23 @@ def compare_dupont(tickerlist,fsdate='latest', \
2017
2042
  except:
2018
2043
  print(" #Warning(compare_dupont): lack of some accounting items for",t)
2019
2044
  continue
2045
+
2046
+ #未出错,但未抓取到数据,再试
2047
+ if dpidf is None:
2048
+ print(f" #Warning(compare_dupont): failed to get data for {t}, retrying ...")
2049
+ sleep_random(max_sleep=30)
2050
+ with HiddenPrints():
2051
+ dpidf=calc_dupont(t)
2052
+
2053
+ if dpidf is None: continue
2054
+
2020
2055
  if fsdate == 'latest':
2021
2056
  try:
2022
2057
  dpi=dpidf.tail(1)
2023
2058
  except:
2024
- print(" #Warning(compare_dupont): problem in some accounting items for",t)
2059
+ print(" #Warning(compare_dupont): got empty data for",t)
2025
2060
  continue
2061
+
2026
2062
  else: dpi=dpidf[dpidf['endDate']==fsdate]
2027
2063
  if len(dpi) == 0:
2028
2064
  print(" #Warning(compare_dupont): lack of some accounting items for",t,'@',fsdate)