siat 3.10.132__py3-none-any.whl → 3.11.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (221) hide show
  1. siat/__init__.py +0 -0
  2. siat/allin.py +8 -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 +4 -4
  13. siat/common.py +9 -6
  14. siat/compare_cross.py +0 -0
  15. siat/copyrights.py +0 -0
  16. siat/cryptocurrency.py +0 -0
  17. siat/economy.py +0 -0
  18. siat/economy2.py +0 -0
  19. siat/esg.py +0 -0
  20. siat/event_study.py +0 -0
  21. siat/exchange_bond_china.pickle +0 -0
  22. siat/fama_french.py +0 -0
  23. siat/fin_stmt2_yahoo.py +0 -0
  24. siat/financial_base.py +0 -0
  25. siat/financial_statements.py +0 -0
  26. siat/financials.py +0 -0
  27. siat/financials2.py +0 -0
  28. siat/financials_china.py +0 -0
  29. siat/financials_china2.py +0 -0
  30. siat/fund.py +0 -0
  31. siat/fund_china.pickle +0 -0
  32. siat/fund_china.py +0 -0
  33. siat/future_china.py +0 -0
  34. siat/google_authenticator.py +0 -0
  35. siat/grafix.py +55 -4
  36. siat/holding_risk.py +0 -0
  37. siat/luchy_draw.py +0 -0
  38. siat/market_china.py +0 -0
  39. siat/markowitz.py +0 -0
  40. siat/markowitz2.py +1 -0
  41. siat/markowitz2_20250704.py +0 -0
  42. siat/markowitz2_20250705.py +0 -0
  43. siat/markowitz_simple.py +0 -0
  44. siat/ml_cases.py +0 -0
  45. siat/ml_cases_example.py +0 -0
  46. siat/option_china.py +0 -0
  47. siat/option_pricing.py +0 -0
  48. siat/other_indexes.py +0 -0
  49. siat/risk_adjusted_return.py +0 -0
  50. siat/risk_adjusted_return2.py +8 -4
  51. siat/risk_evaluation.py +0 -0
  52. siat/risk_free_rate.py +0 -0
  53. siat/save2docx.py +345 -0
  54. siat/save2pdf.py +145 -0
  55. siat/sector_china.py +0 -0
  56. siat/security_price2.py +0 -0
  57. siat/security_prices.py +168 -6
  58. siat/security_trend.py +0 -0
  59. siat/security_trend2.py +2 -2
  60. siat/stock.py +11 -1
  61. siat/stock_advice_linear.py +0 -0
  62. siat/stock_base.py +0 -0
  63. siat/stock_china.py +0 -0
  64. siat/stock_info.pickle +0 -0
  65. siat/stock_prices_kneighbors.py +0 -0
  66. siat/stock_prices_linear.py +0 -0
  67. siat/stock_profile.py +0 -0
  68. siat/stock_technical.py +0 -0
  69. siat/stooq.py +0 -0
  70. siat/transaction.py +0 -0
  71. siat/translate.py +0 -0
  72. siat/valuation.py +0 -0
  73. siat/valuation_china.py +0 -0
  74. siat/var_model_validation.py +0 -0
  75. siat/yf_name.py +0 -0
  76. {siat-3.10.132.dist-info/licenses → siat-3.11.1.dist-info}/LICENSE +0 -0
  77. {siat-3.10.132.dist-info → siat-3.11.1.dist-info}/METADATA +234 -235
  78. siat-3.11.1.dist-info/RECORD +80 -0
  79. {siat-3.10.132.dist-info → siat-3.11.1.dist-info}/WHEEL +1 -1
  80. {siat-3.10.132.dist-info → siat-3.11.1.dist-info}/top_level.txt +0 -1
  81. build/lib/build/lib/siat/__init__.py +0 -75
  82. build/lib/build/lib/siat/allin.py +0 -137
  83. build/lib/build/lib/siat/assets_liquidity.py +0 -915
  84. build/lib/build/lib/siat/beta_adjustment.py +0 -1058
  85. build/lib/build/lib/siat/beta_adjustment_china.py +0 -548
  86. build/lib/build/lib/siat/blockchain.py +0 -143
  87. build/lib/build/lib/siat/bond.py +0 -2900
  88. build/lib/build/lib/siat/bond_base.py +0 -992
  89. build/lib/build/lib/siat/bond_china.py +0 -100
  90. build/lib/build/lib/siat/bond_zh_sina.py +0 -143
  91. build/lib/build/lib/siat/capm_beta.py +0 -783
  92. build/lib/build/lib/siat/capm_beta2.py +0 -887
  93. build/lib/build/lib/siat/common.py +0 -5360
  94. build/lib/build/lib/siat/compare_cross.py +0 -642
  95. build/lib/build/lib/siat/copyrights.py +0 -18
  96. build/lib/build/lib/siat/cryptocurrency.py +0 -667
  97. build/lib/build/lib/siat/economy.py +0 -1471
  98. build/lib/build/lib/siat/economy2.py +0 -1853
  99. build/lib/build/lib/siat/esg.py +0 -536
  100. build/lib/build/lib/siat/event_study.py +0 -815
  101. build/lib/build/lib/siat/fama_french.py +0 -1521
  102. build/lib/build/lib/siat/fin_stmt2_yahoo.py +0 -982
  103. build/lib/build/lib/siat/financial_base.py +0 -1160
  104. build/lib/build/lib/siat/financial_statements.py +0 -598
  105. build/lib/build/lib/siat/financials.py +0 -2339
  106. build/lib/build/lib/siat/financials2.py +0 -1278
  107. build/lib/build/lib/siat/financials_china.py +0 -4433
  108. build/lib/build/lib/siat/financials_china2.py +0 -2212
  109. build/lib/build/lib/siat/fund.py +0 -629
  110. build/lib/build/lib/siat/fund_china.py +0 -3307
  111. build/lib/build/lib/siat/future_china.py +0 -551
  112. build/lib/build/lib/siat/google_authenticator.py +0 -47
  113. build/lib/build/lib/siat/grafix.py +0 -3636
  114. build/lib/build/lib/siat/holding_risk.py +0 -867
  115. build/lib/build/lib/siat/luchy_draw.py +0 -638
  116. build/lib/build/lib/siat/market_china.py +0 -1168
  117. build/lib/build/lib/siat/markowitz.py +0 -2363
  118. build/lib/build/lib/siat/markowitz2.py +0 -3150
  119. build/lib/build/lib/siat/markowitz2_20250704.py +0 -2969
  120. build/lib/build/lib/siat/markowitz2_20250705.py +0 -3158
  121. build/lib/build/lib/siat/markowitz_simple.py +0 -373
  122. build/lib/build/lib/siat/ml_cases.py +0 -2291
  123. build/lib/build/lib/siat/ml_cases_example.py +0 -60
  124. build/lib/build/lib/siat/option_china.py +0 -3069
  125. build/lib/build/lib/siat/option_pricing.py +0 -1925
  126. build/lib/build/lib/siat/other_indexes.py +0 -409
  127. build/lib/build/lib/siat/risk_adjusted_return.py +0 -1576
  128. build/lib/build/lib/siat/risk_adjusted_return2.py +0 -1900
  129. build/lib/build/lib/siat/risk_evaluation.py +0 -2218
  130. build/lib/build/lib/siat/risk_free_rate.py +0 -351
  131. build/lib/build/lib/siat/sector_china.py +0 -4140
  132. build/lib/build/lib/siat/security_price2.py +0 -727
  133. build/lib/build/lib/siat/security_prices.py +0 -3408
  134. build/lib/build/lib/siat/security_trend.py +0 -402
  135. build/lib/build/lib/siat/security_trend2.py +0 -646
  136. build/lib/build/lib/siat/stock.py +0 -4284
  137. build/lib/build/lib/siat/stock_advice_linear.py +0 -934
  138. build/lib/build/lib/siat/stock_base.py +0 -26
  139. build/lib/build/lib/siat/stock_china.py +0 -2095
  140. build/lib/build/lib/siat/stock_prices_kneighbors.py +0 -910
  141. build/lib/build/lib/siat/stock_prices_linear.py +0 -386
  142. build/lib/build/lib/siat/stock_profile.py +0 -707
  143. build/lib/build/lib/siat/stock_technical.py +0 -3305
  144. build/lib/build/lib/siat/stooq.py +0 -74
  145. build/lib/build/lib/siat/transaction.py +0 -347
  146. build/lib/build/lib/siat/translate.py +0 -5183
  147. build/lib/build/lib/siat/valuation.py +0 -1378
  148. build/lib/build/lib/siat/valuation_china.py +0 -2076
  149. build/lib/build/lib/siat/var_model_validation.py +0 -444
  150. build/lib/build/lib/siat/yf_name.py +0 -811
  151. build/lib/siat/__init__.py +0 -75
  152. build/lib/siat/allin.py +0 -137
  153. build/lib/siat/assets_liquidity.py +0 -915
  154. build/lib/siat/beta_adjustment.py +0 -1058
  155. build/lib/siat/beta_adjustment_china.py +0 -548
  156. build/lib/siat/blockchain.py +0 -143
  157. build/lib/siat/bond.py +0 -2900
  158. build/lib/siat/bond_base.py +0 -992
  159. build/lib/siat/bond_china.py +0 -100
  160. build/lib/siat/bond_zh_sina.py +0 -143
  161. build/lib/siat/capm_beta.py +0 -783
  162. build/lib/siat/capm_beta2.py +0 -887
  163. build/lib/siat/common.py +0 -5360
  164. build/lib/siat/compare_cross.py +0 -642
  165. build/lib/siat/copyrights.py +0 -18
  166. build/lib/siat/cryptocurrency.py +0 -667
  167. build/lib/siat/economy.py +0 -1471
  168. build/lib/siat/economy2.py +0 -1853
  169. build/lib/siat/esg.py +0 -536
  170. build/lib/siat/event_study.py +0 -815
  171. build/lib/siat/fama_french.py +0 -1521
  172. build/lib/siat/fin_stmt2_yahoo.py +0 -982
  173. build/lib/siat/financial_base.py +0 -1160
  174. build/lib/siat/financial_statements.py +0 -598
  175. build/lib/siat/financials.py +0 -2339
  176. build/lib/siat/financials2.py +0 -1278
  177. build/lib/siat/financials_china.py +0 -4433
  178. build/lib/siat/financials_china2.py +0 -2212
  179. build/lib/siat/fund.py +0 -629
  180. build/lib/siat/fund_china.py +0 -3307
  181. build/lib/siat/future_china.py +0 -551
  182. build/lib/siat/google_authenticator.py +0 -47
  183. build/lib/siat/grafix.py +0 -3636
  184. build/lib/siat/holding_risk.py +0 -867
  185. build/lib/siat/luchy_draw.py +0 -638
  186. build/lib/siat/market_china.py +0 -1168
  187. build/lib/siat/markowitz.py +0 -2363
  188. build/lib/siat/markowitz2.py +0 -3150
  189. build/lib/siat/markowitz2_20250704.py +0 -2969
  190. build/lib/siat/markowitz2_20250705.py +0 -3158
  191. build/lib/siat/markowitz_simple.py +0 -373
  192. build/lib/siat/ml_cases.py +0 -2291
  193. build/lib/siat/ml_cases_example.py +0 -60
  194. build/lib/siat/option_china.py +0 -3069
  195. build/lib/siat/option_pricing.py +0 -1925
  196. build/lib/siat/other_indexes.py +0 -409
  197. build/lib/siat/risk_adjusted_return.py +0 -1576
  198. build/lib/siat/risk_adjusted_return2.py +0 -1900
  199. build/lib/siat/risk_evaluation.py +0 -2218
  200. build/lib/siat/risk_free_rate.py +0 -351
  201. build/lib/siat/sector_china.py +0 -4140
  202. build/lib/siat/security_price2.py +0 -727
  203. build/lib/siat/security_prices.py +0 -3408
  204. build/lib/siat/security_trend.py +0 -402
  205. build/lib/siat/security_trend2.py +0 -646
  206. build/lib/siat/stock.py +0 -4284
  207. build/lib/siat/stock_advice_linear.py +0 -934
  208. build/lib/siat/stock_base.py +0 -26
  209. build/lib/siat/stock_china.py +0 -2095
  210. build/lib/siat/stock_prices_kneighbors.py +0 -910
  211. build/lib/siat/stock_prices_linear.py +0 -386
  212. build/lib/siat/stock_profile.py +0 -707
  213. build/lib/siat/stock_technical.py +0 -3305
  214. build/lib/siat/stooq.py +0 -74
  215. build/lib/siat/transaction.py +0 -347
  216. build/lib/siat/translate.py +0 -5183
  217. build/lib/siat/valuation.py +0 -1378
  218. build/lib/siat/valuation_china.py +0 -2076
  219. build/lib/siat/var_model_validation.py +0 -444
  220. build/lib/siat/yf_name.py +0 -811
  221. 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
- #==============================================================================