siat 3.3.11__py3-none-any.whl → 3.4.1__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/common.py CHANGED
@@ -1571,7 +1571,7 @@ def print_progress_percent(current,total,steps=5,leading_blanks=2):
1571
1571
 
1572
1572
  if pct=="100%":
1573
1573
  #print("100% completing")
1574
- print("100%, wrapping up ...")
1574
+ print("100%, completing ...")
1575
1575
  else:
1576
1576
  print(pct,end=' ')
1577
1577
 
@@ -1620,7 +1620,7 @@ def print_progress_percent2(current,total_list,steps=5,leading_blanks=4):
1620
1620
  pct=pct_list[pos]
1621
1621
 
1622
1622
  if pct=="100%":
1623
- print("100% wrapping up ...")
1623
+ print("100%, completing ...")
1624
1624
  else:
1625
1625
  print(pct,end=' ')
1626
1626
 
siat/markowitz2.py CHANGED
@@ -165,7 +165,7 @@ def cumulative_returns_plot(retgroup,name_list="",titletxt="投资组合策略
165
165
  footnote1="观察期间: "+hstart+'至'+hend
166
166
  footnote2="\n数据来源:Sina/EM/Stooq/Yahoo,"+str(stoday)
167
167
  else:
168
- footnote1="Period of observation: "+hstart+' to '+hend
168
+ footnote1="Period of sample: "+hstart+' to '+hend
169
169
  footnote2="\nData source: Sina/EM/Stooq/Yahoo, "+str(stoday)
170
170
 
171
171
  xlabeltxt=footnote1+footnote2
@@ -743,7 +743,7 @@ def portfolio_expectation_universal(pname,member_returns,portfolio_weights,membe
743
743
  print(" Investment portfolio:",pname)
744
744
  print(" Date of analysis:",str(hend))
745
745
  print(" Value of portfolio:","about "+str(round(portfolio_value_thedate/1000,2))+"K/portfolio unit")
746
- print(" Period of observation:",hstart+' to '+hend)
746
+ print(" Period of sample:",hstart+' to '+hend)
747
747
  print(" Annualized return:",round(annual_return,4))
748
748
  print(" Annualized std of return:",round(annual_std,4))
749
749
  print(" ***Portfolio Constructing Strategy***")
@@ -819,10 +819,13 @@ def portfolio_ranks_cn(portfolio_returns,pname,facecolor='papayawhip'):
819
819
  #临时保存,避免影响原值
820
820
  pr=portfolio_returns.copy()
821
821
 
822
+ #统一核定小数位数
823
+ ndecimals=2
824
+
822
825
  #以pname组合作为基准
823
826
  import numpy as np
824
827
  mean_return_pname=pr[pname].mean(axis=0)
825
- annual_return_pname=round(((1 + mean_return_pname)**252 - 1)*100,4)
828
+ annual_return_pname=round(((1 + mean_return_pname)**252 - 1)*100,ndecimals)
826
829
  """
827
830
  if annual_return_pname > 0:
828
831
  pct_style=True #百分比模式
@@ -832,7 +835,7 @@ def portfolio_ranks_cn(portfolio_returns,pname,facecolor='papayawhip'):
832
835
  pct_style=False
833
836
 
834
837
  std_return_pname=pr[pname].std(axis=0)
835
- annual_std_pname= round((std_return_pname*np.sqrt(252))*100,4)
838
+ annual_std_pname= round((std_return_pname*np.sqrt(252))*100,ndecimals)
836
839
 
837
840
  import pandas as pd
838
841
  #prr=pd.DataFrame(columns=["名称","年化收益率","收益率变化","年化标准差","标准差变化","收益/风险"])
@@ -843,12 +846,12 @@ def portfolio_ranks_cn(portfolio_returns,pname,facecolor='papayawhip'):
843
846
 
844
847
  #年化收益率:按列求均值
845
848
  mean_return=pr[c].mean(axis=0)
846
- annual_return = round(((1 + mean_return)**252 - 1)*100,4)
849
+ annual_return = round(((1 + mean_return)**252 - 1)*100,ndecimals)
847
850
 
848
851
  if pct_style:
849
- return_chg=round((annual_return - annual_return_pname) / annual_return_pname * 100,4)
852
+ return_chg=round((annual_return - annual_return_pname) / annual_return_pname * 100,ndecimals)
850
853
  else:
851
- return_chg=round((annual_return - annual_return_pname),4)
854
+ return_chg=round((annual_return - annual_return_pname),ndecimals)
852
855
 
853
856
  #收益率变化
854
857
  if return_chg==0:
@@ -866,15 +869,15 @@ def portfolio_ranks_cn(portfolio_returns,pname,facecolor='papayawhip'):
866
869
 
867
870
  #年化标准差
868
871
  std_return=pr[c].std(axis=0)
869
- annual_std = round((std_return*np.sqrt(252))*100,4)
872
+ annual_std = round((std_return*np.sqrt(252))*100,ndecimals)
870
873
 
871
874
  #sharpe_ratio=round(annual_return / annual_std,2)
872
- sharpe_ratio=round((annual_return) / annual_std,4)
875
+ sharpe_ratio=round((annual_return) / annual_std,ndecimals)
873
876
 
874
877
  if pct_style:
875
- std_chg=round((annual_std - annual_std_pname) / annual_std_pname * 100,4)
878
+ std_chg=round((annual_std - annual_std_pname) / annual_std_pname * 100,ndecimals)
876
879
  else:
877
- std_chg=round((annual_std - annual_std_pname),4)
880
+ std_chg=round((annual_std - annual_std_pname),ndecimals)
878
881
 
879
882
  #标准差变化
880
883
  if std_chg==0:
@@ -953,19 +956,32 @@ def portfolio_ranks_cn(portfolio_returns,pname,facecolor='papayawhip'):
953
956
 
954
957
  prr2.rename(columns={"投资组合名称/策略":text_lang("投资组合名称/策略","Strategy"), \
955
958
  "收益排名":text_lang("收益排名","Return#"), \
956
- "年化收益率%":text_lang("年化收益率%","Annualized Return%"), \
959
+ "年化收益率%":text_lang("年化收益率%","pa Return%"), \
957
960
  "收益率变化":text_lang("收益率变化","Return%+/-"), \
958
961
  "风险排名":text_lang("风险排名","Risk#"), \
959
- "年化标准差%":text_lang("年化标准差%","Annualized Std%"), \
962
+ "年化标准差%":text_lang("年化标准差%","pa Std%"), \
960
963
  "标准差变化":text_lang("标准差变化","Std%+/-"), \
961
964
  "收益率/标准差":text_lang("收益率/标准差","Return/Std")}, \
962
965
  inplace=True)
963
966
 
964
- df_display_CSS(prr2,titletxt=titletxt,footnote='',facecolor='papayawhip',decimals=4, \
967
+ #重新排名:相同的值赋予相同的序号
968
+ prr2["pa Return%"]=prr2["pa Return%"].apply(lambda x: round(float(x),ndecimals))
969
+ prr2["Return#"]=prr2["pa Return%"].rank(ascending=False,method='dense')
970
+ prr2["Return#"]=prr2["Return#"].apply(lambda x: int(x))
971
+
972
+ prr2["pa Std%"]=prr2["pa Std%"].apply(lambda x: round(float(x),ndecimals))
973
+ prr2["Risk#"]=prr2["pa Std%"].rank(ascending=False,method='dense')
974
+ prr2["Risk#"]=prr2["Risk#"].apply(lambda x: int(x))
975
+
976
+ prr2["Return/Std"]=prr2["Return/Std"].apply(lambda x: round(float(x),ndecimals))
977
+ prr2["Ret/Std#"]=prr2["Return/Std"].rank(ascending=False,method='dense')
978
+ prr2["Ret/Std#"]=prr2["Ret/Std#"].apply(lambda x: int(x))
979
+
980
+ df_display_CSS(prr2,titletxt=titletxt,footnote='',facecolor='papayawhip',decimals=ndecimals, \
965
981
  first_col_align='left',second_col_align='center', \
966
- last_col_align='right',other_col_align='right', \
967
- titile_font_size='16px',heading_font_size='15px', \
968
- data_font_size='15px')
982
+ last_col_align='center',other_col_align='center', \
983
+ titile_font_size='15px',heading_font_size='14px', \
984
+ data_font_size='14px')
969
985
 
970
986
  """
971
987
  print(' ') #空一行
@@ -1110,16 +1126,37 @@ def portfolio_ranks_en(portfolio_returns,pname):
1110
1126
 
1111
1127
  #==============================================================================
1112
1128
  if __name__=='__main__':
1113
- simulation=1000
1129
+ #Define market information and name of the portfolio: Banking #1
1130
+ Market={'Market':('China','000300.SS','Banking #1')}
1131
+ #First batch of component stocks
1132
+ Stocks1={'601939.SS':.3,#CCB Bank
1133
+ '600000.SS':.3, #SPDB Bank
1134
+ '600036.SS':.2, #CMB Bank
1135
+ '601166.SS':.2,#Industrial Bank
1136
+ }
1137
+ portfolio=dict(Market,**Stocks1)
1138
+
1139
+ pf_info=portfolio_build(portfolio,thedate='2024-7-17')
1140
+
1114
1141
  simulation=50000
1142
+ convex_hull=True; frontier="both"; facecolor='papayawhip'
1115
1143
 
1116
1144
  portfolio_eset(pf_info,simulation=50000)
1117
1145
 
1118
- def portfolio_eset(pf_info,simulation=1000,convex_hull=False,facecolor='papayawhip'):
1146
+ def portfolio_feset(pf_info,simulation=50000,convex_hull=True,frontier="both",facecolor='papayawhip'):
1147
+
1148
+ results=portfolio_eset(pf_info,simulation=simulation,convex_hull=convex_hull,frontier=frontier,facecolor=facecolor)
1149
+
1150
+ return results
1151
+
1152
+
1153
+ def portfolio_eset(pf_info,simulation=50000,convex_hull=False,frontier="both",facecolor='papayawhip'):
1119
1154
  """
1120
1155
  功能:基于随机数,生成大量可能的投资组合,计算各个投资组合的年均收益率和标准差,绘制投资组合的可行集
1121
1156
  默认绘制散点图凸包:convex_hull=True
1122
1157
  """
1158
+ DEBUG=True; MORE_DETAIL=False
1159
+
1123
1160
  [[portfolio,thedate,stock_return,_,_],_]=pf_info
1124
1161
  pname=portfolio_name(portfolio)
1125
1162
  _,_,tickerlist,_,ticker_type=decompose_portfolio(portfolio)
@@ -1138,7 +1175,7 @@ def portfolio_eset(pf_info,simulation=1000,convex_hull=False,facecolor='papayawh
1138
1175
  np.random.seed(RANDOM_SEED)
1139
1176
 
1140
1177
  # 循环模拟n次随机的投资组合
1141
- print(" Calculating portfolio efficient set, please wait ...")
1178
+ print(" Calculating portfolio feasible/efficient set, please wait ...")
1142
1179
  for i in range(simulation):
1143
1180
  # 生成numstocks个随机数,并归一化,得到一组随机的权重数据
1144
1181
  random9 = np.random.random(numstocks)
@@ -1169,7 +1206,6 @@ def portfolio_eset(pf_info,simulation=1000,convex_hull=False,facecolor='papayawh
1169
1206
  + ['Returns', 'Volatility']
1170
1207
 
1171
1208
  # 绘制散点图
1172
- print('')
1173
1209
  """
1174
1210
  RandomPortfolios.plot('Volatility','Returns',kind='scatter',color='y',edgecolors='k')
1175
1211
  """
@@ -1186,6 +1222,8 @@ def portfolio_eset(pf_info,simulation=1000,convex_hull=False,facecolor='papayawh
1186
1222
 
1187
1223
  #绘制散点图轮廓线凸包(convex hull)
1188
1224
  if convex_hull:
1225
+ print(" Calculating convex hull ...")
1226
+
1189
1227
  from scipy.spatial import ConvexHull
1190
1228
 
1191
1229
  #构造散点对的列表
@@ -1197,29 +1235,85 @@ def portfolio_eset(pf_info,simulation=1000,convex_hull=False,facecolor='papayawh
1197
1235
  y=pf_returns_list[pos]
1198
1236
  points=points+[[x,y]]
1199
1237
 
1238
+ #寻找最左侧的坐标:在x最小的同时,y要最大
1239
+ points_df = pd.DataFrame(points, columns=['x', 'y'])
1240
+ points_df.sort_values(by=['x','y'],ascending=[True,False],inplace=True)
1241
+ x1,y1=points_df.head(1).values[0]
1242
+ if DEBUG and MORE_DETAIL:
1243
+ print("\n*** Leftmost point (x1,y1):",x1,y1)
1244
+
1245
+ #寻找最高点的坐标:在y最大的同时,x要最小
1246
+ points_df.sort_values(by=['y','x'],ascending=[False,True],inplace=True)
1247
+ x2,y2=points_df.head(1).values[0]
1248
+ if DEBUG and MORE_DETAIL:
1249
+ print("*** Highest point (x2,y2):",x2,y2)
1250
+
1251
+ if DEBUG:
1252
+ plt.plot([x1,x2],[y1,y2],ls=':',lw=2,alpha=0.5)
1253
+
1254
+ #建立最左侧和最高点之间的拟合直线方程y=a+bx
1255
+ a=(x1*y2-x2*y1)/(x1-x2); b=(y1-y2)/(x1-x2)
1256
+ def y_bar(x_bar):
1257
+ return a+b*x_bar
1258
+
1200
1259
  # 计算散点集的外轮廓
1201
- hull = ConvexHull(points)
1260
+ hull = ConvexHull(points)
1261
+
1202
1262
  # 绘制外轮廓线
1263
+ firsttime_efficient=True; firsttime_inefficient=True
1203
1264
  for simplex in hull.simplices:
1265
+ #p1中是一条线段起点和终点的横坐标
1266
+ p1=[points[simplex[0]][0], points[simplex[1]][0]]
1267
+ px1=p1[0];px2=p1[1]
1268
+ #p2中是一条线段起点和终点的纵坐标
1269
+ p2=[points[simplex[0]][1], points[simplex[1]][1]]
1270
+ py1=p2[0]; py2=p2[1]
1271
+
1272
+ if DEBUG and MORE_DETAIL:
1273
+ print("\n*** Hull line start (px1,py1):",px1,py1)
1274
+ print("*** Hull line end (px2,py2):",px2,py2)
1275
+
1276
+ """
1204
1277
  plt.plot([points[simplex[0]][0], points[simplex[1]][0]],
1205
1278
  [points[simplex[0]][1], points[simplex[1]][1]], 'k-.')
1206
-
1207
- """
1208
- #滚动法寻找上边沿
1209
- points_sorted=points
1210
- points_sorted.sort(key=lambda x: x[0])
1211
- points_df=pd.DataFrame(points_sorted,columns=['x','y'])
1212
-
1213
- window=100
1214
- nwindow=int(len(points_df)/window)
1215
- upper_points=[]
1216
- for n in range(nwindow):
1217
- tmp_df=points_df[n*window:n*window+window]
1218
- max_y=max(tmp_df['y'])
1219
- max_x=tmp_df[tmp_df['y']==max_y]['x'].values[0]
1220
-
1221
- upper_points=upper_points+[[max_x,max_y]]
1222
- """
1279
+ """
1280
+
1281
+ #线段起点:px1,py1;线段终点:px2,py2
1282
+ if DEBUG and MORE_DETAIL:
1283
+ is_efficient=(py1>=y_bar(px1) or py1==y1) and (py2>=y_bar(px2) or py2==y2)
1284
+ print("\n*** is_efficient:",is_efficient)
1285
+ print("py1=",py1,"y_bar1",y_bar(px1),"y1=",y1,"py2=",py2,"ybar2=",y_bar(px2),"y2=",y2)
1286
+ if px1==x1 and py1==y1:
1287
+ print("====== This is the least risk point !")
1288
+ if px2==x2 and py2==y2:
1289
+ print("====== This is the highest return point !")
1290
+
1291
+ #坐标对[px1,py1]既可能作为开始点,也可能作为结束点,[px2,py2]同样
1292
+ if ((py1>=y_bar(px1) or py1==y1) and (py2>=y_bar(px2) or py2==y2)) or \
1293
+ ((py1>=y_bar(px2) or py1==y2) and (py2>=y_bar(px1) or py2==y1)):
1294
+
1295
+ #有效边界
1296
+ if frontier.lower() in ['both','efficient']:
1297
+ if firsttime_efficient:
1298
+ plt.plot(p1,p2, 'r--',label=text_lang("有效边界","Efficient Frontier"),lw=3,alpha=0.5)
1299
+ firsttime_efficient=False
1300
+ else:
1301
+ plt.plot(p1,p2, 'r--',lw=3,alpha=0.5)
1302
+ else:
1303
+ pass
1304
+ else:
1305
+ #其余边沿
1306
+ if frontier.lower() in ['both','inefficient']:
1307
+ if firsttime_inefficient:
1308
+ plt.plot(p1,p2, 'k-.',label=text_lang("无效边界","Inefficient Frontier"),alpha=0.5)
1309
+ firsttime_inefficient=False
1310
+ else:
1311
+ plt.plot(p1,p2, 'k-.',alpha=0.5)
1312
+ else:
1313
+ pass
1314
+ else:
1315
+ print('')
1316
+
1223
1317
 
1224
1318
  import datetime as dt; stoday=dt.date.today()
1225
1319
  lang = check_language()
@@ -1243,12 +1337,13 @@ def portfolio_eset(pf_info,simulation=1000,convex_hull=False,facecolor='papayawh
1243
1337
 
1244
1338
  footnote1="Annualized Std -->\n\n"
1245
1339
  footnote2="Based on given securities, constructed "+str(simulation)+" portfolios\n"
1246
- footnote3="Period of observation: "+hstart+" to "+hend
1340
+ footnote3="Period of sample: "+hstart+" to "+hend
1247
1341
  footnote4="\nData source: Sina/EM/Stooq/Yahoo, "+str(stoday)
1248
1342
 
1249
1343
  plt.xlabel(footnote1+footnote2+footnote3+footnote4,fontsize=xlabel_txt_size)
1250
1344
 
1251
1345
  plt.gca().set_facecolor(facecolor)
1346
+ plt.legend(loc='best')
1252
1347
  plt.show()
1253
1348
 
1254
1349
  return [pf_info,RandomPortfolios]
@@ -1268,7 +1363,7 @@ if __name__=='__main__':
1268
1363
  rate_period='1Y'
1269
1364
  rate_type='treasury'
1270
1365
 
1271
- def portfolio_es_sharpe(pf_info,simulation=1000,RF=0):
1366
+ def portfolio_es_sharpe(pf_info,simulation=50000,RF=0):
1272
1367
  """
1273
1368
  功能:基于随机数,生成大量可能的投资组合,计算各个投资组合的年均风险溢价及其标准差,绘制投资组合的可行集
1274
1369
  """
@@ -1362,7 +1457,7 @@ if __name__=='__main__':
1362
1457
  rate_period='1Y'
1363
1458
  rate_type='treasury'
1364
1459
 
1365
- def portfolio_es_sortino(pf_info,simulation=1000,RF=0):
1460
+ def portfolio_es_sortino(pf_info,simulation=50000,RF=0):
1366
1461
  """
1367
1462
  功能:基于随机数,生成大量可能的投资组合,计算各个投资组合的年均风险溢价及其下偏标准差,绘制投资组合的可行集
1368
1463
  """
@@ -1462,7 +1557,7 @@ if __name__=='__main__':
1462
1557
  rate_period='1Y'
1463
1558
  rate_type='treasury'
1464
1559
 
1465
- def portfolio_es_alpha(pf_info,simulation=1000,RF=0):
1560
+ def portfolio_es_alpha(pf_info,simulation=50000,RF=0):
1466
1561
  """
1467
1562
  功能:基于随机数,生成大量可能的投资组合,计算各个投资组合的年化标准差和阿尔法指数,绘制投资组合的可行集
1468
1563
  """
@@ -1580,7 +1675,7 @@ if __name__=='__main__':
1580
1675
  rate_period='1Y'
1581
1676
  rate_type='treasury'
1582
1677
 
1583
- def portfolio_es_treynor(pf_info,simulation=1000,RF=0):
1678
+ def portfolio_es_treynor(pf_info,simulation=50000,RF=0):
1584
1679
  """
1585
1680
  功能:基于随机数,生成大量可能的投资组合,计算各个投资组合的风险溢价和贝塔系数,绘制投资组合的可行集
1586
1681
  """
@@ -1691,7 +1786,7 @@ if __name__=='__main__':
1691
1786
  #==============================================================================
1692
1787
  def RandomPortfolios_plot(RandomPortfolios,col_x,col_y,colorbartxt,title_ext, \
1693
1788
  ylabeltxt,x_axis_name,pname,simulation,hstart,hend, \
1694
- hiret_point,lorisk_point,convex_hull=True, \
1789
+ hiret_point,lorisk_point,convex_hull=True,frontier='efficient', \
1695
1790
  facecolor="papayawhip"):
1696
1791
  """
1697
1792
  功能:将生成的马科维茨可行集RandomPortfolios绘制成彩色散点图
@@ -1719,7 +1814,8 @@ def RandomPortfolios_plot(RandomPortfolios,col_x,col_y,colorbartxt,title_ext, \
1719
1814
  plt.xlabel(footnote1+footnote2+footnote3+footnote4)
1720
1815
  plt.show()
1721
1816
  """
1722
- print('')
1817
+ DEBUG=False
1818
+
1723
1819
  #RandomPortfolios.plot(col_x,col_y,kind='scatter',color='y',edgecolors='k')
1724
1820
 
1725
1821
  pf_ratio = np.array(RandomPortfolios[col_y] / RandomPortfolios[col_x])
@@ -1732,6 +1828,7 @@ def RandomPortfolios_plot(RandomPortfolios,col_x,col_y,colorbartxt,title_ext, \
1732
1828
 
1733
1829
  #绘制散点图轮廓线凸包(convex hull)
1734
1830
  if convex_hull:
1831
+ print(" Calculating convex hull ...")
1735
1832
  from scipy.spatial import ConvexHull
1736
1833
 
1737
1834
  #构造散点对的列表
@@ -1743,13 +1840,65 @@ def RandomPortfolios_plot(RandomPortfolios,col_x,col_y,colorbartxt,title_ext, \
1743
1840
  y=pf_returns_list[pos]
1744
1841
  points=points+[[x,y]]
1745
1842
 
1843
+ #寻找最左侧的坐标:在x最小的同时,y要最大
1844
+ points_df = pd.DataFrame(points, columns=['x', 'y'])
1845
+ points_df.sort_values(by=['x','y'],ascending=[True,False],inplace=True)
1846
+ x1,y1=points_df.head(1).values[0]
1847
+
1848
+ #寻找最高点的坐标:在y最大的同时,x要最小
1849
+ points_df.sort_values(by=['y','x'],ascending=[False,True],inplace=True)
1850
+ x2,y2=points_df.head(1).values[0]
1851
+
1852
+ if DEBUG:
1853
+ plt.plot([x1,x2],[y1,y2],ls=':',lw=2,alpha=0.5)
1854
+
1855
+ #建立最左侧和最高点之间的拟合直线方程y=a+bx
1856
+ a=(x1*y2-x2*y1)/(x1-x2); b=(y1-y2)/(x1-x2)
1857
+ def y_bar(x_bar):
1858
+ return a+b*x_bar
1859
+
1746
1860
  # 计算散点集的外轮廓
1747
- hull = ConvexHull(points)
1861
+ hull = ConvexHull(points)
1862
+
1748
1863
  # 绘制外轮廓线
1864
+ firsttime_efficient=True; firsttime_inefficient=True
1749
1865
  for simplex in hull.simplices:
1866
+ #p1中是一条线段起点和终点的横坐标
1867
+ p1=[points[simplex[0]][0], points[simplex[1]][0]]
1868
+ px1=p1[0];px2=p1[1]
1869
+ #p2中是一条线段起点和终点的纵坐标
1870
+ p2=[points[simplex[0]][1], points[simplex[1]][1]]
1871
+ py1=p2[0]; py2=p2[1]
1872
+
1873
+ """
1750
1874
  plt.plot([points[simplex[0]][0], points[simplex[1]][0]],
1751
- [points[simplex[0]][1], points[simplex[1]][1]], 'k-')
1752
-
1875
+ [points[simplex[0]][1], points[simplex[1]][1]], 'k-.')
1876
+ """
1877
+ #线段起点:px1,py1;线段终点:px2,py2。但也可能互换起点和终点
1878
+ if ((py1>=y_bar(px1) or py1==y1) and (py2>=y_bar(px2) or py2==y2)) or \
1879
+ ((py1>=y_bar(px2) or py1==y2) and (py2>=y_bar(px1) or py2==y1)) :
1880
+ #有效边界
1881
+ if frontier.lower() in ['both','efficient']:
1882
+ if firsttime_efficient:
1883
+ plt.plot(p1,p2, 'r--',label=text_lang("有效边界","Efficient Frontier"),lw=3,alpha=0.5)
1884
+ firsttime_efficient=False
1885
+ else:
1886
+ plt.plot(p1,p2, 'r--',lw=3,alpha=0.5)
1887
+ else:
1888
+ pass
1889
+ else:
1890
+ #其余边沿
1891
+ if frontier.lower() in ['both','inefficient']:
1892
+ if firsttime_inefficient:
1893
+ plt.plot(p1,p2, 'k-.',label=text_lang("无效边界","Inefficient Frontier"),alpha=0.5)
1894
+ firsttime_inefficient=False
1895
+ else:
1896
+ plt.plot(p1,p2, 'k-.',alpha=0.5)
1897
+ else:
1898
+ pass
1899
+ else:
1900
+ #无convex hull
1901
+ print('')
1753
1902
 
1754
1903
  lang = check_language()
1755
1904
  if lang == 'Chinese':
@@ -1772,7 +1921,7 @@ def RandomPortfolios_plot(RandomPortfolios,col_x,col_y,colorbartxt,title_ext, \
1772
1921
  import datetime as dt; stoday=dt.date.today()
1773
1922
  footnote1=x_axis_name+" -->\n\n"
1774
1923
  footnote2="Based on given securities, constructed "+str(simulation)+" portfolios"
1775
- footnote3="\nPeriod of observation: "+hstart+" to "+hend
1924
+ footnote3="\nPeriod of sample: "+hstart+" to "+hend
1776
1925
  footnote4="\nData source: Sina/EM/Stooq/Yahoo, "+str(stoday)
1777
1926
 
1778
1927
  plt.xlabel(footnote1+footnote2+footnote3+footnote4,fontsize=xlabel_txt_size)
@@ -1780,11 +1929,11 @@ def RandomPortfolios_plot(RandomPortfolios,col_x,col_y,colorbartxt,title_ext, \
1780
1929
  #解析最大比率点和最低风险点信息,并绘点
1781
1930
  [hiret_x,hiret_y,name_hiret]=hiret_point
1782
1931
  #plt.scatter(hiret_x, hiret_y, color='red',marker='*',s=150,label=name_hiret)
1783
- plt.scatter(hiret_x, hiret_y, color='blue',marker='*',s=200,label=name_hiret)
1932
+ plt.scatter(hiret_x, hiret_y, color='red',marker='*',s=300,label=name_hiret,alpha=0.5)
1784
1933
 
1785
1934
  [lorisk_x,lorisk_y,name_lorisk]=lorisk_point
1786
1935
  #plt.scatter(lorisk_x, lorisk_y, color='m',marker='8',s=100,label=name_lorisk)
1787
- plt.scatter(lorisk_x, lorisk_y, color='red',marker='8',s=150,label=name_lorisk)
1936
+ plt.scatter(lorisk_x, lorisk_y, color='blue',marker='8',s=150,label=name_lorisk,alpha=0.5)
1788
1937
 
1789
1938
  plt.legend(loc='best')
1790
1939
 
@@ -1866,7 +2015,7 @@ def cvt_portfolio_name(pname,portfolio_returns):
1866
2015
 
1867
2016
  #==============================================================================
1868
2017
 
1869
- def portfolio_optimize_sharpe(es_info,graph=True,convex_hull=False,facecolor='papayawhip'):
2018
+ def portfolio_optimize_sharpe(es_info,graph=True,convex_hull=False,frontier='efficient',facecolor='papayawhip'):
1870
2019
  """
1871
2020
  功能:计算投资组合的最高夏普比率组合,并绘图
1872
2021
  MSR: Maximium Sharpe Rate, 最高夏普指数方案
@@ -1920,7 +2069,7 @@ def portfolio_optimize_sharpe(es_info,graph=True,convex_hull=False,facecolor='pa
1920
2069
  hiret_weights,lorisk_weights,portfolio_returns = \
1921
2070
  portfolio_optimize_rar(es_info,col_ratio,col_y,col_x,name_hiret,name_lorisk, \
1922
2071
  colorbartxt,title_ext,ylabeltxt,x_axis_name,graph=graph, \
1923
- convex_hull=convex_hull,facecolor=facecolor)
2072
+ convex_hull=convex_hull,frontier=frontier,facecolor=facecolor)
1924
2073
 
1925
2074
  print(text_lang("【注释】","[Notes]"))
1926
2075
  print("★MSR :Maximized Sharpe Ratio"+text_lang(",最大夏普比率点",''))
@@ -1943,7 +2092,7 @@ if __name__=='__main__':
1943
2092
 
1944
2093
  #==============================================================================
1945
2094
 
1946
- def portfolio_optimize_sortino(es_info,graph=True,convex_hull=False,facecolor="papayawhip"):
2095
+ def portfolio_optimize_sortino(es_info,graph=True,convex_hull=False,frontier='efficient',facecolor="papayawhip"):
1947
2096
  """
1948
2097
  功能:计算投资组合的最高索替诺比率组合,并绘图
1949
2098
  MSO: Maximium Sortino ratio, 最高索替诺比率方案
@@ -1961,7 +2110,7 @@ def portfolio_optimize_sortino(es_info,graph=True,convex_hull=False,facecolor="p
1961
2110
  title_ext=text_lang("索替诺比率","Sortino Ratio") #用于标题区别
1962
2111
  colorbartxt=text_lang("索替诺比率","Sortino Ratio") #用于彩色棒标签
1963
2112
  ylabeltxt=text_lang("年化风险溢价","Annualized Risk Premium") #用于纵轴名称
1964
- x_axis_name=text_lang("年化风险溢价之下偏标准差","Annualized Std of Risk Premium") #用于横轴名称
2113
+ x_axis_name=text_lang("年化风险溢价之下偏标准差","Annualized Risk Premium LPSD") #用于横轴名称
1965
2114
 
1966
2115
  #定制部分结束...............................................................
1967
2116
 
@@ -1969,7 +2118,7 @@ def portfolio_optimize_sortino(es_info,graph=True,convex_hull=False,facecolor="p
1969
2118
  hiret_weights,lorisk_weights,portfolio_returns = \
1970
2119
  portfolio_optimize_rar(es_info,col_ratio,col_y,col_x,name_hiret,name_lorisk, \
1971
2120
  colorbartxt,title_ext,ylabeltxt,x_axis_name,graph=graph, \
1972
- convex_hull=convex_hull,facecolor=facecolor)
2121
+ convex_hull=convex_hull,frontier=frontier,facecolor=facecolor)
1973
2122
 
1974
2123
  print(text_lang("【注释】","[Notes]"))
1975
2124
  print("★MSO:Maximum SOrtino ratio"+text_lang(",最大索替诺比率点",''))
@@ -1994,7 +2143,7 @@ if __name__=='__main__':
1994
2143
  if __name__=='__main__':
1995
2144
  graph=True; convex_hull=False
1996
2145
 
1997
- def portfolio_optimize_alpha(es_info,graph=True,convex_hull=False,facecolor='papayawhip'):
2146
+ def portfolio_optimize_alpha(es_info,graph=True,convex_hull=False,frontier='efficient',facecolor='papayawhip'):
1998
2147
  """
1999
2148
  功能:计算投资组合的最高詹森阿尔法组合,并绘图
2000
2149
  MAR: Maximium Alpha Ratio, 最高阿尔法指数方案
@@ -2019,7 +2168,7 @@ def portfolio_optimize_alpha(es_info,graph=True,convex_hull=False,facecolor='pap
2019
2168
  hiret_weights,lorisk_weights,portfolio_returns = \
2020
2169
  portfolio_optimize_rar(es_info,col_ratio,col_y,col_x,name_hiret,name_lorisk, \
2021
2170
  colorbartxt,title_ext,ylabeltxt,x_axis_name,graph=graph, \
2022
- convex_hull=convex_hull,facecolor=facecolor)
2171
+ convex_hull=convex_hull,frontier=frontier,facecolor=facecolor)
2023
2172
 
2024
2173
  print(text_lang("【注释】","[Notes]"))
2025
2174
  print("★MAR :Maximum Alpha Ratio"+text_lang(",最大阿尔法点",''))
@@ -2041,7 +2190,7 @@ if __name__=='__main__':
2041
2190
 
2042
2191
  #==============================================================================
2043
2192
 
2044
- def portfolio_optimize_treynor(es_info,graph=True,convex_hull=False,facecolor='papayawhip'):
2193
+ def portfolio_optimize_treynor(es_info,graph=True,convex_hull=False,frontier='efficient',facecolor='papayawhip'):
2045
2194
  """
2046
2195
  功能:计算投资组合的最高特雷诺比率组合,并绘图
2047
2196
  MTR: Maximium Treynor Ratio, 最高特雷诺指数方案
@@ -2066,7 +2215,7 @@ def portfolio_optimize_treynor(es_info,graph=True,convex_hull=False,facecolor='p
2066
2215
  hiret_weights,lorisk_weights,portfolio_returns = \
2067
2216
  portfolio_optimize_rar(es_info,col_ratio,col_y,col_x,name_hiret,name_lorisk, \
2068
2217
  colorbartxt,title_ext,ylabeltxt,x_axis_name,graph=graph, \
2069
- convex_hull=convex_hull,facecolor=facecolor)
2218
+ convex_hull=convex_hull,frontier=frontier,facecolor=facecolor)
2070
2219
 
2071
2220
  print(text_lang("【注释】","[Notes]"))
2072
2221
  print("★MTR :Maximum Treynor Ratio"+text_lang(",最大特雷诺比率点",''))
@@ -2081,7 +2230,7 @@ if __name__=='__main__':
2081
2230
 
2082
2231
  def portfolio_optimize_rar(es_info,col_ratio,col_y,col_x,name_hiret,name_lorisk, \
2083
2232
  colorbartxt,title_ext,ylabeltxt,x_axis_name,graph=True, \
2084
- convex_hull=False,facecolor='papayawhip'):
2233
+ convex_hull=False,frontier='efficient',facecolor='papayawhip'):
2085
2234
  """
2086
2235
  功能:提供rar比率优化的共同处理部分
2087
2236
  基于RandomPortfolios中的随机投资组合,计算相应的指数,寻找最大指数点和风险最小点,并绘图标注两个点
@@ -2156,7 +2305,8 @@ def portfolio_optimize_rar(es_info,col_ratio,col_y,col_x,name_hiret,name_lorisk,
2156
2305
  if graph:
2157
2306
  RandomPortfolios_plot(RandomPortfolios,col_x,col_y,colorbartxt,title_ext, \
2158
2307
  ylabeltxt,x_axis_name,pname,simulation,hstart,hend, \
2159
- hiret_point,lorisk_point,convex_hull=convex_hull,facecolor=facecolor)
2308
+ hiret_point,lorisk_point,convex_hull=convex_hull, \
2309
+ frontier=frontier,facecolor=facecolor)
2160
2310
 
2161
2311
  #返回数据,供进一步分析
2162
2312
  portfolio_returns=StockReturns.copy()
@@ -2191,9 +2341,9 @@ if __name__=='__main__':
2191
2341
  graph=True;hirar_return=False;lorisk=True
2192
2342
  convex_hull=False
2193
2343
 
2194
- def portfolio_optimize(pf_info,ratio='sharpe',simulation=10000,RF=0, \
2344
+ def portfolio_optimize(pf_info,ratio='sharpe',simulation=50000,RF=0, \
2195
2345
  graph=True,hirar_return=False,lorisk=True, \
2196
- convex_hull=False,facecolor='papayawhip'):
2346
+ convex_hull=True,frontier='efficient',facecolor='papayawhip'):
2197
2347
  """
2198
2348
  功能:集成式投资组合优化策略
2199
2349
  注意:实验发现RF较小时对于结果的影响极其微小难以观察,默认设为不使用无风险利率调整收益
@@ -2224,7 +2374,8 @@ def portfolio_optimize(pf_info,ratio='sharpe',simulation=10000,RF=0, \
2224
2374
  eval(func_optimize)(es_info=es_info,RF=RF,graph=graph)
2225
2375
  """
2226
2376
  name_hiret,hiret_weights,name_lorisk,lorisk_weights,portfolio_returns= \
2227
- eval(func_optimize)(es_info=es_info,graph=graph,convex_hull=convex_hull,facecolor=facecolor)
2377
+ eval(func_optimize)(es_info=es_info,graph=graph,convex_hull=convex_hull, \
2378
+ frontier=frontier,facecolor=facecolor)
2228
2379
 
2229
2380
 
2230
2381
  lang = check_language()
@@ -2232,12 +2383,12 @@ def portfolio_optimize(pf_info,ratio='sharpe',simulation=10000,RF=0, \
2232
2383
  zhuhe_txt='组合'
2233
2384
  mingcheng_txt='投资组合名称/策略'
2234
2385
  titletxt="投资组合策略:业绩比较"
2235
- ylabeltxt="持有收益率"
2386
+ ylabeltxt="持有期收益率"
2236
2387
  else:
2237
2388
  zhuhe_txt=''
2238
2389
  mingcheng_txt='Strategy'
2239
2390
  titletxt="Investment Portfolio Strategy: Performance Comparison"
2240
- ylabeltxt="Holding Return"
2391
+ ylabeltxt="Holding Period Return"
2241
2392
 
2242
2393
  #打印投资组合构造和业绩表现
2243
2394
  hi_name=modify_portfolio_name(name_hiret+zhuhe_txt)
@@ -2508,7 +2659,7 @@ if __name__=='__main__':
2508
2659
  def cm2inch(x,y):
2509
2660
  return x/2.54,y/2.54
2510
2661
 
2511
- def security_correlation(tickers,start,end,info_type='Close'):
2662
+ def security_correlation(tickers,start,end,info_type='Close',facecolor='papayawhip'):
2512
2663
  """
2513
2664
  功能:股票/指数收盘价之间的相关性
2514
2665
  info_type='Close': 默认Close, 还可为Open/High/Low/Volume
@@ -2567,7 +2718,8 @@ def security_correlation(tickers,start,end,info_type='Close'):
2567
2718
 
2568
2719
  im1 = sns.heatmap(df_coor,annot=True,cmap="YlGnBu"
2569
2720
  , mask=mask#构造mask,去除重复数据显示
2570
- ,vmax=1,vmin=-1
2721
+ , vmax=1,vmin=-1
2722
+ , cbar=False
2571
2723
  , fmt='.2f',ax = ax1,annot_kws={"size": 6})
2572
2724
 
2573
2725
  ax1.tick_params(axis = 'both', length=0)
@@ -2617,21 +2769,27 @@ def security_correlation(tickers,start,end,info_type='Close'):
2617
2769
  elif pv< 0.001:
2618
2770
  ax1.text(n+widthx,m+widthy,'***',ha = 'center',color = 'k',fontdict=font_dict)
2619
2771
 
2620
- plt.title("证券"+info_type_cn+"之间的相关性")
2772
+ plt.title(text_lang("证券","Security's Correlation among ")+text_lang(info_type_cn,info_type+" Prices")+text_lang("之间的相关性",''),fontsize=10)
2621
2773
  plt.tick_params(labelsize=6)
2622
2774
 
2623
- footnote1="\n显著性数值:***非常显著(<0.001),**很显著(<0.01),*显著(<0.05),其余为不显著"
2624
- footnote2="\n系数绝对值:>=0.8极强相关,0.6-0.8强相关,0.4-0.6相关,0.2-0.4弱相关,否则为极弱(不)相关"
2775
+ footnote1=text_lang("\n显著性数值:***非常显著(<0.001),**很显著(<0.01),*显著(<0.05),其余为不显著", \
2776
+ "\nSig level: *** Extremely sig(p<0.001), ** Very sig(<0.01), * Sig(<0.05), others unsig")
2777
+ footnote2=text_lang("\n系数绝对值:>=0.8极强相关,0.6-0.8强相关,0.4-0.6相关,0.2-0.4弱相关,否则为极弱(不)相关", \
2778
+ "\nCoef. abs: >=0.8 Extreme corr, 0.6-0.8 Strong corr, 0.4-0.6 Corr, <0.4 Weak or uncorr")
2625
2779
 
2626
- footnote3="\n观察期间: "+start+'至'+end
2780
+ footnote3=text_lang("\n观察期间: ","\nPeriod of sample: ")+start+text_lang('至',' to ')+end
2627
2781
  import datetime as dt; stoday=dt.date.today()
2628
- footnote4=";数据来源:Sina/EM/stooq/Yahoo,"+str(stoday)
2782
+ footnote4=text_lang(";数据来源:Sina/EM/Stooq/Yahoo,",". Data source: Sina/EM/Stooq/Yahoo, ")+str(stoday)
2629
2783
 
2630
2784
  fontxlabel={'size':6}
2631
2785
  plt.xlabel(footnote1+footnote2+footnote3+footnote4,fontxlabel)
2632
2786
  #plt.xticks(rotation=45)
2633
2787
 
2634
- plt.gca().set_facecolor('papayawhip')
2788
+ plt.gca().set_facecolor(facecolor)
2789
+
2790
+ plt.xticks(fontsize=6, rotation=90)
2791
+ plt.yticks(fontsize=6, rotation=0)
2792
+
2635
2793
  plt.show()
2636
2794
 
2637
2795
  return df_coor
siat/markowitz_simple.py CHANGED
@@ -218,7 +218,7 @@ def markowitz_sharpe(components,start,end,risk_free=0.015,simulation=25000, \
218
218
  {"fun":lambda x:(np.sum(x)-1),"type":"eq"}
219
219
  ])
220
220
  if res.success:
221
- frontier=frontier.append({"std":std,"ret":-res.fun},ignore_index=True)
221
+ frontier=frontier._append({"std":std,"ret":-res.fun},ignore_index=True)
222
222
 
223
223
  # 略微上调有效边界
224
224
  frontier2=frontier.copy()
siat/security_prices.py CHANGED
@@ -163,18 +163,18 @@ def get_prices(ticker,fromdate,todate,adj=False,source='auto', \
163
163
 
164
164
  if source in ['auto']:
165
165
  #尝试AkShare+Sina+EM(新浪,对中国内地股票、港股和美股有效,但不包括国外市场指数)
166
- print(" Trying to capture prices from sina/EM ... ...")
166
+ print(" Trying to capture prices from sina/EM for",ticker,"...")
167
167
  try:
168
168
  prices=get_prices_ak(ticker,fromdate,todate,ticker_type=ticker_type) #支持多个证券
169
169
  except:
170
- print(" #Warning(get_prices): info retrieving failed from sina/EM")
170
+ print(" #Warning(get_prices): info retrieving failed from sina/EM for",ticker)
171
171
  else:
172
172
  if prices is None:
173
- print(" #Warning(get_prices): info not found from sina/EM")
173
+ print(" #Warning(get_prices): info not found from sina/EM for",ticker)
174
174
  else:
175
175
  num=len(prices)
176
176
  if num==0:
177
- print(" #Warning(get_prices): security may suspend trading or already expired")
177
+ print(" #Warning(get_prices):",ticker,"may be suspended or delisted")
178
178
  return prices
179
179
  else:
180
180
  prices2=remove_timezone(prices)
@@ -188,14 +188,14 @@ def get_prices(ticker,fromdate,todate,adj=False,source='auto', \
188
188
  prices=get_price_stooq(ticker,fromdate,todate) #仅支持单只证券
189
189
  #prices=get_prices_stooq(ticker,fromdate,todate)?
190
190
  except:
191
- print(" #Warning(get_prices): info retrieving failed from stooq")
191
+ print(" #Warning(get_prices): info retrieving failed from stooq for",ticker)
192
192
  else:
193
193
  if prices is None:
194
- print(" #Warning(get_prices): info not found from stooq")
194
+ print(" #Warning(get_prices): info not found from stooq for",ticker)
195
195
  else:
196
196
  num=len(prices)
197
197
  if num==0:
198
- print(" #Warning(get_prices): zero record found")
198
+ print(" #Warning(get_prices): zero record found for",ticker)
199
199
  else:
200
200
  prices2=remove_timezone(prices)
201
201
  return prices2 #找到有效数据就返回,否则继续
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: siat
3
- Version: 3.3.11
3
+ Version: 3.4.1
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
@@ -18,7 +18,7 @@ siat/capm_beta.py,sha256=cxXdRVBQBllhbfz1LeTJAIWvyRYhW54nhtNUXv4HwS0,29063
18
18
  siat/capm_beta2.py,sha256=lUuCPVSxebkA2yye1PXu1V2Jd2UKEwD_kIA25DCIDTs,29750
19
19
  siat/capm_beta_test.py,sha256=ImR0c5mc4hIl714XmHztdl7qg8v1E2lycKyiqnFj6qs,1745
20
20
  siat/cmat_commons.py,sha256=Nj9Kf0alywaztVoMVeVVL_EZk5jRERJy8R8kBw88_Tg,38116
21
- siat/common.py,sha256=Uc_BLjlp6njmGFBMSaM45fcHKgk9kjnKacFcFYljrmE,151620
21
+ siat/common.py,sha256=MjnhlSLKXHXT6TaveSZ5_-RuPNjPuUe-GC0RpzRvnnw,151619
22
22
  siat/compare_cross.py,sha256=3iP9TH2h3w27F2ARZc7FjKcErYCzWRc-TPiymOyoVtw,24171
23
23
  siat/compare_cross_test.py,sha256=xra5XYmQGEtfIZL2h-GssdH2hLdFIhG3eoCrkDrL3gY,3473
24
24
  siat/concepts_iwencai.py,sha256=m1YEDtECRT6FqtzlKm91pt2I9d3Z_XoP59BtWdRdu8I,3061
@@ -69,12 +69,12 @@ siat/luchy_draw.py,sha256=8Ue-NKnvSVqINPY1eXat0NJat5MR-gex_K62aOYFdmA,20486
69
69
  siat/market_china.py,sha256=EOO-RvdnzJThTrgNHWW3TlWhx4k4rfdjbooOnQsYdQU,50299
70
70
  siat/markowitz.py,sha256=DsfS6vG9TAfdJP4GgN-CCArujPi84XjD23CWbxaA2o4,97627
71
71
  siat/markowitz2-20240620.py,sha256=irZAPnjaatFsKQmFRMENP-cO6bEUl2narYtkU5NKTWI,108019
72
- siat/markowitz2.py,sha256=IJloAP3sAotlVs1tWMUXbIu-9tX4D_Dx12pIkfFDRx4,113955
72
+ siat/markowitz2.py,sha256=LK2pDEtE5PUmBtCHmCcRs8FlPqZKmhFXiuLIL4JeQa8,121991
73
73
  siat/markowitz_ccb_test.py,sha256=xBkkoaNHdq9KSUrNuHGgKTdNYUvgi84kNYcf719eoyE,1593
74
74
  siat/markowitz_ef_test.py,sha256=wjNlICkgRIqnonPeSIHo4Mu2GRtb9dr21wDt2kMNEcI,4032
75
75
  siat/markowitz_old.py,sha256=Lf7O_4QWT8RsdkHiUyc_7kKY3eZjKDtFR89Fz3pwYnY,33046
76
76
  siat/markowitz_simple-20230709.py,sha256=fSzRrX_3HN3lFGJ3PntJFjfHAOc7vjEUZ6T1uQGdc64,14160
77
- siat/markowitz_simple.py,sha256=bckFmH3_OUctofdco4ZojZ412Aqci9vAT7WREiP4PGA,14285
77
+ siat/markowitz_simple.py,sha256=aJVvx669ngcCsqoQtA9kvFOQVjsuipYt2fyTc4yMItE,14286
78
78
  siat/markowitz_test.py,sha256=fDXoPp6DrKeneYjd0lbb0KfYUJj-VcOvVaPlfsIOstw,5818
79
79
  siat/markowitz_test2.py,sha256=FcVZqYU5va4567WGUVUJ7cMQdVbBGxeBAz82Y3BhCTI,2193
80
80
  siat/ml_cases.py,sha256=FYDk0O7l9hhHlbrlOVGgbH-h2DA503lhKFi9XugH1f0,86874
@@ -98,7 +98,7 @@ siat/sector_china.py,sha256=nP6kfYsnaQWZj8dK-zklwSDW8FDS-obZWp_zL0ec2Ig,118603
98
98
  siat/sector_china_test.py,sha256=1wq7ef8Bb_L8F0h0W6FvyBrIcBTEbrTV7hljtpj49U4,5843
99
99
  siat/security_price.py,sha256=2oHskgiw41KMGfqtnA0i2YjNNV6cYgtlUK0j3YeuXWs,29185
100
100
  siat/security_price2.py,sha256=4xvc9AzRhLKJMu6AxVzIqcn1-NrHoeCF2Ao2p9nwYjU,25978
101
- siat/security_prices.py,sha256=9T4RVZNDlxAGursIb4hZqGeekjYgjBgo3uALhzhWWLw,106181
101
+ siat/security_prices.py,sha256=2aLBSyVRfcZ1-5jqF_r3N02RvlaNNqssJS9GgxGidgM,106235
102
102
  siat/security_prices_test.py,sha256=OEphoJ87NPKoNow1QA8EU_5MUYrJF-qKoWKNapVfZNI,10779
103
103
  siat/security_trend.py,sha256=o0vpWdrJkmODCP94X-Bvn-w7efHhj9HpUYBHtLl55D0,17240
104
104
  siat/security_trend2-20240620.py,sha256=QVnEcb7AyVbO77jVqfFsJffGXrX8pgJ9xCfoAKmWBPk,24854
@@ -139,7 +139,7 @@ siat/valuation_china.py,sha256=EkZQaVkoBjM0c4MCNbaX-bMnlG0e3FXeaWczZDnkptU,67784
139
139
  siat/valuation_market_china_test.py,sha256=gbJ0ioauuo4koTPH6WKUkqcXiQPafnbhU5eKJ6lpdLA,1571
140
140
  siat/var_model_validation.py,sha256=R0caWnuZarrRg9939hxh3vJIIpIyPfvelYmzFNZtPbo,14910
141
141
  siat/yf_name.py,sha256=H1EM8YYXA8nQHIqsJlso0I3HKPiJLT3QujO4gRVQXWs,13945
142
- siat-3.3.11.dist-info/METADATA,sha256=r7Y7j2sf7516iGiB-pbSzLRC_a0VuYCLWJ2k6zHJOrE,7310
143
- siat-3.3.11.dist-info/WHEEL,sha256=yQN5g4mg4AybRjkgi-9yy4iQEFibGQmlz78Pik5Or-A,92
144
- siat-3.3.11.dist-info/top_level.txt,sha256=r1cVyL7AIKqeAmEJjNR8FMT20OmEzufDstC2gv3NvEY,5
145
- siat-3.3.11.dist-info/RECORD,,
142
+ siat-3.4.1.dist-info/METADATA,sha256=0s5TpzHfnUzzwRFnFeoBNXS-3miIuEZglezF2dKX0rs,7309
143
+ siat-3.4.1.dist-info/WHEEL,sha256=2wepM1nk4DS4eFpYrW1TTqPcoGNfHhhO_i5m4cOimbo,92
144
+ siat-3.4.1.dist-info/top_level.txt,sha256=r1cVyL7AIKqeAmEJjNR8FMT20OmEzufDstC2gv3NvEY,5
145
+ siat-3.4.1.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.41.2)
2
+ Generator: bdist_wheel (0.38.4)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5