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,2218 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- """
3
- 本模块功能:单项证券的VaR(在险价值)和ES(预期损失)计算函数包
4
- 所属工具包:证券投资分析工具SIAT
5
- SIAT:Security Investment Analysis Tool
6
- 创建日期:2018年10月10日
7
- 最新修订日期:2019年10月10日
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
- if __name__ == '__main__':
63
- ticker='BABA'
64
- start_date='2021-11-1'
65
- end_date='2021-11-10'
66
-
67
- def get_stock_quotes(ticker,start_date,end_date):
68
- """
69
- 输入参数:股票代码,开始日期,结束日期
70
- 输出参数:
71
- 股票价格序列(日期,开盘价,最高价,最低价,收盘价,调整收盘价,交易量)
72
- """
73
-
74
- df=get_prices(ticker,start_date,end_date)
75
-
76
- if df is None:
77
- print(" #Error(get_stock_quotes): retrieving prices failed for",ticker,start_date,end_date)
78
- return None
79
- if len(df) == 0:
80
- print(" #Error(get_stock_quotes): zero record found for",ticker,start_date,end_date)
81
- return None
82
-
83
- return df
84
-
85
- if __name__ == '__main__':
86
- get_stock_quotes('BABA','2021-11-1','2021-11-10')
87
- #==============================================================================
88
- def get_end_price(stock_quotes):
89
- """
90
- 输入参数:股票价格序列
91
- 输出参数:最新股价(金额)
92
- """
93
- end_price=stock_quotes['Close'][-1]
94
- return end_price
95
-
96
- if __name__ == '__main__':
97
- get_end_price(stock_quotes)
98
- #==============================================================================
99
- def get_ret_series(stock_quotes):
100
- """
101
- 输入参数:股票价格序列
102
- 输出参数:股票日收益率序列(注意不是DataFrame)
103
- """
104
- stock_quotes['ret']=stock_quotes['Close'].pct_change()
105
- stock_quotes=stock_quotes.dropna()
106
- ret_series=stock_quotes['ret']
107
- return ret_series
108
- # ret_series是序列类型
109
-
110
- if __name__ == '__main__':
111
- ret_series=get_ret_series(stock_quotes)
112
- #==============================================================================
113
- def VaR_normal_standard(position,ret_series,future_days=1,alpha=0.99):
114
-
115
- """
116
- 标准正太法VaR基本算法
117
- 输入参数:当前持有头寸金额,收益率序列(非百分比),未来持有时间(天),置信度
118
- 输出参数:VaR(金额,单位与当前头寸的金额单位相同),负数
119
- """
120
- #去掉空值
121
- r=ret_series[~ret_series.isnull()]
122
-
123
- import numpy as np
124
- from scipy import stats
125
-
126
- z=stats.norm.ppf(1-alpha)
127
- miu_daily=np.mean(r)
128
- miu_days=np.power(miu_daily+1,future_days)-1
129
- sigma_daily=np.std(r)
130
- sigma_days=np.sqrt(future_days)*sigma_daily
131
-
132
- ratio=miu_days+z*sigma_days
133
- VaR_days=position*ratio
134
-
135
- return VaR_days
136
-
137
- if __name__ == '__main__':
138
- VaR_normal_standard(10000,ret_series,future_days=1,alpha=0.99)
139
- #==============================================================================
140
- def stock_VaR(ticker,shares,today,future_days=1,alpha=0.99, \
141
- pastyears=1,printout=True,random=10000,mctype='random', \
142
- model="normal_standard"):
143
- """
144
- 功能:持有股票的VaR,支持选择四种模型
145
- 输入参数:股票代码,持有股数,当前日期,未来持有时间(天),置信度,
146
- 使用历史数据的年数,是否打印结果,模型方法
147
- 模型方法:标准正态法normal_standard,修正正态法normal_modified,
148
- 蒙特卡洛模拟法montecarlo,历史排序模拟法historical
149
- 输出:VaR(负数金额,单位与股价的金额单位相同),VaR比率
150
- """
151
- # 检查支持的模型
152
- modellist=['normal_standard','normal_modified','montecarlo', \
153
- 'historical','allmodels']
154
- if not (model in modellist):
155
- print(" #Error(stock_VaR): unsupported model",model)
156
- print(" Supported models:",modellist)
157
- return None,None
158
-
159
- if model in ['normal_standard']:
160
- VaR,VaR_ratio=stock_VaR_normal_standard(ticker=ticker,shares=shares, \
161
- today=today,future_days=future_days,alpha=alpha, \
162
- pastyears=pastyears,printout=printout)
163
- return VaR,VaR_ratio
164
-
165
- if model in ['normal_modified']:
166
- VaR,VaR_ratio=stock_VaR_normal_modified(ticker=ticker,shares=shares, \
167
- today=today,future_days=future_days,alpha=alpha, \
168
- pastyears=pastyears,printout=printout)
169
- return VaR,VaR_ratio
170
-
171
- if model in ['montecarlo']:
172
- VaR,VaR_ratio=stock_VaR_montecarlo(ticker=ticker,shares=shares, \
173
- today=today,future_days=future_days,alpha=alpha, \
174
- pastyears=pastyears,random=random,mctype=mctype, \
175
- printout=printout)
176
- return VaR,VaR_ratio
177
-
178
- if model in ['historical']:
179
- VaR,VaR_ratio=stock_VaR_historical_grouping(ticker=ticker,shares=shares, \
180
- today=today,future_days=future_days,alpha=alpha, \
181
- pastyears=pastyears, \
182
- printout=printout)
183
- return VaR,VaR_ratio
184
-
185
- if model in ['allmodels']:
186
- get_VaR_allmodels(ticker=ticker,shares=shares,today=today, \
187
- future_days=future_days,alpha=alpha,pastyears=pastyears)
188
-
189
- return
190
-
191
- #==============================================================================
192
- def security_VaR(ticker,shares,today,future_days=1,alpha=0.99, \
193
- pastyears=1,printout=True,random=10000,mctype='random', \
194
- model="normal_standard"):
195
- """
196
- 功能:持有证券的VaR,支持选择四种模型
197
- 输入参数:证券代码,持有股数,当前日期,未来持有时间(天),置信度,
198
- 使用历史数据的年数,是否打印结果,模型方法
199
- 模型方法:标准正态法normal_standard,修正正态法normal_modified,
200
- 蒙特卡洛模拟法montecarlo,历史排序模拟法historical
201
- 输出:VaR(负数金额,单位与股价的金额单位相同),VaR比率
202
- 说明:套壳函数stock_VaR
203
- """
204
- stock_VaR(ticker=ticker,shares=shares,today=today,future_days=future_days,alpha=alpha, \
205
- pastyears=pastyears,printout=printout,random=random,mctype=mctype, \
206
- model=model)
207
-
208
- return
209
-
210
- #==============================================================================
211
- if __name__ == '__main__':
212
- ticker='BABA'
213
- shares=10000
214
- today='2021-11-18'
215
- future_days=1
216
- alpha=0.99
217
- pastyears=1
218
- printout=True
219
-
220
- def stock_VaR_normal_standard(ticker,shares,today, \
221
- future_days=1,alpha=0.99,pastyears=1,printout=True):
222
- """
223
- 功能:持有股票的VaR,标准正态法
224
- 输入参数:股票代码,持有股数,当前日期,未来持有时间(天),置信度,使用历史数据的年数
225
- 输出:VaR(负数金额,单位与股价的金额单位相同),VaR比率
226
- """
227
- start=get_start_date(today,pastyears)
228
- p=get_stock_quotes(ticker,start,today)
229
- if p is None:
230
- print(" #Error(stock_VaR_normal_standard): no obs retrieved.")
231
- return None,None
232
- if len(p)==0:
233
- print(" #Error(stock_VaR_normal_standard): zero obs retrieved.")
234
- return None,None
235
-
236
- r=get_ret_series(p)
237
- p_end=get_end_price(p)
238
- position=shares*p_end
239
- VaR=VaR_normal_standard(position,r,future_days,alpha)
240
- if VaR is None: return None,None
241
- #最大为全损
242
- if abs(VaR) > position: VaR=-position
243
-
244
- VaR_ratio=abs(VaR/position)
245
-
246
- #from rich import print as rprint
247
- import pandas as pd
248
- disp_df=pd.DataFrame(columns=['Item','Value'])
249
- if printout == True:
250
- """
251
- print("\n=== 计算在险价值:标准正态模型 ===")
252
- print("持有股票 :",ticker_name(ticker))
253
- print("持有股数 :",format(shares,','))
254
- print("持有日期 :",today)
255
- print("预计持有天数:",future_days)
256
- print("置信度 : ",alpha*100,'%',sep='')
257
- print("在险价值VaR :",format(round(VaR,2),','))
258
- print("VaR比率 : ",round(VaR_ratio*100,2),'%',sep='')
259
-
260
- import datetime as dt; today=dt.date.today()
261
- footnote="*数据来源:新浪/stooq,"+str(today)
262
- print(footnote)
263
- """
264
- titletxt="在险价值:标准正态模型"
265
- import datetime as dt; todaydt=dt.date.today()
266
- footnote="数据来源:新浪/stooq,"+str(todaydt)
267
- """
268
- s=pd.Series({'Item':'持有股票','Value':ticker_name(ticker)})
269
- disp_df=disp_df._append(s,ignore_index=True)
270
-
271
- s=pd.Series({'Item':'持有股数','Value':format(shares,',')})
272
- disp_df=disp_df._append(s,ignore_index=True)
273
-
274
- s=pd.Series({'Item':'持有日期','Value':today})
275
- disp_df=disp_df._append(s,ignore_index=True)
276
-
277
- s=pd.Series({'Item':'预计持有天数','Value':future_days})
278
- disp_df=disp_df._append(s,ignore_index=True)
279
-
280
- s=pd.Series({'Item':'置信度','Value':str(alpha*100)+'%'})
281
- disp_df=disp_df._append(s,ignore_index=True)
282
-
283
- s=pd.Series({'Item':'在险价值VaR','Value':format(round(VaR,2),',')})
284
- disp_df=disp_df._append(s,ignore_index=True)
285
-
286
- s=pd.Series({'Item':'VaR比率','Value':str(round(VaR_ratio*100,2))+'%'})
287
- disp_df=disp_df._append(s,ignore_index=True)
288
-
289
- df_display_CSS(disp_df,titletxt=titletxt,footnote=footnote,facecolor='papayawhip',decimals=2, \
290
- hide_columns=True,
291
- first_col_align='left',second_col_align='right', \
292
- last_col_align='right',other_col_align='right', \
293
- titile_font_size='14px',footnote_font_size='12px')
294
- """
295
-
296
- data_dict={'持有股票:':ticker_name(ticker), \
297
- '持有股数:':format(shares,','), \
298
- '持有日期:':today, \
299
- '预计持有天数:':future_days, \
300
- '置信度:':str(alpha*100)+'%', \
301
- '在险价值VaR金额:':format(round(VaR,2),','), \
302
- '在险价值VaR比率:':str(round(VaR_ratio*100,2))+'%'}
303
-
304
- print2CSS(data_dict,titletxt=titletxt,footnote=footnote,
305
- #facecolor='whitesmoke',
306
- )
307
-
308
- return VaR,VaR_ratio
309
-
310
- if __name__ == '__main__':
311
- var1,ratio1=stock_VaR_normal_standard('BABA',10000,'2019-08-08',1,0.99)
312
-
313
- #==============================================================================
314
- def series_VaR_normal_standard(ticker,shares,datelist, \
315
- future_days=1,alpha=0.99,pastyears=1,printout=True):
316
- """
317
- 功能:一步计算在多个日期持有一定天数股票资产的VaR
318
- 输入参数:股票代码,持有股数,日期列表(日期型列表),未来持有时间(天数),置信度,使用历史数据的年数
319
- 输出:多个日期的VaR(日期,股票代码,VaR金额,VaR比率(即单位头寸的VaR))
320
- # datelist是datetime类型日期的列表
321
- """
322
-
323
- import pandas as pd
324
- result=pd.DataFrame(columns=['date','ticker','VaR','ratio'])
325
- for d in datelist:
326
- VaR,ratio=stock_VaR_normal_standard(ticker,shares,d, \
327
- future_days,alpha,pastyears,printout=False)
328
- if (VaR is None) or (ratio is None): continue
329
-
330
- s = pd.Series({'date':d,'ticker':ticker,'VaR':VaR,'ratio':ratio})
331
- try:
332
- result=result.append(s,ignore_index=True)
333
- except:
334
- result=result._append(s,ignore_index=True)
335
-
336
- result2=result.set_index(['date'])
337
- # result2是dateframe类型
338
-
339
- if printout == False: return result2
340
-
341
- #打印
342
- result3=result2.copy()
343
- result3['VaR金额']=round(result3['VaR'],2)
344
- result3['VaR比例%']=round(result3['ratio']*100,2)
345
- result3.drop(columns=['ticker','VaR','ratio'],inplace=True)
346
-
347
- text1="= "+ticker_name(ticker)+": VaR比例,持有"+str(future_days)+"天 ="
348
- print(text1)
349
- print(result3)
350
- import datetime as dt; today=dt.date.today()
351
- print("数据来源:新浪/stooq,"+str(today))
352
-
353
- #绘图
354
- #VaR金额绘图
355
- plt.plot(result3['VaR金额'],c='r',lw=2)
356
- title1=ticker_name(ticker)+": VaR金额的变化,持有"+str(future_days)+"天"
357
- plt.title(title1)
358
- plt.ylabel('VaR金额')
359
- #plt.gcf().autofmt_xdate() # 优化标注(自动倾斜)
360
- plt.xticks(rotation=30)
361
-
362
- import datetime as dt; today=dt.date.today()
363
- footnote="数据来源:新浪/stooq,"+str(today)
364
- plt.xlabel(footnote)
365
-
366
- plt.gca().set_facecolor('whitesmoke')
367
- plt.show()
368
-
369
- plt.plot(result3['VaR比例%'],c='r',lw=2)
370
- title2=ticker_name(ticker)+": VaR比例的变化, 持有"+str(future_days)+"天"
371
- plt.title(title2)
372
- plt.ylabel('VaR比例%')
373
- #plt.gcf().autofmt_xdate() # 优化标注(自动倾斜)
374
- plt.xticks(rotation=30)
375
- plt.xlabel(footnote)
376
-
377
- plt.gca().set_facecolor('whitesmoke')
378
- plt.show()
379
-
380
- return result2
381
-
382
- if __name__ == '__main__':
383
- datelist=['2018-01-01','2018-04-01','2018-07-01','2018-10-01', \
384
- '2019-01-01','2019-04-01','2019-07-01']
385
- result=series_VaR_normal_standard('BABA',10000,datelist,1,0.99)
386
-
387
-
388
- #==============================================================================
389
- def compare_VaR(ticker,shares,datelist, \
390
- future_days=1,alpha=0.99,pastyears=1,model='normal_standard'):
391
- """
392
- 功能:比较多个日期持有一定天数股票资产的VaR高低
393
- 输入参数:股票列表,持有股数,日期列表(日期型列表),未来持有时间(天数),
394
- 置信度,使用历史数据的年数,选择的模型方法
395
- 模型方法:目前仅支持normal_standard和normal_modified
396
- 输出:无
397
- 显示:折线图,各个资产的VaR金额和比率对比
398
- """
399
- tickerlist=ticker
400
-
401
- modellist=['normal_standard','normal_modified']
402
- if not (model in modellist):
403
- print(" #Error(compare_VaR): unsupported model",model)
404
- print(" Supported models at present:",modellist)
405
- return
406
-
407
- if model in ['normal_standard']:
408
- compare_VaR_normal_standard(tickerlist=tickerlist,shares=shares, \
409
- datelist=datelist,future_days=future_days,alpha=alpha, \
410
- pastyears=pastyears)
411
- return
412
-
413
- if model in ['normal_modified']:
414
- compare_VaR_normal_modified(tickerlist=tickerlist,shares=shares, \
415
- datelist=datelist,future_days=future_days,alpha=alpha, \
416
- pastyears=pastyears)
417
- return
418
-
419
-
420
-
421
-
422
- #==============================================================================
423
- if __name__ == '__main__':
424
- tickerlist=['BABA','PDD','JD']
425
- shares=10000
426
- datelist=['2019-01-01','2019-02-01','2019-03-01','2019-04-01', \
427
- '2019-05-01','2019-06-01','2019-07-01']
428
- future_days=1
429
- alpha=0.99
430
- pastyears=1
431
-
432
-
433
- def compare_VaR_normal_standard(tickerlist,shares,datelist, \
434
- future_days=1,alpha=0.99,pastyears=1):
435
- """
436
- 功能:比较多个日期持有一定天数股票资产的VaR高低
437
- 输入参数:股票列表,持有股数,日期列表(日期型列表),未来持有时间(天数),置信度,使用历史数据的年数
438
- 输出:无
439
- 显示:折线图,各个资产的VaR金额和比率对比
440
- """
441
-
442
- import os, sys
443
- class HiddenPrints:
444
- def __enter__(self):
445
- self._original_stdout = sys.stdout
446
- sys.stdout = open(os.devnull, 'w')
447
- def __exit__(self, exc_type, exc_val, exc_tb):
448
- sys.stdout.close()
449
- sys.stdout = self._original_stdout
450
-
451
- print(" The comparison may take time, please wait ...")
452
- markerlist=['.','o','s','*','+','x','1','2']
453
- for t in tickerlist:
454
- pos=tickerlist.index(t)
455
- thismarker=markerlist[pos]
456
-
457
- with HiddenPrints():
458
- r=series_VaR_normal_standard(t,shares,datelist, \
459
- future_days,alpha,pastyears,printout=False)
460
- rr=r.copy()
461
- rr['VaR amount']=round(rr['VaR'],2)
462
- rr.drop(columns=['ticker','VaR','ratio'],inplace=True)
463
-
464
- rr['date']=rr.index
465
- import pandas as pd
466
- rr['date']=rr['date'].apply(lambda x: pd.to_datetime(x))
467
- rr.set_index(['date'],inplace=True)
468
-
469
- plt.plot(rr['VaR amount'],label=ticker_name(t),lw=2,marker=thismarker)
470
-
471
- title1="比较VaR金额,持有"+str(future_days)+"天"
472
- plt.title(title1)
473
- plt.ylabel('VaR金额')
474
- plt.xticks(rotation=30)
475
- plt.legend(loc='best')
476
-
477
- notes="【注】VaR计算模型:标准正态法"
478
- import datetime as dt; today=dt.date.today()
479
- source="数据来源:新浪/stooq,"+str(today)
480
- footnote=notes+'\n'+source
481
- plt.xlabel(footnote)
482
-
483
- plt.gca().set_facecolor('whitesmoke')
484
- plt.show()
485
-
486
- for t in tickerlist:
487
- pos=tickerlist.index(t)
488
- thismarker=markerlist[pos]
489
-
490
- with HiddenPrints():
491
- r=series_VaR_normal_standard(t,shares,datelist, \
492
- future_days,alpha,pastyears,printout=False)
493
- rr=r.copy()
494
- rr['VaR ratio %']=round(rr['ratio']*100,2)
495
- rr.drop(columns=['ticker','VaR','ratio'],inplace=True)
496
-
497
- rr['date']=rr.index
498
- import pandas as pd
499
- rr['date']=rr['date'].apply(lambda x: pd.to_datetime(x))
500
- rr.set_index(['date'],inplace=True)
501
-
502
-
503
- plt.plot(rr['VaR ratio %'],label=ticker_name(t),lw=2,marker=thismarker)
504
-
505
- title2="比较VaR比例,持有"+str(future_days)+"天"
506
- plt.title(title2)
507
- plt.ylabel('VaR比例%')
508
- plt.xticks(rotation=30)
509
- plt.legend(loc='best')
510
- plt.xlabel(footnote)
511
-
512
- plt.gca().set_facecolor('whitesmoke')
513
- plt.show()
514
-
515
- return
516
-
517
- if __name__ == '__main__':
518
- tickerlist=['BABA','PDD','JD']
519
- datelist=['2019-01-01','2019-02-01','2019-03-01','2019-04-01', \
520
- '2019-05-01','2019-06-01','2019-07-01']
521
- compare_VaR_normal_standard(tickerlist,10000,datelist,1,0.99)
522
-
523
- #==============================================================================
524
- def ES_normal_standard(position,ret_series,future_days=1,alpha=0.99):
525
- """
526
- 功能:计算ES,标准正态法
527
- 输入参数:持有头寸金额,日收益率序列,未来持有日期,置信度
528
- 输出:预期损失(金额)
529
- """
530
- import numpy as np
531
- from scipy import stats
532
-
533
- z=stats.norm.ppf(1-alpha)
534
- miu_daily=np.mean(ret_series)
535
- miu_days=np.power(miu_daily+1,future_days)-1
536
- sigma_daily=np.std(ret_series)
537
- sigma_days=np.sqrt(future_days)*sigma_daily
538
-
539
- zES=-stats.norm.pdf(z)/(1-alpha)
540
- ratio=miu_days+zES*sigma_days
541
- ES_days=position*ratio
542
-
543
- #return -ES_days
544
- return ES_days
545
-
546
- #==============================================================================
547
- def stock_ES(ticker,shares,today,future_days=1,alpha=0.99, \
548
- pastyears=1,printout=True,random=10000,mctype='random', \
549
- model="normal_standard"):
550
- """
551
- 功能:持有股票的ES,支持选择模型
552
- 输入参数:股票代码,持有股数,当前日期,未来持有时间(天),置信度,
553
- 使用历史数据的年数,是否打印结果,模型方法
554
- 模型方法:标准正态法normal_standard
555
- 输出:VaR(负数金额,单位与股价的金额单位相同),VaR比率
556
- """
557
- # 检查支持的模型
558
- modellist=['normal_standard']
559
- if not (model in modellist):
560
- print(" #Error(stock_VaR): unsupported model",model)
561
- print(" Supported models at present:",modellist)
562
- return None,None
563
-
564
- if model in ['normal_standard']:
565
- ES,ratio=stock_ES_normal_standard(ticker=ticker,shares=shares, \
566
- today=today,future_days=future_days,alpha=alpha, \
567
- pastyears=pastyears,printout=printout)
568
- return ES,ratio
569
-
570
- #==============================================================================
571
- def security_ES(ticker,shares,today,future_days=1,alpha=0.99, \
572
- pastyears=1,printout=True,random=10000,mctype='random', \
573
- model="normal_standard"):
574
- """
575
- 功能:持有证券的预期不足ES,支持选择模型
576
- 输入参数:证券代码,持有股数,当前日期,未来持有时间(天),置信度,
577
- 使用历史数据的年数,是否打印结果,模型方法
578
- 模型方法:默认标准正态法normal_standard
579
- 说明:套壳函数stock_ES
580
- """
581
- ES,ESratio=stock_ES(ticker=ticker,shares=shares,today=today,future_days=future_days,alpha=alpha, \
582
- pastyears=pastyears,printout=printout,random=random,mctype=mctype, \
583
- model=model)
584
-
585
- return
586
-
587
- #==============================================================================
588
- if __name__ == '__main__':
589
- ticker='JD'
590
- shares=1000
591
- today='2023-2-6'
592
- future_days=1
593
- alpha=0.99
594
- pastyears=1
595
- printout=True
596
-
597
-
598
- def stock_ES_normal_standard(ticker,shares,today, \
599
- future_days=1,alpha=0.99,pastyears=1,printout=True):
600
- """
601
- 功能:计算持有股票资产的ES,标准正态法
602
- 输入参数:股票代码,持有股数,当前日期,未来持有日期(天数),置信度,使用历史数据的年数
603
- #输出参数:预期损失(金额)负数,预期损失与头寸的比率
604
- """
605
- start=get_start_date(today,pastyears)
606
- p=get_stock_quotes(ticker,start,today)
607
-
608
- if p is None:
609
- print(" #Error(stock_ES_normal_standard): no obs retrieved.")
610
- return None,None
611
- if len(p)==0:
612
- print(" #Error(stock_ES_normal_standard): zero obs retrieved.")
613
- return None,None
614
-
615
- r=get_ret_series(p)
616
- p_end=get_end_price(p)
617
- position=shares*p_end
618
- ES=ES_normal_standard(position,r,future_days,alpha)
619
- #最大为全损
620
- if abs(ES) > position: ES=-position
621
-
622
- ratio=abs(ES/position)
623
-
624
- if printout == True:
625
- """
626
- print("\n=== 计算预期不足ES:标准正态模型 ===")
627
- print("持有股票 :",ticker_name(ticker))
628
- print("持有股数 :",format(shares,','))
629
- print("持有日期 :",today)
630
- print("预计持有天数:",future_days)
631
- print("置信度 : ",alpha*100,'%',sep='')
632
- print("ES金额 :",format(round(ES,2),','))
633
- print("ES比例 : ",round(ratio*100,2),'%',sep='')
634
-
635
- import datetime as dt; today=dt.date.today()
636
- print("数据来源:新浪/stooq,"+str(today))
637
- """
638
-
639
- titletxt="预期不足:标准正态模型"
640
- import datetime as dt; todaydt=dt.date.today()
641
- footnote="数据来源:新浪/stooq,"+str(todaydt)
642
-
643
- data_dict={'持有股票:':ticker_name(ticker), \
644
- '持有股数:':format(shares,','), \
645
- '持有日期:':today, \
646
- '预计持有天数:':future_days, \
647
- '置信度:':str(alpha*100)+'%', \
648
- '预期不足ES金额:':format(round(ES,2),','), \
649
- '预期不足ES比例:':str(round(ratio*100,2))+'%'}
650
-
651
- print2CSS(data_dict,titletxt=titletxt,footnote=footnote)
652
-
653
- return ES,ratio
654
-
655
-
656
- #==============================================================================
657
- def series_ES_normal_standard(ticker,shares,datelist, \
658
- future_days=1,alpha=0.99,pastyears=1,printout=True):
659
- """
660
- 功能:一步计算在多个日期持有一定天数股票资产的ES,标准正态法
661
- 输入参数:股票代码,持有股数,日期列表(日期型列表),未来持有时间(天数),置信度,使用历史数据的年数
662
- 输出:多个日期的ES(日期,股票代码,ES金额,ES比率(即单位头寸的ES))
663
- # datelist是datetime类型日期的列表
664
- """
665
-
666
- import pandas as pd
667
- result=pd.DataFrame(columns=['date','ticker','ES','ratio'])
668
- for d in datelist:
669
- ES,ratio=stock_ES_normal_standard(ticker,shares,d, \
670
- future_days,alpha,pastyears,printout=False)
671
- if (ES is None) or (ratio is None): continue
672
-
673
- s = pd.Series({'date':d,'ticker':ticker,'ES':ES,'ratio':ratio})
674
- try:
675
- result=result.append(s,ignore_index=True)
676
- except:
677
- result=result._append(s,ignore_index=True)
678
-
679
- result2=result.set_index(['date'])
680
- # result2是dateframe类型
681
-
682
- if printout == False: return result2
683
-
684
- #打印
685
- result3=result2.copy()
686
- result3['ES金额']=round(result3['ES'],2)
687
- result3['ES比例%']=round(result3['ratio']*100,2)
688
- result3.drop(columns=['ticker','ES','ratio'],inplace=True)
689
-
690
- text1="=== "+ticker_name(ticker)+": ES比例,持有"+str(future_days)+"天 ==="
691
- print(text1)
692
- print(result3)
693
- import datetime as dt; today=dt.date.today()
694
- print("数据来源:新浪/stooq,"+str(today))
695
-
696
- #绘图
697
- #VaR金额绘图
698
- plt.plot(result3['ES金额'],c='r',lw=2)
699
- title1=ticker_name(ticker)+": ES金额的变化,持有"+str(future_days)+"天"
700
- plt.title(title1)
701
- plt.ylabel('ES金额')
702
- plt.xticks(rotation=30)
703
-
704
- plt.gca().set_facecolor('whitesmoke')
705
- plt.show()
706
-
707
- plt.plot(result3['ES比例%'],c='r',lw=2)
708
- title2=ticker_name(ticker)+": ES比例的变化,持有"+str(future_days)+"天"
709
- plt.title(title2)
710
- plt.ylabel('ES比例%')
711
- plt.xticks(rotation=30)
712
-
713
- plt.gca().set_facecolor('whitesmoke')
714
- plt.show()
715
-
716
- return result2
717
-
718
- if __name__ == '__main__':
719
- datelist=['2018-01-01','2018-04-01','2018-07-01','2018-10-01', \
720
- '2019-01-01','2019-04-01','2019-07-01']
721
- result=series_ES_normal_standard('BABA',10000,datelist,1,0.99)
722
-
723
- #==============================================================================
724
- def compare_ES(ticker,shares,datelist, \
725
- future_days=1,alpha=0.99,pastyears=1,model='normal_standard'):
726
- """
727
- 功能:比较多个日期持有一定天数股票资产的ES高低
728
- 输入参数:股票列表,持有股数,日期列表(日期型列表),未来持有时间(天数),
729
- 置信度,使用历史数据的年数,选择的模型方法
730
- 模型方法:目前仅支持normal_standard
731
- 输出:无
732
- 显示:折线图,各个资产的ES金额和比率对比
733
- """
734
- tickerlist=ticker
735
-
736
- modellist=['normal_standard']
737
- if not (model in modellist):
738
- print(" #Error(compare_ES): unsupported model",model)
739
- print(" Supported models at present:",modellist)
740
- return
741
-
742
- if model in ['normal_standard']:
743
- compare_ES_normal_standard(tickerlist=tickerlist,shares=shares, \
744
- datelist=datelist,future_days=future_days,alpha=alpha, \
745
- pastyears=pastyears)
746
- return
747
-
748
- #==============================================================================
749
- def compare_ES_normal_standard(tickerlist,shares,datelist, \
750
- future_days=1,alpha=0.99,pastyears=1):
751
- """
752
- 功能:比较多个日期持有一定天数股票资产的ES高低,标准正态法
753
- 输入参数:股票列表,持有股数,日期列表(日期型列表),未来持有时间(天数),置信度,使用历史数据的年数
754
- 输出:无
755
- 显示:折线图,各个资产的ES金额和比率对比
756
- """
757
-
758
- import os, sys
759
- class HiddenPrints:
760
- def __enter__(self):
761
- self._original_stdout = sys.stdout
762
- sys.stdout = open(os.devnull, 'w')
763
- def __exit__(self, exc_type, exc_val, exc_tb):
764
- sys.stdout.close()
765
- sys.stdout = self._original_stdout
766
-
767
- print(" The comparison may take time, please wait ...")
768
- markerlist=['.','o','s','*','+','x','1','2']
769
- for t in tickerlist:
770
- pos=tickerlist.index(t)
771
- thismarker=markerlist[pos]
772
-
773
- with HiddenPrints():
774
- r=series_ES_normal_standard(t,shares,datelist, \
775
- future_days,alpha,pastyears,printout=False)
776
- rr=r.copy()
777
- rr['ES amount']=round(rr['ES'],2)
778
- rr.drop(columns=['ticker','ES','ratio'],inplace=True)
779
- plt.plot(rr['ES amount'],label=ticker_name(t),lw=2,marker=thismarker)
780
-
781
- title1="比较ES金额,持有"+str(future_days)+"天"
782
- plt.title(title1)
783
- plt.ylabel('ES金额')
784
- plt.xticks(rotation=30)
785
- plt.legend(loc='best')
786
-
787
- notes="【注】ES计算模型:标准正态法"
788
- import datetime as dt; today=dt.date.today()
789
- source="数据来源:新浪/stooq,"+str(today)
790
- footnote=notes+'\n'+source
791
- plt.xlabel(footnote)
792
- plt.show()
793
-
794
- for t in tickerlist:
795
- pos=tickerlist.index(t)
796
- thismarker=markerlist[pos]
797
-
798
- with HiddenPrints():
799
- r=series_ES_normal_standard(t,shares,datelist, \
800
- future_days,alpha,pastyears,printout=False)
801
- rr=r.copy()
802
- rr['ES ratio %']=round(rr['ratio']*100,2)
803
- rr.drop(columns=['ticker','ES','ratio'],inplace=True)
804
- plt.plot(rr['ES ratio %'],label=ticker_name(t),lw=2,marker=thismarker)
805
-
806
- title2="比较ES比例,持有"+str(future_days)+"天"
807
- plt.title(title2)
808
- plt.ylabel('ES比例%')
809
- plt.xticks(rotation=30)
810
- plt.legend(loc='best')
811
- plt.xlabel(footnote)
812
- plt.show()
813
-
814
- return
815
-
816
- if __name__ == '__main__':
817
- tickerlist=['BABA','PDD','JD']
818
- datelist=['2019-01-01','2019-02-01','2019-03-01','2019-04-01', \
819
- '2019-05-01','2019-06-01','2019-07-01']
820
- compare_ES_normal_standard(tickerlist,10000,datelist,1,0.99)
821
-
822
-
823
- #==============================================================================
824
- def normfunc(x,mu,sigma):
825
- #计算正态分布的概率密度,带有均值和标准差
826
- import numpy as np
827
- pdf = np.exp(-((x - mu)**2)/(2*sigma**2)) / (sigma * np.sqrt(2*np.pi))
828
- return pdf
829
-
830
- #==============================================================================
831
- def plot_rets_histogram(ticker,start,end,num_bins=20):
832
- """
833
- 功能:绘制收益率分布的直方图,并于相应的正态分布图对照
834
- 输入:股票代码,开始/结束时间
835
- 显示:收益率分布的直方图(实线),相应的正态分布图(虚线)
836
- x轴为收益率(非百分比),y轴为频度(Frequency)
837
- """
838
- #抓取股价并计算收益率
839
- quotes=get_stock_quotes(ticker,start,end)
840
- if (quotes is None) or (len(quotes)==0):
841
- print("#Error(plot_rets_histogram): Fetching data failed")
842
- print("Information:",ticker,start,end)
843
- return
844
- rets=get_ret_series(quotes)
845
-
846
- #计算收益率的均值和标准差
847
- mu=rets.mean()
848
- sigma=rets.std()
849
-
850
- #绘制股票收益率直方图
851
- #plt.figure(figsize=(8,4))
852
- plt.figure(figsize=(12.8,6.4))
853
- n,bins,patches=plt.hist(rets,num_bins,facecolor='blue',alpha=0.5,label=ticker_name(ticker))
854
-
855
- #生成与直方图柱子对应的正态分布概率密度
856
- y=normfunc(bins,mu,sigma)
857
- #绘制正态分布曲线
858
- plt.plot(bins,y,'r--',label='正态分布',lw=2)
859
- plt.ylabel('Frequency')
860
- plt.xlabel('Stock return')
861
- titletxt="正态性检验:"+ticker_name(ticker)+"收益率, "+start+"至"+end
862
- plt.title(titletxt)
863
- plt.legend(loc='best')
864
-
865
- import datetime as dt; today=dt.date.today()
866
- footnote="数据来源:新浪/stooq,"+str(today)
867
- plt.xlabel(footnote)
868
- plt.show()
869
-
870
- return
871
-
872
- if __name__ == '__main__':
873
- plot_rets_histogram('JD','2019-1-1','2019-6-30')
874
-
875
- #==============================================================================
876
- def plot_rets_curve(ticker,start='MRY',end='today'):
877
- """
878
- 功能:绘制收益率分布的曲线,并于相应的正态分布图对照
879
- 输入:股票代码,开始/结束时间
880
- 显示:收益率分布的直方图(实线),相应的正态分布图(虚线)
881
- x轴为收益率(非百分比),y轴为频度(Frequency)
882
- """
883
- start,end=start_end_preprocess(start,end)
884
-
885
- #抓取股价并计算收益率
886
- quotes=get_stock_quotes(ticker,start,end)
887
- if (quotes is None) or (len(quotes)==0):
888
- print("#Error(plot_rets_curve): Fetching data failed")
889
- print("Information:",ticker,start,end)
890
- return
891
- rets=get_ret_series(quotes)
892
-
893
- #计算收益率的均值和标准差
894
- mu=rets.mean()
895
- sigma=rets.std()
896
-
897
- #生成符合正态分布的随机数,符合股票收益率的均值和标准差
898
- import numpy as np
899
- x=mu+sigma*np.random.randn(1000000)
900
-
901
- #plt.figure(figsize=(12.8,6.4))
902
- import seaborn as sns
903
- #绘制曲线:股票收益率
904
- sns.kdeplot(data=rets,shade=True,color='blue',legend=True,label=ticker_name(ticker),lw=2)
905
- #绘制曲线:对应的正态分布
906
- sns.kdeplot(data=x,shade=True,color='r',legend=True,label='正态分布',ls='--')
907
- #设置标题、图例、坐标轴标签
908
- plt.ylabel('',fontsize=ylabel_txt_size)
909
- #plt.xlabel('收益率')
910
- plt.legend(loc='best',fontsize=legend_txt_size)
911
- titletxt="正态性检验: "+ticker_name(ticker)+",收益率, "+start+"至"+end
912
- plt.title(titletxt,fontsize=title_txt_size)
913
-
914
- import datetime as dt; today=dt.date.today()
915
- footnote="数据来源:新浪/stooq,"+str(today)
916
- plt.xlabel(footnote,fontsize=xlabel_txt_size)
917
- plt.show()
918
-
919
- return
920
-
921
-
922
- if __name__ == '__main__':
923
- plot_rets_curve('JD','2019-1-1','2019-6-30')
924
-
925
-
926
- #===========================================================================
927
- def stock_ret_Normality_SW(ticker,start='MRY',end='today',siglevel=0.05):
928
- """
929
- 功能:测试一个日收益率序列是否符合正态分布,原假设:符合正态分布
930
- 输入参数:股票代码,开始日期,结束日期
931
- 输出:日收益率序列正态性检验的p-value
932
- start_date,end_date均为datetime类型
933
- 【Shapiro-Wilk正态性检验】原假设:服从正态分布
934
- """
935
- start_date,end_date=start_end_preprocess(start,end)
936
-
937
- from scipy import stats
938
-
939
- quotes=get_stock_quotes(ticker,start_date,end_date)
940
- if quotes is None: return None
941
- if len(quotes) == 0: return None
942
-
943
- ret=get_ret_series(quotes)
944
- (W,p_value)=stats.shapiro(ret)
945
-
946
- """
947
- print("\n= Shapiro-Wilk正态性检验: 股票收益率 =")
948
- print("股票 :",ticker_name(ticker))
949
- print("期间 :",start_date,"至",end_date)
950
- print("原假设: 符合正态分布")
951
- print("W值 :",round(W,4))
952
- print("p值 :",round(p_value,4))
953
- if p_value >= siglevel:
954
- print("结果 : 接受原假设, 符合正态分布")
955
- else:
956
- print("结果 : 拒绝原假设, 不符合正态分布")
957
- import datetime as dt; today=dt.date.today()
958
- print("*数据来源:新浪/stooq,"+str(today))
959
- """
960
-
961
- titletxt="Shapiro-Wilk检验: 收益率"
962
- data_dict1={'股票:':ticker_name(ticker), \
963
- '期间:':start_date+"至"+end_date, \
964
- '原假设:':'符合正态分布', \
965
- 'W值:':round(W,4), \
966
- 'p值:':round(p_value,4)}
967
-
968
- if p_value >= siglevel:
969
- result="接受原假设, 符合正态分布"
970
- else:
971
- result="拒绝原假设, 不符合正态分布"
972
- data_dict2={'结果:':result}
973
- data_dict={**data_dict1,**data_dict2}
974
-
975
- import datetime as dt; todaydt=dt.date.today()
976
- footnote="数据来源:新浪/stooq,"+str(todaydt)
977
-
978
- print2CSS(data_dict,titletxt=titletxt,footnote=footnote)
979
-
980
- return p_value
981
-
982
- #==============================================================================
983
- def VaR_normal_modified(position,ret_series,future_days=1,alpha=0.99):
984
- """
985
- 功能:VaR基本算法,修正正态法
986
- #输入参数:持有头寸金额,日收益率序列,未来持有日期,置信度
987
- #输出参数:VaR(金额)
988
- """
989
- #去掉空值
990
- r=ret_series[~ret_series.isnull()]
991
-
992
- from scipy import stats
993
- import numpy as np
994
-
995
- z=np.abs(stats.norm.ppf(1-alpha))
996
- S=stats.skew(r)
997
- K=stats.kurtosis(r)
998
-
999
- t1=1/6*(np.power(z,2)-1)*S
1000
- t2=1/24*(np.power(z,3)-3*z)*K
1001
- t3=1/36*(2*np.power(z,3)-5*z)*np.power(S,2)
1002
- t=z+t1+t2-t3
1003
-
1004
- miu_daily=np.mean(r)
1005
- miu_days=np.power(miu_daily+1,future_days)-1
1006
- sigma_daily=np.std(r)
1007
- sigma_days=np.sqrt(future_days)*sigma_daily
1008
-
1009
- ratio=miu_days+t*sigma_days
1010
- VaR_days=position*ratio
1011
-
1012
- return -abs(VaR_days)
1013
-
1014
- #==============================================================================
1015
- def stock_VaR_normal_modified(ticker,shares,today, \
1016
- future_days=1,alpha=0.99,pastyears=1,printout=True):
1017
- """
1018
- 功能:计算持有一定量股票若干天的VaR,修正正态法
1019
- 输入参数:股票代码,持有股数,当前日期,未来持有天数,置信度,使用历史数据的年数
1020
- 注:当前日期可以为过去的任意一天,历史年数为使用几年的历史数据来分析
1021
- 输出:VaR(金额,负数),VaR比率
1022
- 注释:VaR比率,即每单位持有金额的在险价值
1023
- """
1024
- start=get_start_date(today,pastyears)
1025
- p=get_stock_quotes(ticker,start,today)
1026
- if (p is None) or (len(p)==0):
1027
- print(" #Error(stock_VaR_normal_modified): no observation retrieved.")
1028
- return None,None
1029
-
1030
- r=get_ret_series(p)
1031
- p_end=get_end_price(p)
1032
- position=shares*p_end
1033
- VaR=VaR_normal_modified(position,r,future_days,alpha)
1034
- #最大为全损
1035
- if abs(VaR) > position: VaR=-position
1036
-
1037
- VaR_ratio=abs(VaR/position)
1038
-
1039
- if printout == True:
1040
- """
1041
- print("\n=== 在险价值VaR: 修正正态模型 ===")
1042
- print("持有股票 :",ticker_name(ticker))
1043
- print("持有股数 :",format(shares,','))
1044
- print("持有日期 :",today)
1045
- print("预计持有天数:",future_days)
1046
- print("置信度 : ",alpha*100,'%',sep='')
1047
- print("VaR金额 :",format(round(VaR,2),','))
1048
- print("VaR比例 : ",round(VaR_ratio*100,2),'%',sep='')
1049
-
1050
- import datetime as dt; today=dt.date.today()
1051
- print("*数据来源:新浪/stooq,"+str(today))
1052
- """
1053
- titletxt="在险价值:修正正态模型"
1054
- import datetime as dt; todaydt=dt.date.today()
1055
- footnote="数据来源:新浪/stooq,"+str(todaydt)
1056
-
1057
- data_dict={'持有股票:':ticker_name(ticker), \
1058
- '持有股数:':format(shares,','), \
1059
- '持有日期:':today, \
1060
- '预计持有天数:':future_days, \
1061
- '置信度:':str(alpha*100)+'%', \
1062
- '在险价值VaR金额:':format(round(VaR,2),','), \
1063
- '在险价值VaR比例:':str(round(VaR_ratio*100,2))+'%'}
1064
-
1065
- print2CSS(data_dict,titletxt=titletxt,footnote=footnote)
1066
-
1067
- return VaR,VaR_ratio
1068
-
1069
- #==============================================================================
1070
- def series_VaR_normal_modified(ticker,shares,datelist, \
1071
- future_days=1,alpha=0.99,pastyears=1,printout=True):
1072
- """
1073
- 功能:一步计算多个日期的VaR,修正正态分布法
1074
- 输入参数:股票代码,持有股数,日期列表,未来持有天数,置信度,使用历史数据的年数
1075
- 注释:当前日期可以为过去的任意一天,历史年数为使用几年的历史数据来分析
1076
- 输出:VaR信息表(日期,股票代码,VaR金额,VaR比率)
1077
- """
1078
- # datelist是datetime类型日期的列表
1079
- import pandas as pd
1080
- result=pd.DataFrame(columns=['date','ticker','VaR','ratio'])
1081
- for d in datelist:
1082
- VaR,ratio=stock_VaR_normal_modified(ticker,shares,d, \
1083
- future_days,alpha,pastyears,printout=False)
1084
- s = pd.Series({'date':d,'ticker':ticker,'VaR':VaR,'ratio':ratio})
1085
- try:
1086
- result=result.append(s,ignore_index=True)
1087
- except:
1088
- result=result._append(s,ignore_index=True)
1089
-
1090
- result2=result.set_index(['date'])
1091
- # result2是dateframe类型
1092
-
1093
- if printout == False: return result2
1094
-
1095
- #打印
1096
- result3=result2.copy()
1097
- result3['VaR金额']=round(result3['VaR'],2)
1098
- result3['VaR比例%']=round(result3['ratio']*100,2)
1099
- result3.drop(columns=['ticker','VaR','ratio'],inplace=True)
1100
-
1101
- text1="= "+ticker_name(ticker)+": VaR比例,持有"+str(future_days)+"天 ="
1102
- print(text1)
1103
- print(result3)
1104
- import datetime as dt; today=dt.date.today()
1105
- print("数据来源:新浪/stooq,"+str(today))
1106
-
1107
- #绘图
1108
- #VaR金额绘图
1109
- plt.plot(result3['VaR金额'],c='r',lw=2)
1110
- title1=ticker_name(ticker)+": VaR金额的变化,持有"+str(future_days)+"天"
1111
- plt.title(title1)
1112
- plt.ylabel('VaR金额')
1113
- plt.xticks(rotation=30)
1114
-
1115
- footnote="数据来源:新浪/stooq,"+str(today)
1116
- plt.xlabel(footnote)
1117
- plt.show()
1118
-
1119
- plt.plot(result3['VaR比例%'],c='r',lw=2)
1120
- title2=ticker_name(ticker)+": VaR比例的变化,持有"+str(future_days)+"天"
1121
- plt.title(title2)
1122
- plt.ylabel('VaR比例%')
1123
- plt.xticks(rotation=30)
1124
- plt.xlabel(footnote)
1125
- plt.show()
1126
-
1127
- return result2
1128
-
1129
-
1130
- #==============================================================================
1131
- def compare_VaR_normal_modified(tickerlist,shares,datelist, \
1132
- future_days=1,alpha=0.99,pastyears=1):
1133
- """
1134
- 功能:比较多个日期持有一定天数股票资产的VaR高低,修正正态法
1135
- 输入参数:股票列表,持有股数,日期列表(日期型列表),未来持有时间(天数),置信度,使用历史数据的年数
1136
- 输出:无
1137
- 显示:折线图,各个资产的VaR金额和比率对比
1138
- """
1139
-
1140
- import os, sys
1141
- class HiddenPrints:
1142
- def __enter__(self):
1143
- self._original_stdout = sys.stdout
1144
- sys.stdout = open(os.devnull, 'w')
1145
- def __exit__(self, exc_type, exc_val, exc_tb):
1146
- sys.stdout.close()
1147
- sys.stdout = self._original_stdout
1148
-
1149
- print(" The comparison may take time, please wait ...")
1150
- markerlist=['.','o','s','*','+','x','1','2']
1151
- for t in tickerlist:
1152
- pos=tickerlist.index(t)
1153
- thismarker=markerlist[pos]
1154
-
1155
- with HiddenPrints():
1156
- r=series_VaR_normal_modified(t,shares,datelist, \
1157
- future_days,alpha,pastyears,printout=False)
1158
- rr=r.copy()
1159
- rr['VaR amount']=round(rr['VaR'],2)
1160
- rr.drop(columns=['ticker','VaR','ratio'],inplace=True)
1161
- plt.plot(rr['VaR amount'],label=ticker_name(t),lw=2,marker=thismarker)
1162
-
1163
- title1="比较VaR金额,持有"+str(future_days)+"天"
1164
- plt.title(title1)
1165
- plt.ylabel('VaR金额')
1166
- plt.xticks(rotation=30)
1167
- plt.legend(loc='best')
1168
-
1169
- notes="【注】VaR计算模型:修正正态法"
1170
- import datetime as dt; today=dt.date.today()
1171
- source="数据来源:新浪/stooq,"+str(today)
1172
- footnote=notes+'\n'+source
1173
- plt.xlabel(footnote)
1174
- plt.show()
1175
-
1176
- for t in tickerlist:
1177
- pos=tickerlist.index(t)
1178
- thismarker=markerlist[pos]
1179
-
1180
- with HiddenPrints():
1181
- r=series_VaR_normal_modified(t,shares,datelist, \
1182
- future_days,alpha,pastyears,printout=False)
1183
- rr=r.copy()
1184
- rr['VaR ratio %']=round(rr['ratio']*100,2)
1185
- rr.drop(columns=['ticker','VaR','ratio'],inplace=True)
1186
- plt.plot(rr['VaR ratio %'],label=ticker_name(t),lw=2,marker=thismarker)
1187
-
1188
- title2="比较VaR比例,持有"+str(future_days)+"天"
1189
- plt.title(title2)
1190
- plt.ylabel('VaR比例%')
1191
- plt.xticks(rotation=45)
1192
- plt.legend(loc='best')
1193
- plt.xlabel(footnote)
1194
- plt.show()
1195
-
1196
- return
1197
-
1198
- if __name__ == '__main__':
1199
- tickerlist=['BABA','PDD','JD']
1200
- datelist=['2019-01-01','2019-02-01','2019-03-01','2019-04-01', \
1201
- '2019-05-01','2019-06-01','2019-07-01']
1202
- compare_VaR_normal_standard(tickerlist,10000,datelist,1,0.99)
1203
-
1204
-
1205
- #==============================================================================
1206
- def VaR_historical_1d(position,ret_series,alpha=0.99):
1207
- """
1208
- 功能:计算VaR基本算法,历史模拟法,持有1天
1209
- 输入参数:持有头寸金额,历史日收益率序列,置信度
1210
- 输出:持有一天的VaR(金额)
1211
- """
1212
- #去掉空值
1213
- r=ret_series[~ret_series.isnull()]
1214
-
1215
- import numpy as np
1216
- n=len(r)
1217
- t=int(n*(1-alpha))
1218
- SR=np.sort(r)
1219
- if t>=1:
1220
- A=SR[t-1] #SR的第一个元素的序号是0
1221
- else:
1222
- A=SR[0]
1223
- VaR_1d=position*A
1224
-
1225
- return -abs(VaR_1d)
1226
-
1227
-
1228
- #==============================================================================
1229
- def stock_VaR_historical_1d(ticker,shares,today,alpha=0.99, \
1230
- pastyears=1,printout=True):
1231
- """
1232
- 功能:计算持有股票的VaR,历史模拟法,持有1天
1233
- 输入参数:股票代码,持有股数,当前日期,置信度,使用历史数据的年数
1234
- 输出:持有一天的VaR(金额和比率)
1235
- """
1236
- start=get_start_date(today,pastyears)
1237
- p=get_stock_quotes(ticker,start,today)
1238
- if (p is None) or (len(p)==0):
1239
- print("#Error(stock_VaR_historical_1d): no obs retrieved.")
1240
- return None,None
1241
-
1242
- r=get_ret_series(p)
1243
- p_end=get_end_price(p)
1244
- position=shares*p_end
1245
- VaR_1d=VaR_historical_1d(position,r,alpha)
1246
- #最高为全损
1247
- if abs(VaR_1d)>position: VaR_1d=-position
1248
- VaR_ratio=abs(VaR_1d/position)
1249
-
1250
- if printout == True:
1251
- """
1252
- print("\n=== 计算在险价值VaR:历史模拟方法 ===")
1253
- print("持有股票 :",ticker_name(ticker))
1254
- print("持有股数 :",format(shares,','))
1255
- print("持有日期 :",today)
1256
- future_days=1
1257
- print("预计持有日期:",future_days)
1258
- print("置信度 : ",alpha*100,'%',sep='')
1259
- print("VaR金额 :",format(round(VaR_1d,2),','))
1260
- print("VaR比例 : ",round(VaR_ratio*100,2),'%',sep='')
1261
-
1262
- import datetime as dt; today=dt.date.today()
1263
- print("*数据来源:新浪/stooq,"+str(today))
1264
- """
1265
- titletxt="在险价值:历史模拟方法"
1266
- import datetime as dt; todaydt=dt.date.today()
1267
- footnote="数据来源:新浪/stooq,"+str(todaydt)
1268
-
1269
- future_days=1
1270
- data_dict={'持有股票:':ticker_name(ticker), \
1271
- '持有股数:':format(shares,','), \
1272
- '持有日期:':today, \
1273
- '预计持有天数:':future_days, \
1274
- '置信度:':str(alpha*100)+'%', \
1275
- '在险价值VaR金额:':format(round(VaR_1d,2),','), \
1276
- '在险价值VaR比例:':str(round(VaR_ratio*100,2))+'%'}
1277
-
1278
- print2CSS(data_dict,titletxt=titletxt,footnote=footnote)
1279
-
1280
- return VaR_1d,VaR_ratio
1281
-
1282
- if __name__ == '__main__':
1283
- ticker='BABA'
1284
- shares=1000
1285
- today='2020-7-1'
1286
- alpha=0.99
1287
- pastyears=1
1288
- printout=True
1289
- VaR,Ratio=stock_VaR_historical_1d(ticker,shares,today)
1290
- #==============================================================================
1291
- def VaR_historical_grouping(position,ret_series,future_days=1,alpha=0.99):
1292
- """
1293
- 功能:计算VaR基本算法,历史模拟法,持有多天(基本分组法,无组内收益率波动调整)
1294
- 输入参数:当前头寸金额,历史日收益率序列,未来持有天数,置信度
1295
- 注意:分组法需要更长时间的历史数据,不然准确度不高!
1296
- 输出:持有多天的VaR(金额)
1297
- """
1298
- #去掉空值
1299
- r=ret_series[~ret_series.isnull()]
1300
-
1301
- import pandas as pd
1302
- #将收益率序列转变为df
1303
- r1=pd.DataFrame(r)
1304
-
1305
- #定义组内累计收益率计算方法
1306
- cumret=lambda x:(x+1.0).prod()-1.0
1307
- #使用滚动窗口分组,计算各组收益率gret
1308
- r1['gret']=r1.rolling(future_days).apply(cumret)
1309
- #将各组收益率转换为组收益率序列
1310
- r2=pd.Series(r1['gret'])
1311
-
1312
- #利用单日历史模拟法计算VaR
1313
- VaR_days=VaR_historical_1d(position,r2,alpha)
1314
-
1315
- return -abs(VaR_days)
1316
-
1317
- if __name__ == '__main__':
1318
- ticker='BABA'
1319
- start='2020-6-1'
1320
- today='2020-7-1'
1321
- p=get_stock_quotes(ticker,start,today)
1322
- ret_series=get_ret_series(p)
1323
- future_days=2
1324
-
1325
- shares=1000
1326
- alpha=0.99
1327
- pastyears=1
1328
- printout=True
1329
- position=1
1330
-
1331
- VaR=VaR_historical_grouping(position,ret_series,future_days)
1332
-
1333
-
1334
- #==============================================================================
1335
- def VaR_historical(position,ret_series,future_days=1,alpha=0.99):
1336
- """
1337
- 功能:同名函数,为了后面函数名称合成方便
1338
- """
1339
- VaR=VaR_historical_grouping(position,ret_series,future_days,alpha)
1340
- return VaR
1341
-
1342
- #==============================================================================
1343
- def stock_VaR_historical_grouping(ticker,shares,today, \
1344
- future_days=1,alpha=0.99,pastyears=1,printout=True):
1345
- """
1346
- 功能:计算持有股票的VaR,历史模拟法,持有多天(基本分组法,无组内收益率波动调整)
1347
- 输入参数:股票代码,持有股数,当前日期,未来持有天数,置信度,使用历史数据的年数
1348
- 注意:分组法需要更长时间的历史数据,不然准确度不高!
1349
- 建议:pastyears的数值大于等于future_days的数值
1350
- 输出:基本分组法,持有多天的VaR(金额和比率)
1351
- """
1352
- start=get_start_date(today,pastyears)
1353
- p=get_stock_quotes(ticker,start,today)
1354
- if (p is None) or (len(p)==0):
1355
- print("#Error(stock_VaR_historical_grouping): no obs retrieved.")
1356
- return None,None
1357
- p_end=get_end_price(p); position=shares*p_end
1358
-
1359
- #产生历史收益率序列
1360
- r=get_ret_series(p)
1361
- #分组计算
1362
- VaR_days=VaR_historical_grouping(position,r,future_days,alpha)
1363
- #最大为全损
1364
- if abs(VaR_days) > position: VaR_days=-position
1365
-
1366
- VaR_ratio=abs(VaR_days/position)
1367
-
1368
- if future_days == 1:
1369
- modeltxt="历史排序模拟法"
1370
- else:
1371
- modeltxt="分组历史模拟法"
1372
-
1373
- if printout == True:
1374
- """
1375
- print("\n=== 在险价值VaR:"+modeltxt+" ===")
1376
- print("持有股票 :",ticker_name(ticker))
1377
- print("持有股数 :",format(shares,','))
1378
- print("持有日期 :",today)
1379
- print("预计持有天数:",future_days)
1380
- print("置信度 :",alpha*100,'%',sep='')
1381
- print("VaR金额 :",format(round(VaR_days,2),','))
1382
- print("VaR比例 :",round(VaR_ratio*100,2),'%',sep='')
1383
-
1384
- import datetime as dt; today=dt.date.today()
1385
- print("*数据来源:新浪/stooq,"+str(today))
1386
- """
1387
-
1388
- titletxt="在险价值:"+modeltxt
1389
- import datetime as dt; todaydt=dt.date.today()
1390
- footnote="数据来源:新浪/stooq,"+str(todaydt)
1391
-
1392
- data_dict={'持有股票:':ticker_name(ticker), \
1393
- '持有股数:':format(shares,','), \
1394
- '持有日期:':today, \
1395
- '预计持有天数:':future_days, \
1396
- '置信度:':str(alpha*100)+'%', \
1397
- '在险价值VaR金额:':format(round(VaR_days,2),','), \
1398
- '在险价值VaR比例:':str(round(VaR_ratio*100,2))+'%'}
1399
-
1400
- print2CSS(data_dict,titletxt=titletxt,footnote=footnote)
1401
-
1402
-
1403
- return -abs(VaR_days),VaR_ratio
1404
-
1405
- #==============================================================================
1406
- def VaR_montecarlo(position,ret_series, \
1407
- future_days=1,alpha=0.99,random=10000,mctype='random'):
1408
- """
1409
- 功能:计算VaR基本算法,蒙特卡洛模拟法,持有多日
1410
- 输入参数:当前头寸金额,历史日收益率序列,未来持有天数,置信度,重复模拟次数
1411
- 注:重复模拟次数越多,准确率就越高,但耗时也越多
1412
- 输出:持有多天的VaR(金额)
1413
- """
1414
- #去掉空值
1415
- r=ret_series[~ret_series.isnull()]
1416
-
1417
- import pandas as pd
1418
- #蒙特卡洛模拟类型:随机数or超采样
1419
- if mctype=='random': #随机数产生新的序列
1420
- import numpy as np
1421
- #取得历史日收益率的均值和标准差
1422
- miu=np.mean(r)
1423
- sigma=np.std(r)
1424
- #生成随机数序列
1425
- np.random.seed(12345)
1426
- #按照历史日收益率的均值和标准差重复模拟一定次数,生成新的日收益率序列
1427
- RR=pd.Series(np.random.normal(miu,sigma,random))
1428
- else: #超采样产生新的序列
1429
- #将收益率序列转变为df
1430
- r1=pd.DataFrame(r)
1431
- r2=r1.sample(n=random,replace=True)
1432
- r2.sort_index(inplace=True)
1433
- RR=pd.Series(r2.iloc[:,0])
1434
-
1435
- #基于新的日收益率序列,使用标准正态法计算VaR
1436
- VaR_days=VaR_historical_grouping(position,RR,future_days,alpha)
1437
-
1438
- return -abs(VaR_days)
1439
-
1440
-
1441
- #==============================================================================
1442
- def stock_VaR_montecarlo(ticker,shares,today,future_days=1,alpha=0.99, \
1443
- pastyears=1,random=10000,printout=True,mctype='random'):
1444
- """
1445
- 功能:计算持有股票的VaR,蒙特卡洛模拟法,持有多日
1446
- 输入参数:股票代码,持有股数,当前日期,未来持有天数,置信度,使用历史数据的年数,
1447
- 重复模拟次数
1448
- 输出:持有股票多天的VaR(金额和比率)
1449
- """
1450
- start=get_start_date(today,pastyears)
1451
- p=get_stock_quotes(ticker,start,today)
1452
- if (p is None) or (len(p)==0):
1453
- print("#Error(stock_VaR_montecarlo): no obs retrieved.")
1454
- return None,None
1455
- r=get_ret_series(p)
1456
- p_end=get_end_price(p)
1457
- position=shares*p_end
1458
-
1459
- VaR_days=VaR_montecarlo(position,r,future_days,alpha,random,mctype=mctype)
1460
- ratio=abs(VaR_days/position)
1461
- #最大为全损
1462
- if abs(VaR_days) > position: VaR_days=-position
1463
-
1464
- if printout == True:
1465
- """
1466
- print("\n=== 在险价值VaR:蒙特卡洛模拟法 ===")
1467
- print("持有日期 :",today)
1468
- print("持有股票 :",ticker_name(ticker))
1469
- print("持有股数 :",format(shares,','))
1470
- print("持有头寸 :",format(round(position,2),','))
1471
- print("预计持有天数:",future_days)
1472
- print("置信度 : ",alpha*100,'%',sep='')
1473
- print("序列生成方法:",mctype)
1474
- print("VaR金额 :",format(round(VaR_days,2),','))
1475
- #四舍五不入
1476
- print("VaR比例 : ",(int(ratio*10000))/100,'%',sep='')
1477
-
1478
- import datetime as dt; today=dt.date.today()
1479
- print("*数据来源:新浪/stooq,"+str(today))
1480
- """
1481
- titletxt="在险价值:蒙特卡洛模拟法"
1482
- import datetime as dt; todaydt=dt.date.today()
1483
- footnote="数据来源:新浪/stooq,"+str(todaydt)
1484
-
1485
- data_dict={'持有股票:':ticker_name(ticker), \
1486
- '持有股数:':format(shares,','), \
1487
- '持有头寸:':format(round(position,2),','), \
1488
- '持有日期:':today, \
1489
- '预计持有天数:':future_days, \
1490
- '序列生成方法:':mctype, \
1491
- '置信度:':str(alpha*100)+'%', \
1492
- '在险价值VaR金额:':format(round(VaR_days,2),','), \
1493
- '在险价值VaR比例:':str(round(ratio*100,2))+'%'}
1494
-
1495
- print2CSS(data_dict,titletxt=titletxt,footnote=footnote)
1496
-
1497
- return VaR_days,ratio
1498
-
1499
-
1500
- #==============================================================================
1501
- def calc_VaR_tlcp(ticker,today,alpha=0.99, \
1502
- pastyears=1,model="normal_standard",printout=True):
1503
- """
1504
- 功能:计算一只股票的VaR全损临界点,即VaR达到持有全部头寸的最小天数
1505
- 输入:股票代码,持有日期,置信度,使用历史数据的年数,
1506
- 使用的模型,是否打印结果
1507
- 输出:股票的VaR全损临界点天数,与使用的模型有关
1508
- 显示:无
1509
- """
1510
- print("\n...Calculatiing tlcp of",ticker,"\b, please wait...")
1511
-
1512
- #检查model类型
1513
- modellist=['normal_standard','normal_modified','montecarlo']
1514
- model=model.lower()
1515
- if model not in modellist:
1516
- print("#Error(calc_VaR_tlcp): Unsupported type of model")
1517
- print("Information:",model)
1518
- print("Supported models:",modellist)
1519
- return
1520
-
1521
- #抓取股价,计算历史收益率序列和当前头寸
1522
- start=get_start_date(today,pastyears)
1523
- p=get_stock_quotes(ticker,start,today)
1524
- if (p is None) or (len(p)==0):
1525
- print("#Error(calc_VaR_tlcp): no obs retrieved.")
1526
- return None
1527
- r=get_ret_series(p)
1528
- p_end=get_end_price(p)
1529
- shares=1
1530
- position=shares*p_end
1531
-
1532
- #第1轮搜索,步长1000天
1533
- func="VaR_"+model
1534
- import numpy as np
1535
- stop1=0; max1=9000
1536
- for d in np.arange(0,max1+1000,1000):
1537
- VaR=eval(func)(position,r,d,alpha)
1538
- ratio=abs(VaR)/position*100
1539
- if ratio >= 100.0:
1540
- stop1=d
1541
- break
1542
- if stop1==0:
1543
- if printout == True:
1544
- """
1545
- print("\n=== VaR的全损临界点TLCP ===")
1546
- print("持有股票 :",ticker_name(ticker))
1547
- print("持有日期 :",today)
1548
- print("使用的模型:",model)
1549
- print("置信度 : ",alpha*100,'%',sep='')
1550
- print("TLCP天数 : >",format(max1,','))
1551
-
1552
- print("*注:实际发生全损的概率极小")
1553
- import datetime as dt; today=dt.date.today()
1554
- print("数据来源:新浪/stooq,"+str(today))
1555
- """
1556
- titletxt="VaR全损临界点"
1557
- import datetime as dt; todaydt=dt.date.today()
1558
- ft0="*注:实际发生全损的概率极小"
1559
- footnote=ft0+'\n'+"数据来源:新浪/stooq,"+str(todaydt)
1560
-
1561
- data_dict={'持有股票:':ticker_name(ticker), \
1562
- '持有日期:':today, \
1563
- '使用的模型:':model, \
1564
- '置信度:':str(alpha*100)+'%', \
1565
- '全损临界点TLCP天数 >':format(max1,',')}
1566
-
1567
- print2CSS(data_dict,titletxt=titletxt,footnote=footnote)
1568
-
1569
- return max1
1570
-
1571
- #第2轮搜索,步长100天
1572
- stop2=100
1573
- for d in np.arange(stop1-1000,stop1+100,100):
1574
- VaR=eval(func)(position,r,d,alpha)
1575
- ratio=abs(VaR)/position*100
1576
- if ratio >= 100.0:
1577
- stop2=d
1578
- break
1579
-
1580
- #第3轮搜索,步长10天
1581
- stop3=10
1582
- for d in np.arange(stop2-100,stop2+10,10):
1583
- VaR=eval(func)(position,r,d,alpha)
1584
- ratio=abs(VaR)/position*100
1585
- if ratio >= 100.0:
1586
- stop3=d
1587
- break
1588
-
1589
- #第4轮搜索,步长1天
1590
- stop4=1
1591
- for d in np.arange(stop3-10,stop3+1,1):
1592
- VaR=eval(func)(position,r,d,alpha)
1593
- ratio=abs(VaR)/position*100
1594
- if ratio >= 100.0:
1595
- stop4=d
1596
- break
1597
-
1598
- if printout == True:
1599
- """
1600
- print("\n=== VaR的全损临界点TLCP ===")
1601
- print("持有股票 :",ticker_name(ticker))
1602
- print("持有日期 :",today)
1603
- print("使用的模型:",model)
1604
- print("置信度 : ",alpha*100,'%',sep='')
1605
- print("TLCP天数 : >",format(stop4,','))
1606
- """
1607
-
1608
- titletxt="VaR全损临界点"
1609
- import datetime as dt; todaydt=dt.date.today()
1610
- ft0="*注:实际发生全损的概率极小"
1611
- footnote=ft0+'\n'+"数据来源:新浪/stooq,"+str(todaydt)
1612
-
1613
- data_dict={'持有股票:':ticker_name(ticker), \
1614
- '持有日期:':today, \
1615
- '使用的模型:':model, \
1616
- '置信度:':str(alpha*100)+'%', \
1617
- '全损临界点TLCP天数 >':format(stop4,',')}
1618
-
1619
- print2CSS(data_dict,titletxt=titletxt,footnote=footnote)
1620
-
1621
-
1622
- return stop4
1623
-
1624
- if __name__ == "__main__":
1625
- ticker='AAPL'
1626
- today='2020-7-20'
1627
- alpha=0.99
1628
- pastyears=1
1629
- model="montecarlo"
1630
- printout=True
1631
- tlcp=calc_VaR_tlcp('MSFT','2019-8-8')
1632
-
1633
- #==============================================================================
1634
- def series_VaR_tlcp(tickerlist,today,alpha=0.99,pastyears=1,model="montecarlo"):
1635
- """
1636
- 功能:计算股票列表中各个股票的VaR全损临界点(天数)
1637
- 输出:各个股票的VaR全损临界点(天数)列表
1638
- 显示:柱状图,从小到大排序
1639
- """
1640
-
1641
- #仅测试用
1642
- #tickerlist=['BABA','JD','VIPS','PDD']
1643
- #today='2019-8-8'
1644
- #alpha=0.99
1645
- #pastyears=1
1646
- #model="montecarlo"
1647
- print("\n*** It may need very long time to calculate, please wait ...")
1648
-
1649
- import pandas as pd
1650
- tlcpdf=pd.DataFrame(columns=['Ticker','Holding date','Alpha','Model','TLCP'])
1651
- for t in tickerlist:
1652
- tlcp=calc_VaR_tlcp(t,today,alpha,pastyears,model,printout=False)
1653
- row=pd.Series({'Ticker':t,'Holding date':today,'Alpha':alpha, \
1654
- 'Model':model,'TLCP':tlcp})
1655
- try:
1656
- tlcpdf=tlcpdf.append(row,ignore_index=True)
1657
- except:
1658
- tlcpdf=tlcpdf._append(row,ignore_index=True)
1659
-
1660
- #print("TLCP for stock ",t,": ",tlcp," days",sep='')
1661
- #tlcpdf=tlcpdf.set_index('Ticker')
1662
- tlcpdf=tlcpdf.sort_values(axis=0,ascending=True,by = 'TLCP')
1663
- #tlcpdf.reset_index(drop=True)
1664
- tlcpdf.set_index('Ticker',drop=True,inplace=True)
1665
- """
1666
- #ax=plt.figure(figsize=(12.8,6.4))
1667
- tlcpdf.plot.barh(x='Ticker',y='TLCP',color='r',grid=True)
1668
- plt.ylabel('股票')
1669
- titlel1="VaR全损临界点(TLCP)"
1670
- titlel2="\n"+str(today)+", 使用模型"+model+", 置信度"+str(alpha*100)+"%"
1671
- titletxt=titlel1+titlel2
1672
- plt.title(titletxt)
1673
-
1674
- import datetime as dt; today=dt.date.today()
1675
- footnote='TLCP天数-->'+"\n数据来源:新浪/stooq,"+str(today)
1676
- plt.xlabel(footnote)
1677
- plt.show()
1678
- """
1679
- titlel1="VaR全损临界点(TLCP)"
1680
- titlel2="\n"+str(today)+", 使用模型"+model+", 置信度"+str(alpha*100)+"%"
1681
- titletxt=titlel1+titlel2
1682
- import datetime as dt; today=dt.date.today()
1683
- footnote='TLCP天数-->'+"\n数据来源:新浪/stooq,"+str(today)
1684
- import siat.grafix as g
1685
- g.plot_barh(tlcpdf,'TLCP',titletxt,footnote)
1686
-
1687
- """
1688
- print("===== VaR全损临界点(TLCP, 天数) =====")
1689
- print("持有日期 :",today)
1690
- print("使用的模型:",model)
1691
- print("置信度 :",alpha*100,'%',sep='')
1692
- print(tlcpdf)
1693
- print("数据来源:新浪/stooq,"+str(today))
1694
- """
1695
-
1696
- titletxt="VaR全损临界点(TLCP, 天数)"
1697
- import datetime as dt; todaydt=dt.date.today()
1698
- footnote="数据来源:新浪/stooq,"+str(todaydt)
1699
-
1700
- data_dict={'持有日期:':today, \
1701
- '使用的计算模型:':model, \
1702
- '置信度:':str(alpha*100)+'%'}
1703
-
1704
- print2CSS(data_dict,titletxt='',footnote='')
1705
- df_display_CSS(tlcpdf,titletxt=titletxt,footnote=footnote,facecolor='papayawhip',decimals=2, \
1706
- hide_columns=False,
1707
- first_col_align='left',second_col_align='right', \
1708
- last_col_align='right',other_col_align='right', \
1709
- titile_font_size='14px',heading_font_size='14px', \
1710
- data_font_size='14px',footnote_font_size='12px')
1711
-
1712
- return tlcpdf
1713
-
1714
-
1715
- #==============================================================================
1716
- def plot_VaR_days_changes(ticker,shares,today,dayslist,alpha=0.99, \
1717
- pastyears=1,model="montecarlo", \
1718
- printout=True, markertype='.'):
1719
- """
1720
- 功能:计算持有股票的VaR,持有多个日期
1721
- 输入参数:股票代码,持有股数,当前日期,未来持有天数列表,置信度,
1722
- 使用历史数据的年数,算法,默认为蒙特卡洛模拟法
1723
- 输出:持有股票多个日期的VaR(金额和比率),数据框格式
1724
- """
1725
-
1726
- #仅测试用
1727
- #ticker='AAPL'
1728
- #shares=1000
1729
- #today='2019-8-8'
1730
- #dayslist=[1,5,10,15,30,90,180]
1731
- #alpha=0.99
1732
- #pastyears=1
1733
- #model="montecarlo"
1734
- #printout=True
1735
-
1736
- print("\n... Calculating VaR may take great time, please wait...")
1737
- #抓取股价,计算历史收益率序列和当前头寸
1738
- start=get_start_date(today,pastyears)
1739
- p=get_stock_quotes(ticker,start,today)
1740
- if (p is None) or (len(p)==0): return None
1741
- r=get_ret_series(p)
1742
- p_end=get_end_price(p)
1743
- position=shares*p_end
1744
-
1745
- #计算各个持有天数的VaR
1746
- import pandas as pd
1747
- vardf=pd.DataFrame(columns=['ticker','holding date','holding days','VaR','ratio%'])
1748
- for d in dayslist:
1749
- func="VaR_"+model
1750
- #print(ticker,shares,today,d,alpha)
1751
- VaR=round((eval(func)(position,r,d,alpha)),0)
1752
- ratio=round((abs(VaR)/position*100),2)
1753
- if ratio >= 100.0: ratio=100.0
1754
- s = pd.Series({'ticker':ticker,'holding date':today,'holding day(s)':d, \
1755
- 'VaR':VaR,'ratio%':ratio})
1756
- try:
1757
- vardf=vardf.append(s,ignore_index=True)
1758
- except:
1759
- vardf=vardf._append(s,ignore_index=True)
1760
-
1761
- vardf=vardf.set_index(['holding day(s)'])
1762
-
1763
- #绘图
1764
- if printout == True:
1765
- #plt.figure(figsize=(8,4))
1766
- plt.figure(figsize=(12.8,6.4))
1767
- #绘制曲线:ratio
1768
- plt.plot(vardf['ratio%'],color='red',lw=2,label=ticker_name(ticker),marker=markertype)
1769
- #设置标题、图例、坐标轴标签
1770
- plt.ylabel('VaR比例%')
1771
- plt.legend(loc='best')
1772
- titlel1="持有股票期间与VaR比例的变化趋势"
1773
- titlel2="\n"+ticker_name(ticker)+", "+today+", 使用模型"+model
1774
- titletxt=titlel1+titlel2
1775
- plt.title(titletxt)
1776
-
1777
- import datetime as dt; today=dt.date.today()
1778
- footnote='持有天数-->'+"\n数据来源:新浪/stooq,"+str(today)
1779
- plt.xlabel(footnote)
1780
- plt.show()
1781
-
1782
- return vardf
1783
-
1784
- #==============================================================================
1785
- def compare_VaR_days_changes(tickerlist,shares,today,dayslist,alpha=0.99, \
1786
- pastyears=1,model="montecarlo"):
1787
- """
1788
- 功能:计算多个股票的持有VaR,分别持有多个日期
1789
- 输入参数:股票代码列表,持有股数,当前日期,未来持有天数列表,置信度,
1790
- 使用历史数据的年数,算法,默认为蒙特卡洛模拟法
1791
- 输出:比较多支股票多个日期的VaR(金额和比率),数据框格式
1792
- 显示:绘图比较
1793
- """
1794
-
1795
- #仅测试用
1796
- #tickerlist=['BABA','JD','PDD']
1797
- #shares=1000
1798
- #today='2019-8-8'
1799
- #dayslist=[1,5,10,15,30,60,90,120,150,180,210,240,270,300,330,365]
1800
- #alpha=0.99
1801
- #pastyears=1
1802
- #model="montecarlo"
1803
-
1804
- #检查model类型
1805
- modellist=['normal_standard','normal_modified','historical','montecarlo']
1806
- model=model.lower()
1807
- if model not in modellist:
1808
- print("#Error(compare_VaR_days_changes): Unsupported type of model")
1809
- print("Information:",model)
1810
- print("Supported models:",modellist)
1811
- return
1812
-
1813
- #依次绘图tickerlist中的各个股票
1814
- #plt.figure(figsize=(8,4))
1815
- plt.figure(figsize=(12.8,6.4))
1816
-
1817
- markerlist=['.','o','s','*','+','x','1','2']
1818
- for t in tickerlist:
1819
- pos=tickerlist.index(t)
1820
- thismarker=markerlist[pos]
1821
- vardf=plot_VaR_days_changes(t,shares,today,dayslist,alpha, \
1822
- pastyears,model,printout=False,markertype=thismarker)
1823
- if vardf is None:
1824
- print("#Error(compare_VaR_days_changes): No available data")
1825
- print("Information:",t,today,pastyears,model)
1826
- continue
1827
-
1828
- plt.plot(vardf['ratio%'],lw=2,label=ticker_name(t),marker=thismarker)
1829
-
1830
- #设置标题、图例、坐标轴标签
1831
- plt.ylabel('VaR比例%')
1832
- plt.legend(loc='best')
1833
- titlel1="持有股票期间与VaR比例的变化趋势"
1834
- titlel2="\n股票: "+str(tickerlist)+", "+today+", 使用模型"+model
1835
- titlel3="\n注: 水平线表示VaR全损"
1836
- titletxt=titlel1+titlel2+titlel3
1837
- plt.title(titletxt)
1838
-
1839
- import datetime as dt; today=dt.date.today()
1840
- footnote='持有天数-->'+"\n数据来源:新浪/stooq,"+str(today)
1841
- plt.xlabel(footnote)
1842
- plt.show()
1843
-
1844
- return
1845
-
1846
- if __name__ =="__main__":
1847
- dayslist=[1,5,15,30,60,90,180,365]
1848
- compare_VaR_days_changes('AAPL','JD',1000,'2019-8-8',dayslist)
1849
-
1850
- #==============================================================================
1851
- def get_VaR_allmodels(ticker,shares,today, \
1852
- future_days=1,alpha=0.99,pastyears=1):
1853
- """
1854
- 功能:一次性计算各种模型方法的VaR
1855
- 输入参数:股票代码,持有股数,当前日期,未来持有天数,置信度,使用历史数据的年数
1856
- 股票代码:美股代码格式
1857
- 当前日期:datetime类型
1858
- 输出参数:各种模型的VaR金额和比率
1859
- 模型:标准正态法,修正正态法,历史模拟基本分组法,蒙特卡洛模拟法
1860
- """
1861
- #计算最低年数以保证历史模拟法至少拥有30个分组来确保结果的有效性
1862
- py=int(future_days*30/252)+1
1863
- if py > pastyears:
1864
- print("Warning: Historical samples too few, historical simulation may not work properly")
1865
-
1866
- #抓取开始日期
1867
- start=get_start_date(today,pastyears)
1868
- #抓取股价序列
1869
- quotes=get_stock_quotes(ticker,start,today)
1870
- if (quotes is None) or (len(quotes)==0):
1871
- print("#Error(get_VaR_allmodels): no obs retrieved.")
1872
- return None,None
1873
- #计算当前头寸
1874
- position=shares*get_end_price(quotes)
1875
- #计算收益率序列
1876
- rets=get_ret_series(quotes)
1877
-
1878
- #模型1:标准正太法。加0.5取整相当于四舍五入
1879
- VaR1=int(VaR_normal_standard(position,rets,future_days,alpha)+0.5)
1880
- ratio1=abs(round(VaR1/position,4))
1881
-
1882
- #模型2:修正正太法
1883
- VaR2=int(VaR_normal_modified(position,rets,future_days,alpha)+0.5)
1884
- ratio2=abs(round(VaR2/position,4))
1885
-
1886
- #模型3:历史模拟法-分组法
1887
- #VaR3=int(VaR_historical_cumulative(position,rets,future_days,alpha)+0.5)
1888
- VaR3=int(VaR_historical_grouping(position,rets,future_days,alpha)+0.5)
1889
- ratio3=abs(round(VaR3/position,4))
1890
-
1891
- #模型4:蒙特卡洛模拟法(标准正态分布)
1892
- VaR4=int(VaR_montecarlo(position,rets,future_days,alpha)+0.5)
1893
- ratio4=abs(round(VaR4/position,4))
1894
-
1895
- """
1896
- print("\n==== 不同模型下VaR的计算结果 ====")
1897
- print("持有日期 :",today)
1898
- print("持有股票 :",ticker_name(ticker))
1899
- print("持有股数 :",format(shares,','))
1900
- print("持有头寸 :",format(round(position,2),','))
1901
- print("预计持有天数:",future_days)
1902
- print("置信度 : ",alpha*100,'%',sep='')
1903
-
1904
- print("\n*** 各模型计算的VaR金额:")
1905
- print("标准正态模型 :",format(VaR1,','))
1906
- print("修正正态模型 :",format(VaR2,','))
1907
- print("历史模拟法 :",format(VaR3,','))
1908
- print("蒙特卡洛模拟法:",format(VaR4,','))
1909
-
1910
- print("\n*** 各模型计算的VaR比例:")
1911
- print("标准正态模型 :",round(ratio1*100,2),'%',sep='')
1912
- print("修正正态模型 :",round(ratio2*100,2),'%',sep='')
1913
- print("历史模拟法 :",round(ratio3*100,2),'%',sep='')
1914
- print("蒙特卡洛模拟法:",round(ratio4*100,2),'%',sep='')
1915
-
1916
- import datetime as dt; today=dt.date.today()
1917
- print("\n数据来源:新浪/stooq,"+str(today))
1918
- """
1919
-
1920
- import datetime as dt; todaydt=dt.date.today()
1921
- footnote="数据来源:新浪/stooq,"+str(todaydt)
1922
-
1923
- titletxt="持有资产的状况"
1924
- data_dict={'持有日期:':today, \
1925
- "持有股票:":ticker_name(ticker), \
1926
- "持有股数:":format(shares,','), \
1927
- "持有股数:":format(shares,','), \
1928
- "持有头寸:":format(round(position,2),','), \
1929
- "预计持有天数:":future_days, \
1930
- '置信度:':str(alpha*100)+'%'}
1931
- print2CSS(data_dict,titletxt=titletxt,footnote='')
1932
-
1933
- titletxt="各模型的VaR金额"
1934
- data_dict={"标准正态模型:":format(VaR1,','), \
1935
- "修正正态模型:":format(VaR2,','), \
1936
- "历史模拟模型:":format(VaR3,','), \
1937
- "蒙特卡洛模拟:":format(VaR4,',')}
1938
- print2CSS(data_dict,titletxt=titletxt,footnote='')
1939
-
1940
- titletxt="各模型的VaR比例"
1941
- data_dict={"标准正态模型:":str(round(ratio1*100,2))+'%', \
1942
- "修正正态模型:":str(round(ratio2*100,2))+'%', \
1943
- "历史模拟模型:":str(round(ratio3*100,2))+'%', \
1944
- "蒙特卡洛模拟:":str(round(ratio4*100,2))+'%'}
1945
- print2CSS(data_dict,titletxt=titletxt,footnote=footnote)
1946
-
1947
- VaRlist=[VaR1,VaR2,VaR3,VaR4]
1948
- ratiolist=[ratio1,ratio2,ratio3,ratio4]
1949
-
1950
- return VaRlist,ratiolist
1951
-
1952
- #==============================================================================
1953
- def get_ret_portfolio(tickerlist,shareslist,today,pastyears=1):
1954
- """
1955
- 功能:计算投资组合的历史收益率序列和当前头寸金额
1956
- 输入参数:投资组合的股票列表,投资组合的持有股数列表,当前日期,使用历史数据的年数
1957
- 输出参数:投资组合的历史日收益率序列,当前持有头寸金额
1958
- 注意:
1959
- #tickerlist为字符串列表类型,内容为投资组合内各个股票的代码
1960
- #shareslist为整数列表类型,内容为投资组合内各个股票的持股数量,不是金额
1961
- #tickerlist和shareslist中的元素个数必须一一对等
1962
- """
1963
- import pandas as pd
1964
- start=get_start_date(today,pastyears)
1965
- prices=pd.DataFrame()
1966
- for t in range(len(tickerlist)):
1967
- ticker=tickerlist[t]
1968
- q=get_stock_quotes(ticker,start,today)
1969
- q['date']=q.index.strftime('%Y'+'%m'+'%d')
1970
- q['ticker']=ticker
1971
- q['price']=q['Close']
1972
- q['shares']=shareslist[t]
1973
- q['value']=q['price']*q['shares']
1974
- try:
1975
- prices=prices.append(q)
1976
- except:
1977
- prices=prices._append(q)
1978
-
1979
- prices2=prices.sort_values('date')
1980
- groupKey='date'; groupWay=prices2.groupby(groupKey)
1981
- prices3=groupWay['value'].sum()
1982
- position=prices3[-1]
1983
- ret=prices3.pct_change()
1984
- ret=ret.dropna()
1985
- return ret,position
1986
-
1987
- #==============================================================================
1988
- def get_ret_portfolio2(tickerlist,shareslist,today,pastyears=1):
1989
- """
1990
- 功能:计算投资组合的历史收益率序列、当前头寸金额和各个成分股的历史日收益率序列
1991
- 输入参数:投资组合的股票列表,投资组合的持有股数列表,当前日期,使用历史数据的年数
1992
- 输出:投资组合的历史日收益率序列,当前持有头寸金额,各个成分股的历史日收益率序列
1993
- 注意:
1994
- #tickerlist为字符串列表类型,内容为投资组合内各个股票的代码
1995
- #shareslist为整数列表类型,内容为投资组合内各个股票的持股数量,不是金额
1996
- #tickerlist和shareslist中的元素个数必须一一对等
1997
- """
1998
- import pandas as pd
1999
- start=get_start_date(today,pastyears)
2000
- prices=pd.DataFrame()
2001
- for t in range(len(tickerlist)):
2002
- ticker=tickerlist[t]
2003
- q=get_stock_quotes(ticker,start,today)
2004
- q['date']=q.index.strftime('%Y'+'%m'+'%d')
2005
- q['ticker']=ticker
2006
- q['price']=q['Close']
2007
- q['shares']=shareslist[t]
2008
- q['value']=q['price']*q['shares']
2009
- q['ret']=q['price'].pct_change()
2010
- try:
2011
- prices=prices.append(q)
2012
- except:
2013
- prices=prices._append(q)
2014
-
2015
- #portfolio收益率
2016
- prices2=prices.sort_values('date')
2017
- groupKey='date'; groupWay=prices2.groupby(groupKey)
2018
- prices3=groupWay['value'].sum()
2019
- pret=prices3.pct_change()
2020
- pret=pret.dropna()
2021
-
2022
- #portfolio当前持有头寸
2023
- position=prices3[-1]
2024
-
2025
- #成分股收益率
2026
- sret=prices[['date','ticker','price','shares','value','ret']]
2027
- sret=sret.dropna()
2028
-
2029
- return pret,position,sret
2030
-
2031
- #==============================================================================
2032
- def get_portfolio_info(tickerlist,today,pastyears=1):
2033
- """
2034
- 功能:返回一组股票的历史价格和历史日收益率
2035
- 输入参数:股票列表,当前日期,使用历史数据的年数
2036
- 输出:成分股收益率数据表
2037
- """
2038
- import pandas as pd
2039
- start=get_start_date(today,pastyears)
2040
- prices=pd.DataFrame()
2041
-
2042
- for t in range(len(tickerlist)):
2043
- ticker=tickerlist[t]
2044
- q=get_stock_quotes(ticker,start,today)
2045
- q['date']=q.index.strftime('%Y'+'%m'+'%d')
2046
- q['ticker']=ticker
2047
- q['price']=q['Close']
2048
- q['shares']=0
2049
- q['value']=0
2050
- q['ret']=q['price'].pct_change()
2051
- try:
2052
- prices=prices.append(q)
2053
- except:
2054
- prices=prices._append(q)
2055
-
2056
- #成分股收益率
2057
- tickers_info=prices[['date','ticker','price','shares','value','ret']]
2058
- return tickers_info
2059
-
2060
- #==============================================================================
2061
- def get_portfolio_rets(tickerlist,shareslist,tickers_info,today,pastyears=1):
2062
- """
2063
- 功能:计算投资组合的历史日收益率序列和当前头寸金额,不重新抓取股价
2064
- 输入参数:股票列表,持有股数列表,股票信息数据框,当前日期,使用历史数据的年数
2065
- 输出:投资组合的历史日收益率序列和当前头寸
2066
- 注意:
2067
- #tickerlist为字符串列表类型,内容为投资组合内各个股票的代码
2068
- #shareslist为整数列表类型,内容为投资组合内各个股票的持股数量,不是金额
2069
- #tickerlist和shareslist中的元素个数必须一一对等
2070
- """
2071
- import pandas as pd
2072
- start=get_start_date(today,pastyears)
2073
- startdate=start.strftime('%Y'+'%m'+'%d')
2074
- enddate =today.strftime('%Y'+'%m'+'%d')
2075
- ti=pd.DataFrame()
2076
- for index, row in tickers_info.iterrows():
2077
- if (row['date'] >= startdate) and (row['date'] <= enddate):
2078
- ticker=row['ticker']
2079
- p=tickerlist.index(ticker)
2080
- shares=shareslist[p]
2081
- row['shares']=shares
2082
- row['value']=row['price']*shares
2083
- try:
2084
- ti=ti.append(row,ignore_index=True)
2085
- except:
2086
- ti=ti._append(row,ignore_index=True)
2087
-
2088
- ti1=ti.sort_values('date')
2089
- groupKey='date'; groupWay=ti1.groupby(groupKey)
2090
- ti2=groupWay['value'].sum()
2091
- position=ti2[-1]
2092
- pret=ti2.pct_change()
2093
- pret=pret.dropna()
2094
-
2095
- return pret,position
2096
-
2097
- #==============================================================================
2098
- def get_ret_cumulative(ret_series):
2099
- """
2100
- 功能:计算累计收益率
2101
- 输入参数:收益率序列
2102
- 输出:累积收益率
2103
- """
2104
- c=1
2105
- for r in ret_series:
2106
- c=c*(1+r)
2107
- retcum=c-1
2108
- return retcum
2109
-
2110
- #==============================================================================
2111
- def get_portfolio_ret_risk(tickerlist,shareslist,tickers_info, \
2112
- today,future_days=1,alpha=0.99,pastyears=1):
2113
- """
2114
- 功能:一次性计算投资组合的所有收益率和风险信息,避免重复抓取网络股价
2115
- 输入参数:投资组合的股票列表,投资组合的持有股数列表,投资组合的成分股信息,当前日期,
2116
- 未来持有天数,置信度,使用历史数据的年数
2117
- 输出:投资组合的累积收益率、VaR金额与比率、ES金额与比率;各个成分股的累积收益率、
2118
- VaR金额与比率、ES金额与比率
2119
- """
2120
- #合成投资组合历史信息
2121
- Pret,Pposition=get_portfolio_rets(tickerlist,shareslist, \
2122
- tickers_info,today,pastyears)
2123
-
2124
- #投资组合累积收益率:例13.82%
2125
- Pretcum=round(get_ret_cumulative(Pret),4)
2126
- #投资组合VaR金额和比率:例-$8851,0.0304
2127
- PVaR=int(VaR_normal_standard(Pposition,Pret,future_days,alpha)+0.5)
2128
- PVaRratio=round(abs(PVaR/Pposition),4)
2129
- #投资组合ES金额和比率:例-$10166,0.035
2130
- PES=int(ES_normal_standard(Pposition,Pret,future_days,alpha)+0.5)
2131
- PESratio=round(abs(PES/Pposition),4)
2132
-
2133
- #成分股累积回报率列表:[-0.0113,0.3278]
2134
- retlist=[]
2135
- for t in tickerlist:
2136
- r=tickers_info[tickers_info['ticker']==t]['ret']
2137
- r=r.dropna()
2138
- retcum=round(get_ret_cumulative(r),4)
2139
- retlist=retlist+[retcum]
2140
-
2141
- #VaR金额和比率列表:例[-$4650,-$6691],[0.0329,0.0447]
2142
- VaRlist=[]
2143
- VaRratiolist=[]
2144
- for t in range(len(tickerlist)):
2145
- ticker=tickerlist[t]
2146
- r=tickers_info[tickers_info['ticker']==ticker]['ret']
2147
- r=r.dropna()
2148
-
2149
- shares=shareslist[t]
2150
- price=tickers_info[tickers_info['ticker']==ticker]['price'][-1]
2151
- position=shares*price
2152
-
2153
- VaR=int(VaR_normal_standard(position,r,future_days,alpha)+0.5)
2154
- ratio=round(abs(VaR/position),4)
2155
- VaRlist=VaRlist+[VaR]
2156
- VaRratiolist=VaRratiolist+[ratio]
2157
-
2158
- #ES金额和比率列表:例[-$5329,-$7695],[0.0377,0.0515]
2159
- ESlist=[]
2160
- ESratiolist=[]
2161
- for t in range(len(tickerlist)):
2162
- ticker=tickerlist[t]
2163
- r=tickers_info[tickers_info['ticker']==ticker]['ret']
2164
- r=r.dropna()
2165
-
2166
- shares=shareslist[t]
2167
- price=tickers_info[tickers_info['ticker']==ticker]['price'][-1]
2168
- position=shares*price
2169
-
2170
- ES=int(ES_normal_standard(position,r,future_days,alpha)+0.5)
2171
- ratio=round(abs(ES/position),4)
2172
- ESlist=ESlist+[ES]
2173
- ESratiolist=ESratiolist+[ratio]
2174
-
2175
- return Pretcum,PVaR,PVaRratio,PES,PESratio, \
2176
- retlist,VaRlist,VaRratiolist,ESlist,ESratiolist
2177
-
2178
-
2179
- #==============================================================================
2180
- def get_portfolio_ret_risk2(tickerlist,shareslist,tickers_info, \
2181
- today,future_days=1,alpha=0.99,pastyears=1):
2182
- """
2183
- 功能:一次性计算投资组合的所有收益率和风险信息,仅返回比率
2184
- 输入参数:投资组合的股票列表,投资组合的持有股数列表,投资组合的成分股信息,当前日期,
2185
- 未来持有天数,置信度,使用历史数据的年数
2186
- 输出参数:投资组合的累积收益率、VaR比率、ES比率;各个成分股的累积收益率、VaR比率、ES比率
2187
- """
2188
- Pretcum,PVaR,PVaRratio,PES,PESratio, \
2189
- retlist,VaRlist,VaRratiolist,ESlist,ESratiolist= \
2190
- get_portfolio_ret_risk(tickerlist,shareslist,tickers_info, \
2191
- today,future_days,alpha,pastyears)
2192
-
2193
- return Pretcum,PVaRratio,PESratio,retlist,VaRratiolist,ESratiolist
2194
-
2195
-
2196
- #==============================================================================
2197
- def get_portfolio_ret_risk3(tickerlist,shareslist,tickers_info, \
2198
- today,future_days=1,alpha=0.99,pastyears=1):
2199
- """
2200
- 功能:一次性计算投资组合的所有收益率和风险信息,仅返回投资组合的比率
2201
- 输入参数:投资组合的股票列表,投资组合的持有股数列表,投资组合的成分股信息,当前日期,
2202
- 未来持有天数,置信度,使用历史数据的年数
2203
- 输出:投资组合的累积收益率、VaR比率、ES比率
2204
- """
2205
- Pretcum,PVaR,PVaRratio,PES,PESratio, \
2206
- retlist,VaRlist,VaRratiolist,ESlist,ESratiolist= \
2207
- get_portfolio_ret_risk(tickerlist,shareslist,tickers_info, \
2208
- today,future_days,alpha,pastyears)
2209
-
2210
- return Pretcum,PVaRratio,PESratio
2211
-
2212
-
2213
- #==============================================================================
2214
-
2215
-
2216
-
2217
-
2218
-