Realizar una estrategia de equilibrio de derechos e intereses de múltiples espacios ordenados

El autor:La bondad, Creado: 2019-08-24 10:05:53, Actualizado: 2023-10-19 21:06:54

img

En el artículo anterior (((https://www.fmz.com/digest-topic/4187En este artículo, presentamos las estrategias de negociación de emparejamiento y demostramos cómo crear y automatizar estrategias de negociación utilizando datos y análisis matemáticos.

Las estrategias de equilibrio multicapa son una extensión natural de las estrategias de negociación de pares que se aplican a un indicador de la cesta de operaciones. Se aplican especialmente a mercados de negociación de gran variedad e interconexión, como el mercado de divisas y el mercado de futuros de productos.

Principios básicos

La estrategia de equilibrio multivalente es la de hacer más y hacer menos de una cesta de indicadores al mismo tiempo. Al igual que las operaciones de emparejamiento, se determina qué indicadores son baratos y qué indicadores son caros. La diferencia es que la estrategia de equilibrio multivalente coloca todos los indicadores en un conjunto de opciones para determinar qué indicadores son relativamente baratos o caros.

¿Recuerdas que antes dijimos que las operaciones de emparejamiento son una estrategia neutral en el mercado? También lo es la estrategia de equilibrio de múltiples espacios, ya que la cantidad de posiciones de múltiples cabezas y de cabezas vacías asegura que la estrategia se mantendrá neutral en el mercado ("no afectada por las fluctuaciones del mercado"). La estrategia también es estadísticamente sólida; al clasificar los indicadores de inversión y tener varias posiciones, puedes abrir varias posiciones en tu modelo de clasificación, no solo una sola posición de riesgo.

¿Cuál es el esquema de clasificación?

Un esquema de clasificación es un modelo en el que se puede priorizar a cada indicador según el desempeño esperado. Los factores pueden ser factores de valor, indicadores técnicos, modelos de precios o una combinación de todos los factores anteriores. Por ejemplo, se puede usar indicadores de impulso para clasificar indicadores de inversión que siguen una serie de tendencias: se espera que los indicadores de inversión con mayor impulso sigan funcionando bien y obtengan el mayor ranking; los inversionistas con menor impulso se desempeñan peor y tienen el menor rendimiento.

El éxito de esta estrategia se basa casi exclusivamente en el esquema de clasificación utilizado, es decir, que su esquema de clasificación puede separar los indicadores de inversión de alto rendimiento de los indicadores de inversión de bajo rendimiento para lograr mejor el retorno de la estrategia de indicadores de inversión de múltiples espacios. Por lo tanto, es muy importante desarrollar un esquema de clasificación.

¿Cómo se elabora un esquema de clasificación?

Una vez que definimos el esquema de clasificación, obviamente queremos beneficiarnos de él. Lo que hacemos es invertir la misma cantidad de dinero en inversiones que se encuentran en la parte superior del ranking y en inversiones que se encuentran en la parte inferior del ranking. Esto asegura que la estrategia solo gana dinero proporcionalmente a la calidad del ranking y será "neutral en el mercado".

Supongamos que estás clasificando m de todos los indicadores, que tienes n dólares de inversión y que deseas tener posiciones de un total de 2p (de los cuales m> 2p). Si el indicador clasificado en el rango 1 se espera que funcione peor, el indicador clasificado en el rango m se espera que funcione mejor:

  • Así que si usted tiene un valor de inversión ordenado en una posición como: 1,..., p, entonces usted tiene un valor de inversión de $ 2 / 2p.

  • Así que si usted tiene un valor de inversión ordenado como: m-p,..., m en esta posición, entonces usted tiene un valor de inversión de más de n / 2p dólares.

** NOTA: ** Como los precios de los indicadores de inversión causados por los saltos de precios no siempre se dividen uniformemente en n/2p, y se debe comprar ciertos indicadores en números enteros, habrá algunos algoritmos que no son precisos, y los algoritmos deben acercarse lo más posible a este número.

El valor de las emisiones de gases de efecto invernadero es el valor de las emisiones de gases de efecto invernadero.

Esto puede ser un gran problema para los puntos de precio mayores a 100 (como en el mercado de futuros de productos), ya que no se pueden abrir posiciones con puntos de precio (no existe un problema en el mercado de monedas digitales).

Vamos a ver un ejemplo de lo que se supone.

  • Construimos nuestro entorno de investigación en la plataforma de cuantificación de inventores

En primer lugar, para que el trabajo se desarrolle sin problemas, necesitamos construir nuestro entorno de investigación, y en este artículo usamos la plataforma de cuantificación de los inventores.FMZ.COMEl proyecto de Docker fue desarrollado en el año 2010 para desarrollar un entorno de investigación basado en el uso de una API rápida y cómoda y un sistema de Docker completo.

En el nombre oficial de la plataforma de cuantificación de los inventores, este sistema Docker se conoce como sistema administrador.

Para más información sobre cómo implementar administradores y robots, consulte mi artículo anterior:https://www.fmz.com/bbs-topic/4140

Los lectores que quieran comprar su propio administrador de servidores en la nube pueden consultar este artículo:https://www.fmz.com/bbs-topic/2848

Después de haber implementado con éxito un buen sistema de servidores y administradores en la nube, ahora vamos a instalar el mayor templo de Python: Anaconda.

Para implementar todos los entornos de programación relacionados que se requieren en este artículo (la librería de dependencias, la administración de versiones, etc.), el método más sencillo es usar Anaconda. Es un ecosistema de ciencias de datos Python y un administrador de librería de dependencias.

Para más información sobre cómo instalar Anaconda, consulte el manual oficial de Anaconda:https://www.anaconda.com/distribution/

本文还将用到numpy和pandas这两个目前在Python科学计算方面十分流行且重要的库.

Estos trabajos básicos también pueden ser consultados en mi artículo anterior sobre cómo configurar el entorno de Anaconda y las bibliotecas numpy y pandas.https://www.fmz.com/digest-topic/4169

Generamos indicadores de inversión aleatorios y factores aleatorios para clasificarlos. Supongamos que nuestros retornos futuros dependen realmente de los valores de estos factores.

import numpy as np
import statsmodels.api as sm
import scipy.stats as stats
import scipy
import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
## PROBLEM SETUP ##
# Generate stocks and a random factor value for them
stock_names = ['stock ' + str(x) for x in range(10000)]
current_factor_values = np.random.normal(0, 1, 10000)
# Generate future returns for these are dependent on our factor values
future_returns = current_factor_values + np.random.normal(0, 1, 10000)
# Put both the factor values and returns into one dataframe
data = pd.DataFrame(index = stock_names, columns=['Factor Value','Returns'])
data['Factor Value'] = current_factor_values
data['Returns'] = future_returns
# Take a look
data.head(10)

img

Ahora que tenemos el valor factor y el rendimiento, podemos ver lo que sucede si clasificamos los indicadores de inversión según el valor factor, y luego abrimos posiciones altas y bajas.

# Rank stocks
ranked_data = data.sort_values('Factor Value')
# Compute the returns of each basket with a basket size 500, so total (10000/500) baskets
number_of_baskets = int(10000/500)
basket_returns = np.zeros(number_of_baskets)
for i in range(number_of_baskets):
    start = i * 500
    end = i * 500 + 500 
    basket_returns[i] = ranked_data[start:end]['Returns'].mean()
# Plot the returns of each basket
plt.figure(figsize=(15,7))
plt.bar(range(number_of_baskets), basket_returns)
plt.ylabel('Returns')
plt.xlabel('Basket')
plt.legend(['Returns of Each Basket'])
plt.show()

img

Nuestra estrategia consiste en obtener el primer puesto en el grupo de indicadores de inversión de una canasta; el décimo puesto en el grupo de indicadores de inversión de una canasta; los beneficios de esta estrategia son:

basket_returns[number_of_baskets-1] - basket_returns[0]

El resultado es: 4.172.

Pongamos el dinero en nuestro modelo de clasificación para que pueda separar a los inversores de bajo rendimiento de los de alto rendimiento.

Más adelante en este artículo, vamos a hablar sobre cómo evaluar los esquemas de clasificación. La ventaja de ganar dinero de manera conjunta basado en la clasificación es que no está influenciado por el desorden del mercado, sino que se puede aprovechar.

Consideremos un ejemplo del mundo real.

Hemos cargado datos de 32 acciones de diferentes industrias del S&P 500 e intentado clasificarlas.

from backtester.dataSource.yahoo_data_source import YahooStockDataSource
from datetime import datetime
startDateStr = '2010/01/01'
endDateStr = '2017/12/31'
cachedFolderName = '/Users/chandinijain/Auquan/yahooData/'
dataSetId = 'testLongShortTrading'
instrumentIds = ['ABT','AKS','AMGN','AMD','AXP','BK','BSX',
                'CMCSA','CVS','DIS','EA','EOG','GLW','HAL',
                'HD','LOW','KO','LLY','MCD','MET','NEM',
                'PEP','PG','M','SWN','T','TGT',
                'TWX','TXN','USB','VZ','WFC']
ds = YahooStockDataSource(cachedFolderName=cachedFolderName,
                            dataSetId=dataSetId,
                            instrumentIds=instrumentIds,
                            startDateStr=startDateStr,
                            endDateStr=endDateStr,
                            event='history')
price = 'adjClose'

Así que vamos a usar un indicador de velocidad estandarizado de un ciclo de un mes como base para el ranking.

## Define normalized momentum
def momentum(dataDf, period):
    return dataDf.sub(dataDf.shift(period), fill_value=0) / dataDf.iloc[-1]
## Load relevant prices in a dataframe
data = ds.getBookDataByFeature()[‘Adj Close’]
#Let's load momentum score and returns into separate dataframes
index = data.index
mscores = pd.DataFrame(index=index,columns=assetList)
mscores = momentum(data, 30)
returns = pd.DataFrame(index=index,columns=assetList)
day = 30

Ahora vamos a analizar el comportamiento de nuestras acciones para ver cómo funcionan nuestras acciones en el mercado en los factores de clasificación que elegimos.

Análisis de datos

El comportamiento de las acciones

Veamos cómo se muestran las acciones de la cesta que hemos elegido en nuestro modelo de clasificación. Para ello, vamos a calcular el retorno a largo plazo de una semana de todas las acciones. Y luego podemos ver la relación entre el retorno de cada acción una semana antes y la movilidad de los 30 días anteriores. Las acciones que muestran una relación positiva son las que siguen la tendencia y las que muestran una relación negativa son las que tienen un retorno de media.

# Calculate Forward returns
forward_return_day = 5
returns = data.shift(-forward_return_day)/data -1
returns.dropna(inplace = True)
# Calculate correlations between momentum and returns
correlations = pd.DataFrame(index = returns.columns, columns = [‘Scores’, ‘pvalues’])
mscores = mscores[mscores.index.isin(returns.index)]
for i in correlations.index:
    score, pvalue = stats.spearmanr(mscores[i], returns[i])
    correlations[‘pvalues’].loc[i] = pvalue
    correlations[‘Scores’].loc[i] = score
correlations.dropna(inplace = True)
correlations.sort_values(‘Scores’, inplace=True)
l = correlations.index.size
plt.figure(figsize=(15,7))
plt.bar(range(1,1+l),correlations[‘Scores’])
plt.xlabel(‘Stocks’)
plt.xlim((1, l+1))
plt.xticks(range(1,1+l), correlations.index)
plt.legend([‘Correlation over All Data’])
plt.ylabel(‘Correlation between %s day Momentum Scores and %s-day forward returns by Stock’%(day,forward_return_day));
plt.show()

img

¡Todas nuestras acciones regresan a un cierto nivel de equivalencia! (¡Obviamente, así es como funciona el universo que elegimos) Esto nos dice que si las acciones obtienen un alto puntaje en el análisis de dinámica, debemos esperar que no funcionen bien la próxima semana.

Relación entre la clasificación de las puntuaciones y los beneficios del análisis de potencia

A continuación, necesitamos ver la correlación entre nuestra puntuación de clasificación y el retorno prospectivo del mercado en general, es decir, la predicción de la tasa de retorno esperada y la relación de nuestros factores de clasificación, si los niveles de correlación más altos predicen los retornos relativos más bajos, o viceversa.

Para ello, hemos calculado la correlación diaria entre la movilidad de 30 días de todas las acciones y los retornos a una semana de largo plazo.

correl_scores = pd.DataFrame(index = returns.index.intersection(mscores.index), columns = [‘Scores’, ‘pvalues’])
for i in correl_scores.index:
    score, pvalue = stats.spearmanr(mscores.loc[i], returns.loc[i])
    correl_scores[‘pvalues’].loc[i] = pvalue
    correl_scores[‘Scores’].loc[i] = score
correl_scores.dropna(inplace = True)
l = correl_scores.index.size
plt.figure(figsize=(15,7))
plt.bar(range(1,1+l),correl_scores[‘Scores’])
plt.hlines(np.mean(correl_scores[‘Scores’]), 1,l+1, colors=’r’, linestyles=’dashed’)
plt.xlabel(‘Day’)
plt.xlim((1, l+1))
plt.legend([‘Mean Correlation over All Data’, ‘Daily Rank Correlation’])
plt.ylabel(‘Rank correlation between %s day Momentum Scores and %s-day forward returns’%(day,forward_return_day));
plt.show()

img

La correlación diaria se muestra muy ruidosa, pero muy leve (esto es de esperar, ya que hemos dicho que todas las acciones tienen un retorno igual). También vamos a ver la correlación promedio mensual con el retorno de un mes antes.

monthly_mean_correl =correl_scores['Scores'].astype(float).resample('M').mean()
plt.figure(figsize=(15,7))
plt.bar(range(1,len(monthly_mean_correl)+1), monthly_mean_correl)
plt.hlines(np.mean(monthly_mean_correl), 1,len(monthly_mean_correl)+1, colors='r', linestyles='dashed')
plt.xlabel('Month')
plt.xlim((1, len(monthly_mean_correl)+1))
plt.legend(['Mean Correlation over All Data', 'Monthly Rank Correlation'])
plt.ylabel('Rank correlation between %s day Momentum Scores and %s-day forward returns'%(day,forward_return_day));
plt.show()

img

Podemos ver que la correlación promedio es nuevamente ligeramente negativa, pero también cambia mucho cada mes.

La rentabilidad promedio de una cesta de acciones

Ya hemos calculado el rendimiento de una cesta de acciones retiradas de nuestro ranking. Si hacemos un ranking de todas las acciones y las dividimos en grupos n, ¿cuál es el rendimiento promedio de cada grupo?

El primer paso es crear una función que le dará el promedio de retorno y el factor de clasificación de cada canasta dada cada mes.

def compute_basket_returns(factor, forward_returns, number_of_baskets, index):
data = pd.concat([factor.loc[index],forward_returns.loc[index]], axis=1)
    # Rank the equities on the factor values
    data.columns = ['Factor Value', 'Forward Returns']
    data.sort_values('Factor Value', inplace=True)
    # How many equities per basket
    equities_per_basket = np.floor(len(data.index) / number_of_baskets)
basket_returns = np.zeros(number_of_baskets)
# Compute the returns of each basket
    for i in range(number_of_baskets):
        start = i * equities_per_basket
        if i == number_of_baskets - 1:
            # Handle having a few extra in the last basket when our number of equities doesn't divide well
            end = len(data.index) - 1
        else:
            end = i * equities_per_basket + equities_per_basket
        # Actually compute the mean returns for each basket
        #s = data.index.iloc[start]
        #e = data.index.iloc[end]
        basket_returns[i] = data.iloc[int(start):int(end)]['Forward Returns'].mean()
        
    return basket_returns

Cuando clasificamos las acciones con base en este puntaje, calculamos el rendimiento promedio de cada canasta. Esto debería permitirnos entender su relación en un largo período de tiempo.

number_of_baskets = 8
mean_basket_returns = np.zeros(number_of_baskets)
resampled_scores = mscores.astype(float).resample('2D').last()
resampled_prices = data.astype(float).resample('2D').last()
resampled_scores.dropna(inplace=True)
resampled_prices.dropna(inplace=True)
forward_returns = resampled_prices.shift(-1)/resampled_prices -1
forward_returns.dropna(inplace = True)
for m in forward_returns.index.intersection(resampled_scores.index):
    basket_returns = compute_basket_returns(resampled_scores, forward_returns, number_of_baskets, m)
    mean_basket_returns += basket_returns
mean_basket_returns /= l    
print(mean_basket_returns)
# Plot the returns of each basket
plt.figure(figsize=(15,7))
plt.bar(range(number_of_baskets), mean_basket_returns)
plt.ylabel('Returns')
plt.xlabel('Basket')
plt.legend(['Returns of Each Basket'])
plt.show()

img

Parece que hemos logrado separar a los más exitosos de los menos exitosos.

Diferencia de ganancias (margen)

Por supuesto, estas son solo relaciones medias. Para entender qué tan coherente es esta relación y si estamos dispuestos a operar, debemos cambiar nuestra forma de ver y nuestra actitud hacia ella con el tiempo. A continuación, veremos las diferencias mensuales de los dos primeros años.

total_months = mscores.resample('M').last().index
months_to_plot = 24
monthly_index = total_months[:months_to_plot+1]
mean_basket_returns = np.zeros(number_of_baskets)
strategy_returns = pd.Series(index = monthly_index)
f, axarr = plt.subplots(1+int(monthly_index.size/6), 6,figsize=(18, 15))
for month in range(1, monthly_index.size):
    temp_returns = forward_returns.loc[monthly_index[month-1]:monthly_index[month]]
    temp_scores = resampled_scores.loc[monthly_index[month-1]:monthly_index[month]]
    for m in temp_returns.index.intersection(temp_scores.index):
        basket_returns = compute_basket_returns(temp_scores, temp_returns, number_of_baskets, m)
        mean_basket_returns += basket_returns
    
    strategy_returns[monthly_index[month-1]] = mean_basket_returns[ number_of_baskets-1] - mean_basket_returns[0]
    
    mean_basket_returns /= temp_returns.index.intersection(temp_scores.index).size
    
    r = int(np.floor((month-1) / 6))
    c = (month-1) % 6
    axarr[r, c].bar(range(number_of_baskets), mean_basket_returns)
    axarr[r, c].xaxis.set_visible(False)
    axarr[r, c].set_title('Month ' + str(month))
plt.show()

img

plt.figure(figsize=(15,7))
plt.plot(strategy_returns)
plt.ylabel(‘Returns’)
plt.xlabel(‘Month’)
plt.plot(strategy_returns.cumsum())
plt.legend([‘Monthly Strategy Returns’,’Cumulative Strategy Returns’])
plt.show()

img

Finalmente, si hacemos más de la última canasta y hacemos la primera canasta vacía cada mes, entonces vamos a ver el rendimiento (suponiendo que cada valor tenga una distribución de capital igual)

total_return = strategy_returns.sum()
ann_return = 100*((1 + total_return)**(12.0 /float(strategy_returns.index.size))-1)
print('Annual Returns: %.2f%%'%ann_return)

Rentabilidad anual: 5.03%

Vemos que tenemos un esquema de clasificación muy débil, que solo distingue moderadamente entre las acciones de alto rendimiento y las de bajo rendimiento. Además, el esquema de clasificación no es coherente y varía mucho de mes a mes.

Encontrar el esquema de clasificación correcto

Para implementar una estrategia de equilibrio de múltiples espacios, en realidad solo necesitas determinar el esquema de clasificación. Después de eso, todo es mecánico. Una vez que tienes una estrategia de equilibrio de múltiples espacios, puedes intercambiar diferentes factores de clasificación, y nada más con demasiadas modificaciones.

Los esquemas de clasificación también pueden provenir de casi cualquier modelo. No es necesario que sea un modelo factorial basado en el valor, sino que puede ser una técnica de aprendizaje automático que predice el retorno con un mes de antelación y se clasifica de acuerdo con ese rango.

Selección y evaluación del ranking

El esquema de clasificación es la ventaja y el componente más importante de una estrategia de equilibrio de derechos y intereses multiespacio.

Un buen punto de partida es seleccionar las tecnologías conocidas existentes y ver si puedes modificarlas ligeramente para obtener mayores ganancias.

  • Clonado y ajustadoPor lo general, los factores públicos ya no tendrán señales de negociación, ya que se han aprovechado completamente del mercado. Sin embargo, a veces te guían en la dirección correcta.

  • Modelo de preciosCualquier modelo que predice el retorno futuro puede ser un factor y tiene el potencial de ser usado para clasificar tus indicadores de una cesta. Puedes tomar cualquier modelo de precios complejo y convertirlo en un esquema de clasificación.

  • Los factores basados en el precio (indicadores técnicos)Los factores basados en el precio, como los que hemos discutido hoy, obtienen información sobre los precios históricos de cada derecho y lo utilizan para generar el valor del factor. Los ejemplos pueden ser indicadores de media móvil, indicadores de movimiento o indicadores de volatilidad.

  • Regresión y movimientoEs notable que algunos factores piensan que el precio continúa moviéndose una vez que se mueve en una dirección; otros son exactamente lo contrario. Ambos son modelos efectivos sobre diferentes períodos de tiempo y activos, y es importante estudiar si el comportamiento básico se basa en la movilidad o en la regresión.

  • Los factores básicos (basados en el valor)Es una combinación de valores fundamentales, como el PE, el dividendo, etc. Los valores fundamentales contienen información relacionada con los hechos reales del mundo de la empresa y, por lo tanto, pueden ser más poderosos que el precio en muchos aspectos.

En última instancia, los factores de pronóstico de crecimiento son una carrera de armas, y estás tratando de mantenerte un paso adelante. Los factores se aprovechan del mercado y tienen una vida útil, por lo que debes trabajar constantemente para determinar cuánto de tu factor ha sufrido una recesión y qué nuevos factores pueden usarse para reemplazarlos.

Otros factores a considerar

  • Reequilibrar las frecuencias

Cada sistema de clasificación pronostica los retornos en intervalos de tiempo ligeramente diferentes. Los retornos de medias basados en precios pueden ser predictibles en días, mientras que los modelos basados en factores de valor pueden ser predictivos en meses. Es muy importante determinar el rango de tiempo en que el modelo debe predecir y realizar una verificación estadística antes de ejecutar la estrategia.

  • Capacidad de capital y costos de transacción

Cada estrategia tiene un volumen de capital mínimo y máximo, y los límites mínimos generalmente se determinan por el costo de la transacción.

Comerciar demasiadas acciones resultará en un alto costo de negociación. Supongamos que quieres comprar 1000 acciones, entonces cada reequilibrio producirá costos de varios miles de dólares. Tu base de capital debe ser lo suficientemente alta como para que los costos de negociación representen una pequeña parte de la ganancia generada por tu estrategia. Por ejemplo, si tu capital es de $100,000 y tu estrategia gana un 1% por mes (($1000), todos estos beneficios serán ocupados por el costo de negociación.

El límite mínimo de los activos depende principalmente del número de acciones que se negocian. Sin embargo, el máximo de capacidad también es muy alto, y la estrategia de equilibrio múltiple puede negociar cientos de millones de dólares sin perder ventaja. Esto es cierto porque la estrategia se reequilibra con relativa frecuencia. El número total de activos, además del número de acciones que se negocian, y el valor en dólares de cada acción será muy bajo, y no tendrá que preocuparse de que su volumen de operaciones afecte al mercado.


Relacionados

Más.