1

I am trying to find the value of the S where a Put option equals K-S in Python, where K is the strike price of the option and S is the underlying strike price. Also, in the function call of the Black-Sholes, sigma is the volatility, delta is the dividends paid, T is the time to expiration, r is the risk-free rate of interest.

I am testing it with K=75, r=0.05, T=1/12, sigma =0.35.

Furthermore, I know that my pricing for the Black-Sholes works as I have used it in a previous project of mine, it is possible that the modified versions of a syntax error.

I have tried using scipy.optimize, but I keep getting errors.

Is there another method, I should use?
If so, how?

import numpy as np
import scipy.stats as ss
import time
import pylab as pl
import matplotlib.pyplot as plt
from prettytable import PrettyTable
import datetime
import scipy.optimize

from scipy.optimize import newton


# initial stock price
type = 'C'

def d1(S0, K, r, sigma, T, delta):
    return (np.log(float(S0) / K) + (r - delta + sigma ** 2 / 2) * T) / (sigma * np.sqrt(T))


def d2(S0, K, r, sigma, T,delta):
    return (d1(S0, K, r, sigma, T,delta)-sigma * np.sqrt(T))


def blackScholes(type, S0, K, r, sigma, T, delta):
    if type == "C":
        return S0 * np.exp(-delta * T)* ss.norm.cdf(d1(S0, K, r, sigma, T, delta)) - K * np.exp(-r * T) * ss.norm.cdf(d2(S0, K, r, sigma, T, delta))
    else:
        return K * np.exp(-r * T) * ss.norm.cdf(-d2(S0, K, r, sigma, T, delta)) - S0 * ss.norm.cdf(-d1(S0, K, r, sigma, T, delta))

# args is args = (type,K,r,sigma,T,delta)
# Modifying Black-Sholes function arguments for multivariate optimization
def d1Modified(S, args):

        type = args[0]
        K = args[1]
        r = args[2]
        sigma = args[3]
        T = args[4]
        delta = args[5]
        return (np.log(float(S) / K) + (r - delta + sigma ** 2 / 2) * T) / (sigma * np.sqrt(T))

def d2Modified(S, args):
    type = args[0]
    K = args[1]
    r = args[2]
    sigma = args[3]
    T = args[4]
    delta = args[5]
    return (d1Modified(S,args) - sigma * np.sqrt(T))

def blackScholesModified(S, args):
    type = args[0]
    print("print args")
    print(args)
    K = args[1]
    r = args[2]
    sigma = args[3]
    T = args[4]
    delta = args[5]
    if type == "C":
        return S * np.exp(-delta * T) * ss.norm.cdf(d1Modified(S, args)) - K * np.exp(
            -r * T) * ss.norm.cdf(d2Modified(S,args))
    else:
        return K * np.exp(-r * T) * ss.norm.cdf(-d2Modified(S, args)) - S * ss.norm.cdf(
               -d1Modified(S,args))


print("Pricing a European Put Option")

p = "P"

#Note: at is the tuple with the inputs into the black-sholes equation
# Where p is a string indicating a put option, K is the strike price
# r is the risk free rate of interest, sigma is volatility, T is time to
# expiration and delta is dividends
ar = (p,K,r,sigma,T,delta)


putOptionPriceList = []
for i in range(1,74):
    stockPriceList.append(i)

for x in stockPriceList:
    price = blackScholes("P",x,K,r,sigma,T,delta)
    print(price)
    putOptionPriceList.append(price)



# Constraints for multivariate optimization where price = K-S
def con(S,ar):
    k= 75
    return blackScholesModified(S, ar) -(k-S)


cons = {'type':'eq', 'fun': con(S,ar)}


sPrice = scipy.optimize.minimize(blackScholesModified, 0.1, args=ar, constraints=cons)

print("Value sought")
print(sPrice)

I keep getting the following error:

Traceback (most recent call last):

    sPrice = scipy.optimize.minimize(blackScholesModified, 0.1, args=ar, constraints=cons)
  File "C:\Users\user\Anaconda3\lib\site-packages\scipy\optimize\_minimize.py", line 458, in minimize
    constraints, callback=callback, **options)
  File "C:\Users\user\Anaconda3\lib\site-packages\scipy\optimize\slsqp.py", line 311, in _minimize_slsqp
    meq = sum(map(len, [atleast_1d(c['fun'](x, *c['args'])) for c in cons['eq']]))
  File "C:\Users\user\Anaconda3\lib\site-packages\scipy\optimize\slsqp.py", line 311, in <listcomp>
    meq = sum(map(len, [atleast_1d(c['fun'](x, *c['args'])) for c in cons['eq']]))
TypeError: 'numpy.float64' object is not callable
cjstittles
  • 61
  • 5
  • Being new to StackOverflow, there might be a value for you to note, the edit(s) history is being stored & re-readable *( forever )*, so rather be cautious and carefull **not to post any sensitive data** ( passwords, PIN(s), access-token(s), etc. ) as still being visible in http://stackoverflow.com/posts/43301278/revisions Anyway, enjoy this great Community of Knowledge and feel free to become a next actively contributing Member. – user3666197 Apr 12 '17 at 19:49

1 Answers1

0

My guess would be to carefully follow the 0.18 specified calling interface:

   cons = { 'type': 'eq',
            'fun':   con,       # con( S, ar ) here'd yield float64, not callable
            'args':  ( S, ar )  #    ( ^__^__)_ passed to a fun == con()-callable
             }
user3666197
  • 1
  • 6
  • 50
  • 92
  • Thank you for your response! When I change that I get the following error: – cjstittles Apr 11 '17 at 17:50
  • `File "C:\Users\user\Anaconda3\lib\site-packages\scipy\optimize\slsqp.py", line 311, in meq = sum(map(len, [atleast_1d(c['fun'](x, *c['args'])) for c in cons['eq']])) TypeError: con() takes 2 positional arguments but 3 were given` – cjstittles Apr 11 '17 at 17:55
  • If you read the `slsqp.py` + decode a bit more carefully the calling-interface, which is using indirectly assembled parameters to meet the spec, the user-provided Constraint-function (**`con(...)`**) shall have a different calling-interface, than was defined above. As seen from the `slsqp.py` source, **`scipy.optimize.minimize()`** expects the Constraint-function to always receive **`x`**, as it's first parameter (auto-delivered from `scipy` internalities), next, iterated, whatever amount of parameters, def'd indirectly, via a single "packing" tuple **`cons['args']`** so `def con( x, S, ar):` – user3666197 Apr 11 '17 at 19:22