<jupyter_start><jupyter_text>Python for Finance (2nd ed.)**Mastering Data-Driven Finance**&copy; Dr. <NAME> | The Python Quants GmbH  Mathematical Tools  Approximation<jupyter_code>import numpy as np
from pylab import plt, mpl
plt.style.use('seaborn')
mpl.rcParams['font.family'] = 'serif'
%matplotlib inline
def f(x):
    return np.sin(x) + 0.5 * x
def create_plot(x, y, styles, labels, axlabels):
    plt.figure(figsize=(10, 6))
    for i in range(len(x)):
        plt.plot(x[i], y[i], styles[i], label=labels[i])
        plt.xlabel(axlabels[0])
        plt.ylabel(axlabels[1])
    plt.legend(loc=0)
x = np.linspace(-2 * np.pi, 2 * np.pi, 50)  
create_plot([x], [f(x)], ['b'], ['f(x)'], ['x', 'f(x)'])
# plt.savefig('../../images/ch11/math_01.png');<jupyter_output><empty_output><jupyter_text>Regression  Monomials as Basis Functions<jupyter_code>res = np.polyfit(x, f(x), deg=1, full=True)  
res  
ry = np.polyval(res[0], x)  
create_plot([x, x], [f(x), ry], ['b', 'r.'],
            ['f(x)', 'regression'], ['x', 'f(x)'])
# plt.savefig('../../images/ch11/math_02.png');
reg = np.polyfit(x, f(x), deg=5)
ry = np.polyval(reg, x)
create_plot([x, x], [f(x), ry], ['b', 'r.'],
            ['f(x)', 'regression'], ['x', 'f(x)'])
# plt.savefig('../../images/ch11/math_03.png');
reg = np.polyfit(x, f(x), 7)
ry = np.polyval(reg, x)
np.allclose(f(x), ry)  
np.mean((f(x) - ry) ** 2)  
create_plot([x, x], [f(x), ry], ['b', 'r.'],
            ['f(x)', 'regression'], ['x', 'f(x)'])
# plt.savefig('../../images/ch11/math_04.png');<jupyter_output><empty_output><jupyter_text>Individual Basis Functions<jupyter_code>matrix = np.zeros((3 + 1, len(x)))  
matrix[3, :] = x ** 3  
matrix[2, :] = x ** 2  
matrix[1, :] = x  
matrix[0, :] = 1  
reg = np.linalg.lstsq(matrix.T, f(x), rcond=None)[0]  
reg.round(4)  
ry = np.dot(reg, matrix)  
create_plot([x, x], [f(x), ry], ['b', 'r.'],
            ['f(x)', 'regression'], ['x', 'f(x)'])
# plt.savefig('../../images/ch11/math_05.png');
matrix[3, :] = np.sin(x)  
reg = np.linalg.lstsq(matrix.T, f(x), rcond=None)[0]
reg.round(4)  
ry = np.dot(reg, matrix)
np.allclose(f(x), ry)  
np.mean((f(x) - ry) ** 2)  
create_plot([x, x], [f(x), ry], ['b', 'r.'],
            ['f(x)', 'regression'], ['x', 'f(x)'])
# plt.savefig('../../images/ch11/math_06.png');<jupyter_output><empty_output><jupyter_text>Noisy Data<jupyter_code>xn = np.linspace(-2 * np.pi, 2 * np.pi, 50)  
xn = xn + 0.15 * np.random.standard_normal(len(xn))  
yn = f(xn) + 0.25 * np.random.standard_normal(len(xn))  
reg = np.polyfit(xn, yn, 7)
ry = np.polyval(reg, xn)
create_plot([x, x], [f(x), ry], ['b', 'r.'],
            ['f(x)', 'regression'], ['x', 'f(x)'])
# plt.savefig('../../images/ch11/math_07.png');<jupyter_output><empty_output><jupyter_text>Unsorted Data<jupyter_code>xu = np.random.rand(50) * 4 * np.pi - 2 * np.pi  
yu = f(xu)
print(xu[:10].round(2))  
print(yu[:10].round(2))  
reg = np.polyfit(xu, yu, 5)
ry = np.polyval(reg, xu)
create_plot([xu, xu], [yu, ry], ['b.', 'ro'],
            ['f(x)', 'regression'], ['x', 'f(x)'])
# plt.savefig('../../images/ch11/math_08.png');<jupyter_output><empty_output><jupyter_text>Multiple Dimensions<jupyter_code>def fm(p):
    x, y = p
    return np.sin(x) + 0.25 * x + np.sqrt(y) + 0.05 * y ** 2
x = np.linspace(0, 10, 20)
y = np.linspace(0, 10, 20)
X, Y = np.meshgrid(x, y)  
Z = fm((X, Y))
x = X.flatten()  
y = Y.flatten()  
from mpl_toolkits.mplot3d import Axes3D  
fig = plt.figure(figsize=(10, 6))
ax = fig.gca(projection='3d')
surf = ax.plot_surface(X, Y, Z, rstride=2, cstride=2,
                       cmap='coolwarm', linewidth=0.5,
                       antialiased=True)
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('f(x, y)')
fig.colorbar(surf, shrink=0.5, aspect=5)
# plt.savefig('../../images/ch11/math_09.png');
matrix = np.zeros((len(x), 6 + 1))
matrix[:, 6] = np.sqrt(y)  
matrix[:, 5] = np.sin(x)  
matrix[:, 4] = y ** 2
matrix[:, 3] = x ** 2
matrix[:, 2] = y
matrix[:, 1] = x
matrix[:, 0] = 1
reg = np.linalg.lstsq(matrix, fm((x, y)), rcond=None)[0]
RZ = np.dot(matrix, reg).reshape((20, 20))  
fig = plt.figure(figsize=(10, 6))
ax = fig.gca(projection='3d')
surf1 = ax.plot_surface(X, Y, Z, rstride=2, cstride=2,
            cmap=mpl.cm.coolwarm, linewidth=0.5,
            antialiased=True)  
surf2 = ax.plot_wireframe(X, Y, RZ, rstride=2, cstride=2,
                          label='regression')  
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('f(x, y)')
ax.legend()
fig.colorbar(surf, shrink=0.5, aspect=5)
# plt.savefig('../../images/ch11/math_10.png');<jupyter_output><empty_output><jupyter_text>Interpolation<jupyter_code>import scipy.interpolate as spi  
x = np.linspace(-2 * np.pi, 2 * np.pi, 25)
def f(x):
    return np.sin(x) + 0.5 * x
ipo = spi.splrep(x, f(x), k=1)  
iy = spi.splev(x, ipo)  
np.allclose(f(x), iy)  
create_plot([x, x], [f(x), iy], ['b', 'ro'],
            ['f(x)', 'interpolation'], ['x', 'f(x)'])
# plt.savefig('../../images/ch11/math_11.png');
xd = np.linspace(1.0, 3.0, 50)  
iyd = spi.splev(xd, ipo)
create_plot([xd, xd], [f(xd), iyd], ['b', 'ro'],
            ['f(x)', 'interpolation'], ['x', 'f(x)'])
# plt.savefig('../../images/ch11/math_12.png');
ipo = spi.splrep(x, f(x), k=3)  
iyd = spi.splev(xd, ipo)  
np.allclose(f(xd), iyd)  
np.mean((f(xd) - iyd) ** 2)  
create_plot([xd, xd], [f(xd), iyd], ['b', 'ro'],
            ['f(x)', 'interpolation'], ['x', 'f(x)'])
# plt.savefig('../../images/ch11/math_13.png');<jupyter_output><empty_output><jupyter_text>Convex Optimization<jupyter_code>def fm(p):
    x, y = p
    return (np.sin(x) + 0.05 * x ** 2
          + np.sin(y) + 0.05 * y ** 2)
x = np.linspace(-10, 10, 50)
y = np.linspace(-10, 10, 50)
X, Y = np.meshgrid(x, y)
Z = fm((X, Y))
fig = plt.figure(figsize=(10, 6))
ax = fig.gca(projection='3d')
surf = ax.plot_surface(X, Y, Z, rstride=2, cstride=2,
                       cmap='coolwarm', linewidth=0.5,
                       antialiased=True)
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('f(x, y)')
fig.colorbar(surf, shrink=0.5, aspect=5)
# plt.savefig('../../images/ch11/math_14.png');<jupyter_output><empty_output><jupyter_text>Global Optimization<jupyter_code>import scipy.optimize as sco  
def fo(p):
    x, y = p
    z = np.sin(x) + 0.05 * x ** 2 + np.sin(y) + 0.05 * y ** 2
    if output == True:
        print('%8.4f | %8.4f | %8.4f' % (x, y, z))  
    return z
output = True
sco.brute(fo, ((-10, 10.1, 5), (-10, 10.1, 5)), finish=None)  
output = False
opt1 = sco.brute(fo, ((-10, 10.1, 0.1), (-10, 10.1, 0.1)), finish=None)
opt1
fm(opt1)<jupyter_output><empty_output><jupyter_text>Local Optimization<jupyter_code>output = True
opt2 = sco.fmin(fo, opt1, xtol=0.001, ftol=0.001,
                maxiter=15, maxfun=20)  
opt2
fm(opt2)
output = False
sco.fmin(fo, (2.0, 2.0), maxiter=250)<jupyter_output>Optimization terminated successfully.
         Current function value: 0.015826
         Iterations: 46
         Function evaluations: 86<jupyter_text>Constrained Optimization<jupyter_code>import math
def Eu(p):  
    s, b = p
    return -(0.5 * math.sqrt(s * 15 + b * 5) +
             0.5 * math.sqrt(s * 5 + b * 12))
cons = ({'type': 'ineq',
         'fun': lambda p: 100 - p[0] * 10 - p[1] * 10})  
bnds = ((0, 1000), (0, 1000))  
result = sco.minimize(Eu, [5, 5], method='SLSQP',
                       bounds=bnds, constraints=cons)  
result
result['x']  
-result['fun']  
np.dot(result['x'], [10, 10])<jupyter_output><empty_output><jupyter_text>Integration<jupyter_code>import scipy.integrate as sci
def f(x):
    return np.sin(x) + 0.5 * x
x = np.linspace(0, 10)
y = f(x)
a = 0.5  
b = 9.5  
Ix = np.linspace(a, b)  
Iy = f(Ix)  #  <4>
from matplotlib.patches import Polygon
fig, ax = plt.subplots(figsize=(10, 6))
plt.plot(x, y, 'b', linewidth=2)
plt.ylim(bottom=0)
Ix = np.linspace(a, b)
Iy = f(Ix)
verts = [(a, 0)] + list(zip(Ix, Iy)) + [(b, 0)]
poly = Polygon(verts, facecolor='0.7', edgecolor='0.5')
ax.add_patch(poly)
plt.text(0.75 * (a + b), 1.5, r"$\int_a^b f(x)dx$",
         horizontalalignment='center', fontsize=20)
plt.figtext(0.9, 0.075, '$x$')
plt.figtext(0.075, 0.9, '$f(x)$')
ax.set_xticks((a, b))
ax.set_xticklabels(('$a$', '$b$'))
ax.set_yticks([f(a), f(b)]);
# plt.savefig('../../images/ch11/math_15.png');<jupyter_output><empty_output><jupyter_text>Numerical Integration<jupyter_code>sci.fixed_quad(f, a, b)[0]
sci.quad(f, a, b)[0]
sci.romberg(f, a, b)
xi = np.linspace(0.5, 9.5, 25)
sci.trapz(f(xi), xi)
sci.simps(f(xi), xi)<jupyter_output><empty_output><jupyter_text>Integration by Simulation<jupyter_code>for i in range(1, 20):
    np.random.seed(1000)
    x = np.random.random(i * 10) * (b - a) + a  
    print(np.mean(f(x)) * (b - a))<jupyter_output>24.804762279331463
26.522918898332378
26.265547519223976
26.02770339943824
24.99954181440844
23.881810141621663
23.527912274843253
23.507857658961207
23.67236746066989
23.679410416062886
24.424401707879305
24.239005346819056
24.115396924962802
24.424191987566726
23.924933080533783
24.19484212027875
24.117348378249833
24.100690929662274
23.76905109847816<jupyter_text>Symbolic Computation  Basics<jupyter_code>import sympy as sy
x = sy.Symbol('x')  
y = sy.Symbol('y')  
type(x)
sy.sqrt(x)  
3 + sy.sqrt(x) - 4 ** 2  
f = x ** 2 + 3 + 0.5 * x ** 2 + 3 / 2  
sy.simplify(f)  
sy.init_printing(pretty_print=False, use_unicode=False)
print(sy.pretty(f))
print(sy.pretty(sy.sqrt(x) + 0.5))
%time pi_str = str(sy.N(sy.pi, 400000))  
pi_str[:42]  
pi_str[-40:]  
%time pi_str.find('061072')<jupyter_output>CPU times: user 89 µs, sys: 0 ns, total: 89 µs
Wall time: 94.2 µs<jupyter_text>Equations<jupyter_code>sy.solve(x ** 2 - 1)
sy.solve(x ** 2 - 1 - 3)
sy.solve(x ** 3 + 0.5 * x ** 2 - 1)
sy.solve(x ** 2 + y ** 2)<jupyter_output><empty_output><jupyter_text>Integration and Differentiation<jupyter_code>a, b = sy.symbols('a b')  
I = sy.Integral(sy.sin(x) + 0.5 * x, (x, a, b))  
print(sy.pretty(I))  
int_func = sy.integrate(sy.sin(x) + 0.5 * x, x)  
print(sy.pretty(int_func))  
Fb = int_func.subs(x, 9.5).evalf()  
Fa = int_func.subs(x, 0.5).evalf()  
Fb - Fa  
int_func_limits = sy.integrate(sy.sin(x) + 0.5 * x, (x, a, b))  
print(sy.pretty(int_func_limits))  
int_func_limits.subs({a : 0.5, b : 9.5}).evalf()  
sy.integrate(sy.sin(x) + 0.5 * x, (x, 0.5, 9.5))<jupyter_output><empty_output><jupyter_text>Differentiation<jupyter_code>int_func.diff()
f = (sy.sin(x) + 0.05 * x ** 2
   + sy.sin(y) + 0.05 * y ** 2)  
del_x = sy.diff(f, x)  
del_x  
del_y = sy.diff(f, y)  
del_y  
xo = sy.nsolve(del_x, -1.5)  
xo  
yo = sy.nsolve(del_y, -1.5)  
yo  
f.subs({x : xo, y : yo}).evalf()  
xo = sy.nsolve(del_x, 1.5)
xo
yo = sy.nsolve(del_y, 1.5)  
yo
f.subs({x : xo, y : yo}).evalf()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.22589995324918186, 'fraction_numerical': 0.07424029920523609, 'mean_word_length': 3.656508489333914, 'pattern_counts': {'":': 0, '<': 72, '<?xml version=': 0, '>': 72, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '18', 'dir': 'jupyter-structured-clean-dedup', 'id': '117001', 'license': 'CNRI-Python', 'n_tokens_mistral': 5421, 'n_tokens_neox': 4934, 'n_words': 909, 'path': 'code/ch11/11_math_tools.ipynb', 'repo_name': 'saltyspades/pythonforfinance', 'size': '10705'}