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,783 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- """
3
- 本模块功能:CAPM模型贝塔系数计算
4
- 所属工具包:证券投资分析工具SIAT
5
- SIAT:Security Investment Analysis Tool
6
- 创建日期:2018年7月16日
7
- 最新修订日期:2020年1月15日
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
- def get_price_excel(ticker,fromdate,todate,excelfile,sheetname='Sheet1'):
43
- """
44
- 功能:抓取股价,保存到Excel文件中
45
- 输出:指定收盘价格序列,最新日期的股价排列在前
46
- ticker: 股票代码。大陆股票代码加上后缀.SZ或.SS,港股代码去掉前导0加后缀.HK
47
- fromdate: 样本开始日期,尽量远的日期,以便取得足够多的原始样本
48
- todate: 样本结束日期,既可以是今天日期,也可以是一个历史日期
49
- excelfile:保存到Excel文件名,含目录。如果目录不存在,将会导致错误。
50
- """
51
-
52
- #仅为调试用的函数入口参数,正式使用前需要注释掉!
53
- #ticker='000300.SS'
54
- #fromdate='01/01/2018'
55
- #todate='06/30/2019'
56
- #---------------------------------------------
57
-
58
- #仅为测试使用
59
- #ticker='601857.SS'
60
- #fromdate='2019-1-1'
61
- #todate='2019-8-31'
62
- #excelfile='C:/temp/myexcel1.xlsx'
63
- #sheetname='601857.SS'
64
-
65
- price=get_price(ticker,fromdate,todate)
66
- if price is None:
67
- print(" #Error(get_price_excel): failed to retrieve stock data")
68
- print(" Information:",ticker,fromdate,todate)
69
- return
70
- try:
71
- price.to_excel(excelfile,sheetname,encoding='utf-8')
72
- except:
73
- print(" #Error((get_price_excel): failed to stock data to excel file")
74
- print(" Information:",excelfile,sheetname)
75
- return
76
- print("***Results saved in",excelfile,"with sheet",sheetname)
77
- return
78
-
79
-
80
- if __name__=='__main__':
81
- df601857=get_price_excel('601857.SS','2019-1-1','2019-12-31', \
82
- 'C:/temp/myexcel1.xlsx','601857.SS')
83
-
84
-
85
- #==============================================================================
86
- def prepare_capm_data(stkcd,mktidx,start,end):
87
- """
88
- 函数功能:准备计算一只股票CAPM模型贝塔系数的数据,并标记年度
89
- 输入参数:
90
- stkcd: 股票代码
91
- mktidx: 指数代码
92
- start:使用股票价格数据的开始日期,MM/DD/YYYY
93
- end:使用股票价格数据的结束日期,MM/DD/YYYY
94
- 输出数据:
95
- 返回数据:带年度标记的可直接用于capm回归的股票收益率数据
96
- """
97
-
98
- #仅用于调试,正式使用前应注释掉
99
- #stkcd='600028.SS'; mktidx='000001.SS'
100
- #start="12/31/2011"; end="12/31/2018"
101
-
102
- #抓取股价和指数
103
- import siat.security_prices as ssp
104
- stock=get_price(stkcd,start,end)
105
- if stock is None:
106
- print(" #Error(prepare_capm_data): failed to get stock price")
107
- print(" Information:",stkcd,start,end)
108
- return None
109
- market=get_price(mktidx,start,end)
110
- if market is None:
111
- print(" #Error(prepare_capm_data): failed to get market index")
112
- print(" Information:",mktidx,start,end)
113
- return None
114
-
115
- #计算日收益率
116
- import pandas as pd
117
- stkret=pd.DataFrame(stock['Close'].pct_change())
118
- mktret=pd.DataFrame(market['Close'].pct_change())
119
-
120
- #合并,去掉空缺
121
- R=pd.merge(mktret,stkret,how='left',left_index=True,right_index=True)
122
- R=R.dropna()
123
-
124
- #标记各个年度
125
- R['Year']=R.index.strftime("%Y")
126
-
127
- #返回带年份的股票收益率序列
128
- return R
129
-
130
- #==============================================================================
131
- def capm_beta(ticker,mktidx,start,end='today'):
132
- """
133
- 函数功能:计算一只股票的静态CAPM模型贝塔系数
134
- 输入参数:
135
- ticker: 股票代码
136
- mktidx: 指数代码
137
- start:使用股票价格数据的开始日期,MM/DD/YYYY
138
- end:使用股票价格数据的结束日期,MM/DD/YYYY
139
- 输出数据:
140
- 显示CAPM市场模型回归的alpha, beta, 以及显著性和拟合优度
141
- 无返回数据
142
- """
143
- start,end=start_end_preprocess(start,end)
144
-
145
- #读取股价并准备好收益率数据
146
- R=prepare_capm_data(ticker,mktidx,start,end)
147
- if R is None:
148
- print(" #Error(capm_beta): failed to prepare capm data")
149
- print(" Info:",ticker,mktidx,start,end)
150
- return
151
-
152
- #全数据OLS回归
153
- from scipy import stats
154
- (beta,alpha,r_value,p_value,std_err)= \
155
- stats.linregress(R['Close_x'],R['Close_y'])
156
-
157
- #显示回归结果
158
- print(" \n===== 计算CAPM贝塔系数 =====")
159
- print("回归模型:市场模型")
160
- print(equalwidth("股票",16), ticker_name(ticker))
161
- print(equalwidth("市场指数",16), ticker_name(mktidx))
162
- print(equalwidth("样本期间开始于",16), start)
163
- print(equalwidth("样本期间结束于",16), end)
164
- print(equalwidth("截距项",16), round(alpha,4))
165
- print(equalwidth("贝塔系数",16), round(beta,4))
166
- print(equalwidth("R-square",16), round(r_value**2,4))
167
- print(equalwidth("p-value",16), round(p_value,4))
168
-
169
- import datetime
170
- today = datetime.date.today()
171
- print("*数据来源: 新浪/stooq/fred,",today)
172
-
173
- return beta
174
-
175
- if __name__=='__main__':
176
- capm_beta('002504.SZ','000001.SS','12/31/2011','12/31/2018')
177
-
178
- #==============================================================================
179
-
180
- def plot_trend(titletxt,footnotetxt,df,power=1,axhline_value=1,axhline_label=''):
181
- """
182
- 功能:绘制散点数据的平滑曲线图及其趋势线
183
- titletxt: 标题
184
- footnotetxt:脚注
185
- df: 数据框,其索引为字符型年份,第1列与年份对应的数值1,
186
- 第2列与年份对应的数值2,。。。
187
- power: 趋势线拟合的幂阶数,默认为三阶多项式
188
- """
189
- #将字符型年份转化为整数型
190
- yearstr=df.index
191
- year=[]
192
- for t in yearstr:
193
- tt=int(t)
194
- year=year+[tt]
195
-
196
- #取得列名
197
- rowlist=df.columns.values.tolist()
198
- n=len(rowlist)
199
-
200
- import numpy as np
201
- import scipy.interpolate as itp
202
-
203
- #由于年度为连续整数,为插值方便,先将所有年度放大10倍
204
- year0=[]
205
- for t in year:
206
- tt=t*10
207
- year0=year0+[tt]
208
-
209
- #形成用于插值的连续整数自变量xx
210
- x1=year0[0]
211
- x2=year0[-1]+1
212
- xx=np.array(range(x1,x2,1))
213
-
214
- #将用于插值的自变量缩小10倍,以便自变量在x轴上的尺度统一
215
- x=[]
216
- for t in xx:
217
- tt=t/10.0
218
- x=x+[tt]
219
-
220
- #循环处理每个因变量
221
- for i in np.array(range(0,n,1)):
222
- number=df[rowlist[i]]
223
-
224
- #进行插值: linear=线性插值, cubic=立方插值
225
- y=itp.interp1d(year0,number,kind='cubic')
226
- #生成插值出来的模拟数据因变量
227
- y2=y(xx)
228
- #绘图1:插值出来的大量模拟点构成的平滑曲线
229
- plt.plot(x,y2)
230
- #绘图2:原数据点
231
-
232
- #进行拟合: 1=线性拟合, 2=二次拟合,3=三次拟合
233
- p=np.polyfit(year0,number,power)
234
- #生成拟合出来的模拟数据因变量
235
- p2=np.polyval(p,xx)
236
- #绘图2:拟合出来的大量模拟点构成的平滑趋势曲线
237
- plt.plot(x,p2,linestyle=':',linewidth=3)
238
-
239
- #绘图3:原数据点
240
- plt.plot(year,number,'*',label=rowlist[i])
241
-
242
- #是否绘制水平线
243
- if axhline_label !="":
244
- if '市场' in axhline_label:
245
- axhline_label=''
246
- plt.axhline(y=axhline_value,label=axhline_label,color='black',linestyle=':',linewidth=2)
247
- #plt.axhline(y=axhline_value,color='purple',linestyle=':',linewidth=1.5)
248
-
249
- #x轴刻度:使用原数据点的自变量
250
- plt.xticks(year,rotation=30)
251
- plt.legend(loc='best')
252
- plt.title(titletxt)
253
- plt.xlabel(footnotetxt)
254
-
255
- plt.gca().set_facecolor('whitesmoke')
256
- plt.show()
257
-
258
- return
259
- #==============================================================================
260
-
261
- def capm_beta_yearly(ticker,mktidx,yearlist):
262
- """
263
- 函数功能:分年度计算一只股票的CAPM模型贝塔系数
264
- 输入参数:
265
- ticker: 股票代码
266
- mktidx: 指数代码
267
- yearlist: 年度列表,start日期要给第一个年份留出至少一年数据供回归使用
268
- 输出数据:
269
- 按年份显示CAPM市场模型回归的alpha, beta, 以及显著性和拟合优度
270
- 无返回数据
271
- """
272
-
273
- #运行开始信息
274
- print("*** Analysing yearly CAPM betas, please wait ...")
275
-
276
- #生成开始结束日期
277
- Y4=str(int(yearlist[0])-1)
278
- start=Y4+'-01-01'
279
- end=yearlist[-1]+'-12-31'
280
-
281
- #读取股价并准备好收益率数据
282
- R=prepare_capm_data(ticker,mktidx,start,end)
283
- if R is None:
284
- print(" #Error(capm_beta_yearly): failed to prepare capm data")
285
- print(" Information:",ticker,mktidx,start,end)
286
- return
287
-
288
- #print("\n***CAPM yearly beta: Stock_return=alpha+beta*Market_return")
289
- #print("Stock code:",ticker)
290
- #print("Market index:",mktidx)
291
- #print("Year Beta R-sqr p-value")
292
-
293
- #用于保存beta(CAPM)
294
- import pandas as pd
295
- betas=pd.DataFrame(columns=('Year','Beta','alpha','R-sqr','p-value'))
296
-
297
- #分年度OLS回归
298
- from scipy import stats
299
- for year in yearlist:
300
- #print(year,' ',end='')
301
- r=R[R['Year']==year]
302
- if len(r)==0: continue
303
- try:
304
- output=stats.linregress(r['Close_x'],r['Close_y'])
305
- except:
306
- print(" #Error(capm_beta_yearly): no data for regression")
307
- print(" Information:",stkcd,year,R,r)
308
- return
309
- (beta,alpha,r_value,p_value,std_err)=output
310
-
311
- row=pd.Series({'Year':year,'Beta':beta,'alpha':alpha, \
312
- 'R-sqr':r_value**2,'p-value':p_value})
313
- try:
314
- betas=betas.append(row,ignore_index=True)
315
- except:
316
- betas=betas._append(row,ignore_index=True)
317
- #print(year,round(beta,4),round(r_value**2,3),round(p_value,4))
318
-
319
- betas['Significance']=betas['p-value'].apply(lambda x: '***' if x<0.01 \
320
- else '**' if x<0.05 else '*' if x<0.1 else '')
321
-
322
- #设置打印标题与数据对齐
323
- """
324
- pd.set_option('display.unicode.ambiguous_as_wide', True)
325
- pd.set_option('display.unicode.east_asian_width', True)
326
- pd.set_option('display.width', 180) # 设置打印宽度(**重要**)
327
-
328
- print("\n ===== 分年度静态贝塔系数:",ticker_name(ticker),"=====")
329
- print(betas.to_string(index=False))
330
- import datetime as dt; todaydt=dt.date.today()
331
- print("数据来源:新浪/stooq/fred,基于"+ticker_name(mktidx)+','+str(dttoday))
332
- print('') #空一行
333
- """
334
- titletxt="分年度静态贝塔系数: "+ticker_name(ticker)
335
- import datetime as dt; todaydt=dt.date.today()
336
- footnote="数据来源:新浪/stooq/fred,基于"+ticker_name(mktidx)+', '+str(todaydt)
337
- df_display_CSS(betas,titletxt=titletxt,footnote=footnote,facecolor='papayawhip', \
338
- decimals=4, \
339
- first_col_align='center',second_col_align='center', \
340
- last_col_align='center',other_col_align='center')
341
-
342
- #准备绘图
343
- betas.set_index('Year',inplace=True)
344
-
345
- #绘图:年度贝塔系数趋势
346
- df=pd.DataFrame(betas['Beta'])
347
- title="分年度静态贝塔系数: "+ticker_name(ticker)
348
- foot="\n数据来源:新浪/stooq/fred,基于"+ticker_name(mktidx)+','+str(todaydt)
349
- plot_trend(title,foot,df,power=3,axhline_value=1,axhline_label='市场风险线')
350
-
351
- return betas
352
-
353
- if __name__=='__main__':
354
- yearlist=['2013','2014','2015','2016','2017','2018','2019']
355
- capm_beta_yearly('AAPL','^GSPC',yearlist)
356
-
357
- #==============================================================================
358
- #新增投资组合贝塔系数部分
359
- #==============================================================================
360
- #==============================================================================
361
- def prepare_capm_portfolio(tickerlist,sharelist,mktidx,start,end):
362
- """
363
- 函数功能:准备计算股票投资组合CAPM模型贝塔系数的数据,并标记年度
364
- 输入参数:
365
- tickerlist: 股票代码列表
366
- sharelist:持有份额列表
367
- mktidx: 市场指数代码
368
- start:使用股票价格数据的开始日期,'YYYY-MM-DD'
369
- end:使用股票价格数据的结束日期
370
- 输出数据:
371
- 返回数据:带年度标记的可直接用于capm模型回归的数据表
372
- """
373
-
374
- #仅用于调试,正式使用前应注释掉
375
- #tickerlist=['AAPL','MSFT']
376
- #sharelist=[2,1]
377
- #mktidx='^GSPC'
378
- #start="1/1/2019"; end="8/31/2019"
379
-
380
- #抓取投资组合股价和指数
381
- import siat.security_prices as ssp
382
- stock=get_price_portfolio(tickerlist,sharelist,start,end)
383
- if (stock is None) or (len(stock)==0):
384
- print(" #Error(prepare_capm_portfolio): failed to get stock prices")
385
- print(" Info:",tickerlist,start,end)
386
- return None
387
- market=get_price(mktidx,start,end)
388
- if (market is None) or (len(market)==0):
389
- print(" #Error(prepare_capm_portfolio): failed to get market index")
390
- print(" Info:",mktidx,start,end)
391
- return None
392
-
393
- #计算日收益率
394
- import pandas as pd
395
- stkret=pd.DataFrame(stock['Close'].pct_change())
396
- mktret=pd.DataFrame(market['Close'].pct_change())
397
-
398
- #合并:mktret作为Close_x,stkret作为Close_y,去掉空缺
399
- R=pd.merge(mktret,stkret,how='left',left_index=True,right_index=True)
400
- R=R.dropna()
401
-
402
- #标记各个年度
403
- R['Year']=R.index.strftime("%Y")
404
-
405
- #返回带年份的股票收益率序列
406
- return R
407
-
408
- #==============================================================================
409
- def capm_beta_portfolio(tickerlist,sharelist,mktidx,start,end):
410
- """
411
- 函数功能:计算投资组合的静态CAPM模型贝塔系数
412
- 输入参数:
413
- tickerlist: 股票代码列表
414
- sharelist:持有份额列表
415
- mktidx: 指数代码
416
- start:使用股票价格数据的开始日期,MM/DD/YYYY
417
- end:使用股票价格数据的结束日期,MM/DD/YYYY
418
- 输出数据:
419
- 显示CAPM市场模型回归的截距, beta, 以及显著性和拟合优度
420
- 无返回数据
421
- """
422
-
423
- #读取股价并准备好收益率数据
424
- R=prepare_capm_portfolio(tickerlist,sharelist,mktidx,start,end)
425
- if R is None:
426
- print(" #Error(capm_beta_portfolio): failed to prepare capm data")
427
- print(" Information:",tickerlist,sharelist,mktidx,start,end)
428
- return
429
-
430
- #全数据OLS回归
431
- from scipy import stats
432
- (beta,alpha,r_value,p_value,std_err)= \
433
- stats.linregress(R['Close_x'],R['Close_y'])
434
-
435
- #显示回归结果
436
- print("\n *** Portfolio CAPM Beta Coefficient \
437
- \n Model: Stock_return=intercept + beta * Market_return")
438
- print(" Portfolio stocks:",tickerlist)
439
- print(" Stock portions :",sharelist)
440
- print(" Market index :",mktidx)
441
- print(" Intercept :",round(alpha,4))
442
- print(" Portfolio beta :",round(beta,4))
443
- print(" R-sqr :",round(r_value**2,4))
444
- print(" p-value :",round(p_value,4))
445
-
446
- return beta
447
-
448
-
449
- #==============================================================================
450
- def capm_beta_portfolio_yearly(tickerlist,sharelist,mktidx,yearlist):
451
- """
452
- 函数功能:分年度计算投资组合的CAPM模型贝塔系数,并绘图
453
- 输入参数:
454
- tickerlist: 投资组合中各个成分股的股票代码
455
- sharelist: 各个成分股的持股比例
456
- mktidx: 指数代码
457
- yearlist: 年度列表,start日期要给第一个年份留出至少一年数据供回归使用
458
- 输出数据:
459
- 按年份绘图beta
460
- 无返回数据
461
- """
462
-
463
- #运行开始信息
464
- print("*** Analysing yearly portfolio CAPM betas, please wait ...")
465
-
466
- #生成开始结束日期
467
- Y4=str(int(yearlist[0])-1)
468
- start=Y4+'-01-01'
469
- end=yearlist[-1]+'-12-31'
470
-
471
- #读取股价并准备好收益率数据
472
- R=prepare_capm_portfolio(tickerlist,sharelist,mktidx,start,end)
473
- if (R is None) or (len(R)==0):
474
- print(" #Error(capm_beta_portfolio_yearly): failed to prepare capm data")
475
- print(" Info:",tickerlist,sharelist,mktidx,start,end)
476
- return
477
-
478
- #用于保存beta(CAPM)和beta
479
- import pandas as pd
480
- betas=pd.DataFrame(columns=('Year','Beta','intercept','R-sqr','p-value'))
481
-
482
- #分年度OLS回归
483
- from scipy import stats
484
- for year in yearlist:
485
- #print(year,' ',end='')
486
- r=R[R['Year']==year]
487
- if len(r)==0: continue
488
- try:
489
- output=stats.linregress(r['Close_x'],r['Close_y'])
490
- except:
491
- print(" #Error(capm_beta_portfolio_yearly): no data for regression")
492
- print(" Information:",year,R,r)
493
- return
494
- (beta,alpha,r_value,p_value,std_err)=output
495
-
496
- row=pd.Series({'Year':year,'Beta':beta,'intercept':alpha, \
497
- 'R-sqr':r_value**2,'p-value':p_value})
498
- try:
499
- betas=betas.append(row,ignore_index=True)
500
- except:
501
- betas=betas._append(row,ignore_index=True)
502
-
503
- betas['Significance']=betas['p-value'].apply(lambda x: '***' if x<0.01 \
504
- else '**' if x<0.05 else '*' if x<0.1 else '')
505
- #print("\n",betas)
506
-
507
- titletxt="投资组合的静态年度贝塔系数"
508
- import datetime as dt; todaydt=dt.date.today()
509
- footnote="数据来源:新浪/stooq/fred,基于"+ticker_name(mktidx)+', '+str(todaydt)
510
- df_display_CSS(betas,titletxt=titletxt,footnote=footnote,facecolor='papayawhip', \
511
- decimals=4, \
512
- first_col_align='center',second_col_align='center', \
513
- last_col_align='center',other_col_align='center')
514
-
515
- betas.set_index('Year',inplace=True)
516
-
517
- #绘图:年度贝塔系数变化
518
- df=pd.DataFrame(betas['Beta'])
519
- title="投资组合的静态年度贝塔系数"+ \
520
- "\n成分股: "+str(ticker_name(tickerlist,'bond'))+"\n持仓权重: "+str(sharelist)
521
- import datetime; today = datetime.date.today()
522
- foot="数据来源: 新浪/stooq/fred,"+str(today)
523
- plot_trend(title,foot,df,power=2,axhline_value=1,axhline_label='市场风险线')
524
-
525
- return betas
526
-
527
- if __name__=='__main__':
528
- yearlist=['2013','2014','2015','2016','2017','2018','2019']
529
- capm_beta_portfolio_yearly(['AAPL','MSFT'],[2,1],'^GSPC',yearlist)
530
- capm_beta_portfolio_yearly(['600028.SS','600036.SS'],[2,1],'000001.SS',yearlist)
531
-
532
- #==============================================================================
533
- def capm_beta_portfolio_yearly_excel(tickerlist,sharelist,mktidx,yearlist, \
534
- excelfile,sheetname='Sheet1'):
535
- """
536
- 函数功能:分年度计算投资组合的CAPM模型贝塔系数,绘图,结果保存到Excel
537
- 输入参数:
538
- tickerlist: 投资组合中各个成分股的股票代码
539
- sharelist: 各个成分股的持股比例
540
- mktidx: 指数代码
541
- yearlist: 年度列表
542
- excelfile: 带目录的Excel文件名,如果目录不存在则出错
543
- sheetname:Excel文件中的sheet名
544
- 输出:
545
- 按年份绘图beta系数, 并保存到Excel文件
546
- 无返回数据
547
- """
548
-
549
- #运行开始信息
550
- print("\n*** Analysing yearly portfolio CAPM betas, please wait ...")
551
-
552
- #生成开始结束日期
553
- Y4=str(int(yearlist[0])-1)
554
- start=Y4+'-01-01'
555
- end=yearlist[-1]+'-12-31'
556
-
557
- #读取股价并准备好收益率数据
558
- R=prepare_capm_portfolio(tickerlist,sharelist,mktidx,start,end)
559
- if R is None:
560
- print(" #Error(capm_beta_portfolioyearly_excel): failed to prepare capm data")
561
- print(" Information:",tickerlist,sharelist,mktidx,start,end)
562
- return
563
-
564
- #用于保存beta(CAPM)和beta
565
- import pandas as pd
566
- betas=pd.DataFrame(columns=('Year','Beta','intercept','R-sqr','p-value'))
567
-
568
- #分年度OLS回归
569
- from scipy import stats
570
- for year in yearlist:
571
- #print(year,' ',end='')
572
- r=R[R['Year']==year]
573
- if len(r)==0: continue
574
- try:
575
- output=stats.linregress(r['Close_x'],r['Close_y'])
576
- except:
577
- print(" #Error(capm_beta_portfolio_yearly_excel): no data available for regressing beta")
578
- print(" Information:",year,R,r)
579
- return
580
- (beta,alpha,r_value,p_value,std_err)=output
581
-
582
- row=pd.Series({'Year':year,'Beta':beta,'intercept':alpha, \
583
- 'R-sqr':r_value**2,'p-value':p_value})
584
- try:
585
- betas=betas.append(row,ignore_index=True)
586
- except:
587
- betas=betas._append(row,ignore_index=True)
588
-
589
- betas2=betas.copy() #用于保存excel
590
- betas2['Year']=betas2['Year'].astype('int')
591
- betas2['Portfolio']=str(tickerlist)
592
- betas2['Share Ratio']=str(sharelist)
593
- betas2['Market Index']=mktidx
594
-
595
- betas.set_index('Year',inplace=True) #用于绘图
596
-
597
- #绘图:年度贝塔系数变化
598
- df=pd.DataFrame(betas['Beta'])
599
- title="Investment Portfolio's Annual CAPM Betas"+ \
600
- "\nPortfolio: "+str(tickerlist)+"\nComposition: "+str(sharelist)
601
- foot="\nSource: Sina Finance/Yahoo Finance"
602
- plot_trend(title,foot,df,power=2)
603
-
604
- """
605
- #为折线加数据标签
606
- for a,b in zip(betas.index,betas['Beta']):
607
- plt.text(a,b+0.02,str(round(b,2)),ha='center',va='bottom',fontsize=7)
608
- plt.show()
609
- """
610
-
611
- #保存到Excel
612
- import pandas as pd
613
- try:
614
- file1=pd.ExcelFile(excelfile)
615
- except:
616
- #不存在excelfile文件,直接写入
617
- betas2.to_excel(excelfile,sheet_name=sheetname, \
618
- header=True,encoding='utf-8')
619
- print("***Results saved in",excelfile,"@ sheet",sheetname)
620
- return
621
- else:
622
- #已存在excelfile文件,先将所有已有内容读出
623
- dict=pd.read_excel(file1, None)
624
- file1.close()
625
-
626
- #获得所有sheet名字
627
- sheetlist=list(dict.keys())
628
-
629
- #检查新的sheet名字是否已存在
630
- try:
631
- pos=sheetlist.index(sheetname)
632
- except:
633
- #不存在重复
634
- dup=False
635
- else:
636
- #存在重复,合并内容
637
- dup=True
638
- #print(dict[sheetlist[pos]],betas2)
639
- df1=dict[sheetlist[pos]][['Year','Beta','intercept','R-sqr','p-value','Portfolio','Share Ratio','Market Index']]
640
- df=pd.concat([df1,betas2],axis=0,ignore_index=True)
641
- dict[sheetlist[pos]]=df
642
-
643
- #将原有内容写回excelfile
644
- result=pd.ExcelWriter(excelfile)
645
- for s in sheetlist:
646
- df1=dict[s][['Year','Beta','intercept','R-sqr','p-value','Portfolio','Share Ratio','Market Index']]
647
- df1.to_excel(result,s,header=True,index=True,encoding='utf-8')
648
- #写入新内容
649
- if not dup: #sheetname未重复
650
- betas2.to_excel(result,sheetname,header=True,index=True,encoding='utf-8')
651
- try:
652
- result.save()
653
- result.close()
654
- except:
655
- print(" #Error(capm_beta_portfolio_yearly_excel): writing file permission denied")
656
- print(" Information:",excelfile)
657
- return
658
- print("***Results saved in",excelfile,"@ sheet",sheetname)
659
- return betas
660
-
661
- if __name__=='__main__':
662
- yearlist=['2013','2014','2015','2016','2017','2018','2019']
663
- excelfile='C:/temp/myexcel.xls'
664
- capm_beta_portfolio_yearly_excel(['AAPL','MSFT'],[2,1],'^GSPC',yearlist, excelfile,'p01')
665
-
666
- #==============================================================================
667
- def compare2_betas_yearly(ticker1,ticker2,mktidx,yearlist):
668
- """
669
- 函数功能:分年度计算两只股票的CAPM模型贝塔系数,并绘图对比其风险特征的对冲性
670
- 输入参数:
671
- ticker1: 股票代码
672
- ticker2: 股票代码
673
- mktidx: 指数代码
674
- yearlist: 年度列表,start日期要给第一个年份留出至少一年数据供回归使用
675
- 输出数据:
676
- 按年份绘图贝塔系数的变化
677
- 无返回数据
678
- """
679
- #仅用于测试,完成后应注释掉
680
- #stkcd1='600028.SS'
681
- #stkcd2='600036.SS'
682
- #mktidx='000001.SS'
683
- #yearlist=['2013','2014','2015','2016','2017','2018','2019']
684
-
685
-
686
- #运行开始信息
687
- print(" Comparing stock CAPM betas, please wait ...")
688
-
689
- #生成开始结束日期
690
- Y4=str(int(yearlist[0])-1)
691
- start=Y4+'-01-01'
692
- end=yearlist[-1]+'-12-31'
693
-
694
- #读取股价并准备好收益率数据
695
- R1=prepare_capm_data(ticker1,mktidx,start,end)
696
- if R1 is None:
697
- print(" #Error(compare2_betas_yearly): failed to prepare capm data")
698
- print(" Information:",ticker1,mktidx,start,end)
699
- return
700
-
701
- R2=prepare_capm_data(ticker2,mktidx,start,end)
702
- if R2 is None:
703
- print(" #Error(compare2_betas_yearly): failed to prepare capm data")
704
- print(" Information:",ticker2,mktidx,start,end)
705
- return
706
-
707
- #用于保存beta(CAPM)
708
- import pandas as pd
709
- betas1=pd.DataFrame(columns=('Year','Beta','alpha','R-sqr','p-value'))
710
- #分年度OLS回归
711
- from scipy import stats
712
- for year in yearlist:
713
- r=R1[R1['Year']==year]
714
- if len(r)==0: continue
715
- try:
716
- output=stats.linregress(r['Close_x'],r['Close_y'])
717
- except:
718
- print(" #Error(compare2_betas_yearly): no data for regression")
719
- print(" Information:",stkcd1,year,r,R1)
720
- continue
721
- (beta,alpha,r_value,p_value,std_err)=output
722
-
723
- row=pd.Series({'Year':year,'Beta':beta,'alpha':alpha, \
724
- 'R-sqr':r_value**2,'p-value':p_value})
725
- try:
726
- betas1=betas1.append(row,ignore_index=True)
727
- except:
728
- betas1=betas1._append(row,ignore_index=True)
729
- #print(" Calculated CAPM beta of",stkcd1,'on year',year)
730
-
731
- betas1.set_index('Year',inplace=True)
732
-
733
- betas2=pd.DataFrame(columns=('Year','Beta','alpha','R-sqr','p-value'))
734
- for year in yearlist:
735
- #print(year,' ',end='')
736
- r=R2[R2['Year']==year]
737
- if len(r)==0: continue
738
- try:
739
- output=stats.linregress(r['Close_x'],r['Close_y'])
740
- except:
741
- print(" #Error(compare2_betas_yearly): no data for regression")
742
- print(" Information:",stkcd2,year,r,R2)
743
- continue
744
- (beta,alpha,r_value,p_value,std_err)=output
745
- row=pd.Series({'Year':year,'Beta':beta,'alpha':alpha, \
746
- 'R-sqr':r_value**2,'p-value':p_value})
747
- try:
748
- betas2=betas2.append(row,ignore_index=True)
749
- except:
750
- betas2=betas2._append(row,ignore_index=True)
751
- #print(" Calculated CAPM beta of",stkcd2,'on year',year)
752
-
753
- betas2.set_index('Year',inplace=True)
754
-
755
- #绘图:年度贝塔系数变化
756
- plt.plot(betas1['Beta'],label=ticker_name(ticker1),c='red',marker='o',lw=1)
757
- plt.plot(betas2['Beta'],label=ticker_name(ticker2),c='blue',marker='D',lw=2,linestyle='--')
758
-
759
- #plt.axhline(y=1.0,color='b',linestyle=':',c='green',label='市场平均风险')
760
- plt.axhline(y=1.0,color='b',linestyle=':',c='black')
761
-
762
- plt.ylabel("贝塔系数",fontweight='bold')
763
- plt.xticks(rotation=45,fontweight='bold')
764
- trtitle="比较证券之间的贝塔系数"+"\n"+ticker_name(ticker1)+" vs "+ticker_name(ticker2)
765
- plt.title(trtitle,fontweight='bold')
766
- plt.legend(loc='best')
767
-
768
- import datetime; today = datetime.date.today()
769
- plt.xlabel("数据来源:新浪/stooq/fred,基于"+ticker_name(mktidx)+','+str(today))
770
-
771
- plt.gca().set_facecolor('whitesmoke')
772
- plt.show()
773
-
774
- return betas1,betas2
775
-
776
- if __name__=='__main__':
777
- yearlist=['2013','2014','2015','2016','2017','2018','2019']
778
- compare2_betas_yearly('AMZN','WMT','^GSPC',yearlist)
779
- compare2_betas_yearly('601857.SS','600036.SS','000001.SS',yearlist)
780
-
781
- #==============================================================================
782
- #==============================================================================
783
- #==============================================================================