siat 3.3.1__py3-none-any.whl → 3.3.10__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/capm_beta2.py +83 -7
- siat/common.py +4 -4
- siat/fund_china.pickle +0 -0
- siat/markowitz.py +17 -17
- siat/risk_adjusted_return2.py +311 -63
- siat/stock.py +24 -23
- siat/stock_info.pickle +0 -0
- siat/translate.py +21 -6
- {siat-3.3.1.dist-info → siat-3.3.10.dist-info}/METADATA +1 -1
- {siat-3.3.1.dist-info → siat-3.3.10.dist-info}/RECORD +12 -12
- {siat-3.3.1.dist-info → siat-3.3.10.dist-info}/WHEEL +0 -0
- {siat-3.3.1.dist-info → siat-3.3.10.dist-info}/top_level.txt +0 -0
siat/capm_beta2.py
CHANGED
@@ -202,6 +202,79 @@ def regression_capm(ticker,start2,end, \
|
|
202
202
|
|
203
203
|
return reg_result,dretdf3
|
204
204
|
|
205
|
+
|
206
|
+
def regression_capm_df(marketdf,pricedf,mktidx,adjust='',RF=0,regtrddays=252):
|
207
|
+
"""
|
208
|
+
功能:进行CAPM回归,R-Rf=beta*(Rm-Rf),无截距项回归
|
209
|
+
x为(Rm-Rf),y为R-Rf,均为日收益率,默认回归样本长度一年(365日历日或252交易日)
|
210
|
+
返回:beta系数
|
211
|
+
注意:回归基于传统的日收益率,而非滚动收益率
|
212
|
+
"""
|
213
|
+
|
214
|
+
#合并股票和大盘指数日收益率
|
215
|
+
dretdf1=pd.merge(marketdf,pricedf,how='inner',left_index=True,right_index=True)
|
216
|
+
|
217
|
+
#准备CAPM回归文件
|
218
|
+
if adjust == '':
|
219
|
+
dretname='Daily Ret'
|
220
|
+
else:
|
221
|
+
dretname='Daily Adj Ret'
|
222
|
+
|
223
|
+
#计算日无风险利率
|
224
|
+
RF_daily=RF / 365
|
225
|
+
|
226
|
+
dretx=dretname+'_x' #指数日收益率
|
227
|
+
drety=dretname+'_y' #股票日收益率
|
228
|
+
dretdf2=dretdf1[[dretx,drety]]
|
229
|
+
dretdf2.dropna(inplace=True)
|
230
|
+
|
231
|
+
#计算股票和指数收益率的风险溢价R-RF
|
232
|
+
dretdfcols=list(dretdf2)
|
233
|
+
for c in dretdfcols:
|
234
|
+
dretdf2[c]=dretdf2[c].apply(lambda x: x-RF_daily)
|
235
|
+
dretdf2=dretdf2.reset_index()
|
236
|
+
#dretdf2.rename(columns={'index':'Date'},inplace=True)
|
237
|
+
if 'Date' not in list(dretdf2):
|
238
|
+
dretdf2['Date']=dretdf2['index']
|
239
|
+
|
240
|
+
#CAPM回归,计算贝塔系数
|
241
|
+
dretnum=len(dretdf2)
|
242
|
+
if regtrddays >= dretnum:
|
243
|
+
regtrddays=dretnum - 31 *2
|
244
|
+
|
245
|
+
import statsmodels.api as sm
|
246
|
+
reg_result=pd.DataFrame(columns=('Date','beta'))
|
247
|
+
for i in range(dretnum):
|
248
|
+
i2=dretnum-i
|
249
|
+
i1=i2-regtrddays
|
250
|
+
if i1 < 0: break
|
251
|
+
|
252
|
+
regdf=dretdf2[i1:i2]
|
253
|
+
lastdate=regdf.tail(1)['Date'].values[0]
|
254
|
+
|
255
|
+
X=regdf[dretx] #无截距项回归
|
256
|
+
Y=regdf[drety]
|
257
|
+
model = sm.OLS(Y,X) #定义回归模型R-Rf=beta(Rm-Rf),X可为多元矩阵
|
258
|
+
results = model.fit() #进行OLS回归
|
259
|
+
beta=results.params[0] #提取回归系数
|
260
|
+
|
261
|
+
row=pd.Series({'Date':lastdate,'beta':beta})
|
262
|
+
try:
|
263
|
+
reg_result=reg_result.append(row,ignore_index=True)
|
264
|
+
except:
|
265
|
+
reg_result=reg_result._append(row,ignore_index=True)
|
266
|
+
|
267
|
+
reg_result.set_index(['Date'],inplace=True)
|
268
|
+
reg_result.sort_index(inplace=True) #按日期升序排列
|
269
|
+
|
270
|
+
dretdf3=dretdf2.set_index(['Date'])
|
271
|
+
if 'index' in list(dretdf3):
|
272
|
+
del dretdf3['index']
|
273
|
+
|
274
|
+
reg_result['mktidx']=mktidx
|
275
|
+
|
276
|
+
return reg_result,dretdf3
|
277
|
+
|
205
278
|
#==============================================================================
|
206
279
|
if __name__=='__main__':
|
207
280
|
ticker="600519.SS"
|
@@ -328,16 +401,19 @@ def compare_mticker_1beta(ticker,start,end, \
|
|
328
401
|
#df1.rename(columns={c:ticker_name(c)},inplace=True)
|
329
402
|
|
330
403
|
#共同脚注
|
331
|
-
footnote1="注:"
|
404
|
+
footnote1=text_lang("注:","Notes: ")
|
405
|
+
"""
|
332
406
|
if RF !=0:
|
333
|
-
footnote2="年化无风险利率为"+str(round(RF*100,4))+'%。'
|
407
|
+
footnote2=text_lang("年化无风险利率为","RF = ")+str(round(RF*100,4))+text_lang('%。','% pa. ')
|
334
408
|
else:
|
335
409
|
footnote2="假设年化无风险利率为零。"
|
336
|
-
|
337
|
-
|
410
|
+
"""
|
411
|
+
footnote2=text_lang("年化无风险利率为","RF = ")+str(round(RF*100,4))+text_lang('%。','% pa. ')
|
412
|
+
|
413
|
+
footnote3=text_lang("基于","Beta using ")+mktidx_name+text_lang(",CAPM回归期间为",", CAPM rolling ")+str(regression_period)+text_lang("个自然日"," days")
|
338
414
|
|
339
415
|
import datetime; todaydt = datetime.date.today()
|
340
|
-
footnote4="数据来源: 综合新浪/
|
416
|
+
footnote4=text_lang("数据来源: 综合新浪/Stooq/Yahoo,","Data source: Sina/Stooq/Yahoo, ")+str(todaydt)+text_lang("统计",'')
|
341
417
|
if footnote3 !='':
|
342
418
|
footnotex=footnote1+footnote2+footnote3+'\n'+footnote4
|
343
419
|
else:
|
@@ -345,8 +421,8 @@ def compare_mticker_1beta(ticker,start,end, \
|
|
345
421
|
|
346
422
|
#绘图
|
347
423
|
if graph:
|
348
|
-
title_txt="CAPM贝塔系数"
|
349
|
-
y_label="贝塔系数"
|
424
|
+
title_txt=text_lang("CAPM贝塔系数","CAPM Beta Coefficient")
|
425
|
+
y_label=text_lang("贝塔系数","Beta")
|
350
426
|
|
351
427
|
draw_lines(df1,y_label,x_label=footnotex, \
|
352
428
|
axhline_value=axhline_value,axhline_label=axhline_label, \
|
siat/common.py
CHANGED
@@ -2437,15 +2437,15 @@ def descriptive_statistics2(df,titletxt,footnote,decimals=4,sortby='tpw_mean', \
|
|
2437
2437
|
heading_font_size=data_font_size=str(int(font_size.replace('px',''))-1)+'px'
|
2438
2438
|
|
2439
2439
|
dst6.rename(columns={"比较对象":text_lang("比较对象","Securities"), \
|
2440
|
-
"最小值":text_lang("最小值","
|
2441
|
-
"最大值":text_lang("最大值","
|
2440
|
+
"最小值":text_lang("最小值","Min"), \
|
2441
|
+
"最大值":text_lang("最大值","Max"), \
|
2442
2442
|
"中位数":text_lang("中位数","Median"), \
|
2443
2443
|
"平均值":text_lang("平均值","Mean"), \
|
2444
2444
|
"标准差":text_lang("标准差","Std Dev"), \
|
2445
2445
|
"近期优先加权平均":text_lang("近期优先加权平均","RWA"), \
|
2446
|
-
"期间趋势":text_lang("期间趋势","
|
2446
|
+
"期间趋势":text_lang("期间趋势","Period Trend"), \
|
2447
2447
|
"近期趋势":text_lang("近期趋势","Recent Trend"), \
|
2448
|
-
"推荐标记":text_lang("推荐标记","
|
2448
|
+
"推荐标记":text_lang("推荐标记","Recommend")},inplace=True)
|
2449
2449
|
|
2450
2450
|
df_display_CSS(dst6,titletxt=titletxt,footnote=footnote,facecolor=facecolor, \
|
2451
2451
|
titile_font_size=titile_font_size,heading_font_size=heading_font_size, \
|
siat/fund_china.pickle
CHANGED
Binary file
|
siat/markowitz.py
CHANGED
@@ -159,10 +159,10 @@ def cumulative_returns_plot(retgroup,name_list="",titletxt="投资组合策略
|
|
159
159
|
import datetime as dt; stoday=dt.date.today()
|
160
160
|
if lang == 'Chinese':
|
161
161
|
footnote1="观察期间: "+hstart+'至'+hend
|
162
|
-
footnote2="\n
|
162
|
+
footnote2="\n数据来源:Sina/EM/Stooq/Yahoo, "+str(stoday)
|
163
163
|
else:
|
164
164
|
footnote1="Period of observation: "+hstart+' to '+hend
|
165
|
-
footnote2="\
|
165
|
+
footnote2="\nData source: Sina/EM/Stooq/Yahoo, "+str(stoday)
|
166
166
|
|
167
167
|
xlabeltxt=footnote1+footnote2
|
168
168
|
|
@@ -344,11 +344,11 @@ def portfolio_cumret(portfolio,thedate,pastyears=1, \
|
|
344
344
|
if lang == 'Chinese':
|
345
345
|
title_txt="投资组合: 日收益率的变化趋势"
|
346
346
|
ylabel_txt="日收益率"
|
347
|
-
source_txt="
|
347
|
+
source_txt="数据来源: Sina/EM/Stooq/Yahoo, "
|
348
348
|
else:
|
349
349
|
title_txt="Investment Portfolio: Daily Return"
|
350
350
|
ylabel_txt="Daily Return"
|
351
|
-
source_txt="
|
351
|
+
source_txt="Data source: Sina/EM/Stooq/Yahoo, "
|
352
352
|
|
353
353
|
plt.title(title_txt)
|
354
354
|
plt.ylabel(ylabel_txt)
|
@@ -368,11 +368,11 @@ def portfolio_cumret(portfolio,thedate,pastyears=1, \
|
|
368
368
|
if lang == 'Chinese':
|
369
369
|
titletxt="投资组合: 持有收益率的变化趋势"
|
370
370
|
ylabeltxt="持有收益率"
|
371
|
-
xlabeltxt="
|
371
|
+
xlabeltxt="数据来源: Sina/EM/Stooq/Yahoo, "+str(stoday)
|
372
372
|
else:
|
373
373
|
titletxt="Investment Portfolio: Holding Return"
|
374
374
|
ylabeltxt="Holding Return"
|
375
|
-
xlabeltxt="
|
375
|
+
xlabeltxt="Data source: Sina/EM/Stooq/Yahoo, "+str(stoday)
|
376
376
|
|
377
377
|
#绘制持有收益率曲线
|
378
378
|
if graph:
|
@@ -497,7 +497,7 @@ def portfolio_corr(pf_info):
|
|
497
497
|
|
498
498
|
footnote1="观察期间: "+hstart+'至'+hend
|
499
499
|
import datetime as dt; stoday=dt.date.today()
|
500
|
-
footnote2="\n
|
500
|
+
footnote2="\n数据来源:Sina/EM/Stooq/Yahoo, "+str(stoday)
|
501
501
|
plt.xlabel(footnote1+footnote2)
|
502
502
|
plt.xticks(rotation=90); plt.yticks(rotation=0)
|
503
503
|
|
@@ -541,7 +541,7 @@ def portfolio_covar(pf_info):
|
|
541
541
|
|
542
542
|
footnote1="观察期间: "+hstart+'至'+hend
|
543
543
|
import datetime as dt; stoday=dt.date.today()
|
544
|
-
footnote2="\n
|
544
|
+
footnote2="\n数据来源:Sina/EM/Stooq/Yahoo, "+str(stoday)
|
545
545
|
plt.xlabel(footnote1+footnote2)
|
546
546
|
plt.xticks(rotation=90)
|
547
547
|
plt.yticks(rotation=0)
|
@@ -623,7 +623,7 @@ def portfolio_expectation_universal(pname,member_returns,portfolio_weights,membe
|
|
623
623
|
print(" ***投资组合持仓策略***")
|
624
624
|
print_tickerlist_sharelist(tickerlist,portfolio_weights,4)
|
625
625
|
|
626
|
-
print("
|
626
|
+
print(" *数据来源:Sina/EM/Stooq/Yahoo, "+str(stoday))
|
627
627
|
else:
|
628
628
|
print("\n ======= Investment Portfolio: Return and Risk =======")
|
629
629
|
print(" Investment portfolio:",pname)
|
@@ -635,7 +635,7 @@ def portfolio_expectation_universal(pname,member_returns,portfolio_weights,membe
|
|
635
635
|
print(" ***Portfolio Constructing Strategy***")
|
636
636
|
print_tickerlist_sharelist(tickerlist,portfolio_weights,4)
|
637
637
|
|
638
|
-
print(" *
|
638
|
+
print(" *Data source: Sina/EM/Stooq/Yahoo, "+str(stoday))
|
639
639
|
|
640
640
|
return
|
641
641
|
|
@@ -1007,7 +1007,7 @@ def portfolio_es(pf_info,simulation=50000):
|
|
1007
1007
|
footnote1="年化收益率标准差-->"
|
1008
1008
|
footnote2="\n\n基于给定的成份证券构造"+str(simulation)+"个投资组合"
|
1009
1009
|
footnote3="\n观察期间:"+hstart+"至"+hend
|
1010
|
-
footnote4="\n
|
1010
|
+
footnote4="\n数据来源: Sina/EM/Stooq/Yahoo, "+str(stoday)
|
1011
1011
|
else:
|
1012
1012
|
if pname == '': pname='Investment Portfolio'
|
1013
1013
|
|
@@ -1017,8 +1017,8 @@ def portfolio_es(pf_info,simulation=50000):
|
|
1017
1017
|
|
1018
1018
|
footnote1="Annualized Std -->\n\n"
|
1019
1019
|
footnote2="Based on given component securities, constructed "+str(simulation)+" portfolios\n"
|
1020
|
-
footnote3="Period of
|
1021
|
-
footnote4="\
|
1020
|
+
footnote3="Period of sample: "+hstart+" to "+hend
|
1021
|
+
footnote4="\nData Source: Sina/EM/Stooq/Yahoo, "+str(stoday)
|
1022
1022
|
|
1023
1023
|
plt.xlabel(footnote1+footnote2+footnote3+footnote4,fontsize=xlabel_txt_size)
|
1024
1024
|
|
@@ -1481,7 +1481,7 @@ def RandomPortfolios_plot(RandomPortfolios,col_x,col_y,colorbartxt,title_ext, \
|
|
1481
1481
|
footnote1=x_axis_name+" -->\n\n"
|
1482
1482
|
footnote2="基于设定的成份证券构造"+str(simulation)+"个投资组合"
|
1483
1483
|
footnote3="\n观察期间:"+hstart+"至"+hend
|
1484
|
-
footnote4="\n
|
1484
|
+
footnote4="\n数据来源: Sina/EM/Stooq/Yahoo, "+str(stoday)
|
1485
1485
|
else:
|
1486
1486
|
if pname == '': pname='Investment Portfolio'
|
1487
1487
|
|
@@ -1491,8 +1491,8 @@ def RandomPortfolios_plot(RandomPortfolios,col_x,col_y,colorbartxt,title_ext, \
|
|
1491
1491
|
import datetime as dt; stoday=dt.date.today()
|
1492
1492
|
footnote1=x_axis_name+" -->\n\n"
|
1493
1493
|
footnote2="Based on given component securities, constructed "+str(simulation)+" portfolios"
|
1494
|
-
footnote3="\nPeriod of
|
1495
|
-
footnote4="\
|
1494
|
+
footnote3="\nPeriod of sample: "+hstart+" to "+hend
|
1495
|
+
footnote4="\nData source: Sina/EM/Stooq/Yahoo, "+str(stoday)
|
1496
1496
|
|
1497
1497
|
plt.xlabel(footnote1+footnote2+footnote3+footnote4,fontsize=xlabel_txt_size)
|
1498
1498
|
|
@@ -2267,7 +2267,7 @@ def security_correlation(tickers,start,end,info_type='Close'):
|
|
2267
2267
|
|
2268
2268
|
footnote3="\n观察期间: "+start+'至'+end
|
2269
2269
|
import datetime as dt; stoday=dt.date.today()
|
2270
|
-
footnote4="
|
2270
|
+
footnote4=";数据来源:Sina/EM/Stooq/Yahoo,"+str(stoday)
|
2271
2271
|
|
2272
2272
|
fontxlabel={'size':6}
|
2273
2273
|
plt.xlabel(footnote1+footnote2+footnote3+footnote4,fontxlabel)
|
siat/risk_adjusted_return2.py
CHANGED
@@ -32,15 +32,15 @@ import numpy as np
|
|
32
32
|
#==============================================================================
|
33
33
|
#==============================================================================
|
34
34
|
if __name__=='__main__':
|
35
|
-
ticker="
|
35
|
+
ticker="AAPL"
|
36
36
|
ticker={'Market':('US','^SPX','中概教培组合'),'EDU':0.7,'TAL':0.3}
|
37
37
|
|
38
38
|
start="2024-1-1"
|
39
|
-
end="2024-
|
39
|
+
end="2024-6-30"
|
40
40
|
rar_name="sharpe"
|
41
|
-
ret_type="
|
42
|
-
RF=0
|
43
|
-
source='auto'
|
41
|
+
ret_type="Annual Adj Ret%"
|
42
|
+
RF=0.055
|
43
|
+
source='auto'; ticker_type='auto'
|
44
44
|
|
45
45
|
sharpe1m0=get_rolling_sharpe_sortino(ticker,start,end,rar_name="sharpe",ret_type="Monthly Ret%",RF=0)
|
46
46
|
sharpe2w=get_rolling_sharpe_sortino(ticker,start,end,rar_name="sharpe",ret_type="Weekly Ret%",RF=0.01759)
|
@@ -52,7 +52,7 @@ if __name__=='__main__':
|
|
52
52
|
sortino2=get_rolling_sharpe_sortino(ticker,start,end,rar_name="sortino",ret_type="Monthly Ret%",RF=0.01759)
|
53
53
|
|
54
54
|
def get_rolling_sharpe_sortino(ticker,start,end,rar_name="sharpe", \
|
55
|
-
ret_type="Monthly Ret%",RF=0,source='auto', \
|
55
|
+
ret_type="Monthly Adj Ret%",RF=0,source='auto', \
|
56
56
|
ticker_type='auto'):
|
57
57
|
"""
|
58
58
|
功能:获取一只股票的夏普比率或索替诺比率,基于给定的滚动收益率类型,在指定期间内
|
@@ -116,7 +116,6 @@ def get_rolling_sharpe_sortino(ticker,start,end,rar_name="sharpe", \
|
|
116
116
|
#收益率减去一个常数其实不影响其标准差的数值,即std(ret-RF)=std(ret)
|
117
117
|
rardf2[ret_type]=rardf2[ret_type] - RF_period
|
118
118
|
rardf3=rolling_ret_volatility(rardf2, period=ret_period)
|
119
|
-
#收益率减去一个常数应该影响其下偏标准差的数值,即lpsd(ret-RF)!=lpsd(ret),实际上却未影响,有点奇怪
|
120
119
|
rardf4=rolling_ret_lpsd(rardf3, period=ret_period)
|
121
120
|
|
122
121
|
#开始日期富余一段时间,有助于绘图时显示出期望的开始日期
|
@@ -171,7 +170,7 @@ if __name__=='__main__':
|
|
171
170
|
sortino2=get_expanding_sharpe_sortino(ticker,start,end,rar_name="sortino",RF=0.01759)
|
172
171
|
|
173
172
|
def get_expanding_sharpe_sortino(ticker,start,end,rar_name="sharpe", \
|
174
|
-
ret_type="Exp Ret%",RF=0,source='auto',ticker_type='auto'):
|
173
|
+
ret_type="Exp Adj Ret%",RF=0,source='auto',ticker_type='auto'):
|
175
174
|
"""
|
176
175
|
功能:获取一只股票的夏普比率或索替诺比率,基于扩展收益率,在指定期间内
|
177
176
|
支持股票和投资组合
|
@@ -252,16 +251,16 @@ def get_expanding_sharpe_sortino(ticker,start,end,rar_name="sharpe", \
|
|
252
251
|
|
253
252
|
#==============================================================================
|
254
253
|
if __name__=='__main__':
|
255
|
-
ticker="
|
254
|
+
ticker="AAPL"
|
256
255
|
ticker={'Market':('US','^SPX','中概教培组合'),'EDU':0.7,'TAL':0.3}
|
257
256
|
|
258
257
|
start="2024-1-1"
|
259
|
-
end="2024-
|
260
|
-
rar_name="
|
261
|
-
ret_type="
|
262
|
-
RF=0.
|
258
|
+
end="2024-6-30"
|
259
|
+
rar_name="treynor"
|
260
|
+
ret_type="Annual Adj Ret%"
|
261
|
+
RF=0.055
|
263
262
|
regression_period=365
|
264
|
-
mktidx='auto'; source='auto'
|
263
|
+
mktidx='auto'; source='auto'; ticker_type='auto'
|
265
264
|
|
266
265
|
alpha1m0=get_rolling_treynor_alpha(ticker,start,end,rar_name="alpha",ret_type="Monthly Ret%",RF=0)
|
267
266
|
alpha2w=get_rolling_treynor_alpha(ticker,start,end,rar_name="alpha",ret_type="Weekly Ret%",RF=0.01759)
|
@@ -277,6 +276,7 @@ def get_rolling_treynor_alpha(ticker,start,end,rar_name="alpha", \
|
|
277
276
|
支持股票和投资组合
|
278
277
|
RF: 年化利率,不带百分数
|
279
278
|
计算CAPM的期间:默认一年,252个交易日
|
279
|
+
***废弃!!!指标计算有问题
|
280
280
|
"""
|
281
281
|
|
282
282
|
#估计需要的日期提前量
|
@@ -284,19 +284,19 @@ def get_rolling_treynor_alpha(ticker,start,end,rar_name="alpha", \
|
|
284
284
|
if 'weekly' in ret_type_lower:
|
285
285
|
dateahead=7*2+7 #考虑收益率标准差和节假日
|
286
286
|
ret_period='Weekly'
|
287
|
-
period_days=
|
287
|
+
period_days=7
|
288
288
|
elif 'monthly' in ret_type_lower:
|
289
289
|
dateahead=31*2+7 #考虑收益率标准差和节假日
|
290
290
|
ret_period='Monthly'
|
291
|
-
period_days=
|
291
|
+
period_days=30
|
292
292
|
elif 'quarterly' in ret_type_lower:
|
293
293
|
dateahead=(31*3+7)*2 #考虑收益率标准差和节假日
|
294
294
|
ret_period='Quarterly'
|
295
|
-
period_days=
|
295
|
+
period_days=90
|
296
296
|
else:
|
297
297
|
dateahead=(366+7*3)*2 #考虑收益率标准差和节假日
|
298
298
|
ret_period='Annual'
|
299
|
-
period_days=
|
299
|
+
period_days=365
|
300
300
|
|
301
301
|
#计算日历日regression_period对应的交易日数
|
302
302
|
regtrddays=int(252 / 365 * regression_period)
|
@@ -321,8 +321,8 @@ def get_rolling_treynor_alpha(ticker,start,end,rar_name="alpha", \
|
|
321
321
|
source=source,ticker_type=ticker_type)
|
322
322
|
|
323
323
|
#计算股票和指数的滚动收益率
|
324
|
-
varx=ret_type+'_x'
|
325
|
-
vary=ret_type+'_y'
|
324
|
+
varx=ret_type+'_x' #指数收益率
|
325
|
+
vary=ret_type+'_y' #股票收益率
|
326
326
|
|
327
327
|
pretdf=dretdf3.copy()
|
328
328
|
pretdfcols=list(pretdf)
|
@@ -331,6 +331,7 @@ def get_rolling_treynor_alpha(ticker,start,end,rar_name="alpha", \
|
|
331
331
|
|
332
332
|
#对数法计算滚动收益率
|
333
333
|
RF_period=RF/365 * period_days
|
334
|
+
|
334
335
|
if '%' in ret_type_lower:
|
335
336
|
pretdf[lndretx]=pretdf[pretdfcols[0]].apply(lambda x: np.log(1+x/100))
|
336
337
|
pretdf[lndrety]=pretdf[pretdfcols[1]].apply(lambda x: np.log(1+x/100))
|
@@ -338,7 +339,6 @@ def get_rolling_treynor_alpha(ticker,start,end,rar_name="alpha", \
|
|
338
339
|
pretdf[varx]=pretdf[lndretx].rolling(window=period_days).apply(lambda x: (np.exp(sum(x))-1)*100)
|
339
340
|
pretdf[vary]=pretdf[lndrety].rolling(window=period_days).apply(lambda x: (np.exp(sum(x))-1)*100)
|
340
341
|
|
341
|
-
RF_period=(RF/365 * period_days)*100
|
342
342
|
else:
|
343
343
|
pretdf[lndretx]=pretdf[pretdfcols[0]].apply(lambda x: np.log(1+x))
|
344
344
|
pretdf[lndrety]=pretdf[pretdfcols[1]].apply(lambda x: np.log(1+x))
|
@@ -366,16 +366,145 @@ def get_rolling_treynor_alpha(ticker,start,end,rar_name="alpha", \
|
|
366
366
|
|
367
367
|
return pretdf3
|
368
368
|
|
369
|
+
|
370
|
+
def get_rolling_treynor_alpha2(ticker,start,end,rar_name="alpha", \
|
371
|
+
ret_type="Monthly Adj Ret%",RF=0, \
|
372
|
+
regression_period=365,mktidx='auto',source='auto',ticker_type='auto'):
|
373
|
+
"""
|
374
|
+
功能:获取一只股票的特雷诺比率或阿尔法指数,基于给定的滚动收益率类型,在指定期间内
|
375
|
+
支持股票和投资组合
|
376
|
+
RF: 年化利率,不带百分数
|
377
|
+
计算CAPM的期间:默认一年,252个交易日
|
378
|
+
"""
|
379
|
+
|
380
|
+
#估计滚动窗口日期的提前量
|
381
|
+
ret_type_lower=ret_type.lower()
|
382
|
+
if 'weekly' in ret_type_lower:
|
383
|
+
dateahead=7*2+7 #考虑收益率标准差和节假日
|
384
|
+
ret_period='Weekly'
|
385
|
+
period_days=5
|
386
|
+
elif 'monthly' in ret_type_lower:
|
387
|
+
dateahead=31*2+7 #考虑收益率标准差和节假日
|
388
|
+
ret_period='Monthly'
|
389
|
+
period_days=21
|
390
|
+
elif 'quarterly' in ret_type_lower:
|
391
|
+
dateahead=(31*3+7)*2 #考虑收益率标准差和节假日
|
392
|
+
ret_period='Quarterly'
|
393
|
+
period_days=63
|
394
|
+
else:
|
395
|
+
dateahead=(366+7*3)*2 #考虑收益率标准差和节假日
|
396
|
+
ret_period='Annual'
|
397
|
+
period_days=252
|
398
|
+
|
399
|
+
#计算滚动查看需要的日期提前量
|
400
|
+
start1=date_adjust(start,adjust=-dateahead)
|
401
|
+
#计算CAPM需要的日期提前量
|
402
|
+
start2=date_adjust(start1,adjust=-regression_period-7*2)
|
403
|
+
|
404
|
+
#判断复权价
|
405
|
+
ret_type=ret_type.title()
|
406
|
+
if ('Adj' in ret_type):
|
407
|
+
adjust='qfq'
|
408
|
+
else:
|
409
|
+
adjust=''
|
410
|
+
|
411
|
+
#获取股票收益率
|
412
|
+
if '%' in ret_type:
|
413
|
+
if 'Adj' in ret_type:
|
414
|
+
dret_type="Daily Adj Ret%"
|
415
|
+
else:
|
416
|
+
dret_type="Daily Ret%"
|
417
|
+
else:
|
418
|
+
if 'Adj' in ret_type:
|
419
|
+
dret_type="Daily Adj Ret"
|
420
|
+
else:
|
421
|
+
dret_type="Daily Ret"
|
422
|
+
|
423
|
+
#抓取股价
|
424
|
+
pricedfs,found=get_price_1ticker_mixed(ticker=ticker,fromdate=start2,todate=end, \
|
425
|
+
adjust=adjust, \
|
426
|
+
source=source,ticker_type=ticker_type)
|
427
|
+
if found !='Found':
|
428
|
+
print(" #Error(get_rolling_treynor_alpha2): no records found for",ticker)
|
429
|
+
return None
|
430
|
+
|
431
|
+
#计算股票收益率
|
432
|
+
rardf1s=calc_daily_return(pricedfs)
|
433
|
+
rardf2s=calc_rolling_return(rardf1s,period=ret_period)
|
434
|
+
|
435
|
+
#抓取指数
|
436
|
+
if isinstance(ticker,dict):
|
437
|
+
_,mktidx,pftickerlist,_,ticker_type=decompose_portfolio(ticker)
|
438
|
+
if 'auto' in mktidx.lower():
|
439
|
+
mktidx=get_market_index_code(pftickerlist[0])
|
440
|
+
else:
|
441
|
+
if 'auto' in mktidx.lower():
|
442
|
+
mktidx=get_market_index_code(ticker)
|
443
|
+
|
444
|
+
marketdf,found=get_price_1ticker_mixed(ticker=mktidx,fromdate=start2,todate=end, \
|
445
|
+
adjust=adjust, \
|
446
|
+
source=source,ticker_type=ticker_type)
|
447
|
+
if found !='Found':
|
448
|
+
print(" #Error(get_rolling_treynor_alpha2): no records found for",mktidx)
|
449
|
+
return None
|
450
|
+
|
451
|
+
#计算指数收益率
|
452
|
+
rardf1m=calc_daily_return(marketdf)
|
453
|
+
rardf2m=calc_rolling_return(rardf1m,period=ret_period)
|
454
|
+
|
455
|
+
|
456
|
+
#计算日历日regression_period对应的交易日数
|
457
|
+
regtrddays=int(252 / 365 * regression_period)
|
458
|
+
|
459
|
+
#CAPM回归,计算贝塔系数
|
460
|
+
reg_result,dretdf3=regression_capm_df(rardf1m,rardf1s,mktidx=mktidx,adjust=adjust,RF=RF,regtrddays=regtrddays)
|
461
|
+
|
462
|
+
#合成滚动收益率与贝塔系数:_x为指数收益率,_y为股票收益率
|
463
|
+
pretdfms=pd.merge(rardf2m[[ret_type]],rardf2s[[ret_type]],how='inner',left_index=True,right_index=True)
|
464
|
+
pretdf1=pd.merge(pretdfms,reg_result,how='inner',left_index=True,right_index=True)
|
465
|
+
|
466
|
+
if '%' in ret_type:
|
467
|
+
RF=RF*100
|
468
|
+
if ret_period=='Weekly':
|
469
|
+
RF_period=RF/52
|
470
|
+
elif ret_period=='Monthly':
|
471
|
+
RF_period=RF/12
|
472
|
+
elif ret_period=='Quarterly':
|
473
|
+
RF_period=RF/4
|
474
|
+
else:
|
475
|
+
RF_period=RF
|
476
|
+
|
477
|
+
#计算特雷诺比率和阿尔法指标
|
478
|
+
if 'treynor' in rar_name.lower():
|
479
|
+
pretdf1[rar_name]=pretdf1.apply(lambda x: (x[ret_type+'_y']-RF_period)/x['beta'],axis=1)
|
480
|
+
|
481
|
+
elif 'alpha' in rar_name.lower():
|
482
|
+
vary_pred=ret_type+'_pred'
|
483
|
+
pretdf1[vary_pred]=pretdf1.apply(lambda x: RF_period+x['beta']*(x[ret_type+'_x']-RF_period),axis=1)
|
484
|
+
pretdf1[rar_name]=pretdf1.apply(lambda x: x[ret_type+'_y']-x[vary_pred],axis=1)
|
485
|
+
|
486
|
+
if '%' in ret_type:
|
487
|
+
pretdf1[rar_name]=pretdf1[rar_name]/100
|
488
|
+
|
489
|
+
#开始日期富余一段时间,有助于绘图时显示出期望的开始日期
|
490
|
+
startpd=pd.to_datetime(date_adjust(start,adjust=-7))
|
491
|
+
endpd=pd.to_datetime(end)
|
492
|
+
pretdf2=pretdf1[(pretdf1.index >=startpd) & (pretdf1.index <=endpd)]
|
493
|
+
|
494
|
+
pretdf3=pretdf2[[rar_name,'beta']]
|
495
|
+
|
496
|
+
return pretdf3
|
497
|
+
|
369
498
|
#==============================================================================
|
370
499
|
if __name__=='__main__':
|
371
|
-
ticker="
|
500
|
+
ticker="AAPL"
|
372
501
|
ticker={'Market':('US','^SPX','中概教培组合'),'EDU':0.7,'TAL':0.3}
|
373
502
|
|
374
503
|
start="2024-1-1"
|
375
|
-
end="2024-
|
504
|
+
end="2024-6-30"
|
376
505
|
rar_name="alpha"
|
377
|
-
ret_type="Exp Ret%"
|
378
|
-
RF=0.
|
506
|
+
ret_type="Exp Adj Ret%"
|
507
|
+
RF=0.055
|
379
508
|
regression_period=365
|
380
509
|
mktidx='auto'; source='auto'
|
381
510
|
|
@@ -384,13 +513,14 @@ if __name__=='__main__':
|
|
384
513
|
|
385
514
|
|
386
515
|
def get_expanding_treynor_alpha(ticker,start,end,rar_name="alpha", \
|
387
|
-
ret_type="Exp Ret%",RF=0, \
|
516
|
+
ret_type="Exp Adj Ret%",RF=0, \
|
388
517
|
regression_period=365,mktidx='auto',source='auto',ticker_type='auto'):
|
389
518
|
"""
|
390
519
|
功能:获取一只股票的特雷诺比率或阿尔法指数,基于扩展收益率类型,在指定期间内
|
391
520
|
支持股票和投资组合
|
392
521
|
RF: 年化利率,不带百分数
|
393
522
|
计算CAPM的期间:默认一年,252个交易日=365个日历日
|
523
|
+
***废弃!!!收益率计算有问题
|
394
524
|
"""
|
395
525
|
ret_type_lower=ret_type.lower()
|
396
526
|
#计算日历日regression_period对应的交易日数
|
@@ -479,6 +609,109 @@ def get_expanding_treynor_alpha(ticker,start,end,rar_name="alpha", \
|
|
479
609
|
return pretdf3
|
480
610
|
|
481
611
|
|
612
|
+
def get_expanding_treynor_alpha2(ticker,start,end,rar_name="alpha", \
|
613
|
+
ret_type="Exp Adj Ret%",RF=0, \
|
614
|
+
regression_period=365,mktidx='auto',source='auto',ticker_type='auto'):
|
615
|
+
"""
|
616
|
+
功能:获取一只股票的特雷诺比率或阿尔法指数,基于扩展收益率类型,在指定期间内
|
617
|
+
支持股票和投资组合
|
618
|
+
RF: 年化利率,不带百分数
|
619
|
+
计算CAPM的期间:默认一年,252个交易日=365个日历日
|
620
|
+
"""
|
621
|
+
ret_type_lower=ret_type.lower()
|
622
|
+
|
623
|
+
#计算滚动查看需要的日期提前量:无滚动
|
624
|
+
start1=date_adjust(start,adjust=0)
|
625
|
+
#计算CAPM需要的日期提前量
|
626
|
+
start2=date_adjust(start1,adjust=-regression_period-7*2)
|
627
|
+
|
628
|
+
#判断复权价
|
629
|
+
ret_type=ret_type.title()
|
630
|
+
if ('Adj' in ret_type):
|
631
|
+
adjust='qfq'
|
632
|
+
else:
|
633
|
+
adjust=''
|
634
|
+
|
635
|
+
#抓取股价
|
636
|
+
pricedfs,found=get_price_1ticker_mixed(ticker=ticker,fromdate=start2,todate=end, \
|
637
|
+
adjust=adjust, \
|
638
|
+
source=source,ticker_type=ticker_type)
|
639
|
+
if found !='Found':
|
640
|
+
print(" #Error(get_expanding_treynor_alpha2): no records found for",ticker)
|
641
|
+
return None
|
642
|
+
|
643
|
+
#计算股票扩展收益率
|
644
|
+
rardf1s=calc_daily_return(pricedfs)
|
645
|
+
rardf2s=calc_expanding_return(pricedfs,start)
|
646
|
+
|
647
|
+
if '%' in ret_type:
|
648
|
+
RF=RF*100
|
649
|
+
RF_daily=RF/365
|
650
|
+
|
651
|
+
#增加距离开始日期的天数
|
652
|
+
date0=pd.to_datetime(rardf2s.index[0])
|
653
|
+
if 'date' not in list(rardf2s):
|
654
|
+
if 'Date' in list(rardf2s):
|
655
|
+
rardf2s['date']=rardf2s['Date']
|
656
|
+
else:
|
657
|
+
rardf2s['date']=rardf2s.index
|
658
|
+
|
659
|
+
rardf2s['days']=rardf2s['date'].apply(lambda x: days_between_dates(date0,pd.to_datetime(x)))
|
660
|
+
rardf2s[ret_type+'_RP']=rardf2s.apply(lambda x: x[ret_type] - RF_daily*x['days'],axis=1)
|
661
|
+
|
662
|
+
#抓取指数
|
663
|
+
if isinstance(ticker,dict):
|
664
|
+
_,mktidx,pftickerlist,_,ticker_type=decompose_portfolio(ticker)
|
665
|
+
if 'auto' in mktidx.lower():
|
666
|
+
mktidx=get_market_index_code(pftickerlist[0])
|
667
|
+
else:
|
668
|
+
if 'auto' in mktidx.lower():
|
669
|
+
mktidx=get_market_index_code(ticker)
|
670
|
+
|
671
|
+
marketdf,found=get_price_1ticker_mixed(ticker=mktidx,fromdate=start2,todate=end, \
|
672
|
+
adjust=adjust, \
|
673
|
+
source=source,ticker_type=ticker_type)
|
674
|
+
if found !='Found':
|
675
|
+
print(" #Error(get_expanding_treynor_alpha2): no records found for",mktidx)
|
676
|
+
return None
|
677
|
+
|
678
|
+
#计算指数扩展收益率
|
679
|
+
rardf1m=calc_daily_return(marketdf)
|
680
|
+
rardf2m=calc_expanding_return(marketdf,start)
|
681
|
+
#增加距离开始日期的天数
|
682
|
+
date0=pd.to_datetime(rardf2m.index[0])
|
683
|
+
if 'date' not in list(rardf2m):
|
684
|
+
if 'Date' in list(rardf2m):
|
685
|
+
rardf2m['date']=rardf2m['Date']
|
686
|
+
else:
|
687
|
+
rardf2m['date']=rardf2m.index
|
688
|
+
|
689
|
+
rardf2m['days']=rardf2m['date'].apply(lambda x: days_between_dates(date0,pd.to_datetime(x)))
|
690
|
+
rardf2m[ret_type+'_RP']=rardf2m.apply(lambda x: x[ret_type] - RF_daily*x['days'],axis=1)
|
691
|
+
|
692
|
+
#计算日历日regression_period对应的交易日数
|
693
|
+
regtrddays=int(252 / 365 * regression_period)
|
694
|
+
#CAPM回归,计算贝塔系数
|
695
|
+
reg_result,dretdf3=regression_capm_df(rardf1m,rardf1s,mktidx=mktidx,adjust=adjust,RF=RF,regtrddays=regtrddays)
|
696
|
+
|
697
|
+
#合成扩展收益率与贝塔系数:_x为指数收益率,_y为股票收益率,_RP为股票风险溢价
|
698
|
+
pretdfms=pd.merge(rardf2m[[ret_type,ret_type+'_RP','days']],rardf2s[[ret_type,ret_type+'_RP']],how='inner',left_index=True,right_index=True)
|
699
|
+
pretdf1=pd.merge(pretdfms,reg_result,how='inner',left_index=True,right_index=True)
|
700
|
+
|
701
|
+
#计算特雷诺比率和阿尔法指标
|
702
|
+
if 'treynor' in rar_name.lower():
|
703
|
+
pretdf1[rar_name]=pretdf1.apply(lambda x: x[ret_type+'_RP_y']/x['beta'],axis=1)
|
704
|
+
elif 'alpha' in rar_name.lower():
|
705
|
+
vary_pred=ret_type+'_y_pred'
|
706
|
+
pretdf1[vary_pred]=pretdf1.apply(lambda x: RF_daily*x['days']+x['beta']*x[ret_type+'_RP_x'],axis=1)
|
707
|
+
pretdf1[rar_name]=pretdf1.apply(lambda x: x[ret_type+'_y']-x[vary_pred],axis=1)
|
708
|
+
|
709
|
+
if '%' in ret_type:
|
710
|
+
pretdf1[rar_name]=pretdf1[rar_name]/100
|
711
|
+
|
712
|
+
pretdf3=pretdf1[[rar_name,'beta']]
|
713
|
+
|
714
|
+
return pretdf3
|
482
715
|
#==============================================================================
|
483
716
|
if __name__=='__main__':
|
484
717
|
ticker="600519.SS"
|
@@ -524,7 +757,7 @@ def get_rar(ticker,start,end,rar_name="sharpe",ret_type="Monthly Ret%", \
|
|
524
757
|
ret_type=ret_type_title,RF=RF, \
|
525
758
|
source=source,ticker_type=ticker_type)
|
526
759
|
elif ('alpha' in rar_name_lower) or ('treynor' in rar_name_lower):
|
527
|
-
rardf=
|
760
|
+
rardf=get_rolling_treynor_alpha2(ticker=ticker,start=start,end=end, \
|
528
761
|
rar_name=rar_name_lower, \
|
529
762
|
ret_type=ret_type_title,RF=RF, \
|
530
763
|
regression_period=regression_period, \
|
@@ -537,7 +770,7 @@ def get_rar(ticker,start,end,rar_name="sharpe",ret_type="Monthly Ret%", \
|
|
537
770
|
ret_type=ret_type_title,RF=RF, \
|
538
771
|
source=source,ticker_type=ticker_type)
|
539
772
|
elif ('alpha' in rar_name_lower) or ('treynor' in rar_name_lower):
|
540
|
-
rardf=
|
773
|
+
rardf=get_expanding_treynor_alpha2(ticker=ticker,start=start,end=end, \
|
541
774
|
rar_name=rar_name_lower, \
|
542
775
|
ret_type=ret_type_title,RF=RF, \
|
543
776
|
regression_period=regression_period, \
|
@@ -633,15 +866,21 @@ def compare_1ticker_mrar(ticker,start,end,rar=['sharpe','sortino','treynor','alp
|
|
633
866
|
|
634
867
|
df1.rename(columns={c:ectranslate(c)},inplace=True)
|
635
868
|
|
636
|
-
footnote1="注:基于"+ectranslate(ret_type)+"
|
869
|
+
footnote1=text_lang("注:基于","Note: RaR based on ")+ectranslate(ret_type)+text_lang("。",". ")
|
637
870
|
if RF !=0:
|
638
|
-
footnote2="年化无风险利率为"+str(round(RF*100,4))+text_lang('%。','%')
|
871
|
+
footnote2=text_lang("年化无风险利率为","RF = ")+str(round(RF*100,4))+text_lang('%。','% pa')
|
639
872
|
else:
|
640
|
-
footnote2="不考虑年化无风险利率时。"
|
873
|
+
footnote2=text_lang("不考虑年化无风险利率时。","RF = 0 pa")
|
641
874
|
|
642
875
|
footnote3=''
|
643
876
|
if 'treynor' in rar or 'alpha' in rar:
|
644
|
-
|
877
|
+
if mktidx != 'auto':
|
878
|
+
mktidx_text=ticker_name(mktidx)
|
879
|
+
footnote3x=text_lang(",市场指数基于",", using ")+mktidx_text
|
880
|
+
footnote3=text_lang("\nCAPM回归期间","\nCAPM rolling ")+str(regression_period)+text_lang("个自然日"," days, ")+footnote3x
|
881
|
+
else:
|
882
|
+
footnote3=text_lang("CAPM回归期间",", CAPM rolling ")+str(regression_period)+text_lang("个自然日"," days")
|
883
|
+
|
645
884
|
|
646
885
|
import datetime; todaydt = datetime.date.today()
|
647
886
|
footnote4=text_lang("数据来源: 综合新浪/Stooq/Yahoo,","Data source: Sina/Stooq/Yahoo, ")+str(todaydt)
|
@@ -661,7 +900,7 @@ def compare_1ticker_mrar(ticker,start,end,rar=['sharpe','sortino','treynor','alp
|
|
661
900
|
axhline_value=axhline_value,axhline_label=axhline_label, \
|
662
901
|
title_txt=title_txt,data_label=False, \
|
663
902
|
annotate=annotate,annotate_value=annotate, \
|
664
|
-
|
903
|
+
mark_top=mark_top,mark_bottom=mark_bottom,mark_end=mark_end, \
|
665
904
|
facecolor=facecolor,loc=loc1)
|
666
905
|
|
667
906
|
#制表
|
@@ -679,10 +918,10 @@ def compare_1ticker_mrar(ticker,start,end,rar=['sharpe','sortino','treynor','alp
|
|
679
918
|
sortby_txt=text_lang('按推荐标记+短期均值走势降序排列',"by Recommend + Recent Trend, Descending")
|
680
919
|
|
681
920
|
#title_txt='***** 风险调整收益评估:'+tname+','+sortby_txt+' *****'
|
682
|
-
title_txt=text_lang('
|
921
|
+
title_txt=text_lang('风险调整收益评估:',"RaR Evaluation: ")+ectranslate(rar)+text_lang(',',', ')+sortby_txt
|
683
922
|
|
684
|
-
footnote6=text_lang('期间为',"Period: ")+str(start)+text_lang('至'," to ")+str(end)+text_lang(";近期指近","
|
685
|
-
footnote7=text_lang("近期优先趋势和星号为风险调整收益指标加趋势等多项因素综合研判,最多五颗星","Recommend max 5 stars. RWA = Recent Weighted Average")
|
923
|
+
footnote6=text_lang('期间为',"Period: ")+str(start)+text_lang('至'," to ")+str(end)+text_lang(";近期指近","\nRecent trend: ")+str(trailing)+text_lang("个交易日。趋势变化率阈值:", " days. Trend threshhold ")+str(trend_threshold)
|
924
|
+
footnote7=text_lang("近期优先趋势和星号为风险调整收益指标加趋势等多项因素综合研判,最多五颗星","Recommend max 5 stars. RWA = Recent-priority Weighted Average")
|
686
925
|
footnotey=footnote6+footnote7+'\n'+footnotex
|
687
926
|
|
688
927
|
recommenddf=descriptive_statistics2(df1,title_txt,footnotey,decimals=4, \
|
@@ -801,12 +1040,15 @@ def compare_mticker_1rar(ticker,start,end,rar='sharpe', \
|
|
801
1040
|
#rar_text=rar_text.title()
|
802
1041
|
rar_text="Jensen Alpha"
|
803
1042
|
|
804
|
-
footnote1=text_lang("注:","")+rar_text.capitalize()+text_lang("基于","
|
1043
|
+
footnote1=text_lang("注:","Note: ")+rar_text.capitalize()+text_lang("基于"," based on ")+ectranslate(ret_type)+text_lang("。",", ")
|
1044
|
+
"""
|
805
1045
|
if RF !=0:
|
806
|
-
footnote2=text_lang("年化无风险利率","
|
1046
|
+
footnote2=text_lang("年化无风险利率","RF = ")+str(round(RF*100,4))+text_lang('%。','% pa')
|
807
1047
|
else:
|
808
|
-
footnote2=text_lang("假设年化无风险利率为零。","assuming
|
809
|
-
|
1048
|
+
footnote2=text_lang("假设年化无风险利率为零。","assuming RF = 0 pa.")
|
1049
|
+
"""
|
1050
|
+
footnote2=text_lang("年化无风险利率","RF = ")+str(round(RF*100,4))+text_lang('%。','% pa')
|
1051
|
+
|
810
1052
|
footnote3=''
|
811
1053
|
if rar.lower() in ['treynor','alpha']:
|
812
1054
|
mktidx_text=''
|
@@ -814,10 +1056,10 @@ def compare_mticker_1rar(ticker,start,end,rar='sharpe', \
|
|
814
1056
|
mktidx_text=ticker_name(mktidx)
|
815
1057
|
|
816
1058
|
if mktidx != 'auto':
|
817
|
-
footnote3=text_lang("CAPM回归期间","\nCAPM
|
1059
|
+
footnote3=text_lang("CAPM回归期间","\nCAPM rolling ")+str(regression_period)+text_lang("个自然日,"," days, ")+ \
|
818
1060
|
text_lang("市场指数基于","using ")+mktidx_text
|
819
1061
|
else:
|
820
|
-
footnote3=text_lang("CAPM回归期间","\nCAPM
|
1062
|
+
footnote3=text_lang("CAPM回归期间","\nCAPM rolling ")+str(regression_period)+text_lang("个自然日"," days")
|
821
1063
|
|
822
1064
|
import datetime; todaydt = datetime.date.today()
|
823
1065
|
footnote4=text_lang("数据来源: 综合新浪/Stooq/Yahoo,","Data source: Sina/Stooq/Yahoo, ")+str(todaydt)
|
@@ -854,10 +1096,10 @@ def compare_mticker_1rar(ticker,start,end,rar='sharpe', \
|
|
854
1096
|
sortby_txt=text_lang('按推荐标记+短期均值走势降序排列',"by Recommend + Recent Trend, Descending")
|
855
1097
|
|
856
1098
|
#title_txt='***** 风险调整收益评估:基于'+ectranslate(rar)+','+sortby_txt+' *****'
|
857
|
-
title_txt=text_lang('
|
1099
|
+
title_txt=text_lang('风险调整收益评估:',"RaR Evaluation: ")+rar_text+text_lang(',',', ')+sortby_txt
|
858
1100
|
|
859
|
-
footnote6=text_lang('期间为',"Period: ")+str(start)+text_lang('至'," to ")+str(end)+text_lang(";近期指近","
|
860
|
-
footnote7=text_lang("近期优先趋势和星号为风险调整收益指标加趋势等多项因素综合研判,最多五颗星","Recommend max 5 stars. RWA = Recent Weighted Average")
|
1101
|
+
footnote6=text_lang('期间为',"Period: ")+str(start)+text_lang('至'," to ")+str(end)+text_lang(";近期指近","\nRecent trend: ")+str(trailing)+text_lang("个交易日。趋势变化率阈值:", " trading days. Trend change threshhold: ")+str(trend_threshhold)
|
1102
|
+
footnote7=text_lang("近期优先趋势和星号为风险调整收益指标加趋势等多项因素综合研判,最多五颗星","Recommend max 5 stars. RWA = Recent-priority Weighted Average")
|
861
1103
|
footnotey=footnote6+'\n'+footnote7+'\n'+footnotex
|
862
1104
|
|
863
1105
|
#不能简单删除含有Nan的行,否则导致清空df1,应该进行填充
|
@@ -1037,18 +1279,21 @@ def compare_mticker_mrar(ticker,start,end,rar=['sharpe','alpha','sortino','treyn
|
|
1037
1279
|
"""
|
1038
1280
|
|
1039
1281
|
#脚注
|
1040
|
-
footnote1=text_lang("风险调整收益基于","
|
1282
|
+
footnote1=text_lang("风险调整收益基于","RaR based on ")+ectranslate(ret_type)+text_lang(",",', ')
|
1283
|
+
"""
|
1041
1284
|
if RF !=0:
|
1042
|
-
footnote2=text_lang("年化无风险利率","
|
1285
|
+
footnote2=text_lang("年化无风险利率","RF = ")+str(round(RF*100,4))+text_lang('%','% pa')
|
1043
1286
|
else:
|
1044
|
-
footnote2=text_lang("假设年化无风险利率为零","assuming
|
1045
|
-
|
1287
|
+
footnote2=text_lang("假设年化无风险利率为零","assuming RF = 0 pa")
|
1288
|
+
"""
|
1289
|
+
footnote2=text_lang("年化无风险利率","RF = ")+str(round(RF*100,4))+text_lang('%','% pa')
|
1290
|
+
|
1046
1291
|
footnote3=''
|
1047
1292
|
if 'treynor' in rar or 'alpha' in rar:
|
1048
1293
|
if mktidx=='auto':
|
1049
1294
|
mktidx=get_market_index_code(ticker[0] if isinstance(ticker,list) else ticker)
|
1050
1295
|
mktidx_name=ticker_name(mktidx)
|
1051
|
-
footnote3=text_lang("CAPM基于","CAPM
|
1296
|
+
footnote3=text_lang("CAPM基于","CAPM using ")+mktidx_name+text_lang(",回归期间",", rolling ")+str(regression_period)+text_lang("个自然日"," days")
|
1052
1297
|
|
1053
1298
|
import datetime; todaydt = datetime.date.today()
|
1054
1299
|
footnote4=text_lang("数据来源: 综合新浪/Stooq/Yahoo,","Data source: Sina/Stooq/Yahoo, ")+str(todaydt)+text_lang("统计",'')
|
@@ -1060,7 +1305,7 @@ def compare_mticker_mrar(ticker,start,end,rar=['sharpe','alpha','sortino','treyn
|
|
1060
1305
|
#print("\n"+footnotex)
|
1061
1306
|
#print(footnotex)
|
1062
1307
|
if check_language()=="English":
|
1063
|
-
df1.rename(columns={"比较对象":"Securities","sharpe":"Sharpe Ratio","sortino":"Sortino Ratio","alpha":"Jensen Alpha","treynor":"Treynor Ratio","综合推荐":"Overall
|
1308
|
+
df1.rename(columns={"比较对象":"Securities","sharpe":"Sharpe Ratio","sortino":"Sortino Ratio","alpha":"Jensen Alpha","treynor":"Treynor Ratio","综合推荐":"Overall Recommend"},inplace=True)
|
1064
1309
|
|
1065
1310
|
df_display_CSS(df1,titletxt=titletxt,footnote=footnotex,decimals=4, \
|
1066
1311
|
first_col_align='left',second_col_align='center', \
|
@@ -1154,15 +1399,18 @@ def compare_1ticker_1rar_mret(ticker,start,end,rar='sharpe', \
|
|
1154
1399
|
#df1.rename(columns={c:"基于"+ectranslate(c)},inplace=True)
|
1155
1400
|
|
1156
1401
|
#共同脚注
|
1157
|
-
footnote1="注:"
|
1402
|
+
footnote1=text_lang("注:","Note: ")
|
1403
|
+
"""
|
1158
1404
|
if RF !=0:
|
1159
|
-
footnote2="年化无风险利率为"+str(round(RF*100,4))+text_lang('%。','%')
|
1405
|
+
footnote2=text_lang("年化无风险利率为","RF = ")+str(round(RF*100,4))+text_lang('%。','% pa. ')
|
1160
1406
|
else:
|
1161
|
-
footnote2=text_lang("假设年化无风险利率为零。","
|
1162
|
-
|
1407
|
+
footnote2=text_lang("假设年化无风险利率为零。","Assuming RF = 0 pa")
|
1408
|
+
"""
|
1409
|
+
footnote2=text_lang("年化无风险利率为","RF = ")+str(round(RF*100,4))+text_lang('%。','% pa. ')
|
1410
|
+
|
1163
1411
|
footnote3=''
|
1164
1412
|
if rar.lower() in ['treynor','alpha']:
|
1165
|
-
footnote3="
|
1413
|
+
footnote3=text_lang("CAPM回归期间","CAPM rolling ")+str(regression_period)+text_lang("个自然日"," days")
|
1166
1414
|
|
1167
1415
|
import datetime; todaydt = datetime.date.today()
|
1168
1416
|
footnote4=text_lang("数据来源: 综合新浪/Stooq/Yahoo,","Data source: Sina/Stooq/Yahoo, ")+str(todaydt)
|
@@ -1199,10 +1447,10 @@ def compare_1ticker_1rar_mret(ticker,start,end,rar='sharpe', \
|
|
1199
1447
|
sortby_txt=text_lang('按推荐标记+短期均值走势降序排列',"by Recommend + Recent Trend, Descending")
|
1200
1448
|
|
1201
1449
|
#title_txt='***** 风险调整收益评估:'+'基于'+ectranslate(rar)+','+ticker_name(ticker,ticker_type)+','+sortby_txt+' *****'
|
1202
|
-
title_txt=text_lang('
|
1450
|
+
title_txt=text_lang('风险调整收益评估:',"RaR Evaluation: ")+ectranslate(rar)+text_lang(',',', ')+sortby_txt
|
1203
1451
|
|
1204
|
-
footnote6=text_lang('期间为',"Period: ")+str(start)+text_lang('至'," to ")+str(end)+text_lang(";近期指近","
|
1205
|
-
footnote7=text_lang("近期优先趋势和星号为风险调整收益指标加趋势等多项因素综合研判,最多五颗星","Recommend max 5 stars. RWA = Recent Weighted Average")
|
1452
|
+
footnote6=text_lang('期间为',"Period: ")+str(start)+text_lang('至'," to ")+str(end)+text_lang(";近期指近","\nRecent trend: ")+str(trailing)+text_lang("个交易日。趋势变化率阈值:", " days. Trend threshhold ")+str(trend_threshhold)
|
1453
|
+
footnote7=text_lang("近期优先趋势和星号为风险调整收益指标加趋势等多项因素综合研判,最多五颗星","Recommend max 5 stars. RWA = Recent-priority Weighted Average")
|
1206
1454
|
footnotey=footnote6+footnote7+'\n'+footnotex
|
1207
1455
|
|
1208
1456
|
#删除含有Nan的行
|
@@ -1301,7 +1549,7 @@ def compare_1ticker_1rar_1ret_mRF(ticker,start,end,rar='sharpe', \
|
|
1301
1549
|
#df1.rename(columns={c:"基于无风险利率"+c},inplace=True)
|
1302
1550
|
|
1303
1551
|
#共同脚注
|
1304
|
-
footnote1=text_lang("注:","")+ectranslate(rar)+text_lang("基于","
|
1552
|
+
footnote1=text_lang("注:","Note: ")+ectranslate(rar)+text_lang("基于"," based on ")+ectranslate(ret_type)+text_lang('。','')
|
1305
1553
|
footnote2=""
|
1306
1554
|
|
1307
1555
|
footnote3=""
|
@@ -1343,10 +1591,10 @@ def compare_1ticker_1rar_1ret_mRF(ticker,start,end,rar='sharpe', \
|
|
1343
1591
|
sortby_txt=text_lang('按推荐标记+短期均值走势降序排列',"by Recommend + Recent Trend, Descending")
|
1344
1592
|
|
1345
1593
|
#title_txt='***** 风险调整收益评估:'+'基于'+ectranslate(rar)+','+ticker_name(ticker,ticker_type)+','+sortby_txt+' *****'
|
1346
|
-
title_txt=text_lang('
|
1594
|
+
title_txt=text_lang('风险调整收益评估:',"RaR Evaluation: ")+ectranslate(rar)+text_lang(',',', ')+sortby_txt
|
1347
1595
|
|
1348
|
-
footnote6=text_lang('期间为',"Period: ")+str(start)+text_lang('至'," to ")+str(end)+text_lang(";近期指近","
|
1349
|
-
footnote7=text_lang("近期优先趋势和星号为风险调整收益指标加趋势等多项因素综合研判,最多五颗星","Recommend max 5 stars. RWA = Recent Weighted Average")
|
1596
|
+
footnote6=text_lang('期间为',"Period: ")+str(start)+text_lang('至'," to ")+str(end)+text_lang(";近期指近","\nRecent trend: ")+str(trailing)+text_lang("个交易日。趋势变化率阈值:", " days. Trend threshhold ")+str(trend_threshhold)
|
1597
|
+
footnote7=text_lang("近期优先趋势和星号为风险调整收益指标加趋势等多项因素综合研判,最多五颗星","Recommend max 5 stars. RWA = Recent-priority Weighted Average")
|
1350
1598
|
footnotey=footnote6+footnote7+'\n'+footnotex
|
1351
1599
|
|
1352
1600
|
#删除含有Nan的行
|
siat/stock.py
CHANGED
@@ -920,30 +920,31 @@ def security_mindicators(ticker,measures,
|
|
920
920
|
|
921
921
|
df['ticker']=ticker
|
922
922
|
|
923
|
-
|
924
|
-
|
925
|
-
|
926
|
-
|
927
|
-
|
928
|
-
|
929
|
-
|
930
|
-
|
931
|
-
|
932
|
-
|
933
|
-
|
934
|
-
|
935
|
-
|
936
|
-
|
937
|
-
|
923
|
+
if graph:
|
924
|
+
# 翻译指标名称
|
925
|
+
for c in list(df):
|
926
|
+
df.rename(columns={c:ectranslate(c)},inplace=True)
|
927
|
+
|
928
|
+
y_label=text_lang('证券指标',"Indicator")
|
929
|
+
import datetime; todaydt = datetime.date.today()
|
930
|
+
x_label=text_lang("数据来源:综合新浪/东方财富/stooq/yahoo,","Data source: Sina/EM/Stooq/Yahoo, ")+str(todaydt)
|
931
|
+
|
932
|
+
axhline_value=0
|
933
|
+
axhline_label=''
|
934
|
+
for c in measures:
|
935
|
+
if 'Ret%' in c:
|
936
|
+
axhline_value=0
|
937
|
+
axhline_label='零线'
|
938
|
+
break
|
939
|
+
|
940
|
+
titletxt=text_lang("证券趋势分析:","Security Trend: ")+ticker_name(ticker,ticker_type=ticker_type)
|
938
941
|
|
939
|
-
|
940
|
-
|
941
|
-
|
942
|
-
|
943
|
-
|
944
|
-
|
945
|
-
mark_top=mark_top,mark_bottom=mark_bottom,mark_end=mark_end,facecolor=facecolor, \
|
946
|
-
band_area=band_area,loc=loc)
|
942
|
+
draw_lines2(df,y_label,x_label,axhline_value,axhline_label,titletxt, \
|
943
|
+
data_label=False,resample_freq='6H',smooth=smooth, \
|
944
|
+
date_range=date_range,date_freq=date_freq,date_fmt='%Y-%m-%d', \
|
945
|
+
annotate=annotate,annotate_value=annotate_value, \
|
946
|
+
mark_top=mark_top,mark_bottom=mark_bottom,mark_end=mark_end,facecolor=facecolor, \
|
947
|
+
band_area=band_area,loc=loc)
|
947
948
|
|
948
949
|
return df
|
949
950
|
|
siat/stock_info.pickle
CHANGED
Binary file
|
siat/translate.py
CHANGED
@@ -3108,11 +3108,22 @@ def update_all_names2files():
|
|
3108
3108
|
功能:更新股票(中港美)、基金(沪深)和债券(沪深)名称至文件中(S:/siat)
|
3109
3109
|
"""
|
3110
3110
|
print(" Updating stock names in China, China HK and US markets ... ...")
|
3111
|
-
|
3112
|
-
|
3113
|
-
|
3114
|
-
|
3115
|
-
|
3111
|
+
try:
|
3112
|
+
df1=update_stock_names()
|
3113
|
+
except:
|
3114
|
+
pass
|
3115
|
+
|
3116
|
+
print("\n Updating exchange fund names in China markets ... ...")
|
3117
|
+
try:
|
3118
|
+
df2=update_fund_names_china()
|
3119
|
+
except:
|
3120
|
+
pass
|
3121
|
+
|
3122
|
+
print("\n Updating exchange bond names in China markets ... ...")
|
3123
|
+
try:
|
3124
|
+
df3=update_exchange_bond_name_china()
|
3125
|
+
except:
|
3126
|
+
pass
|
3116
3127
|
|
3117
3128
|
return
|
3118
3129
|
|
@@ -3292,6 +3303,7 @@ def ticker1_name(ticker,ticker_type='auto'):
|
|
3292
3303
|
ttlist=['bond','stock','fund']
|
3293
3304
|
|
3294
3305
|
#循环查询,查到则跳出
|
3306
|
+
lang=check_language()
|
3295
3307
|
tname=symbol
|
3296
3308
|
for tt in ttlist:
|
3297
3309
|
#查找证券名称文件:优先股票
|
@@ -3302,7 +3314,10 @@ def ticker1_name(ticker,ticker_type='auto'):
|
|
3302
3314
|
if '.HK' in symbol and len(symbol)==8: symbol=symbol[1:]
|
3303
3315
|
|
3304
3316
|
try:
|
3305
|
-
|
3317
|
+
if lang == "Chinese":
|
3318
|
+
tname=df1[df1['SYMBOL']==symbol]['CNAME'].values[0]
|
3319
|
+
else:
|
3320
|
+
tname=df1[df1['SYMBOL']==symbol]['ENAME'].values[0]
|
3306
3321
|
except: pass
|
3307
3322
|
if tname != symbol: break
|
3308
3323
|
|
@@ -15,10 +15,10 @@ siat/bond_china.py,sha256=eYv-nMoWSS5fZ4VxnuJ29QFY9GUS6meGiIc0Xjm1fQI,3038
|
|
15
15
|
siat/bond_test.py,sha256=yUOFw7ddGU-kb1rJdnsjkJWziDNgUR7OLDA7F7Ub91A,5246
|
16
16
|
siat/bond_zh_sina.py,sha256=26BohGcS120utwqg9dJvdGm5OkuNpNu5bco80uOuQpU,4423
|
17
17
|
siat/capm_beta.py,sha256=cxXdRVBQBllhbfz1LeTJAIWvyRYhW54nhtNUXv4HwS0,29063
|
18
|
-
siat/capm_beta2.py,sha256=
|
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=Uc_BLjlp6njmGFBMSaM45fcHKgk9kjnKacFcFYljrmE,151620
|
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
|
@@ -52,7 +52,7 @@ siat/financials_china_test2_fin_indicator.py,sha256=WkNlVW_0hGegdw1rzg4BP_dKR-sm
|
|
52
52
|
siat/financials_test.py,sha256=HJ3CPo_Xckz2wXi3AEP6ZNWCF1Duc1pLi0Y10USiImc,23829
|
53
53
|
siat/fred_test.py,sha256=KF50ssSbsfpa_kT6iuomD0vG4eXztAcOasZxg1OGX5w,1201
|
54
54
|
siat/fund.py,sha256=wMDORsCBV8ZXfgwbtq-0bu3qqWY66dHnbqgllW0gWCo,24637
|
55
|
-
siat/fund_china.pickle,sha256=
|
55
|
+
siat/fund_china.pickle,sha256=x_nPPdwy7wzIhtZQOplgDyTSyyUdXy9lbNxWysq7N6k,2437771
|
56
56
|
siat/fund_china.py,sha256=rPGnYSPkbZUqtBoJnxLZLIQ8MjD8vD3TovCMfletBP4,111839
|
57
57
|
siat/fund_china_test.py,sha256=-Bh6m0J0GPpIbYXx-H2vpzJoNFI6pE2C2jVPa8DazgE,6649
|
58
58
|
siat/fund_test.py,sha256=V4ADb8Gsp8gyeFTwcgRsJBpnUih_O-Q2V1ILc5oKjK8,1116
|
@@ -67,7 +67,7 @@ siat/holding_risk_test.py,sha256=FRlw_9wFG98BYcg_cSj95HX5WZ1TvkGaOUdXD7-V86s,474
|
|
67
67
|
siat/local_debug_test.py,sha256=CDAOffW1Rvs-TcNN5giWVvHMlch1w4dp-w5SIV9jXL0,3936
|
68
68
|
siat/luchy_draw.py,sha256=8Ue-NKnvSVqINPY1eXat0NJat5MR-gex_K62aOYFdmA,20486
|
69
69
|
siat/market_china.py,sha256=EOO-RvdnzJThTrgNHWW3TlWhx4k4rfdjbooOnQsYdQU,50299
|
70
|
-
siat/markowitz.py,sha256=
|
70
|
+
siat/markowitz.py,sha256=DsfS6vG9TAfdJP4GgN-CCArujPi84XjD23CWbxaA2o4,97627
|
71
71
|
siat/markowitz2-20240620.py,sha256=irZAPnjaatFsKQmFRMENP-cO6bEUl2narYtkU5NKTWI,108019
|
72
72
|
siat/markowitz2.py,sha256=oStv4V74OiqBk-rnBPo6QJTUSNe1FCyT1Yl6-Fx_mHc,113934
|
73
73
|
siat/markowitz_ccb_test.py,sha256=xBkkoaNHdq9KSUrNuHGgKTdNYUvgi84kNYcf719eoyE,1593
|
@@ -88,7 +88,7 @@ siat/option_sina_api_test.py,sha256=dn-k_wrQnAaNKHoROvWJEc7lqlU0bwiV2Aa4usWAFGM,
|
|
88
88
|
siat/proxy_test.py,sha256=erQJrmGs2X46z8Gb1h-7GYQ0rTUcaR8dxHExWoBz2eM,2610
|
89
89
|
siat/quandl_test.py,sha256=EcPoXnLuqzPl5dKyVEZi3j3PJZFpsnU_iNPhLWC9p-A,1552
|
90
90
|
siat/risk_adjusted_return.py,sha256=oRUOagpQlGB56R1xIHZoYwAi42RqcZl0R-JCVBCKVe0,55086
|
91
|
-
siat/risk_adjusted_return2.py,sha256=
|
91
|
+
siat/risk_adjusted_return2.py,sha256=Gdbgn_mIeNnPnUL89pss6c9gDtrNQqWCx7HBlQdpEQo,80800
|
92
92
|
siat/risk_adjusted_return_test.py,sha256=m_VHL5AtT74cJv5i7taTeTfnkX48y0AFJk5phawyYWg,3416
|
93
93
|
siat/risk_evaluation.py,sha256=I6B3gty-t--AkDCO0tKF-291YfpnF-IkXcFjqNKCt9I,76286
|
94
94
|
siat/risk_evaluation_test.py,sha256=YEXM96gKzTfwN4U61AS4Rr1tV7KgUvn4rRC6f3iMw9s,3731
|
@@ -105,12 +105,12 @@ siat/security_trend2-20240620.py,sha256=QVnEcb7AyVbO77jVqfFsJffGXrX8pgJ9xCfoAKmW
|
|
105
105
|
siat/security_trend2.py,sha256=lUMab8HilXIUPo_z9ZkztMiZ5kf3jAbbCwPPkYbQ1TI,25288
|
106
106
|
siat/setup.py,sha256=up65rQGLmTBkhtaMLowjoQXYmIsnycnm4g1SYmeQS6o,1335
|
107
107
|
siat/shenwan index history test.py,sha256=JCVAzOSEldHalhSFa3pqD8JI_8_djPMQOxpkuYU-Esg,1418
|
108
|
-
siat/stock.py,sha256=
|
108
|
+
siat/stock.py,sha256=cKtez5i9G143rSw7rRll6rRIFTWnQ3RaHF7CVnu7qk8,152571
|
109
109
|
siat/stock_advice_linear.py,sha256=-twT7IGP-NEplkL1WPSACcNJjggRB2j4mlAQCkzOAuo,31655
|
110
110
|
siat/stock_base.py,sha256=uISvbRyOGy8p9QREA96CVydgflBkn5L3OXOGKl8oanc,1312
|
111
111
|
siat/stock_china.py,sha256=zyUyghIrkkkYWlHRRP7Hoblxzfp-jrck60pTJpwMahg,91553
|
112
112
|
siat/stock_china_test.py,sha256=eO4HWsSvc6qezl0LndjtL24lViEyrBjH_sx2c2Y2Q2M,1294
|
113
|
-
siat/stock_info.pickle,sha256=
|
113
|
+
siat/stock_info.pickle,sha256=XqcFwQrXoBXAzZnE6rnfpI7zETXZS2usqzsx2ff7MEg,1319005
|
114
114
|
siat/stock_info_test.py,sha256=gfG3DbhDACbtD8wnv_R6zhj0t11XaC8NX8uLD9Qv3Fo,6122
|
115
115
|
siat/stock_list_china_test.py,sha256=gv14UwMMvkZqtb6G7DCTSuehIwVHuVwu7w60p6gyHoo,1014
|
116
116
|
siat/stock_prices_kneighbors.py,sha256=WfZvo5EyeBsm-T37zDj7Sl9dPSRq5Bx4JxIJ9IUum6s,36738
|
@@ -131,7 +131,7 @@ siat/transaction_test.py,sha256=Z8g1LJCN4-mnUByXMUMoFmN0t105cbmsz2QmvSuIkbU,1858
|
|
131
131
|
siat/translate-20230125.py,sha256=NPPSXhT38s5t9fzMvl_fvi4ckSB73ThLmZetVI-xGdU,117953
|
132
132
|
siat/translate-20230206.py,sha256=-vtI125WyaJhmPotOpDAmclt_XnYVaWU9ByLWZ6FyYE,118133
|
133
133
|
siat/translate-20230215.py,sha256=TJgtPE3n8IjljmZ4Pefy8dmHoNdFF-1zpML6BhA9FKE,121657
|
134
|
-
siat/translate.py,sha256=
|
134
|
+
siat/translate.py,sha256=_3fOZozd4RsJGJaITSn7Kil4PvmQFGpKVKHbcLRiBZI,218193
|
135
135
|
siat/translate_20240606.py,sha256=63IyHWEU3Uz9mjwyuAX3fqY4nUMdwh0ICQAgmgPXP7Y,215121
|
136
136
|
siat/universal_test.py,sha256=CDAOffW1Rvs-TcNN5giWVvHMlch1w4dp-w5SIV9jXL0,3936
|
137
137
|
siat/valuation.py,sha256=NKfeZMdDJOW42oLVHob6eSVBXUqlN1OCnnzwyGAst8c,48855
|
@@ -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.
|
143
|
-
siat-3.3.
|
144
|
-
siat-3.3.
|
145
|
-
siat-3.3.
|
142
|
+
siat-3.3.10.dist-info/METADATA,sha256=P7aiODOfU2l5p8yo_YUAiCS6vm5qQAGiM_iZdCRs79Y,7310
|
143
|
+
siat-3.3.10.dist-info/WHEEL,sha256=2wepM1nk4DS4eFpYrW1TTqPcoGNfHhhO_i5m4cOimbo,92
|
144
|
+
siat-3.3.10.dist-info/top_level.txt,sha256=r1cVyL7AIKqeAmEJjNR8FMT20OmEzufDstC2gv3NvEY,5
|
145
|
+
siat-3.3.10.dist-info/RECORD,,
|
File without changes
|
File without changes
|