siat 3.10.75__py3-none-any.whl → 3.10.125__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/assets_liquidity.py +168 -30
- siat/bond.py +34 -7
- siat/capm_beta.py +34 -9
- siat/common.py +88 -7
- siat/economy2.py +75 -1
- siat/exchange_bond_china.pickle +0 -0
- siat/fama_french.py +201 -12
- siat/financial_statements.py +26 -85
- siat/financials.py +114 -14
- siat/financials_china.py +1 -1
- siat/fund_china.py +6 -5
- siat/future_china.py +8 -2
- siat/holding_risk.py +38 -31
- siat/market_china.py +20 -10
- siat/markowitz2.py +72 -10
- siat/option_china.py +45 -17
- siat/option_pricing.py +3 -0
- siat/other_indexes.py +16 -3
- siat/risk_adjusted_return.py +182 -114
- siat/risk_evaluation.py +252 -20
- siat/sector_china.py +12 -9
- siat/security_price2.py +19 -4
- siat/security_prices.py +222 -23
- siat/security_trend2.py +3 -3
- siat/stock.py +32 -0
- siat/translate.py +18 -9
- siat/var_model_validation.py +59 -0
- {siat-3.10.75.dist-info → siat-3.10.125.dist-info}/METADATA +1 -1
- {siat-3.10.75.dist-info → siat-3.10.125.dist-info}/RECORD +32 -32
- {siat-3.10.75.dist-info → siat-3.10.125.dist-info}/LICENSE +0 -0
- {siat-3.10.75.dist-info → siat-3.10.125.dist-info}/WHEEL +0 -0
- {siat-3.10.75.dist-info → siat-3.10.125.dist-info}/top_level.txt +0 -0
siat/financial_statements.py
CHANGED
@@ -52,14 +52,8 @@ def get_balance_sheet(symbol):
|
|
52
52
|
try:
|
53
53
|
stmta=stock.balance_sheet() # Defaults to Annual
|
54
54
|
except:
|
55
|
-
print("
|
56
|
-
|
57
|
-
|
58
|
-
try:
|
59
|
-
stmta=stock.balance_sheet()
|
60
|
-
except:
|
61
|
-
print(" #Warning(get_balance_sheet): no annual info available for",symbol)
|
62
|
-
return None
|
55
|
+
print(" #Warning(get_balance_sheet): no annual info available for",symbol)
|
56
|
+
return None
|
63
57
|
|
64
58
|
if isinstance(stmta,dict):
|
65
59
|
print(" #Warning(get_balance_sheet): Yahoo Finance currently unaccessable for",symbol)
|
@@ -76,14 +70,8 @@ def get_balance_sheet(symbol):
|
|
76
70
|
try:
|
77
71
|
stmtq=stock.balance_sheet(frequency="q")
|
78
72
|
except:
|
79
|
-
print("
|
80
|
-
|
81
|
-
|
82
|
-
try:
|
83
|
-
stmtq=stock.balance_sheet(frequency="q")
|
84
|
-
except:
|
85
|
-
print(" #Warning(get_balance_sheet): no quarterly info available for",symbol)
|
86
|
-
return None
|
73
|
+
print(" #Warning(get_balance_sheet): no quarterly info available for",symbol)
|
74
|
+
return None
|
87
75
|
|
88
76
|
if isinstance(stmtq,dict):
|
89
77
|
print(" #Warning(get_balance_sheet): Yahoo Finance currently unaccessable for",symbol)
|
@@ -196,17 +184,12 @@ def get_income_statements(symbol):
|
|
196
184
|
try:
|
197
185
|
stmta=stock.income_statement() # Defaults to Annual
|
198
186
|
except:
|
199
|
-
print("
|
200
|
-
|
201
|
-
try:
|
202
|
-
stmta=stock.income_statement()
|
203
|
-
except:
|
204
|
-
print(" #Warning(get_income_statements): no annual info available for",symbol)
|
205
|
-
return None
|
187
|
+
print(" #Warning(get_income_statements): no annual info available for",symbol)
|
188
|
+
return None
|
206
189
|
|
207
190
|
if isinstance(stmta,dict):
|
208
|
-
|
209
|
-
|
191
|
+
print(" #Warning(get_balance_sheet): Yahoo Finance currently unaccessable for",symbol)
|
192
|
+
return None
|
210
193
|
|
211
194
|
"""
|
212
195
|
#判断是否抓取到了数据
|
@@ -219,17 +202,12 @@ def get_income_statements(symbol):
|
|
219
202
|
try:
|
220
203
|
stmtq=stock.income_statement(frequency="q")
|
221
204
|
except:
|
222
|
-
print("
|
223
|
-
|
224
|
-
try:
|
225
|
-
stmtq=stock.income_statement(frequency="q")
|
226
|
-
except:
|
227
|
-
print(" #Warning(get_income_statements): no quarterly info available for",symbol)
|
228
|
-
return None
|
205
|
+
print(" #Warning(get_income_statements): no quarterly info available for",symbol)
|
206
|
+
return None
|
229
207
|
|
230
208
|
if isinstance(stmtq,dict):
|
231
|
-
|
232
|
-
|
209
|
+
print(" #Warning(get_balance_sheet): Yahoo Finance currently unaccessable for",symbol)
|
210
|
+
return None
|
233
211
|
|
234
212
|
"""
|
235
213
|
if (len(stmta)==0) and (len(stmtq)==0):
|
@@ -311,17 +289,12 @@ def get_cashflow_statements(symbol):
|
|
311
289
|
try:
|
312
290
|
stmta=stock.cash_flow() # Defaults to Annual
|
313
291
|
except:
|
314
|
-
print("
|
315
|
-
|
316
|
-
try:
|
317
|
-
stmta=stock.cash_flow()
|
318
|
-
except:
|
319
|
-
print(" #Warning(get_cashflow_statements): no annual info available for",symbol)
|
320
|
-
return None
|
292
|
+
print(" #Warning(get_cashflow_statements): no annual info available for",symbol)
|
293
|
+
return None
|
321
294
|
|
322
295
|
if isinstance(stmta,dict):
|
323
|
-
|
324
|
-
|
296
|
+
print(" #Warning(get_balance_sheet): Yahoo Finance currently unaccessable for",symbol)
|
297
|
+
return None
|
325
298
|
|
326
299
|
"""
|
327
300
|
#判断是否抓取到了数据
|
@@ -334,17 +307,12 @@ def get_cashflow_statements(symbol):
|
|
334
307
|
try:
|
335
308
|
stmtq=stock.cash_flow(frequency="q")
|
336
309
|
except:
|
337
|
-
print("
|
338
|
-
|
339
|
-
try:
|
340
|
-
stmtq=stock.cash_flow(frequency="q")
|
341
|
-
except:
|
342
|
-
print(" #Warning(get_cashflow_statements): no quarterly info available for",symbol)
|
343
|
-
return None
|
310
|
+
print(" #Warning(get_cashflow_statements): no quarterly info available for",symbol)
|
311
|
+
return None
|
344
312
|
|
345
313
|
if isinstance(stmtq,dict):
|
346
|
-
|
347
|
-
|
314
|
+
print(" #Warning(get_balance_sheet): Yahoo Finance currently unaccessable for",symbol)
|
315
|
+
return None
|
348
316
|
|
349
317
|
"""
|
350
318
|
if (len(stmta)==0) and (len(stmtq)==0):
|
@@ -408,17 +376,8 @@ def get_financial_statements(ticker):
|
|
408
376
|
try:
|
409
377
|
fbs = get_balance_sheet(ticker)
|
410
378
|
except:
|
411
|
-
print("
|
412
|
-
|
413
|
-
try:
|
414
|
-
fbs = get_balance_sheet(ticker)
|
415
|
-
except:
|
416
|
-
sleep_random(max_sleep=60)
|
417
|
-
try:
|
418
|
-
fbs = get_balance_sheet(ticker)
|
419
|
-
except:
|
420
|
-
print(" #Error(get_financial_statements): balance sheet not available for",ticker)
|
421
|
-
return None
|
379
|
+
print(" #Error(get_financial_statements): balance sheet not available for",ticker)
|
380
|
+
return None
|
422
381
|
if fbs is None:
|
423
382
|
print(" #Error(get_financial_statements): financial statements not available for",ticker)
|
424
383
|
return None
|
@@ -427,17 +386,8 @@ def get_financial_statements(ticker):
|
|
427
386
|
try:
|
428
387
|
fis = get_income_statements(ticker)
|
429
388
|
except:
|
430
|
-
print("
|
431
|
-
|
432
|
-
try:
|
433
|
-
fis = get_income_statements(ticker)
|
434
|
-
except:
|
435
|
-
sleep_random(max_sleep=60)
|
436
|
-
try:
|
437
|
-
fis = get_income_statements(ticker)
|
438
|
-
except:
|
439
|
-
print(" #Error(get_financial_statements): income info not available for",ticker)
|
440
|
-
return None
|
389
|
+
print(" #Error(get_financial_statements): income info not available for",ticker)
|
390
|
+
return None
|
441
391
|
if fis is None:
|
442
392
|
print(" #Error(get_financial_statements): financial statements not available for",ticker)
|
443
393
|
return None
|
@@ -446,17 +396,8 @@ def get_financial_statements(ticker):
|
|
446
396
|
try:
|
447
397
|
fcf = get_cashflow_statements(ticker)
|
448
398
|
except:
|
449
|
-
print("
|
450
|
-
|
451
|
-
try:
|
452
|
-
fcf = get_cashflow_statements(ticker)
|
453
|
-
except:
|
454
|
-
sleep_random(max_sleep=60)
|
455
|
-
try:
|
456
|
-
fcf = get_cashflow_statements(ticker)
|
457
|
-
except:
|
458
|
-
print(" #Error(get_financial_statements): cash flow info not available for",ticker)
|
459
|
-
return None
|
399
|
+
print(" #Error(get_financial_statements): cash flow info not available for",ticker)
|
400
|
+
return None
|
460
401
|
if fcf is None:
|
461
402
|
print(" #Error(get_financial_statements): financial statements not available for",ticker)
|
462
403
|
return None
|
siat/financials.py
CHANGED
@@ -1991,6 +1991,7 @@ if __name__=='__main__':
|
|
1991
1991
|
|
1992
1992
|
def compare_dupont(tickerlist,fsdate='latest', \
|
1993
1993
|
sort='PM',facecolor='whitesmoke',font_size='16px', \
|
1994
|
+
loc1='best',retry=10, \
|
1994
1995
|
scale1 = 10,scale2 = 10,hatchlist=['.', 'o', '\\']):
|
1995
1996
|
"""
|
1996
1997
|
功能:获得tickerlist中每只股票的杜邦分析项目,绘制柱状叠加比较图
|
@@ -2034,34 +2035,56 @@ def compare_dupont(tickerlist,fsdate='latest', \
|
|
2034
2035
|
dpidflist,dpilist,fsdatelist,fstypelist=[],[],[],[]
|
2035
2036
|
name1list,name2list,name3list,name4list,name5list,name6list=[],[],[],[],[],[]
|
2036
2037
|
newtickerlist=[]
|
2037
|
-
print("
|
2038
|
+
print("Working on DuPont factsheet, it takes a very long time, take a breather ...")
|
2039
|
+
|
2040
|
+
#第1次尝试
|
2041
|
+
faillist=[]
|
2038
2042
|
for t in tickerlist:
|
2039
2043
|
try:
|
2040
2044
|
with HiddenPrints():
|
2041
2045
|
dpidf=calc_dupont(t)
|
2042
2046
|
except:
|
2043
|
-
print(" #Warning(compare_dupont):
|
2047
|
+
print(" #Warning(compare_dupont): found errors in accounting items, ignore",t)
|
2044
2048
|
continue
|
2045
2049
|
|
2046
2050
|
#未出错,但未抓取到数据,再试
|
2047
|
-
if dpidf is None:
|
2048
|
-
|
2049
|
-
sleep_random(max_sleep=30)
|
2050
|
-
|
2051
|
-
dpidf=calc_dupont(t)
|
2052
|
-
|
2053
|
-
if dpidf is None: continue
|
2051
|
+
if dpidf is None:
|
2052
|
+
faillist=faillist+[t]
|
2053
|
+
#sleep_random(max_sleep=30)
|
2054
|
+
continue
|
2054
2055
|
|
2055
2056
|
if fsdate == 'latest':
|
2056
2057
|
try:
|
2057
2058
|
dpi=dpidf.tail(1)
|
2058
2059
|
except:
|
2059
|
-
print(" #Warning(compare_dupont): got empty data for"
|
2060
|
+
print(f" #Warning(compare_dupont): got empty data for {t} @ {fsdate} financials")
|
2061
|
+
faillist=faillist+[t]
|
2062
|
+
#sleep_random(max_sleep=30)
|
2063
|
+
continue
|
2064
|
+
elif fsdate == 'annual':
|
2065
|
+
dpidf_tmp=dpidf[dpidf['periodType']=="12M"]
|
2066
|
+
try:
|
2067
|
+
dpi=dpidf_tmp.tail(1)
|
2068
|
+
except:
|
2069
|
+
print(f" #Warning(compare_dupont): got empty data for {t} @ {fsdate} financials")
|
2070
|
+
faillist=faillist+[t]
|
2071
|
+
#sleep_random(max_sleep=30)
|
2072
|
+
continue
|
2073
|
+
|
2074
|
+
elif fsdate == 'quarterly':
|
2075
|
+
dpidf_tmp=dpidf[dpidf['periodType']=="3M"]
|
2076
|
+
try:
|
2077
|
+
dpi=dpidf_tmp.tail(1)
|
2078
|
+
except:
|
2079
|
+
print(f" #Warning(compare_dupont): got empty data for {t} @ {fsdate} financials")
|
2080
|
+
faillist=faillist+[t]
|
2081
|
+
#sleep_random(max_sleep=30)
|
2060
2082
|
continue
|
2061
|
-
|
2062
2083
|
else: dpi=dpidf[dpidf['endDate']==fsdate]
|
2063
2084
|
if len(dpi) == 0:
|
2064
|
-
print(" #Warning(compare_dupont):
|
2085
|
+
print(" #Warning(compare_dupont): financial statements not found for",t,'@',fsdate)
|
2086
|
+
faillist=faillist+[t]
|
2087
|
+
#sleep_random(max_sleep=30)
|
2065
2088
|
continue
|
2066
2089
|
|
2067
2090
|
newtickerlist=newtickerlist+[t]
|
@@ -2078,7 +2101,84 @@ def compare_dupont(tickerlist,fsdate='latest', \
|
|
2078
2101
|
name6list=name6list+[dpi['periodType'][0]]
|
2079
2102
|
|
2080
2103
|
#显示进度
|
2081
|
-
print_progress_percent2(t,tickerlist,steps=5,leading_blanks=4)
|
2104
|
+
#print_progress_percent2(t,tickerlist,steps=5,leading_blanks=4)
|
2105
|
+
print(f" *** Successfully obtained financial information for {t}")
|
2106
|
+
|
2107
|
+
#第2次尝试
|
2108
|
+
for i in range(retry):
|
2109
|
+
if len(faillist) == 0: break
|
2110
|
+
|
2111
|
+
tickerlist=faillist
|
2112
|
+
faillist=[]
|
2113
|
+
|
2114
|
+
for t in tickerlist:
|
2115
|
+
try:
|
2116
|
+
with HiddenPrints():
|
2117
|
+
dpidf=calc_dupont(t)
|
2118
|
+
except:
|
2119
|
+
print(" #Warning(compare_dupont): found errors in accounting items, ignore",t)
|
2120
|
+
continue
|
2121
|
+
|
2122
|
+
#未出错,但未抓取到数据,再试
|
2123
|
+
if dpidf is None:
|
2124
|
+
faillist=faillist+[t]
|
2125
|
+
#sleep_random(max_sleep=30)
|
2126
|
+
continue
|
2127
|
+
|
2128
|
+
if fsdate == 'latest':
|
2129
|
+
try:
|
2130
|
+
dpi=dpidf.tail(1)
|
2131
|
+
except:
|
2132
|
+
print(f" #Warning(compare_dupont): got empty data for {t} @ {fsdate} financials")
|
2133
|
+
faillist=faillist+[t]
|
2134
|
+
#sleep_random(max_sleep=30)
|
2135
|
+
continue
|
2136
|
+
elif fsdate == 'annual':
|
2137
|
+
dpidf_tmp=dpidf[dpidf['periodType']=="12M"]
|
2138
|
+
try:
|
2139
|
+
dpi=dpidf_tmp.tail(1)
|
2140
|
+
except:
|
2141
|
+
print(f" #Warning(compare_dupont): got empty data for {t} @ {fsdate} financials")
|
2142
|
+
faillist=faillist+[t]
|
2143
|
+
#sleep_random(max_sleep=30)
|
2144
|
+
continue
|
2145
|
+
|
2146
|
+
elif fsdate == 'quarterly':
|
2147
|
+
dpidf_tmp=dpidf[dpidf['periodType']=="3M"]
|
2148
|
+
try:
|
2149
|
+
dpi=dpidf_tmp.tail(1)
|
2150
|
+
except:
|
2151
|
+
print(f" #Warning(compare_dupont): got empty data for {t} @ {fsdate} financials")
|
2152
|
+
faillist=faillist+[t]
|
2153
|
+
#sleep_random(max_sleep=30)
|
2154
|
+
continue
|
2155
|
+
else: dpi=dpidf[dpidf['endDate']==fsdate]
|
2156
|
+
if len(dpi) == 0:
|
2157
|
+
print(" #Warning(compare_dupont): financial statements not found for",t,'@',fsdate)
|
2158
|
+
faillist=faillist+[t]
|
2159
|
+
#sleep_random(max_sleep=30)
|
2160
|
+
continue
|
2161
|
+
|
2162
|
+
newtickerlist=newtickerlist+[t]
|
2163
|
+
dpidflist=dpidflist+[dpidf]
|
2164
|
+
dpilist=dpilist+[dpi]
|
2165
|
+
fsdatelist=fsdatelist+[dpi['endDate'][0]]
|
2166
|
+
fstypelist=fstypelist+[dpi['periodType'][0]]
|
2167
|
+
|
2168
|
+
name1list=name1list+[dpi['Profit Margin'][0]*scale1]
|
2169
|
+
name2list=name2list+[dpi['Total Asset Turnover'][0]*scale2]
|
2170
|
+
name3list=name3list+[dpi['Equity Multiplier'][0]]
|
2171
|
+
name4list=name4list+[dpi['ROE'][0]]
|
2172
|
+
name5list=name5list+[dpi['endDate'][0]]
|
2173
|
+
name6list=name6list+[dpi['periodType'][0]]
|
2174
|
+
|
2175
|
+
#显示进度
|
2176
|
+
#print_progress_percent2(t,tickerlist,steps=5,leading_blanks=4)
|
2177
|
+
print(f" *** Successfully obtained financial information for {t}")
|
2178
|
+
|
2179
|
+
|
2180
|
+
if len(faillist) > 0:
|
2181
|
+
print(f" ~~~ Pity: failed to fetch financials for {faillist}")
|
2082
2182
|
|
2083
2183
|
tickerlist=newtickerlist
|
2084
2184
|
raw_data = {ticker:tickerlist,
|
@@ -2168,7 +2268,7 @@ def compare_dupont(tickerlist,fsdate='latest', \
|
|
2168
2268
|
footnote2=footnote1+'\n'+texttranslate("数据来源: 雅虎财经,")+' '+str(today)
|
2169
2269
|
plt.xlabel(footnote2,fontsize=xlabel_txt_size)
|
2170
2270
|
|
2171
|
-
plt.legend(loc=
|
2271
|
+
plt.legend(loc=loc1,fontsize=legend_txt_size)
|
2172
2272
|
if lang == 'Chinese':
|
2173
2273
|
plt.title("杜邦分析对比图"+sorttxt,fontsize=title_txt_size,fontweight='bold')
|
2174
2274
|
else:
|
siat/financials_china.py
CHANGED
@@ -692,7 +692,7 @@ def compare_dupont_china(tickerlist,fsdate='latest',scale1 = 10,scale2 = 10, \
|
|
692
692
|
可用的符号:'-', '+', 'x', '\\', '*', 'o', 'O', '.'
|
693
693
|
"""
|
694
694
|
error_flag=False
|
695
|
-
if fsdate
|
695
|
+
if fsdate in ['latest','annual','quarterly']:
|
696
696
|
import datetime as dt; end=str(dt.date.today())
|
697
697
|
start=date_adjust(end, adjust=-365)
|
698
698
|
else:
|
siat/fund_china.py
CHANGED
@@ -1754,9 +1754,10 @@ if __name__=='__main__':
|
|
1754
1754
|
|
1755
1755
|
#==============================================================================
|
1756
1756
|
if __name__=='__main__':
|
1757
|
-
|
1758
|
-
|
1759
|
-
|
1757
|
+
ticker='159922.SS'
|
1758
|
+
ticker='510580'
|
1759
|
+
start='2025-1-1'
|
1760
|
+
end='2025-5-30'
|
1760
1761
|
|
1761
1762
|
def etf_trend_china(ticker,start,end='today',indicator='净值',power=0, \
|
1762
1763
|
average_value=True,facecolor='whitesmoke', \
|
@@ -1765,7 +1766,7 @@ def etf_trend_china(ticker,start,end='today',indicator='净值',power=0, \
|
|
1765
1766
|
功能:ETF基金业绩趋势,单位净值,累计净值
|
1766
1767
|
"""
|
1767
1768
|
fund=ticker
|
1768
|
-
fromdate,todate=start_end_preprocess(start,end
|
1769
|
+
fromdate,todate=start_end_preprocess(start,end)
|
1769
1770
|
|
1770
1771
|
indicator_list=['净值','单位净值','累计净值']
|
1771
1772
|
if indicator not in indicator_list:
|
@@ -1789,7 +1790,7 @@ def etf_trend_china(ticker,start,end='today',indicator='净值',power=0, \
|
|
1789
1790
|
|
1790
1791
|
#获取基金数据
|
1791
1792
|
fund1=fund[:6]
|
1792
|
-
df =
|
1793
|
+
df = ak.fund_etf_fund_info_em(fund1)
|
1793
1794
|
df['date']=pd.to_datetime(df['净值日期'])
|
1794
1795
|
df.set_index(['date'],inplace=True)
|
1795
1796
|
df['单位净值']=df['单位净值'].astype("float")
|
siat/future_china.py
CHANGED
@@ -218,11 +218,14 @@ if __name__=='__main__':
|
|
218
218
|
end='2025-5-30'
|
219
219
|
power=1
|
220
220
|
|
221
|
-
def future_price_china(code,start,end
|
221
|
+
def future_price_china(code,start='MRM',end='today', \
|
222
|
+
power=0,loc1='upper left',loc2='upper right'):
|
222
223
|
"""
|
223
224
|
综合程序:
|
224
225
|
绘制内盘期货交易曲线:收盘价vs结算价vs成交量
|
225
226
|
"""
|
227
|
+
start,end=start_end_preprocess(start,end)
|
228
|
+
|
226
229
|
print("Searching for contract "+code+", it may take time ...")
|
227
230
|
#日期变换
|
228
231
|
start1=convert_date_ts(start)
|
@@ -482,11 +485,14 @@ if __name__=='__main__':
|
|
482
485
|
end='2021-9-27'
|
483
486
|
power=0
|
484
487
|
|
485
|
-
def future_price_foreign(code,start,end
|
488
|
+
def future_price_foreign(code,start='MRM',end='today', \
|
489
|
+
power=0,loc1='upper left',loc2='upper right'):
|
486
490
|
"""
|
487
491
|
综合程序:
|
488
492
|
绘制中国外盘期货的交易趋势:收盘价vs成交量
|
489
493
|
"""
|
494
|
+
start,end=start_end_preprocess(start,end)
|
495
|
+
|
490
496
|
print("Searching for contract "+code+", it costs great time, just take a break...")
|
491
497
|
#日期变换
|
492
498
|
flag,start1,end1=check_period(start,end)
|
siat/holding_risk.py
CHANGED
@@ -562,28 +562,29 @@ def get_VaR_portfolio(portfolio,today,future_days=1,alpha=0.99, \
|
|
562
562
|
if not printout: return VaRlist,ratiolist
|
563
563
|
|
564
564
|
#输出VaR金额和比率
|
565
|
-
print("\n=====
|
566
|
-
_,_,tickerlist,sharelist,ticker_type=decompose_portfolio(portfolio)
|
567
|
-
print("成分股列表 :",tickerlist)
|
568
|
-
print("成分股的配置:",sharelist)
|
569
|
-
print("
|
570
|
-
print("
|
571
|
-
print("
|
572
|
-
print("
|
573
|
-
print("
|
574
|
-
print("
|
565
|
+
print("\n===== 在险价值VaR:投资组合 =====")
|
566
|
+
#_,_,tickerlist,sharelist,ticker_type=decompose_portfolio(portfolio)
|
567
|
+
#print("成分股列表 :",tickerlist)
|
568
|
+
#print("成分股的配置:",sharelist)
|
569
|
+
print("投资组合:",portfolio_name(portfolio))
|
570
|
+
print("当前日期:",today)
|
571
|
+
print("当前头寸(1份投资组合):",format(position,','))
|
572
|
+
print("预计持有天数:",future_days)
|
573
|
+
print("置信度水平:",str(int(alpha*100))+'%')
|
574
|
+
print("历史样本年数:",pastyears)
|
575
|
+
print("样本数量:",num)
|
575
576
|
|
576
577
|
import datetime as dt; today=dt.date.today()
|
577
|
-
footnote="
|
578
|
+
footnote="\n数据来源:新浪/stooq,"+str(today)
|
578
579
|
if not (modeltyp == 'all'):
|
579
|
-
print("
|
580
|
-
print("VaR
|
580
|
+
print("使用的模型:",model)
|
581
|
+
print("VaR金额/比率:",format(VaR,','), \
|
581
582
|
'\b,',str(round(VaR_ratio*100,2))+'%')
|
582
583
|
|
583
584
|
print(footnote)
|
584
585
|
return VaR,VaR_ratio
|
585
586
|
|
586
|
-
print("\
|
587
|
+
print("\n*** VaR金额/比率 ***")
|
587
588
|
modellist.pop()
|
588
589
|
for m in modellist:
|
589
590
|
pos=modellist.index(m)
|
@@ -687,27 +688,28 @@ def get_ES_portfolio(portfolio,today,future_days=1,alpha=0.99, \
|
|
687
688
|
|
688
689
|
#输出ES金额和比率
|
689
690
|
print("\n===== 投资组合的预期不足ES =====")
|
690
|
-
_,_,tickerlist,sharelist,ticker_type=decompose_portfolio(portfolio)
|
691
|
-
print("成分股列表 :",tickerlist)
|
692
|
-
print("成分股配置 :",sharelist)
|
693
|
-
print("
|
694
|
-
print("
|
695
|
-
print("
|
696
|
-
print("
|
697
|
-
print("
|
698
|
-
print("
|
691
|
+
#_,_,tickerlist,sharelist,ticker_type=decompose_portfolio(portfolio)
|
692
|
+
#print("成分股列表 :",tickerlist)
|
693
|
+
#print("成分股配置 :",sharelist)
|
694
|
+
print("投资组合:",portfolio_name(portfolio))
|
695
|
+
print("当前日期:",today)
|
696
|
+
print("当前头寸(1份投资组合):",format(position,','))
|
697
|
+
print("预计持有天数:",future_days)
|
698
|
+
print("置信度水平:",str(int(alpha*100))+'%')
|
699
|
+
print("历史样本年数:",pastyears)
|
700
|
+
print("样本个数:",num)
|
699
701
|
|
700
702
|
import datetime as dt; today=dt.date.today()
|
701
|
-
footnote="
|
703
|
+
footnote="\n数据来源:新浪/stooq,"+str(today)
|
702
704
|
|
703
705
|
if not (modeltyp == 'all'):
|
704
|
-
print("
|
705
|
-
print("ES
|
706
|
+
print("使用的模型:",model)
|
707
|
+
print("ES金额/比率:",format(ES,','), \
|
706
708
|
'\b,',str(round(ES_ratio*100,2))+'%')
|
707
709
|
print(footnote)
|
708
710
|
return ES,ES_ratio
|
709
711
|
|
710
|
-
print("ES
|
712
|
+
print("ES金额/比率:")
|
711
713
|
modellist.pop()
|
712
714
|
for m in modellist:
|
713
715
|
pos=modellist.index(m)
|
@@ -799,13 +801,15 @@ if __name__ == '__main__':
|
|
799
801
|
fromdate='2022-1-1'
|
800
802
|
todate='2022-4-18'
|
801
803
|
|
802
|
-
def portfolio_rets_curve(portfolio,
|
804
|
+
def portfolio_rets_curve(portfolio,start='MRY',end='today'):
|
803
805
|
"""
|
804
806
|
功能:绘制投资组合portfolio在给定期间(fromdate,todate)收益率分布的曲线,
|
805
807
|
并于相应的正态分布图对照
|
806
808
|
显示:收益率分布的直方图(实线),相应的正态分布图(虚线)
|
807
809
|
x轴为收益率(非百分比),y轴为频度(Frequency)
|
808
810
|
"""
|
811
|
+
fromdate,todate=start_end_preprocess(start,end)
|
812
|
+
|
809
813
|
#抓取投资组合股价和收益率
|
810
814
|
prices=get_portfolio_prices0(portfolio,fromdate,todate)
|
811
815
|
if prices is None: return None,None
|
@@ -833,22 +837,25 @@ def portfolio_rets_curve(portfolio,fromdate,todate):
|
|
833
837
|
#plt.ylabel('Frequency')
|
834
838
|
|
835
839
|
footnote1='日收益率%'
|
836
|
-
footnote2='\
|
837
|
-
footnote3="
|
840
|
+
footnote2='\n【注】Shapiro-Wilk检验:W值'+str(W)+',p值'+str(p_value)
|
841
|
+
footnote3="。偏度"+str(S)+",峰度"+str(K)
|
838
842
|
|
839
843
|
import datetime as dt; today=dt.date.today()
|
840
|
-
footnote4="
|
844
|
+
footnote4="。数据来源:新浪/stooq,"+str(today)
|
841
845
|
|
842
846
|
footnote=footnote1+footnote2+footnote3+footnote4
|
843
847
|
plt.xlabel(footnote)
|
844
848
|
|
845
849
|
plt.legend(loc='best')
|
850
|
+
"""
|
846
851
|
titletxt1="投资组合收益率的正态分布检验"
|
847
852
|
titletxt2="\n成分股"+str(tickerlist)
|
848
853
|
titletxt3="\n持仓配置"+str(sharelist)
|
849
854
|
titletxt4="\n样本期间:"+str(fromdate)+'至'+str(todate)+ \
|
850
855
|
',样本数量'+str(num)+'个'
|
851
856
|
titletxt=titletxt1+titletxt2+titletxt3+titletxt4
|
857
|
+
"""
|
858
|
+
titletxt="投资组合收益率的正态分布检验:"+portfolio_name(portfolio)
|
852
859
|
plt.title(titletxt)
|
853
860
|
|
854
861
|
plt.gca().set_facecolor('whitesmoke')
|
siat/market_china.py
CHANGED
@@ -123,11 +123,13 @@ def market_profile_china(market='SSE'):
|
|
123
123
|
if lang == 'Chinese':
|
124
124
|
i2=itemlist2[pos]
|
125
125
|
blanknum=maxlen-hzlen(i2)
|
126
|
-
print(' ',i2+' '*blanknum+':',end='')
|
126
|
+
#print(' ',i2+' '*blanknum+':',end='')
|
127
|
+
print(' ',i2+':',end='')
|
127
128
|
else:
|
128
129
|
i2e=itemlist2e[pos]
|
129
130
|
blanknum=maxlen-hzlen(i2e)
|
130
|
-
print(' ',i2e+' '*blanknum+':',end='')
|
131
|
+
#print(' ',i2e+' '*blanknum+':',end='')
|
132
|
+
print(' ',i2e+':',end='')
|
131
133
|
except:
|
132
134
|
pos=itemlist.index(i)
|
133
135
|
i2=itemlist2[pos]
|
@@ -136,10 +138,12 @@ def market_profile_china(market='SSE'):
|
|
136
138
|
|
137
139
|
if lang == 'Chinese':
|
138
140
|
blanknum=maxlen-hzlen(i2)
|
139
|
-
print(' ',i2+' '*blanknum+':',end='')
|
141
|
+
#print(' ',i2+' '*blanknum+':',end='')
|
142
|
+
print(' ',i2+':',end='')
|
140
143
|
else:
|
141
144
|
blanknum=maxlen-hzlen(i2e)
|
142
|
-
print(' ',i2e+' '*blanknum+':',end='')
|
145
|
+
#print(' ',i2e+' '*blanknum+':',end='')
|
146
|
+
print(' ',i2e+':',end='')
|
143
147
|
|
144
148
|
if i in ["上市股票",'上市公司']: #若是字符则转换成数字
|
145
149
|
value2=int(value)
|
@@ -231,11 +235,13 @@ def market_profile_china(market='SSE'):
|
|
231
235
|
if lang == 'Chinese':
|
232
236
|
i2=itemlist2[pos]
|
233
237
|
blanknum=maxlen-hzlen(i2)
|
234
|
-
print(' ',i2+' '*blanknum+':',end='')
|
238
|
+
#print(' ',i2+' '*blanknum+':',end='')
|
239
|
+
print(' ',i2+':',end='')
|
235
240
|
else:
|
236
241
|
i2e=itemlist2e[pos]
|
237
242
|
blanknum=maxlen-hzlen(i2e)
|
238
|
-
print(' ',i2e+' '*blanknum+':',end='')
|
243
|
+
#print(' ',i2e+' '*blanknum+':',end='')
|
244
|
+
print(' ',i2e+':',end='')
|
239
245
|
except:
|
240
246
|
pos=itemlist.index(i)
|
241
247
|
i2=itemlist2[pos]
|
@@ -244,10 +250,12 @@ def market_profile_china(market='SSE'):
|
|
244
250
|
|
245
251
|
if lang == 'Chinese':
|
246
252
|
blanknum=maxlen-hzlen(i2)
|
247
|
-
print(' ',i2+' '*blanknum+':',end='')
|
253
|
+
#print(' ',i2+' '*blanknum+':',end='')
|
254
|
+
print(' ',i2+':',end='')
|
248
255
|
else:
|
249
256
|
blanknum=maxlen-hzlen(i2e)
|
250
|
-
print(' ',i2e+' '*blanknum+':',end='')
|
257
|
+
#print(' ',i2e+' '*blanknum+':',end='')
|
258
|
+
print(' ',i2e+':',end='')
|
251
259
|
|
252
260
|
if i in ['数量']: #若是字符则转换成数字
|
253
261
|
value2=int(value)
|
@@ -354,11 +362,13 @@ def market_profile_china_tmp(market='SSE'):
|
|
354
362
|
value=list(subdf[subdf['item']==i]['number'])[0]
|
355
363
|
|
356
364
|
if lang == 'Chinese':
|
357
|
-
print(' ',i+' '*blanknum+':',end='')
|
365
|
+
#print(' ',i+' '*blanknum+':',end='')
|
366
|
+
print(' ',i+':',end='')
|
358
367
|
else:
|
359
368
|
pos=itemlist.index(i)
|
360
369
|
ie=itemliste[pos]
|
361
|
-
print(' ',ie+' '*blanknum+':',end='')
|
370
|
+
#print(' ',ie+' '*blanknum+':',end='')
|
371
|
+
print(' ',ie+':',end='')
|
362
372
|
|
363
373
|
print("{:,}".format(value))
|
364
374
|
|