Joli portrait publié sur Linkedin, de Franklin Feukam Kouhoue pour son mémoire d’actuariat sur l’explicabilité des modèles boites noires, qu’on avait supervisé avec Laurence Barry. Bravo Franklin.
Tag Archives: prix
Prix des Sciences du Risque de la Fondation Optimind – Accenture
Bravo à Franklin Feukam Kouhoue, qui a obtenu le prix des sciences du risques pour son mémoire de maîtrise en actuariat, à l’ENSAE, sur le thème de l’interprétabilié des modèles d’actuariat en tarification, sous la supervision de Laurence Barry, et moi-même.
Acheter un billet de train (pas trop cher)
Hier, je suis tombé sur article qui discutait des prix des billets de train, en France (et du prix très élevé, a certaines dates, genre pendant les vacances d’hiver). Tous ceux qui ont l’habitude de prendre le train savent que le prix que l’on paye dépend du moment ou on achète le billet (et de la souplesse que l’on peut avoir sur l’heure (voire la date) du trajet). Cet été, dans le cadre du projet de la formation Data Science pour l’Actuariat, pour mon cours, Pierre proposait de moissonner le site https://www.oui.sncf/ pour suivre un peu l’évolution du prix des billets.
Le principal soucis est que le site https://www.oui.sncf/ s’appuie sur du javascript pour les formulaires de saisie et pour l’affichage des résultats, ce qui empêche l’utilisation classique du package rvest, par exemple. J’avais évoqué dans un autre billet l’utilisation de wdman, pour scraper le site des incendies de forets. Ici, Pierre proposait de passer par casperjs, et je vais reprendre un peu ici sa stratégie:
- on va utiliser casperjs, un émulateur de navigateur écrit en javascript. Il permet d’émuler un véritable navigateur (même moteur que google chrome) et de résoudre le javascript intégrés à la page
- on va utiliser un petit code en bash pour lancer le code
Pour le code en bash, c’est juste que je suis sous mac et linux. Sous mac, on peut faire pas mal de choses en bash… Tout passe par des variables, que l’on peut définir, et afficher, par exemple
qui nous donne l’heure. Je peux aussi définir une variable, et l’incrémenter (pratique pour faire des boucles)
Plus intéressant, on peut planifier des taches. Pour ça, on tape
qui va ouvrir un éditeur,
Je demande ici de lancer un code R, tous les heures, a 13:50, 14:50, 15:50, etc. Pour demander tous les jours a 13:50, je tape
on va ensuite sauver l’instruction
On voit que la commande sera lancée, tous les jours : elle est dans la liste des taches a faire
notons qu’on peut lancer un code tout en passant des arguments : ici je lui dis quel objet manipuler (le premier argument) et le second sert pour créer un fichier (et pour le nommer).
Bref, c’est assez facile de lancer automatiquement des codes, pour scraper. Sous windows, on passe par le planificateur de taches. Un premier script permet d’extraire les trains ouverts dans la journée,
et le second, les trains ouverts depuis plus de 24 heures,
Ensuite, on va utiliser http://docs.casperjs.org/en/latest/ pour coder notre émulateur de navigateur internet (le code est ici en ligne).
On va ainsi créer plein de fichiers, contenant les informations que l’on veut ! Je vais passer un peu le retraitement, et juste présenter les informations qu’on peut en tirer. En particulier, Pierre avait stocke les données entre mars et juin dernier.
Ici, on est juste sur quelques trajets de grande ligne,
library(readr) library(rgdal) nomFichier = tempfile(fileext = ".zip") download.file("https://freakonometrics.free.fr/CarteFrance.zip", destfile = nomFichier, mode = "wb") unzip(zipfile = nomFichier, exdir = getwd()) download.file("https://freakonometrics.free.fr/LgTroncons.csv", destfile = "LgTroncons.csv", mode = "wb") download.file("https://freakonometrics.free.fr/CoordVilles.csv", destfile = "CoordVilles.csv", mode = "wb") fra0 = readOGR(dsn = paste(getwd(), "/CarteFrance", sep = ""), layer = "gadm36_FRA_0", verbose = F) LgTroncons = read_delim("LgTroncons.csv",";", escape_double = FALSE,locale = locale(decimal_mark = ","), trim_ws = TRUE) CoordVilles = read_delim("CoordVilles.csv",";", escape_double = FALSE,locale = locale(decimal_mark = ","), trim_ws = TRUE) NomsVilles = CoordVilles[CoordVilles$NOM_A_AFFICHER==1,] library(ggplot2) fr_df = fortify(fra0) ggp = ggplot() + geom_polygon(data=fr_df, aes(long, lat,group = group), fill = "#3A8EBA") ggp = ggp + geom_path(data = LgTroncons, aes(x = LONG, y = LAT, group = ID_TRONCON), colour= "#CC5500", lineend = "round", size=3) + geom_path(data = LgTroncons, aes(x=LONG, y=LAT, group = ID_TRONCON), colour="white", lineend = "round", size=1.75) ggp = ggp + geom_point(data = NomsVilles, aes(x=LONG, y=LAT), colour = "blue", fill = "white", shape=21, size = NomsVilles$PT_SIZE, stroke = NomsVilles$PT_STROKE) + theme_void() ggp = ggp + geom_text(data = NomsVilles, aes(x=LONG, y=LAT, label=NOM),hjust = NomsVilles$H_AJUST, vjust=NomsVilles$V_AJUST, colour = "white", fontface = "bold", size =3.25)+coord_fixed(1.47) ggp = ggp + ggtitle("Représentation des trajets étudiées") + theme(plot.title = element_text(hjust = 0.5, face="bold")) print(ggp) |
On va travailler sur les trajets suivants,
Comparons ici les billets pour un trajet Pars-Rennes, a partir des informations moissonnées pendant 3 mois, le vendredi soir, en particulier 2 vendredi de juin 2018 (les 15 et 22 juin). Pour ces deux jours, il y a eu 6 trains, entre 17 et 20 heures. Pour le 15 juin, les trois premiers ont commencé avec un prix de 45 €. Pour le 22 juin, le premier a commence a 45 €, mais les deux suivant on été lancés a 33 €. Assez rapidement, les prix sont monte a 45 €.
On peut regarder l’evolution du prix
Si on regarde plusieurs destination, on observe des comportement très différentes,
- pour Le Mans, les prix montent très vite, commençant a 15 €, montant a 18 € 10 heures après le lancement, 21 € le lendemdemain, 27 € au bout d’une semaine. En un mois, les prix ont presque doublé.
- pour Rennes, on observe une evolution similaire, passant de 20 € a 25 € en quelques heures, et 40 € deux semaines après !
- pour Toulouse en revanche, le prix initial est plus haut, 43 €, monte de 3 € en 10 heures, 6 € en 16 heures, pour rester a 49 €
Mais pour toutes les destinations, les prix sont croissants.
soit graphiquement
On peut aussi faire une carte. Si on regarde les prix a l’ouverture, Lille, Le Mans et Rennes sont peu chères.
Et les plus fortes variations sur 10 heures sont observées sur Nantes et Bordeaux.
Amusant non ?
Le prix de l’essence en cas de pénurie
Cet après midi, sur le site de 60 millions de consommateurs, Lionel Maugain revenait sur les stations services qui avaient de très fortes variations de prix pendant les jours de pénurie.
En utilisant la base des prix des carburants à la pompe, téléchargeable sur http://www.prix-carburants.economie.gouv.fr/, il est possible de visualiser ces fortes variations de prix. Pour lire la base, rien de plus simple
> rm(list=ls()) > annee=year=2016 > fichier="PrixCarburants_annuel_2016.xml" > library(plyr) > library(XML) > library(lubridate) > l=xmlToList(fichier)
Ensuite, on transforme la grosse liste en une série temporelle, à l’aide de la fonction suivante
> time_series=function(no,type_gas="Gazole"){ + prix=list() + date=list() + nom=list() + j=0 + for(i in 1:length(l[[no]])){ + v=names(l[[no]]) + if(!is.null(v[i])){ + if(v[i]=="prix"){ + j=j+1 + date[[j]]=as.character(l[[no]][[i]]["maj"]) + prix[[j]]=as.character(l[[no]][[i]]["valeur"]) + nom[[j]]=as.character(l[[no]][[i]]["nom"]) + }} + } + id=which(unlist(nom)==type_gas) + n=length(id) + jour=function(j) as.Date(substr(date[[id[j]]],1,10),"%Y-%m-%d") + jour_heure=function(j) as.POSIXct(substr(date[[id[j]]],1,19), format = "%Y-%m-%d %H:%M:%S", tz = "UTC") + ext_y=function(j) substr(date[[id[j]]],1,4) + ext_m=function(j) substr(date[[id[j]]],6,7) + ext_d=function(j) substr(date[[id[j]]],9,10) + ext_h=function(j) substr(date[[id[j]]],12,13) + ext_mn=function(j) substr(date[[id[j]]],15,16) + prix_essence=function(i) as.numeric(prix[[id[i]]])/1000 + base1=data.frame(indice=no, + id=l[[no]]$.attrs["id"], + adresse=l[[no]]$adresse, + ville=l[[no]]$ville, + lat=as.numeric(l[[no]]$.attrs["latitude"]) /100000, + lon=as.numeric(l[[no]]$.attrs["longitude"]) /100000, + cp=l[[no]]$.attrs["cp"], + saufjour=l[[no]]$ouverture["saufjour"], + Y=unlist(lapply(1:n,ext_y)), + M=unlist(lapply(1:n,ext_m)), + D=unlist(lapply(1:n,ext_d)), + H=unlist(lapply(1:n,ext_h)), + MN=unlist(lapply(1:n,ext_mn)), + prix=unlist(lapply(1:n,prix_essence))) + base1=base1[!is.na(base1$prix),] + date_d=paste(year,"-01-01 12:00:00",sep="") + date_f=paste(year,"-06-01 12:00:00",sep="") + vecteur_date=seq(as.POSIXct(date_d, format = + "%Y-%m-%d %H:%M:%S"), + as.POSIXct(date_f, format = + "%Y-%m-%d %H:%M:%S"),by="days") + date=paste(base1$Y,"-",base1$M,"-",base1$D, + " ",base1$H,":",base1$MN,":00",sep="") + date_base=as.POSIXct(date, format = + "%Y-%m-%d %H:%M:%S", tz = "UTC") + idx=function(t) sum(vecteur_date[t]>=date_base) + vect_idx=Vectorize(idx)(1:length(vecteur_date)) + P=c(NA,base1$prix) + vp=P[1+vect_idx] + vp=vp*100/(vp[!is.na(vp)][1]) + base2=ts(vp,start=year,frequency=365) + list(base=base1,ts=base2) + }
Dans l’article, la plus forte variation a été observée à Sevran. Pour récupérer la liste des stations services, on utilise
> ville=list() > for(no in 1:length(l)) ville[[no]]=l[[no]]$ville > ville=unlist(ville) > idx=which(ville=="Sevran")
Pour la première station, l’évolution du prix est relativement modérée
> plot(time_series(idx[1])$ts,col="red",type="l") > abline(h=100,lty=2)
Même si le prix semble avoir augmenté de 5% pendant les dernières semaines. Mais ce n’est effectivement rien en comparaison de l’autre station,
> plot(time_series(idx[2])$ts,col="red",type="l") > abline(h=100,lty=2)
avec un prix qui a augmenté de 50% en 2 mois, et presque 30% en quelques jours.
A Villeneuve-d’Asq, on retrouve un comportement similaire, mais moins important
> idx=which(ville=="Villeneuve-d'Ascq") > plot(time_series(idx[3])$ts,col="red",type="l") > abline(h=100,lty=2)
Quand faut-il acheter son billet d’avion ?
Lors de l’organisation des JEEA (ici), la principale incertitude était non pas le nombre de participants (qui n’a cessé d’augmenter jusqu’à ce qu’on se décide à clôturer, et finalement les prévisions faites il y a un mois, lorsque l’on a contacté les traiteurs pour les plateaux repas du midi se sont avérées très précises), mais les remboursements de frais de transports1.
Pour laisser toute souplesse aux intervenants, je leur avais laissé acheter eux-même leurs billets pour venir sur Rennes, sans aucune précision sur le mode de transport. Pour le train, les prix sont assez stables, mais j’avais très peur pour les personnes qui venaient en avion, qu’elles s’y soient prises trop tôt, ou trop tard et que le prix soit très élevé. Bref, comme à chaque fois que je dois acheter un billet d’avion, je me pose la même question: “existe-t-il une date optimale pour acheter ton billet d’avion en ligne ?”.
- Une petite étude sur 6000 vols (domestiques) américains
Benny Mantin a fait une étude semblable, en regardant sur la période de 3 mois précédant le départ (ou 90 jours pour être précis) un millier de vols (au sens origine-destination), chaque vol étant considéré à 6 dates différentes (6 mercredis consécutifs).
Par exemple pour un vol. ABQ-BOS (Albuquerque-Boston), on a les six évolutions de prix suivantes,
(on peut visualiser une prédiction par régression locale, en rouge). Si l’on prend comme prix de départ comme référence (base 100), on observe les évolutions suivantes sur les 200 premiers vols,
Vu de loin, on semble observer une réelle tendance avec un optimum à 30 jours du départ. Si on change la fenêtre de la régression locale, on obtient des résultats assez similaires,
pour un lissage beaucoup plus fin,
- Quelle est alors la date optimale ?
On peut d’ailleurs regarder la distribution de la date optimale de départ (sur la régression lowess). On note que la date optimale semble être 1 mois avant le départ,
Si on prend une fenêtre de lissage beaucoup plus fine, on observe la distribution suivante pour la date où le minimum est atteint,
Si on regarde quand est obtenu le minimum sur la base brute (ou plutôt le moment où est atteint le minimum pour la première fois, car le prix est parfois constant deux jours consécutifs), et non pas sur les données lissées, on obtient la distribution suivante,
Si on fait la même chose sur le moment où le minimum est atteint pour la dernière fois, on a
Ces deux graphiques sont beaucoup plus difficile à lire, car les données brutes sont beaucoup plus ératiques que la prédiction par régression locale.
- Quid de la volatilité des prix ?
Bon, c’est bien tout de voir qu’il est optimal d’attendre un mois avant le départ pour avoir un prix en moyenne plus bas. Mais c’est aussi la période où les prix sont les plus volatiles…. Par exemple sur le premier vol que nous avons étudié, si on normalise le prix en base 100 (comme dans la partie précédante) on obtient une volatilité de la forme suivante, qui augmente au fur et à mesure que l’on se rapproche de la date de départ.
Pour une personne qui ne cherche pas le meilleur prix en moyenne, mais qui cherche à éviter que le prix soit trop élevé, on peut regarder par exemple une régression quantile. La courbe en rouge ici présente le quantile à 90% du prix du billet d’avion.
Comme précédement, on peut chercher la date optimale pour que le prix – en tant que quantile et pas en tant que prix moyen – soit le plus bas possible,
Notons que l’on a chercher une régression quantile sous une forme polynomiale (ici un polynôme de degré 5). Si on utilise un polynôme de degré plus faible (par exemple 4), la distribution du maximum – sur la courbe lissée – change un peu, mais finalement pas tant que ça….
Ce qui confirmerait la robustesse de nos conclusions…
- est-il pertinant de commander ses billets depuis le bureau ?
Un dernier point avant de cloturer ce billet. Sur les graphiques suivant, on s’intéresse aux variations du prix du billet d’avion d’un jour sur l’autre (aux log-rendements). On s’intéresse là encore au premier vol, ABQ-BOS, avec les zones bleues correspondant aux week-end,
La courbe en rouge est une régression locale afin de visualiser une éventuelle tendance, avec un voisinage fin afin de prendre en compte les cycles hebdomadaires. Ce qui est intéressant, c’est que les plus grandes variations ont lieu en dehors des week-end, avec en particulier des baisses de prix en début de semaines, et de hausse de prix juste avant les week-end,
Afin de mieux visualiser ces centaines de courbes brutalement superposées, on peut plutôt superposer les tendances lissées,
Cette impression d’avoir des baisses les lundi et des hausses le vendredi est confirmé sur ce graphique. On peut aussi regarder brutalement la moyenne des log-rendement en fonction du jour,
On peut aussi étudier la volatilité brute, en chacun des jours,
On note que les prix sont relativement calmes le week end, et que généralement, ils ont tendance à baisser le lundi…. moralité, mieux vaut attendre de revenir au bureau pour commander son billet… Bon bien sûr, il faut habiter aux Etats-Unis….
1 un parti pris était de faire une conférence gratuite, en fournissant des repas le midi pour tous les participants. En contrepartie, la conférence avait obtenu des subventions de la chaire AXA grands risques, et de différentes entités locales (ville de Rennes, Rennes métropoles, conseils général et régional). Mais nous ne souhaitions pas trop solliciter le CREM (le labo de la faculté de sciences économiques). Bref, nous avions une limite dans notre budget, et avec une centaine de participants, nous ignorions réellement quelle souplesse nous avions….