siat 3.10.130__py3-none-any.whl → 3.10.132__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 (217) hide show
  1. build/lib/build/lib/siat/__init__.py +75 -0
  2. build/lib/build/lib/siat/allin.py +137 -0
  3. build/lib/build/lib/siat/assets_liquidity.py +915 -0
  4. build/lib/build/lib/siat/beta_adjustment.py +1058 -0
  5. build/lib/build/lib/siat/beta_adjustment_china.py +548 -0
  6. build/lib/build/lib/siat/blockchain.py +143 -0
  7. build/lib/build/lib/siat/bond.py +2900 -0
  8. build/lib/build/lib/siat/bond_base.py +992 -0
  9. build/lib/build/lib/siat/bond_china.py +100 -0
  10. build/lib/build/lib/siat/bond_zh_sina.py +143 -0
  11. build/lib/build/lib/siat/capm_beta.py +783 -0
  12. build/lib/build/lib/siat/capm_beta2.py +887 -0
  13. build/lib/build/lib/siat/common.py +5360 -0
  14. build/lib/build/lib/siat/compare_cross.py +642 -0
  15. build/lib/build/lib/siat/copyrights.py +18 -0
  16. build/lib/build/lib/siat/cryptocurrency.py +667 -0
  17. build/lib/build/lib/siat/economy.py +1471 -0
  18. build/lib/build/lib/siat/economy2.py +1853 -0
  19. build/lib/build/lib/siat/esg.py +536 -0
  20. build/lib/build/lib/siat/event_study.py +815 -0
  21. build/lib/build/lib/siat/fama_french.py +1521 -0
  22. build/lib/build/lib/siat/fin_stmt2_yahoo.py +982 -0
  23. build/lib/build/lib/siat/financial_base.py +1160 -0
  24. build/lib/build/lib/siat/financial_statements.py +598 -0
  25. build/lib/build/lib/siat/financials.py +2339 -0
  26. build/lib/build/lib/siat/financials2.py +1278 -0
  27. build/lib/build/lib/siat/financials_china.py +4433 -0
  28. build/lib/build/lib/siat/financials_china2.py +2212 -0
  29. build/lib/build/lib/siat/fund.py +629 -0
  30. build/lib/build/lib/siat/fund_china.py +3307 -0
  31. build/lib/build/lib/siat/future_china.py +551 -0
  32. build/lib/build/lib/siat/google_authenticator.py +47 -0
  33. build/lib/build/lib/siat/grafix.py +3636 -0
  34. build/lib/build/lib/siat/holding_risk.py +867 -0
  35. build/lib/build/lib/siat/luchy_draw.py +638 -0
  36. build/lib/build/lib/siat/market_china.py +1168 -0
  37. build/lib/build/lib/siat/markowitz.py +2363 -0
  38. build/lib/build/lib/siat/markowitz2.py +3150 -0
  39. build/lib/build/lib/siat/markowitz2_20250704.py +2969 -0
  40. build/lib/build/lib/siat/markowitz2_20250705.py +3158 -0
  41. build/lib/build/lib/siat/markowitz_simple.py +373 -0
  42. build/lib/build/lib/siat/ml_cases.py +2291 -0
  43. build/lib/build/lib/siat/ml_cases_example.py +60 -0
  44. build/lib/build/lib/siat/option_china.py +3069 -0
  45. build/lib/build/lib/siat/option_pricing.py +1925 -0
  46. build/lib/build/lib/siat/other_indexes.py +409 -0
  47. build/lib/build/lib/siat/risk_adjusted_return.py +1576 -0
  48. build/lib/build/lib/siat/risk_adjusted_return2.py +1900 -0
  49. build/lib/build/lib/siat/risk_evaluation.py +2218 -0
  50. build/lib/build/lib/siat/risk_free_rate.py +351 -0
  51. build/lib/build/lib/siat/sector_china.py +4140 -0
  52. build/lib/build/lib/siat/security_price2.py +727 -0
  53. build/lib/build/lib/siat/security_prices.py +3408 -0
  54. build/lib/build/lib/siat/security_trend.py +402 -0
  55. build/lib/build/lib/siat/security_trend2.py +646 -0
  56. build/lib/build/lib/siat/stock.py +4284 -0
  57. build/lib/build/lib/siat/stock_advice_linear.py +934 -0
  58. build/lib/build/lib/siat/stock_base.py +26 -0
  59. build/lib/build/lib/siat/stock_china.py +2095 -0
  60. build/lib/build/lib/siat/stock_prices_kneighbors.py +910 -0
  61. build/lib/build/lib/siat/stock_prices_linear.py +386 -0
  62. build/lib/build/lib/siat/stock_profile.py +707 -0
  63. build/lib/build/lib/siat/stock_technical.py +3305 -0
  64. build/lib/build/lib/siat/stooq.py +74 -0
  65. build/lib/build/lib/siat/transaction.py +347 -0
  66. build/lib/build/lib/siat/translate.py +5183 -0
  67. build/lib/build/lib/siat/valuation.py +1378 -0
  68. build/lib/build/lib/siat/valuation_china.py +2076 -0
  69. build/lib/build/lib/siat/var_model_validation.py +444 -0
  70. build/lib/build/lib/siat/yf_name.py +811 -0
  71. build/lib/siat/__init__.py +75 -0
  72. build/lib/siat/allin.py +137 -0
  73. build/lib/siat/assets_liquidity.py +915 -0
  74. build/lib/siat/beta_adjustment.py +1058 -0
  75. build/lib/siat/beta_adjustment_china.py +548 -0
  76. build/lib/siat/blockchain.py +143 -0
  77. build/lib/siat/bond.py +2900 -0
  78. build/lib/siat/bond_base.py +992 -0
  79. build/lib/siat/bond_china.py +100 -0
  80. build/lib/siat/bond_zh_sina.py +143 -0
  81. build/lib/siat/capm_beta.py +783 -0
  82. build/lib/siat/capm_beta2.py +887 -0
  83. build/lib/siat/common.py +5360 -0
  84. build/lib/siat/compare_cross.py +642 -0
  85. build/lib/siat/copyrights.py +18 -0
  86. build/lib/siat/cryptocurrency.py +667 -0
  87. build/lib/siat/economy.py +1471 -0
  88. build/lib/siat/economy2.py +1853 -0
  89. build/lib/siat/esg.py +536 -0
  90. build/lib/siat/event_study.py +815 -0
  91. build/lib/siat/fama_french.py +1521 -0
  92. build/lib/siat/fin_stmt2_yahoo.py +982 -0
  93. build/lib/siat/financial_base.py +1160 -0
  94. build/lib/siat/financial_statements.py +598 -0
  95. build/lib/siat/financials.py +2339 -0
  96. build/lib/siat/financials2.py +1278 -0
  97. build/lib/siat/financials_china.py +4433 -0
  98. build/lib/siat/financials_china2.py +2212 -0
  99. build/lib/siat/fund.py +629 -0
  100. build/lib/siat/fund_china.py +3307 -0
  101. build/lib/siat/future_china.py +551 -0
  102. build/lib/siat/google_authenticator.py +47 -0
  103. build/lib/siat/grafix.py +3636 -0
  104. build/lib/siat/holding_risk.py +867 -0
  105. build/lib/siat/luchy_draw.py +638 -0
  106. build/lib/siat/market_china.py +1168 -0
  107. build/lib/siat/markowitz.py +2363 -0
  108. build/lib/siat/markowitz2.py +3150 -0
  109. build/lib/siat/markowitz2_20250704.py +2969 -0
  110. build/lib/siat/markowitz2_20250705.py +3158 -0
  111. build/lib/siat/markowitz_simple.py +373 -0
  112. build/lib/siat/ml_cases.py +2291 -0
  113. build/lib/siat/ml_cases_example.py +60 -0
  114. build/lib/siat/option_china.py +3069 -0
  115. build/lib/siat/option_pricing.py +1925 -0
  116. build/lib/siat/other_indexes.py +409 -0
  117. build/lib/siat/risk_adjusted_return.py +1576 -0
  118. build/lib/siat/risk_adjusted_return2.py +1900 -0
  119. build/lib/siat/risk_evaluation.py +2218 -0
  120. build/lib/siat/risk_free_rate.py +351 -0
  121. build/lib/siat/sector_china.py +4140 -0
  122. build/lib/siat/security_price2.py +727 -0
  123. build/lib/siat/security_prices.py +3408 -0
  124. build/lib/siat/security_trend.py +402 -0
  125. build/lib/siat/security_trend2.py +646 -0
  126. build/lib/siat/stock.py +4284 -0
  127. build/lib/siat/stock_advice_linear.py +934 -0
  128. build/lib/siat/stock_base.py +26 -0
  129. build/lib/siat/stock_china.py +2095 -0
  130. build/lib/siat/stock_prices_kneighbors.py +910 -0
  131. build/lib/siat/stock_prices_linear.py +386 -0
  132. build/lib/siat/stock_profile.py +707 -0
  133. build/lib/siat/stock_technical.py +3305 -0
  134. build/lib/siat/stooq.py +74 -0
  135. build/lib/siat/transaction.py +347 -0
  136. build/lib/siat/translate.py +5183 -0
  137. build/lib/siat/valuation.py +1378 -0
  138. build/lib/siat/valuation_china.py +2076 -0
  139. build/lib/siat/var_model_validation.py +444 -0
  140. build/lib/siat/yf_name.py +811 -0
  141. siat/__init__.py +0 -0
  142. siat/allin.py +0 -0
  143. siat/assets_liquidity.py +0 -0
  144. siat/beta_adjustment.py +0 -0
  145. siat/beta_adjustment_china.py +0 -0
  146. siat/blockchain.py +0 -0
  147. siat/bond.py +0 -0
  148. siat/bond_base.py +0 -0
  149. siat/bond_china.py +0 -0
  150. siat/bond_zh_sina.py +0 -0
  151. siat/capm_beta.py +0 -0
  152. siat/capm_beta2.py +0 -0
  153. siat/common.py +94 -30
  154. siat/compare_cross.py +0 -0
  155. siat/copyrights.py +0 -0
  156. siat/cryptocurrency.py +0 -0
  157. siat/economy.py +0 -0
  158. siat/economy2.py +0 -0
  159. siat/esg.py +0 -0
  160. siat/event_study.py +0 -0
  161. siat/fama_french.py +0 -0
  162. siat/fin_stmt2_yahoo.py +0 -0
  163. siat/financial_base.py +0 -0
  164. siat/financial_statements.py +0 -0
  165. siat/financials.py +0 -0
  166. siat/financials2.py +0 -0
  167. siat/financials_china.py +0 -0
  168. siat/financials_china2.py +0 -0
  169. siat/fund.py +0 -0
  170. siat/fund_china.py +0 -0
  171. siat/future_china.py +0 -0
  172. siat/google_authenticator.py +0 -0
  173. siat/grafix.py +1 -1
  174. siat/holding_risk.py +0 -0
  175. siat/luchy_draw.py +0 -0
  176. siat/market_china.py +7 -1
  177. siat/markowitz.py +0 -0
  178. siat/markowitz2.py +240 -39
  179. siat/markowitz2_20250704.py +2969 -0
  180. siat/markowitz2_20250705.py +3158 -0
  181. siat/markowitz_simple.py +0 -0
  182. siat/ml_cases.py +0 -0
  183. siat/ml_cases_example.py +0 -0
  184. siat/option_china.py +0 -0
  185. siat/option_pricing.py +0 -0
  186. siat/other_indexes.py +0 -0
  187. siat/risk_adjusted_return.py +0 -0
  188. siat/risk_adjusted_return2.py +0 -0
  189. siat/risk_evaluation.py +0 -0
  190. siat/risk_free_rate.py +0 -0
  191. siat/sector_china.py +0 -0
  192. siat/security_price2.py +0 -0
  193. siat/security_prices.py +3 -1
  194. siat/security_trend.py +0 -0
  195. siat/security_trend2.py +1 -1
  196. siat/stock.py +4 -2
  197. siat/stock_advice_linear.py +0 -0
  198. siat/stock_base.py +0 -0
  199. siat/stock_china.py +0 -0
  200. siat/stock_prices_kneighbors.py +0 -0
  201. siat/stock_prices_linear.py +0 -0
  202. siat/stock_profile.py +0 -0
  203. siat/stock_technical.py +0 -0
  204. siat/stooq.py +0 -0
  205. siat/transaction.py +0 -0
  206. siat/translate.py +11 -11
  207. siat/valuation.py +0 -0
  208. siat/valuation_china.py +0 -0
  209. siat/var_model_validation.py +0 -0
  210. siat/yf_name.py +0 -0
  211. {siat-3.10.130.dist-info → siat-3.10.132.dist-info}/METADATA +11 -11
  212. siat-3.10.132.dist-info/RECORD +218 -0
  213. siat-3.10.132.dist-info/top_level.txt +4 -0
  214. siat-3.10.130.dist-info/RECORD +0 -76
  215. siat-3.10.130.dist-info/top_level.txt +0 -1
  216. {siat-3.10.130.dist-info → siat-3.10.132.dist-info}/WHEEL +0 -0
  217. {siat-3.10.130.dist-info → siat-3.10.132.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,1925 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ 本模块功能:期权定价理论计算函数包
4
+ 所属工具包:证券投资分析工具SIAT
5
+ SIAT:Security Investment Analysis Tool
6
+ 创建日期:2020年7月16日
7
+ 最新修订日期:2020年8月5日
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.grafix import *
21
+ from siat.security_prices import *
22
+ from siat.security_trend2 import *
23
+ from siat.yf_name import *
24
+ #==============================================================================
25
+ import matplotlib.pyplot as plt
26
+
27
+ #处理绘图汉字乱码问题
28
+ import sys; czxt=sys.platform
29
+ if czxt in ['win32','win64']:
30
+ plt.rcParams['font.sans-serif'] = ['SimHei'] # 设置默认字体
31
+ mpfrc={'font.family': 'SimHei'}
32
+
33
+ if czxt in ['darwin']: #MacOSX
34
+ plt.rcParams['font.family']= ['Heiti TC']
35
+ mpfrc={'font.family': 'Heiti TC'}
36
+
37
+ if czxt in ['linux']: #website Jupyter
38
+ plt.rcParams['font.family']= ['Heiti TC']
39
+ mpfrc={'font.family':'Heiti TC'}
40
+
41
+ # 解决保存图像时'-'显示为方块的问题
42
+ plt.rcParams['axes.unicode_minus'] = False
43
+
44
+ #==============================================================================
45
+ if __name__=='__main__':
46
+ direction='call'
47
+
48
+
49
+ def bs_pricing(S0,X,Days,r0,sigma,direction='call',printout=True):
50
+ """
51
+ 功能:计算无红利支付的欧式期权B-S定价模型,默认看涨期权
52
+ 注意:
53
+ S0:标的物资产的当前价格,X为其行权价
54
+ sigma:标的物资产价格收益率的年化标准差
55
+ r0:年化无风险利率(程序中会转化为连续计算的无风险利率)
56
+ Days:距离到期日的天数(程序中会转换为距离到期日的年数=距离到期日的天数/365)
57
+ """
58
+
59
+ direction=direction.upper()
60
+
61
+ if direction=='CALL':
62
+ C0=bs_call(S0,X,Days,r0,sigma,printout=printout)
63
+ else:
64
+ C0=bs_put(S0,X,Days,r0,sigma,printout=printout)
65
+
66
+
67
+ return C0
68
+
69
+ #==============================================================================
70
+
71
+ def bs_call(S0,X,Days,r0,sigma,printout=True):
72
+ """
73
+ 功能:计算无红利支付的欧式期权B-S定价模型,看涨期权
74
+ 注意:
75
+ S0:标的物资产的当前价格,X为其行权价
76
+ sigma:标的物资产价格收益率的年化标准差
77
+ r0:年化无风险利率(需要转化为连续计算的无风险利率)
78
+ Days:距离到期日的天数,需要转换为距离到期日的年数=距离到期日的天数/365
79
+ """
80
+ from scipy import stats
81
+ from numpy import log,exp,sqrt
82
+
83
+ #Days为距离到期日的日历日天数
84
+ T=Days/365.
85
+ r=log(r0+1)
86
+
87
+ d1=(log(S0/X)+(r+sigma*sigma/2.)*T)/(sigma*sqrt(T))
88
+ d2=d1-sigma*sqrt(T)
89
+
90
+ C0=S0*stats.norm.cdf(d1)-X*exp(-r*T)*stats.norm.cdf(d2)
91
+
92
+ if not printout: return C0
93
+ print("\n===== Black-Scholes期权定价 =====")
94
+ print("适用情形: 欧式期权,标的资产无红利收益")
95
+ print("标的资产行权价:",X)
96
+ print("标的资产现价 :",S0)
97
+ print("标的资产的年化波动率:",round(sigma,4))
98
+ print("距离到期日的年数 :",round(T,4))
99
+ print("连续计算的无风险利率:",round(r*100,4),'\b%')
100
+ print("看涨期权的预期价格 :",round(C0,4))
101
+
102
+ return C0
103
+
104
+ if __name__=='__main__':
105
+ S0=40
106
+ X=42
107
+ Days=183
108
+ r0=0.03
109
+ sigma=0.02
110
+ C0=bs_call(40,42,183,0.015,0.02)
111
+
112
+ #==============================================================================
113
+ def bsm_call(S0,X,Days,r0,sigma,Days1=0,div1=0,printout=True):
114
+ """
115
+ 功能:计算有红利支付的欧式期权B-S定价模型,看涨期权
116
+ 注意:
117
+ S0:标的物资产的当前价格,X为其行权价
118
+ sigma:标的物资产价格收益率的年化标准差
119
+ r0:年化无风险利率(需要转化为连续计算的无风险利率)
120
+ Days:距离到期日的天数,需要转换为距离到期日的年数=距离到期日的天数/365
121
+ Days1:红利发放时距离到期日的天数,需要转换为年数
122
+ div1:红利金额
123
+ """
124
+ from numpy import log,exp
125
+ #Days1为距离到期日的日历日天数
126
+ T=Days/365.
127
+ T1=Days1/365.
128
+ r=log(r0+1)
129
+ #调整标的物当前价
130
+ S=S0-exp(-r*T1)*div1
131
+
132
+ #调用BS模型计算
133
+ C=bs_call(S,X,Days,r0,sigma,printout=False)
134
+
135
+ if not printout: return C
136
+ print("\n=== Black-Scholes-Merton期权定价 ===")
137
+ print("适用情形: 欧式期权,标的资产有红利收益")
138
+ print("标的资产行权价:",X)
139
+ print("标的资产现价 :",S0)
140
+ print("标的资产的年化波动率 :",round(sigma,4))
141
+ print("距离到期日的年数 :",round(T,4))
142
+ print("连续计算的无风险利率 :",round(r,4)*100,'\b%')
143
+ print("红利及距离到期日的年数:",div1,"@",round(T1,4))
144
+ print("看涨期权的预期价格 :",round(C,4))
145
+
146
+ return C
147
+
148
+ if __name__=='__main__':
149
+ S0=42
150
+ X=40
151
+ Days=183
152
+ r0=0.03
153
+ sigma=0.02
154
+ dv1=1.5
155
+ Days1=183
156
+ C=bsm_call(42,40,183,0.015,0.02,183,1.5)
157
+ C0=bsm_call(42,40,183,0.015,0.23)
158
+
159
+ #==============================================================================
160
+ def bs_put(S0,X,Days,r0,sigma,printout=True):
161
+ """
162
+ 功能:计算无红利支付的欧式期权B-S定价模型,看跌期权
163
+ 注意:
164
+ S0:标的物资产的当前价格,X为其行权价
165
+ sigma:标的物资产价格收益率的年化标准差
166
+ r0:年化无风险利率(需要转化为连续计算的无风险利率)
167
+ Days:距离到期日的天数,需要转换为距离到期日的年数=距离到期日的天数/365
168
+ """
169
+ from scipy import stats
170
+ from numpy import log,exp,sqrt
171
+
172
+ #Days为距离到期日的日历日天数
173
+ T=Days/365.
174
+ r=log(r0+1)
175
+
176
+ d1=(log(S0/X)+(r+sigma*sigma/2.)*T)/(sigma*sqrt(T))
177
+ d2=d1-sigma*sqrt(T)
178
+
179
+ P0=-S0*stats.norm.cdf(-d1)+X*exp(-r*T)*stats.norm.cdf(-d2)
180
+
181
+ if not printout: return P0
182
+ print("\n===== Black-Scholes期权定价 =====")
183
+ print("适用情形: 欧式期权,标的资产无红利收益")
184
+ print("标的资产行权价:",X)
185
+ print("标的资产现价 :",S0)
186
+ print("标的资产的年化波动率:",round(sigma,4))
187
+ print("距离到期日的年数 :",round(T,4))
188
+ print("连续计算的无风险利率:",round(r*100,4),'\b%')
189
+ print("看跌期权的预期价格 :",round(P0,4))
190
+
191
+ return P0
192
+
193
+ if __name__=='__main__':
194
+ S0=40
195
+ X=42
196
+ Days=183
197
+ r0=0.03
198
+ sigma=0.02
199
+ P0=bs_put(40,42,183,0.015,0.02)
200
+
201
+ #==============================================================================
202
+ def bsm_put(S0,X,Days,r0,sigma,Days1=0,div1=0,printout=True):
203
+ """
204
+ 功能:计算有红利支付的欧式期权B-S定价模型,看跌期权
205
+ 注意:
206
+ S0:标的物资产的当前价格,X为其行权价
207
+ sigma:标的物资产价格收益率的年化标准差
208
+ r0:年化无风险利率(需要转化为连续计算的无风险利率)
209
+ Days:距离到期日的天数,需要转换为距离到期日的年数=距离到期日的天数/365
210
+ Days1:红利发放时距离到期日的天数,需要转换为年数
211
+ div1:红利金额
212
+ """
213
+ from numpy import log,exp,sqrt
214
+
215
+ #Days为距离到期日的日历日天数
216
+ T=Days/365.
217
+ T1=Days1/365.
218
+ r=log(r0+1)
219
+
220
+ S=S0-exp(-r*T1)*div1
221
+
222
+ #调用BS模型计算
223
+ P=bs_put(S,X,Days,r0,sigma,printout=False)
224
+
225
+ if not printout: return P
226
+ print("\n=== Black-Scholes-Merton期权定价 ===")
227
+ print("适用情形: 欧式期权,标的资产有红利收益")
228
+ print("标的资产行权价:",X)
229
+ print("标的资产现价 :",S0)
230
+ print("标的资产的年化波动率 :",round(sigma,4))
231
+ print("距离到期日的年数 :",round(T,4))
232
+ print("连续计算的无风险利率 :",round(r,4)*100,'\b%')
233
+ print("红利及距离到期日的年数:",div1,"@",round(T1,2))
234
+ print("看跌期权的预期价格 :",round(P,4))
235
+
236
+ return P
237
+
238
+ if __name__=='__main__':
239
+ S0=42
240
+ X=40
241
+ Days=183
242
+ r0=0.03
243
+ sigma=0.02
244
+ P=bsm_put(42,40,183,0.015,0.23,90,1.5)
245
+ P0=bsm_put(42,40,183,0.015,0.23)
246
+
247
+ #==============================================================================
248
+ def bsm_put_aprice(Srange,X,Days,r0,sigma,Days1=0,div1=0,graph=True):
249
+ """
250
+ 功能:计算有红利支付的欧式期权BSM定价模型,看跌期权,当前价格为变化范围
251
+ 注意:
252
+ Srange:标的物资产的当前价格范围,默认20等分后作为横轴绘图
253
+ X:期权的行权价
254
+ sigma:标的物资产价格收益率的年化标准差
255
+ r0:年化无风险利率(需要转化为连续计算的无风险利率)
256
+ Days:距离到期日的天数,需要转换为距离到期日的年数=距离到期日的天数/365
257
+ Days1:红利发放时距离到期日的天数,需要转换为年数
258
+ div1:红利金额
259
+ """
260
+ #通用修改点
261
+ trange=Srange
262
+ #检查是否为列表
263
+ if not isinstance(trange,list):
264
+ print("#Error(bsm_put_aprice): target is not a range,",trange)
265
+ return
266
+ if len(trange) < 2:
267
+ print("#Error(bsm_put_aprice): not enough range for target,",trange)
268
+ return
269
+
270
+ #确定起始位置和间隔大小
271
+ tstart=trange[0]; tend=trange[1]
272
+ if len(trange) >=3: tstep=trange[2]
273
+ else: tstep=(tend-tstart)/20.
274
+ #横轴点列表
275
+ import numpy as np
276
+ tlist=np.arange(tstart,tend+tstep,tstep)
277
+
278
+ #循环计算各点数值
279
+ import pandas as pd
280
+ df=pd.DataFrame(columns=['Option Price','Asset Price','Strike Price', \
281
+ 'Days to Maturity','Annual RF', \
282
+ 'Annual Sigma','Div to Maturity','Dividend'])
283
+ for t in tlist:
284
+ #通用修改点
285
+ op=bsm_put(t,X,Days,r0,sigma,Days1,div1,printout=False)
286
+ s=pd.Series({'Option Price':op,'Asset Price':t,'Strike Price':X, \
287
+ 'Days to Maturity':Days,'Annual RF':r0, \
288
+ 'Annual Sigma':sigma,'Div to Maturity':Days1, \
289
+ 'Dividend':div1})
290
+ try:
291
+ df=df.append(s,ignore_index=True)
292
+ except:
293
+ df=df._append(s,ignore_index=True)
294
+ #通用修改点
295
+ df2=df.set_index(['Asset Price'])
296
+ if not graph: return df2
297
+
298
+ #绘图
299
+ #通用修改点
300
+ colname='Option Price'; collabel='看跌期权'
301
+ ylabeltxt='期权价格'
302
+ titletxt='期权价格的变化趋势图'
303
+ #通用修改点
304
+ fn1='标的物市场价格'
305
+ fn2='\n[期权信息]行权价='+str(X)+', 距离到期天数='+str(Days)
306
+ fn3='\n年化无风险利率%='+str(round(r0*100.,2))+', 年化波动率%='+str(round(sigma*100.,2))
307
+ if div1==0:
308
+ fn4='\n本产品无红利收益'
309
+ else:
310
+ fn4='\n发放红利时间距离到期天数='+str(Days1)+', 红利='+str(div1)
311
+ footnote=fn1+fn2+fn3+fn4
312
+ plot_line(df2,colname,collabel,ylabeltxt,titletxt,footnote)
313
+
314
+ return df2
315
+
316
+ if __name__=='__main__':
317
+ Srange=[30,50,1]
318
+ X=40
319
+ Days=183
320
+ r0=0.03
321
+ sigma=0.02
322
+ Days1=0
323
+ div1=0
324
+ pdf=bsm_put_aprice(Srange,40,183,0.015,0.23,90,1.5)
325
+
326
+ #==============================================================================
327
+ def bsm_call_aprice(Srange,X,Days,r0,sigma,Days1=0,div1=0,graph=True):
328
+ """
329
+ 功能:计算有红利支付的欧式期权BSM定价模型,看涨期权,当前价格为变化范围
330
+ 注意:
331
+ Srange:标的物资产的当前价格范围,默认20等分后作为横轴绘图
332
+ X:期权的行权价
333
+ sigma:标的物资产价格收益率的年化标准差
334
+ r0:年化无风险利率(需要转化为连续计算的无风险利率)
335
+ Days:距离到期日的天数,需要转换为距离到期日的年数=距离到期日的天数/365
336
+ Days1:红利发放时距离到期日的天数,需要转换为年数
337
+ div1:红利金额
338
+ """
339
+ #通用修改点
340
+ trange=Srange
341
+ #检查是否为列表
342
+ if not isinstance(trange,list):
343
+ print("#Error(bsm_call_aprice): target is not a range,",trange)
344
+ return
345
+ if len(trange) < 2:
346
+ print("#Error(bsm_call_aprice): not enough range for target,",trange)
347
+ return
348
+
349
+ #确定起始位置和间隔大小
350
+ tstart=trange[0]; tend=trange[1]
351
+ if len(trange) >=3: tstep=trange[2]
352
+ else: tstep=(tend-tstart)/20.
353
+ #横轴点列表
354
+ import numpy as np
355
+ tlist=np.arange(tstart,tend+tstep,tstep)
356
+
357
+ #循环计算各点数值
358
+ import pandas as pd
359
+ df=pd.DataFrame(columns=['Option Price','Asset Price','Strike Price', \
360
+ 'Days to Maturity','Annual RF', \
361
+ 'Annual Sigma','Div to Maturity','Dividend'])
362
+ for t in tlist:
363
+ #通用修改点
364
+ op=bsm_call(t,X,Days,r0,sigma,Days1,div1,printout=False)
365
+ s=pd.Series({'Option Price':op,'Asset Price':t,'Strike Price':X, \
366
+ 'Days to Maturity':Days,'Annual RF':r0, \
367
+ 'Annual Sigma':sigma,'Div to Maturity':Days1, \
368
+ 'Dividend':div1})
369
+ try:
370
+ df=df.append(s,ignore_index=True)
371
+ except:
372
+ df=df._append(s,ignore_index=True)
373
+ #通用修改点
374
+ df2=df.set_index(['Asset Price'])
375
+ if not graph: return df2
376
+
377
+ #绘图
378
+ #通用修改点
379
+ colname='Option Price'; collabel='看涨期权'
380
+ ylabeltxt='期权价格'
381
+ titletxt='期权价格的变化趋势图'
382
+ #通用修改点
383
+ fn1='标的物市场价格'
384
+ fn2='\n[期权信息]行权价='+str(X)+', 距离到期天数='+str(Days)
385
+ fn3='\n年化无风险利率%='+str(round(r0*100.,2))+', 年化波动率%='+str(round(sigma*100.,2))
386
+ if div1==0:
387
+ fn4='\n本产品无红利收益'
388
+ else:
389
+ fn4='\n发放红利时间距离到期天数='+str(Days1)+', 红利='+str(div1)
390
+ footnote=fn1+fn2+fn3+fn4
391
+ plot_line(df2,colname,collabel,ylabeltxt,titletxt,footnote)
392
+
393
+ return df2
394
+
395
+ if __name__=='__main__':
396
+ Srange=[30,50,1]
397
+ X=40
398
+ Days=183
399
+ r0=0.03
400
+ sigma=0.02
401
+ Days1=0
402
+ div1=0
403
+ cdf=bsm_call_aprice(Srange,40,183,0.015,0.23,90,1.5)
404
+
405
+ #==============================================================================
406
+ def bsm_aprice(Srange,X,Days,r0,sigma,Days1=0,div1=0,graph=True):
407
+ """
408
+ 功能:计算有红利支付的欧式期权BSM定价模型,看涨/看跌期权,当前价格为变化范围
409
+ 注意:
410
+ Srange:标的物资产的当前价格范围,默认20等分后作为横轴绘图
411
+ X:期权的行权价
412
+ sigma:标的物资产价格收益率的年化标准差
413
+ r0:年化无风险利率(需要转化为连续计算的无风险利率)
414
+ Days:距离到期日的天数,需要转换为距离到期日的年数=距离到期日的天数/365
415
+ Days1:红利发放时距离到期日的天数,需要转换为年数
416
+ div1:红利金额
417
+ """
418
+ #通用修改点
419
+ trange=Srange
420
+ #检查是否为列表
421
+ if not isinstance(trange,list):
422
+ print("#Error(bsm_aprice): target is not a range,",trange)
423
+ return
424
+ if len(trange) < 2:
425
+ print("#Error(bsm_aprice): not enough range for target,",trange)
426
+ return
427
+
428
+ #看涨期权
429
+ df1=bsm_call_aprice(Srange,X,Days,r0,sigma,Days1=0,div1=0,graph=False)
430
+ #看跌期权
431
+ df2=bsm_put_aprice(Srange,X,Days,r0,sigma,Days1=0,div1=0,graph=False)
432
+
433
+ #绘图
434
+ #通用修改点
435
+ ticker1='看涨期权'; colname1='Option Price'; label1='期权-C-'+str(X)
436
+ ticker2='看跌期权'; colname2='Option Price'; label2='期权-P-'+str(X)
437
+ ylabeltxt='期权价格'
438
+ titletxt='期权价格的变化趋势图'
439
+ #通用修改点
440
+ fn1='标的物市场价格-->'
441
+ fn2='\n[期权信息]行权价='+str(X)+', 距离到期天数='+str(Days)
442
+ fn3='\n年化无风险利率%='+str(round(r0*100.,2))+', 年化波动率%='+str(round(sigma*100.,2))
443
+ if div1==0:
444
+ fn4='\n本产品无红利收益'
445
+ else:
446
+ fn4='\n发放红利时间距离到期天数='+str(Days1)+', 红利='+str(div1)
447
+ footnote=fn1+fn2+fn3+fn4
448
+ plot_line2_coaxial(df1,ticker1,colname1,label1, \
449
+ df2,ticker2,colname2,label2, \
450
+ ylabeltxt,titletxt,footnote)
451
+ return
452
+
453
+ if __name__=='__main__':
454
+ Srange=[30,50,1]
455
+ X=40
456
+ Days=183
457
+ r0=0.03
458
+ sigma=0.02
459
+ Days1=0
460
+ div1=0
461
+ bsm_aprice(Srange,40,183,0.015,0.23,90,1.5)
462
+ bsm_aprice([30,50],40,183,0.015,0.23,90,1.5)
463
+
464
+ #==============================================================================
465
+ def bsm_put_maturity(S0,X,Dayrange,r0,sigma,Days1=0,div1=0,graph=True):
466
+ """
467
+ 功能:计算有红利支付的欧式期权BSM定价模型,看跌期权,距离到期日天数为变化范围
468
+ 注意:
469
+ S0:标的物资产的当前价格
470
+ X:期权的行权价
471
+ sigma:标的物资产价格收益率的年化标准差
472
+ r0:年化无风险利率(需要转化为连续计算的无风险利率)
473
+ Dayrange:距离到期日的天数范围,默认变化间隔为20分之一取整
474
+ Days1:红利发放时距离到期日的天数,需要转换为年数
475
+ div1:红利金额
476
+ """
477
+ #通用修改点
478
+ trange=Dayrange
479
+ #检查是否为列表
480
+ if not isinstance(trange,list):
481
+ print("#Error(bsm_put_maturity): target is not a range,",trange)
482
+ return
483
+ if len(trange) < 2:
484
+ print("#Error(bsm_put_maturity): not enough range for target,",trange)
485
+ return
486
+
487
+ #确定起始位置和间隔大小
488
+ tstart=int(trange[0]); tend=int(trange[1])
489
+ if len(trange) >=3: tstep=trange[2]
490
+ else: tstep=int((tend-tstart)/20)
491
+ #横轴点列表
492
+ #import numpy as np
493
+ tlist=range(tstart,tend+tstep,tstep)
494
+
495
+ #循环计算各点数值
496
+ import pandas as pd
497
+ df=pd.DataFrame(columns=['Option Price','Asset Price','Strike Price', \
498
+ 'Days to Maturity','Annual RF', \
499
+ 'Annual Sigma','Div to Maturity','Dividend'])
500
+ for t in tlist:
501
+ #通用修改点
502
+ op=bsm_put(S0,X,t,r0,sigma,Days1,div1,printout=False)
503
+ s=pd.Series({'Option Price':op,'Asset Price':S0,'Strike Price':X, \
504
+ 'Days to Maturity':t,'Annual RF':r0, \
505
+ 'Annual Sigma':sigma,'Div to Maturity':Days1, \
506
+ 'Dividend':div1})
507
+ try:
508
+ df=df.append(s,ignore_index=True)
509
+ except:
510
+ df=df._append(s,ignore_index=True)
511
+ #通用修改点
512
+ df2=df.set_index(['Days to Maturity'])
513
+ if not graph: return df2
514
+
515
+ #绘图
516
+ #通用修改点
517
+ colname='Option Price'; collabel='看跌期权'
518
+ ylabeltxt='期权价格'
519
+ titletxt='期权价格的变化趋势图'
520
+ #通用修改点
521
+ fn1='<--距离到期日的天数'
522
+ fn2='\n[期权信息]行权价='+str(X)+', 标的物市价='+str(S0)
523
+ fn3='\n年化无风险利率%='+str(round(r0*100.,2))+', 年化波动率%='+str(round(sigma*100.,2))
524
+ if div1==0:
525
+ fn4='\n本产品无红利收益'
526
+ else:
527
+ fn4='\n发放红利时间距离到期天数='+str(Days1)+', 红利='+str(div1)
528
+ footnote=fn1+fn2+fn3+fn4
529
+ plot_line(df2,colname,collabel,ylabeltxt,titletxt,footnote)
530
+
531
+ return df2
532
+
533
+ if __name__=='__main__':
534
+ S0=42
535
+ X=40
536
+ Dayrange=[200,50]
537
+ r0=0.015
538
+ sigma=0.23
539
+ Days1=90
540
+ div1=1.5
541
+ pdf=bsm_put_maturity(42,40,[200,50],0.015,0.23,90,1.5)
542
+
543
+ #==============================================================================
544
+ def bsm_call_maturity(S0,X,Dayrange,r0,sigma,Days1=0,div1=0,graph=True):
545
+ """
546
+ 功能:计算有红利支付的欧式期权BSM定价模型,看涨期权,距离到期日天数为变化范围
547
+ 注意:
548
+ S0:标的物资产的当前价格
549
+ X:期权的行权价
550
+ sigma:标的物资产价格收益率的年化标准差
551
+ r0:年化无风险利率(需要转化为连续计算的无风险利率)
552
+ Dayrange:距离到期日的天数范围,默认变化间隔为20分之一取整
553
+ Days1:红利发放时距离到期日的天数,需要转换为年数
554
+ div1:红利金额
555
+ """
556
+ #通用修改点
557
+ trange=Dayrange
558
+ #检查是否为列表
559
+ if not isinstance(trange,list):
560
+ print("#Error(bsm_call_maturity): target is not a range,",trange)
561
+ return
562
+ if len(trange) < 2:
563
+ print("#Error(bsm_call_maturity): not enough range for target,",trange)
564
+ return
565
+
566
+ #确定起始位置和间隔大小
567
+ tstart=int(trange[0]); tend=int(trange[1])
568
+ if len(trange) >=3: tstep=trange[2]
569
+ else: tstep=int((tend-tstart)/20)
570
+ #横轴点列表
571
+ #import numpy as np
572
+ tlist=range(tstart,tend+tstep,tstep)
573
+
574
+ #循环计算各点数值
575
+ import pandas as pd
576
+ df=pd.DataFrame(columns=['Option Price','Asset Price','Strike Price', \
577
+ 'Days to Maturity','Annual RF', \
578
+ 'Annual Sigma','Div to Maturity','Dividend'])
579
+ for t in tlist:
580
+ #通用修改点
581
+ op=bsm_call(S0,X,t,r0,sigma,Days1,div1,printout=False)
582
+ s=pd.Series({'Option Price':op,'Asset Price':S0,'Strike Price':X, \
583
+ 'Days to Maturity':t,'Annual RF':r0, \
584
+ 'Annual Sigma':sigma,'Div to Maturity':Days1, \
585
+ 'Dividend':div1})
586
+ try:
587
+ df=df.append(s,ignore_index=True)
588
+ except:
589
+ df=df._append(s,ignore_index=True)
590
+ #通用修改点
591
+ df2=df.set_index(['Days to Maturity'])
592
+ if not graph: return df2
593
+
594
+ #绘图
595
+ #通用修改点
596
+ colname='Option Price'; collabel='看涨期权'
597
+ ylabeltxt='期权价格'
598
+ titletxt='期权价格的变化趋势图'
599
+ #通用修改点
600
+ fn1='<--距离到期日的天数'
601
+ fn2='\n[期权信息]行权价='+str(X)+', 标的物市价='+str(S0)
602
+ fn3='\n年化无风险利率%='+str(round(r0*100.,2))+', 年化波动率%='+str(round(sigma*100.,2))
603
+ if div1==0:
604
+ fn4='\n本产品无红利收益'
605
+ else:
606
+ fn4='\n发放红利时间距离到期天数='+str(Days1)+', 红利='+str(div1)
607
+ footnote=fn1+fn2+fn3+fn4
608
+ plot_line(df2,colname,collabel,ylabeltxt,titletxt,footnote)
609
+
610
+ return df2
611
+
612
+ if __name__=='__main__':
613
+ S0=42
614
+ X=40
615
+ Dayrange=[200,50]
616
+ r0=0.015
617
+ sigma=0.23
618
+ Days1=90
619
+ div1=1.5
620
+ cdf=bsm_call_maturity(42,40,[200,50],0.015,0.23,90,1.5)
621
+
622
+ #==============================================================================
623
+ if __name__=='__main__':
624
+ S0=42
625
+ X=40
626
+ Dayrange=[200,50]
627
+ r0=0.015
628
+ sigma=0.23
629
+ Days1=90
630
+ div1=1.5
631
+
632
+ def bsm_maturity(S0,X,Dayrange,r0,sigma,Days1=0,div1=0,graph=True):
633
+ """
634
+ 功能:计算有红利支付的欧式期权BSM定价模型,看涨/看跌期权,距离到期日天数为变化范围
635
+ 注意:
636
+ S0:标的物资产的当前价格
637
+ X:期权的行权价
638
+ sigma:标的物资产价格收益率的年化标准差
639
+ r0:年化无风险利率(需要转化为连续计算的无风险利率)
640
+ Dayrange:距离到期日的天数范围,默认间隔为20分之一取证
641
+ Days1:红利发放时距离到期日的天数,需要转换为年数
642
+ div1:红利金额
643
+ """
644
+ #通用修改点
645
+ trange=Dayrange
646
+ #检查是否为列表
647
+ if not isinstance(trange,list):
648
+ print("#Error(bsm_maturity): target is not a range,",trange)
649
+ return
650
+ if len(trange) < 2:
651
+ print("#Error(bsm_maturity): not enough range for target,",trange)
652
+ return
653
+
654
+ #看涨期权
655
+ df1=bsm_call_maturity(S0,X,Dayrange,r0,sigma,Days1=0,div1=0,graph=False)
656
+ df1.sort_index(ascending=False, inplace=True)
657
+ #看跌期权
658
+ df2=bsm_put_maturity(S0,X,Dayrange,r0,sigma,Days1=0,div1=0,graph=False)
659
+ df2.sort_index(ascending=False, inplace=True)
660
+ #合并
661
+ import pandas as pd
662
+ df=pd.merge(df1,df2,how='inner',left_index=True,right_index=True,sort=True)
663
+ #df['到期日']=df.index
664
+ #df.sort_values('到期日',ascending=False,inplace=True)
665
+
666
+ #绘图
667
+ plt.title('期权价格的变化趋势图')
668
+ plt.ylabel('期权价格')
669
+
670
+ df['Option Price_x'].plot(label='看涨期权',ls='-')
671
+ df['Option Price_y'].plot(label='看跌期权',ls='-.')
672
+
673
+ fn1='距离到期日的天数-->'
674
+ fn2='\n[期权信息]行权价='+str(X)+', 标的物市价='+str(S0)
675
+ fn3='\n年化无风险利率%='+str(round(r0*100.,2))+', 年化波动率%='+str(round(sigma*100.,2))
676
+ if div1==0: fn4='\n本产品无红利收益'
677
+ else: fn4='\n发放红利时间距离到期天数='+str(Days1)+', 红利='+str(div1)
678
+ footnote=fn1+fn2+fn3+fn4
679
+ plt.xlabel(footnote)
680
+
681
+ #让横轴逆序从大到小显示,正常顺序为从小到大
682
+ plt.gca().invert_xaxis()
683
+ plt.legend()
684
+
685
+ plt.gca().set_facecolor('whitesmoke')
686
+ plt.show()
687
+
688
+ return
689
+
690
+ if __name__=='__main__':
691
+ S0=42
692
+ X=40
693
+ Dayrange=[200,50]
694
+ r0=0.015
695
+ sigma=0.23
696
+ Days1=90
697
+ div1=1.5
698
+ bsm_maturity(S0,40,[200,5],0.015,0.23,90,1.5)
699
+ bsm_maturity(42,40,[50,200],0.015,0.23,90,1.5)
700
+
701
+ #==============================================================================
702
+ def bsm_put_sigma(S0,X,Days,r0,sigmarange,Days1=0,div1=0,graph=True):
703
+ """
704
+ 功能:计算有红利支付的欧式期权BSM定价模型,看跌期权,年化波动率为变化范围
705
+ 注意:
706
+ S0:标的物资产的当前价格
707
+ X:期权的行权价
708
+ sigmarange:标的物资产价格收益率的年化标准差范围,默认为区间的20分之一作为间隔
709
+ r0:年化无风险利率(需要转化为连续计算的无风险利率)
710
+ Days:距离到期日的天数
711
+ Days1:红利发放时距离到期日的天数,需要转换为年数
712
+ div1:红利金额
713
+ """
714
+ #通用修改点
715
+ trange=sigmarange
716
+ #检查是否为列表
717
+ if not isinstance(trange,list):
718
+ print("#Error(bsm_put_sigma): target is not a range,",trange)
719
+ return
720
+ if len(trange) < 2:
721
+ print("#Error(bsm_put_sigma): not enough range for target,",trange)
722
+ return
723
+
724
+ #确定起始位置和间隔大小
725
+ tstart=trange[0]; tend=trange[1]
726
+ if len(trange) >=3: tstep=trange[2]
727
+ else: tstep=(tend-tstart)/20.
728
+ #横轴点列表
729
+ import numpy as np
730
+ tlist=np.arange(tstart,tend+tstep,tstep)
731
+
732
+ #循环计算各点数值
733
+ import pandas as pd
734
+ df=pd.DataFrame(columns=['Option Price','Asset Price','Strike Price', \
735
+ 'Days to Maturity','Annual RF', \
736
+ 'Annual Sigma','Div to Maturity','Dividend'])
737
+ for t in tlist:
738
+ #通用修改点
739
+ op=bsm_put(S0,X,Days,r0,t,Days1,div1,printout=False)
740
+ s=pd.Series({'Option Price':op,'Asset Price':S0,'Strike Price':X, \
741
+ 'Days to Maturity':Days,'Annual RF':r0, \
742
+ 'Annual Sigma':t,'Div to Maturity':Days1, \
743
+ 'Dividend':div1})
744
+ try:
745
+ df=df.append(s,ignore_index=True)
746
+ except:
747
+ df=df._append(s,ignore_index=True)
748
+ #通用修改点
749
+ df2=df.set_index(['Annual Sigma'])
750
+ if not graph: return df2
751
+
752
+ #绘图
753
+ #通用修改点
754
+ colname='Option Price'; collabel='看跌期权'
755
+ ylabeltxt='期权价格'
756
+ titletxt='期权价格的变化趋势图'
757
+ #通用修改点
758
+ fn1='波动率-->'
759
+ fn2='\n[期权信息]行权价='+str(X)+', 标的物市价='+str(S0)
760
+ fn3='\n年化无风险利率%='+str(round(r0*100.,2))+', 距离到期日天数='+str(Days)
761
+ if div1==0:
762
+ fn4='\n本产品无红利收益'
763
+ else:
764
+ fn4='\n发放红利时间距离到期天数='+str(Days1)+', 红利='+str(div1)
765
+ footnote=fn1+fn2+fn3+fn4
766
+ plot_line(df2,colname,collabel,ylabeltxt,titletxt,footnote)
767
+
768
+ return df2
769
+
770
+ if __name__=='__main__':
771
+ S0=42
772
+ X=40
773
+ Days=183
774
+ r0=0.015
775
+ sigmarange=[0.1,0.4]
776
+ Days1=90
777
+ div1=1.5
778
+ pdf=bsm_put_sigma(42,40,183,0.015,[0.1,0.4],90,1.5)
779
+
780
+
781
+ #==============================================================================
782
+ def bsm_call_sigma(S0,X,Days,r0,sigmarange,Days1=0,div1=0,graph=True):
783
+ """
784
+ 功能:计算有红利支付的欧式期权BSM定价模型,看涨期权,年化波动率为变化范围
785
+ 注意:
786
+ S0:标的物资产的当前价格
787
+ X:期权的行权价
788
+ sigmarange:标的物资产价格收益率的年化标准差范围,默认为区间的20分之一作为间隔
789
+ r0:年化无风险利率(需要转化为连续计算的无风险利率)
790
+ Days:距离到期日的天数
791
+ Days1:红利发放时距离到期日的天数,需要转换为年数
792
+ div1:红利金额
793
+ """
794
+ #通用修改点
795
+ trange=sigmarange
796
+ #检查是否为列表
797
+ if not isinstance(trange,list):
798
+ print("#Error(bsm_call_sigma): target is not a range,",trange)
799
+ return
800
+ if len(trange) < 2:
801
+ print("#Error(bsm_call_sigma): not enough range for target,",trange)
802
+ return
803
+
804
+ #确定起始位置和间隔大小
805
+ tstart=trange[0]; tend=trange[1]
806
+ if len(trange) >=3: tstep=trange[2]
807
+ else: tstep=(tend-tstart)/20.
808
+ #横轴点列表
809
+ import numpy as np
810
+ tlist=np.arange(tstart,tend+tstep,tstep)
811
+
812
+ #循环计算各点数值
813
+ import pandas as pd
814
+ df=pd.DataFrame(columns=['Option Price','Asset Price','Strike Price', \
815
+ 'Days to Maturity','Annual RF', \
816
+ 'Annual Sigma','Div to Maturity','Dividend'])
817
+ for t in tlist:
818
+ #通用修改点
819
+ op=bsm_call(S0,X,Days,r0,t,Days1,div1,printout=False)
820
+ s=pd.Series({'Option Price':op,'Asset Price':S0,'Strike Price':X, \
821
+ 'Days to Maturity':Days,'Annual RF':r0, \
822
+ 'Annual Sigma':t,'Div to Maturity':Days1, \
823
+ 'Dividend':div1})
824
+ try:
825
+ df=df.append(s,ignore_index=True)
826
+ except:
827
+ df=df._append(s,ignore_index=True)
828
+ #通用修改点
829
+ df2=df.set_index(['Annual Sigma'])
830
+ if not graph: return df2
831
+
832
+ #绘图
833
+ #通用修改点
834
+ colname='Option Price'; collabel='看涨期权'
835
+ ylabeltxt='期权价格'
836
+ titletxt='期权价格的变化趋势图'
837
+ #通用修改点
838
+ fn1='波动率-->'
839
+ fn2='\n[期权信息]行权价='+str(X)+', 标的物市价='+str(S0)
840
+ fn3='\n年化无风险利率%='+str(round(r0*100.,2))+', 距离到期日天数='+str(Days)
841
+ if div1==0:
842
+ fn4='\n本产品无红利收益'
843
+ else:
844
+ fn4='\n发放红利时间距离到期天数='+str(Days1)+', 红利='+str(div1)
845
+ footnote=fn1+fn2+fn3+fn4
846
+ plot_line(df2,colname,collabel,ylabeltxt,titletxt,footnote)
847
+
848
+ return df2
849
+
850
+ if __name__=='__main__':
851
+ S0=42
852
+ X=40
853
+ Days=183
854
+ r0=0.015
855
+ sigmarange=[0.1,0.4]
856
+ Days1=90
857
+ div1=1.5
858
+ cdf=bsm_call_sigma(42,40,183,0.015,[0.1,0.4],90,1.5)
859
+
860
+ #==============================================================================
861
+ def bsm_sigma(S0,X,Days,r0,sigmarange,Days1=0,div1=0,graph=True):
862
+ """
863
+ 功能:计算有红利支付的欧式期权BSM定价模型,看涨/看跌期权,波动率为变化范围
864
+ 注意:
865
+ S0:标的物资产的当前价格
866
+ X:期权的行权价
867
+ sigmarange:标的物资产价格收益率的年化标准差范围
868
+ r0:年化无风险利率(需要转化为连续计算的无风险利率)
869
+ Days:距离到期日的天数
870
+ Days1:红利发放时距离到期日的天数,需要转换为年数
871
+ div1:红利金额
872
+ """
873
+ #通用修改点
874
+ trange=sigmarange
875
+ #检查是否为列表
876
+ if not isinstance(trange,list):
877
+ print("#Error(bsm_sigma): target is not a range,",trange)
878
+ return
879
+ if len(trange) < 2:
880
+ print("#Error(bsm_sigma): not enough range for target,",trange)
881
+ return
882
+
883
+ #看涨期权
884
+ df1=bsm_call_sigma(S0,X,Days,r0,sigmarange,Days1=0,div1=0,graph=False)
885
+ df1.sort_index(ascending=True, inplace=True)
886
+ #看跌期权
887
+ df2=bsm_put_sigma(S0,X,Days,r0,sigmarange,Days1=0,div1=0,graph=False)
888
+ df2.sort_index(ascending=True, inplace=True)
889
+
890
+ #绘制双线图
891
+ titletxt='期权价格的变化趋势图'
892
+ colname1='Option Price'; label1='看涨期权'
893
+ colname2='Option Price'; label2='看跌期权'
894
+ ylabeltxt='期权价格'
895
+
896
+ fn1='波动率-->'
897
+ fn2='\n[期权信息]行权价='+str(X)+', 标的物市价='+str(S0)
898
+ fn3='\n年化无风险利率%='+str(round(r0*100.,2))+', 距离到期日天数='+str(Days)
899
+ if div1==0: fn4='\n本产品无红利收益'
900
+ else: fn4='\n发放红利时间距离到期天数='+str(Days1)+', 红利='+str(div1)
901
+ footnote=fn1+fn2+fn3+fn4
902
+
903
+ plot_2lines(df1,colname1,label1,df2,colname2,label2, \
904
+ ylabeltxt,titletxt,footnote)
905
+
906
+ return
907
+
908
+ if __name__=='__main__':
909
+ S0=42
910
+ X=40
911
+ Days=183
912
+ r0=0.015
913
+ sigmarange=[0.1,0.4]
914
+ Days1=90
915
+ div1=1.5
916
+ bsm_sigma(42,40,183,0.015,[0.1,0.4],90,1.5)
917
+
918
+ #==============================================================================
919
+ def iv_call_bsm(aop,S0,X,Days,r0,Days1=0,div1=0,precision=0.01,printout=True):
920
+ """
921
+ 功能:基于BSM模型,二分迭代法,计算隐含波动率,看涨期权
922
+ aop:实际期权价格
923
+ S0:标的物当前市价
924
+ X:标的物行权价
925
+ Days:距离到期日的天数
926
+ r0:年华无风险利率
927
+ Days1:预期红利收益发放日期距离到期日的天数,默认=0
928
+ div1:预期红利收益金额,默认=0
929
+ printout:是否显示计算结果,默认=True
930
+ """
931
+ k=1
932
+ volLow=0.001 #设置波动率的最低值
933
+ volHigh=1.0 #设置波动率的最高值
934
+
935
+ #波动率最低值对应的期权价格
936
+ #cLow=bsCall(S,X,T,r,volLow)
937
+ cLow=bsm_call(S0,X,Days,r0,volLow,Days1,div1,printout=False)
938
+
939
+ #波动率最高值对应的期权价格
940
+ #cHigh=bsCall(S,X,T,r,volHigh)
941
+ cHigh=bsm_call(S0,X,Days,r0,volHigh,Days1,div1,printout=False)
942
+
943
+ #防止出现死循环
944
+ if cLow > aop or cHigh < aop:
945
+ print("#Error(iv_call_bsm): Option price not reasonable,",aop)
946
+ return None
947
+ #raise ValueError
948
+
949
+ while k ==1:
950
+ #cLow=bsCall(S,X,T,r,volLow)
951
+ cLow=bsm_call(S0,X,Days,r0,volLow,Days1,div1,printout=False)
952
+ #cHigh=bsCall(S,X,T,r,volHigh)
953
+ cHigh=bsm_call(S0,X,Days,r0,volHigh,Days1,div1,printout=False)
954
+
955
+ #取波动率的高低均值
956
+ volMid=(volLow+volHigh)/2.0
957
+ #cMid=bsCall(S,X,T,r,volMid)
958
+ cMid=bsm_call(S0,X,Days,r0,volMid,Days1,div1,printout=False)
959
+
960
+ #满足期权价格误差精度要求(0.01以下)则结束循环
961
+ if abs(cHigh-cLow) < precision: k=2
962
+ #否则,缩小范围,继续循环
963
+ elif cMid>aop: volHigh=volMid
964
+ else: volLow=volMid
965
+
966
+ iv=round(volMid,4)
967
+ if not printout: return iv
968
+
969
+ #显示
970
+ print("\n=== 隐含波动率: 二叉树迭代 ===")
971
+ print("看涨期权:")
972
+ print(" 期权现价 :",aop)
973
+ print(" 标的资产现价 :",S0)
974
+ print(" 标的资产行权价 :",X)
975
+ print(" 距离到期日的天数:",Days)
976
+ if not (div1 == 0):
977
+ print(" 预期红利 :",div1)
978
+ print(" 红利发放距离到期日的天数:",Days1)
979
+ print("隐含波动率:")
980
+ print(" 预计的年化波动率 :",iv)
981
+ print(" 对应的期权价格范围:",round(cLow,3),'-',round(cHigh,3))
982
+ print(" 迭代精度 :",precision)
983
+ return iv
984
+
985
+ #==============================================================================
986
+ def iv_put_bsm(aop,S0,X,Days,r0,Days1=0,div1=0,precision=0.01,printout=True):
987
+ """
988
+ 功能:基于BSM模型,二分迭代法,计算隐含波动率,看跌期权
989
+ aop:实际期权价格
990
+ S0:标的物当前市价
991
+ X:标的物行权价
992
+ Days:距离到期日的天数
993
+ r0:年华无风险利率
994
+ Days1:预期红利收益发放日期距离到期日的天数,默认=0
995
+ div1:预期红利收益金额,默认=0
996
+ printout:是否显示计算结果,默认=True
997
+ """
998
+ k=1
999
+ volLow=0.001 #设置波动率的最低值
1000
+ volHigh=1.0 #设置波动率的最高值
1001
+
1002
+ #波动率最低值对应的期权价格
1003
+ #cLow=bsCall(S,X,T,r,volLow)
1004
+ cLow=bsm_put(S0,X,Days,r0,volLow,Days1,div1,printout=False)
1005
+
1006
+ #波动率最高值对应的期权价格
1007
+ #cHigh=bsCall(S,X,T,r,volHigh)
1008
+ cHigh=bsm_put(S0,X,Days,r0,volHigh,Days1,div1,printout=False)
1009
+
1010
+ #防止出现死循环
1011
+ if cLow > aop or cHigh < aop:
1012
+ print("#Error(iv_put_bsm): Option price not reasonable,",aop)
1013
+ return None
1014
+ #raise ValueError
1015
+
1016
+ while k ==1:
1017
+ #cLow=bsCall(S,X,T,r,volLow)
1018
+ cLow=bsm_put(S0,X,Days,r0,volLow,Days1,div1,printout=False)
1019
+ #cHigh=bsCall(S,X,T,r,volHigh)
1020
+ cHigh=bsm_put(S0,X,Days,r0,volHigh,Days1,div1,printout=False)
1021
+
1022
+ #取波动率的高低均值
1023
+ volMid=(volLow+volHigh)/2.0
1024
+ #cMid=bsCall(S,X,T,r,volMid)
1025
+ cMid=bsm_put(S0,X,Days,r0,volMid,Days1,div1,printout=False)
1026
+
1027
+ #满足期权价格误差精度要求(precision)则结束循环
1028
+ if abs(cHigh-cLow) < precision: k=2
1029
+ #否则,缩小范围,继续循环
1030
+ elif cMid>aop: volHigh=volMid
1031
+ else: volLow=volMid
1032
+
1033
+ iv=round(volMid,4)
1034
+ if not printout: return iv
1035
+
1036
+ #显示
1037
+ print("\n=== 隐含波动率: 二叉树迭代 ===")
1038
+ print("看跌期权:")
1039
+ print(" 期权现价 :",aop)
1040
+ print(" 标的资产现价 :",S0)
1041
+ print(" 标的资产行权价 :",X)
1042
+ print(" 距离到期日的天数:",Days)
1043
+ if not (div1 == 0):
1044
+ print(" 预期红利 :",div1)
1045
+ print(" 红利发放距离到期日的天数:",Days1)
1046
+ print("隐含波动率:")
1047
+ print(" 预计的年化波动率 :",iv)
1048
+ print(" 对应的期权价格范围:",round(cLow,3),'-',round(cHigh,3))
1049
+ print(" 迭代精度 :",precision)
1050
+
1051
+ return iv
1052
+
1053
+ #==============================================================================
1054
+ def binomial_american_call(S0,X,Days,r0,sigma,q0=0,steps=200,printout=True):
1055
+ """
1056
+ 功能:计算有红利支付的美式期权二叉树定价模型,看涨期权
1057
+ 注意:
1058
+ S0:标的物资产的当前价格
1059
+ X为其行权价
1060
+ Days:距离到期日的天数,需要转换为距离到期日的年数=距离到期日的天数/365
1061
+ r0:年化无风险利率(需要转化为连续计算的无风险利率)
1062
+ sigma:标的物资产价格收益率的年化标准差
1063
+ q0:年化红利收益率,由于美式期权可能提前行权,故不考虑发放日期
1064
+ steps:二叉树的步骤
1065
+ """
1066
+ from numpy import log,exp
1067
+
1068
+ #Days1为距离到期日的日历日天数
1069
+ t=Days/365.
1070
+ r=log(r0+1)
1071
+ q=log(q0+1)
1072
+ #调整标的物当前价
1073
+ S=S0
1074
+
1075
+ import numpy as np
1076
+ u=np.exp(sigma*np.sqrt(t/steps)); d=1/u
1077
+
1078
+ P=(np.exp((r-q)*t/steps)-d)/(u-d)
1079
+ prices=np.zeros(steps+1)
1080
+ c_values=np.zeros(steps+1)
1081
+ prices[0]=S*d**steps
1082
+ c_values[0]=np.maximum(prices[0]-X,0)
1083
+
1084
+ for i in range(1,steps+1):
1085
+ prices[i]=prices[i-1]*(u**2)
1086
+ c_values[i]=np.maximum(prices[i]-X,0)
1087
+
1088
+ for j in range(steps,0,-1):
1089
+ for i in range(0,j):
1090
+ prices[i]=prices[i+1]*d
1091
+ #c_values[i]=np.maximum((P*c_values[i+1]+(1-P)*c_values[i])/np.exp(r*t/steps),prices[i]-X)
1092
+ c_values[i]=np.maximum((P*c_values[i+1]+(1-P)*c_values[i])/np.exp((r-q)*t/steps),prices[i]-X)
1093
+ C=round(c_values[0],2)
1094
+
1095
+ if not printout: return C
1096
+ print("\n===== 二叉树期权定价 =====")
1097
+ print("适用情形: 美式期权,标的资产有红利")
1098
+ print("标的资产行权价 :",X)
1099
+ print("标的资产现价 :",S0)
1100
+ print("标的资产年化波动率 :",round(sigma,4))
1101
+ print("距离到期日的年数 :",round(t,2))
1102
+ print("连续计算的无风险收益率:",round(r,4)*100,'\b%')
1103
+ print("连续计算的红利率 :",round(q,4)*100,'\b%')
1104
+ print("二叉树迭代步数 :",steps)
1105
+ print("看涨期权的预期价格 :",round(C,4))
1106
+
1107
+ return C
1108
+
1109
+ #==============================================================================
1110
+ def binomial_american_put(S0,X,Days,r0,sigma,q0=0,steps=200,printout=True):
1111
+ """
1112
+ 功能:计算有红利支付的美式期权二叉树定价模型,看跌期权
1113
+ 注意:
1114
+ S0:标的物资产的当前价格
1115
+ X为其行权价
1116
+ Days:距离到期日的天数,需要转换为距离到期日的年数=距离到期日的天数/365
1117
+ r0:年化无风险利率(需要转化为连续计算的无风险利率)
1118
+ sigma:标的物资产价格收益率的年化标准差
1119
+ q0:年化红利收益率,由于美式期权可能提前行权,故不考虑发放日期
1120
+ steps:二叉树的步骤
1121
+ """
1122
+ from numpy import log,exp
1123
+
1124
+ #Days1为距离到期日的日历日天数
1125
+ t=Days/365.
1126
+ r=log(r0+1)
1127
+ q=log(q0+1)
1128
+ #调整标的物当前价
1129
+ S=S0
1130
+
1131
+ import numpy as np
1132
+ u=np.exp(sigma*np.sqrt(t/steps))
1133
+ d=1/u
1134
+ P=(np.exp((r-q)*t/steps)-d)/(u-d)
1135
+ prices=np.zeros(steps+1)
1136
+ c_values=np.zeros(steps+1)
1137
+ prices[0]=S*d**steps
1138
+ c_values[0]=np.maximum(X-prices[0],0)
1139
+
1140
+ for i in range(1,steps+1):
1141
+ prices[i]=prices[i-1]*(u**2)
1142
+ c_values[i]=np.maximum(X-prices[i],0)
1143
+
1144
+ for j in range(steps,0,-1):
1145
+ for i in range(0,j):
1146
+ prices[i]=prices[i+1]*d
1147
+ #c_values[i]=np.maximum((P*c_values[i+1]+(1-P)*c_values[i])/np.exp(r*t/steps),X-prices[i])#检查是否提前行权
1148
+ c_values[i]=np.maximum((P*c_values[i+1]+(1-P)*c_values[i])/np.exp((r-q)*t/steps),X-prices[i])#检查是否提前行权
1149
+ C=round(c_values[0],2)
1150
+
1151
+ if not printout: return C
1152
+ print("\n===== 二叉树期权定价 =====")
1153
+ print("适用情形: 美式期权,标的资产有红利")
1154
+ print("标的资产行权价 :",X)
1155
+ print("标的资产现价 :",S0)
1156
+ print("标的资产年化波动率 :",round(sigma,4))
1157
+ print("距离到期日的年数 :",round(t,2))
1158
+ print("连续计算的无风险收益率:",round(r,4)*100,'\b%')
1159
+ print("连续计算的红利率 :",round(q,4)*100,'\b%')
1160
+ print("二叉树迭代步数 :",steps)
1161
+ print("看跌期权的预期价格 :",round(C,4))
1162
+
1163
+ return C
1164
+
1165
+ #==============================================================================
1166
+ #==============================================================================
1167
+ #==============================================================================
1168
+ #==============================================================================
1169
+ if __name__=='__main__':
1170
+ ticker="AAPL"
1171
+ ticker="SPY"
1172
+
1173
+ def option_maturity(ticker,printout=True):
1174
+ """
1175
+ 功能:获得期权的各个到期日期
1176
+ 注意:目前yfinance无法使用,股票期权链功能暂时不可用,可尝试yahooquery?
1177
+ """
1178
+ """
1179
+ if not test_yahoo_access():
1180
+ print(" #Warning(option_maturity): failed to access data source Yahoo Finance")
1181
+ return None
1182
+ """
1183
+ import yfinance as yf
1184
+ # yf.__version__
1185
+
1186
+ opt = yf.Ticker(ticker)
1187
+
1188
+ #获得期权的各个到期日
1189
+ try:
1190
+ exp_dates=opt.options
1191
+ except:
1192
+ print(" #Error(option_maturity): failed to get option maturity dates for underlying",ticker)
1193
+ print(" Reasons: either",ticker,"does not exist or Yahoo Finance is currently inaccessible")
1194
+ return None
1195
+
1196
+ datelist=list(exp_dates)
1197
+ if not printout:
1198
+ return datelist
1199
+
1200
+ tname=get_stock_name1_en(ticker)
1201
+
1202
+ #显示结果
1203
+ print("\n===== 期权的时间序列 =====")
1204
+ print("标的资产:",tname)
1205
+ print("到期日期:")
1206
+
1207
+ num=len(datelist)
1208
+ for d in datelist:
1209
+ print(d,end=' ')
1210
+ pos=datelist.index(d)+1
1211
+ if (pos % 4 ==0) or (pos==num): print(' ')
1212
+
1213
+ print("总计:",num,"个日期")
1214
+ import datetime
1215
+ today = datetime.date.today()
1216
+ print("\n*** 数据来源: 雅虎财经,",today)
1217
+
1218
+ return datelist
1219
+
1220
+ if __name__=='__main__':
1221
+ ticker='AAPL'
1222
+ datelist=option_maturity(ticker)
1223
+ datelist=option_maturity('AAPL')
1224
+ datelist=option_maturity('000001.SS')
1225
+
1226
+ #================================================================
1227
+ if __name__=='__main__':
1228
+ ticker="AAPL"
1229
+ maturity_date="2025-2-21"
1230
+
1231
+ def option_chain(ticker,maturity_date='today',printout=True):
1232
+ """
1233
+ 功能:获得期权的各个到期日期,并列出某个到期日的期权合约
1234
+ """
1235
+ mdate=maturity_date
1236
+
1237
+ if mdate=='today':
1238
+ import datetime as dt; stoday=dt.date.today()
1239
+ mdate=str(stoday)
1240
+
1241
+ import yfinance as yf
1242
+ opt = yf.Ticker(ticker)
1243
+
1244
+ #处理称为规范日期
1245
+ from datetime import datetime
1246
+ mdate2 = datetime.strptime(mdate, '%Y-%m-%d')
1247
+ mdate3 = datetime.strftime(mdate2,'%Y-%m-%d')
1248
+
1249
+ #获得一个到期日的所有期权合约
1250
+ try:
1251
+ optlist = opt.option_chain(mdate3)
1252
+ except:
1253
+ if printout:
1254
+ print(" #Error(option_chain): failed to get option chain for",ticker,'\b@',mdate)
1255
+ return None,None
1256
+
1257
+ opt_call=optlist.calls
1258
+ opt_call['underlyingAsset']=ticker
1259
+ opt_call['optionType']='Call'
1260
+
1261
+ inttodate=lambda x: int2date(x)
1262
+ opt_call['date']=opt_call['lastTradeDate'].apply(inttodate)
1263
+ opt_call['maturity']=mdate3
1264
+
1265
+ collist=['contractSymbol','underlyingAsset','optionType','date', \
1266
+ 'maturity','strike','lastPrice','impliedVolatility','volume', \
1267
+ 'inTheMoney','currency']
1268
+ opt_call2=opt_call[collist].copy()
1269
+ num_call=len(opt_call2)
1270
+ num_call_ITM=len(opt_call2[opt_call2['inTheMoney']==True])
1271
+ num_call_OTM=num_call-num_call_ITM
1272
+
1273
+ strike_min=min(opt_call2['strike'])
1274
+ strike_max=max(opt_call2['strike'])
1275
+ currency=opt_call2['currency'][0]
1276
+
1277
+ opt_put=optlist.puts
1278
+ opt_put['underlyingAsset']=ticker
1279
+ opt_put['optionType']='Put'
1280
+ opt_put['date']=opt_put['lastTradeDate'].apply(inttodate)
1281
+ opt_put['maturity']=mdate3
1282
+ opt_put2=opt_put[collist].copy()
1283
+ num_put=len(opt_put2)
1284
+ num_put_ITM=len(opt_put2[opt_put2['inTheMoney']==True])
1285
+ num_put_OTM=num_put-num_put_ITM
1286
+
1287
+ if not printout:
1288
+ return opt_call2, opt_put2
1289
+
1290
+ tname=get_stock_name1_en(ticker)
1291
+
1292
+ print("\n===== 期权链的结构 =====")
1293
+ print("标的资产:",tname)
1294
+ print("到期日期:",mdate)
1295
+ print("看涨期权:",num_call)
1296
+ print(" 实值/虚值:",num_call_ITM,'/',num_call_OTM)
1297
+ print("看跌期权:",num_put)
1298
+ print(" 实值/虚值:",num_put_ITM,'/',num_put_OTM)
1299
+ print("最低/最高行权价:",strike_min,'/',strike_max,currency)
1300
+
1301
+ import datetime
1302
+ stoday = datetime.date.today()
1303
+ print("\n*数据来源: 雅虎财经,",stoday)
1304
+
1305
+ #设置绘图数据
1306
+ df1=opt_call2.copy()
1307
+ df1.sort_values(by=['strike'],axis=0,ascending=[True],inplace=True)
1308
+ df1.set_index(['strike'],inplace=True)
1309
+ df1['exercise']=df1.index
1310
+ colname1='lastPrice'; label1='看涨期权价格'
1311
+
1312
+ df2=opt_put2.copy()
1313
+ df2.sort_values(by=['strike'],axis=0,ascending=[True],inplace=True)
1314
+ df2.set_index(['strike'],inplace=True)
1315
+ df2['exercise']=df2.index
1316
+ colname2='lastPrice'; label2='看跌期权价格'
1317
+
1318
+ ylabeltxt='期权价格('+currency+')'
1319
+ titletxt="期权价格与标的行权价格的关系"
1320
+ footnote="标的行权价("+currency+") -->\n"+ \
1321
+ "标的资产: "+tname+ \
1322
+ ", "+"到期日: "+mdate+ \
1323
+ "\n数据来源: 雅虎财经, "+str(stoday)
1324
+
1325
+ #绘图
1326
+ import matplotlib.pyplot as plt
1327
+ plt.plot(df1.index,df1[colname1],color='red',linestyle='-',linewidth=1.5, \
1328
+ label=label1)
1329
+
1330
+ plt.plot(df2.index,df2[colname2],color='blue',linestyle='-',linewidth=1.5, \
1331
+ label=label2)
1332
+
1333
+ plt.ylabel(ylabeltxt,fontsize=ylabel_txt_size)
1334
+ plt.xlabel(footnote,fontsize=xlabel_txt_size)
1335
+ plt.title(titletxt,fontsize=title_txt_size)
1336
+ plt.legend(fontsize=legend_txt_size)
1337
+ plt.show()
1338
+
1339
+
1340
+ return opt_call2, opt_put2
1341
+
1342
+ if __name__=='__main__':
1343
+ ticker='AAPL'
1344
+ mdate='2022-6-17'
1345
+ dfc,dfp=option_chain(ticker,mdate)
1346
+
1347
+ #==============================================================================
1348
+ if __name__ =="__main__":
1349
+ ticker='AAPL'
1350
+ lastndays=7
1351
+
1352
+ #def predict_stock_trend_by_option(ticker,lastndays=7,power=4):
1353
+ def market_prospect_via_option(ticker,lastdays=7):
1354
+ """
1355
+ 功能:根据期权行权价及交易量预测标的物价格
1356
+ 注意:本函数与price_prospect_via_option内容基本一致,图示方式略有不同
1357
+ """
1358
+ lastndays=lastdays
1359
+
1360
+ DEBUG=False
1361
+ try:
1362
+ datelist=option_maturity(ticker,printout=False)
1363
+ except:
1364
+ print(" #Error(predict_stock_price_by_option): option info not found for",ticker)
1365
+ if datelist is None:
1366
+ print(" #Warning(predict_stock_price_by_option): options not found for",ticker)
1367
+ return None
1368
+ print("\nFound options with",len(datelist),"maturity dates for",ticker)
1369
+
1370
+ import pandas as pd
1371
+ df=pd.DataFrame(columns=['Ticker','Date','WA Strike','Total Options', \
1372
+ 'Calls in Total%','OTM in Calls%','OTM Calls in Total%', \
1373
+ 'Puts in Total%','OTM in Puts%','OTM Puts in Total%'])
1374
+ for d in datelist:
1375
+ print_progress_percent2(d,datelist,steps=5,leading_blanks=4)
1376
+
1377
+ if DEBUG: print("Processing options matured on",d)
1378
+ opt_call,opt_put=option_chain(ticker,d,printout=False)
1379
+
1380
+ numofcalls=len(opt_call)
1381
+ opt_call_otm=opt_call[opt_call['inTheMoney']==False]
1382
+ numofotmcalls=len(opt_call_otm)
1383
+
1384
+ numofputs=len(opt_put)
1385
+ opt_put_otm=opt_put[opt_put['inTheMoney']==False]
1386
+ numofotmputs=len(opt_put_otm)
1387
+
1388
+ totalopts=numofcalls+numofputs
1389
+
1390
+ callsintotal=round(numofcalls/totalopts*100,2)
1391
+ if numofcalls != 0:
1392
+ otmincalls=round(numofotmcalls/numofcalls*100,2)
1393
+ else:
1394
+ otmincalls=0
1395
+ otmcallsintotal=round(numofotmcalls/totalopts*100,2)
1396
+
1397
+ putsintotal=round(numofputs/totalopts*100,2)
1398
+ if numofputs != 0:
1399
+ otminputs=round(numofotmputs/numofputs*100,2)
1400
+ else:
1401
+ otminputs=0
1402
+ otmputsintotal=round(numofotmputs/totalopts*100,2)
1403
+
1404
+ opts=pd.concat([opt_call,opt_put])
1405
+ opts.sort_values('date',ascending=False,inplace=True)
1406
+ lasttradedate=list(opts['date'])[0]
1407
+ lastndate=date_adjust(lasttradedate, adjust=-lastndays)
1408
+
1409
+ #取最近几天的期权交易
1410
+ opts2=opts[opts['date']>=lastndate]
1411
+ opts2.dropna(inplace=True)
1412
+ wa_strike=round(((opts2['strike']*opts2['volume']).sum())/(opts2['volume'].sum()),2)
1413
+
1414
+ s=pd.Series({'Ticker':ticker,'Date':d,'WA Strike':wa_strike, \
1415
+ 'Total Options':totalopts, \
1416
+ 'Calls in Total%':callsintotal,'OTM in Calls%':otmincalls,'OTM Calls in Total%':otmcallsintotal, \
1417
+ 'Puts in Total%':putsintotal,'OTM in Puts%':otminputs,'OTM Puts in Total%':otmputsintotal})
1418
+ try:
1419
+ df=df.append(s,ignore_index=True)
1420
+ except:
1421
+ df=df._append(s,ignore_index=True)
1422
+
1423
+ #建立日期索引
1424
+ todatetime=lambda x:pd.to_datetime(x)
1425
+ df['date']=df['Date'].apply(todatetime)
1426
+ df2=df.set_index(['date'])
1427
+
1428
+ #绘图1:Calls vs Puts比例
1429
+ import datetime
1430
+ today = datetime.date.today()
1431
+
1432
+ colname1='Calls in Total%'
1433
+ label1='Calls in Total%'
1434
+ colname2='Puts in Total%'
1435
+ label2='Puts in Total%'
1436
+ ylabeltxt='Percentage'
1437
+ titletxt="Option Comparison: "+ticker+", Calls vs Puts"
1438
+
1439
+ footnote="Source: Yahoo Finance, "+str(today)
1440
+ plot_line2(df2,ticker,colname1,label1, \
1441
+ df2,ticker,colname2,label2, \
1442
+ ylabeltxt,titletxt,footnote)
1443
+
1444
+ #绘图2:OTM Calls vs OTM Puts相对比例
1445
+ colname1='OTM in Calls%'
1446
+ label1='OTM in Calls%'
1447
+ colname2='OTM in Puts%'
1448
+ label2='OTM in Puts%'
1449
+ ylabeltxt='Percentage'
1450
+ titletxt="Option Relative Proportion Comparison\n("+ticker+", OTM Calls vs OTM Puts)"
1451
+
1452
+ footnote="Source: Yahoo Finance, "+str(today)
1453
+ plot_line2(df2,ticker,colname1,label1, \
1454
+ df2,ticker,colname2,label2, \
1455
+ ylabeltxt,titletxt,footnote)
1456
+
1457
+ #绘图3:OTM Calls vs OTM Puts绝对比例
1458
+ colname1='OTM Calls in Total%'
1459
+ label1='OTM Calls in Total%'
1460
+ colname2='OTM Puts in Total%'
1461
+ label2='OTM Puts in Total%'
1462
+ ylabeltxt='Percentage'
1463
+ titletxt="Option Absolute Proportion Comparison\n("+ticker+", OTM Calls vs OTM Puts)"
1464
+
1465
+ footnote="Source: Yahoo Finance, "+str(today)
1466
+ plot_line2(df2,ticker,colname1,label1, \
1467
+ df2,ticker,colname2,label2, \
1468
+ ylabeltxt,titletxt,footnote)
1469
+
1470
+ #绘图4:标的物价格预测
1471
+ df2x=df2.drop(df2[df2['Total Options']<=1].index)
1472
+ """
1473
+ colname='WA Strike'
1474
+ collabel='Predicted Price'
1475
+ ylabeltxt=''
1476
+ titletxt="Predicting Prices via Options: "+ticker
1477
+ footnote="Source: Yahoo Finance, "+str(today)
1478
+ plot_line(df2x,colname,collabel,ylabeltxt,titletxt,footnote,power=power)
1479
+ """
1480
+
1481
+ #打印预测结果
1482
+ compotm=lambda x:compare_otm(x)
1483
+ df2x['Trend']=df2x.apply(compotm,axis=1) #axis=1表示按行操作
1484
+ """
1485
+ collist=['Date','Trend','WA Strike','Total Options','Calls in Total%','OTM in Calls%', \
1486
+ 'Puts in Total%','OTM in Puts%']
1487
+ """
1488
+ collist=['Date','Trend','Total Options','Calls in Total%','Puts in Total%', \
1489
+ 'OTM in Calls%','OTM in Puts%','OTM Calls in Total%','OTM Puts in Total%']
1490
+ df3=df2x[collist]
1491
+ df3.rename(columns={'Total Options':'TotalOptions'}, inplace = True)
1492
+ df3.rename(columns={'Calls in Total%':'Calls%','Puts in Total%':'Puts%'}, inplace = True)
1493
+ df3.rename(columns={'OTM in Calls%':'OTMinCalls%','OTM in Puts%':'OTMinPuts%'}, inplace = True)
1494
+ df3.rename(columns={'OTM Calls in Total%':'OTM Calls/Total%','OTM Puts in Total%':'OTM Puts/Total%'}, inplace = True)
1495
+
1496
+ """
1497
+ print("\n ======= Predicting Price Trend via Option Configuration: "+ticker+" =======")
1498
+ #设置打印对齐
1499
+ pd.set_option('display.max_columns', 1000)
1500
+ pd.set_option('display.width', 1000)
1501
+ pd.set_option('display.max_colwidth', 1000)
1502
+ pd.set_option('display.unicode.ambiguous_as_wide', True)
1503
+ pd.set_option('display.unicode.east_asian_width', True)
1504
+ print(df3.to_string(index=False))
1505
+ """
1506
+ #lastdate,lastprice=get_last_close1(ticker)
1507
+ prices_tmp=security_trend(ticker,graph=False)
1508
+ lastdate=str(prices_tmp.tail(1).index.values[0].date())
1509
+ lastprice=str(prices_tmp.tail(1).Close.values[0])
1510
+ """
1511
+ print(" Note:")
1512
+ print(" 1) Recent price:",lastprice,"\b,",lastdate,'\b.')
1513
+ print(" 2) +(-) predicts higher(lower) price than recent, ++(--) for more likely, +/- for undetermined trend.")
1514
+ print(" 3) Option trade period: recent "+str(lastndays)+" days. No stock splits in the period. Dates with only 1 option removed.")
1515
+ #print(" 4) Removed those samples with only one option, if any.")
1516
+ print(" "+footnote+'.')
1517
+ """
1518
+ tname=get_stock_name1_en(ticker,short_name=True)
1519
+ titletxt="Predicting Price Trend via Option Configuration: "+tname
1520
+ footnote1="Note:\n"
1521
+ footnote2="1. Recent price: "+lastprice+", "+lastdate+'\n'
1522
+ footnote3="2. +(-) predicts higher(lower) price than recent, ++(--) more likely, +/- undetermined\n"
1523
+ footnote4="3. Period: recent "+str(lastndays)+" days. No stock splits in the period. Removed dates with 1 option only\n"
1524
+ footnote9=footnote1+footnote2+footnote3+footnote4+footnote
1525
+
1526
+ df_display_CSS(df3,titletxt=titletxt,footnote=footnote9,facecolor='papayawhip',decimals=2, \
1527
+ first_col_align='left',second_col_align='right', \
1528
+ last_col_align='right',other_col_align='right', \
1529
+ titile_font_size='15px',heading_font_size='13px', \
1530
+ data_font_size='13px')
1531
+
1532
+ return df2
1533
+
1534
+
1535
+
1536
+
1537
+ #================================================================
1538
+ if __name__=='__main__':
1539
+ intdate=1604350755
1540
+
1541
+ def int2date(intdate):
1542
+ """
1543
+ 功能:将数字转换为日期,10位数字为秒级,13位的为毫秒级
1544
+ 输入:使用10位或13位整数表示的日期时间
1545
+ 返回:yyyy-mm-dd hh:mm:ss
1546
+ """
1547
+ import time
1548
+ intstr=str(intdate)
1549
+
1550
+ if len(intstr) == 10:
1551
+ tupTime = time.localtime(intdate) #秒时间戳
1552
+ #standardTime = time.strftime("%Y-%m-%d %H:%M:%S", tupTime)
1553
+ standardTime = time.strftime("%Y-%m-%d", tupTime)
1554
+ return standardTime
1555
+
1556
+ if len(intstr)==13:
1557
+ timeNum=intdate #毫秒时间戳
1558
+ timeTemp = float(timeNum/1000)
1559
+ tupTime = time.localtime(timeTemp)
1560
+ #standardTime = time.strftime("%Y-%m-%d %H:%M:%S", tupTime)
1561
+ standardTime = time.strftime("%Y-%m-%d", tupTime)
1562
+ return standardTime
1563
+
1564
+ #直接为日期时间结构
1565
+ standardTime = intdate.strftime("%Y-%m-%d")
1566
+ return standardTime
1567
+
1568
+ if __name__=='__main__':
1569
+ intdate1=1604349847
1570
+ int2date(intdate1)
1571
+
1572
+ intdate2=1566366547705
1573
+ int2date(intdate2)
1574
+
1575
+ import pandas as pd
1576
+ intdate3=pd.to_datetime('2020-11-03')
1577
+ int2date(intdate3)
1578
+ #==============================================================================
1579
+ #==============================================================================
1580
+ def compare_otm(row,spread=1.0):
1581
+ """
1582
+ 功能:比较OTM Call vs OTM Put的绝对比例大小,赋值+/-
1583
+ 输入:df的一行
1584
+ 输出:+/-
1585
+ """
1586
+ if row['OTM Calls in Total%'] > row['OTM Puts in Total%']:
1587
+ result='+'
1588
+ if (row['Calls in Total%'] > row['Puts in Total%']) and ((row['OTM in Calls%'] > row['OTM in Puts%'])):
1589
+ result='++'
1590
+
1591
+ if row['OTM Calls in Total%'] < row['OTM Puts in Total%']:
1592
+ result='-'
1593
+ if (row['Calls in Total%'] < row['Puts in Total%']) and ((row['OTM in Calls%'] < row['OTM in Puts%'])):
1594
+ result='--'
1595
+
1596
+ if abs(row['OTM Calls in Total%'] - row['OTM Puts in Total%']) < spread:
1597
+ result='+/-'
1598
+
1599
+ return result
1600
+
1601
+ #==============================================================================
1602
+ def call_timevalue(row):
1603
+ """
1604
+ 功能:计算看涨期权的时间价值
1605
+ 输入:df的一行
1606
+ 输出:期权的时间价值
1607
+ """
1608
+ #是否实值期权
1609
+ if row['inTheMoney']:
1610
+ tv=row['lastPrice']-row['lastSPrice']+row['strike']
1611
+ else:
1612
+ tv=row['lastPrice']
1613
+ return tv
1614
+
1615
+ def put_timevalue(row):
1616
+ """
1617
+ 功能:计算看跌期权的时间价值
1618
+ 输入:df的一行
1619
+ 输出:期权的时间价值
1620
+ """
1621
+ #是否实值期权
1622
+ if row['inTheMoney']:
1623
+ tv=row['lastPrice']+row['lastSPrice']-row['strike']
1624
+ else:
1625
+ tv=row['lastPrice']
1626
+ return tv
1627
+
1628
+ #==============================================================================
1629
+
1630
+ if __name__ =="__main__":
1631
+ ticker='AAPL'
1632
+ lastndays=2
1633
+
1634
+ def price_prospect_via_option(ticker,lastdays=7,cutoff=[1.1,5.0,10.0]):
1635
+ """
1636
+ 功能:根据股票期权预测标的物价格
1637
+ 算法:
1638
+ 1、计算虚值看涨/看跌期权数量比例
1639
+ 2、计算虚值看涨/看跌期权交易金额比例
1640
+ 3、若虚值看涨期权占优,为看涨,并据此估计未来标的物价格;
1641
+ 4、若虚值看跌期权占优,为看跌,并据此估计未来标的物价格;
1642
+ 5、否则,为不明确
1643
+ 返回:期权明细
1644
+ """
1645
+ lastndays=lastdays
1646
+
1647
+ DEBUG=False
1648
+ print("Searching option chain for",ticker,'...',end='')
1649
+
1650
+ try:
1651
+ datelist=option_maturity(ticker,printout=False)
1652
+ except:
1653
+ print("\n #Warning(price_prospect_via_option): option info not found for",ticker)
1654
+ return None
1655
+ if datelist is None:
1656
+ print("\n #Warning(price_prospect_via_option): options not found for",ticker)
1657
+ return None
1658
+ print("found",len(datelist),"maturity dates of options")
1659
+
1660
+ #最新的标的物价格
1661
+ #print("Searching recent close price for",ticker,'...',end='')
1662
+ try:
1663
+ #lastsdate,lastsprice=get_last_close1(ticker)
1664
+ prices_tmp=security_trend(ticker,graph=False)
1665
+ lastsdate=str(prices_tmp.tail(1).index.values[0].date())
1666
+ lastsprice=str(prices_tmp.tail(1).Close.values[0])
1667
+
1668
+ except:
1669
+ print("\n #Error(price_prospect_via_option): failed in retrieving close price for",ticker)
1670
+ return None
1671
+ if (lastsdate is None) or (lastsprice is None):
1672
+ print("\n #Error(price_prospect_via_option): retrieving close price failed for",ticker)
1673
+ return None
1674
+ if DEBUG: print(lastsprice,'\b,',lastsdate)
1675
+
1676
+ import pandas as pd
1677
+ df=pd.DataFrame(columns=['Ticker','Date','Trend','Estimated Price', \
1678
+ 'OTM Volume Call/Put','OTM Amount Call/Put','Spot Date','Spot Price'])
1679
+ for d in datelist:
1680
+ print_progress_percent2(d,datelist,steps=5,leading_blanks=4)
1681
+
1682
+ if DEBUG: print("Analyzing options matured on",d,'...')
1683
+ opt_call,opt_put=option_chain(ticker,d,printout=False)
1684
+
1685
+ if (opt_call is None) or (opt_put is None):
1686
+ if DEBUG:
1687
+ print(" #Warning(price_prospect_via_option): failed in retrieving options matured on",d)
1688
+ """
1689
+ break
1690
+ return None
1691
+ """
1692
+ continue
1693
+
1694
+ if (len(opt_call) == 0) or (len(opt_put) == 0):
1695
+ if DEBUG:
1696
+ print(" #Warning(price_prospect_via_option): retrieved zero options matured on",d)
1697
+ """
1698
+ break
1699
+ return None
1700
+ """
1701
+ continue
1702
+
1703
+ currency=list(opt_call['currency'])[0]
1704
+
1705
+ ##########处理看涨期权##########
1706
+ if DEBUG: print(" Call volume: ",end='')
1707
+ opt_call['lastSDate']=lastsdate
1708
+ opt_call['lastSPrice']=lastsprice
1709
+
1710
+ #去掉无交易的期权
1711
+ opt_call.dropna(inplace=True)
1712
+ #只保留过去lastndays日历日的交易
1713
+ lasttdate=max(list(opt_call['date']))
1714
+ fromtdate=date_adjust(lasttdate, adjust=-lastndays)
1715
+ opt_call=opt_call[opt_call['date'] >= fromtdate]
1716
+ numofcalls=sum(opt_call['volume'])
1717
+
1718
+ """
1719
+ #计算期权的时间价值:不一致,无法进一步利用
1720
+ calltv=lambda x:call_timevalue(x)
1721
+ opt_call['timeValue']=opt_call.apply(calltv,axis=1) #axis=1表示按行操作
1722
+ """
1723
+
1724
+ #计算虚值期权的交易数量、交易金额和加权价格
1725
+ opt_call_otm=opt_call[opt_call['inTheMoney']==False]
1726
+ numofotmcalls=sum(opt_call_otm['volume'])
1727
+ amtofotmcalls=round(sum(opt_call_otm['lastPrice']*opt_call_otm['volume']),2)
1728
+ avopofotmcalls=round((amtofotmcalls/numofotmcalls),2)
1729
+ if DEBUG: print("total",int(numofcalls),'\b, OTM',int(numofotmcalls),end='')
1730
+
1731
+ #基于加权价格判断行权价
1732
+ opt_call_otm.sort_values('lastPrice',ascending=True,inplace=True)
1733
+ strikelist=list(opt_call_otm['strike'])
1734
+ lastPricelist=list(opt_call_otm['lastPrice'])+[avopofotmcalls]
1735
+ lastPricelist=sorted(lastPricelist,reverse=False)
1736
+ avoppos=lastPricelist.index(avopofotmcalls)
1737
+ if avoppos > 0:
1738
+ op1=lastPricelist[avoppos-1]
1739
+ strike1=strikelist[avoppos-1]
1740
+ op2=lastPricelist[avoppos+1]
1741
+ strike2=strikelist[avoppos]
1742
+ avspofotmcalls=round(min(strike1,strike2)+abs(strike1-strike2)*((avopofotmcalls-min(op1,op2))/abs(op1-op2)),2)
1743
+ else:
1744
+ avspofotmcalls=strikelist[avoppos]
1745
+ if DEBUG: print(", done!")
1746
+
1747
+ ##########处理看跌期权##########
1748
+ if DEBUG: print(" Put volume: ",end='')
1749
+ opt_put['lastSDate']=lastsdate
1750
+ opt_put['lastSPrice']=lastsprice
1751
+
1752
+ #去掉无交易的期权
1753
+ opt_put.dropna(inplace=True)
1754
+ #只保留过去lastndays日历日的交易
1755
+ lasttdate=max(list(opt_put['date']))
1756
+ fromtdate=date_adjust(lasttdate, adjust=-lastndays)
1757
+ opt_put=opt_put[opt_put['date'] >= fromtdate]
1758
+ numofputs=sum(opt_put['volume'])
1759
+
1760
+ """
1761
+ #计算期权的时间价值:不一致,无法进一步利用
1762
+ puttv=lambda x:put_timevalue(x)
1763
+ opt_put['timeValue']=opt_put.apply(puttv,axis=1) #axis=1表示按行操作
1764
+ """
1765
+
1766
+ #计算虚值期权的交易数量、交易金额和加权价格
1767
+ opt_put_otm=opt_put[opt_put['inTheMoney']==False]
1768
+ numofotmputs=sum(opt_put_otm['volume'])
1769
+ amtofotmputs=round(sum(opt_put_otm['lastPrice']*opt_put_otm['volume']),2)
1770
+ avopofotmputs=round((amtofotmputs/numofotmputs),2)
1771
+ if DEBUG: print("total",int(numofputs),'\b, OTM',int(numofotmputs),end='')
1772
+
1773
+ #基于加权价格判断行权价
1774
+ opt_put_otm.sort_values('lastPrice',ascending=True,inplace=True)
1775
+ strikelist=list(opt_put_otm['strike'])
1776
+ lastPricelist=list(opt_put_otm['lastPrice'])+[avopofotmputs]
1777
+ lastPricelist=sorted(lastPricelist,reverse=False)
1778
+ avoppos=lastPricelist.index(avopofotmputs)
1779
+ if avoppos > 0:
1780
+ op1=lastPricelist[avoppos-1]
1781
+ strike1=strikelist[avoppos-1]
1782
+ op2=lastPricelist[avoppos+1]
1783
+ strike2=strikelist[avoppos]
1784
+ avspofotmputs=round(min(strike1,strike2)+abs(strike1-strike2)*((avopofotmputs-min(op1,op2))/abs(op1-op2)),2)
1785
+ else:
1786
+ avspofotmputs=strikelist[avoppos]
1787
+ if DEBUG: print(", done!")
1788
+
1789
+ #比较虚值看涨/看跌期权的数量和交易金额
1790
+ if DEBUG: print(" Evaluating price trend ...",end='')
1791
+ rateqty=round(numofotmcalls/numofotmputs,2)
1792
+ rateamt=round(amtofotmcalls/amtofotmputs,2)
1793
+ trend='+/-'
1794
+ star1=cutoff[0]; star2=cutoff[1]; star3=cutoff[2]
1795
+ #加强判断:以rateamt为主,结合rateqty
1796
+ if (rateqty > 1.0) and (rateamt > star1):
1797
+ trend='+'
1798
+ if (rateqty < 1.0) and (rateamt < 1.0/star1):
1799
+ trend='-'
1800
+ if (rateqty > star2) and (rateamt > star2):
1801
+ trend='++'
1802
+ if (1/rateqty > star2) and (1/rateamt > star2):
1803
+ trend='--'
1804
+ if (rateqty > star3) and (rateamt > star3):
1805
+ trend='+++'
1806
+ if (1/rateqty > star3) and (1/rateamt > star3):
1807
+ trend='---'
1808
+
1809
+ estsprice=lastsprice
1810
+ if (trend[0] == '+') and (trend != '+/-'):
1811
+ estsprice=avspofotmcalls
1812
+ if trend[0]=='-':
1813
+ estsprice=avspofotmputs
1814
+ if trend == '+/-':
1815
+ estsprice=(avspofotmcalls + avspofotmputs)/2.0
1816
+
1817
+ s=pd.Series({'Ticker':ticker,'Date':d,'Trend':trend,'Estimated Price':estsprice, \
1818
+ 'OTM Volume Call/Put':rateqty,'OTM Amount Call/Put':rateamt,'Spot Date':lastsdate,'Spot Price':lastsprice})
1819
+ try:
1820
+ df=df.append(s,ignore_index=True)
1821
+ except:
1822
+ df=df._append(s,ignore_index=True)
1823
+ if DEBUG: print(", done!")
1824
+
1825
+ #建立日期索引
1826
+ todatetime=lambda x:pd.to_datetime(x)
1827
+ df['date']=df['Date'].apply(todatetime)
1828
+ df2=df.set_index(['date'])
1829
+
1830
+ tname=get_stock_name1_en(ticker,short_name=True)
1831
+
1832
+ #绘图1:虚值Calls vs Puts数量比例
1833
+ import datetime
1834
+ stoday = datetime.date.today()
1835
+
1836
+ df2['Benchmark']=1.0
1837
+ colname1='OTM Volume Call/Put'
1838
+ label1='虚值看涨/看跌期权合约数量比例'
1839
+ colname2='Benchmark'
1840
+ label2='等比例线'
1841
+ ylabeltxt='比例'
1842
+ titletxt="期权链中的合约数量: "+tname+", 虚值看涨/看跌期权比例"
1843
+
1844
+ footnote="数据来源:雅虎财经, "+str(stoday)
1845
+ plot_line2(df2,ticker,colname1,label1, \
1846
+ df2,ticker,colname2,label2, \
1847
+ ylabeltxt,titletxt,footnote)
1848
+
1849
+ #绘图2:OTM Calls vs OTM Puts交易金额比例
1850
+ colname1='OTM Amount Call/Put'
1851
+ label1='虚值看涨/看跌期权交易金额比例'
1852
+ titletxt="期权链中的交易金额: "+tname+", 虚值看涨/看跌期权比例"
1853
+
1854
+ plot_line2(df2,ticker,colname1,label1, \
1855
+ df2,ticker,colname2,label2, \
1856
+ ylabeltxt,titletxt,footnote)
1857
+
1858
+ #绘图3:预测的标的物价格
1859
+ df2['Benchmark']=lastsprice
1860
+ colname1='Estimated Price'
1861
+ label1='预期价格'
1862
+ colname2='Benchmark'
1863
+ label2='当前价格'
1864
+ ylabeltxt='价格('+currency+')'
1865
+ titletxt="期权链与标的价格预期: "+tname
1866
+
1867
+ plot_line2(df2,ticker,colname1,label1, \
1868
+ df2,ticker,colname2,label2, \
1869
+ ylabeltxt,titletxt,footnote)
1870
+
1871
+ #打印预测结果
1872
+ collist=['Date','Trend','Estimated Price','OTM Volume Call/Put','OTM Amount Call/Put']
1873
+ df3=df2[collist]
1874
+ """
1875
+ print("\n ======= 基于期权链结构的股票走势和价格预期: "+tname+" =======")
1876
+ #设置打印对齐
1877
+ pd.set_option('display.max_columns', 1000)
1878
+ pd.set_option('display.width', 1000)
1879
+ pd.set_option('display.max_colwidth', 1000)
1880
+ pd.set_option('display.unicode.ambiguous_as_wide', True)
1881
+ pd.set_option('display.unicode.east_asian_width', True)
1882
+ df3.columns=['日期','标的物价格走势','标的物价格预期','虚值看涨/看跌合约数量比例','虚值看涨/看跌交易金额比例']
1883
+ print(df3.to_string(index=False))
1884
+
1885
+ print(" 注:")
1886
+ print(" 1) 当前价格: "+currency+str(lastsprice),"\b,",lastsdate,'\b.')
1887
+ print(" 2) +(-)表示价格将比当前变高(低), +/-表示趋势不明朗.")
1888
+ print(" 3) 期权交易样本期间: 最近"+str(lastndays)+"个日历日,且期间内未发生分拆.")
1889
+ print(" 4) 价格估计可能随时变化,越远期的估计可能准确度越欠佳.")
1890
+ print(" "+footnote+'.')
1891
+ """
1892
+ titletxt="期权链与标的价格预期: "+tname
1893
+ footnote1="注:\n"
1894
+ footnote2="1、当前价格: "+currency+str(lastsprice)+", "+lastsdate+'\n'
1895
+ footnote3="2、+(-)表示价格将比当前变高(低), +/-表示趋势不明朗\n"
1896
+ footnote4="3、期权交易样本期间: 最近"+str(lastndays)+"个日历日,且期间内未发生分拆\n"
1897
+ footnote5="4) 价格价格估计可能随时变化,越远期的估计可能准确度越欠佳\n"
1898
+
1899
+ footnote9=footnote1+footnote2+footnote3+footnote4+footnote5+footnote
1900
+
1901
+ df_display_CSS(df3,titletxt=titletxt,footnote=footnote9,facecolor='papayawhip',decimals=2, \
1902
+ first_col_align='left',second_col_align='right', \
1903
+ last_col_align='right',other_col_align='right', \
1904
+ titile_font_size='15px',heading_font_size='13px', \
1905
+ data_font_size='13px')
1906
+
1907
+ return df2
1908
+
1909
+ if __name__ =="__main__":
1910
+ df=stock_trend_by_option('AAPL',7)
1911
+
1912
+ #==============================================================================
1913
+ #==============================================================================
1914
+ #==============================================================================
1915
+ #==============================================================================
1916
+
1917
+ #==============================================================================
1918
+
1919
+
1920
+
1921
+
1922
+
1923
+
1924
+
1925
+