Matplotlib 没有填满整个区域
Matplotlib not filling full area
我似乎无法弄清楚为什么 python 没有填充从 'Strike' 到 'Break Even'(红色)和 'Break Even' 到 21(绿色的)。我认为设置 'where = price>=break_even' 会允许这样做。在我执行以下代码以根据行使价为价格提供范围后发生错误。
display_range1 = strike*.9
display_range2 = strike*1.2
price = np.arange(display_range1, display_range2)
Graph Output
import pandas as pd
from pandas import DataFrame
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
symbol = 'Stock'
option_type = 'Call'
expiry = 'March 17, 2020'
strike = 20.00
IV = 120.625
premium = .54
contracts = 1
break_even = strike+premium
display_range1 = strike*.9
display_range2 = strike*1.2
price = np.arange(display_range1, display_range2)
def long_call(price, strike, premium, contracts):
P = (max(price - strike, 0) - premium)*(contracts*100)
return P
def get_graph_value():
graph_values = []
for i in price:
graph_values.append(long_call(i, strike, premium, contracts))
return graph_values
fig, ax = plt.subplots()
ax.plot(price, get_graph_value())
ax.set(xlabel='Underlying Price ($)', ylabel='Profit/Loss ($)',
title=str(symbol)+' '+str(option_type)+ ' Option Payoff')
ax.fill_between(price, get_graph_value(), where = price>=break_even, color='#3cb371')
ax.fill_between(price, get_graph_value(), where = price<=break_even, color ='#ff6347')
plt.axvline(break_even, color="black", label='Break Even' )
plt.axvline(strike, color="black", linestyle="--", label='Strike')
plt.legend()
plt.show()
其实你的代码没有任何问题!但是,存在分辨率问题:
where
参数允许 select 应包含 price
数组的哪些索引。现在,由于您的价格数组以 1 为步长递增,因此要包含的第一个值是 price[3]
,即 21。因此 fill_between
从 21 开始,就像您在图中观察到的那样。
要解决这个问题,您需要提高数据的分辨率。
在您的情况下,最好的选择是使用 and simply increase the resolution of your price
variable by explicitly setting the step
in numpy arange
,例如
price = np.arange(display_range1, display_range2, 0.01)
如果由于某种原因无法提高 price
的分辨率,那么您可以随时通过以下方式提高 Profit/Loss 值的分辨率插值。这可能很棘手,特别是如果您的 get_graph_value
函数不是微不足道的。
幸运的是,您在此处给出的示例解决起来相当简单,因为这些值线性增加,我们可以在不通过线性插值逼近值的情况下获得更高的分辨率。
Numpy 通过提供允许计算分段线性插值的 np.interp
来覆盖您。
以下是使用 np.interp
解决分辨率问题的方法:
# ...
# nothing changes up to here:
def get_graph_value():
graph_values = []
for i in price:
graph_values.append(long_call(i, strike, premium, contracts))
# simply returning a numpy array here, makes things easier
return np.array(graph_values)
def interpolated_values(values):
"""Do a piecewise linear interpolation between the elements of an array
"""
# creating a 'high resolution' version of the price
xvals = np.linspace(np.min(price), np.max(price), 1000)
# now create 'high resolution' (interpolated) version of values
yinterp = np.interp(xvals, price, values)
# return both
return xvals, yinterp
fig, ax = plt.subplots()
# ... simply replace the first fill_between call by these 2 lines:
xvals, yinterp = interpolated_values(get_graph_value())
ax.fill_between(xvals, yinterp, where = xvals>=break_even, color='#3cb371')
最后你会得到:
我似乎无法弄清楚为什么 python 没有填充从 'Strike' 到 'Break Even'(红色)和 'Break Even' 到 21(绿色的)。我认为设置 'where = price>=break_even' 会允许这样做。在我执行以下代码以根据行使价为价格提供范围后发生错误。
display_range1 = strike*.9
display_range2 = strike*1.2
price = np.arange(display_range1, display_range2)
Graph Output
import pandas as pd
from pandas import DataFrame
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
symbol = 'Stock'
option_type = 'Call'
expiry = 'March 17, 2020'
strike = 20.00
IV = 120.625
premium = .54
contracts = 1
break_even = strike+premium
display_range1 = strike*.9
display_range2 = strike*1.2
price = np.arange(display_range1, display_range2)
def long_call(price, strike, premium, contracts):
P = (max(price - strike, 0) - premium)*(contracts*100)
return P
def get_graph_value():
graph_values = []
for i in price:
graph_values.append(long_call(i, strike, premium, contracts))
return graph_values
fig, ax = plt.subplots()
ax.plot(price, get_graph_value())
ax.set(xlabel='Underlying Price ($)', ylabel='Profit/Loss ($)',
title=str(symbol)+' '+str(option_type)+ ' Option Payoff')
ax.fill_between(price, get_graph_value(), where = price>=break_even, color='#3cb371')
ax.fill_between(price, get_graph_value(), where = price<=break_even, color ='#ff6347')
plt.axvline(break_even, color="black", label='Break Even' )
plt.axvline(strike, color="black", linestyle="--", label='Strike')
plt.legend()
plt.show()
其实你的代码没有任何问题!但是,存在分辨率问题:
where
参数允许 select 应包含 price
数组的哪些索引。现在,由于您的价格数组以 1 为步长递增,因此要包含的第一个值是 price[3]
,即 21。因此 fill_between
从 21 开始,就像您在图中观察到的那样。
要解决这个问题,您需要提高数据的分辨率。
在您的情况下,最好的选择是使用 price
variable by explicitly setting the step
in numpy arange
,例如
price = np.arange(display_range1, display_range2, 0.01)
如果由于某种原因无法提高 price
的分辨率,那么您可以随时通过以下方式提高 Profit/Loss 值的分辨率插值。这可能很棘手,特别是如果您的 get_graph_value
函数不是微不足道的。
幸运的是,您在此处给出的示例解决起来相当简单,因为这些值线性增加,我们可以在不通过线性插值逼近值的情况下获得更高的分辨率。
Numpy 通过提供允许计算分段线性插值的 np.interp
来覆盖您。
以下是使用 np.interp
解决分辨率问题的方法:
# ...
# nothing changes up to here:
def get_graph_value():
graph_values = []
for i in price:
graph_values.append(long_call(i, strike, premium, contracts))
# simply returning a numpy array here, makes things easier
return np.array(graph_values)
def interpolated_values(values):
"""Do a piecewise linear interpolation between the elements of an array
"""
# creating a 'high resolution' version of the price
xvals = np.linspace(np.min(price), np.max(price), 1000)
# now create 'high resolution' (interpolated) version of values
yinterp = np.interp(xvals, price, values)
# return both
return xvals, yinterp
fig, ax = plt.subplots()
# ... simply replace the first fill_between call by these 2 lines:
xvals, yinterp = interpolated_values(get_graph_value())
ax.fill_between(xvals, yinterp, where = xvals>=break_even, color='#3cb371')
最后你会得到: