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 +2 -2
- siat/markowitz2.py +234 -76
- siat/markowitz_simple.py +1 -1
- siat/security_prices.py +7 -7
- {siat-3.3.11.dist-info → siat-3.4.1.dist-info}/METADATA +1 -1
- {siat-3.3.11.dist-info → siat-3.4.1.dist-info}/RECORD +8 -8
- {siat-3.3.11.dist-info → siat-3.4.1.dist-info}/WHEEL +1 -1
- {siat-3.3.11.dist-info → siat-3.4.1.dist-info}/top_level.txt +0 -0
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%,
|
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
|
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
|
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
|
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,
|
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,
|
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,
|
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,
|
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),
|
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,
|
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,
|
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,
|
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),
|
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("年化收益率%","
|
959
|
+
"年化收益率%":text_lang("年化收益率%","pa Return%"), \
|
957
960
|
"收益率变化":text_lang("收益率变化","Return%+/-"), \
|
958
961
|
"风险排名":text_lang("风险排名","Risk#"), \
|
959
|
-
"年化标准差%":text_lang("年化标准差%","
|
962
|
+
"年化标准差%":text_lang("年化标准差%","pa Std%"), \
|
960
963
|
"标准差变化":text_lang("标准差变化","Std%+/-"), \
|
961
964
|
"收益率/标准差":text_lang("收益率/标准差","Return/Std")}, \
|
962
965
|
inplace=True)
|
963
966
|
|
964
|
-
|
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='
|
967
|
-
titile_font_size='
|
968
|
-
data_font_size='
|
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
|
-
|
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
|
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
|
-
|
1210
|
-
|
1211
|
-
|
1212
|
-
|
1213
|
-
|
1214
|
-
|
1215
|
-
|
1216
|
-
|
1217
|
-
|
1218
|
-
|
1219
|
-
|
1220
|
-
|
1221
|
-
|
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
|
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=
|
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=
|
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=
|
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=
|
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
|
-
|
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
|
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='
|
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='
|
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
|
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,
|
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=
|
2344
|
+
def portfolio_optimize(pf_info,ratio='sharpe',simulation=50000,RF=0, \
|
2195
2345
|
graph=True,hirar_return=False,lorisk=True, \
|
2196
|
-
convex_hull=
|
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,
|
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
|
-
|
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/
|
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(
|
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.
|
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):
|
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 #找到有效数据就返回,否则继续
|
@@ -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=
|
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=
|
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=
|
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=
|
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.
|
143
|
-
siat-3.
|
144
|
-
siat-3.
|
145
|
-
siat-3.
|
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,,
|
File without changes
|