Вопрос или проблема
Я написал функцию на Python, которая, по моему ожиданию, должна позволять векторизацию, используя np.where и np.maximum. Однако, когда я пытаюсь вызвать эту функцию, передавая столбцы датафрейма, я получаю ошибку “ValueError: operands could not be broadcast together with shapes (2,20) (2,).”
Функция работает нормально при передаче констант. Я почти уверен, что это связано с тем, как я нарезаю массив констант montecarlo[j], но я не знаю, как переписать его, чтобы позволить векторизацию.
заметьте, что x – это массив формы 250×20, случайные числа будут работать нормально
import numpy as np
np.random.seed(5)
x = stats.montecarlo_brownian(4.5, 1, 250, .15, sims=20)
j = 249
otype="p"
k = 4.0
def montecarlo_payouts(montecarlo, j, otype, k, kotype = None, b = 0, i=1):
#корректировка количества дней для индекса, начинающегося с 0
i = i - 1
j = j - 1
#выплаты по обычным опционам для колл и пут
payoff = np.where(otype=='c', np.maximum(montecarlo[j] - k, 0), np.maximum(k - montecarlo[j], 0))
return payoff.mean()
df = pd.DataFrame({'days': [230,250], 'otype': ['c','p'], 'strike': [4.8,4.3]})
payout = montecarlo_payouts(x, 250, df['otype'], 5)
если я заменю df[‘otype’] на одно значение, ‘c’, код работает нормально
Ответ или решение
Решение проблемы векторизации функции Monte Carlo в Python
Вам удалось разработать функцию, использующую векторизацию с библиотеками NumPy и Pandas, но вы столкнулись с ошибкой "ValueError: operands could not be broadcast together with shapes", что указывает на проблему с несоответствием форм массивов. Это частая проблема при работе с многомерными массивами в Python. Давайте внимательно рассмотрим вашу функцию и как можно адаптировать её для работы с Pandas DataFrame.
Исходная проблема
Вы используете код, в котором передаете столбцы DataFrame в качестве параметров функции montecarlo_payouts
. Однако, функция ожидает массив стандартного формата, и когда вы передаете столбцы DataFrame, NumPy не может корректно обработать различные размеры массивов и вызывает ошибку.
Вот ключевые моменты, на которые стоит обратить внимание:
- Формы массивов: Когда вы передаете
df['otype']
, это возвращает объект типа Series, а не массив с фиксированной длиной, что приводит к проблемам при векторизации внутриnp.where
. - Ожидаемые входные данные: Функция ожидает параметры, которые имеют одинаковую длину или размер, чтобы NumPy мог производить над ними операции.
Исправление функции для поддержки векторизации
Чтобы ваша функция работала корректно для векторизованных данных, вам необходимо убедиться, что каждое значение otype
, k
, и другие параметры имеют совместимые размеры с массивом montecarlo
. В данном случае, мы можем адаптировать вашу функцию следующим образом:
import numpy as np
import pandas as pd
from scipy import stats
np.random.seed(5)
x = stats.montecarlo_brownian(4.5, 1, 250, .15, sims=20)
j = 249
def montecarlo_payouts(montecarlo, j, otype, k):
# корреция индекса
j = j - 1
payoff = np.where(
otype == 'c',
np.maximum(montecarlo[j] - k[:, None], 0),
np.maximum(k[:, None] - montecarlo[j], 0)
)
return payoff.mean(axis=1)
# Предполагаем, что 'k' - это массив, который содержит соответствующий страйк для каждой строки DataFrame.
df = pd.DataFrame({'days': [230,250], 'otype': ['c','p'], 'strike': [4.8,4.3]})
payout = montecarlo_payouts(x, 250, df['otype'].values, df['strike'].values)
Ключевые изменения
- Использование
[:, None]
для векторизации: Это преобразует векторk
в двумерный массив, который NumPy может корректно сравнивать с соответствующими значениями вmontecarlo[j]
. - Обработка
otype
иk
как массивов: Приведение их к массивам NumPy через.values
, чтобы избежать ошибок совместимости, когда они передаются в функции NumPy.
Заключение
С такими изменениями ваша функция montecarlo_payouts
теперь будет способны обрабатывать массивы и DataFrame корректно, а также предоставит вам ожидаемые результаты. Векторизация не только улучшит производительность, но и упростит чтение кода. Если у вас будут дополнительные вопросы или возникнут сложности, не стесняйтесь обращаться за помощью!