siat 3.10.75__py3-none-any.whl → 3.10.125__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.
@@ -4,7 +4,7 @@
4
4
  所属工具包:证券投资分析工具SIAT
5
5
  SIAT:Security Investment Analysis Tool
6
6
  创建日期:2018年10月16日
7
- 最新修订日期:2020817
7
+ 最新修订日期:2025620
8
8
  作者:王德宏 (WANG Dehong, Peter)
9
9
  作者单位:北京外国语大学国际商学院
10
10
  作者邮件:wdehong2000@163.com
@@ -65,8 +65,9 @@ def calc_treynor_ratio(regdf):
65
65
  #计算特雷诺指数
66
66
  tr=ret_rf_mean/beta
67
67
 
68
- ret_mean=regdf['Close'].mean()
69
- return tr,ret_mean
68
+ #ret_mean=regdf['Ret%'].mean()
69
+ rp_mean=ret_rf_mean
70
+ return tr,rp_mean,beta
70
71
 
71
72
  #==============================================================================
72
73
  def calc_alpha_ratio(regdf):
@@ -75,17 +76,15 @@ def calc_alpha_ratio(regdf):
75
76
  输入:数据框,至少含有Ret-Rf和Mkt-Rf两项
76
77
  输出:詹森阿尔法指数,Ret-Rf均值
77
78
  """
78
- """
79
79
  #计算风险溢价Ret-RF均值
80
80
  ret_rf_mean=regdf['Ret-RF'].mean()
81
- """
82
81
  #使用CAPM回归计算投资组合的贝塔系数,这里得到的alpha就是Jensen's alpha
83
82
  from scipy import stats
84
83
  output=stats.linregress(regdf['Mkt-RF'],regdf['Ret-RF'])
85
84
  (beta,alpha,r_value,p_value,std_err)=output
86
85
 
87
- ret_mean=regdf['Close'].mean()
88
- return alpha,ret_mean
86
+ rp_mean=ret_rf_mean
87
+ return alpha,rp_mean,beta
89
88
 
90
89
  #==============================================================================
91
90
  def calc_sharpe_ratio(regdf):
@@ -101,8 +100,9 @@ def calc_sharpe_ratio(regdf):
101
100
  #计算夏普指数
102
101
  sr=ret_rf_mean/ret_rf_std
103
102
 
104
- ret_mean=regdf['Close'].mean()
105
- return sr,ret_mean
103
+ rp_mean=ret_rf_mean
104
+ beta=False
105
+ return sr,rp_mean,beta
106
106
 
107
107
  if __name__=='__main__':
108
108
  rfd=rf_daily_china('2021-10-1','2021-11-28',rate_period='1Y',rate_type='shibor')
@@ -131,15 +131,18 @@ def calc_sortino_ratio(regdf):
131
131
  #计算索梯诺指数
132
132
  sr=ret_rf_mean/ret_rf_lpsd
133
133
 
134
- ret_mean=regdf['Close'].mean()
135
- return sr,ret_mean
134
+ rp_mean=ret_rf_mean
135
+ beta=False
136
+ return sr,rp_mean,beta
136
137
 
137
138
  #==============================================================================
138
- def print_rar_ratio(regdf,portfolio,ret_mean,ratio_name,ratio):
139
+ def print_rar_ratio(regdf,portfolio,rp_mean,beta,ratio_name,ratio):
139
140
  """
140
141
  功能:打印风险调整后的收益率
141
- 输入:数据框,投资组合构成,收益溢价均值,指数名称,指数
142
+ 输入:数据框,投资组合构成,收益溢价均值,贝塔系数,指数名称,指数
142
143
  输出:打印
144
+
145
+ 注意:若贝塔系数为False则不打印
143
146
  """
144
147
 
145
148
  #从字典中提取信息
@@ -151,31 +154,40 @@ def print_rar_ratio(regdf,portfolio,ret_mean,ratio_name,ratio):
151
154
  date_end=str(regdf.index[-1].year)+'-'+str(regdf.index[-1].month)+ \
152
155
  '-'+str(regdf.index[-1].day)
153
156
  print("\n======== 风险调整收益率 ========")
154
- print("市场指数:",ectranslate(scope),'\b,',ticker_name(mktidx))
157
+ print("证券资产:",portfolio_name(portfolio))
158
+ #print("市场指数:",ectranslate(scope),'\b,',ticker_name(mktidx))
159
+ print("市场指数:",ticker_name(mktidx))
155
160
  #print("成分股 :",ticker_name(stocklist))
156
161
  #print("持仓权重:",portionlist)
157
162
  print("样本期间:",date_start,"至",date_end)
158
163
  """
159
164
  print("日均收益率:",round(ret_mean,4),'\b%')
160
- """
161
165
  annual_ret=(1+ret_mean/100)**252-1
162
166
  print("年化收益率:",round(annual_ret,4))
163
- #print(ratio_name.capitalize(),"\b比率:",round(ratio,4),'\b%')
164
- print(ratio_name.capitalize(),"\b比率:",round(ratio,4))
167
+ """
168
+ if not isinstance(beta,bool):
169
+ print("贝塔系数:",round(beta,4))
170
+
171
+ print("风险溢价均值%:",round(rp_mean,4))
165
172
 
173
+ #print(ratio_name.capitalize(),"\b比率:",round(ratio,4),'\b%')
174
+ print(ratio_name.capitalize(),"\b比率%:",round(ratio,4))
175
+ """
166
176
  print("***投资组合构成:")
167
177
  print_tickerlist_sharelist(stocklist,portionlist,2)
168
-
178
+ """
169
179
 
170
- import datetime as dt; today=dt.date.today()
171
- print("数据来源:新浪/stooq/FRED, "+str(today))
180
+ import datetime as dt; todaydt=dt.date.today()
181
+ print("数据来源:新浪/stooq, "+str(todaydt))
172
182
 
173
183
  return
174
184
  #==============================================================================
175
185
  if __name__=='__main__':
176
- start='2021-1-1'
177
- end='2021-11-30'
178
- portfolio={'Market':('US','^GSPC'),'EDU':0.4,'TAL':0.3,'TEDU':0.2,'RYB':0.1}
186
+ portfolio={'Market':('US','^GSPC'),'AAPL':0.5,'MSFT':0.3,'IBM':0.2}
187
+ start='2024-6-1'
188
+ end='2025-5-30'
189
+ RF=0.04
190
+ printout=True
179
191
 
180
192
  rate_period='ON'
181
193
 
@@ -200,31 +212,43 @@ def treynor_ratio_portfolio(portfolio,start,end,RF=True,printout=True):
200
212
 
201
213
  #从字典中提取信息
202
214
  scope,mktidx,stocklist,portionlist,ticker_type=decompose_portfolio(portfolio)
215
+
216
+ #第2步:获得无风险收益率/市场收益率序列
217
+ #获得期间的日无风险收益率(抓取的RF为百分比)
218
+ if isinstance(RF,bool):
219
+ print(" Searching for risk-free interest rate ...")
220
+ if scope=='China':
221
+ rf_df=get_mkt_rf_daily_china(mktidx,start,end,rate_period='1Y',rate_type='shibor',RF=RF)
222
+ else:
223
+ rf_df=get_rf(start,end,scope=scope,freq='daily')
224
+ if rf_df is None:
225
+ message=" #Error("+func_name+"): "+"no data available for rf in"
226
+ print(message,scope,start,end)
227
+ return None,None
228
+ RF=rf_df['RF'].mean()
203
229
 
204
- #第2步:计算投资组合的日收益率序列
205
- #抓取日投资组合价格
206
- sp=get_portfolio_prices(portfolio,start,end)
230
+ #第3步:计算投资组合的日收益率序列
231
+ #抓取日投资组合价格:内含Mkt-RF和RF
232
+ sp=get_portfolio_prices(portfolio,start,end,RF=RF)
207
233
  #计算日收益率,表示为百分比
234
+ """
208
235
  import pandas as pd
209
236
  ret_pf=pd.DataFrame(sp['Close'].pct_change())*100.0
210
237
  ret_pf=ret_pf.dropna()
211
-
212
- #第3步:获得无风险收益率/市场收益率序列
213
- #获得期间的日无风险收益率(抓取的RF为百分比)
214
- print(" Searching for risk-free interest rate ...")
215
- if scope=='China':
216
- rf_df=get_mkt_rf_daily_china(mktidx,start,end,rate_period='1Y',rate_type='shibor',RF=RF)
217
- else:
218
- rf_df=get_rf(start,end,scope=scope,freq='daily')
219
- if rf_df is None:
220
- message=" #Error("+func_name+"): "+"no data available for rf in"
221
- print(message,scope,start,end)
222
- return None,None
238
+ """
239
+ ret_pf=sp
223
240
 
224
241
  #第4步:合并投资组合日收益率与无风险利率/市场收益率序列
225
- #合并rf_df与ret_pf
226
- reg=pd.merge(ret_pf,rf_df,how='inner',left_index=True,right_index=True)
242
+ """
243
+ if isinstance(RF,bool):
244
+ #合并rf_df与ret_pf
245
+ reg=pd.merge(ret_pf,rf_df,how='inner',left_index=True,right_index=True)
246
+ else:
247
+ reg=ret_pf
248
+ reg['RF']=RF/365 #日度无风险收益率%
227
249
  reg['Ret-RF']=reg['Close']-reg['RF']
250
+ """
251
+ reg=ret_pf
228
252
  reg=reg.dropna()
229
253
  if len(reg) == 0:
230
254
  message=" #Error("+func_name+"): "+"empty ret-rf data for regression"
@@ -233,14 +257,14 @@ def treynor_ratio_portfolio(portfolio,start,end,RF=True,printout=True):
233
257
 
234
258
  #第5步:计算风险调整后的收益率
235
259
  ##########风险调整后的收益率,计算开始##########
236
- tr,ret_mean=calc_treynor_ratio(reg)
260
+ tr,rp_mean,beta=calc_treynor_ratio(reg)
237
261
  ##########风险调整后的收益率,计算结束##########
238
262
 
239
263
  #第6步:打印结果
240
264
  if printout == True:
241
- print_rar_ratio(reg,portfolio,ret_mean,ratio_name,tr)
265
+ print_rar_ratio(reg,portfolio,rp_mean,beta,ratio_name,tr)
242
266
 
243
- return tr,ret_mean
267
+ return tr,rp_mean
244
268
 
245
269
 
246
270
  if __name__=='__main__':
@@ -258,11 +282,13 @@ if __name__=='__main__':
258
282
  indicator='alpha'
259
283
 
260
284
 
261
- def rar_ratio_portfolio(portfolio,start,end,indicator='sharpe',RF=0,printout=True):
285
+ def rar_ratio_portfolio(portfolio,start='MRY',end='today', \
286
+ indicator='sharpe', \
287
+ RF=0,printout=True):
262
288
  """
263
289
  功能:按天计算一个投资组合的风险调整后的收益率指数
264
290
  投资组合的结构:{'Market':('US','^GSPC'),'AAPL':0.5,'MSFT':0.3,'IBM':0.2}
265
- 输入:投资组合,开始日期,结束日期
291
+ 输入:投资组合,开始日期,结束日期,rar种类
266
292
  输出:风险调整后的收益率指数
267
293
  """
268
294
  ratio_name=indicator
@@ -276,13 +302,16 @@ def rar_ratio_portfolio(portfolio,start,end,indicator='sharpe',RF=0,printout=Tru
276
302
  if ratio_name not in ratio_list:
277
303
  message=" #Error("+func_name+"): "+"unsupported rar ratio type"
278
304
  print(message)
279
- return None,None
305
+ return None,None
306
+
307
+ start,end=start_end_preprocess(start,end)
280
308
  result,startdate,enddate=check_period(start,end)
281
309
  if not result:
282
310
  message=" #Error("+func_name+"): "+"invalid start or end date"
283
311
  print(message,start,end)
284
312
  return None,None
285
313
 
314
+ print(f" Calculating {ratio_name} ratio ...")
286
315
  #从字典中提取信息
287
316
  scope,mktidx,stocklist,portionlist,ticker_type=decompose_portfolio(portfolio)
288
317
 
@@ -307,8 +336,19 @@ def rar_ratio_portfolio(portfolio,start,end,indicator='sharpe',RF=0,printout=Tru
307
336
  rf_value_flag=True
308
337
 
309
338
  #第3步:计算投资组合的日收益率序列
339
+ import os,sys
340
+ class HiddenPrints:
341
+ def __enter__(self):
342
+ self._original_stdout = sys.stdout
343
+ sys.stdout = open(os.devnull, 'w')
344
+
345
+ def __exit__(self, exc_type, exc_val, exc_tb):
346
+ sys.stdout.close()
347
+ sys.stdout = self._original_stdout
348
+
310
349
  #抓取日投资组合价格
311
- sp=get_portfolio_prices(portfolio,startdate,enddate,RF=RF)
350
+ with HiddenPrints():
351
+ sp=get_portfolio_prices(portfolio,startdate,enddate,RF=RF)
312
352
  if sp is None:
313
353
  print(" #Error(rar_ratio_portfolio): failed to retrieve portfolio information")
314
354
  return None,None
@@ -339,17 +379,17 @@ def rar_ratio_portfolio(portfolio,start,end,indicator='sharpe',RF=0,printout=Tru
339
379
  print(message)
340
380
  return None,None
341
381
 
342
- #第5步:计算风险调整后的收益率
382
+ #第4步:计算风险调整后的收益率
343
383
  ##########风险调整后的收益率,计算开始##########
344
384
  calc_func='calc_'+ratio_name+'_ratio'
345
- rar,ret_mean=eval(calc_func)(reg)
385
+ rar,rp_mean,beta=eval(calc_func)(reg)
346
386
  ##########风险调整后的收益率,计算结束##########
347
387
 
348
- #第6步:打印结果
388
+ #第5步:打印结果
349
389
  if printout == True:
350
- print_rar_ratio(reg,portfolio,ret_mean,ratio_name,rar)
390
+ print_rar_ratio(reg,portfolio,rp_mean,beta,ratio_name,rar)
351
391
 
352
- return rar,ret_mean
392
+ return rar,rp_mean
353
393
 
354
394
 
355
395
  if __name__=='__main__':
@@ -366,7 +406,7 @@ if __name__=='__main__':
366
406
  window=30
367
407
  graph=True
368
408
 
369
- def rar_ratio_rolling(portfolio,start,end,indicator='sharpe',RF=0, \
409
+ def rar_ratio_rolling(portfolio,start='MRY',end='today',indicator='sharpe',RF=0, \
370
410
  window=21,graph=True,source='auto'):
371
411
  """
372
412
  功能:滚动计算一个投资组合的风险调整后的收益率指数
@@ -378,7 +418,9 @@ def rar_ratio_rolling(portfolio,start,end,indicator='sharpe',RF=0, \
378
418
 
379
419
  注意:当RF=False时有bug
380
420
  """
381
- ratio_name=indicator
421
+ start,end=start_end_preprocess(start,end)
422
+
423
+ ratio_name=indicator.lower()
382
424
 
383
425
  #第1步:各种准备和检查工作
384
426
  print(" Start to calculate rar ratios, please wait ...")
@@ -459,7 +501,7 @@ def rar_ratio_rolling(portfolio,start,end,indicator='sharpe',RF=0, \
459
501
  print(message)
460
502
  return None,None
461
503
 
462
- #第5步:滚动计算风险调整后的收益率
504
+ #第4步:滚动计算风险调整后的收益率
463
505
  ##########风险调整后的收益率,计算开始##########
464
506
  #用于保存rar和ret_rf_mean
465
507
  import pandas as pd
@@ -496,7 +538,7 @@ def rar_ratio_rolling(portfolio,start,end,indicator='sharpe',RF=0, \
496
538
  rars.set_index(['Date'],inplace=True)
497
539
  ##########风险调整后的收益率,计算结束##########
498
540
 
499
- #第6步:绘图
541
+ #第5步:绘图
500
542
  if graph == True:
501
543
  print(" Rendering graphics ...")
502
544
  draw_rar_ratio(rars,portfolio,ratio_name,pname)
@@ -605,35 +647,43 @@ def sharpe_ratio_portfolio(portfolio,start,end,RF=True,printout=True):
605
647
  return None,None
606
648
  """
607
649
 
608
- #抓取日投资组合价格
609
- sp=get_portfolio_prices(portfolio,start,end)
650
+ #获得期间的无风险收益率
651
+ if isinstance(RF,bool):
652
+ print(" Searching for risk-free interest rate ...")
653
+ if scope=='China':
654
+ rf_df=get_mkt_rf_daily_china(mktidx,start,end,rate_period='1Y',rate_type='shibor',RF=RF)
655
+ else:
656
+ rf_df=get_rf(start,end,scope=scope,freq='daily')
657
+ if rf_df is None:
658
+ message=" #Error("+func_name+"): "+"no data available for rf in"
659
+ print(message,scope,start,end)
660
+ return None,None
661
+ RF=rf_df['RF'].mean()
662
+
663
+ #抓取日投资组合价格:内含Mkt-RF和RF
664
+ sp=get_portfolio_prices(portfolio,start,end,RF=RF)
610
665
  #计算日收益率,表示为百分比
666
+ """
611
667
  import pandas as pd
612
668
  ret_pf=pd.DataFrame(sp['Close'].pct_change())*100.0
669
+ """
670
+ ret_pf=sp
613
671
  ret_pf=ret_pf.dropna()
614
-
615
- #获得期间的无风险收益率
616
- print(" Searching for risk-free interest rate ...")
617
- if scope=='China':
618
- rf_df=get_mkt_rf_daily_china(mktidx,start,end,rate_period='1Y',rate_type='shibor',RF=RF)
619
- else:
620
- rf_df=get_rf(start,end,scope=scope,freq='daily')
621
- if rf_df is None:
622
- message=" #Error("+func_name+"): "+"no data available for rf in"
623
- print(message,scope,start,end)
624
- return None,None
625
672
 
626
673
  #强制转换索引格式,彻底消除下面并表的潜在隐患
674
+ """
627
675
  rf_df['ffdate']=rf_df.index.astype('str')
628
676
  rf_df['ffdate']=pd.to_datetime(rf_df['ffdate'])
629
677
  rf_df.set_index(['ffdate'],inplace=True)
630
-
678
+ """
679
+ """
631
680
  #合并rf_df与ret_pf
632
681
  reg=pd.merge(ret_pf,rf_df,how='inner',left_index=True,right_index=True)
633
682
  reg['Ret-RF']=reg['Close']-reg['RF']
634
683
  reg=reg.dropna()
635
-
684
+ """
636
685
  #计算风险溢价Ret-RF均值和标准差
686
+ reg=ret_pf
637
687
  ret_rf_mean=reg['Ret-RF'].mean()
638
688
  ret_rf_std=reg['Ret-RF'].std()
639
689
 
@@ -647,20 +697,23 @@ def sharpe_ratio_portfolio(portfolio,start,end,RF=True,printout=True):
647
697
  date_end=str(reg.index[-1].year)+'-'+str(reg.index[-1].month)+ \
648
698
  '-'+str(reg.index[-1].day)
649
699
  print("\n===== 风险调整收益率 =====")
650
-
700
+ """
651
701
  _,_,tickerlist,sharelist,ticker_type=decompose_portfolio(portfolio)
652
702
  if len(tickerlist)==1:
653
703
  product=str(ticker_name(tickerlist,'bond'))
654
704
  else:
655
705
  product=str(ticker_name(tickerlist,'bond'))+' by '+str(sharelist)
656
- print("投资组合:",product)
657
- print("计算期间:",date_start,"至",date_end,"(可用日期)")
658
- print("风险溢价均值(%):",round(ret_rf_mean,4))
659
- print("夏普比率(%) :",round(sr,4))
706
+ """
707
+ print("证券资产:",portfolio_name(portfolio))
708
+ print("样本期间:",date_start,"至",date_end,"(可用日期)")
709
+ print("风险溢价均值%:",round(ret_rf_mean,4))
710
+ print("风险溢价标准差%:",round(ret_rf_std,4))
711
+ print("夏普比率%:",round(sr,4))
660
712
  import datetime as dt; today=dt.date.today()
661
713
  print("*数据来源:新浪/stooq/FRED,"+str(today))
662
714
 
663
- return sr,ret_rf_mean
715
+ beta=False
716
+ return sr,ret_rf_mean,beta
664
717
 
665
718
 
666
719
  if __name__=='__main__':
@@ -700,24 +753,28 @@ def sortino_ratio_portfolio(portfolio,start,end,RF=True,printout=True):
700
753
  return None,None
701
754
  """
702
755
 
756
+ #获得期间的无风险收益率
757
+ if isinstance(RF,bool):
758
+ print(" Searching for risk-free interest rate ...")
759
+ if scope=='China':
760
+ rf_df=get_mkt_rf_daily_china(mktidx,start,end,rate_period='1Y',rate_type='shibor',RF=RF)
761
+ else:
762
+ rf_df=get_rf(start,end,scope=scope,freq='daily')
763
+ if rf_df is None:
764
+ message=" #Error("+func_name+"): "+"no data available for rf in"
765
+ print(message,scope,start,end)
766
+ return None,None
767
+ RF=rf_df['RF'].mean()
768
+
703
769
  #抓取日投资组合价格
704
- sp=get_portfolio_prices(portfolio,start,end)
770
+ sp=get_portfolio_prices(portfolio,start,end,RF=RF)
771
+ ret_pf=sp
772
+ """
705
773
  #计算日收益率,表示为百分比
706
774
  import pandas as pd
707
775
  ret_pf=pd.DataFrame(sp['Close'].pct_change())*100.0
708
776
  ret_pf=ret_pf.dropna()
709
777
 
710
- #获得期间的无风险收益率
711
- print(" Searching for risk-free interest rate ...")
712
- if scope=='China':
713
- rf_df=get_mkt_rf_daily_china(mktidx,start,end,rate_period='1Y',rate_type='shibor',RF=RF)
714
- else:
715
- rf_df=get_rf(start,end,scope=scope,freq='daily')
716
- if rf_df is None:
717
- message=" #Error("+func_name+"): "+"no data available for rf in"
718
- print(message,scope,start,end)
719
- return None,None
720
-
721
778
  #强制转换索引格式,彻底消除下面并表的潜在隐患
722
779
  rf_df['ffdate']=rf_df.index.astype('str')
723
780
  rf_df['ffdate']=pd.to_datetime(rf_df['ffdate'])
@@ -726,6 +783,8 @@ def sortino_ratio_portfolio(portfolio,start,end,RF=True,printout=True):
726
783
  #合并rf_df与ret_pf
727
784
  reg=pd.merge(ret_pf,rf_df,how='inner',left_index=True,right_index=True)
728
785
  reg['Ret-RF']=reg['Close']-reg['RF']
786
+ """
787
+ reg=ret_pf
729
788
  reg=reg.dropna()
730
789
 
731
790
  #计算风险溢价Ret-RF均值和下偏标准差LPSD
@@ -743,17 +802,18 @@ def sortino_ratio_portfolio(portfolio,start,end,RF=True,printout=True):
743
802
  date_end=str(reg.index[-1].year)+'-'+str(reg.index[-1].month)+ \
744
803
  '-'+str(reg.index[-1].day)
745
804
  print("\n===== 风险调整收益率 =====")
746
-
805
+ """
747
806
  _,_,tickerlist,sharelist,ticker_type=decompose_portfolio(portfolio)
748
807
  if len(tickerlist)==1:
749
808
  product=str(ticker_name(tickerlist,'bond'))
750
809
  else:
751
810
  product=str(ticker_name(tickerlist,'bond'))+' by '+str(sharelist)
752
- print("投资组合:",product)
753
- print("计算期间:",date_start,"至",date_end, \
754
- "(可用日期)")
755
- print("风险溢价均值(%):",round(ret_rf_mean,4))
756
- print("索替诺比率(%) :",round(sr,4))
811
+ """
812
+ print("证券资产:",portfolio_name(portfolio))
813
+ print("样本期间:",date_start,"至",date_end,"(可用日期)")
814
+ print("风险溢价均值%:",round(ret_rf_mean,4))
815
+ print("下偏标准差%:",round(ret_rf_lpsd,4))
816
+ print("索替诺比率%:",round(sr,4))
757
817
 
758
818
  import datetime as dt; today=dt.date.today()
759
819
  print("*数据来源:新浪/stooq/FRED,"+str(today))
@@ -797,24 +857,28 @@ def jensen_alpha_portfolio(portfolio,start,end,RF=True,printout=True):
797
857
  return None,None
798
858
  """
799
859
 
800
- #抓取日投资组合价格
801
- sp=get_portfolio_prices(portfolio,start,end)
860
+ #获得期间的无风险收益率
861
+ if isinstance(RF,bool):
862
+ print(" Searching for risk-free interest rate ...")
863
+ if scope=='China':
864
+ rf_df=get_mkt_rf_daily_china(mktidx,start,end,rate_period='1Y',rate_type='shibor',RF=RF)
865
+ else:
866
+ rf_df=get_rf(start,end,scope=scope,freq='daily')
867
+ if rf_df is None:
868
+ message=" #Error("+func_name+"): "+"no data available for rf in"
869
+ print(message,scope,start,end)
870
+ return None,None
871
+ RF=rf_df['RF'].mean()
872
+
873
+ #抓取日投资组合价格:内含Mkt-RF和RF
874
+ sp=get_portfolio_prices(portfolio,start,end,RF=RF)
802
875
  #计算日收益率,表示为百分比
876
+ ret_pf=sp
877
+ """
803
878
  import pandas as pd
804
879
  ret_pf=pd.DataFrame(sp['Close'].pct_change())*100.0
805
880
  ret_pf=ret_pf.dropna()
806
881
 
807
- #获得期间的无风险收益率
808
- print(" Searching for risk-free interest rate ...")
809
- if scope=='China':
810
- rf_df=get_mkt_rf_daily_china(mktidx,start,end,rate_period='1Y',rate_type='shibor',RF=RF)
811
- else:
812
- rf_df=get_rf(start,end,scope=scope,freq='daily')
813
- if rf_df is None:
814
- message=" #Error("+func_name+"): "+"no data available for rf in"
815
- print(message,scope,start,end)
816
- return None,None
817
-
818
882
  #强制转换索引格式,彻底消除下面并表的潜在隐患
819
883
  rf_df['ffdate']=rf_df.index.astype('str')
820
884
  rf_df['ffdate']=pd.to_datetime(rf_df['ffdate'])
@@ -830,6 +894,8 @@ def jensen_alpha_portfolio(portfolio,start,end,RF=True,printout=True):
830
894
  #合并rf_df与ret_pf
831
895
  reg=pd.merge(ret_pf,rf_df,how='inner',left_index=True,right_index=True)
832
896
  reg['Ret-RF']=reg['Close']-reg['RF']
897
+ """
898
+ reg=ret_pf
833
899
  reg=reg.dropna()
834
900
  if len(reg) == 0:
835
901
  print(" #Error(jensen_alpha_portfolio): empty data for regression.")
@@ -848,21 +914,23 @@ def jensen_alpha_portfolio(portfolio,start,end,RF=True,printout=True):
848
914
  date_end=str(reg.index[-1].year)+'-'+str(reg.index[-1].month)+ \
849
915
  '-'+str(reg.index[-1].day)
850
916
  print("\n===== 风险调整收益率 =====")
851
-
917
+ """
852
918
  _,_,tickerlist,sharelist,ticker_type=decompose_portfolio(portfolio)
853
919
  if len(tickerlist)==1:
854
920
  product=str(ticker_name(tickerlist,'bond'))
855
921
  else:
856
922
  product=str(ticker_name(tickerlist,'bond'))+' by '+str(sharelist)
857
- print("投资组合:",product)
858
- print("计算期间:",date_start,"至",date_end,"(可用日期)")
859
- print("风险溢价均值(%):",round(ret_rf_mean,4))
860
- print("詹森阿尔法(%) :",round(alpha,4))
923
+ """
924
+ print("证券资产:",portfolio_name(portfolio))
925
+ print("样本期间:",date_start,"至",date_end,"(可用日期)")
926
+ print("贝塔系数:",round(beta,4))
927
+ print("风险溢价均值%:",round(ret_rf_mean,4))
928
+ print("詹森阿尔法%:",round(alpha,4))
861
929
 
862
930
  import datetime as dt; today=dt.date.today()
863
931
  print("*数据来源:新浪/stooq/FRED,"+str(today))
864
932
 
865
- return alpha,ret_rf_mean
933
+ return alpha,ret_rf_mean,beta
866
934
 
867
935
 
868
936
  if __name__=='__main__':