siat 3.10.132__py3-none-any.whl → 3.10.133__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.
Files changed (218) hide show
  1. siat/__init__.py +0 -0
  2. siat/allin.py +0 -0
  3. siat/assets_liquidity.py +0 -0
  4. siat/beta_adjustment.py +0 -0
  5. siat/beta_adjustment_china.py +0 -0
  6. siat/blockchain.py +0 -0
  7. siat/bond.py +0 -0
  8. siat/bond_base.py +0 -0
  9. siat/bond_china.py +0 -0
  10. siat/bond_zh_sina.py +0 -0
  11. siat/capm_beta.py +0 -0
  12. siat/capm_beta2.py +0 -0
  13. siat/compare_cross.py +0 -0
  14. siat/copyrights.py +0 -0
  15. siat/cryptocurrency.py +0 -0
  16. siat/economy.py +0 -0
  17. siat/economy2.py +0 -0
  18. siat/esg.py +0 -0
  19. siat/event_study.py +0 -0
  20. siat/exchange_bond_china.pickle +0 -0
  21. siat/fama_french.py +0 -0
  22. siat/fin_stmt2_yahoo.py +0 -0
  23. siat/financial_base.py +0 -0
  24. siat/financial_statements.py +0 -0
  25. siat/financials.py +0 -0
  26. siat/financials2.py +0 -0
  27. siat/financials_china.py +0 -0
  28. siat/financials_china2.py +0 -0
  29. siat/fund.py +0 -0
  30. siat/fund_china.pickle +0 -0
  31. siat/fund_china.py +0 -0
  32. siat/future_china.py +0 -0
  33. siat/google_authenticator.py +0 -0
  34. siat/grafix.py +0 -0
  35. siat/holding_risk.py +0 -0
  36. siat/luchy_draw.py +0 -0
  37. siat/market_china.py +0 -0
  38. siat/markowitz.py +0 -0
  39. siat/markowitz2.py +0 -0
  40. siat/markowitz2_20250704.py +0 -0
  41. siat/markowitz2_20250705.py +0 -0
  42. siat/markowitz_simple.py +0 -0
  43. siat/ml_cases.py +0 -0
  44. siat/ml_cases_example.py +0 -0
  45. siat/option_china.py +0 -0
  46. siat/option_pricing.py +0 -0
  47. siat/other_indexes.py +0 -0
  48. siat/risk_adjusted_return.py +0 -0
  49. siat/risk_adjusted_return2.py +0 -0
  50. siat/risk_evaluation.py +0 -0
  51. siat/risk_free_rate.py +0 -0
  52. siat/sector_china.py +0 -0
  53. siat/security_price2.py +0 -0
  54. siat/security_prices.py +40 -2
  55. siat/security_trend.py +0 -0
  56. siat/security_trend2.py +0 -0
  57. siat/stock.py +0 -0
  58. siat/stock_advice_linear.py +0 -0
  59. siat/stock_base.py +0 -0
  60. siat/stock_china.py +0 -0
  61. siat/stock_info.pickle +0 -0
  62. siat/stock_prices_kneighbors.py +0 -0
  63. siat/stock_prices_linear.py +0 -0
  64. siat/stock_profile.py +0 -0
  65. siat/stock_technical.py +0 -0
  66. siat/stooq.py +0 -0
  67. siat/transaction.py +0 -0
  68. siat/translate.py +0 -0
  69. siat/valuation.py +0 -0
  70. siat/valuation_china.py +0 -0
  71. siat/var_model_validation.py +0 -0
  72. siat/yf_name.py +0 -0
  73. {siat-3.10.132.dist-info/licenses → siat-3.10.133.dist-info}/LICENSE +0 -0
  74. {siat-3.10.132.dist-info → siat-3.10.133.dist-info}/METADATA +232 -235
  75. siat-3.10.133.dist-info/RECORD +78 -0
  76. {siat-3.10.132.dist-info → siat-3.10.133.dist-info}/WHEEL +1 -1
  77. {siat-3.10.132.dist-info → siat-3.10.133.dist-info}/top_level.txt +0 -1
  78. build/lib/build/lib/siat/__init__.py +0 -75
  79. build/lib/build/lib/siat/allin.py +0 -137
  80. build/lib/build/lib/siat/assets_liquidity.py +0 -915
  81. build/lib/build/lib/siat/beta_adjustment.py +0 -1058
  82. build/lib/build/lib/siat/beta_adjustment_china.py +0 -548
  83. build/lib/build/lib/siat/blockchain.py +0 -143
  84. build/lib/build/lib/siat/bond.py +0 -2900
  85. build/lib/build/lib/siat/bond_base.py +0 -992
  86. build/lib/build/lib/siat/bond_china.py +0 -100
  87. build/lib/build/lib/siat/bond_zh_sina.py +0 -143
  88. build/lib/build/lib/siat/capm_beta.py +0 -783
  89. build/lib/build/lib/siat/capm_beta2.py +0 -887
  90. build/lib/build/lib/siat/common.py +0 -5360
  91. build/lib/build/lib/siat/compare_cross.py +0 -642
  92. build/lib/build/lib/siat/copyrights.py +0 -18
  93. build/lib/build/lib/siat/cryptocurrency.py +0 -667
  94. build/lib/build/lib/siat/economy.py +0 -1471
  95. build/lib/build/lib/siat/economy2.py +0 -1853
  96. build/lib/build/lib/siat/esg.py +0 -536
  97. build/lib/build/lib/siat/event_study.py +0 -815
  98. build/lib/build/lib/siat/fama_french.py +0 -1521
  99. build/lib/build/lib/siat/fin_stmt2_yahoo.py +0 -982
  100. build/lib/build/lib/siat/financial_base.py +0 -1160
  101. build/lib/build/lib/siat/financial_statements.py +0 -598
  102. build/lib/build/lib/siat/financials.py +0 -2339
  103. build/lib/build/lib/siat/financials2.py +0 -1278
  104. build/lib/build/lib/siat/financials_china.py +0 -4433
  105. build/lib/build/lib/siat/financials_china2.py +0 -2212
  106. build/lib/build/lib/siat/fund.py +0 -629
  107. build/lib/build/lib/siat/fund_china.py +0 -3307
  108. build/lib/build/lib/siat/future_china.py +0 -551
  109. build/lib/build/lib/siat/google_authenticator.py +0 -47
  110. build/lib/build/lib/siat/grafix.py +0 -3636
  111. build/lib/build/lib/siat/holding_risk.py +0 -867
  112. build/lib/build/lib/siat/luchy_draw.py +0 -638
  113. build/lib/build/lib/siat/market_china.py +0 -1168
  114. build/lib/build/lib/siat/markowitz.py +0 -2363
  115. build/lib/build/lib/siat/markowitz2.py +0 -3150
  116. build/lib/build/lib/siat/markowitz2_20250704.py +0 -2969
  117. build/lib/build/lib/siat/markowitz2_20250705.py +0 -3158
  118. build/lib/build/lib/siat/markowitz_simple.py +0 -373
  119. build/lib/build/lib/siat/ml_cases.py +0 -2291
  120. build/lib/build/lib/siat/ml_cases_example.py +0 -60
  121. build/lib/build/lib/siat/option_china.py +0 -3069
  122. build/lib/build/lib/siat/option_pricing.py +0 -1925
  123. build/lib/build/lib/siat/other_indexes.py +0 -409
  124. build/lib/build/lib/siat/risk_adjusted_return.py +0 -1576
  125. build/lib/build/lib/siat/risk_adjusted_return2.py +0 -1900
  126. build/lib/build/lib/siat/risk_evaluation.py +0 -2218
  127. build/lib/build/lib/siat/risk_free_rate.py +0 -351
  128. build/lib/build/lib/siat/sector_china.py +0 -4140
  129. build/lib/build/lib/siat/security_price2.py +0 -727
  130. build/lib/build/lib/siat/security_prices.py +0 -3408
  131. build/lib/build/lib/siat/security_trend.py +0 -402
  132. build/lib/build/lib/siat/security_trend2.py +0 -646
  133. build/lib/build/lib/siat/stock.py +0 -4284
  134. build/lib/build/lib/siat/stock_advice_linear.py +0 -934
  135. build/lib/build/lib/siat/stock_base.py +0 -26
  136. build/lib/build/lib/siat/stock_china.py +0 -2095
  137. build/lib/build/lib/siat/stock_prices_kneighbors.py +0 -910
  138. build/lib/build/lib/siat/stock_prices_linear.py +0 -386
  139. build/lib/build/lib/siat/stock_profile.py +0 -707
  140. build/lib/build/lib/siat/stock_technical.py +0 -3305
  141. build/lib/build/lib/siat/stooq.py +0 -74
  142. build/lib/build/lib/siat/transaction.py +0 -347
  143. build/lib/build/lib/siat/translate.py +0 -5183
  144. build/lib/build/lib/siat/valuation.py +0 -1378
  145. build/lib/build/lib/siat/valuation_china.py +0 -2076
  146. build/lib/build/lib/siat/var_model_validation.py +0 -444
  147. build/lib/build/lib/siat/yf_name.py +0 -811
  148. build/lib/siat/__init__.py +0 -75
  149. build/lib/siat/allin.py +0 -137
  150. build/lib/siat/assets_liquidity.py +0 -915
  151. build/lib/siat/beta_adjustment.py +0 -1058
  152. build/lib/siat/beta_adjustment_china.py +0 -548
  153. build/lib/siat/blockchain.py +0 -143
  154. build/lib/siat/bond.py +0 -2900
  155. build/lib/siat/bond_base.py +0 -992
  156. build/lib/siat/bond_china.py +0 -100
  157. build/lib/siat/bond_zh_sina.py +0 -143
  158. build/lib/siat/capm_beta.py +0 -783
  159. build/lib/siat/capm_beta2.py +0 -887
  160. build/lib/siat/common.py +0 -5360
  161. build/lib/siat/compare_cross.py +0 -642
  162. build/lib/siat/copyrights.py +0 -18
  163. build/lib/siat/cryptocurrency.py +0 -667
  164. build/lib/siat/economy.py +0 -1471
  165. build/lib/siat/economy2.py +0 -1853
  166. build/lib/siat/esg.py +0 -536
  167. build/lib/siat/event_study.py +0 -815
  168. build/lib/siat/fama_french.py +0 -1521
  169. build/lib/siat/fin_stmt2_yahoo.py +0 -982
  170. build/lib/siat/financial_base.py +0 -1160
  171. build/lib/siat/financial_statements.py +0 -598
  172. build/lib/siat/financials.py +0 -2339
  173. build/lib/siat/financials2.py +0 -1278
  174. build/lib/siat/financials_china.py +0 -4433
  175. build/lib/siat/financials_china2.py +0 -2212
  176. build/lib/siat/fund.py +0 -629
  177. build/lib/siat/fund_china.py +0 -3307
  178. build/lib/siat/future_china.py +0 -551
  179. build/lib/siat/google_authenticator.py +0 -47
  180. build/lib/siat/grafix.py +0 -3636
  181. build/lib/siat/holding_risk.py +0 -867
  182. build/lib/siat/luchy_draw.py +0 -638
  183. build/lib/siat/market_china.py +0 -1168
  184. build/lib/siat/markowitz.py +0 -2363
  185. build/lib/siat/markowitz2.py +0 -3150
  186. build/lib/siat/markowitz2_20250704.py +0 -2969
  187. build/lib/siat/markowitz2_20250705.py +0 -3158
  188. build/lib/siat/markowitz_simple.py +0 -373
  189. build/lib/siat/ml_cases.py +0 -2291
  190. build/lib/siat/ml_cases_example.py +0 -60
  191. build/lib/siat/option_china.py +0 -3069
  192. build/lib/siat/option_pricing.py +0 -1925
  193. build/lib/siat/other_indexes.py +0 -409
  194. build/lib/siat/risk_adjusted_return.py +0 -1576
  195. build/lib/siat/risk_adjusted_return2.py +0 -1900
  196. build/lib/siat/risk_evaluation.py +0 -2218
  197. build/lib/siat/risk_free_rate.py +0 -351
  198. build/lib/siat/sector_china.py +0 -4140
  199. build/lib/siat/security_price2.py +0 -727
  200. build/lib/siat/security_prices.py +0 -3408
  201. build/lib/siat/security_trend.py +0 -402
  202. build/lib/siat/security_trend2.py +0 -646
  203. build/lib/siat/stock.py +0 -4284
  204. build/lib/siat/stock_advice_linear.py +0 -934
  205. build/lib/siat/stock_base.py +0 -26
  206. build/lib/siat/stock_china.py +0 -2095
  207. build/lib/siat/stock_prices_kneighbors.py +0 -910
  208. build/lib/siat/stock_prices_linear.py +0 -386
  209. build/lib/siat/stock_profile.py +0 -707
  210. build/lib/siat/stock_technical.py +0 -3305
  211. build/lib/siat/stooq.py +0 -74
  212. build/lib/siat/transaction.py +0 -347
  213. build/lib/siat/translate.py +0 -5183
  214. build/lib/siat/valuation.py +0 -1378
  215. build/lib/siat/valuation_china.py +0 -2076
  216. build/lib/siat/var_model_validation.py +0 -444
  217. build/lib/siat/yf_name.py +0 -811
  218. siat-3.10.132.dist-info/RECORD +0 -218
@@ -1,867 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- """
3
- 本模块功能:投资组合的VaR(在险价值)和ES(预期损失)分析
4
- 所属工具包:证券投资分析工具SIAT
5
- SIAT:Security Investment Analysis Tool
6
- 创建日期:2018年6月16日
7
- 最新修订日期:2020年7月23日
8
- 作者:王德宏 (WANG Dehong, Peter)
9
- 作者单位:北京外国语大学国际商学院
10
- 作者邮件:wdehong2000@163.com
11
- 版权所有:王德宏
12
- 用途限制:仅限研究与教学使用,不可商用!商用需要额外授权。
13
- 特别声明:作者不对使用本工具进行证券投资导致的任何损益负责!
14
- """
15
- #==============================================================================
16
- #统一屏蔽一般性警告
17
- import warnings; warnings.filterwarnings("ignore")
18
- from siat.common import *
19
- from siat.translate import *
20
- from siat.security_prices import *
21
- from siat.security_price2 import *
22
- #==============================================================================
23
- import matplotlib.pyplot as plt
24
-
25
- #处理绘图汉字乱码问题
26
- import sys; czxt=sys.platform
27
- if czxt in ['win32','win64']:
28
- plt.rcParams['font.sans-serif'] = ['SimHei'] # 设置默认字体
29
- mpfrc={'font.family': 'SimHei'}
30
-
31
- if czxt in ['darwin']: #MacOSX
32
- plt.rcParams['font.family']= ['Heiti TC']
33
- mpfrc={'font.family': 'Heiti TC'}
34
-
35
- if czxt in ['linux']: #website Jupyter
36
- plt.rcParams['font.family']= ['Heiti TC']
37
- mpfrc={'font.family':'Heiti TC'}
38
-
39
- # 解决保存图像时'-'显示为方块的问题
40
- plt.rcParams['axes.unicode_minus'] = False
41
- #==============================================================================
42
- #统一设定绘制的图片大小:数值为英寸,1英寸=100像素
43
- #plt.rcParams['figure.figsize']=(12.8,7.2)
44
- plt.rcParams['figure.figsize']=(12.8,6.4)
45
- plt.rcParams['figure.dpi']=300
46
- plt.rcParams['font.size'] = 13
47
- plt.rcParams['xtick.labelsize']=11 #横轴字体大小
48
- plt.rcParams['ytick.labelsize']=11 #纵轴字体大小
49
-
50
- title_txt_size=16
51
- ylabel_txt_size=14
52
- xlabel_txt_size=14
53
- legend_txt_size=14
54
-
55
- #设置绘图风格:网格虚线
56
- plt.rcParams['axes.grid']=True
57
- #plt.rcParams['grid.color']='steelblue'
58
- #plt.rcParams['grid.linestyle']='dashed'
59
- #plt.rcParams['grid.linewidth']=0.5
60
- #plt.rcParams['axes.facecolor']='whitesmoke'
61
-
62
- #==============================================================================
63
- import os, sys
64
- class HiddenPrints:
65
- def __enter__(self):
66
- self._original_stdout = sys.stdout
67
- sys.stdout = open(os.devnull, 'w')
68
-
69
- def __exit__(self, exc_type, exc_val, exc_tb):
70
- sys.stdout.close()
71
- sys.stdout = self._original_stdout
72
- #==============================================================================
73
-
74
- #==============================================================================
75
- if __name__ == '__main__':
76
- portfolio={'Market':('China','000001.SS'),'300782.SZ':1}
77
- fromdate='2022-1-1'
78
- todate='2022-4-18'
79
-
80
- def get_portfolio_prices0(portfolio,fromdate,todate):
81
- """
82
- 功能:抓取投资组合portfolio的每日价值
83
- 输入:投资组合portfolio,开始日期,结束日期
84
- fromdate: 样本开始日期。格式:'YYYY-MM-DD'
85
- todate: 样本结束日期。既可以是今天日期,也可以是一个历史日期
86
-
87
- 输出:投资组合的价格序列,按照日期升序排列
88
- """
89
-
90
- #解构投资组合
91
- _,mktidx,tickerlist,sharelist,ticker_type=decompose_portfolio(portfolio)
92
-
93
- #检查股票列表个数与份额列表个数是否一致
94
- if len(tickerlist) != len(sharelist):
95
- print("#Error(get_portfolio_prices0): numbers of stocks and shares mismatch.")
96
- return None
97
-
98
- #抓取股票价格
99
- p=get_prices(tickerlist,fromdate,todate)
100
- if p is None: return None
101
-
102
- import pandas as pd
103
- #计算投资组合的开盘价
104
- op=p[['Open']]
105
- #计算投资组合的价值
106
- oprice=pd.DataFrame(op.dot(sharelist))
107
- oprice.rename(columns={0: 'Open'}, inplace=True)
108
-
109
- #计算投资组合的收盘价
110
- cp=p[['Close']]
111
- #计算投资组合的价值
112
- cprice=pd.DataFrame(cp.dot(sharelist))
113
- cprice.rename(columns={0: 'Close'}, inplace=True)
114
-
115
- #计算投资组合的调整收盘价
116
- acp=p[['Adj Close']]
117
- #计算投资组合的价值
118
- acprice=pd.DataFrame(acp.dot(sharelist))
119
- acprice.rename(columns={0: 'Adj Close'}, inplace=True)
120
-
121
- #计算投资组合的交易量
122
- vol=p[['Volume']]
123
- #计算投资组合的价值
124
- pfvol=pd.DataFrame(vol.dot(sharelist))
125
- pfvol.rename(columns={0: 'Volume'}, inplace=True)
126
-
127
- #计算投资组合的交易金额
128
- if len(tickerlist)==1:
129
- p['Amount']=p['Close']*p['Volume']
130
- else:
131
- for t in tickerlist:
132
- p['Amount',t]=p['Close',t]*p['Volume',t]
133
- amt=p[['Amount']]
134
- #计算投资组合的价值
135
- pfamt=pd.DataFrame(amt.dot(sharelist))
136
- pfamt.rename(columns={0: 'Amount'}, inplace=True)
137
-
138
- #合成开盘价、收盘价、调整收盘价、交易量和交易金额
139
- pf1=pd.merge(oprice,cprice,how='inner',left_index=True,right_index=True)
140
- pf2=pd.merge(pf1,acprice,how='inner',left_index=True,right_index=True)
141
- pf3=pd.merge(pf2,pfvol,how='inner',left_index=True,right_index=True)
142
- pf4=pd.merge(pf3,pfamt,how='inner',left_index=True,right_index=True)
143
- pf4['Ret']=pf4['Close'].pct_change()
144
-
145
- #获得期间的市场收益率:假设无风险收益率非常小,可以忽略
146
- m=get_prices(mktidx,fromdate,todate)
147
- m['Mkt']=m['Close'].pct_change()
148
- rf_df=m[['Mkt']]
149
-
150
- #合并pf4与rf_df
151
- prices=pd.merge(pf4,rf_df,how='left',left_index=True,right_index=True)
152
-
153
- #提取日期和星期几
154
- prices['Date']=prices.index.strftime("%Y-%m-%d")
155
- prices['Weekday']=prices.index.weekday+1
156
-
157
- prices['Portfolio']=str(tickerlist)
158
- prices['Shares']=str(sharelist)
159
- prices['Adjustment']=prices.apply(lambda x: \
160
- False if x['Close']==x['Adj Close'] else True, axis=1)
161
-
162
- pfdf=prices[['Portfolio','Shares','Date','Weekday', \
163
- 'Open','Close','Adj Close','Adjustment', \
164
- 'Volume','Amount','Ret','Mkt']]
165
-
166
- #判断空值,控制空值可能引起的程序崩溃
167
- if pfdf is None:
168
- print("#Error(get_portfolio_prices0): failed to retrieve portfolio data")
169
- return None
170
- pfdf.dropna(inplace=True)
171
- if (pfdf is None) or (len(pfdf)==0):
172
- print("#Error(get_portfolio_prices0): failed to retrieve portfolio data")
173
- return None
174
-
175
- return pfdf
176
-
177
-
178
- #==============================================================================
179
- def calc_VaR_normal_standard(ret_series,future_days=1,alpha=0.99):
180
-
181
- """
182
- 功能:VaR算法之标准正态法
183
- 输入参数:收益率序列(非百分比),未来持有时间(天),置信度
184
- 输出参数:VaR比率,正数
185
- """
186
- #去掉空值
187
- r=ret_series[~ret_series.isnull()]
188
-
189
- import numpy as np
190
- from scipy import stats
191
-
192
- z=stats.norm.ppf(1-alpha)
193
-
194
- miu_daily=np.mean(r)
195
- miu_days=np.power(miu_daily+1,future_days)-1
196
-
197
- sigma_daily=np.std(r)
198
- sigma_days=np.sqrt(future_days)*sigma_daily
199
-
200
- VaR_ratio=abs(miu_days+z*sigma_days)
201
-
202
- return VaR_ratio
203
-
204
- #==============================================================================
205
- def calc_ES_normal_standard(ret_series,future_days=1,alpha=0.99):
206
- """
207
- 功能:计算ES,标准正态法
208
- 输入参数:收益率序列,未来持有日期,置信度
209
- 输出:ES比率,正数
210
- """
211
- #去掉空值
212
- r=ret_series[~ret_series.isnull()]
213
-
214
- import numpy as np
215
- from scipy import stats
216
-
217
- z=stats.norm.ppf(1-alpha)
218
- miu_daily=np.mean(r)
219
- miu_days=np.power(miu_daily+1,future_days)-1
220
-
221
- sigma_daily=np.std(r)
222
- sigma_days=np.sqrt(future_days)*sigma_daily
223
-
224
- zES=-stats.norm.pdf(z)/(1-alpha)
225
- ratio=abs(miu_days+zES*sigma_days)
226
-
227
- return ratio
228
-
229
- #==============================================================================
230
- def calc_VaR_normal_modified(ret_series,future_days=1,alpha=0.99):
231
- """
232
- 功能:VaR算法之修正正态法
233
- #输入参数:日收益率序列(非百分比),未来持有日期,置信度
234
- #输出参数:VaR比率,正数
235
- """
236
- #去掉空值
237
- r=ret_series[~ret_series.isnull()]
238
-
239
- from scipy import stats
240
- import numpy as np
241
-
242
- z=np.abs(stats.norm.ppf(1-alpha))
243
- S=stats.skew(r)
244
- K=stats.kurtosis(r)
245
-
246
- t1=1/6*(np.power(z,2)-1)*S
247
- t2=1/24*(np.power(z,3)-3*z)*K
248
- t3=1/36*(2*np.power(z,3)-5*z)*np.power(S,2)
249
- t=z+t1+t2-t3
250
-
251
- miu_daily=np.mean(r)
252
- miu_days=np.power(miu_daily+1,future_days)-1
253
- sigma_daily=np.std(r)
254
- sigma_days=np.sqrt(future_days)*sigma_daily
255
-
256
- ratio=abs(miu_days+t*sigma_days)
257
-
258
- return ratio
259
-
260
- #==============================================================================
261
- def calc_ES_normal_modified(ret_series,future_days=1,alpha=0.99):
262
- """
263
- 功能:ES算法之修正正态法
264
- #输入参数:日收益率序列(非百分比),未来持有日期,置信度
265
- #输出参数:ES比率,正数
266
- """
267
- #去掉空值
268
- r=ret_series[~ret_series.isnull()]
269
-
270
- from scipy import stats
271
- import numpy as np
272
-
273
- #计算替代z的t值
274
- z=np.abs(stats.norm.ppf(1-alpha))
275
- S=stats.skew(r)
276
- K=stats.kurtosis(r)
277
-
278
- t1=1/6*(np.power(z,2)-1)*S
279
- t2=1/24*(np.power(z,3)-3*z)*K
280
- t3=1/36*(2*np.power(z,3)-5*z)*np.power(S,2)
281
- t=z+t1+t2-t3
282
-
283
- miu_daily=np.mean(r)
284
- miu_days=np.power(miu_daily+1,future_days)-1
285
- sigma_daily=np.std(r)
286
- sigma_days=np.sqrt(future_days)*sigma_daily
287
-
288
- #使用t替代原来的z
289
- zES=-stats.norm.pdf(t)/(1-alpha)
290
- ratio=abs(miu_days+zES*sigma_days)
291
-
292
- return ratio
293
-
294
- #==============================================================================
295
- def get_grouped_rets(ret_series,groupsize=1):
296
- """
297
- 功能:给定收益率序列pfdf,按照组的大小,在pfdf内创建滚动分组,
298
- 计算每组组内的累计收益率,消除空值,返回组收益率序列
299
- """
300
- #测试用数据,测试后应注释掉
301
- """
302
- portfolio={'Market':('US','^GSPC'),'AAPL':0.5,'MSFT':0.3,'IBM':0.2}
303
- fromdate='2019-7-31'
304
- todate ='2019-8-31'
305
- groupsize=2
306
- #获得投资组合的收益率
307
- pfdf=get_portfolio_prices0(portfolio,fromdate,todate)
308
- import pandas as pd
309
- ret_series=pd.Series(pfdf['Ret'])
310
- """
311
-
312
- #定义组内累计收益率计算方法
313
- cumret=lambda x:(x+1.0).prod()-1.0
314
- #使用滚动窗口分组,计算各组收益率gret
315
- gret_series=ret_series.rolling(groupsize).apply(cumret)
316
- gret_series=gret_series[~gret_series.isnull()]
317
-
318
- #返回组收益率序列
319
- return gret_series
320
-
321
- #==============================================================================
322
- def calc_VaR_historical(ret_series,future_days=1,alpha=0.99):
323
- """
324
- 功能:VaR算法之历史模拟法
325
- 输入参数:历史日收益率序列,未来持有日期,置信度
326
- 输出:VaR比率,正数
327
- """
328
- #去掉空值
329
- r0=ret_series[~ret_series.isnull()]
330
- #按未来持有期间数计算分组收益率
331
- r=get_grouped_rets(r0,future_days)
332
-
333
- import numpy as np
334
- n=len(r)
335
- t=int(n*(1-alpha))
336
- SR=np.sort(r)
337
-
338
- if t>=1:
339
- A=SR[t-1] #SR的第一个元素的序号是0
340
- else:
341
- A=SR[0]
342
-
343
- VaR_ratio=abs(A)
344
-
345
- return VaR_ratio
346
-
347
- #==============================================================================
348
- def calc_ES_historical(ret_series,future_days=1,alpha=0.99):
349
- """
350
- 功能:ES算法之历史模拟法
351
- 输入参数:历史日收益率序列,未来持有日期,置信度
352
- 输出:ES比率,正数
353
- 要求:足够多的历史数据
354
- """
355
- #去掉空值
356
- r0=ret_series[~ret_series.isnull()]
357
- #按未来持有期间数计算分组收益率
358
- r=get_grouped_rets(r0,future_days)
359
-
360
- import numpy as np
361
- n=len(r)
362
- t=int(n*(1-alpha))
363
- SR=np.sort(r)
364
-
365
- if t>2:
366
- #SR中第t个元素是VaR,第0~(t-1)个元素的均值是ES
367
- #SR的第一个元素的序号是0
368
- A=np.mean(SR[0:(t-2)])
369
- else:
370
- A=SR[0]
371
-
372
- ratio=abs(A)
373
-
374
- return ratio
375
-
376
- if __name__ == '__main__':
377
- Market={'Market':('China','000001.SS')}
378
- Stocks={'300782.SZ':2,'300661.SZ':3,'688019.SS':4}
379
- portfolio=dict(Market,**Stocks)
380
- prices=get_portfolio_prices0(portfolio,'2019-7-20','2020-7-20')
381
- ret_series=prices['Ret']
382
- future_days=3
383
- alpha=0.99
384
-
385
- #==============================================================================
386
- def calc_VaR_montecarlo(ret_series,future_days=1,alpha=0.99, \
387
- random=10000,mctype='random'):
388
- """
389
- 功能:VaR算法之蒙特卡洛模拟法,持有多日
390
- 输入参数:历史日收益率序列,未来持有天数,置信度,重复模拟次数,模拟类型
391
- 注:重复模拟次数越多,准确率就越高,但耗时也越多
392
- 输出:持有多天的VaR(金额)
393
- """
394
- #去掉空值
395
- r=ret_series[~ret_series.isnull()]
396
-
397
- import pandas as pd
398
- import numpy as np
399
- #蒙特卡洛模拟类型:随机数or超采样
400
- if mctype=='random': #随机数产生新的序列
401
- #取得历史日收益率的均值和标准差
402
- miu=np.mean(r)
403
- sigma=np.std(r)
404
-
405
- #指定随机数种子
406
- np.random.seed(12345)
407
- #按照历史日收益率的均值和标准差重复模拟一定次数,生成新的日收益率序列
408
- RR=pd.Series(np.random.normal(miu,sigma,random))
409
- else: #超采样产生新的序列
410
- #将收益率序列转变为df
411
- r1=pd.DataFrame(r)
412
- r2=r1.sample(n=random,replace=True)
413
- r2.sort_index(inplace=True)
414
- RR=pd.Series(r2.iloc[:,0])
415
- """
416
- r1=np.random.choice(r,size=random,replace=True)
417
- RR=pd.Series(r1)
418
- """
419
-
420
- #基于新的日收益率序列,使用标准正态法计算VaR
421
- ratio=calc_VaR_normal_standard(RR,future_days,alpha)
422
- #ratio=calc_VaR_historical(RR,future_days,alpha)
423
-
424
- return ratio
425
-
426
- if __name__ == '__main__':
427
- random=1000
428
- mctype='oversampling'
429
-
430
- #==============================================================================
431
- def calc_ES_montecarlo(ret_series,future_days=1,alpha=0.99, \
432
- random=10000,mctype='random'):
433
- """
434
- 功能:ES算法之蒙特卡洛模拟法,持有多日
435
- 输入参数:历史日收益率序列,未来持有天数,置信度,重复模拟次数,模拟类型
436
- 注:重复模拟次数越多,准确率就越高,但耗时也越多
437
- 输出:持有多天的ES比率
438
- """
439
- #去掉空值
440
- r=ret_series[~ret_series.isnull()]
441
-
442
- import pandas as pd
443
- import numpy as np
444
- #蒙特卡洛模拟类型:随机数or超采样
445
- if mctype=='random': #随机数产生新的序列
446
- #取得历史日收益率的均值和标准差
447
- miu=np.mean(r)
448
- sigma=np.std(r)
449
-
450
- #指定随机数种子
451
- np.random.seed(12345)
452
- #按照历史日收益率的均值和标准差重复模拟一定次数,生成新的日收益率序列
453
- RR=pd.Series(np.random.normal(miu,sigma,random))
454
- else: #超采样产生新的序列
455
- #将收益率序列转变为df
456
- r1=pd.DataFrame(r)
457
- r2=r1.sample(n=random,replace=True)
458
- r2.sort_index(inplace=True)
459
- RR=pd.Series(r2.iloc[:,0])
460
- """
461
- r1=np.random.choice(r,size=random,replace=True)
462
- RR=pd.Series(r1)
463
- """
464
-
465
- #基于新的日收益率序列,使用标准正态法计算ES
466
- ratio=calc_ES_normal_standard(RR,future_days,alpha)
467
-
468
- return ratio
469
-
470
- #==============================================================================
471
- if __name__ == '__main__':
472
- portfolio={'Market':('China','000001.SS'),'000661.SZ':2,'603392.SS':3,'300601.SZ':4}
473
- today='2020-7-20'
474
- future_days=1
475
- alpha=0.99
476
- pastyears=1
477
- model='all'
478
- printout=True
479
-
480
-
481
- def get_VaR_portfolio(portfolio,today,future_days=1,alpha=0.99, \
482
- pastyears=1,model='normal_standard',printout=True):
483
- """
484
- 功能:基于指定模型model,计算投资组合portfolio的VaR金额和比率
485
- """
486
- print(" Start working on portfolio VaR, please wait ...")
487
-
488
- #检查model类型
489
- modellist=['normal_standard','normal_modified','historical','montecarlo', \
490
- 'mc_oversampling','all']
491
- modeltyp=model.lower()
492
- if modeltyp not in modellist:
493
- print(" #Error(get_VaR_portfolio): Unsupported type of model,",model)
494
- print(" Supported models:",modellist)
495
- return None,None
496
-
497
- #获得样本起始日期
498
- start=get_start_date(today,pastyears)
499
- if start is None: return None,None
500
-
501
- #抓取投资组合股价和收益率
502
- print(" Searching for portfolio prices from",start,'to',today)
503
- prices=get_portfolio_prices0(portfolio,start,today)
504
- #判断空值,控制空值可能引起的程序崩溃
505
- if prices is None:
506
- print(" #Error(get_VaR_portfolio): failed to retrieve portfolio prices")
507
- return None,None
508
-
509
- prices.dropna(inplace=True)
510
- if len(prices)==0:
511
- print(" #Error(get_VaR_portfolio): zero records found for the portfolio")
512
- return None,None
513
-
514
- num=len(prices)
515
- ret_series=prices['Ret']
516
-
517
- print(" Calculating portfolio VaR ...")
518
- #计算当日头寸
519
- position=round(prices['Close'][-1],2)
520
- VaRlist=[]; ratiolist=[]
521
- #标准正态法
522
- if modeltyp in ['normal_standard','all']:
523
- ratio=calc_VaR_normal_standard(ret_series,future_days,alpha)
524
- VaR=-round(position*ratio,2)
525
- VaRlist=VaRlist+[VaR]
526
- VaR_ratio=round(ratio,4)
527
- ratiolist=ratiolist+[VaR_ratio]
528
-
529
- #修正正态法
530
- if modeltyp in ['normal_modified','all']:
531
- ratio=calc_VaR_normal_modified(ret_series,future_days,alpha)
532
- VaR=-round(position*ratio,2)
533
- VaRlist=VaRlist+[VaR]
534
- VaR_ratio=round(ratio,4)
535
- ratiolist=ratiolist+[VaR_ratio]
536
-
537
- #历史模拟法
538
- if modeltyp in ['historical','all']:
539
- ratio=calc_VaR_historical(ret_series,future_days,alpha)
540
- VaR=-round(position*ratio,2)
541
- VaRlist=VaRlist+[VaR]
542
- VaR_ratio=round(ratio,4)
543
- ratiolist=ratiolist+[VaR_ratio]
544
-
545
- #蒙特卡洛模拟法,随机数,默认
546
- if modeltyp in ['montecarlo','all']:
547
- ratio=calc_VaR_montecarlo(ret_series,future_days,alpha,mctype='random')
548
- VaR=-round(position*ratio,2)
549
- VaRlist=VaRlist+[VaR]
550
- VaR_ratio=round(ratio,4)
551
- ratiolist=ratiolist+[VaR_ratio]
552
-
553
- #蒙特卡洛模拟法,超采样
554
- if modeltyp in ['mc_oversampling','all']:
555
- ratio=calc_VaR_montecarlo(ret_series,future_days,alpha, \
556
- mctype='mc_oversampling')
557
- VaR=-round(position*ratio,2)
558
- VaRlist=VaRlist+[VaR]
559
- VaR_ratio=round(ratio,4)
560
- ratiolist=ratiolist+[VaR_ratio]
561
-
562
- if not printout: return VaRlist,ratiolist
563
-
564
- #输出VaR金额和比率
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)
576
-
577
- import datetime as dt; today=dt.date.today()
578
- footnote="\n数据来源:新浪/stooq,"+str(today)
579
- if not (modeltyp == 'all'):
580
- print("使用的模型:",model)
581
- print("VaR金额/比率:",format(VaR,','), \
582
- '\b,',str(round(VaR_ratio*100,2))+'%')
583
-
584
- print(footnote)
585
- return VaR,VaR_ratio
586
-
587
- print("\n*** VaR金额/比率 ***")
588
- modellist.pop()
589
- for m in modellist:
590
- pos=modellist.index(m)
591
- v=VaRlist[pos]
592
- r=ratiolist[pos]
593
- print(" ",format(v,','),'\b,', \
594
- str(round(r*100,2))+'%'+' ('+m+')')
595
-
596
- print(footnote)
597
-
598
- return VaRlist,ratiolist
599
-
600
- if __name__ == '__main__':
601
- portfolio={'Market':('China','000001.SS'),'000661.SZ':1,'603392.SS':2, \
602
- '300601.SZ':3}
603
- today='2020-7-20'
604
- future_days=1
605
- alpha=0.99
606
- pastyears=1
607
- model='all'
608
- printout=True
609
-
610
- #==============================================================================
611
- def get_ES_portfolio(portfolio,today,future_days=1,alpha=0.99, \
612
- pastyears=1,model='normal_standard',printout=True):
613
- """
614
- 功能:基于指定模型model,计算投资组合portfolio的ES金额和比率
615
- """
616
-
617
- #检查model类型
618
- modellist=['normal_standard','normal_modified','historical','montecarlo', \
619
- 'mc_oversampling','all']
620
- modeltyp=model.lower()
621
- if modeltyp not in modellist:
622
- print("#Error(get_ES_portfolio): Unsupported type of model,",model)
623
- print("Supported models:",modellist)
624
- return None,None
625
-
626
- #获得样本起始日期
627
- start=get_start_date(today,pastyears)
628
- if start is None: return None,None
629
- #抓取投资组合股价和收益率
630
- prices=get_portfolio_prices0(portfolio,start,today)
631
- #判断空值,控制空值可能引起的程序崩溃
632
- if prices is None:
633
- print("#Error(get_ES_portfolio): failed to retrieve portfolio prices")
634
- return None,None
635
- prices.dropna(inplace=True)
636
- if (prices is None) or (len(prices)==0):
637
- print("#Error(get_ES_portfolio): failed to retrieve portfolio prices")
638
- return None,None
639
-
640
- num=len(prices)
641
- ret_series=prices['Ret']
642
-
643
- #计算当日头寸
644
- position=round(prices['Close'][-1],2)
645
- ESlist=[]; ratiolist=[]
646
- #标准正态法
647
- if modeltyp in ['normal_standard','all']:
648
- ratio=calc_ES_normal_standard(ret_series,future_days,alpha)
649
- ES=-round(position*ratio,2)
650
- ESlist=ESlist+[ES]
651
- ES_ratio=round(ratio,4)
652
- ratiolist=ratiolist+[ES_ratio]
653
-
654
- #修正正态法
655
- if modeltyp in ['normal_modified','all']:
656
- ratio=calc_ES_normal_modified(ret_series,future_days,alpha)
657
- ES=-round(position*ratio,2)
658
- ESlist=ESlist+[ES]
659
- ES_ratio=round(ratio,4)
660
- ratiolist=ratiolist+[ES_ratio]
661
-
662
- #历史模拟法
663
- if modeltyp in ['historical','all']:
664
- ratio=calc_ES_historical(ret_series,future_days,alpha)
665
- ES=-round(position*ratio,2)
666
- ESlist=ESlist+[ES]
667
- ES_ratio=round(ratio,4)
668
- ratiolist=ratiolist+[ES_ratio]
669
-
670
- #蒙特卡洛模拟法,随机数,默认
671
- if modeltyp in ['montecarlo','all']:
672
- ratio=calc_ES_montecarlo(ret_series,future_days,alpha,mctype='random')
673
- ES=-round(position*ratio,2)
674
- ESlist=ESlist+[ES]
675
- ES_ratio=round(ratio,4)
676
- ratiolist=ratiolist+[ES_ratio]
677
-
678
- #蒙特卡洛模拟法,超采样
679
- if modeltyp in ['mc_oversampling','all']:
680
- ratio=calc_ES_montecarlo(ret_series,future_days,alpha, \
681
- mctype='mc_oversampling')
682
- ES=-round(position*ratio,2)
683
- ESlist=ESlist+[ES]
684
- ES_ratio=round(ratio,4)
685
- ratiolist=ratiolist+[ES_ratio]
686
-
687
- if not printout: return ESlist,ratiolist
688
-
689
- #输出ES金额和比率
690
- print("\n===== 投资组合的预期不足ES =====")
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)
701
-
702
- import datetime as dt; today=dt.date.today()
703
- footnote="\n数据来源:新浪/stooq,"+str(today)
704
-
705
- if not (modeltyp == 'all'):
706
- print("使用的模型:",model)
707
- print("ES金额/比率:",format(ES,','), \
708
- '\b,',str(round(ES_ratio*100,2))+'%')
709
- print(footnote)
710
- return ES,ES_ratio
711
-
712
- print("ES金额/比率:")
713
- modellist.pop()
714
- for m in modellist:
715
- pos=modellist.index(m)
716
- v=ESlist[pos]
717
- r=ratiolist[pos]
718
- print(" ",format(v,','),'\b,', \
719
- str(round(r*100,2))+'%'+' ('+m+')')
720
-
721
- print(footnote)
722
-
723
- return ESlist,ratiolist
724
-
725
- if __name__ == '__main__':
726
- portfolio={'Market':('China','000001.SS'),'000661.SZ':1,'603392.SS':2, \
727
- '300601.SZ':3}
728
- today='2020-7-20'
729
- future_days=1
730
- alpha=0.99
731
- pastyears=1
732
- model='all'
733
- printout=True
734
-
735
- #===========================================================================
736
- def ret_Normality_SW(ret_series,siglevel=0.05):
737
- """
738
- 功能:测试一个投资组合portfolio在给定期间内(fromdate,todate)的收益率序列
739
- 是否符合正态分布
740
- 输入参数:投资组合,开始日期,结束日期,显著性要求水平
741
- 输出:收益率序列正态性检验的W, p-value, Skewness, Kurtosis
742
- 【Shapiro-Wilk正态性检验】原假设:服从正态分布
743
- """
744
- #去掉空值
745
- ret_series=ret_series[~ret_series.isnull()]
746
-
747
- from scipy import stats
748
- (W,p_value)=stats.shapiro(ret_series)
749
-
750
- S=stats.skew(ret_series)
751
- K=stats.kurtosis(ret_series)
752
-
753
- return round(W,4),round(p_value,4),round(S,2),round(K,2)
754
-
755
- #===========================================================================
756
- def portfolio_ret_Normality_SW(portfolio,fromdate,todate, \
757
- siglevel=0.05,printout=True):
758
- """
759
- 功能:测试一个投资组合portfolio在给定期间内(fromdate,todate)的收益率序列
760
- 是否符合正态分布
761
- 输入参数:投资组合,开始日期,结束日期,显著性要求水平
762
- 输出:收益率序列正态性检验的p-value
763
- 【Shapiro-Wilk正态性检验】原假设:服从正态分布
764
- """
765
- #抓取投资组合股价和收益率
766
- prices=get_portfolio_prices0(portfolio,fromdate,todate)
767
- if prices is None: return None,None
768
- ret_series=prices['Ret']
769
- num=len(prices)-1
770
-
771
- #检验正态分布
772
- W,p_value,S,K=ret_Normality_SW(ret_series,siglevel)
773
-
774
- if not printout: return W,p_value,S,K
775
-
776
- _,_,tickerlist,sharelist,ticker_type=decompose_portfolio(portfolio)
777
- print("*** Shapiro-Wilk Normality Test ***")
778
- print(" Stock(s):",tickerlist)
779
- print(" Holding proportion:",sharelist)
780
- print(" Sampling period :",fromdate,'to',todate)
781
- print(" Observations :",num)
782
- print(" Null hypothesis : Normal")
783
- print(" W statistic :",round(W,4))
784
- print(" p-value :",round(p_value,4))
785
- print(" Skewness :",round(S,2))
786
- print(" Kurtosis :",round(K,2))
787
- if p_value >= siglevel:
788
- print("Result: Accept null hypothesis, normal")
789
- else:
790
- print("Result: Reject null hypothesis, not normal")
791
-
792
- footnote="... Data source: Yahoo Finance"
793
- print(footnote)
794
-
795
- return W,p_value,S,K
796
-
797
- #==============================================================================
798
- if __name__ == '__main__':
799
- portfolio={'Market':('China','000001.SS'),'000661.SZ':0.1,'603392.SS':0.2, \
800
- '300601.SZ':0.7}
801
- fromdate='2022-1-1'
802
- todate='2022-4-18'
803
-
804
- def portfolio_rets_curve(portfolio,start='MRY',end='today'):
805
- """
806
- 功能:绘制投资组合portfolio在给定期间(fromdate,todate)收益率分布的曲线,
807
- 并于相应的正态分布图对照
808
- 显示:收益率分布的直方图(实线),相应的正态分布图(虚线)
809
- x轴为收益率(非百分比),y轴为频度(Frequency)
810
- """
811
- fromdate,todate=start_end_preprocess(start,end)
812
-
813
- #抓取投资组合股价和收益率
814
- prices=get_portfolio_prices0(portfolio,fromdate,todate)
815
- if prices is None: return None,None
816
-
817
- num=len(prices)
818
- rets=prices['Ret']
819
- W,p_value,S,K=ret_Normality_SW(rets)
820
- _,_,tickerlist,sharelist,ticker_type=decompose_portfolio(portfolio)
821
- #计算收益率的均值和标准差
822
- mu=rets.mean()
823
- sigma=rets.std()
824
-
825
- #生成符合正态分布的随机数,符合股票收益率的均值和标准差
826
- import numpy as np
827
- x=mu+sigma*np.random.randn(10000)
828
-
829
- #plt.figure(figsize=(8,4))
830
- plt.figure(figsize=(12.8,6.4))
831
- import seaborn as sns
832
- #绘制曲线:股票收益率
833
- sns.kdeplot(data=rets,shade=True,color='blue',legend=True,label='投资组合',lw=4)
834
- #绘制曲线:对应的正态分布
835
- sns.kdeplot(data=x,shade=True,color='r',legend=True,label='正态分布线',ls='--')
836
- #设置标题、图例、坐标轴标签
837
- #plt.ylabel('Frequency')
838
-
839
- footnote1='日收益率%'
840
- footnote2='\n【注】Shapiro-Wilk检验:W值'+str(W)+',p值'+str(p_value)
841
- footnote3="。偏度"+str(S)+",峰度"+str(K)
842
-
843
- import datetime as dt; today=dt.date.today()
844
- footnote4="。数据来源:新浪/stooq,"+str(today)
845
-
846
- footnote=footnote1+footnote2+footnote3+footnote4
847
- plt.xlabel(footnote)
848
-
849
- plt.legend(loc='best')
850
- """
851
- titletxt1="投资组合收益率的正态分布检验"
852
- titletxt2="\n成分股"+str(tickerlist)
853
- titletxt3="\n持仓配置"+str(sharelist)
854
- titletxt4="\n样本期间:"+str(fromdate)+'至'+str(todate)+ \
855
- ',样本数量'+str(num)+'个'
856
- titletxt=titletxt1+titletxt2+titletxt3+titletxt4
857
- """
858
- titletxt="投资组合收益率的正态分布检验:"+portfolio_name(portfolio)
859
- plt.title(titletxt)
860
-
861
- plt.gca().set_facecolor('whitesmoke')
862
- plt.show()
863
-
864
- return
865
-
866
-
867
- #==============================================================================