Aplicando Python para análisis de precios: simulación de escenarios futuros de precios

En la clase anterior vimos como importar datos de activos de la base de datos de Yahoo Finance, tanto descargándolos como archivos separados por comas (.csv), como usando el paquete pandas-datareader. En esta clase, veremos como pronosticar escenarios de evolución de precios, suponiendo que los rendimientos diarios se distribuyen normalmente.

Referencias:

1. Motivación

Hace menos de una década, los instrumentos financieros estaban en la cúspide de la popularidad. Las instituciones financieras de todo el mundo estaban negociando miles de millones de dólares de estos instrumentos a diario, y los analistas cuantitativos estaban modelándolos utilizando el cálculo estocástico y el poderoso C++.

Sin embargo, el avance en los últimos años ha sido impresionante y las cosas han cambiado. Por una parte, la crisis financiera del 2008 fue producida por los instrumentos financieros llamados derivados. Por otra parte, los volúmenes transaccionales han bajado y la demanda de modelado con C++ se ha marchitado con ellos. Además, un nuevo jugador entró en la competencia... ¡Python!

Python ha estado ganando muchos seguidores en la industria financiera en los últimos años y con razón. No en vano, junto a R son los lenguajes de programación más utilizados en cuanto a análisis financiero.

2. Recordemos como descargar datos...

Antes que nada, para poder hacer simular escenarios de predicción de precios, vamos a recordar lo que hicimos en la clase pasada de descargar los datos de Yahoo Finance, utilizando el paquete data de la librería pandas_datareader.

Esta vez, utilizaremos los datos de precios de cierre ajustados de activos de la compañía Apple en el año 2016 para nuestra aplicación.


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

In [16]:
# Descargamos datos...
# Instrumento: Apple
ticker = ['AAPL']
# Fuente: Yahoo Finance
data_source = 'yahoo'
# Fechas de interés (inicio y fin): 2016
start_date = '2016-01-04'
end_date = '2016-12-31'
# Función DataReader
panel_data = data.DataReader(ticker, data_source, start_date, end_date)

In [17]:
# Solo nos interesa los precios de cierre ajustados...
closes = panel_data.loc['Adj Close']
# Generamos todos los días del 2016 en orden
all_weekdays = pd.date_range(start_date, end_date)
# Reindizamos
closes = closes.reindex(all_weekdays)
# Llenamos huecos en los precios de cierre
closes = closes.fillna(method='ffill')

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


3. Rendimientos diarios

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$.

Ver en el pizarrón: aproximación con logaritmo, además mencionar validez estadística suponiendo distribución lognormal.

Entonces, los rendimientos diarios se pueden calcular como:


In [25]:
# Función para calcular los rendimientos diarios a partir de los precios de cierre...
def calc_daily_returns(closes):
    return np.log(closes/closes.shift(1))[1:]

In [28]:
# Calcular rendimientos diarios y graficarlos
daily_returns = calc_daily_returns(closes)
daily_returns.plot(figsize=(8,6));


Entonces, suponemos que la diferencia logaritmica de los precios (rendimientos diarios) tiene una distribución normal.

¿Cómo se caracteriza una distribución normal?


In [29]:
mu=daily_returns.mean().AAPL
sigma=daily_returns.std().AAPL
mu, sigma


Out[29]:
(0.00032252606319594702, 0.012278733453628314)

4. Simulación de varios escenarios

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 las acciones en el 2017.

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 (próxima clase).

Pero, ¿cómo generar vectores de números aleatorios que distribuyen normalmente con una media y varianza dadas?


In [5]:
help(np.random.randn)


Help on built-in function randn:

randn(...) method of mtrand.RandomState instance
    randn(d0, d1, ..., dn)
    
    Return a sample (or samples) from the "standard normal" distribution.
    
    If positive, int_like or int-convertible arguments are provided,
    `randn` generates an array of shape ``(d0, d1, ..., dn)``, filled
    with random floats sampled from a univariate "normal" (Gaussian)
    distribution of mean 0 and variance 1 (if any of the :math:`d_i` are
    floats, they are first converted to integers by truncation). A single
    float randomly sampled from the distribution is returned if no
    argument is provided.
    
    This is a convenience function.  If you want an interface that takes a
    tuple as the first argument, use `numpy.random.standard_normal` instead.
    
    Parameters
    ----------
    d0, d1, ..., dn : int, optional
        The dimensions of the returned array, should be all positive.
        If no argument is given a single Python float is returned.
    
    Returns
    -------
    Z : ndarray or float
        A ``(d0, d1, ..., dn)``-shaped array of floating-point samples from
        the standard normal distribution, or a single such float if
        no parameters were supplied.
    
    See Also
    --------
    random.standard_normal : Similar, but takes a tuple as its argument.
    
    Notes
    -----
    For random samples from :math:`N(\mu, \sigma^2)`, use:
    
    ``sigma * np.random.randn(...) + mu``
    
    Examples
    --------
    >>> np.random.randn()
    2.1923875335537315 #random
    
    Two-by-four array of samples from N(3, 6.25):
    
    >>> 2.5 * np.random.randn(2, 4) + 3
    array([[-4.49401501,  4.00950034, -1.81814867,  7.29718677],  #random
           [ 0.39924804,  4.68456316,  4.99394529,  4.84057254]]) #random

Generamos un data frame de rendimientos diarios proyectados (10 trayectorias)


In [33]:
ndays = 360
ntraj=10
dates=pd.date_range('20170101',periods=ndays)
simret = pd.DataFrame(sigma*np.random.randn(ndays,ntraj)+mu,index=dates)
simret


Out[33]:
0 1 2 3 4 5 6 7 8 9
2017-01-01 0.001635 -0.009805 -0.017782 0.009676 -0.004888 0.002540 0.008746 0.012359 0.013965 -0.011846
2017-01-02 0.026196 -0.004280 -0.000222 -0.014662 -0.015916 0.003292 0.015374 0.002333 -0.010639 0.022012
2017-01-03 0.001157 0.011639 0.004739 -0.004335 -0.005158 -0.030909 -0.029466 0.003240 0.004610 0.005462
2017-01-04 0.014833 0.011974 0.003052 0.012743 0.011755 0.018015 0.004187 0.002654 0.000491 -0.021645
2017-01-05 -0.009603 -0.029719 0.023247 0.007783 0.007477 0.010282 0.000222 -0.005886 -0.004087 0.020534
2017-01-06 0.004296 0.010370 0.005441 0.021967 0.001707 -0.002056 0.021941 0.004952 -0.002793 0.014643
2017-01-07 -0.001130 0.017210 0.018686 -0.005758 0.012695 -0.026993 -0.004309 -0.003507 0.021019 0.009641
2017-01-08 -0.017076 0.003059 0.006499 -0.004242 0.017326 0.000968 0.003835 -0.011881 -0.016687 -0.004275
2017-01-09 0.013656 0.014024 0.016472 0.013918 -0.012474 0.011353 -0.011358 0.001590 0.006316 0.017131
2017-01-10 0.017973 0.012252 -0.003146 0.000181 0.006700 0.012226 -0.006764 0.003978 0.005186 0.003637
2017-01-11 0.011986 -0.006766 -0.002177 -0.008032 0.003820 -0.019233 -0.003324 0.003967 -0.013692 -0.006229
2017-01-12 -0.019501 0.000312 -0.014076 0.004491 -0.004520 0.008112 -0.006794 0.029027 -0.006161 0.002583
2017-01-13 0.010174 -0.002632 -0.003349 0.018712 0.012899 0.015045 0.006782 -0.000629 -0.026083 0.004304
2017-01-14 -0.002599 -0.011145 0.011550 -0.004617 0.001870 0.015886 0.019708 0.009834 0.012653 0.009668
2017-01-15 -0.015208 -0.000832 0.014985 0.014446 -0.015531 -0.016650 0.000757 0.007868 -0.003239 0.010871
2017-01-16 0.012466 -0.001309 0.007323 -0.014597 0.010634 0.001879 -0.015696 0.001069 -0.002184 0.014792
2017-01-17 0.002546 -0.011002 -0.006634 -0.011102 -0.001530 -0.007483 0.000989 0.012210 0.000114 0.017578
2017-01-18 0.006659 -0.017985 0.004048 -0.003895 -0.012751 0.001868 -0.001618 -0.001637 -0.005030 0.021775
2017-01-19 0.013234 0.014969 0.005220 -0.015106 0.019113 0.018295 0.030389 0.019503 0.002661 -0.004833
2017-01-20 -0.013008 0.000460 -0.006082 0.001730 0.005206 0.025067 0.001559 -0.009832 -0.016421 0.008000
2017-01-21 0.005161 -0.001504 0.003882 0.010115 0.002668 0.011422 -0.026077 0.010940 -0.009660 0.004939
2017-01-22 -0.009079 -0.018114 -0.003165 -0.002671 -0.007284 0.010555 0.020110 0.000251 0.008224 -0.011758
2017-01-23 0.005465 0.003654 -0.004430 -0.000569 0.006121 0.021166 -0.007490 0.009120 0.012208 0.005613
2017-01-24 0.001611 -0.000328 0.013454 0.003264 -0.010833 -0.007116 -0.013008 -0.009764 0.037963 -0.002116
2017-01-25 0.015743 0.013642 -0.001552 0.001998 0.019844 -0.008015 -0.017601 -0.004407 -0.000271 0.019447
2017-01-26 -0.014317 0.008864 0.012776 0.019172 0.000217 -0.008575 0.017964 0.000417 0.021091 -0.014189
2017-01-27 0.016546 -0.006578 -0.001065 -0.003888 0.000021 -0.020072 0.012768 0.016908 -0.004452 -0.026215
2017-01-28 -0.003563 0.011343 -0.023083 0.009566 0.001271 -0.000712 0.011130 -0.003756 -0.009444 -0.006764
2017-01-29 -0.009841 0.004236 0.000059 -0.001138 0.008783 -0.011061 0.003415 0.001657 -0.016416 0.001230
2017-01-30 -0.004130 0.008675 -0.015378 -0.009291 0.011943 0.001601 0.017542 -0.019090 -0.005568 -0.001849
... ... ... ... ... ... ... ... ... ... ...
2017-11-27 0.007556 -0.011841 0.009909 0.004305 -0.011312 -0.015307 0.010652 -0.003567 -0.006457 0.002033
2017-11-28 -0.014438 -0.007346 -0.022481 0.000631 0.009699 0.003930 0.006814 0.003454 0.009840 -0.008614
2017-11-29 -0.014526 -0.003500 0.024960 -0.006093 -0.000635 0.003847 -0.016097 0.000096 -0.001193 0.002449
2017-11-30 -0.016050 0.025307 0.002347 0.020145 -0.018988 0.002838 -0.006594 0.026106 -0.008405 -0.016111
2017-12-01 0.011158 -0.001659 -0.000366 -0.014142 -0.006841 0.011968 -0.004281 0.008911 -0.011338 0.011404
2017-12-02 0.018667 0.009638 -0.010837 -0.002440 0.000109 0.000715 0.013715 -0.007542 -0.006603 -0.010332
2017-12-03 0.009941 0.014621 -0.019942 0.005058 -0.003502 0.005676 -0.005833 0.008129 -0.015009 0.004568
2017-12-04 0.001559 -0.008312 -0.011307 0.005147 -0.019394 -0.013827 0.009281 0.008066 0.001154 0.005752
2017-12-05 0.005204 -0.005849 -0.006936 0.015428 0.002972 0.004435 -0.003698 0.003228 0.008106 -0.003678
2017-12-06 0.019090 -0.008847 0.005056 -0.007084 0.003637 -0.012323 0.015219 0.003825 0.002709 0.018603
2017-12-07 -0.002101 0.001946 0.002757 -0.016052 -0.001441 -0.010461 0.004290 0.005848 0.009367 -0.014643
2017-12-08 0.000135 0.014434 -0.006115 -0.014371 0.025172 0.018693 0.015314 0.003224 -0.010508 -0.007256
2017-12-09 -0.003299 -0.003622 -0.005240 -0.015726 -0.000399 -0.001157 0.027594 0.009925 0.003248 -0.010676
2017-12-10 -0.012277 0.014550 -0.004148 -0.032955 0.012771 0.009280 0.002404 0.010939 0.002052 -0.001851
2017-12-11 0.000301 0.012803 0.023424 -0.011778 0.017059 -0.013463 -0.006297 0.030367 -0.008242 0.008615
2017-12-12 0.019381 -0.011218 -0.011620 -0.006458 -0.007801 -0.001653 -0.009326 -0.008934 0.019987 0.003965
2017-12-13 0.013960 0.008187 -0.004795 -0.010864 -0.007743 -0.012740 0.008036 0.016236 0.002573 0.005652
2017-12-14 -0.013984 0.001737 0.022147 0.002454 0.011253 0.026602 0.013948 0.013234 -0.002109 0.005229
2017-12-15 0.006357 -0.006640 -0.005520 0.001869 -0.012127 -0.020225 -0.001572 -0.011891 0.001727 0.011958
2017-12-16 0.007895 0.016826 0.013639 0.022095 0.015367 -0.006510 -0.000359 -0.005531 -0.008543 0.005717
2017-12-17 0.023831 -0.008335 -0.002538 -0.013271 0.004330 0.018406 0.016581 0.011025 0.017743 -0.002915
2017-12-18 -0.009995 -0.011326 0.015698 0.000619 0.013311 -0.007340 0.002196 0.023186 0.020098 -0.003940
2017-12-19 0.042686 -0.000483 0.010491 0.021548 0.002753 0.006897 -0.006826 0.021217 0.003688 -0.014165
2017-12-20 0.013124 0.009801 0.009783 0.011403 -0.002770 0.010050 -0.011645 0.017482 0.003255 0.000536
2017-12-21 -0.023554 0.031473 0.005506 -0.000976 -0.018106 0.003397 0.001772 -0.003138 -0.017946 -0.015982
2017-12-22 0.001204 -0.017023 0.009463 0.017953 0.014322 0.011161 0.001696 0.017773 0.015775 0.006945
2017-12-23 -0.010608 0.019001 0.012828 -0.023677 -0.023595 0.003758 -0.017105 -0.000509 0.006760 -0.005219
2017-12-24 0.012809 0.006851 0.006450 0.004138 0.011743 0.011899 -0.011566 -0.004584 -0.000184 0.001979
2017-12-25 0.000524 -0.003675 -0.003900 -0.016397 0.008392 0.003099 0.002630 0.009348 0.000496 -0.004760
2017-12-26 0.007524 0.013518 0.022000 -0.009571 -0.028486 0.017769 0.024975 -0.019487 -0.005518 -0.003951

360 rows × 10 columns

Con los rendimientos, calculamos los precios de cierre... (explicar en el tablero)


In [34]:
simdata=(closes.loc['2016-12-30',:].AAPL)*np.exp(simret.cumsum())
simdata


Out[34]:
0 1 2 3 4 5 6 7 8 9
2017-01-01 114.583898 113.280617 112.380542 115.508992 113.838944 114.687720 115.401667 115.819331 116.005530 113.049609
2017-01-02 117.625225 112.796831 112.355545 113.827773 112.041371 115.065837 117.189527 116.089826 114.777848 115.565620
2017-01-03 117.761349 114.117323 112.889297 113.335412 111.464991 111.563680 113.786846 116.466586 115.308251 116.198584
2017-01-04 119.521093 115.492011 113.234327 114.788845 112.782940 113.591702 114.264306 116.776120 115.364829 113.710535
2017-01-05 118.378846 112.110228 115.897468 115.685727 113.629372 114.765689 114.289629 116.090813 114.894347 116.069630
2017-01-06 118.888501 113.278886 116.529735 118.255151 113.823533 114.530020 116.824953 116.667111 114.573887 117.781684
2017-01-07 118.754185 115.245287 118.727703 117.576149 115.277680 111.479893 116.322661 116.258629 117.007592 118.922709
2017-01-08 116.743571 115.598358 119.501769 117.078472 117.292441 111.587856 116.769599 114.885484 115.071322 118.415427
2017-01-09 118.348698 117.230916 121.486529 118.719393 115.838434 112.861959 115.450870 115.068355 115.800450 120.461535
2017-01-10 120.494987 118.676055 121.104893 118.740843 116.617167 114.250306 114.672570 115.526976 116.402551 120.900411
2017-01-11 121.947919 117.875811 120.841522 117.790952 117.063462 112.073968 114.292003 115.986187 114.819610 120.149653
2017-01-12 119.592829 117.912639 119.152433 118.321117 116.535561 112.986866 113.518168 119.402306 114.114343 120.460405
2017-01-13 120.815761 117.602758 118.754033 120.555989 118.048483 114.699576 114.290627 119.327169 111.176395 120.979941
2017-01-14 120.502143 116.299354 120.133653 120.000658 118.269460 116.536253 116.565463 120.506379 112.592065 122.155268
2017-01-15 118.683438 116.202626 121.947411 121.746786 116.446795 114.612018 116.653720 121.458253 112.227965 123.490401
2017-01-16 120.172264 116.050563 122.843735 119.982608 117.691722 114.827523 114.837052 121.588100 111.983181 125.330644
2017-01-17 120.478648 114.780756 122.031470 118.657913 117.511751 113.971515 114.950692 123.081813 111.995960 127.553145
2017-01-18 121.283559 112.734873 122.526408 118.196615 116.022835 114.184654 114.764832 122.880543 111.434047 130.361126
2017-01-19 122.899299 114.435090 123.167656 116.424521 118.261747 116.292910 118.305928 125.300640 111.731021 129.732675
2017-01-20 121.310950 114.487723 122.420851 116.626084 118.879005 119.244884 118.490542 124.074691 109.911218 130.774716
2017-01-21 121.938664 114.315635 122.896980 117.811790 119.196563 120.614661 115.440658 125.439481 108.854580 131.422182
2017-01-22 120.836570 112.263540 122.508593 117.497482 118.331471 121.894446 117.785692 125.470947 109.753440 129.885986
2017-01-23 121.498807 112.674550 121.967086 117.430593 119.058044 124.502015 116.906820 126.620432 111.101553 130.617064
2017-01-24 121.694711 112.637650 123.619098 117.814505 117.775243 123.619149 115.395939 125.390113 115.400330 130.341031
2017-01-25 123.625686 114.184732 123.427422 118.050128 120.135659 122.632294 113.382665 124.838709 115.369048 132.900557
2017-01-26 121.868345 115.201349 125.014459 120.335163 120.161686 121.585264 115.437861 124.890772 117.828087 131.028172
2017-01-27 123.901580 114.446079 124.881412 119.868204 120.164200 119.169126 116.921238 127.020398 117.304683 127.637915
2017-01-28 123.460893 115.751607 122.031812 121.020374 120.317065 119.084357 118.229860 126.544163 116.202102 126.777462
2017-01-29 122.251836 116.242997 122.038991 120.882768 121.378407 117.774470 118.634303 126.754077 114.310114 126.933515
2017-01-30 121.748024 117.255764 120.176600 119.764800 122.836751 117.963200 120.733796 124.357282 113.675432 126.698999
... ... ... ... ... ... ... ... ... ... ...
2017-11-27 127.650523 155.741106 154.030467 122.280864 116.728320 145.340958 120.808242 98.322406 100.394299 213.350798
2017-11-28 125.820727 154.601278 150.606341 122.358071 117.865942 145.913218 121.634273 98.662648 101.387045 211.520796
2017-11-29 124.006251 154.061087 154.412838 121.614832 117.791080 146.475627 119.692050 98.672115 101.266119 212.039352
2017-11-30 122.031865 158.009704 154.775711 124.089648 115.575541 146.891979 118.905390 101.281935 100.418506 208.650506
2017-12-01 123.401165 157.747748 154.719080 122.347081 114.787578 148.660557 118.397496 102.188480 99.286380 211.043621
2017-12-02 125.726317 159.275489 153.051425 122.048882 114.800065 148.766912 120.032522 101.420683 98.632981 208.874241
2017-12-03 126.982426 161.621307 150.029455 122.667804 114.398727 149.613654 119.334460 102.248451 97.163684 209.830607
2017-12-04 127.180561 160.283475 148.342621 123.300744 112.201416 147.559116 120.447158 103.076513 97.275861 211.041114
2017-12-05 127.844095 159.348652 147.317349 125.217785 112.535364 148.214980 120.002584 103.409812 98.067598 210.266364
2017-12-06 130.308028 157.945073 148.064027 124.333869 112.945391 146.399791 121.842930 103.806145 98.333652 214.214638
2017-12-07 130.034479 158.252752 148.472823 122.353976 112.782738 144.876251 122.366724 104.414979 99.259081 211.100704
2017-12-08 130.052099 160.553608 147.567627 120.608176 115.657704 147.609825 124.255098 104.752152 98.221529 209.574436
2017-12-09 129.623759 159.973105 146.796354 118.726311 115.611525 147.439134 127.731511 105.796946 98.541059 207.348885
2017-12-10 128.042111 162.317672 146.188763 114.877472 117.097427 148.813666 128.038931 106.960607 98.743511 206.965471
2017-12-11 128.080640 164.409264 149.653569 113.532411 119.112091 146.823661 127.235147 110.258537 97.932987 208.756215
2017-12-12 130.587202 162.575196 147.924600 112.801578 118.186507 146.581221 126.054102 109.277874 99.910105 209.585576
2017-12-13 132.422969 163.911703 147.216976 111.582754 117.274901 144.725663 127.071183 111.066623 100.167459 210.773608
2017-12-14 130.584059 164.196657 150.513755 111.856888 118.602069 148.627358 128.856043 112.546272 99.956429 211.878703
2017-12-15 131.416834 163.110050 149.685151 112.066127 117.172524 145.651533 128.653665 111.215888 100.129161 214.427521
2017-12-16 132.458526 165.877714 151.740738 114.569777 118.986980 144.706418 128.607536 110.602453 99.277374 215.656986
2017-12-17 135.653070 164.500858 151.356125 113.059328 119.503363 147.394558 130.757791 111.828603 101.054553 215.029276
2017-12-18 134.303981 162.648287 153.750824 113.129310 121.104725 146.316623 131.045191 114.451750 103.106103 214.183718
2017-12-19 140.160964 162.569794 155.372278 115.593452 121.438550 147.329188 130.153762 116.905963 103.487086 211.171203
2017-12-20 142.012567 164.170949 156.899676 116.919098 121.102676 148.817321 128.646966 118.967733 103.824534 211.284344
2017-12-21 138.706719 169.420100 157.765919 116.805091 118.929722 149.323650 128.875156 118.595002 101.977882 207.934538
2017-12-22 138.873774 166.560431 159.265982 118.921014 120.645266 150.999621 129.093897 120.721588 103.599359 209.383685
2017-12-23 137.408365 169.755458 161.322220 116.138354 117.831938 151.568158 126.904477 120.660152 104.302103 208.293801
2017-12-24 139.179739 170.922512 162.366049 116.619988 119.223750 153.382386 125.445170 120.108256 104.282886 208.706495
2017-12-25 139.252659 170.295485 161.733997 114.723332 120.228436 153.858393 125.775499 121.236304 104.334582 207.715421
2017-12-26 140.304357 172.613186 165.331655 113.630569 116.851923 156.616690 128.956342 118.896691 103.760495 206.896268

360 rows × 10 columns

Concatenamos y graficamos...


In [35]:
simul=pd.concat([closes.T, simdata.T]).T
simul.plot(figsize=(8,6),legend=False);



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).

La próxima clase veremos cómo tomar decisiones estableciendo un umbral de precio.

Anuncios parroquiales...

  1. Viernes 28 de Octubre y Martes 21 de Noviembre no hay clase.
  2. Clase de reposición: próximo Miércoles 18 de Octubre de 16:00-18:00, aula D-206 (Clase de repaso).
  3. Grupos de proyectos: hoja con integrantes.
  4. Para el próximo viernes: proyecto definido, subir a moodle un cuaderno con nombre del proyecto, objetivos y una breve introducción.
  5. Les sigo debiendo una tarea de la parte de integración.
Created with Jupyter by Esteban Jiménez Rodríguez.