Aplicando Python para análisis de precios: probabilidad precio-umbral

Ya habíamos visto como importar precios de cierre de acciones desde Yahoo Finance con la libreria pandas-datareader. En la clase pasada, además, vimos como pronosticar escenarios de evolución de precios suponiendo que los rendimientos diarios distribuyen normalmente. Como esta evolución de precios es aleatoria, utilizaremos la simulación montecarlo (hacer muchas simulaciones de escenarios de evolución de precios) para obtener probabilidades de que los precios de cierre estén encima de un valor umbral y tomar decisiones con base en estas probabilidades.

Referencias:

1. Descargando datos, una vez más

Recordamos una vez más como descargar los precios de cierre ajustados desde yahoo finance.

Esta vez haremos una función.


In [41]:
# Importamos librerías
import numpy as np
import pandas as pd
import pandas_datareader as data
import matplotlib.pyplot as plt
%matplotlib inline

In [42]:
# Creamos la función
def load_adj_close(ticker, data_source, start_date, end_date):
    panel_data = data.DataReader(ticker, data_source, start_date, end_date)
    closes = panel_data.loc['Adj Close']
    all_weekdays = pd.date_range(start=start_date, end=end_date)
    closes = closes.reindex(all_weekdays)
    closes = closes.fillna(method='ffill')
    return closes

In [43]:
# Descargamos datos de microsoft en el 2016
ticker = ['NVDA']
data_source = 'yahoo'
start_date = '2016-01-04'
end_date = '2016-12-31'
closes = load_adj_close(ticker, data_source, start_date, end_date)

In [44]:
# Grafiquemos
closes.plot(figsize=(8,6));


2. Proyección de rendimientos diarios

Recordemos que los precios diarios de cierre ajustados no son un proceso estocástico estacionario, pero los rendimientos diarios si lo son. Por tanto calculamos los rendimientos a partir de los precios de cierre, obtenemos sus propiedades estadísticas muestrales y proyectamos los rendimientos. Luego, obtenemos la proyección de los precios.

Los rendimientos diarios se pueden calcular con los precios de cierre de la siguiente manera:

$$r_i=\frac{p_i-p_{i-1}}{p_{i-1}},$$

donde $r_i$ es el rendimiento en el día $i$ y $p_i$ es el precio de cierre ajustado en el día $i$.

En la clase pasada, vimos que una buena aproximación de la anterior expresión es:

$$r_i=\frac{p_i-p_{i-1}}{p_{i-1}}\approx \ln\left(\frac{p_i}{p_{i-1}}\right).$$

Además, supusimos que los rendimientos diarios eran una variable aleatoria con distribución normal (que se caracteriza con su media y varianza). Por tanto obtenemos la media y desviación estandar muestrales. Hagamos una función que retorne lo anterior.


In [45]:
# Función que devuelve rendimientos diarios, media y desviación estándar
def mu_std_daily_ret(closes):
    daily_returns = (np.log(closes/closes.shift(1)))[1:]
    mu = daily_returns.mean().values[0]
    sigma = daily_returns.std().values[0]
    return daily_returns, mu, sigma

In [46]:
# Calculamos con la función anterior
daily_returns, mu, sigma = mu_std_daily_ret(closes)
mu, sigma


Out[46]:
(0.0033224614879625229, 0.023412153511648267)

In [47]:
# Graficamos rendimientos diarios
daily_returns.plot(figsize=(8,6));


Habiendo caracterizado los rendimientos diarios como una variable aleatoria normal con la media y la varianza muestral obtenida de los datos del 2016, podemos generar números aleatorios con estas características para simular el comportamiento de los precios de cierre de las acciones en el 2017 (hay un supuesto de que las cosas no cambiarán fundamentalmente).

Sin embargo, cada simulación que hagamos nos conducirá a distintos resultados (los precios siguen evolucionando aleatoriamente). Entonces, lo que haremos es simular varios escenarios para así ver alguna tendencia y tomar decisiones.

Hagamos una una función que simule varios escenarios de rendimientos diarios rendimientos diarios y que devuelva un dataframe con esta simulación.


In [49]:
# Función que simula varios escenarios de rendimientos diarios
def daily_ret_sim(mu, sigma, ndays, ntraj, start_date):
    dates = pd.date_range(start=start_date,periods=ndays)
    return pd.DataFrame(sigma*np.random.randn(ndays, ntraj)+mu, index = dates)

In [50]:
# Simulamos 100 escenarios para todo el 2017
ndays = 360
ntraj = 100
start_date = '2017-01-01'
simret = daily_ret_sim(mu, sigma, ndays, ntraj, start_date)

3. Proyección de precios de cierre

Por tanto, para calcular los precios, tenemos:

$$\begin{align} p_i&=p_{i-1}\exp(r_i)\\ p_{i+1}&=p_i\exp(r_{i+1})=p_{i-1}\exp(r_i)\exp(r_{i+1})=p_{i-1}\exp(r_i+r_{i+1})\\ &\vdots\\ p_{i+k}&=p_{i-1}\exp(r_i+\cdots+r_{i+k}). \end{align}$$

Si hacemos $i=0$ en la última ecuación, tenemos que $p_{k}=p_{-1}\exp(r_0+\cdots+r_{k})$, donde $p_{-1}$ es el último precio reportado en el 2016.


In [60]:
# Función de proyección de precios
def closes_proj(simret, closes):
    return (closes.iloc[-1,:].values[0])*np.exp(simret.cumsum())

In [61]:
# Proyección de precios y concatenación con precios de 2016
simdata = closes_proj(simret, closes)
simdata


Out[61]:
0 1 2 3 4 5 6 7 8 9 ... 90 91 92 93 94 95 96 97 98 99
2017-01-01 104.290091 108.133138 109.782872 107.134501 107.764632 103.288117 106.081068 103.293452 105.876880 108.835401 ... 106.128762 107.938030 104.842949 103.745600 104.719794 104.934434 107.232697 110.253253 109.490259 107.185351
2017-01-02 108.429917 109.228866 112.682909 103.465173 108.165405 105.545818 107.567778 102.582912 103.879160 108.141670 ... 107.680695 107.340054 110.253249 104.006348 107.654150 105.428341 109.324474 111.239419 110.954130 106.184627
2017-01-03 109.356456 109.506211 113.948346 103.422131 113.668405 105.513740 110.228045 103.043146 102.140979 110.947842 ... 107.068222 105.237981 115.288563 103.158922 112.193367 105.946107 105.529665 113.873721 112.107024 109.188058
2017-01-04 107.293919 108.639507 113.769500 102.682859 117.881947 103.726287 106.502662 103.860961 103.557860 109.058185 ... 109.409791 104.256522 113.312269 100.521327 113.896108 103.467446 105.059237 109.570771 108.594093 109.381646
2017-01-05 107.137285 110.950648 111.447005 101.763697 117.697896 106.469226 108.688798 106.377002 103.911685 111.615541 ... 114.167637 103.457086 112.668608 100.223725 118.354830 102.034944 106.767514 109.961151 108.153160 112.426606
2017-01-06 108.443659 110.668723 107.165044 101.917733 120.047096 109.570144 105.845417 109.714327 109.995856 114.428665 ... 110.977893 100.825000 112.765111 99.177369 121.925202 100.109656 108.483369 112.232154 110.288365 118.203293
2017-01-07 110.277489 109.652355 110.074629 100.679759 122.585070 109.045113 102.274081 103.050137 109.174788 116.123892 ... 110.496118 102.040956 111.872469 103.912950 118.445791 100.512453 109.624488 110.793830 112.080899 119.920860
2017-01-08 110.732139 108.818133 109.815351 98.614682 119.096748 107.916693 104.943449 102.350502 103.738982 114.604120 ... 109.664644 100.960139 109.481213 108.168359 120.174711 96.955309 107.998814 112.022421 113.126861 118.559203
2017-01-09 113.763875 110.447617 113.983039 99.160134 117.957050 109.881454 102.806656 103.336208 99.580678 115.600827 ... 112.549827 99.559574 105.970866 109.962491 120.966268 95.856206 109.465870 112.393894 111.919839 121.144890
2017-01-10 109.003115 109.568875 115.022221 99.309824 121.115297 108.560510 103.938943 102.827972 98.660738 117.656812 ... 116.208373 100.372567 111.074638 108.666639 117.512674 97.931461 110.719513 117.880358 110.749903 123.887768
2017-01-11 105.883578 106.087847 113.299390 100.822478 123.419779 110.753996 103.415293 97.454593 100.703702 120.445469 ... 114.144856 99.085359 112.357796 107.671079 118.457768 100.463123 110.167062 119.138173 112.058106 126.921992
2017-01-12 102.832000 108.468214 114.389035 102.645974 126.655666 110.850967 101.995322 97.389202 95.551963 123.271415 ... 111.847919 97.395800 111.270447 106.771572 117.081356 103.061069 113.072445 120.519376 114.820038 132.401039
2017-01-13 102.519187 107.941891 114.711491 99.787264 131.701489 110.944809 101.589424 94.360716 99.625379 121.388562 ... 111.394140 97.711647 114.921742 109.438405 120.248557 106.060006 108.924674 121.045799 115.595808 132.063323
2017-01-14 101.458080 113.380691 116.561680 98.094418 137.484222 113.550439 99.370083 92.386026 102.106899 124.465056 ... 110.880932 99.739914 116.771312 107.504725 120.377324 104.834061 107.662232 122.770265 117.684615 134.427291
2017-01-15 100.212436 112.927792 114.310770 98.168600 134.503583 113.868745 100.797365 95.104850 102.966645 125.684502 ... 108.836650 99.434423 122.251239 105.799935 125.965747 106.216540 108.265929 120.368954 119.481835 132.562443
2017-01-16 98.777558 114.317969 114.994688 100.578628 135.753145 114.899708 101.653584 94.465424 101.683694 126.810197 ... 112.966946 98.597335 118.769749 105.161001 120.160971 107.631656 109.763455 121.202748 121.293190 131.798619
2017-01-17 99.480071 117.328986 114.664777 100.448083 132.652429 109.057170 99.111035 96.693247 101.716753 129.216469 ... 116.850376 99.819185 120.426691 107.942338 124.474988 109.027644 112.383494 117.875216 121.365100 130.681216
2017-01-18 102.768926 115.170968 113.437338 104.471836 130.668575 105.872924 101.305401 99.300930 103.416186 129.967564 ... 117.525549 100.119147 123.086660 108.102916 121.052358 111.046538 110.734515 115.161899 123.553247 130.284842
2017-01-19 99.615710 122.744765 116.223923 108.737537 128.650807 110.313639 99.339930 100.558745 102.320684 135.109390 ... 115.537477 105.505840 124.275575 104.302809 120.514500 111.691583 109.663928 115.765376 127.390538 130.710584
2017-01-20 99.376631 121.540068 116.590757 107.413234 128.130747 115.880259 95.566997 99.216461 103.681813 139.106840 ... 114.601877 104.784206 123.740573 99.272456 121.521101 108.044939 115.450585 115.208020 127.956501 129.559675
2017-01-21 96.564350 118.282331 113.606599 106.740154 128.515234 115.581246 94.410893 98.992136 99.935702 139.019004 ... 115.057034 102.877980 121.824294 98.363725 118.689903 107.069428 117.257016 113.224868 128.661271 124.678793
2017-01-22 97.614187 120.730988 115.203030 105.419264 125.421872 113.983158 96.319290 97.231554 100.289237 139.009679 ... 114.133225 104.414455 120.643103 92.600184 114.661293 111.007508 112.815549 111.004797 130.490454 126.518869
2017-01-23 96.216679 115.661245 116.606477 102.558723 128.240311 115.547012 90.883121 97.759943 99.285234 134.213879 ... 111.478352 103.773110 118.508131 95.842163 118.850326 107.657565 111.333526 111.873462 132.065365 128.692979
2017-01-24 97.656819 114.937220 116.531298 101.755794 129.425012 116.190293 91.442378 96.808844 96.893123 136.947231 ... 111.021006 102.748851 120.149063 96.883553 119.272501 108.874576 117.700557 111.219200 129.931443 128.632083
2017-01-25 98.582186 109.273930 116.393423 100.310270 131.617270 117.024854 92.793769 95.449961 97.027075 140.352074 ... 111.348705 103.360930 120.395230 98.898648 124.492932 105.729305 118.899958 113.438527 130.436121 133.595839
2017-01-26 99.189318 107.402469 115.989398 99.770235 138.657128 115.589780 91.577093 96.048263 101.021920 140.147069 ... 112.764974 102.702197 124.202859 99.512035 128.601075 104.775867 121.346043 114.452984 131.192081 133.447235
2017-01-27 103.130319 111.137014 115.343679 97.469282 138.794116 114.477210 90.152781 97.513420 98.472069 142.127654 ... 112.410978 103.183978 123.683588 101.679164 128.474467 100.482024 126.677140 114.180581 132.295455 133.368492
2017-01-28 104.271041 110.174837 115.463377 98.170218 139.388071 118.269708 90.495988 96.733903 99.291716 143.632262 ... 110.421484 103.636525 122.052273 104.102916 126.310157 99.688714 124.323501 110.017647 129.757633 132.931133
2017-01-29 103.130078 113.113745 114.704479 100.628905 138.540732 121.352257 93.541435 95.812889 101.093163 142.507117 ... 110.865440 107.146652 124.424431 100.595100 126.344792 103.200591 124.112114 112.459447 130.406307 135.336008
2017-01-30 106.081787 112.288894 115.225699 106.441345 137.060021 122.231634 92.003730 99.461830 102.466113 138.578120 ... 104.994958 105.728750 124.000689 105.063248 126.112558 103.542699 118.557567 114.448627 131.088227 135.524249
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
2017-11-27 130.295578 603.938064 304.871882 378.054030 561.269396 242.883811 638.191860 273.900960 317.770672 314.985406 ... 448.105174 193.266442 480.819196 126.847492 556.982925 435.826472 586.227838 232.586872 249.880194 299.855859
2017-11-28 130.756866 605.641252 309.242343 371.782157 559.989627 240.012940 671.747854 272.010275 324.515404 315.442716 ... 465.448943 200.484082 466.261486 123.509651 561.588659 445.513854 599.459474 231.418961 250.905398 297.027106
2017-11-29 135.874758 597.459968 320.673561 362.502391 554.354018 242.148931 648.933188 279.679155 315.296912 333.352913 ... 462.471065 201.865383 472.797801 124.220355 562.457751 461.012709 606.340639 229.889495 240.271800 294.033494
2017-11-30 139.033258 587.728747 321.399280 368.160285 525.288517 240.188029 659.554629 290.028802 317.934935 332.282460 ... 446.069145 206.688819 478.386419 121.024805 557.933866 446.667158 608.363901 230.754471 248.070273 291.407141
2017-12-01 135.111012 566.175652 329.961150 376.384989 508.082975 234.700555 679.790517 289.522399 316.718940 333.675478 ... 471.247605 213.399380 487.778163 117.209110 587.624653 462.172732 589.467385 232.642038 247.413527 299.549793
2017-12-02 136.370487 559.394086 332.311622 372.924179 493.958136 238.637088 680.239863 299.434638 328.529717 326.771934 ... 470.259119 217.037534 467.479007 115.273901 584.277046 457.688512 591.554154 232.133209 260.556657 306.853416
2017-12-03 137.128690 564.427477 341.874911 380.682622 483.853311 234.223768 708.795614 316.673511 313.481481 332.231959 ... 464.919461 214.415005 481.824930 119.110995 583.702677 451.288279 563.159427 235.653647 259.236112 312.284353
2017-12-04 129.821285 552.770042 346.598638 384.760371 483.288662 241.522630 729.019084 316.205436 309.499174 330.128888 ... 461.542045 214.478362 480.655517 119.011284 593.868519 465.735675 571.574412 239.096674 261.983681 318.613519
2017-12-05 124.697842 546.772572 355.126465 394.480980 475.949288 249.940830 736.590839 319.995902 311.265461 330.656154 ... 480.198906 210.440671 469.693484 120.172168 598.339771 475.057818 561.726664 245.261328 274.672136 329.164252
2017-12-06 125.030490 551.414418 362.090610 382.531786 471.518394 259.119878 739.403072 333.231713 313.625861 332.091039 ... 473.463568 207.918334 466.967468 122.225260 595.144595 473.310073 552.214891 251.323205 272.931991 332.617442
2017-12-07 125.960680 557.849255 349.913299 392.979757 463.430306 258.229280 734.875079 342.388414 307.726324 343.788510 ... 479.187969 205.586179 470.346678 121.073941 590.721317 462.781261 551.266495 251.607379 276.060755 342.311303
2017-12-08 130.883755 544.738442 352.737632 390.876043 487.774179 262.470013 737.122484 339.825575 295.504788 349.709883 ... 487.838206 201.930970 475.169564 117.934164 609.727093 471.175157 565.367342 251.035208 279.545738 348.531563
2017-12-09 131.555273 530.721730 376.912847 388.965861 495.250150 264.918762 715.596725 340.987689 296.640124 356.794713 ... 491.441691 201.533138 468.518554 118.359293 597.967246 479.063323 561.214761 256.883062 277.626356 338.482205
2017-12-10 124.193428 523.086939 365.290089 374.246104 486.914549 267.390362 681.880946 341.076973 289.670232 358.972996 ... 521.635314 198.187992 491.160223 121.337620 617.924557 493.211005 541.513773 261.426776 290.198791 341.323065
2017-12-11 124.884351 525.067540 367.421924 363.069134 498.127372 271.138607 671.153981 334.668582 281.173341 350.153551 ... 502.862350 201.005568 476.189071 120.315117 612.792139 493.447526 548.451146 271.876255 298.353444 349.948599
2017-12-12 129.782164 507.059140 372.697920 354.879636 506.662859 277.456197 679.122309 328.899814 283.834065 354.383431 ... 511.999506 200.260250 476.996977 118.723203 631.417597 496.508227 551.884805 268.976932 302.140774 355.202421
2017-12-13 126.152194 529.074270 364.605867 348.780664 522.176136 280.218823 685.962205 322.633719 291.255218 356.949739 ... 509.143039 202.943016 470.651206 116.409397 636.188429 479.359055 548.734571 269.613062 299.530302 366.045528
2017-12-14 130.219311 543.186974 375.508228 348.657031 525.498931 285.704098 696.206401 306.064555 291.680691 363.159011 ... 508.848332 204.499869 459.546725 117.584479 630.562333 488.519260 559.013201 265.528481 299.543384 375.908831
2017-12-15 132.796940 530.600513 373.665194 351.416913 533.058445 289.965151 717.451258 300.160138 284.678555 367.284859 ... 506.440295 208.287436 449.579141 120.684930 646.360057 481.780526 549.322744 272.890887 298.891324 369.146510
2017-12-16 131.704154 526.198110 367.301734 352.544694 527.915098 275.635318 690.178116 289.658751 278.315143 373.130298 ... 506.475568 210.570134 444.250117 115.320530 651.378238 483.124836 541.794523 277.988483 293.616405 378.088564
2017-12-17 127.050963 516.559674 378.729436 360.445713 544.832649 274.342920 673.855768 291.664250 281.209915 363.380655 ... 496.846171 210.352202 440.561993 110.615516 686.986246 459.063799 541.967396 270.730920 310.775412 381.297661
2017-12-18 128.912901 521.876615 387.259123 365.277071 524.728223 273.437497 655.312559 287.810637 278.693522 366.857964 ... 475.387499 214.833427 440.681053 107.617718 691.481694 467.376097 540.605063 273.002747 321.693057 366.572033
2017-12-19 122.297189 520.602356 400.154579 360.134232 516.283087 277.398876 653.914159 291.762259 273.803690 365.545869 ... 504.478431 216.533110 442.707813 111.156720 707.010487 481.090611 536.895754 281.856179 316.347324 379.824174
2017-12-20 125.076499 525.519724 398.774981 366.929710 526.954819 266.434071 675.125064 291.946319 267.153946 361.567605 ... 510.401176 212.961216 435.867254 111.181809 678.849378 487.930300 517.367184 277.309572 319.704782 379.446154
2017-12-21 123.843717 517.358456 395.664172 371.281233 509.198286 259.670507 657.282081 288.012729 268.294544 350.986928 ... 498.512391 220.653987 423.141672 106.760284 659.371565 490.711329 518.841898 283.548924 335.280931 375.133058
2017-12-22 121.138265 517.389250 393.428747 366.646159 494.661089 258.987411 656.262871 289.348200 271.586747 348.373678 ... 486.100748 224.382588 420.059938 102.275987 667.953118 488.052958 514.837212 278.132402 332.638248 387.381377
2017-12-23 125.579687 518.492590 396.878531 379.478191 478.952000 262.713666 673.544476 289.151720 257.467600 352.147135 ... 472.246105 225.595891 409.369783 102.309818 688.811634 488.046978 509.721652 280.876623 328.990162 398.535021
2017-12-24 124.929369 500.934268 394.821636 384.103592 477.621375 266.311666 654.803587 293.840579 256.260304 357.536305 ... 455.745243 231.729800 400.554051 104.744664 727.589625 464.795936 497.804485 273.495872 343.998167 397.844820
2017-12-25 126.624804 491.526883 384.280348 378.787005 460.289355 273.453366 680.671173 298.174681 251.691118 350.665654 ... 467.510697 239.323475 403.680517 107.373298 731.364066 466.648053 489.669123 271.505887 355.642311 392.624951
2017-12-26 129.653196 496.546380 387.974913 382.120967 450.854374 280.755156 659.212975 302.327628 254.580085 363.934305 ... 451.958910 249.081920 401.733856 106.346288 755.314462 469.458391 477.424913 273.664101 351.633128 377.960612

360 rows × 100 columns


In [63]:
# Gráfico
simdata.plot(figsize=(8,6),legend=False);


4. Probabilidad Precio-Umbral

Ya que tenemos muchos escenarios de precios proyectados, podemos ver varias cosas. Por ejemplo, ¿cuál es la probabilidad de que el precio de cierre sobrepase algún valor umbral en algún momento?


In [64]:
K = 200
dates = pd.date_range('20170101',periods=ndays)
strike = pd.DataFrame({'Strike':K*np.ones(ndays)},index=dates)
simul = pd.concat([closes.T,simdata.T,strike.T]).T
simul.plot(figsize=(8,6),legend=False);



In [65]:
strike = pd.DataFrame(K*np.ones(ndays*ntraj).reshape((ndays,ntraj)),index=dates)
count = simdata>strike
prob = count.T.sum()/ntraj
prob.plot(figsize=(8,6),legend=False);



In [67]:
((K-closes.iloc[-1,:])/closes.iloc[-1,:]).values


Out[67]:
array([ 0.87970596])

In [66]:
closes.iloc[-1,:]


Out[66]:
NVDA    106.39962
Name: 2016-12-31 00:00:00, dtype: float64

Entonces, ya aprendimos a bajar datos con pandas-datareader. En específico, a partir de los precios de cierre ajustados obtuvimos los rendimientos diarios.

Suponiendo que los rendimientos diarios son un proceso estocástico estacionario de distribución normal, pudimos caracaterizarlo y proyectar varios escenarios de evolución de los precios (montecarlo).

Con estas proyecciones pudimos calcular probabilidades de sobrepasar cierto precio umbral: toma de decisiones.

Recordar... Clase de reposición: mañana Miércoles 18 de Octubre de 16:00-18:00, aula D-206 (Clase de repaso).

  1. Viernes 28 de Octubre y Martes 21 de Noviembre no hay clase.
  2. Clase de reposición: mañana Miércoles 18 de Octubre de 16:00-18:00, aula D-206 (Clase de repaso).
  3. Para el próximo viernes: proyecto definido, subir a moodle un cuaderno con nombre del proyecto, objetivos y una breve introducción.
  4. Tarea la pongo hoy o mañana en la noche.
Created with Jupyter by Esteban Jiménez Rodríguez.