# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: Python 2
#     language: python
#     name: python2
# ---

# + [markdown] nbgrader={}
# # Numpy Exercise 3

# + [markdown] nbgrader={}
# ## Imports

# + nbgrader={}
import numpy as np
# %matplotlib inline
import matplotlib.pyplot as plt
import seaborn as sns

# + nbgrader={}
import antipackage
import github.ellisonbg.misc.vizarray as va


# + [markdown] nbgrader={}
# ## Geometric Brownian motion

# + [markdown] nbgrader={}
# Here is a function that produces standard Brownian motion using NumPy. This is also known as a [Wiener Process](http://en.wikipedia.org/wiki/Wiener_process).

# + nbgrader={}
def brownian(maxt, n):
    """Return one realization of a Brownian (Wiener) process with n steps and a max time of t."""
    t = np.linspace(0.0,maxt,n)
    h = t[1]-t[0]
    Z = np.random.normal(0.0,1.0,n-1)
    dW = np.sqrt(h)*Z
    W = np.zeros(n)
    W[1:] = dW.cumsum()
    return t, W


# + [markdown] nbgrader={}
# Call the `brownian` function to simulate a Wiener process with `1000` steps and max time of `1.0`. Save the results as two arrays `t` and `W`.

# + deletable=false nbgrader={"checksum": "6cff4e8e53b15273846c3aecaea84a3d", "grade": false, "grade_id": "numpyex03a", "points": 2, "solution": true}
t = brownian(1.0, 1000)[0]
W = brownian(1.0, 1000)[1]

# + deletable=false nbgrader={"checksum": "b671a523fd8cb7621c2445244189d5a4", "grade": true, "grade_id": "numpyex03a", "points": 2}
assert isinstance(t, np.ndarray)
assert isinstance(W, np.ndarray)
assert t.dtype==np.dtype(float)
assert W.dtype==np.dtype(float)
assert len(t)==len(W)==1000

# + [markdown] nbgrader={}
# Visualize the process using `plt.plot` with `t` on the x-axis and `W(t)` on the y-axis. Label your x and y axes.

# + deletable=false nbgrader={"checksum": "6cff4e8e53b15273846c3aecaea84a3d", "grade": false, "grade_id": "numpyex03b", "points": 2, "solution": true}
plt.plot(t, W)
plt.xlabel('t')
plt.ylabel('W(t)')

# + deletable=false nbgrader={"checksum": "1a35840ca7eaf864f9201ee4e0d947e0", "grade": true, "grade_id": "numpyex03b", "points": 2}
assert True # this is for grading

# + [markdown] nbgrader={}
# Use `np.diff` to compute the changes at each step of the motion, `dW`, and then compute the mean and standard deviation of those differences.

# + deletable=false nbgrader={"checksum": "6cff4e8e53b15273846c3aecaea84a3d", "grade": false, "grade_id": "numpyex03c", "points": 2, "solution": true}
dW = np.diff(W)
print(dW.mean(), dW.std())

# + deletable=false nbgrader={"checksum": "b2236af662ecc138c4b78af673b476c1", "grade": true, "grade_id": "numpyex03c", "points": 2}
assert len(dW)==len(W)-1
assert dW.dtype==np.dtype(float)


# + [markdown] nbgrader={}
# Write a function that takes $W(t)$ and converts it to geometric Brownian motion using the equation:
#
# $$
# X(t) = X_0 e^{((\mu - \sigma^2/2)t + \sigma W(t))}
# $$
#
# Use Numpy ufuncs and no loops in your function.

# + nbgrader={"checksum": "2b05883af2c87bc938fc4f7fe7e35f66", "grade": false, "grade_id": "numpyex03d", "points": 2, "solution": true}
def geo_brownian(t, W, X0, mu, sigma):
    "Return X(t) for geometric brownian motion with drift mu, volatility sigma."""
    X = X0 * np.exp(((mu-sigma**2)/2)*t + sigma*W)
    return X


# + deletable=false nbgrader={"checksum": "401ffd490410ab0a18612d641e24c02f", "grade": true, "grade_id": "numpyex03d", "points": 2}
assert True # leave this for grading

# + [markdown] nbgrader={}
# Use your function to simulate geometric brownian motion, $X(t)$ for $X_0=1.0$, $\mu=0.5$ and $\sigma=0.3$ with the Wiener process you computed above.
#
# Visualize the process using `plt.plot` with `t` on the x-axis and `X(t)` on the y-axis. Label your x and y axes.

# + deletable=false nbgrader={"checksum": "6cff4e8e53b15273846c3aecaea84a3d", "grade": false, "grade_id": "numpyex03f", "points": 2, "solution": true}
X = geo_brownian(t, W, 1.0, 0.5, 0.3)
plt.plot(t, X)
plt.xlabel('t')
plt.ylabel('X(t)')

# + deletable=false nbgrader={"checksum": "00e3fda54f3eba73d67842cf7f02777a", "grade": true, "grade_id": "numpyex03e", "points": 2}
assert True # leave this for grading

StarcoderdataJupyterScriptsDedupFiltered