Search code examples
pythonnumpyfinancemontecarlo

keep getting "only length-1 arrays can be converted to Python scalars"


I kept getting the error only length-1 arrays can be converted to Python scalars. Most people suggest sometimes numpy is not compatible with other existing math functions. but I changed every math function to np functions.

The error states:

Traceback (most recent call last):   File "/Users/jimmy/Documents/2.py", line 20, in <module>
    eu = mc_simulation(89,102,0.5,0.03,0.3,1000)   File "/Users/jimmy/Documents/2.py", line 12, in mc_simulation
    ST = s0 * exp((r - 0.5 * sigma ** 2) * T + sigma * a * z) TypeError: only length-1 arrays can be converted to Python scalars

My code:

from numpy import *
import numpy as np
from math import exp

def mc_simulation(s0, K, T, r, sigma, no_t):

    random.seed(1000)
    z = random.standard_normal(no_t)

    ST = s0 * exp((r - 0.5 * sigma ** 2) * T + sigma * np.sqrt(T) * z)

    payoff = maximum(ST - K, 0)

    eu_call = exp(-r * T) * sum(payoff) / no_t

    return eu_call


eu = mc_simulation(89,102,0.5,0.03,0.3,1000)

Solution

  • You don't need math here. Use numpy.exp. Furthermore, consider getting into the habit of not using the * operator with imports.

    import numpy as np
    np.random.seed(1000)
    
    def mc_simulation(s0, K, T, r, sigma, no_t):
        z = np.random.standard_normal(no_t)
        ST = s0 * np.exp((r - 0.5 * sigma ** 2) * T + sigma * np.sqrt(T) * z)
        payoff = np.maximum(ST - K, 0)
        eu_call = np.exp(-r * T) * np.sum(payoff) / no_t
        return eu_call
    
    print(mc_simulation(89,102,0.5,0.03,0.3,1000))
    3.4054951916465099
    

    To your comment of "why shouldn't I use the * operator": there are a ton of good discussions on why this can create trouble. But here is what the official documentation has to say on that: when you use from numpy import *:

    This imports all names except those beginning with an underscore (_). In most cases Python programmers do not use this facility since it introduces an unknown set of names into the interpreter, possibly hiding some things you have already defined.

    Your own example illustrates that. If you were to use:

    from numpy import *
    from math import *
    

    Both have an exp function that gets imported into the namespace as exp. Python might then have trouble knowing which exp you want to use and, as you saw here, they are quite different. The same applies if you have already defined an exp function yourself, or any other function that shares a name with any in those two packages.

    In general, be wary of any tutorials you run across that use from x import * consistently.