web-dev-qa-db-fra.com

Comment télécharger des données boursières intrajournalières avec R

Tout, 

Je cherche à télécharger les données boursières de Yahoo ou de Google à des intervalles de 15 à 60 minutes pour obtenir le plus d’historique possible. J'ai trouvé une solution brute comme suit: 

library(RCurl)
tmp <- getURL('https://www.google.com/finance/getprices?i=900&p=1000d&f=d,o,h,l,c,v&df=cpct&q=AAPL')
tmp <- strsplit(tmp,'\n')
tmp <- tmp[[1]]
tmp <- tmp[-c(1:8)]
tmp <- strsplit(tmp,',')
tmp <- do.call('rbind',tmp)
tmp <- apply(tmp,2,as.numeric)
tmp <- tmp[-apply(tmp,1,function(x) any(is.na(x))),]

Compte tenu de la quantité de données que je cherche à importer, je crains que cela ne soit coûteux en calcul. Moi aussi, je ne comprends pas comment les horodatages sont codés dans Yahoo et Google. 

Ma question est donc double: quel est le moyen simple et élégant d’intégrer rapidement dans R les données d’une série d’actions, et comment interpréter l’horodatage des fichiers Google/Yahoo que j’utiliserais? 

21
Aaron

Je vais essayer de répondre d'abord à la question d'horodatage. S'il vous plaît noter que ceci est mon interprétation et je pourrais me tromper. 

En utilisant le lien dans votre exemple https://www.google.com/finance/getprices?i=900&p=1000d&f=d,o,h,l,c,v&df=cpct&q=AAPL, je reçois les données suivantes:

EXCHANGE%3DNASDAQ
MARKET_OPEN_MINUTE=570
MARKET_CLOSE_MINUTE=960
INTERVAL=900
COLUMNS=DATE,CLOSE,HIGH,LOW,OPEN,VOLUME
DATA=
TIMEZONE_OFFSET=-300
a1357828200,528.5999,528.62,528.14,528.55,129259
1,522.63,528.72,522,528.6499,2054578
2,523.11,523.69,520.75,522.77,1422586
3,520.48,523.11,519.6501,523.09,1130409
4,518.28,520.579,517.86,520.34,1215466
5,518.8501,519.48,517.33,517.94,832100
6,518.685,520.22,518.63,518.85,565411
7,516.55,519.2,516.55,518.64,617281
...
...

Notez la première valeur de la première colonne a1357828200, mon intuition était que cela ait quelque chose à voir avec POSIXct. D'où une vérification rapide:

> as.POSIXct(1357828200, Origin = '1970-01-01', tz='EST')
[1] "2013-01-10 14:30:00 EST"

Donc, mon intuition semble être correcte. Mais le temps semble s'être arrêté. Nous avons maintenant une information supplémentaire dans les données. TIMEZONE_OFFSET=-300. Donc, si nous compensons nos horodatages par ce montant, nous devrions obtenir:

as.POSIXct(1357828200-300*60, Origin = '1970-01-01', tz='EST')
[1] "2013-01-10 09:30:00 EST"

Notez que je ne savais pas quel jour vous aviez demandé. Mais une vérification rapide de Google Finance révèle qu’il s’agissait bien de niveaux de prix au 10 janvier 2013. 

enter image description here

Les valeurs restantes de la première colonne semblent être une sorte de décalage par rapport à la valeur de la première ligne. 

22
Chinmay Patil

Ainsi, le téléchargement et la normalisation des données ont fini par être plus pénibles que je ne le pensais - environ 150 lignes de code. Le problème est que, bien que Google fournisse des données sur les 50 derniers jours de formation pour tous les titres négociés en bourse, les horodatages de ces jours ne sont pas normalisés: un index de «1», par exemple, pourrait faire référence au premier ou au deuxième incrément de temps. le premier jour de bourse de l’ensemble de données. Pire encore, les stocks qui ne négocient que de faibles volumes ont uniquement des entrées dans lesquelles une transaction est enregistrée. Ce n'est pas un problème pour un stock à volume élevé comme APPL, mais pour les petites capitalisations à faible volume, cela signifie que votre série manquera beaucoup, sinon de la majorité des données. Cela posait problème car il fallait que toutes les séries d'actions soient parfaitement harmonisées pour l'analyse que je faisais. 

Heureusement, il existe encore une structure générale pour les données. En utilisant ce lien: 

https://www.google.com/finance/getprices?i=1800&p=1000d&f=d,o,h,l,c,v&df=cpct&q=AAPL 

et en changeant le symbole boursier à la fin, vous obtiendrez les 50 derniers jours de négociation sur des incréments d’1/2 heure. Les horodatages POSIX, très utilement décodés par @geektrader, apparaissent dans la colonne timestamp toutes les 3 semaines. Bien que les index d'horodatage ne correspondent pas invariablement d'une manière commode 1: 1 (je soupçonne presque que cela était intentionnel de la part de Google), il existe un motif. Par exemple, pour la série d’une demi-heure que j’ai examinée le premier jour de bourse de l’incrément de trois semaines, les index d’horodatage sont affichés de manière uniforme dans le quartier 1:15. Cela pourrait être 1:13, 1:14, 2: 15 - tout dépend du stock. Je ne suis pas sûr de ce que sont les 14e et 15e entrées: je soupçonne qu’il s’agit de résumés quotidiens ou d’informations commerciales après les heures normales de travail. Le problème, c’est qu’il n’ya pas de modèle cohérent sur lequel vous pouvez compter. Le premier timbre d’un jour de formation ne contient malheureusement pas toujours les données d’ouverture. Même chose pour la dernière entrée et les données de fermeture. J'ai découvert que le seul moyen de savoir ce qui représente réellement les données commerciales est de comparer les chiffres à ceux de la série sur Google Maps. Après des jours de futiley essayant de trouver comment extraire un schéma de mappage 1: 1 des données, je me suis orienté vers une stratégie "approximative". J'ai gratté les données de APPL (stock négocié à très fort volume) et défini ses index d'horodatage, chaque jour de bourse, comme valeurs de référence pour l'ensemble du marché. Tous les jours comportaient un minimum de 13 incréments, ce qui correspond au jour de négociation de 6,5 heures, mais certains en avaient 14 ou 15. Dans ce cas, je viens de tronquer en prenant les 13 premiers indices. À partir de là, j'ai utilisé une boucle while pour progresser essentiellement dans les données téléchargées de chaque ticker boursier et pour comparer ses index d'horodatage d'un jour de formation donné aux horodatages APPL. J'ai gardé le chevauchement, comblé les données manquantes et découpé les parties ne se chevauchant pas. 

Cela ressemble à une solution simple, mais pour les actions à faible volume avec des données de transaction éparses, il y avait littéralement des dizaines de cas spéciaux que je devais préparer et de nombreuses données à interpoler. J'ai obtenu des résultats assez étranges pour certains d'entre eux que je sais sont incorrects. Pour les actions à volume élevé, à moyenne et à grande capitalisation, toutefois, la solution a fonctionné à merveille: la plupart des séries ont été synchronisées de manière très nette avec les données APPL et correspondaient parfaitement à leurs profils Google Finance. 

Il n'y a aucun moyen de contourner le fait que cette méthode introduit une erreur, et je dois encore affiner la méthode pour les petites capitales de réserve. Cela dit, le décalage d'une série d'une demi-heure ou le comblement d'un intervalle incrémenté dans le temps introduit une erreur très mineure par rapport au mouvement global du marché et du stock. Je suis convaincu que mes données sont "assez bonnes" pour me permettre d'obtenir des réponses pertinentes à certaines de mes questions. Obtenir ce genre de choses coûte littéralement des milliers de dollars. 

Pensées ou suggestions? 

3
Aaron

Pourquoi ne pas charger les données de Quandl ? Par exemple.

library(Quandl)
Quandl('YAHOO/AAPL')

Update: désolé, je viens de me rendre compte que seules les quotidiennes données sont récupérées avec Quandl - mais je laisse ma réponse ici car Quandl est très facile à interroger dans des cas similaires

1
daroczig

Pour le décalage horaire, essayez:

as.POSIXct (1357828200, Origin = '1970-01-01', tz = Sys.timezone (location = TRUE))

(Le tz s'ajustera automatiquement en fonction de votre emplacement)

0
sempedocles