

# Artificial Intelligence in Finance

## Normative Finance

Dr Yves J Hilpisch | The AI Machine

http://aimachine.io | http://twitter.com/dyjh

## Uncertainty and Risk


```python
import numpy as np
```


```python
S0 = 10
B0 = 10
```


```python
S1 = np.array((20, 5))
B1 = np.array((11, 11))
```


```python
M0 = np.array((S0, B0))
M0
```


```python
M1 = np.array((S1, B1)).T
M1
```


```python
K = 14.5
```


```python
C1 = np.maximum(S1 - K, 0)
C1
```


```python
phi = np.linalg.solve(M1, C1)
phi
```


```python
np.allclose(C1, np.dot(M1, phi))
```


```python
C0 = np.dot(M0, phi)
C0
```

## Expected Utility Theory


```python
def u(x):
    return np.sqrt(x)
```


```python
phi_A = np.array((0.75, 0.25))
phi_D = np.array((0.25, 0.75))
```


```python
np.dot(M0, phi_A) == np.dot(M0, phi_D)
```


```python
A1 = np.dot(M1, phi_A)
A1
```


```python
D1 = np.dot(M1, phi_D)
D1
```


```python
P = np.array((0.5, 0.5))
```


```python
def EUT(x):
    return np.dot(P, u(x))
```


```python
EUT(A1)
```


```python
EUT(D1)
```


```python
from scipy.optimize import minimize
```


```python
w = 10
```


```python
cons = {'type': 'eq', 'fun': lambda phi: np.dot(M0, phi) - w}
```


```python
def EUT_(phi):
    x = np.dot(M1, phi)
    return EUT(x)
```


```python
opt = minimize(lambda phi: -EUT_(phi),
               x0=phi_A,
               constraints=cons)
```


```python
opt
```


```python
EUT_(opt['x'])
```


```python
np.dot(M0, opt['x'])
```

## Mean-Variance Portfolio Theory


```python
rS = S1 / S0 - 1
rS
```


```python
rB = B1 / B0 - 1
rB
```


```python
def mu(rX):
    return np.dot(P, rX)
```


```python
mu(rS)
```


```python
mu(rB)
```


```python
rM = M1 / M0 - 1
rM
```


```python
mu(rM)
```


```python
def var(rX):
    return ((rX - mu(rX)) ** 2).mean()
```


```python
var(rS)
```


```python
var(rB)
```


```python
def sigma(rX):
    return np.sqrt(var(rX))
```


```python
sigma(rS)
```


```python
sigma(rB)
```


```python
np.cov(rM.T, aweights=P, ddof=0)
```


```python
phi = np.array((0.5, 0.5))
```


```python
def mu_phi(phi):
    return np.dot(phi, mu(rM))
```


```python
mu_phi(phi)
```


```python
def var_phi(phi):
    cv = np.cov(rM.T, aweights=P, ddof=0)
    return np.dot(phi, np.dot(cv, phi))
```


```python
var_phi(phi)
```


```python
def sigma_phi(phi):
    return var_phi(phi) ** 0.5
```


```python
sigma_phi(phi)
```


```python
from pylab import plt, mpl
plt.style.use('seaborn')
mpl.rcParams['savefig.dpi'] = 300
mpl.rcParams['font.family'] = 'serif'
```


```python
phi_mcs = np.random.random((2, 200))
```


```python
phi_mcs = (phi_mcs / phi_mcs.sum(axis=0)).T
```


```python
mcs = np.array([(sigma_phi(phi), mu_phi(phi))
                for phi in phi_mcs])
```


```python
plt.figure(figsize=(10, 6))
plt.plot(mcs[:, 0], mcs[:, 1], 'ro')
plt.xlabel('expected volatility')
plt.ylabel('expected return');
```


```python
P = np.ones(3) / 3
P
```


```python
S1 = np.array((20, 10, 5))
```


```python
T0 = 10
T1 = np.array((1, 12, 13))
```


```python
M0 = np.array((S0, T0))
M0
```


```python
M1 = np.array((S1, T1)).T
M1
```


```python
rM = M1 / M0 - 1
rM
```


```python
mcs = np.array([(sigma_phi(phi), mu_phi(phi))
                for phi in phi_mcs])
```


```python
plt.figure(figsize=(10, 6))
plt.plot(mcs[:, 0], mcs[:, 1], 'ro')
plt.xlabel('expected volatility')
plt.ylabel('expected return');
```


```python
cons = {'type': 'eq', 'fun': lambda phi: np.sum(phi) - 1}
```


```python
bnds = ((0, 1), (0, 1))
```


```python
min_var = minimize(sigma_phi, (0.5, 0.5),
                   constraints=cons, bounds=bnds)
```


```python
min_var
```


```python
def sharpe(phi):
    return mu_phi(phi) / sigma_phi(phi)
```


```python
max_sharpe = minimize(lambda phi: -sharpe(phi), (0.5, 0.5),
               constraints=cons, bounds=bnds)
```


```python
max_sharpe
```


```python
plt.figure(figsize=(10, 6))
plt.plot(mcs[:, 0], mcs[:, 1], 'ro', ms=5)
plt.plot(sigma_phi(min_var['x']), mu_phi(min_var['x']),
         '^', ms=12.5, label='minimum volatility')
plt.plot(sigma_phi(max_sharpe['x']), mu_phi(max_sharpe['x']),
         'v', ms=12.5, label='maximum Sharpe ratio')
plt.xlabel('expected volatility')
plt.ylabel('expected return')
plt.legend();
```


```python
cons = [{'type': 'eq', 'fun': lambda phi: np.sum(phi) - 1},
       {'type': 'eq', 'fun': lambda phi: mu_phi(phi) - target}]
```


```python
bnds = ((0, 1), (0, 1))
```


```python
targets = np.linspace(mu_phi(min_var['x']), 0.16)
```


```python
frontier = []
for target in targets:
    phi_eff = minimize(sigma_phi, (0.5, 0.5),
                       constraints=cons, bounds=bnds)['x']
    frontier.append((sigma_phi(phi_eff), mu_phi(phi_eff)))
frontier = np.array(frontier)
```


```python
plt.figure(figsize=(10, 6))
plt.plot(frontier[:, 0], frontier[:, 1], 'mo', ms=5,
         label='efficient frontier')
plt.plot(sigma_phi(min_var['x']), mu_phi(min_var['x']),
         '^', ms=12.5, label='minimum volatility')
plt.plot(sigma_phi(max_sharpe['x']), mu_phi(max_sharpe['x']),
         'v', ms=12.5, label='maximum Sharpe ratio')
plt.xlabel('expected volatility')
plt.ylabel('expected return')
plt.legend();
```

## Capital Asset Pricing Model


```python
plt.figure(figsize=(10, 6))
plt.plot((0, 0.3), (0.01, 0.22), label='capital market line')
plt.plot(0, 0.01, 'o', ms=9, label='risk-less asset')
plt.plot(0.2, 0.15, '^', ms=9, label='market portfolio')
plt.annotate('$(0, \\bar{r})$', (0, 0.01), (-0.01, 0.02))
plt.annotate('$(\sigma_M, \mu_M)$', (0.2, 0.15), (0.19, 0.16))
plt.xlabel('expected volatility')
plt.ylabel('expected return')
plt.legend();
```


```python
phi_M = np.array((0.8, 0.2))
```


```python
mu_M = mu_phi(phi_M)
mu_M
```


```python
sigma_M = sigma_phi(phi_M)
sigma_M
```


```python
r = 0.0025
```


```python
plt.figure(figsize=(10, 6))
plt.plot(frontier[:, 0], frontier[:, 1], 'm.', ms=5,
         label='efficient frontier')
plt.plot(0, r, 'o', ms=9, label='risk-less asset')
plt.plot(sigma_M, mu_M, '^', ms=9, label='market portfolio')
plt.plot((0, 0.6), (r, r + ((mu_M - r) / sigma_M) * 0.6),
         'r', label='capital market line', lw=2.0)
plt.annotate('$(0, \\bar{r})$', (0, r), (-0.015, r + 0.01))
plt.annotate('$(\sigma_M, \mu_M)$', (sigma_M, mu_M),
             (sigma_M - 0.025, mu_M + 0.01))
plt.xlabel('expected volatility')
plt.ylabel('expected return')
plt.legend();
```


```python
def U(p):
    mu, sigma = p
    return mu - 1 / 2 * (sigma ** 2 + mu ** 2)
```


```python
cons = {'type': 'eq',
        'fun': lambda p: p[0] - (r + (mu_M - r) / sigma_M * p[1])}
```


```python
opt = minimize(lambda p: -U(p), (0.1, 0.3), constraints=cons)
```


```python
opt
```


```python
from sympy import *
init_printing(use_unicode=False, use_latex=False)
```


```python
mu, sigma, b, v = symbols('mu sigma b v')
```


```python
sol = solve('mu - b / 2 * (sigma ** 2 + mu ** 2) - v', mu)
```


```python
sol
```


```python
u1 = sol[0].subs({'b': 1, 'v': 0.1})
u1
```


```python
u2 = sol[0].subs({'b': 1, 'v': 0.125})
u2
```


```python
f1 = lambdify(sigma, u1)
f2 = lambdify(sigma, u2)
```


```python
sigma_ = np.linspace(0.0, 0.5)
u1_ = f1(sigma_)
u2_ = f2(sigma_)
```


```python
plt.figure(figsize=(10, 6))
plt.plot(sigma_, u1_, label='$v=0.1$')
plt.plot(sigma_, u2_, '--', label='$v=0.125$')
plt.xlabel('expected volatility')
plt.ylabel('expected return')
plt.legend();
```


```python
u = sol[0].subs({'b': 1, 'v': -opt['fun']})
u
```


```python
f = lambdify(sigma, u)
```


```python
u_ = f(sigma_)
```


```python
plt.figure(figsize=(10, 6))
plt.plot(0, r, 'o', ms=9, label='risk-less asset')
plt.plot(sigma_M, mu_M, '^', ms=9, label='market portfolio')
plt.plot(opt['x'][1], opt['x'][0], 'v', ms=9, label='optimal portfolio')
plt.plot((0, 0.5), (r, r + (mu_M - r) / sigma_M * 0.5),
         label='capital market line', lw=2.0)
plt.plot(sigma_, u_, '--', label='$v={}$'.format(-round(opt['fun'], 3)))
plt.xlabel('expected volatility')
plt.ylabel('expected return')
plt.legend();
```

## Arbitrage Pricing Theory


```python
M1
```


```python
M0
```


```python
V1 = np.array((12, 15, 7))
```


```python
reg = np.linalg.lstsq(M1, V1, rcond=-1)[0]
reg
```


```python
np.dot(M1, reg)
```


```python
np.dot(M1, reg) - V1
```


```python
V0 = np.dot(M0, reg)
V0
```


```python
U0 = 10
U1 = np.array((12, 5, 11))
```


```python
M0_ = np.array((S0, T0, U0))
```


```python
M1_ = np.concatenate((M1.T, np.array([U1,]))).T
```


```python
M1_
```


```python
np.linalg.matrix_rank(M1_)
```


```python
reg = np.linalg.lstsq(M1_, V1, rcond=-1)[0]
reg
```


```python
np.allclose(np.dot(M1_, reg), V1)
```


```python
V0_ = np.dot(M0_, reg)
V0_
```



<br><br><br><a href="http://tpq.io" target="_blank">http://tpq.io</a> | <a href="http://twitter.com/dyjh" target="_blank">@dyjh</a> | <a href="mailto:ai@tpq.io">ai@tpq.io</a>

a811b7554bd4caa263f653a260bb437e5977626b
ipynb
Jupyter Notebook
03_normative_finance.ipynb
pepelawycliffe/AI_in_Finance
5eb29afed137c809955d116e7a7764b5914add96
MIT
2021-03-15T05:30:50.000Z
2021-12-14T07:28:44.000Z
03_normative_finance.ipynb
pepelawycliffe/AI_in_Finance
5eb29afed137c809955d116e7a7764b5914add96
MIT
03_normative_finance.ipynb
pepelawycliffe/AI_in_Finance
5eb29afed137c809955d116e7a7764b5914add96
MIT
Qwen/Qwen-72B
1. YES
2. YES