siat 3.2.5__py3-none-any.whl → 3.2.15__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/__init__.py +14 -8
- siat/assets_liquidity.py +8 -8
- siat/capm_beta2.py +1 -1
- siat/common.py +116 -20
- siat/esg.py +2 -2
- siat/holding_risk.py +5 -5
- siat/markowitz.py +10 -10
- siat/markowitz2.py +73 -46
- siat/risk_adjusted_return.py +13 -13
- siat/security_price2.py +6 -6
- siat/security_prices.py +29 -10
- siat/stock.py +1 -1
- siat/stock_technical.py +569 -372
- siat/translate.py +1 -1
- siat/var_model_validation.py +1 -1
- {siat-3.2.5.dist-info → siat-3.2.15.dist-info}/METADATA +2 -1
- {siat-3.2.5.dist-info → siat-3.2.15.dist-info}/RECORD +19 -19
- {siat-3.2.5.dist-info → siat-3.2.15.dist-info}/WHEEL +0 -0
- {siat-3.2.5.dist-info → siat-3.2.15.dist-info}/top_level.txt +0 -0
siat/markowitz2.py
CHANGED
@@ -247,24 +247,35 @@ if __name__=='__main__':
|
|
247
247
|
}
|
248
248
|
portfolio=dict(Market,**porkbig,**porksmall)
|
249
249
|
|
250
|
-
thedate='2024-5-30'
|
251
|
-
pastyears=1
|
252
|
-
printout=True
|
253
|
-
graph=False
|
254
|
-
|
255
250
|
#测试3
|
256
|
-
Market={'Market':('China','000300.SS','
|
257
|
-
Stocks={'
|
258
|
-
'
|
259
|
-
'
|
260
|
-
'300207.SZ':0.1,#欣旺达
|
251
|
+
Market={'Market':('China','000300.SS','股债基组合')}
|
252
|
+
Stocks={'600519.SS':0.3,#股票:贵州茅台
|
253
|
+
'sh010504':[0.5,'bond'],#05国债⑷
|
254
|
+
'010504.SS':('fund',0.2),#招商稳兴混合C基金
|
261
255
|
}
|
262
256
|
portfolio=dict(Market,**Stocks)
|
263
257
|
|
258
|
+
printout=True
|
259
|
+
graph=False
|
260
|
+
|
264
261
|
indicator='Adj Close'
|
265
262
|
adjust='qfq'; source='auto'; ticker_type='bond'
|
266
263
|
thedate='2024-6-19'
|
267
264
|
pastyears=2
|
265
|
+
|
266
|
+
|
267
|
+
#测试3
|
268
|
+
Market={'Market':('China','000300.SS','股债基组合')}
|
269
|
+
Stocks={'600519.SS':0.3,#股票:贵州茅台
|
270
|
+
'sh010504':[0.5,'bond'],#05国债⑷
|
271
|
+
'010504.SS':('fund',0.2),#招商稳兴混合C基金
|
272
|
+
}
|
273
|
+
portfolio=dict(Market,**Stocks)
|
274
|
+
|
275
|
+
indicator='Close'
|
276
|
+
adjust=''; source='auto'; ticker_type='auto'
|
277
|
+
thedate='2024-6-19'
|
278
|
+
pastyears=1
|
268
279
|
printout=True
|
269
280
|
graph=False
|
270
281
|
|
@@ -312,7 +323,7 @@ def portfolio_build(portfolio,thedate='default',pastyears=1, \
|
|
312
323
|
|
313
324
|
print("\n Searching for portfolio info, which may take time ...")
|
314
325
|
# 解构投资组合
|
315
|
-
scope,_,tickerlist,sharelist0=decompose_portfolio(portfolio)
|
326
|
+
scope,_,tickerlist,sharelist0,ticker_type=decompose_portfolio(portfolio)
|
316
327
|
pname=portfolio_name(portfolio)
|
317
328
|
|
318
329
|
#如果持仓份额总数不为1,则将其转换为总份额为1
|
@@ -440,7 +451,7 @@ def portfolio_build(portfolio,thedate='default',pastyears=1, \
|
|
440
451
|
|
441
452
|
title_txt=text_lang("投资组合: 日收益率的变化趋势","Investment Portfolio: Daily Return")
|
442
453
|
ylabel_txt=text_lang("日收益率","Daily Return")
|
443
|
-
source_txt=text_lang("来源:
|
454
|
+
source_txt=text_lang("来源: 综合新浪/东方财富/stooq/雅虎等, ","Source: sina/eastmoney/stooq, ")
|
444
455
|
|
445
456
|
plt.title(title_txt)
|
446
457
|
plt.ylabel(ylabel_txt)
|
@@ -460,7 +471,7 @@ def portfolio_build(portfolio,thedate='default',pastyears=1, \
|
|
460
471
|
|
461
472
|
titletxt=text_lang("投资组合: 持有收益率的变化趋势","Investment Portfolio: Holding Return")
|
462
473
|
ylabeltxt=text_lang("持有收益率","Holding Return")
|
463
|
-
xlabeltxt1=text_lang("来源:
|
474
|
+
xlabeltxt1=text_lang("来源: 综合新浪/东方财富/stooq/雅虎等, ","Source: sina/eastmoney/stooq, ")
|
464
475
|
xlabeltxt=xlabeltxt1+str(stoday)
|
465
476
|
|
466
477
|
#绘制持有收益率曲线
|
@@ -476,22 +487,29 @@ def portfolio_build(portfolio,thedate='default',pastyears=1, \
|
|
476
487
|
StockReturns['Portfolio_EW']=stock_return.mul(portfolio_weights_ew,axis=1).sum(axis=1)
|
477
488
|
#..........................................................................
|
478
489
|
|
479
|
-
#
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
490
|
+
# 创建交易额加权组合:按照成交金额计算期间内交易额均值。债券和基金信息中无交易量!
|
491
|
+
if ('bond' not in ticker_type) and ('fund' not in ticker_type):
|
492
|
+
tamount=prices['Close']*prices['Volume']
|
493
|
+
tamountlist=tamount.mean(axis=0) #求列的均值
|
494
|
+
tamountlist_array = np.array(tamountlist)
|
495
|
+
# 计算成交金额权重
|
496
|
+
portfolio_weights_lw = tamountlist_array / np.sum(tamountlist_array)
|
497
|
+
# 计算成交金额加权的组合收益
|
498
|
+
StockReturns['Portfolio_LW'] = stock_return.mul(portfolio_weights_lw, axis=1).sum(axis=1)
|
487
499
|
|
488
500
|
#绘制累计收益率对比曲线
|
489
501
|
title_txt=text_lang("投资组合策略:业绩对比","Portfolio Strategies: Performance Comparison")
|
490
502
|
Portfolio_EW_txt=text_lang("等权重策略","Equal-weight")
|
491
|
-
|
503
|
+
if ('bond' not in ticker_type) and ('fund' not in ticker_type):
|
504
|
+
Portfolio_LW_txt=text_lang("交易额加权策略","Amount-weight")
|
492
505
|
|
493
|
-
|
494
|
-
|
506
|
+
name_list=['Portfolio', 'Portfolio_EW', 'Portfolio_LW']
|
507
|
+
label_list=[pname, Portfolio_EW_txt, Portfolio_LW_txt]
|
508
|
+
else:
|
509
|
+
name_list=['Portfolio', 'Portfolio_EW']
|
510
|
+
label_list=[pname, Portfolio_EW_txt]
|
511
|
+
|
512
|
+
|
495
513
|
titletxt=title_txt
|
496
514
|
|
497
515
|
#绘制各个投资组合的持有收益率曲线
|
@@ -501,9 +519,11 @@ def portfolio_build(portfolio,thedate='default',pastyears=1, \
|
|
501
519
|
#打印各个投资组合的持股比例
|
502
520
|
member_returns=stock_return
|
503
521
|
if printout:
|
504
|
-
portfolio_expectation_universal(pname,member_returns,portfolio_weights,member_prices)
|
505
|
-
portfolio_expectation_universal(Portfolio_EW_txt,member_returns,portfolio_weights_ew,member_prices)
|
506
|
-
|
522
|
+
portfolio_expectation_universal(pname,member_returns,portfolio_weights,member_prices,ticker_type)
|
523
|
+
portfolio_expectation_universal(Portfolio_EW_txt,member_returns,portfolio_weights_ew,member_prices,ticker_type)
|
524
|
+
|
525
|
+
if ('bond' not in ticker_type) and ('fund' not in ticker_type):
|
526
|
+
portfolio_expectation_universal(Portfolio_LW_txt,member_returns,portfolio_weights_lw,member_prices,ticker_type)
|
507
527
|
|
508
528
|
#返回投资组合的综合信息
|
509
529
|
member_returns=stock_return
|
@@ -516,8 +536,14 @@ def portfolio_build(portfolio,thedate='default',pastyears=1, \
|
|
516
536
|
if printout:
|
517
537
|
portfolio_ranks(portfolio_returns,pname)
|
518
538
|
|
519
|
-
|
520
|
-
|
539
|
+
#
|
540
|
+
if ('bond' not in ticker_type) and ('fund' not in ticker_type):
|
541
|
+
return [[portfolio,thedate,member_returns,rf_df,member_prices], \
|
542
|
+
[portfolio_returns,portfolio_weights,portfolio_weights_ew,portfolio_weights_lw]]
|
543
|
+
else:
|
544
|
+
return [[portfolio,thedate,member_returns,rf_df,member_prices], \
|
545
|
+
[portfolio_returns,portfolio_weights,portfolio_weights_ew,None]]
|
546
|
+
|
521
547
|
|
522
548
|
if __name__=='__main__':
|
523
549
|
X=portfolio_build(portfolio,'2021-9-30')
|
@@ -656,10 +682,10 @@ if __name__=='__main__':
|
|
656
682
|
portfolio=dict(Market,**Stocks1,**Stocks2)
|
657
683
|
pf_info=portfolio_expret(portfolio,'2019-12-31')
|
658
684
|
|
659
|
-
|
685
|
+
portfolio_expectation_original(pf_info)
|
660
686
|
|
661
687
|
#==============================================================================
|
662
|
-
def portfolio_expectation_universal(pname,member_returns,portfolio_weights,member_prices):
|
688
|
+
def portfolio_expectation_universal(pname,member_returns,portfolio_weights,member_prices,ticker_type):
|
663
689
|
"""
|
664
690
|
功能:计算给定成份股收益率和持股权重的投资组合年均收益率和标准差
|
665
691
|
输入:投资组合名称,成份股历史收益率数据表,投资组合权重series
|
@@ -704,12 +730,12 @@ def portfolio_expectation_universal(pname,member_returns,portfolio_weights,membe
|
|
704
730
|
print(" 投资组合:",pname)
|
705
731
|
print(" 分析日期:",str(hend))
|
706
732
|
# 投资组合中即使持股比例最低的股票每次交易最少也需要1手(100股)
|
707
|
-
print("
|
733
|
+
print(" 1手组合单位价值:","约"+str(round(portfolio_value_thedate/10000*100,2))+"万")
|
708
734
|
print(" 观察期间:",hstart+'至'+hend)
|
709
735
|
print(" 年化收益率:",round(annual_return,4))
|
710
736
|
print(" 年化标准差:",round(annual_std,4))
|
711
737
|
print(" ***投资组合持仓策略***")
|
712
|
-
print_tickerlist_sharelist(tickerlist,portfolio_weights,leading_blanks=4,ticker_type=
|
738
|
+
print_tickerlist_sharelist(tickerlist,portfolio_weights,leading_blanks=4,ticker_type=ticker_type)
|
713
739
|
|
714
740
|
print(" *来源:Sina/EM/stooq,"+str(stoday)+"统计")
|
715
741
|
else:
|
@@ -740,7 +766,7 @@ if __name__=='__main__':
|
|
740
766
|
portfolio_expectation2(pname,member_returns, portfolio_weights)
|
741
767
|
|
742
768
|
#==============================================================================
|
743
|
-
def portfolio_expectation(pname,pf_info,portfolio_weights):
|
769
|
+
def portfolio_expectation(pname,pf_info,portfolio_weights,ticker_type):
|
744
770
|
"""
|
745
771
|
功能:计算给定pf_info和持仓权重的投资组合年均收益率和标准差
|
746
772
|
输入:投资组合名称,pf_info,投资组合权重series
|
@@ -749,7 +775,7 @@ def portfolio_expectation(pname,pf_info,portfolio_weights):
|
|
749
775
|
"""
|
750
776
|
[[_,_,member_returns,_,member_prices],_]=pf_info
|
751
777
|
|
752
|
-
portfolio_expectation_universal(pname,member_returns,portfolio_weights,member_prices)
|
778
|
+
portfolio_expectation_universal(pname,member_returns,portfolio_weights,member_prices,ticker_type)
|
753
779
|
|
754
780
|
return
|
755
781
|
|
@@ -1080,7 +1106,7 @@ def portfolio_eset(pf_info,simulation=1000,convex_hull=False):
|
|
1080
1106
|
"""
|
1081
1107
|
[[portfolio,thedate,stock_return,_,_],_]=pf_info
|
1082
1108
|
pname=portfolio_name(portfolio)
|
1083
|
-
_,_,tickerlist,_=decompose_portfolio(portfolio)
|
1109
|
+
_,_,tickerlist,_,ticker_type=decompose_portfolio(portfolio)
|
1084
1110
|
|
1085
1111
|
#取出观察期
|
1086
1112
|
hstart0=stock_return.index[0]; hstart=str(hstart0.strftime("%Y-%m-%d"))
|
@@ -1233,7 +1259,7 @@ def portfolio_es_sharpe(pf_info,simulation=1000,RF=0):
|
|
1233
1259
|
|
1234
1260
|
[[portfolio,thedate,stock_return0,rf_df,_],_]=pf_info
|
1235
1261
|
pname=portfolio_name(portfolio)
|
1236
|
-
scope,_,tickerlist,_=decompose_portfolio(portfolio)
|
1262
|
+
scope,_,tickerlist,_,ticker_type=decompose_portfolio(portfolio)
|
1237
1263
|
|
1238
1264
|
#取出观察期
|
1239
1265
|
hstart0=stock_return0.index[0]; hstart=str(hstart0.strftime("%Y-%m-%d"))
|
@@ -1327,7 +1353,7 @@ def portfolio_es_sortino(pf_info,simulation=1000,RF=0):
|
|
1327
1353
|
|
1328
1354
|
[[portfolio,thedate,stock_return0,rf_df,_],_]=pf_info
|
1329
1355
|
pname=portfolio_name(portfolio)
|
1330
|
-
scope,_,tickerlist,_=decompose_portfolio(portfolio)
|
1356
|
+
scope,_,tickerlist,_,ticker_type=decompose_portfolio(portfolio)
|
1331
1357
|
|
1332
1358
|
#取出观察期
|
1333
1359
|
hstart0=stock_return0.index[0]; hstart=str(hstart0.strftime("%Y-%m-%d"))
|
@@ -1427,7 +1453,7 @@ def portfolio_es_alpha(pf_info,simulation=1000,RF=0):
|
|
1427
1453
|
|
1428
1454
|
[[portfolio,thedate,stock_return0,rf_df,_],_]=pf_info
|
1429
1455
|
pname=portfolio_name(portfolio)
|
1430
|
-
scope,mktidx,tickerlist,_=decompose_portfolio(portfolio)
|
1456
|
+
scope,mktidx,tickerlist,_,ticker_type=decompose_portfolio(portfolio)
|
1431
1457
|
|
1432
1458
|
#取出观察期
|
1433
1459
|
hstart0=stock_return0.index[0]; hstart=str(hstart0.strftime("%Y-%m-%d"))
|
@@ -1545,7 +1571,7 @@ def portfolio_es_treynor(pf_info,simulation=1000,RF=0):
|
|
1545
1571
|
|
1546
1572
|
[[portfolio,_,stock_return0,rf_df,_],_]=pf_info
|
1547
1573
|
pname=portfolio_name(portfolio)
|
1548
|
-
scope,mktidx,tickerlist,_=decompose_portfolio(portfolio)
|
1574
|
+
scope,mktidx,tickerlist,_,ticker_type=decompose_portfolio(portfolio)
|
1549
1575
|
|
1550
1576
|
#取出观察期
|
1551
1577
|
hstart0=stock_return0.index[0]; hstart=str(hstart0.strftime("%Y-%m-%d"))
|
@@ -2049,7 +2075,7 @@ def portfolio_optimize_rar(es_info,col_ratio,col_y,col_x,name_hiret,name_lorisk,
|
|
2049
2075
|
"""
|
2050
2076
|
#解析传入的数据
|
2051
2077
|
[[[portfolio,thedate,stock_return,_,_],[StockReturns,_,_,_]],RandomPortfolios]=es_info
|
2052
|
-
_,_,tickerlist,_=decompose_portfolio(portfolio)
|
2078
|
+
_,_,tickerlist,_,ticker_type=decompose_portfolio(portfolio)
|
2053
2079
|
numstocks=len(tickerlist)
|
2054
2080
|
pname=portfolio_name(portfolio)
|
2055
2081
|
|
@@ -2158,6 +2184,7 @@ def portfolio_optimize(pf_info,ratio='sharpe',simulation=10000,RF=0, \
|
|
2158
2184
|
|
2159
2185
|
[[portfolio,_,_,_,_],_]=pf_info
|
2160
2186
|
pname=portfolio_name(portfolio)
|
2187
|
+
_,_,_,_,ticker_type=decompose_portfolio(portfolio)
|
2161
2188
|
|
2162
2189
|
#观察马科维茨可行集:风险溢价-标准差,用于夏普比率优化
|
2163
2190
|
func_es="portfolio_es_"+ratio
|
@@ -2189,10 +2216,10 @@ def portfolio_optimize(pf_info,ratio='sharpe',simulation=10000,RF=0, \
|
|
2189
2216
|
#打印投资组合构造和业绩表现
|
2190
2217
|
hi_name=modify_portfolio_name(name_hiret+zhuhe_txt)
|
2191
2218
|
lo_name=modify_portfolio_name(name_lorisk+zhuhe_txt)
|
2192
|
-
portfolio_expectation(hi_name,pf_info,hiret_weights)
|
2219
|
+
portfolio_expectation(hi_name,pf_info,hiret_weights,ticker_type)
|
2193
2220
|
|
2194
2221
|
if hirar_return:
|
2195
|
-
scope,mktidx,tickerlist,_=decompose_portfolio(portfolio)
|
2222
|
+
scope,mktidx,tickerlist,_,ticker_type=decompose_portfolio(portfolio)
|
2196
2223
|
hwdf=pd.DataFrame(hiret_weights)
|
2197
2224
|
hwdft=hwdf.T
|
2198
2225
|
hwdft.columns=tickerlist
|
@@ -2207,7 +2234,7 @@ def portfolio_optimize(pf_info,ratio='sharpe',simulation=10000,RF=0, \
|
|
2207
2234
|
portfolio_new=dict(Market,**stocks_new)
|
2208
2235
|
|
2209
2236
|
if lorisk:
|
2210
|
-
portfolio_expectation(lo_name,pf_info,lorisk_weights)
|
2237
|
+
portfolio_expectation(lo_name,pf_info,lorisk_weights,ticker_type)
|
2211
2238
|
|
2212
2239
|
#现有投资组合的排名
|
2213
2240
|
ranks=portfolio_ranks(portfolio_returns,pname)
|
@@ -2594,7 +2621,7 @@ def describe_portfolio(portfolio):
|
|
2594
2621
|
输出:市场,市场指数,股票代码列表和份额列表
|
2595
2622
|
"""
|
2596
2623
|
|
2597
|
-
scope,mktidx,tickerlist,sharelist=decompose_portfolio(portfolio)
|
2624
|
+
scope,mktidx,tickerlist,sharelist,ticker_type=decompose_portfolio(portfolio)
|
2598
2625
|
pname=portfolio_name(portfolio)
|
2599
2626
|
|
2600
2627
|
print("*** 投资组合信息:",pname)
|
@@ -2626,7 +2653,7 @@ def portfolio_drop(portfolio,last=0,droplist=[],new_name=''):
|
|
2626
2653
|
"""
|
2627
2654
|
功能:删除最后几个成分股
|
2628
2655
|
"""
|
2629
|
-
scope,mktidx,tickerlist,sharelist=decompose_portfolio(portfolio)
|
2656
|
+
scope,mktidx,tickerlist,sharelist,ticker_type=decompose_portfolio(portfolio)
|
2630
2657
|
pname=portfolio_name(portfolio)
|
2631
2658
|
|
2632
2659
|
if not (last ==0):
|
siat/risk_adjusted_return.py
CHANGED
@@ -143,7 +143,7 @@ def print_rar_ratio(regdf,portfolio,ret_mean,ratio_name,ratio):
|
|
143
143
|
"""
|
144
144
|
|
145
145
|
#从字典中提取信息
|
146
|
-
scope,mktidx,stocklist,portionlist=decompose_portfolio(portfolio)
|
146
|
+
scope,mktidx,stocklist,portionlist,ticker_type=decompose_portfolio(portfolio)
|
147
147
|
stocklist1,_=cvt_yftickerlist(stocklist)
|
148
148
|
|
149
149
|
date_start=str(regdf.index[0].year)+'-'+str(regdf.index[0].month)+ \
|
@@ -199,7 +199,7 @@ def treynor_ratio_portfolio(portfolio,start,end,RF=True,printout=True):
|
|
199
199
|
return None,None
|
200
200
|
|
201
201
|
#从字典中提取信息
|
202
|
-
scope,mktidx,stocklist,portionlist=decompose_portfolio(portfolio)
|
202
|
+
scope,mktidx,stocklist,portionlist,ticker_type=decompose_portfolio(portfolio)
|
203
203
|
|
204
204
|
#第2步:计算投资组合的日收益率序列
|
205
205
|
#抓取日投资组合价格
|
@@ -280,7 +280,7 @@ def rar_ratio_portfolio(portfolio,start,end,ratio_name='treynor',RF=True,printou
|
|
280
280
|
return None,None
|
281
281
|
|
282
282
|
#从字典中提取信息
|
283
|
-
scope,mktidx,stocklist,portionlist=decompose_portfolio(portfolio)
|
283
|
+
scope,mktidx,stocklist,portionlist,ticker_type=decompose_portfolio(portfolio)
|
284
284
|
|
285
285
|
#第2步:计算投资组合的日收益率序列
|
286
286
|
#抓取日投资组合价格
|
@@ -373,7 +373,7 @@ def rar_ratio_rolling(portfolio,start,end,ratio_name='treynor',RF=True, \
|
|
373
373
|
startdate1=date_adjust(startdate, adjust=-startdate_delta)
|
374
374
|
|
375
375
|
#从字典中提取信息
|
376
|
-
scope,mktidx,stocklist,portionlist=decompose_portfolio(portfolio)
|
376
|
+
scope,mktidx,stocklist,portionlist,ticker_type=decompose_portfolio(portfolio)
|
377
377
|
|
378
378
|
#第2步:计算投资组合的日收益率序列
|
379
379
|
#抓取日投资组合价格
|
@@ -465,7 +465,7 @@ def draw_rar_ratio(rars,portfolio,ratio_name):
|
|
465
465
|
输入:滚动数据df,投资组合,指数名称
|
466
466
|
"""
|
467
467
|
|
468
|
-
scope,mktidx,stocklist,portionlist=decompose_portfolio(portfolio)
|
468
|
+
scope,mktidx,stocklist,portionlist,ticker_type=decompose_portfolio(portfolio)
|
469
469
|
stocklist1,_=cvt_yftickerlist(stocklist)
|
470
470
|
|
471
471
|
"""
|
@@ -545,7 +545,7 @@ def sharpe_ratio_portfolio(portfolio,start,end,RF=True,printout=True):
|
|
545
545
|
return None,None
|
546
546
|
|
547
547
|
#从字典中提取信息
|
548
|
-
scope,mktidx,stocklist,portionlist=decompose_portfolio(portfolio)
|
548
|
+
scope,mktidx,stocklist,portionlist,ticker_type=decompose_portfolio(portfolio)
|
549
549
|
|
550
550
|
#检查份额配比是否合理
|
551
551
|
"""
|
@@ -597,7 +597,7 @@ def sharpe_ratio_portfolio(portfolio,start,end,RF=True,printout=True):
|
|
597
597
|
'-'+str(reg.index[-1].day)
|
598
598
|
print("\n===== 风险调整收益率 =====")
|
599
599
|
|
600
|
-
_,_,tickerlist,sharelist=decompose_portfolio(portfolio)
|
600
|
+
_,_,tickerlist,sharelist,ticker_type=decompose_portfolio(portfolio)
|
601
601
|
if len(tickerlist)==1:
|
602
602
|
product=str(ticker_name(tickerlist,'bond'))
|
603
603
|
else:
|
@@ -640,7 +640,7 @@ def sortino_ratio_portfolio(portfolio,start,end,RF=True,printout=True):
|
|
640
640
|
return None,None
|
641
641
|
|
642
642
|
#从字典中提取信息
|
643
|
-
scope,mktidx,stocklist,portionlist=decompose_portfolio(portfolio)
|
643
|
+
scope,mktidx,stocklist,portionlist,ticker_type=decompose_portfolio(portfolio)
|
644
644
|
|
645
645
|
#检查份额配比是否合理
|
646
646
|
"""
|
@@ -693,7 +693,7 @@ def sortino_ratio_portfolio(portfolio,start,end,RF=True,printout=True):
|
|
693
693
|
'-'+str(reg.index[-1].day)
|
694
694
|
print("\n===== 风险调整收益率 =====")
|
695
695
|
|
696
|
-
_,_,tickerlist,sharelist=decompose_portfolio(portfolio)
|
696
|
+
_,_,tickerlist,sharelist,ticker_type=decompose_portfolio(portfolio)
|
697
697
|
if len(tickerlist)==1:
|
698
698
|
product=str(ticker_name(tickerlist,'bond'))
|
699
699
|
else:
|
@@ -738,7 +738,7 @@ def jensen_alpha_portfolio(portfolio,start,end,RF=True,printout=True):
|
|
738
738
|
return None,None
|
739
739
|
|
740
740
|
#从字典中提取信息
|
741
|
-
scope,mktidx,stocklist,portionlist=decompose_portfolio(portfolio)
|
741
|
+
scope,mktidx,stocklist,portionlist,ticker_type=decompose_portfolio(portfolio)
|
742
742
|
#检查份额配比是否合理
|
743
743
|
"""
|
744
744
|
if round(sum(portionlist),1) != 1.0:
|
@@ -798,7 +798,7 @@ def jensen_alpha_portfolio(portfolio,start,end,RF=True,printout=True):
|
|
798
798
|
'-'+str(reg.index[-1].day)
|
799
799
|
print("\n===== 风险调整收益率 =====")
|
800
800
|
|
801
|
-
_,_,tickerlist,sharelist=decompose_portfolio(portfolio)
|
801
|
+
_,_,tickerlist,sharelist,ticker_type=decompose_portfolio(portfolio)
|
802
802
|
if len(tickerlist)==1:
|
803
803
|
product=str(ticker_name(tickerlist,'bond'))
|
804
804
|
else:
|
@@ -1120,14 +1120,14 @@ def compare_rar_portfolio(portfolio1,portfolio2,start,end,ratio_name='sharpe', \
|
|
1120
1120
|
ylabeltxt=label1
|
1121
1121
|
titletxt="证券风险调整收益的滚动趋势对比"
|
1122
1122
|
|
1123
|
-
_,_,tickers1,shares1=decompose_portfolio(portfolio1)
|
1123
|
+
_,_,tickers1,shares1,ticker_type=decompose_portfolio(portfolio1)
|
1124
1124
|
if len(tickers1) == 1:
|
1125
1125
|
ticker1=tickers1[0]
|
1126
1126
|
pf1str=tickers1[0]
|
1127
1127
|
else:
|
1128
1128
|
pf1str=ticker1+':成分'+str(tickers1)+',比例'+str(shares1)
|
1129
1129
|
|
1130
|
-
_,_,tickers2,shares2=decompose_portfolio(portfolio2)
|
1130
|
+
_,_,tickers2,shares2,ticker_type=decompose_portfolio(portfolio2)
|
1131
1131
|
if len(tickers2) == 1:
|
1132
1132
|
ticker2=tickers2[0]
|
1133
1133
|
pf2str=tickers2[0]
|
siat/security_price2.py
CHANGED
@@ -86,8 +86,8 @@ def get_price_1ticker(ticker,fromdate,todate, \
|
|
86
86
|
#print(" #Warning(get_price_1ticker): invalid date period from",fromdate,"to",todate)
|
87
87
|
return df,found
|
88
88
|
|
89
|
-
|
90
|
-
ak_fq_list=['','qfq','hfq','qfq-factor','hfq-factor']
|
89
|
+
#检查复权选项合理性:adj_only特别指最高最低价开盘收盘价全为复权价
|
90
|
+
ak_fq_list=['','qfq','hfq','qfq-factor','hfq-factor','adj_only']
|
91
91
|
if adjust not in ak_fq_list:
|
92
92
|
adjust='qfq'
|
93
93
|
|
@@ -149,11 +149,11 @@ def get_price_1ticker(ticker,fromdate,todate, \
|
|
149
149
|
if source in ['auto','yahoo'] and found not in ['Found','Empty']:
|
150
150
|
dft=None
|
151
151
|
if test_yahoo_finance():
|
152
|
-
#数据源情形3:yahoo, yfinance, 需要访问yahoo
|
152
|
+
#数据源情形3:yahoo, yfinance, 需要访问yahoo,直接为复权价?
|
153
153
|
dft=get_price_yf(ticker1,fromdate,todate)
|
154
154
|
found=df_have_data(dft)
|
155
155
|
|
156
|
-
#数据源情形4:yahoo, pandas_datareader,需要访问yahoo
|
156
|
+
#数据源情形4:yahoo, pandas_datareader,需要访问yahoo,似乎不工作!
|
157
157
|
if found not in ['Found','Empty']:
|
158
158
|
dft=get_prices_yahoo(ticker1,fromdate,todate)
|
159
159
|
found=df_have_data(dft)
|
@@ -364,13 +364,13 @@ def get_price_1portfolio(ticker,fromdate,todate, \
|
|
364
364
|
return df,found
|
365
365
|
|
366
366
|
#拆分投资组合为成份股列表和份额列表
|
367
|
-
_,_,tickerlist,sharelist=decompose_portfolio(ticker)
|
367
|
+
_,_,tickerlist,sharelist,ticker_type=decompose_portfolio(ticker)
|
368
368
|
|
369
369
|
#处理份额列表,确保其和为1
|
370
370
|
share_sum=sum(sharelist)
|
371
371
|
sharelist1=[x / share_sum for x in sharelist]
|
372
372
|
|
373
|
-
#预处理ticker_type
|
373
|
+
#预处理ticker_type,是否还需要?
|
374
374
|
ticker_type=ticker_type_preprocess_1portfolio(ticker,ticker_type)
|
375
375
|
|
376
376
|
#抓取各个成份股的价格信息
|
siat/security_prices.py
CHANGED
@@ -78,9 +78,9 @@ def get_prices_all(ticker,fromdate,todate,adj=False,source='auto',ticker_type='a
|
|
78
78
|
|
79
79
|
#投资组合
|
80
80
|
if isinstance(ticker_list[0],dict):
|
81
|
-
_,_,tickerlist,sharelist=decompose_portfolio(ticker_list[0])
|
81
|
+
_,_,tickerlist,sharelist,ticker_type=decompose_portfolio(ticker_list[0])
|
82
82
|
df=get_price_portfolio(tickerlist,sharelist,fromdate,todate,adj=adj, \
|
83
|
-
source=source,ticker_type=
|
83
|
+
source=source,ticker_type=ticker_type)
|
84
84
|
return df
|
85
85
|
|
86
86
|
#多个证券
|
@@ -95,9 +95,9 @@ def get_prices_all(ticker,fromdate,todate,adj=False,source='auto',ticker_type='a
|
|
95
95
|
|
96
96
|
#投资组合
|
97
97
|
if isinstance(t,dict):
|
98
|
-
_,_,tickerlist,sharelist=decompose_portfolio(t)
|
98
|
+
_,_,tickerlist,sharelist,ticker_type=decompose_portfolio(t)
|
99
99
|
dft=get_price_portfolio(tickerlist,sharelist,fromdate,todate,adj=adj, \
|
100
|
-
source=source,ticker_type=
|
100
|
+
source=source,ticker_type=ticker_type)
|
101
101
|
t=portfolio_name(t)
|
102
102
|
|
103
103
|
columns=create_tuple_for_columns(dft,t)
|
@@ -755,14 +755,14 @@ def get_price_ak_cn(ticker,fromdate,todate,adjust='',ticker_type='auto'):
|
|
755
755
|
end1=end.strftime('%Y%m%d')
|
756
756
|
|
757
757
|
#adjustlist=['none','hfq','qfq']
|
758
|
-
adjustlist=['','qfq','hfq','qfq-factor','hfq-factor']
|
758
|
+
adjustlist=['','qfq','hfq','qfq-factor','hfq-factor','adj_only']
|
759
759
|
if adjust not in adjustlist:
|
760
760
|
print(" #Warning(get_price_ak_cn): adjust only supports",adjustlist)
|
761
761
|
return None
|
762
762
|
|
763
763
|
_,prefix,suffix=split_prefix_suffix(ticker2)
|
764
|
-
|
765
|
-
if adjust
|
764
|
+
#考虑股票复权情形:仅收盘价为复权价,指数/基金/债券无复权
|
765
|
+
if adjust not in ['','adj_only']:
|
766
766
|
if ticker_type in ['auto','stock'] and suffix not in ['SW']:
|
767
767
|
try:
|
768
768
|
#仅用于股票的历史行情数据(考虑复权)
|
@@ -775,6 +775,18 @@ def get_price_ak_cn(ticker,fromdate,todate,adjust='',ticker_type='auto'):
|
|
775
775
|
except:
|
776
776
|
df=None
|
777
777
|
found=df_have_data(df)
|
778
|
+
|
779
|
+
#考虑股票复权情形:所有价格均为复权价,指数/基金/债券无复权
|
780
|
+
if adjust == 'adj_only':
|
781
|
+
if ticker_type in ['auto','stock'] and suffix not in ['SW']:
|
782
|
+
try:
|
783
|
+
#仅用于股票的历史行情数据(考虑复权)
|
784
|
+
df=ak.stock_zh_a_daily(ticker2,start1,end1,adjust='qfq')
|
785
|
+
df['Adj Close']=df['close']
|
786
|
+
df['Date']=df['date']
|
787
|
+
except:
|
788
|
+
df=None
|
789
|
+
found=df_have_data(df)
|
778
790
|
|
779
791
|
#股票(无复权)指数/基金/债券
|
780
792
|
if found != 'Found':
|
@@ -961,6 +973,10 @@ def get_price_ak_us(symbol, fromdate, todate, adjust=""):
|
|
961
973
|
try:
|
962
974
|
if adjust=='':
|
963
975
|
df=ak.stock_us_daily(symbol=symbol,adjust=adjust)
|
976
|
+
elif adjust=='Adj_only':
|
977
|
+
df=ak.stock_us_daily(symbol=symbol,adjust='qfq')
|
978
|
+
df['Adj Close']=df['close']
|
979
|
+
|
964
980
|
else:
|
965
981
|
dffqno=ak.stock_us_daily(symbol=symbol,adjust='')
|
966
982
|
dffq=ak.stock_us_daily(symbol=symbol,adjust='qfq')
|
@@ -1048,6 +1064,9 @@ def get_price_ak_hk(symbol,fromdate,todate,adjust=""):
|
|
1048
1064
|
try:
|
1049
1065
|
if adjust == '':
|
1050
1066
|
df=ak.stock_hk_daily(symbol=symbol3, adjust=adjust)
|
1067
|
+
elif adjust == 'Adj_only':
|
1068
|
+
df=ak.stock_hk_daily(symbol=symbol3, adjust='qfq')
|
1069
|
+
df['Adj Close']=df['close']
|
1051
1070
|
else:
|
1052
1071
|
dffqno=ak.stock_hk_daily(symbol=symbol3, adjust='')
|
1053
1072
|
dffq =ak.stock_hk_daily(symbol=symbol3,adjust='qfq')
|
@@ -1503,7 +1522,7 @@ if __name__=='__main__':
|
|
1503
1522
|
ticker_type='auto'
|
1504
1523
|
|
1505
1524
|
ticker={'Market':('China','000001.SS','白酒组合'),'600519.SS':0.4,'000858.SZ':0.6}
|
1506
|
-
_,_,tickerlist,sharelist=decompose_portfolio(ticker)
|
1525
|
+
_,_,tickerlist,sharelist,ticker_type=decompose_portfolio(ticker)
|
1507
1526
|
|
1508
1527
|
p=get_prices_portfolio(tickerlist,sharelist,fromdate,todate,source='auto')
|
1509
1528
|
|
@@ -2157,7 +2176,7 @@ def get_portfolio_prices(portfolio,fromdate,todate,adj=False,source='auto'):
|
|
2157
2176
|
"""
|
2158
2177
|
|
2159
2178
|
#解构投资组合
|
2160
|
-
_,mktidx,tickerlist,sharelist=decompose_portfolio(portfolio)
|
2179
|
+
_,mktidx,tickerlist,sharelist,ticker_type=decompose_portfolio(portfolio)
|
2161
2180
|
|
2162
2181
|
#检查股票列表个数与份额列表个数是否一致
|
2163
2182
|
if len(tickerlist) != len(sharelist):
|
@@ -2405,7 +2424,7 @@ def get_price_security(security,start,end,source='auto'):
|
|
2405
2424
|
"""
|
2406
2425
|
|
2407
2426
|
if isinstance(security,dict): #投资组合
|
2408
|
-
scope,mktidx,tickerlist,sharelist=decompose_portfolio(security)
|
2427
|
+
scope,mktidx,tickerlist,sharelist,ticker_type=decompose_portfolio(security)
|
2409
2428
|
prices=get_price_portfolio(tickerlist,sharelist,start,end,source=source)
|
2410
2429
|
|
2411
2430
|
pname=portfolio_name(security)
|