Ingeniería de características de factores: análisis en profundidad de la biblioteca alphalens

El artículo original número 107 se centra en "el crecimiento personal y la libertad de riqueza, la lógica de la operación mundial y la inversión cuantitativa de IA".

En el artículo anterior, hemos preparado las funciones de datos, personalización de factores y etiquetado automático. Hoy continuaremos con el análisis factorial. El marco de análisis es, por supuesto, alphalens.

El planeta tiene un informe de investigación sobre el uso de alphalens:

[Informe de investigación semanal] alphalens de la ingeniería de características cuantitativas de IA: un conjunto de herramientas generales para analizar los factores alfa

Interpretación del código fuente de alphalens para el análisis factorial de qlib

Análisis de factor único de alpha158 de qlib basado en alphalens

El uso de alphalens es muy sencillo, consiste en organizar dos estructuras de datos, principalmente para familiarizarse con el uso de pandas dataframe.

Los datos del factor están en formato de marco de datos con fecha y código como índices dobles:

Y el precio de cierre está indexado por fecha, y cada activo es una columna separada:

Después de preparar los datos, llama a get_clear_factor_and_forward_returns en utils:

Obtenga el período N futuro (el valor predeterminado es 1 día, 5 días y 10 días de rendimiento), el valor del factor y el cuantil del factor (factor_quantile, el valor predeterminado se divide en 5 partes de menor a mayor)

Al llamar a create_information_tear_sheet en lágrimas, obtenga el resultado del análisis de información:

Lo anterior es el concepto importante del análisis IC en el análisis factorial.

¿Qué es un CI? Podemos ver el código de alphalens en concreto:

El valor de iC es igual a la correlación de Spearman entre la tasa de rendimiento y el factor en la misma sección transversal (es decir, el coeficiente de correlación en las estadísticas con las que estamos familiarizados):

estadísticas.spearmanr( factor_data['5D'], factor_data['factor'])

Código para generar formulario IC:

def plot_information_table(ic_data): 
    ic_summary_table = pd.DataFrame() 
    ic_summary_table["IC Mean"] = ic_data.mean() 
    ic_summary_table["IC Std."] = ic_data.std() ic_summary_table 
    ["Risk-Adjusted IC"] = \ 
        ic_data.mean() / ic_data.std() 
    t_stat, p_value = stats.ttest_1samp(ic_data, 0) 
    ic_summary_table["t-stat(IC)"] = t_stat 
    ic_summary_table["p-value(IC)"] = p_value 
    ic_summary_table["IC Skew"] = stats.skew(ic_data) 
    ic_summary_table["IC Kurtosis"] = stats.kurtosis(ic_data) 

    print("Análisis de información") 
    utils.print_table(ic_summary_table.apply(lambda x: x.round( 3)).T)

Se puede ver que el valor de IC es el coeficiente de correlación entre el valor del factor de cada sección y la tasa de retorno de un cierto período en el futuro, y luego el valor medio, la desviación estándar, la asimetría, la curtosis, etc. de este coeficiente de correlación. secuencia. El IC ajustado al riesgo es la media de IC/desviación estándar de IC.

En términos generales, cuando el RIC alcanza 0,05 o más, la correlación se considera significativa.

Cuanto mayor sea el valor de IC, mejor. En el ejemplo anterior, el impulso de 20 días tiene una correlación significativa con los siguientes 1 día, 5 días y 10 días, lo que indica que este es un factor relativamente efectivo.

Análisis de beneficios:

Permítanme hablar sobre las últimas tres columnas primero, Top Quantile es la combinación de los valores de factor más altos y más bajos, dos construcciones. Spread es la diferencia entre los dos.

Alfa y Beta:

Aquí y es la tasa de rendimiento del factor, x es el valor del factor, que es diferente de IC, IC es el coeficiente de correlación entre los dos, y Alpha, Beta es el ajuste lineal entre los dos.

alpha_beta = pd.DataFrame() 
para período en devoluciones.columnas.valores: 
    x = universe_ret[período].valores 
    y = devoluciones[período].valores 
    x = add_constant(x)

@plotting.customize 
def create_returns_tear_sheet( 
    factor_data, long_short=True, group_neutral=False, by_group=False 
): 

    factor_returns = perf.factor_returns( 
        factor_data, long_short, group_neutral 
    ) 

    mean_quant_ret, std_quantile = perf.mean_return_by_quantile( 
        factor_data, 
        by_group=False, 
        demeaned= long_short, 
        group_adjust=group_neutral, 
    ) 

    mean_quant_rateret = mean_quant_ret.apply( 
        utils.rate_of_return, axis=0, base_period=mean_quant_ret.columns[0] 
    ) 

    mean_quant_ret_bydate, std_quant_daily = perf.mean_return_by_quantile( 
        factor_data,
        by_date=Verdadero, 
    mean_ret_spread_quant, std_spread_quant = perf.compute_mean_returns_spread(
        by_group=False, 
        demeaned=long_short, 
        group_adjust=group_neutral, 
    ) 

    mean_quant_rateret_bydate = mean_quant_ret_bydate.apply( 
        utils.rate_of_return, 
        axis=0, 
        base_period=mean_quant_ret_bydate.columns[0], 
    ) 

    compst_quant_daily = std_quant_daily.apply( 
        utils.std_conversion, axis =0 , base_period=std_quant_daily.columns[0] 
    ) 

    alpha_beta = perf.factor_alpha_beta( 
        factor_data, factor_returns, long_short, group_neutral 
    ) 

        mean_quant_rateret_bydate, 
        factor_data["factor_quantile"].max(),
        factor_data["factor_quantile"].min(), 
        std_err=compstd_quant_daily, 
    ) 

    fr_cols = len(factor_returns.columns) 
    vertical_sections = 2 + fr_cols * 3 
    gf = GridFigure(rows=vertical_sections, cols=1) 

    plotting.plot_returns_table( 
        alpha_beta, mean_quant_rateret , mean_ret_spread_quant 
    ) 

    plotting.plot_quantile_returns_bar( 
        mean_quant_rateret, 
        by_group=False, 
        ylim_percentiles=Ninguno, 
        ax=gf.next_row(), 
    ) 
 
    plotting.plot_quantile_returns_violin(
        mean_quant_rateret_bydate, ylim_percentiles=(1, 99), ax=gf.next_row() 
    ) 

    trading_calendar = factor_data.index. niveles[0].frecuencia
    si trading_calendar es Ninguno: 
        trading_calendar = pd.tseries.offsets.BDay() 
        advertencias.warn( 
            "'freq' no establecida en factor_data index: suponiendo día hábil", 
            UserWarning, 
        ) 

    # Calcule los rendimientos acumulativos de los rendimientos simples diarios, si '1D 
    Se proporcionan # devoluciones . 
    if "1D" in factor_returns: 
        title = ( 
            "Factor ponderado " 
            + ("Grupo neutral " if group_neutral else "") 
            + ("Largo/Corto" if long_short else "") 
        ) 

        plotting.plot_acumulative_returns( 
            factor_returns["
        ) 

        plotting.plot_cumulative_returns_by_quantile( 
            mean_quant_ret_bydate["1D"], period="1D", ax=gf.next_row() ) ax_mean_quantile_returns_spread_ts 
        = 

    [ 
        gf.next_row() for x in range(fr_cols) 
    ] 
    plotting.plot_mean_quantile_returns_spread_time_series( 
        mean_ret_sp read_quant, 
        std_err= std_spread_quant, 
        ancho de banda=0.5, 
        ax=ax_mean_quantile_returns_spread_ts, 
    ) 

    plt.show() 
    gf.close() 

    if by_group: 
        ( 
            mean_return_quantile_group,  
            mean_return_quantile_group_std_err,
        ) = perf.mean_return_by_quantile( 
            factor_data, 
            by_date=False, 
            by_group=True, 
            demeaned=long_short, 
            group_adjust=group_neutral, 
        ) 

        mean_quant_rateret_group = mean_return_quantile_group.apply( 
            utils.rate_of_return, 
            axis=0, 
            base_period=mean_return_quantile_group.columns[0], 
        ) 

        num_ grupos = len( 
            mean_quant_rateret_group.index.get_level_values("group").unique() 
        ) 

        verticales_sections = 1 + (((num_groups - 1) // 2) + 1) 
        gf = GridFigure(rows=vertical_sections, cols=2)

        ax_quantile_returns_bar_by_group = [ 
            gf.next_cell() for _ in range(num_groups) 
        ] 
        plotting.plot_quantile_returns_bar( 
            mean_quant_rateret_group, 
            by_group=True, 
            ylim_percentiles=(5, 95), 
            ax=ax_quantile_returns_bar_by_group, 
        ) 
        plt.show() 
        gf.close()

Calcular la tasa de rendimiento para diferentes cuantiles;

Haga carteras de inversión de acuerdo con los cuantiles, por ejemplo, el promedio ponderado del cuantil = 1 hace una cartera y el promedio ponderado del cuantil = 5 hace otra cartera.

Solo tenemos 3 ramas, y solo se forman tres segmentos por cuantiles, formando así una secuencia de combinación por cuantiles:

resumen:

Hoy, nos enfocamos en analizar el análisis de IC y el análisis de ingresos de alphalens. El análisis IC es el más importante entre ellos, que es la correlación entre el factor único y el rendimiento esperado.

El análisis de ingresos es similar al "backtesting", es decir, cuál es la tasa de retorno del quintil más alto del factor de compra, cuál es la tasa de retorno del quintil más bajo y cuál es el diferencial entre los dos. Además, la tasa de retorno se ajusta linealmente con el valor del factor para obtener alfa y beta.
Para obtener el código y los datos más recientes, vaya a la columna de cuantificación del planeta para descargar.

Supongo que te gusta

Origin blog.csdn.net/weixin_38175458/article/details/127906849
Recomendado
Clasificación