pandas                
            Análisis: Reunirlo todo y tomar decisiones.
        
        
            
    Buscar..
Análisis quintil: con datos aleatorios
El análisis quintil es un marco común para evaluar la eficacia de los factores de seguridad.
Que es un factor
Un factor es un método para calificar / clasificar conjuntos de valores. Para un punto particular en el tiempo y para un conjunto particular de valores, un factor puede representarse como una serie de pandas donde el índice es una matriz de los identificadores de seguridad y los valores son las puntuaciones o rangos.
Si tomamos las puntuaciones de los factores a lo largo del tiempo, podemos, en cada momento, dividir el conjunto de valores en 5 grupos o quintiles iguales, según el orden de las puntuaciones de los factores. No hay nada particularmente sagrado en el número 5. Podríamos haber usado 3 o 10. Pero usamos 5 a menudo. Finalmente, hacemos un seguimiento del rendimiento de cada uno de los cinco grupos para determinar si hay una diferencia significativa en las devoluciones. Tendemos a enfocarnos más intensamente en la diferencia en los rendimientos del grupo con el rango más alto en relación con el rango más bajo.
Comencemos estableciendo algunos parámetros y generando datos aleatorios.
Para facilitar la experimentación con los mecanismos, proporcionamos un código simple para crear datos aleatorios que nos dan una idea de cómo funciona esto.
Incluye datos aleatorios
- Devoluciones : generar devoluciones aleatorias para un número específico de valores y periodos.
-  Señales : genere señales aleatorias para un número específico de valores y períodos y con el nivel prescrito de correlación con las devoluciones . Para que un factor sea útil, debe haber alguna información o correlación entre las puntuaciones / rangos y los rendimientos posteriores. Si no hubiera correlación, lo veríamos. Ese sería un buen ejercicio para el lector, duplique este análisis con datos aleatorios generados con 0correlaciones.
Inicialización
import pandas as pd
import numpy as np
num_securities = 1000
num_periods = 1000
period_frequency = 'W'
start_date = '2000-12-31'
np.random.seed([3,1415])
means = [0, 0]
covariance = [[  1., 5e-3],
              [5e-3,   1.]]
# generates to sets of data m[0] and m[1] with ~0.005 correlation
m = np.random.multivariate_normal(means, covariance,
                                  (num_periods, num_securities)).T
Ahora generemos un índice de series de tiempo y un índice que represente los identificadores de seguridad. Luego úselos para crear marcos de datos para devoluciones y señales
ids = pd.Index(['s{:05d}'.format(s) for s in range(num_securities)], 'ID')
tidx = pd.date_range(start=start_date, periods=num_periods, freq=period_frequency)
 Divido m[0] por 25 para reducir a algo que se parece a los rendimientos de las acciones. También agrego 1e-7 para dar un rendimiento promedio positivo modesto. 
security_returns = pd.DataFrame(m[0] / 25 + 1e-7, tidx, ids)
security_signals = pd.DataFrame(m[1], tidx, ids)
 pd.qcut - Crea cubos quintiles 
 pd.qcut para dividir mis señales en pd.qcut de quintiles para cada período. 
def qcut(s, q=5):
    labels = ['q{}'.format(i) for i in range(1, 6)]
    return pd.qcut(s, q, labels=labels)
    
cut = security_signals.stack().groupby(level=0).apply(qcut)
Utilice estos recortes como un índice en nuestras devoluciones
returns_cut = security_returns.stack().rename('returns') \
    .to_frame().set_index(cut, append=True) \
    .swaplevel(2, 1).sort_index().squeeze() \
    .groupby(level=[0, 1]).mean().unstack()
Análisis
Devoluciones de parcela
import matplotlib.pyplot as plt
fig = plt.figure(figsize=(15, 5))
ax1 = plt.subplot2grid((1,3), (0,0))
ax2 = plt.subplot2grid((1,3), (0,1))
ax3 = plt.subplot2grid((1,3), (0,2))
# Cumulative Returns
returns_cut.add(1).cumprod() \
    .plot(colormap='jet', ax=ax1, title="Cumulative Returns")
leg1 = ax1.legend(loc='upper left', ncol=2, prop={'size': 10}, fancybox=True)
leg1.get_frame().set_alpha(.8)
# Rolling 50 Week Return
returns_cut.add(1).rolling(50).apply(lambda x: x.prod()) \
    .plot(colormap='jet', ax=ax2, title="Rolling 50 Week Return")
leg2 = ax2.legend(loc='upper left', ncol=2, prop={'size': 10}, fancybox=True)
leg2.get_frame().set_alpha(.8)
# Return Distribution
returns_cut.plot.box(vert=False, ax=ax3, title="Return Distribution")
fig.autofmt_xdate()
plt.show()
 Visualizar la correlación del scatter_matrix con scatter_matrix 
from pandas.tools.plotting import scatter_matrix
scatter_matrix(returns_cut, alpha=0.5, figsize=(8, 8), diagonal='hist')
plt.show()
Calcula y visualiza Máximo Draw Down
def max_dd(returns):
    """returns is a series"""
    r = returns.add(1).cumprod()
    dd = r.div(r.cummax()).sub(1)
    mdd = dd.min()
    end = dd.argmin()
    start = r.loc[:end].argmax()
    return mdd, start, end
def max_dd_df(returns):
    """returns is a dataframe"""
    series = lambda x: pd.Series(x, ['Draw Down', 'Start', 'End'])
    return returns.apply(max_dd).apply(series)
A qué se parece esto
max_dd_df(returns_cut)
Vamos a trazarlo
draw_downs = max_dd_df(returns_cut)
fig, axes = plt.subplots(5, 1, figsize=(10, 8))
for i, ax in enumerate(axes[::-1]):
    returns_cut.iloc[:, i].add(1).cumprod().plot(ax=ax)
    sd, ed = draw_downs[['Start', 'End']].iloc[i]
    ax.axvspan(sd, ed, alpha=0.1, color='r')
    ax.set_ylabel(returns_cut.columns[i])
fig.suptitle('Maximum Draw Down', fontsize=18)
fig.tight_layout()
plt.subplots_adjust(top=.95)
Calcular estadísticas
Hay muchas estadísticas potenciales que podemos incluir. A continuación se muestran solo algunas, pero demuestre cómo podemos incorporar nuevas estadísticas en nuestro resumen.
def frequency_of_time_series(df):
    start, end = df.index.min(), df.index.max()
    delta = end - start
    return round((len(df) - 1.) * 365.25 / delta.days, 2)
def annualized_return(df):
    freq = frequency_of_time_series(df)
    return df.add(1).prod() ** (1 / freq) - 1
    
def annualized_volatility(df):
    freq = frequency_of_time_series(df)
    return df.std().mul(freq ** .5)
def sharpe_ratio(df):
    return annualized_return(df) / annualized_volatility(df)
def describe(df):
    r = annualized_return(df).rename('Return')
    v = annualized_volatility(df).rename('Volatility')
    s = sharpe_ratio(df).rename('Sharpe')
    skew = df.skew().rename('Skew')
    kurt = df.kurt().rename('Kurtosis')
    desc = df.describe().T
    
    return pd.concat([r, v, s, skew, kurt, desc], axis=1).T.drop('count')
 Terminaremos usando solo la función de describe , ya que une a todos los demás. 
describe(returns_cut)
Esto no pretende ser exhaustivo. Está pensado para reunir muchas de las características de los pandas y demostrar cómo se puede usar para responder preguntas importantes para usted. Este es un subconjunto de los tipos de métricas que utilizo para evaluar la eficacia de los factores cuantitativos.




