Organisation

(NB : l'auteur s'est quelque peu laisser emporter sur ce post... à refaire...)

Coder c’est s’organiser. Plutôt que de me lancer dans explications sans fin, je vais vous donner un exemple d’organisation et vous laisser juger par vous-même de l’intérêt de la chose.

Voilà : pour des raisons qui me sont propres, je souhaite suivre les performances d’un certain nombre de fonds d’investissement. En l’occurrence, ce sont des mutual funds américains investis en actions étasuniennes que je compare — très logiquement — à l’indice S&P 500.

Ce que je voudrais, c’est disposer d’un historique complet de ces fonds (et du S&P 500) depuis le 31 mai 2012 (parce que !) ; historique prêt à l’emploi quand le besoin m’en prend.

Nous allons commencer, si vous le voulez bien, par créer un répertoire dédié à ce projet : mettez ça où vous voulez et appelez-le funds. Nous allons considérer que ce répertoire est situé à l’adresse :

C:/…/funds

Il se trouve que Yahoo! nous propose les données dont j’ai besoin à titre gracieux et que, mieux encore, l’entreprise dirigée par la très jolie Marissa Mayer a eu l’excellente idée de créer un système de requêtes en ligne qui génère des fichiers .csv à la demande.

Par exemple, si vous cliquez sur ce lien, vous récupèrerez les cours de l’indice S&P 500 du 31 mai 2012 au 31 mai 2013 au format .csv mais si vous cliquez sur celui-là, vous obtiendrez les cours d’Apple du 31 mai 2011 au 31 mai 2013.

En inspectant la manière dont ces liens sont construit (et, au besoin, en vous référant à cette page), vous pouvez assez facilement créer une fonction sous R qui permet de récupérer ces données pour n’importe quel titre et entre n’importe quelles dates.

Soit la fonction yget :

yget <- function(symb, from, to = Sys.Date(), quiet = TRUE) {
      
      # Construction de l'URL :
      url <- paste("http://ichart.finance.yahoo.com/table.csv?s=", 
            symb, 
            "&a=", as.numeric(format(from, "%m")) - 1, 
            "&b=", format(from, "%d"), 
            "&c=", format(from, "%Y"), 
            "&d=", as.numeric(format(to, "%m")) - 1, 
            "&e=", format(to, "%d"), 
            "&f=", format(to, "%Y"), 
            "&g=d&ignore=.csv", sep = "")
      
      # Lecture des données :
      res <- try(read.csv(url), silent = TRUE)
      
      # Notez l'usage de la fonction *try* qui renvoie un objet de classe
      # *try-error* en cas de problème :
      if(class(res) == "try-error") {
            
            # En cas d'erreur on renvoie un dataframe vide :
            res <- data.frame(Sym = NULL, Date = NULL, Open = NULL,
                  High = NULL, Low = NULL, Close = NULL, Adj.Close = NULL)
            
            # Et si *quiet = FALSE* on rajoute un avertissement :
            if(! quiet) warning("No data for ", sQuote(symb))
      
      # Sinon (i.e. si tout va bien) :
      } else {
            
            # On réordonne les données...
            res <- cbind(Sym = symb, res[order(res$Date), ])
      }
      
      # ... et on renvoie le résultat :
      return(res)
}

Ce qui nous donne :

> ans <- yget("^GSPC", as.Date("2012-05-31"))
> head(ans, 10)
      Sym       Date    Open    High     Low   Close     Volume Adj.Close
456 ^GSPC 2012-05-31 1313.09 1319.74 1298.90 1310.33 4557620000   1310.33
455 ^GSPC 2012-06-01 1309.87 1309.87 1277.25 1278.04 4669350000   1278.04
454 ^GSPC 2012-06-04 1278.29 1282.55 1266.74 1278.18 4011960000   1278.18
453 ^GSPC 2012-06-05 1277.82 1287.62 1274.16 1285.50 3403230000   1285.50
452 ^GSPC 2012-06-06 1285.61 1315.13 1285.61 1315.13 4268360000   1315.13
451 ^GSPC 2012-06-07 1316.15 1329.05 1312.68 1314.99 4258140000   1314.99
450 ^GSPC 2012-06-08 1314.99 1325.81 1307.77 1325.66 3497190000   1325.66
449 ^GSPC 2012-06-11 1325.72 1335.52 1307.73 1308.93 3537530000   1308.93
448 ^GSPC 2012-06-12 1309.40 1324.31 1306.62 1324.18 3442920000   1324.18
447 ^GSPC 2012-06-13 1324.02 1327.28 1310.51 1314.88 3506510000   1314.88

Formidable ! Copiez cette fonction et collez la dans un nouveau script que vous allez nommer ylib.R est sauvegarder à l’adresse :

C:/…/funds/ylib.R

L’air de rien, vous venez de poser le premier jalon de ce qui constituera — si ce genre de données vous intéressent — votre future de bibliothèque de fonctions dédiées à la récupération de données sur finance.yahoo.com.

Fermez ylib.R et ouvrez un nouveau script dans lequel nous allons écrire le code nécessaire à la mise à jour de nos données :

# ===========================================================================
# Yahoo! 
# ===========================================================================

# Le vicomte : Qu'est-ce que c'est que ça, s'il vous plaît ?
# Cyrano : C'est le titre.

# Ménage (au cas où) :
rm(list = ls(all = TRUE))

# Pointeur vers votre répertoire (vous n'avez que ça à taper !) :
.mydir <- "C:/.../funds"

# On charge la bibliothèque de fonctions :
source(file.path(.mydir, "ylib.R"))

# ---------------------------------------------------------------------------
# Params
# ---------------------------------------------------------------------------

# Le vicomte : Qu'est-ce que c'est que ça, s'il vous plaît ?
# Cyrano : Les paramètres de mise à jour.

# Nous voulons des données à partir du 31 mai 2012 :
from <- as.Date("2012-05-31")

# Une liste avec le S&P 500 et les fonds qui nous intéressent :
PeerGroup <- list(
    "^GSPC" = "S&P 500 Index",                           # (*)
      LMOPX = "Legg Mason Opportunity Trust",            # Bill Miller
      CPOAX = "Morgan Stanley Multi Cap Growth A",       # Lynch & team
      VCVLX = "Vanguard Capital Value Inv",              # Higgins & Palmer
      POAGX = "PrimeCap Odyssey Aggressive Growth Fund", # PrimeCap Team
      MXXVX = "Matthew 25"                               # Mark Mulholland
)

# (*) Ces types sont très très forts !

# ---------------------------------------------------------------------------
# Script 
# ---------------------------------------------------------------------------

# Le vicomte : Qu'est-ce que c'est que ça, s'il vous plaît ?
# Cyrano : Comment vous dire (sans être grossier) ?

# Téléchargement :
X <- lapply(names(PeerGroup), yget, from = from)

# Je construis un gros dataframe avec ce qui nous intéresse * :
Dta <- do.call(rbind, X)[, c("Sym", "Date", "Close", "Adj.Close")]
colnames(Dta) <- c("Sym", "Date", "NAV", "TR")
rownames(Dta) <- NULL

# (*) *Close* c'est le prix de clôture ; dans le cas d'un fonds on parlera
# plutôt de la *Net Asset Value* (NAV) et nous remplaçons *Adj.Close* (prix
# ajusté des dividendes) par *TR* (pour *Total Return*).

# On sauvegarde :
dump("Dta", file.path(.mydir, "Dta.R"))

Voilà un script bien ficelé dans lequel nous avons pris le soin de rajouter des commentaires (devant les #) afin de le rendre lisible à d’autres utilisateurs ou, d’ailleurs, à nous-mêmes si nous étions amenés à y revenir plus tard.

Enregistrons-le dans notre répertoire :

C:/…/funds/Update.R

Si vous exécutez ce script, vous constaterez qu’il créé un fichier Dta.R dans votre répertoire ; fichier dans lequel vous trouverez notre dataframe Dta. Il fera ça à chaque fois que vous l’exécuterez.

Seulement voilà : à ce stade, vous êtes encore obligés de lancer Rgui, d’ouvrir Update.R et de l’exécuter. C’est un peu fatiguant ; surtout si vous devez faire ça tous les jours. Nous allons donc nous simplifier le travail :

Avec un éditeur de texte — façon Bloc-notes de Windows — ouvrez un nouveau document texte et saisissez-y ceci :

"C:\Program Files\R\R-X.X.X\bin\Rscript.exe" "C:\...\funds\Update.R"

(R-X.X.X correspondant à votre version de R et "C:\...\funds\Update.R" étant l'adresse de Update.R.)

Lorsque c’est fait, sauvegardez ce fichier dans votre répertoire (appelez-le Update par exemple) en prenant soin de changer le suffixe .txt en .cmd :

Ce qui a pour effet de créer une chose de ce genre dans votre répertoire :

Double-cliquez sur la chose et vous obtenez :

... qui signifie que R est en train d'exécuter votre script.

Si c'est encore trop, rendez-vous dans le panneau de configuration, chapitre outils d’administration, où vous trouverez une section planificateur de tâches qui vous permettra de programmer le lancement automatiquement Update.cmd quand vous le souhaitez.

Voilà, ça n’est qu’un exemple et vous l’adapterez comme vous le souhaitez mais il a au moins l’avantage de vous montrer comment on se débarrasse d’une tâche quotidienne rébarbative au possible avec un peu d’organisation et quelques lignes de code.

Ce qui nous donne l’occasion de nous entraîner un peu…

Aucun commentaire:

Enregistrer un commentaire