Pouvons-nous prévoir le marché boursier en utilisant uniquement les prix de clôture?

DEV - 18/06
Les données sur les cours des actions sont partout en ligne, ce qui signifie l'ouverture, la fermeture, les hautes, les bas, le volume et un tas de ...

Les données sur les cours des actions sont partout en ligne, ce qui signifie l'ouverture, la fermeture, les hautes, les faibles, le volume et un tas d'indicateurs basés sur eux. C'est gratuit et facile à obtenir. D'un autre côté, d'autres types de données qui pourraient être utiles pour les prévisions, comme les états financiers ou le sentiment du marché, sont souvent plus difficiles à trouver, et peuvent être vraiment (parfois vraiment) chers.

Pour cette raison, beaucoup de gens ont essayé de prédire le marché boursier en utilisant uniquement les données des prix, en particulier le prix de clôture. Vous pouvez trouver de nombreux articles montrant des modèles qui semblent faire du bon travail, avec des prix prévus qui semblent très proches des vrais. Mais dans de nombreux cas, ces articles n'incluent pas une évaluation appropriée, même les mesures de base comme MAE ou MSE sont souvent manquantes.

Donc, cela m'a fait réfléchir: pouvons-nous réellement prévoir les cours des actions en utilisant uniquement les prix passés? Dans cet article, je vais essayer de répondre à cela en testant certains des modèles populaires flottant en ligne et en les évaluant en utilisant une approche simple (mais honnête).

Si vous êtes curieux ou si vous souhaitez creuser dans les détails, tout est disponible sur Github. Je n'ai pas inclus les instructions d'importation ici pour garder les choses propres, mais vous trouverez tout le code, les données et la configuration là-bas.

Quelles données j'utilise?

Les données sur les cours des actions sont faciles à trouver en ligne, alors n'hésitez pas à utiliser la source que vous préférez. Pour cet article, j'utilise un ensemble de données que j'ai déjà analysé et nettoyé. Il comprend 17 610 lignes de données de 10 sociétés bien connues, couvrant la période du 1er janvier 2018 au 1er janvier 2025.

df = pd.read_csv ('data.csv', index_col = 0) df.head ()
Entrez le mode de sortie en mode plein écran
symboledatefermer
0AAPL2024-12-31250.42
1AAPL2024-12-30252.20
2AAPL2024-12-27255.59
3AAPL2024-12-26259.02
4AAPL2024-12-24258.20

J'encourage cela comme un problème de série chronologique, où l'entrée (x) n'est que les prix de clôture passés, et la cible est le retour au cours des x jours suivants. Pourquoi utiliser le retour au lieu du prix lui-même? Principalement parce que les prix peuvent varier considérablement entre les entreprises: un actions de 10 $ et un actions de 1 000 $ se comportent très différemment en nombre brut. L'utilisation des retours aide à normaliser les choses à tous les niveaux.

Voici le code que j'ai utilisé pour créer les données de séries chronologiques:

DEF PREPECT_SUPERVISED_RETURN_DATA (DF: PD.DATAFRAME, Window_Size: int = 60, prévisé_horizon: int = 10): df = df.copy () df.sort_values ​​(par = ['symbol', 'date'], inplace = true) # Assurez-vous que les données sont triées chronologiques par actions df ['symbol']. Unique (): Stock_df = df [df ['symbol'] == symbol] .reset_index (drop = true) # boucle sur la série temporelle, en laissant l'espace au début pour la fenêtre, et à la fin pour l'horizon de prévision pour i dans Range (Window_Size, Len (Stock_df) - prévision_horzon): row = 'Symbol': Symbol, - prévision_horzon): row = {'Symbol': symbole, - prévision_horzon): row = {'Symbol': Symbol, - prévisionne Stock_df.loc [i, 'Date'], 'Price': Stock_df.loc [i, 'close']} # Extraire le passé `Window_Size` Clôture en tant qu'entrée Input_seq = Stock_df.loc [i - Window_Size: i - 1, 'Close']. np.mean (input_seq)) / np.std (input_seq) if np.isnan (input_seq) .any (): continuez # sauter cette ligne si la normalisation a produit nans # Ajouter chaque retour normalisé en tant que fonctionnalité pour j dans la plage (window_size): row [f'ret_t- {window_size - j} '] = entrée_seq [j] # compute le retour sur la prochaine `prévisé_horizon` jours en tant que cible cible_price = stocke_df.loc [i + prévision_horizon, 'close'] current_price = stock_df.loc [i, 'close'] cible = (target_price - current_price) / current_price if pd.isna (Target): continue # skip if a cible est nan row ['' DataFrame avec tous les échantillons de séries chronologiques res_df = pd.dataframe (out) res_df.sort_values ​​(par = ['date'], inplace = true) return res_df.reset_index (drop = true)
Entrez le mode de sortie en mode plein écran

Comme vous pouvez le voir, la normalisation se fait dans chaque séquence d'entrée. Cela aide à résoudre le problème que j'ai mentionné plus tôt à propos de différentes échelles de prix entre les entreprises. N'hésitez pas à expérimenter les paramètres si vous le souhaitez. Cette configuration est censée être un point de départ simple et solide.

J'ai choisi un horizon de prévision de 10 jours car il sonne un bel équilibre: ...
[Courte citation de 8% de l'article original]

Loading...