Матплотлиб не заполняет всю площадь - PullRequest
2 голосов
/ 17 апреля 2020

Я не могу понять, почему python не заполняет область от «Strike» до «Break Even» (красный) и «Break Even» до 21 (Green). Я подумал, что установка 'где = цена> = break_even' позволит это. Ошибка произошла после того, как я применил следующий код, чтобы дать цене диапазон, зависящий от страйка.

display_range1 = strike*.9
display_range2 = strike*1.2
price = np.arange(display_range1, display_range2)

График вывода

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()

1 Ответ

0 голосов
/ 18 апреля 2020

Нет ничего плохого в вашем коде! Однако существует проблема с разрешением:

Параметр where позволяет выбрать, какие индексы массива price следует включить. Теперь, когда ваш ценовой массив увеличивается с шагом 1, первое значение, которое нужно включить, равно price[3], что равно 21. Таким образом, fill_between начинается с 21, как вы наблюдаете на своем графике.

Чтобы решить эту проблему вам нужно увеличить разрешение ваших данных . В вашем случае лучше всего сделать ставку go с предложением @ Johan C и просто увеличить разрешение вашей переменной price, явно указав step в numpy arange, например

price = np.arange(display_range1, display_range2, 0.01)

Если по какой-то причине увеличение разрешения price не является вариантом, вы всегда можете увеличить разрешение вашей Прибыль / Убыток значения через интерполяцию. Это может быть сложно, особенно если ваша 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')

В итоге вы получите:

enter image description here

...