Dans l'article précédent (((https://www.fmz.com/digest-topic/4187Nous avons présenté les stratégies de trading de couplage et montré comment utiliser les données et l'analyse mathématique pour créer et automatiser des stratégies de trading.
Les stratégies d'équilibrage multi-espaces sont une extension naturelle des stratégies d'appariement des indices d'un panier; elles sont particulièrement utiles sur les marchés de négociation variés et interdépendants, tels que les marchés de la monnaie numérique et les marchés des futures sur produits.
La stratégie de l'équilibrage multiplaque consiste à négocier un panier d'indices à la fois à la fois à la fois à la fois à la fois à la fois à la fois à la fois à la fois à la fois à la fois à la fois à la fois à la fois à la fois à la fois à la fois à la fois à la fois à la fois à la fois à la fois à la fois à la fois à la fois à la fois à la fois à la fois à la fois à la fois à la fois à la fois à la fois à la fois à la fois à la fois à la fois à la fois à la fois à la fois à la fois à la fois à la fois à la fois à la fois à la fois à la fois à la fois à la fois à la fois à la fois à la fois à la fois à la fois à la fois à la fois à la fois à la fois à la fois à la fois à la fois à la fois à la fois à la fois à la fois à la fois à la fois à la fois à la fois à la fois à la fois à la fois à la fois à la fois à la fois à la fois à la fois à
Rappelez-vous que nous avons dit plus tôt que les transactions en paire sont une stratégie neutre sur le marché? La même chose est vraie pour la stratégie de l'équilibre multipla, car l'équivalence de la position multipla et de la position vacante garantit que la stratégie restera neutre sur le marché (sans être affectée par les fluctuations du marché). La stratégie est également statistiquement solide; en classant les investissements et en détenant plusieurs positions, vous pouvez placer plusieurs positions sur votre modèle de classement, et non une seule position de risque unique.
Un schéma de classement est un modèle qui permet de hiérarchiser les priorités pour chaque indice en fonction de la performance prévue. Les facteurs peuvent être des facteurs de valeur, des indicateurs techniques, des modèles de prix ou une combinaison de tous les facteurs ci-dessus. Par exemple, vous pouvez utiliser des indicateurs de dynamisme pour classer une gamme d'indices de suivi des tendances: les indices les plus dynamiques devraient continuer à bien fonctionner et obtenir le meilleur classement; les investissements les moins dynamiques sont les moins performants et les moins rentables.
La réussite de cette stratégie repose presque entièrement sur le classement utilisé, c'est-à-dire que votre classement peut séparer les investissements à fort rendement des investissements à faible rendement pour mieux réaliser le retour sur investissement des investissements à fort rendement. Il est donc important de concevoir un classement.
Une fois que nous avons déterminé le programme de classement, nous espérons évidemment en tirer profit. Nous le faisons en investissant le même montant en investissant dans les investissements les plus haut classés et en investissant dans les investissements les moins haut classés. Cela garantit que la stratégie ne gagne de l'argent que proportionnellement à la qualité des classements et qu'elle sera "marché neutre".
Supposons que vous soyez en train de classer tous les indices m, que vous ayez n dollars d'investissement et que vous souhaitiez avoir un total de 2p (dont m> 2p). Si l'indice de classement 1 est le moins performant, l'indice de classement m est le mieux performant:
Vous avez des indices rangés comme: 1,..., p, et vous avez des indices de 2/2p de dollars.
Vous avez des indices de placement: m-p,..., m, etc., et vous avez des indices de placement de plus de n/2p dollars.
**Note:** Comme les prix des indices d'investissement causés par les sauts de prix ne sont pas toujours uniformément divisés en n/2p et que certains indices doivent être achetés en entiers, il y a des algorithmes peu précis qui devraient être aussi proches que possible de ce chiffre. Pour les stratégies qui exécutent n = 100000 et p = 500, nous voyons:
N/2p = 100000/1000 = 100
Cela pose de gros problèmes pour les prix supérieurs à 100 (comme les marchés à terme sur les produits), car vous ne pouvez pas ouvrir de positions avec des prix supérieurs à 100 (ce qui n'existe pas sur les marchés de crypto-monnaie). Nous atténuons cette situation en réduisant les prix supérieurs à 100 ou en augmentant le capital.
Tout d'abord, pour que le travail se déroule bien, nous devons construire notre environnement de recherche, et dans cet article, nous utilisons une plate-forme de quantification des inventeurs.FMZ.COMLe projet a été conçu pour créer un environnement de recherche, principalement pour une interface d'API facile et rapide et un système Docker complet.
Dans le nom officiel de la plate-forme de quantification des inventeurs, ce système Docker est appelé système d'hébergement.
Pour savoir comment déployer des hôtes et des robots, veuillez vous référer à mon précédent article:https://www.fmz.com/bbs-topic/4140
Les lecteurs qui souhaitent acheter leur propre hôte de déploiement de serveur en nuage peuvent consulter cet article:https://www.fmz.com/bbs-topic/2848
Après avoir déployé avec succès de bons services de cloud computing et un système d'administrateur, nous allons installer le plus grand temple de Python à ce jour: Anaconda.
Pour mettre en œuvre tous les environnements de programmation nécessaires à cet article (la bibliothèque de dépendances, la gestion des versions, etc.), le moyen le plus simple est d'utiliser Anaconda. Il s'agit d'un écosystème de data science Python et d'un gestionnaire de bibliothèque de dépendances.
Pour savoir comment installer Anaconda, consultez le guide officiel d'Anaconda:https://www.anaconda.com/distribution/
本文还将用到numpy和pandas这两个目前在Python科学计算方面十分流行且重要的库.
Ces bases peuvent également être consultées dans mon article précédent sur la configuration de l'environnement Anaconda et les bibliothèques numpy et pandas:https://www.fmz.com/digest-topic/4169
Nous générons des indices d'investissement aléatoires et des facteurs aléatoires, et nous les classons.
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)
Maintenant que nous avons les facteurs de valeur et de rendement, nous pouvons voir ce qui se passe si nous classons les indices d'investissement en fonction de la valeur des facteurs, puis nous ouvrons des positions à tête et des positions vides.
# 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()
Notre stratégie est de faire le plus grand nombre de premières places dans un bassin d'indices d'investissement; de faire le moins grand nombre de 10 premières places.
basket_returns[number_of_baskets-1] - basket_returns[0]
Le résultat est: 4.172.
Mettre de l'argent dans notre modèle de classement pour qu'il puisse distinguer les investisseurs les plus performants des moins performants.
Plus loin dans cet article, nous allons discuter de la façon d'évaluer les stratégies de classement. Les avantages d'un profit partiel basé sur le classement sont qu'il n'est pas affecté par le désordre du marché, mais qu'il peut être exploité.
Nous avons téléchargé des données pour 32 actions de différents secteurs de l'indice S&P 500 et nous avons essayé de les classer.
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'
Nous allons utiliser un indicateur de dynamisme standardisé sur une période d'un mois comme base pour le classement.
## 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
Maintenant, nous allons analyser le comportement de nos actions pour voir comment nos actions fonctionnent sur le marché dans les facteurs de classement que nous choisissons.
Le comportement des actions
Nous voyons comment les actions de notre panier de choix se comportent dans notre modèle de classement. Pour cela, nous calculons les rendements à long terme d'une semaine pour toutes les actions. Nous pouvons ensuite voir la relation entre les rendements de chaque action une semaine plus tôt et la dynamique des 30 jours précédents.
# 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()
Tous nos stocks ont une certaine irrégularité! (Apparemment, c'est ainsi que fonctionne l'univers que nous avons choisi) Cela nous dit que si un stock est classé haut dans l'analyse de la dynamique, nous devrions nous attendre à une mauvaise performance la semaine prochaine.
Ensuite, nous avons besoin de voir la corrélation entre nos scores de classement et les rendements à l'avenir du marché dans son ensemble, c'est-à-dire si les prévisions de rendements attendus sont liées à nos facteurs de classement, si des niveaux de correlation plus élevés peuvent prédire des rendements relatifs plus faibles, ou vice versa.
Pour ce faire, nous avons calculé la corrélation quotidienne entre la dynamique de 30 jours de toutes les actions et les rendements à une semaine de l'échéance.
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()
La corrélation quotidienne est très bruyante, mais très légère (ce qui est attendu, car nous avons dit que toutes les actions ont un retour égal). Nous allons également examiner la corrélation mensuelle moyenne avec le rendement d'un mois auparavant.
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()
Nous pouvons voir que la correlation moyenne est à nouveau légèrement négative, mais qu'elle varie énormément chaque mois.
Nous avons calculé le rendement d'un panier de titres retiré de notre classement. Si nous classons tous les titres et les divisons en n groupes, quel est le rendement moyen de chaque groupe?
La première étape consiste à créer une fonction qui donnera une moyenne de rendement et un facteur de classement pour chaque panier donné par mois.
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
Nous calculons le retour moyen de chaque panier lorsque nous classons les actions selon ce score. Cela devrait nous permettre d'avoir une idée de leur relation sur une longue période.
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()
Il semble que nous ayons réussi à séparer les hauts et les bas.
Bien sûr, ce ne sont que des ratios moyens. Pour comprendre à quel point cette relation est cohérente et si nous sommes prêts à négocier, nous devrions changer notre façon de la voir et notre attitude à son égard au fil du temps. Ensuite, nous examinerons les écarts mensuels de leurs deux premières années.
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()
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()
Enfin, si nous ajoutons le dernier panier et que nous vidons le premier panier chaque mois, alors voyons le retour (en supposant que le capital de chaque titre soit égal).
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)
Retour sur investissement annuel: 5.03%
Nous voyons que nous avons un système de classement très faible, qui ne fait qu'une légère distinction entre les actions performantes et les actions performantes.
Pour réaliser une stratégie d'équilibrage multi-space, vous n'avez en réalité qu'à définir un schéma de classement. Tout est mécanique après. Une fois que vous avez une stratégie d'équilibrage multi-space, vous pouvez échanger différents facteurs de classement, sans trop de modifications.
Un schéma de classement peut également provenir de presque n'importe quel modèle. Il ne doit pas nécessairement être un modèle facteuré basé sur la valeur, mais il peut être une technique d'apprentissage automatique qui peut prédire les rendements un mois à l'avance et classer en fonction de ce classement.
Le classement est l'avantage et l'élément le plus important d'une stratégie de multi-espaces équilibrés. Choisir un bon classement est une tâche systématique, et il n'y a pas de réponse simple.
Un bon point de départ est de choisir des technologies déjà connues et de voir si vous pouvez les modifier légèrement pour obtenir des rendements plus élevés.
Clonage et ajustementChoisissez un sujet souvent discuté et voyez si vous pouvez le modifier légèrement pour obtenir un avantage. Dans la plupart des cas, les facteurs publiés n'auront plus de signaux de négociation car ils sont complètement exploités par le marché. Mais parfois, ils vous guideront dans la bonne direction.
Modèle de prix: tout modèle qui prédit les rendements futurs peut être un facteur, avec un potentiel potentiel de classement de votre panier d'indices. Vous pouvez utiliser n'importe quel modèle de prix complexe et le convertir en un schéma de classement.
Facteurs basés sur le prix (indicateurs techniques)Les facteurs basés sur les prix, comme nous le verrons aujourd'hui, permettent d'obtenir des informations sur les prix historiques de chaque intérêt et de les utiliser pour générer des valeurs de facteurs.
Retour et dynamiqueIl est intéressant de noter que certains facteurs considèrent que les prix continuent à évoluer une fois qu'ils se sont déplacés dans une direction. D'autres facteurs sont tout le contraire. Les deux sont des modèles efficaces pour différentes périodes et actifs, et il est important d'étudier si le comportement de base est basé sur la dynamique ou sur la régression.
Les facteurs de base (basés sur la valeur): c'est une combinaison de valeurs fondamentales utilisées, telles que PE, dividendes, etc. Les valeurs fondamentales contiennent des informations qui sont pertinentes pour les faits du monde réel de l'entreprise et peuvent donc être plus puissantes que le prix à bien des égards.
En fin de compte, les facteurs de prévision de croissance sont une course à l'armement, vous essayez de garder une longueur d'avance. Les facteurs seront retirés du marché et ont une durée de vie, vous devez donc travailler en permanence pour déterminer combien de votre facteur a connu une récession et quels nouveaux facteurs peuvent être utilisés pour les remplacer.
Chaque système de classement prédit des rendements sur des intervalles de temps légèrement différents. Les rendements moyens basés sur le prix peuvent être prévus en quelques jours, tandis que les modèles facteurs basés sur la valeur peuvent être prévisibles en quelques mois. Il est important de déterminer le laps de temps pendant lequel le modèle doit prédire et de vérifier statistiquement avant d'exécuter la stratégie.
Chaque stratégie a un volume de capital minimum et maximum, et les seuils minimaux sont généralement déterminés par le coût de la transaction.
Traiter trop de titres entraînera des coûts de transaction élevés. Supposons que vous souhaitiez acheter 1000 titres, chaque rééquilibrage entraînera des coûts de plusieurs milliers de dollars. Votre base de capital doit être suffisamment élevée pour que les coûts de transaction représentent une fraction du retour généré par votre stratégie. Par exemple, si votre capital est de 100 000 dollars et que votre stratégie gagne 1% par mois (environ 1000 dollars), tous ces retours seront pris en charge par le coût de la transaction.
Le seuil d'actifs le plus bas dépend principalement du nombre d'actions négociées. Cependant, la capacité maximale est également très élevée, et la stratégie d'équilibrage multi-espaces permet de négocier des centaines de millions de dollars sans perdre de l'avantage. C'est vrai, car la stratégie est relativement peu régulière pour rééquilibrer. Le nombre total d'actifs en plus du nombre d'actions négociées, la valeur en dollars de chaque action est très faible, et vous n'avez pas à craindre que votre volume de transactions affecte le marché.