<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Plan
Look at some stock price series
devise a model for stock price series
describe a call option
price a call option
Look at some stock prices
We import data from Yahoo finance
Step1:  $\Rightarrow$ We get various different prices
Step2:  $\Longrightarrow$ There was a stock split 7
Step3:  For the apple chart one can see, that price increments seem to correlate with the price
Step4:  Now the roughness of the chart looks more even
Find a model
Idea
Step5:  Call option
Call option on a stock $S$ with strike price $K$ and expiry $T$
Step6:  Optionprices
Step7:  This curve can also be calculated theoretically. Using stochastic calculus, one can deduce the famous Black-Scholes equation, to calculate this curve. We will not go into detail ...
Step8:  ... but will just state the final result!
Black Scholes formula
Step9:  For small prices we do not need to own shares, to hedge the option. For high prices we need exactly one share. The interesting area is around the strike price.
Simulate a portfolio consisting of 1 call option and $-\Delta$ Shares
Step10:  Challenges
1) the price depends on the calibration of several parameters, $\sigma$, $\mu$
2) the price depends on the validity of the model
Both problems need attention
Step11:  Proposed solution
Find a way to price an option without the assumption of a market model, without the need to calibrate and recalibrate the model.
<ASSISTANT_TASK:>
Python Code:
aapl = data.DataReader('AAPL', 'yahoo', '2000-01-01')
print(aapl.head())
Explanation: Plan
Look at some stock price series
devise a model for stock price series
describe a call option
price a call option
Look at some stock prices
We import data from Yahoo finance: two examples are IBM and Apple
End of explanation
plt.plot(aapl.Close)
Explanation: $\Rightarrow$ We get various different prices
End of explanation
print(aapl['Adj Close'].head())
%matplotlib inline
plt.plot(aapl['Adj Close'])
plt.ylabel('price')
plt.xlabel('year')
plt.title('Price history of Apple stock')
plt.show()
ibm = data.DataReader('IBM', 'yahoo', '2000-1-1')
print(ibm['Adj Close'].head())
%matplotlib inline
plt.plot(ibm['Adj Close'])
plt.ylabel('price')
plt.xlabel('year')
plt.title('Price history of IBM stock')
Explanation: $\Longrightarrow$ There was a stock split 7:1 on 06/09/2014.
As we do not want to take care of things like that, we use the Adjusted close price!
End of explanation
Log_Data = plt.figure()
%matplotlib inline
plt.plot(np.log(aapl['Adj Close']))
plt.ylabel('logarithmic price')
plt.xlabel('year')
plt.title('Logarithmic price history of Apple stock')
Explanation: For the apple chart one can see, that price increments seem to correlate with the price: thus we plot logarithmic prices:
End of explanation
S0 = 1
sigma = 0.01
mu = 0
r = np.random.randn((1000))
S =  S0 * np.cumprod(np.exp(sigma *r))
%matplotlib inline
plt.plot(S)
Explanation: Now the roughness of the chart looks more even
Find a model
Idea: 
- Small changes appear often, large changes rarly:
- changes are proportional to the underlying stock price
$\Rightarrow$ use an exponential Gaussian distribution for increments:
 $$S_{n+1} = S_n e^{\sigma X+ \mu} $$
 where $X \sim N(0,1)$, $\sigma$ denotes the variance and $\mu$ the mean growth rate.
End of explanation
S0 = 1.5                    # start price
K = 1.0                     # strike price
mu = 0                      # average growth
sigma = 0.2/np.sqrt(252)    # volatility
N = 10000                   # runs
M = 252*4                   # length of each run (252 business days per year times 4 years)
def call_price(S, K):
    return max(0.0, S-K)
def MC_call_price(S0, K, mu, sigma, N, M):
    CSum = 0
    SSum = 0
    for n in range(N):
        r = np.random.randn((M))
        S =  S0 * np.cumprod(np.exp(sigma *r))
        SSum += S
        CSum += call_price(S[M-1], K)
    return CSum/N
S0 = np.linspace(0.0, 2.0,21)
C = []
for k in range(21):
    C.append(MC_call_price(k*2/20, K, mu, sigma, N, M))
Explanation: Call option
Call option on a stock $S$ with strike price $K$ and expiry $T$: 
The buyer of the call option has the right, but not the obligation, to buy $1$ stock $S$  (the underlying) from the seller of the option at a certain time (the expiration date $T$) for a certain price (the strike price $K$).
What is a fair price for this option?
If the stock trades at a price $S$ at time $T$, then the payoff is: 
Payoff: $C_T =\max(0, S-K)\,.$
If the interest rate is $r$, then for this Payoff, one would pay today (time $t = 0$)
$$C_0 = e^{- r T} \max(0, S-K)\,.$$
Problem: we do not know $S_T$ at time $0$.
Solution: we take the expectation of $S$. This yields
$$C_{0, S} = e^{- r T} \mathbb{E}\left[ \max(0, S-K)\right]\,.$$
End of explanation
C
plt.plot(S0, C)
plt.ylabel('Call price')
plt.xlabel('Start price')
plt.title('Call price')
plt.show()
Explanation: Optionprices:
End of explanation
from IPython.display import Image
Image("Picture_Then_Miracle_Occurs.PNG")
Explanation: This curve can also be calculated theoretically. Using stochastic calculus, one can deduce the famous Black-Scholes equation, to calculate this curve. We will not go into detail ...
End of explanation
d_1 = lambda σ, T, t, S, K: 1. / σ / np.sqrt(T - t) * (np.log(S / K) + 0.5 * (σ ** 2) * (T-t))
d_2 = lambda σ, T, t, S, K: 1. / σ / np.sqrt(T - t) * (np.log(S / K) - 0.5 * (σ ** 2) * (T-t))
call = lambda σ, T, t, S, K: S * sp.stats.norm.cdf( d_1(σ, T, t, S, K) ) - K * sp.stats.norm.cdf( d_2(σ, T, t, S, K) )
Delta = lambda σ, T, t, S, K: sp.stats.norm.cdf( d_1(σ, T, t, S, K) )
plt.plot(np.linspace(sigma, 4., 100), call(1., 1., .9, np.linspace(0.1, 4., 100), 1.))
plt.plot(d_1(1., 1., 0., np.linspace(0.1, 2.9, 10), 1))
#plt.plot(np.linspace(sigma, 4., 100), Delta(1., 1.,  .9, np.linspace(0.1,   4., 100), 1.))
plt.plot(np.linspace(sigma, 1.9, 100), Delta(1., 1., 0.2, np.linspace(0.01, 1.9, 100), 1.))
plt.plot(np.linspace(sigma, 1.9, 100), Delta(1., 1., 0.6, np.linspace(0.01, 1.9, 100), 1.))
plt.plot(np.linspace(sigma, 1.9, 100), Delta(1., 1., 0.9, np.linspace(0.01, 1.9, 100), 1.))
plt.plot(np.linspace(sigma, 1.9, 100), Delta(1., 1., 0.99, np.linspace(0.01, 1.9, 100), 1.))
plt.plot(np.linspace(sigma, 1.9, 100), Delta(1., 1., 0.9999, np.linspace(0.01, 1.9, 100), 1.))
plt.xlabel("Price/strike price")
plt.ylabel("$\Delta$")
plt.legend(['t = 0.2','t = 0.6', 't = 0.9', 't = 0.99', 't = 0.9999'], loc= )
Explanation: ... but will just state the final result!
Black Scholes formula:
$${\displaystyle d_{1}={\frac {1}{\sigma {\sqrt {T-t}}}}\left[\ln \left({\frac {S_{t}}{K}}\right)+(r-q+{\frac {1}{2}}\sigma ^{2})(T-t)\right]}$$
$${\displaystyle d_{2}=d_{1}-\sigma {\sqrt {T-t}}={\frac {1}{\sigma {\sqrt {T-t}}}}\left[\ln \left({\frac {S_{t}}{K}}\right)+(r-q-{\frac {1}{2}}\sigma ^{2})(T-t)\right]}$$
Black-Scholes Formula for the call price:
$${\displaystyle C(S_{t},t)=e^{-r(T-t)}[S_tN(d_{1})-KN(d_{2})]\,}$$
$\Delta$ describes the change in the price of the option if the stock price changes by $1$.
Black Scholes formula for the Delta:
$$ \Delta(C, t) = e^{-r(T-t)} N(d_1)$$
End of explanation
def Simulate_Price_Series(S0, sigma, N, M):
    for n in range(N):
        r = np.random.randn((M))
        S =  S0 * np.cumprod(np.exp(sigma * r))
    return S
plt.plot(1+np.cumsum(np.diff(S) *Delta(sigma, 4, 0, S, K)[1, M-1]))
plt.plot(S)
len(Delta(sigma, 4, 0, S, K)[[1:999]])
def Calculate_Portfolio(S0, K, mu, sigma, N, M):
    S = Simulate_Price_Series(S0, sigma, N, M)
    StockDelta = Delta(sigma, 4, 0, S, K) )
    vol = vol0 * np.cumprod(np.exp(sigma*r2)
    S =  S0 * np.cumprod(np.exp(vol * r))
    SSum += S
    CSum += call_price(S[M-1], K)
Explanation: For small prices we do not need to own shares, to hedge the option. For high prices we need exactly one share. The interesting area is around the strike price.
Simulate a portfolio consisting of 1 call option and $-\Delta$ Shares:
$$P = C - \Delta S$$
In approximation, the portfolio value should be constant!
End of explanation
def MC_call_price_Loc_Vol(S0, K, mu, sigma, N, M):
    CSum = 0
    SSum = 0
    for n in range(N):
        r = np.random.randn((M))
        r2 = np.random.randn((M))
        vol = vol0 * np.cumprod(np.exp(sigma*r2)
        S =  S0 * np.cumprod(np.exp(vol * r))
        SSum += S
        CSum += call_price(S[M-1], K)
    return CSum/N
S0 = np.linspace(0.0, 2.0,21)
CLoc = []
for k in range(21):
    CLoc.append(MC_call_price_Loc_Vol(k*2/20, K, mu, 0.1*sigma, N, M))
  
CLoc
plt.plot(S0, C)
plt.plot(S0, CLoc)
plt.ylabel('Call price')
plt.xlabel('Start price')
plt.title('Call price')
plt.show()
Explanation: Challenges
1) the price depends on the calibration of several parameters, $\sigma$, $\mu$
2) the price depends on the validity of the model
Both problems need attention:
1) $\sigma$ and $\mu$ may change over time. Hence changes of volatility should adapted in the price
$\Longrightarrow$ new more complex models describing stochastic volatility are introduced 
- Heston model, 
- Ball-Roma model, 
- SABR-model and many more
2) normally distributed increments are not realistic. Real distributions are
- Heavy tails:
- Gain/Loss asymmetry 
- Aggregational Gaussianity
- Intermittency (parameter changes over time)
- Volatility clustering
- Leverage effect
- Volume/volatility correlation:
- Slow decay of autocorrelation in absolute returns:
- Asymmetry in time scales
(see for example: Rama Cont: Empirical properties of asset returns: stylized facts and statistical issues, Journal of quantitative finance, Volume 1 (2001) 223–236)
The option price depends on the model, on the calibration.
Alternative model: Local volatility model
The closest alternative to the Black-Scholes model are local volatility models.
End of explanation
def iterate_series(n=1000, S0 = 1):
    while True:
        r = np.random.randn((n))
        S = np.cumsum(r) + S0
        yield S, r
for (s, r) in iterate_series():
    t, t_0 = 0, 0
    for t in np.linspace(0, len(s)-1, 100):
        r = s[int(t)] / s[int(t_0)]
        t_0 = t
    break
state = (stock_val, besitz)
state = rel_stock_price, tau
Explanation: Proposed solution
Find a way to price an option without the assumption of a market model, without the need to calibrate and recalibrate the model.
End of explanation
<END_TASK>