siat 3.1.6__py3-none-any.whl → 3.1.11__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/markowitz2.py CHANGED
@@ -152,8 +152,12 @@ def cumulative_returns_plot(retgroup,name_list="",titletxt="投资组合策略
152
152
 
153
153
  if xlabeltxt=="":
154
154
  #取出观察期
155
- hstart0=retgroup.index[0]; hstart=str(hstart0.date())
156
- hend0=retgroup.index[-1]; hend=str(hend0.date())
155
+ hstart0=retgroup.index[0]
156
+ #hstart=str(hstart0.date())
157
+ hstart=str(hstart0)
158
+ hend0=retgroup.index[-1]
159
+ #hend=str(hend0.date())
160
+ hend=str(hend0)
157
161
 
158
162
  lang = check_language()
159
163
  import datetime as dt; stoday=dt.date.today()
@@ -227,31 +231,41 @@ def portfolio_hpr(portfolio,thedate,pastyears=1, \
227
231
  if __name__=='__main__':
228
232
  Market={'Market':('US','^GSPC')}
229
233
  Market={'Market':('US','^GSPC','我的组合001')}
230
- Stocks1={'AAPL':.3,'MSFT':.15,'AMZN':.15,'FB':.01,'GOOG':.01}
234
+ Stocks1={'AAPL':.3,'MSFT':.15,'AMZN':.15,'GOOG':.01}
231
235
  Stocks2={'XOM':.02,'JNJ':.02,'JPM':.01,'TSLA':.3,'SBUX':.03}
232
236
  portfolio=dict(Market,**Stocks1,**Stocks2)
233
237
 
234
238
  ticker_name(portfolio)
235
239
 
236
- thedate='2023-2-17'
240
+ portfolio=dict(Market,**Stocks1)
241
+ thedate='2024-5-30'
237
242
  pastyears=1
238
- rate_period='1Y'
239
- rate_type='shibor'
240
- RF=0.01795
241
- printout=True
243
+ printout=True
244
+ graph=True
245
+
246
+ pf_info=portfolio_build(portfolio,'2024-5-30')
242
247
 
243
248
  """
244
249
  def portfolio_cumret(portfolio,thedate,pastyears=1, \
245
250
  RF=0, \
246
251
  printout=True,graph=True):
247
252
  """
248
- def portfolio_build(portfolio,thedate,pastyears=1, \
249
- RF=0, \
250
- printout=True,graph=True):
253
+ def portfolio_build(portfolio,thedate='default',pastyears=1, \
254
+ printout=True,graph=False):
251
255
  """
252
256
  功能:收集投资组合成份股数据,绘制收益率趋势图,并与等权和期间内交易额加权策略组合比较
253
- 注意:使用手动输入RF
257
+ 注意:此处无需RF,待到优化策略时再指定
258
+ printout=True控制获取股价时是否逐个显示
254
259
  """
260
+ import datetime
261
+ stoday = datetime.date.today()
262
+ if thedate=='default':
263
+ thedate=str(stoday)
264
+ else:
265
+ if not check_date(adate):
266
+ print(" #Warning(portfolio_build): invalid date",thedate)
267
+ return None
268
+
255
269
  print("\n Searching for portfolio info, which may take time ...")
256
270
  # 解构投资组合
257
271
  scope,_,tickerlist,sharelist0=decompose_portfolio(portfolio)
@@ -271,13 +285,13 @@ def portfolio_build(portfolio,thedate,pastyears=1, \
271
285
  # 计算历史数据的开始日期
272
286
  start=get_start_date(thedate,pastyears)
273
287
 
274
- #处理无风险利率,根据手动输入的RF构造rf_df以便后续改动量较小
288
+ #处理无风险利率,不再需要,但为兼容考虑仍保留,根据手动输入的RF构造rf_df以便后续改动量较小
275
289
  import pandas as pd
276
- date_series = pd.date_range(start=start, end=thedate, freq='D')
290
+ date_series = pd.date_range(start=start,end=thedate,freq='D')
277
291
  rf_df=pd.DataFrame(index=date_series)
278
292
  rf_df['date']=rf_df.index
279
293
  rf_df['date']=rf_df['date'].apply(lambda x: x.strftime('%Y-%m-%d'))
280
- rf_df['RF']=RF
294
+ rf_df['RF']=RF=0
281
295
  rf_df['rf_daily']=RF/365
282
296
  """
283
297
  #一次性获得无风险利率,传递给后续函数,避免后续每次获取,耗费时间
@@ -308,19 +322,32 @@ def portfolio_build(portfolio,thedate,pastyears=1, \
308
322
  #prices=get_prices(tickerlist,start,thedate)
309
323
 
310
324
  if printout:
311
- prices=get_prices_simple(tickerlist,start,thedate) #有待改造?
325
+ #prices=get_prices_simple(tickerlist,start,thedate) #有待改造?
326
+ #债券优先
327
+ prices,found=get_price_mticker(tickerlist,start,thedate, \
328
+ adjust='',source='auto',ticker_type='bond',fill=False)
312
329
  else:
313
330
  with HiddenPrints():
314
- prices=get_prices_simple(tickerlist,start,thedate) #有待改造?
315
- ntickers=len(list(prices['Close']))
316
- nrecords=len(prices)
331
+ #prices=get_prices_simple(tickerlist,start,thedate) #有待改造?
332
+ prices,found=get_price_mticker(tickerlist,start,thedate, \
333
+ adjust='',source='auto',ticker_type='bond',fill=False)
334
+
335
+ if found == 'Found':
336
+ ntickers=len(list(prices['Close']))
337
+ nrecords=len(prices)
317
338
  #print(" Successfully retrieved",ntickers,"stocks with",nrecords,"record(s) respectively")
318
- print(" Successfully retrieved prices of",ntickers,"stocks for",pname)
339
+ print(" Successfully retrieved prices of",ntickers,"securities for",pname)
340
+
341
+ if ntickers != len(tickerlist):
342
+ print(" However, failed to access some securities, unable to build portfolio",pname)
343
+ return None
319
344
 
320
- if prices is None:
345
+ #if prices is None:
346
+ if found == 'None':
321
347
  print(" #Error(portfolio_build): failed to get portfolio prices",pname)
322
348
  return None
323
- if len(prices) == 0:
349
+ #if len(prices) == 0:
350
+ if found == 'Empty':
324
351
  print(" #Error(portfolio_build): retrieved empty prices for",pname)
325
352
  return None
326
353
  #..........................................................................
@@ -367,9 +394,9 @@ def portfolio_build(portfolio,thedate,pastyears=1, \
367
394
  plt.gca().set_facecolor('whitesmoke')
368
395
 
369
396
  plt.legend(); plt.show(); plt.close()
370
- #..........................................................................
371
-
372
- # 计算原投资组合的持有收益率,并绘图
397
+ #..........................................................................
398
+
399
+ # 计算原投资组合的持有收益率,并绘图
373
400
  name_list=["Portfolio"]
374
401
  label_list=[pname]
375
402
 
@@ -475,8 +502,8 @@ def portfolio_correlate(pf_info):
475
502
  pname=portfolio_name(portfolio)
476
503
 
477
504
  #取出观察期
478
- hstart0=stock_return.index[0]; hstart=str(hstart0.date())
479
- hend0=stock_return.index[-1]; hend=str(hend0.date())
505
+ hstart0=stock_return.index[0]; hstart=str(hstart0)
506
+ hend0=stock_return.index[-1]; hend=str(hend0)
480
507
 
481
508
  sr=stock_return.copy()
482
509
  collist=list(sr)
@@ -523,8 +550,8 @@ def portfolio_covar(pf_info):
523
550
  pname=portfolio_name(portfolio)
524
551
 
525
552
  #取出观察期
526
- hstart0=stock_return.index[0]; hstart=str(hstart0.date())
527
- hend0=stock_return.index[-1]; hend=str(hend0.date())
553
+ hstart0=stock_return.index[0]; hstart=str(hstart0)
554
+ hend0=stock_return.index[-1]; hend=str(hend0)
528
555
 
529
556
  # 计算协方差矩阵
530
557
  cov_mat = stock_return.cov()
@@ -584,8 +611,12 @@ def portfolio_expectation_universal(pname,member_returns,portfolio_weights,membe
584
611
  """
585
612
 
586
613
  #观察期
587
- hstart0=member_returns.index[0]; hstart=str(hstart0.date())
588
- hend0=member_returns.index[-1]; hend=str(hend0.date())
614
+ hstart0=member_returns.index[0]
615
+ #hstart=str(hstart0.date())
616
+ hstart=str(hstart0)
617
+ hend0=member_returns.index[-1]
618
+ #hend=str(hend0.date())
619
+ hend=str(hend0)
589
620
  tickerlist=list(member_returns)
590
621
 
591
622
  #合成投资组合的历史收益率,按行横向加权求和
@@ -623,7 +654,7 @@ def portfolio_expectation_universal(pname,member_returns,portfolio_weights,membe
623
654
  print(" ***投资组合持仓策略***")
624
655
  print_tickerlist_sharelist(tickerlist,portfolio_weights,4)
625
656
 
626
- print(" *来源:Sina/EM/stooq,"+str(stoday))
657
+ print(" *来源:Sina/EM/stooq,"+str(stoday)+"统计")
627
658
  else:
628
659
  print("\n ======= Investment Portfolio: Return and Risk =======")
629
660
  print(" Investment portfolio:",pname)
@@ -703,7 +734,7 @@ def portfolio_ranks_cn(portfolio_returns,pname,facecolor='whitesmoke'):
703
734
  #以pname组合作为基准
704
735
  import numpy as np
705
736
  mean_return_pname=pr[pname].mean(axis=0)
706
- annual_return_pname=round(((1 + mean_return_pname)**252 - 1)*100,2)
737
+ annual_return_pname=round(((1 + mean_return_pname)**252 - 1)*100,4)
707
738
  """
708
739
  if annual_return_pname > 0:
709
740
  pct_style=True #百分比模式
@@ -713,22 +744,23 @@ def portfolio_ranks_cn(portfolio_returns,pname,facecolor='whitesmoke'):
713
744
  pct_style=False
714
745
 
715
746
  std_return_pname=pr[pname].std(axis=0)
716
- annual_std_pname= round((std_return_pname*np.sqrt(252))*100,2)
747
+ annual_std_pname= round((std_return_pname*np.sqrt(252))*100,4)
717
748
 
718
749
  import pandas as pd
719
750
  #prr=pd.DataFrame(columns=["名称","年化收益率","收益率变化","年化标准差","标准差变化","收益/风险"])
720
- prr=pd.DataFrame(columns=["名称","年化收益率%","收益率变化","年化标准差%","标准差变化","收益/风险"])
751
+ #prr=pd.DataFrame(columns=["名称","年化收益率%","收益率变化","年化标准差%","标准差变化","收益/风险"])
752
+ prr=pd.DataFrame(columns=["名称","年化收益率%","收益率变化","年化标准差%","标准差变化","收益率/标准差"])
721
753
  cols=list(pr)
722
754
  for c in cols:
723
755
 
724
756
  #年化收益率:按列求均值
725
757
  mean_return=pr[c].mean(axis=0)
726
- annual_return = round(((1 + mean_return)**252 - 1)*100,2)
758
+ annual_return = round(((1 + mean_return)**252 - 1)*100,4)
727
759
 
728
760
  if pct_style:
729
- return_chg=round((annual_return - annual_return_pname) / annual_return_pname * 100,2)
761
+ return_chg=round((annual_return - annual_return_pname) / annual_return_pname * 100,4)
730
762
  else:
731
- return_chg=round((annual_return - annual_return_pname),2)
763
+ return_chg=round((annual_return - annual_return_pname),4)
732
764
 
733
765
  #收益率变化
734
766
  if return_chg==0:
@@ -746,14 +778,15 @@ def portfolio_ranks_cn(portfolio_returns,pname,facecolor='whitesmoke'):
746
778
 
747
779
  #年化标准差
748
780
  std_return=pr[c].std(axis=0)
749
- annual_std = round((std_return*np.sqrt(252))*100,2)
781
+ annual_std = round((std_return*np.sqrt(252))*100,4)
750
782
 
751
- sharpe_ratio=round(annual_return / annual_std,2)
783
+ #sharpe_ratio=round(annual_return / annual_std,2)
784
+ sharpe_ratio=round((annual_return) / annual_std,4)
752
785
 
753
786
  if pct_style:
754
- std_chg=round((annual_std - annual_std_pname) / annual_std_pname * 100,1)
787
+ std_chg=round((annual_std - annual_std_pname) / annual_std_pname * 100,4)
755
788
  else:
756
- std_chg=round((annual_std - annual_std_pname),2)
789
+ std_chg=round((annual_std - annual_std_pname),4)
757
790
 
758
791
  #标准差变化
759
792
  if std_chg==0:
@@ -771,7 +804,7 @@ def portfolio_ranks_cn(portfolio_returns,pname,facecolor='whitesmoke'):
771
804
 
772
805
  row=pd.Series({"名称":c,"年化收益率%":annual_return, \
773
806
  "收益率变化":return_chg_str, \
774
- "年化标准差%":annual_std,"标准差变化":std_chg_str,"收益/风险":sharpe_ratio})
807
+ "年化标准差%":annual_std,"标准差变化":std_chg_str,"收益率/标准差":sharpe_ratio})
775
808
  try:
776
809
  prr=prr.append(row,ignore_index=True)
777
810
  except:
@@ -790,7 +823,7 @@ def portfolio_ranks_cn(portfolio_returns,pname,facecolor='whitesmoke'):
790
823
  #prr2=prr[["名称","收益排名","风险排名","年化收益率","年化标准差","收益率变化","标准差变化","收益/风险"]]
791
824
  prr2=prr[["名称","收益排名","年化收益率%","收益率变化", \
792
825
  "风险排名","年化标准差%","标准差变化", \
793
- "收益/风险"]]
826
+ "收益率/标准差"]]
794
827
  prr2.sort_values(by="年化收益率%",ascending=False,inplace=True)
795
828
  #prr2.reset_index(inplace=True)
796
829
 
@@ -816,7 +849,7 @@ def portfolio_ranks_cn(portfolio_returns,pname,facecolor='whitesmoke'):
816
849
  prr2.rename(columns={'名称':'投资组合名称/策略'},inplace=True)
817
850
  for c in list(prr2):
818
851
  try:
819
- prr2[c]=prr2[c].apply(lambda x: str(round(x,2)) if isinstance(x,float) else str(x))
852
+ prr2[c]=prr2[c].apply(lambda x: str(round(x,4)) if isinstance(x,float) else str(x))
820
853
  except: pass
821
854
 
822
855
  titletxt='投资组合策略排名:平衡收益与风险'
@@ -829,6 +862,14 @@ def portfolio_ranks_cn(portfolio_returns,pname,facecolor='whitesmoke'):
829
862
  from IPython.display import display
830
863
  display(dispf)
831
864
  """
865
+
866
+ df_display_CSS(prr2,titletxt=titletxt,footnote='',facecolor='papayawhip',decimals=4, \
867
+ first_col_align='left',second_col_align='center', \
868
+ last_col_align='right',other_col_align='right', \
869
+ titile_font_size='16px',heading_font_size='15px', \
870
+ data_font_size='15px')
871
+
872
+ """
832
873
  print(' ') #空一行
833
874
 
834
875
  disph=prr2.style.hide() #不显示索引列
@@ -853,7 +894,7 @@ def portfolio_ranks_cn(portfolio_returns,pname,facecolor='whitesmoke'):
853
894
  display(dispf2)
854
895
 
855
896
  print('') #空一行
856
-
897
+ """
857
898
  return prr2
858
899
 
859
900
  if __name__=='__main__':
@@ -910,12 +951,12 @@ def portfolio_ranks_en(portfolio_returns,pname):
910
951
  std_return=pr[c].std(axis=0)
911
952
  annual_std = std_return*np.sqrt(252)
912
953
 
913
- sharpe_ratio=round(annual_return / annual_std,2)
954
+ sharpe_ratio=round(annual_return / annual_std,4)
914
955
 
915
956
  if pct_style:
916
- std_chg=round((annual_std - annual_std_pname) / annual_std_pname *100,1)
957
+ std_chg=round((annual_std - annual_std_pname) / annual_std_pname *100,4)
917
958
  else:
918
- std_chg=round((annual_std - annual_std_pname),5)
959
+ std_chg=round((annual_std - annual_std_pname),4)
919
960
  if std_chg==0:
920
961
  std_chg_str="base"
921
962
  elif std_chg > 0:
@@ -982,8 +1023,8 @@ def portfolio_eset(pf_info,simulation=50000):
982
1023
  _,_,tickerlist,_=decompose_portfolio(portfolio)
983
1024
 
984
1025
  #取出观察期
985
- hstart0=stock_return.index[0]; hstart=str(hstart0.date())
986
- hend0=stock_return.index[-1]; hend=str(hend0.date())
1026
+ hstart0=stock_return.index[0]; hstart=str(hstart0)
1027
+ hend0=stock_return.index[-1]; hend=str(hend0)
987
1028
 
988
1029
  #获得成份股个数
989
1030
  numstocks=len(tickerlist)
@@ -1098,8 +1139,8 @@ def portfolio_es_sharpe(pf_info,simulation=1000,RF=0):
1098
1139
  scope,_,tickerlist,_=decompose_portfolio(portfolio)
1099
1140
 
1100
1141
  #取出观察期
1101
- hstart0=stock_return0.index[0]; hstart=str(hstart0.date())
1102
- hend0=stock_return0.index[-1]; hend=str(hend0.date())
1142
+ hstart0=stock_return0.index[0]; hstart=str(hstart0)
1143
+ hend0=stock_return0.index[-1]; hend=str(hend0)
1103
1144
 
1104
1145
  import pandas as pd
1105
1146
  #处理无风险利率
@@ -1192,8 +1233,8 @@ def portfolio_es_sortino(pf_info,simulation=1000,RF=0):
1192
1233
  scope,_,tickerlist,_=decompose_portfolio(portfolio)
1193
1234
 
1194
1235
  #取出观察期
1195
- hstart0=stock_return0.index[0]; hstart=str(hstart0.date())
1196
- hend0=stock_return0.index[-1]; hend=str(hend0.date())
1236
+ hstart0=stock_return0.index[0]; hstart=str(hstart0)
1237
+ hend0=stock_return0.index[-1]; hend=str(hend0)
1197
1238
 
1198
1239
  import pandas as pd
1199
1240
  #处理无风险利率
@@ -1292,8 +1333,8 @@ def portfolio_es_alpha(pf_info,simulation=1000,RF=0):
1292
1333
  scope,mktidx,tickerlist,_=decompose_portfolio(portfolio)
1293
1334
 
1294
1335
  #取出观察期
1295
- hstart0=stock_return0.index[0]; hstart=str(hstart0.date())
1296
- hend0=stock_return0.index[-1]; hend=str(hend0.date())
1336
+ hstart0=stock_return0.index[0]; hstart=str(hstart0)
1337
+ hend0=stock_return0.index[-1]; hend=str(hend0)
1297
1338
 
1298
1339
  #计算市场指数的收益率
1299
1340
  import pandas as pd
@@ -1408,8 +1449,8 @@ def portfolio_es_treynor(pf_info,simulation=1000,RF=0):
1408
1449
  scope,mktidx,tickerlist,_=decompose_portfolio(portfolio)
1409
1450
 
1410
1451
  #取出观察期
1411
- hstart0=stock_return0.index[0]; hstart=str(hstart0.date())
1412
- hend0=stock_return0.index[-1]; hend=str(hend0.date())
1452
+ hstart0=stock_return0.index[0]; hstart=str(hstart0)
1453
+ hend0=stock_return0.index[-1]; hend=str(hend0)
1413
1454
 
1414
1455
  #计算市场指数的收益率
1415
1456
  import pandas as pd
@@ -1588,6 +1629,31 @@ def RandomPortfolios_plot(RandomPortfolios,col_x,col_y,colorbartxt,title_ext, \
1588
1629
 
1589
1630
  return
1590
1631
  #==============================================================================
1632
+ #==============================================================================
1633
+ if __name__=='__main__':
1634
+ pname="MSR组合"
1635
+ modify_portfolio_name(pname)
1636
+
1637
+ def modify_portfolio_name(pname):
1638
+ """
1639
+ 功能:将原来的类似于MSR组合修改为更易懂的名称,仅供打印时使用
1640
+ """
1641
+ pclist=['等权重组合','交易额加权组合','MSR组合','GMVS组合','MSO组合','GML组合', \
1642
+ 'MAR组合','GMBA组合', 'MTR组合','GMBT组合']
1643
+
1644
+ pclist1=['等权重组合','交易额加权组合', \
1645
+ '最佳夏普比率组合(MSR)','夏普比率最小风险组合(GMVS)', \
1646
+ '最佳索替诺比率组合(MSO)','索替诺比率最小风险组合(GML)', \
1647
+ '最佳阿尔法指标组合(MAR)','阿尔法指标最小风险组合(GMBA)', \
1648
+ '最佳特雷诺比率组合(MTR)','特雷诺比率最小风险组合(GMBT)']
1649
+
1650
+ if pname not in pclist:
1651
+ return pname
1652
+
1653
+ pos=pclist.index(pname)
1654
+
1655
+ return pclist1[pos]
1656
+
1591
1657
  #==============================================================================
1592
1658
  def cvt_portfolio_name(pname,portfolio_returns):
1593
1659
  """
@@ -1601,8 +1667,16 @@ def cvt_portfolio_name(pname,portfolio_returns):
1601
1667
 
1602
1668
  lang=check_language()
1603
1669
  if lang == "Chinese":
1670
+ """
1604
1671
  pclist=[pname,'等权重组合','交易额加权组合','MSR组合','GMVS组合','MSO组合','GML组合', \
1605
1672
  'MAR组合','GMBA组合', 'MTR组合','GMBT组合']
1673
+ """
1674
+ pclist=[pname,'等权重组合','交易额加权组合', \
1675
+ '最佳夏普比率组合(MSR)','夏普比率最小风险组合(GMVS)', \
1676
+ '最佳索替诺比率组合(MSO)','索替诺比率最小风险组合(GML)', \
1677
+ '最佳阿尔法指标组合(MAR)','阿尔法指标最小风险组合(GMBA)', \
1678
+ '最佳特雷诺比率组合(MTR)','特雷诺比率最小风险组合(GMBT)']
1679
+
1606
1680
  else:
1607
1681
  pclist=[pname,'Equal-weight','Amount-weight','MSR','GMVS','MSO','GML', \
1608
1682
  'MAR','GMBA', 'MTR','GMBT']
@@ -1621,7 +1695,7 @@ def cvt_portfolio_name(pname,portfolio_returns):
1621
1695
 
1622
1696
  #==============================================================================
1623
1697
 
1624
- def portfolio_optimize_sharpe(es_info,RF=0,graph=True):
1698
+ def portfolio_optimize_sharpe(es_info,graph=True):
1625
1699
  """
1626
1700
  功能:计算投资组合的最高夏普比率组合,并绘图
1627
1701
  MSR: Maximium Sharpe Rate, 最高夏普指数方案
@@ -1697,7 +1771,7 @@ if __name__=='__main__':
1697
1771
 
1698
1772
  #==============================================================================
1699
1773
 
1700
- def portfolio_optimize_sortino(es_info,RF=0,graph=True):
1774
+ def portfolio_optimize_sortino(es_info,graph=True):
1701
1775
  """
1702
1776
  功能:计算投资组合的最高索替诺比率组合,并绘图
1703
1777
  MSO: Maximium Sortino ratio, 最高索替诺比率方案
@@ -1745,7 +1819,7 @@ if __name__=='__main__':
1745
1819
 
1746
1820
  #==============================================================================
1747
1821
 
1748
- def portfolio_optimize_alpha(es_info,RF=0,graph=True):
1822
+ def portfolio_optimize_alpha(es_info,graph=True):
1749
1823
  """
1750
1824
  功能:计算投资组合的最高詹森阿尔法组合,并绘图
1751
1825
  MAR: Maximium Alpha Ratio, 最高阿尔法指数方案
@@ -1791,7 +1865,7 @@ if __name__=='__main__':
1791
1865
 
1792
1866
  #==============================================================================
1793
1867
 
1794
- def portfolio_optimize_treynor(es_info,RF=0,graph=True):
1868
+ def portfolio_optimize_treynor(es_info,graph=True):
1795
1869
  """
1796
1870
  功能:计算投资组合的最高特雷诺比率组合,并绘图
1797
1871
  MTR: Maximium Treynor Ratio, 最高特雷诺指数方案
@@ -1851,8 +1925,8 @@ def portfolio_optimize_rar(es_info,col_ratio,col_y,col_x,name_hiret,name_lorisk,
1851
1925
  pname=portfolio_name(portfolio)
1852
1926
 
1853
1927
  #取出观察期
1854
- hstart0=StockReturns.index[0]; hstart=str(hstart0.date())
1855
- hend0=StockReturns.index[-1]; hend=str(hend0.date())
1928
+ hstart0=StockReturns.index[0]; hstart=str(hstart0)
1929
+ hend0=StockReturns.index[-1]; hend=str(hend0)
1856
1930
 
1857
1931
  #识别并计算指数..........................................................
1858
1932
  if col_ratio in ['Alpha']:
@@ -1932,12 +2006,16 @@ if __name__=='__main__':
1932
2006
  ratio='treynor'
1933
2007
  simulation=1000
1934
2008
  simulation=50000
2009
+
2010
+ RF=0
2011
+ graph=True;hirar_return=False;lorisk=True
1935
2012
 
1936
- def portfolio_optimize(pf_info,ratio='sharpe',simulation=50000,RF=0, \
1937
- graph=True,MSR_return=False,GMVS=True):
2013
+ def portfolio_optimize(pf_info,ratio='sharpe',simulation=10000,RF=0, \
2014
+ graph=True,hirar_return=False,lorisk=True):
1938
2015
  """
1939
2016
  功能:集成式投资组合优化策略
1940
- 注意:实验发现RF对于结果的影响极其微小难以观察,默认设为不使用无风险利率调整收益
2017
+ 注意:实验发现RF较小时对于结果的影响极其微小难以观察,默认设为不使用无风险利率调整收益
2018
+ 但RF较大时对于结果的影响明显变大,已经不能忽略!
1941
2019
  """
1942
2020
 
1943
2021
  ratio_list=['treynor','sharpe','sortino','alpha']
@@ -1956,11 +2034,16 @@ def portfolio_optimize(pf_info,ratio='sharpe',simulation=50000,RF=0, \
1956
2034
  es_info=eval(func_es)(pf_info=pf_info,simulation=simulation,RF=RF)
1957
2035
 
1958
2036
 
1959
- #寻找比率最优点:最大夏普比率策略MSR和最小风险策略GMV
2037
+ #寻找比率最优点:最大比率策略和最小风险策略
1960
2038
  func_optimize="portfolio_optimize_"+ratio
2039
+ """
1961
2040
  name_hiret,hiret_weights,name_lorisk,lorisk_weights,portfolio_returns= \
1962
2041
  eval(func_optimize)(es_info=es_info,RF=RF,graph=graph)
1963
-
2042
+ """
2043
+ name_hiret,hiret_weights,name_lorisk,lorisk_weights,portfolio_returns= \
2044
+ eval(func_optimize)(es_info=es_info,graph=graph)
2045
+
2046
+
1964
2047
  lang = check_language()
1965
2048
  if lang == 'Chinese':
1966
2049
  zhuhe_txt='组合'
@@ -1974,11 +2057,11 @@ def portfolio_optimize(pf_info,ratio='sharpe',simulation=50000,RF=0, \
1974
2057
  ylabeltxt="Holding Return"
1975
2058
 
1976
2059
  #打印投资组合构造和业绩表现
1977
- hi_name=name_hiret+zhuhe_txt
1978
- lo_name=name_lorisk+zhuhe_txt
2060
+ hi_name=modify_portfolio_name(name_hiret+zhuhe_txt)
2061
+ lo_name=modify_portfolio_name(name_lorisk+zhuhe_txt)
1979
2062
  portfolio_expectation(hi_name,pf_info,hiret_weights)
1980
2063
 
1981
- if MSR_return:
2064
+ if hirar_return:
1982
2065
  scope,mktidx,tickerlist,_=decompose_portfolio(portfolio)
1983
2066
  hwdf=pd.DataFrame(hiret_weights)
1984
2067
  hwdft=hwdf.T
@@ -1993,7 +2076,7 @@ def portfolio_optimize(pf_info,ratio='sharpe',simulation=50000,RF=0, \
1993
2076
  Market={'Market':(scope,mktidx,pname)}
1994
2077
  portfolio_new=dict(Market,**stocks_new)
1995
2078
 
1996
- if GMVS:
2079
+ if lorisk:
1997
2080
  portfolio_expectation(lo_name,pf_info,lorisk_weights)
1998
2081
 
1999
2082
  #现有投资组合的排名
@@ -2011,7 +2094,7 @@ def portfolio_optimize(pf_info,ratio='sharpe',simulation=50000,RF=0, \
2011
2094
  if graph:
2012
2095
  portfolio_expret_plot(portfolio_returns,name_list,titletxt=titletxt,ylabeltxt=ylabeltxt)
2013
2096
 
2014
- if MSR_return:
2097
+ if hirar_return:
2015
2098
  return portfolio_new
2016
2099
  else:
2017
2100
  return
siat/sector_china.py CHANGED
@@ -3065,6 +3065,53 @@ def find_industry_sw(ticker):
3065
3065
  break
3066
3066
 
3067
3067
  return
3068
+
3069
+ #==============================================================================
3070
+ if __name__=='__main__':
3071
+ ticker='600791.SS'
3072
+ find_industry_sw(ticker)
3073
+
3074
+ def find_industry_sw(ticker,level='2'):
3075
+ """
3076
+ 功能:寻找一只股票所属的申万行业
3077
+ """
3078
+ ticker6=ticker[:6]
3079
+
3080
+ import akshare as ak
3081
+ if level == '3':
3082
+ df = ak.sw_index_third_info()
3083
+ elif level == '2':
3084
+ df = ak.sw_index_second_info()
3085
+ else:
3086
+ df = ak.sw_index_first_info()
3087
+
3088
+ df['industry_code']=df['行业代码'].apply(lambda x: x[:6])
3089
+ industry_list=list(df['industry_code'])
3090
+
3091
+ for i in industry_list:
3092
+ print_progress_percent2(i,industry_list,steps=10,leading_blanks=0)
3093
+
3094
+ try:
3095
+ cdf = ak.index_component_sw(i)
3096
+ except:
3097
+ print(" #Warning(find_industry_sw): server banned this ip becos of too many requests")
3098
+ print(" Solution: change to another ip or another computer, or try a few hours later.")
3099
+ return
3100
+
3101
+ component_list=list(cdf['证券代码'])
3102
+
3103
+ if ticker6 in component_list:
3104
+ stock_name=cdf[cdf["证券代码"]==ticker6]['证券名称'].values[0]
3105
+ print("\n\n股票代码:"+ticker+","+stock_name)
3106
+
3107
+ isi=i+'.SI'
3108
+ industry_name=df[df['行业代码']==isi]['行业名称'].values[0]
3109
+ print("申万"+str(level)+"级行业代码:"+i+".SW,"+industry_name)
3110
+
3111
+ break
3112
+
3113
+ return
3114
+
3068
3115
  #==============================================================================
3069
3116
  #==============================================================================
3070
3117
  #==============================================================================
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: siat
3
- Version: 3.1.6
3
+ Version: 3.1.11
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
@@ -66,7 +66,7 @@ siat/holding_risk_test.py,sha256=FRlw_9wFG98BYcg_cSj95HX5WZ1TvkGaOUdXD7-V86s,474
66
66
  siat/local_debug_test.py,sha256=CDAOffW1Rvs-TcNN5giWVvHMlch1w4dp-w5SIV9jXL0,3936
67
67
  siat/market_china.py,sha256=nabx24qm7N51OafTrwUw542pNeFJ3JaQ1wqyv-nLN5I,37883
68
68
  siat/markowitz.py,sha256=c06gCRhMABnrb30F-npJsKVv8nFfEoNNR3bzrkMCyGg,97406
69
- siat/markowitz2.py,sha256=dBjxbb4K3jQkehzNLj8lQQXmkSAgE8Zs5_wDZLLvaEM,100759
69
+ siat/markowitz2.py,sha256=r8lqLhp0MrswkaPeLMEQvk4b5qC_Wc8U04PlJ45Y9o4,104269
70
70
  siat/markowitz_ccb_test.py,sha256=xBkkoaNHdq9KSUrNuHGgKTdNYUvgi84kNYcf719eoyE,1593
71
71
  siat/markowitz_ef_test.py,sha256=wjNlICkgRIqnonPeSIHo4Mu2GRtb9dr21wDt2kMNEcI,4032
72
72
  siat/markowitz_old.py,sha256=Lf7O_4QWT8RsdkHiUyc_7kKY3eZjKDtFR89Fz3pwYnY,33046
@@ -91,7 +91,7 @@ siat/risk_evaluation.py,sha256=I6B3gty-t--AkDCO0tKF-291YfpnF-IkXcFjqNKCt9I,76286
91
91
  siat/risk_evaluation_test.py,sha256=YEXM96gKzTfwN4U61AS4Rr1tV7KgUvn4rRC6f3iMw9s,3731
92
92
  siat/risk_free_rate.py,sha256=ZMr4cHikPvXvywr54gGqiI3Nvb69am6tq3zj2hwzANE,12384
93
93
  siat/risk_free_rate_test.py,sha256=CpmhUf8aEAEZeNu4gvWP2Mz2dLoIgBX5bI41vfUBEr8,4285
94
- siat/sector_china.py,sha256=zbN8MdQJi84femJFB9vxu1XgfPPCWGH7SPV44EjZCNI,113475
94
+ siat/sector_china.py,sha256=ijczadqHt4wEvNYjzDFllanxBLfXJy10v5th09KBEpI,115049
95
95
  siat/sector_china_test.py,sha256=1wq7ef8Bb_L8F0h0W6FvyBrIcBTEbrTV7hljtpj49U4,5843
96
96
  siat/security_price.py,sha256=2oHskgiw41KMGfqtnA0i2YjNNV6cYgtlUK0j3YeuXWs,29185
97
97
  siat/security_price2.py,sha256=kuYh0V5cqclkM6MjZUd-N361fv3oxGVVerYINuTzZrE,24622
@@ -132,7 +132,7 @@ siat/valuation.py,sha256=NKfeZMdDJOW42oLVHob6eSVBXUqlN1OCnnzwyGAst8c,48855
132
132
  siat/valuation_china.py,sha256=Tde2LzPDQy3Z7xOQQDw4ckQMPdROp_z0-GjFE6Z5_lI,67639
133
133
  siat/valuation_market_china_test.py,sha256=gbJ0ioauuo4koTPH6WKUkqcXiQPafnbhU5eKJ6lpdLA,1571
134
134
  siat/var_model_validation.py,sha256=f-oDewg7bPzyNanz_Y_jLH68NowAA3gXFehW_weKGG0,14898
135
- siat-3.1.6.dist-info/METADATA,sha256=7I1oTuPz1RUF3cmw1c0t_zAdexvckE9P8x9U5sCp16c,1447
136
- siat-3.1.6.dist-info/WHEEL,sha256=2wepM1nk4DS4eFpYrW1TTqPcoGNfHhhO_i5m4cOimbo,92
137
- siat-3.1.6.dist-info/top_level.txt,sha256=r1cVyL7AIKqeAmEJjNR8FMT20OmEzufDstC2gv3NvEY,5
138
- siat-3.1.6.dist-info/RECORD,,
135
+ siat-3.1.11.dist-info/METADATA,sha256=lFu29swamLdB_jdSJNZqMhgIwlHI80JQffc5qHAj7f4,1448
136
+ siat-3.1.11.dist-info/WHEEL,sha256=2wepM1nk4DS4eFpYrW1TTqPcoGNfHhhO_i5m4cOimbo,92
137
+ siat-3.1.11.dist-info/top_level.txt,sha256=r1cVyL7AIKqeAmEJjNR8FMT20OmEzufDstC2gv3NvEY,5
138
+ siat-3.1.11.dist-info/RECORD,,
File without changes