Avec @renaudjf, on discutait l’autre jour de la simulation d’un processus de Lévy. Et on se posait la question d’un algorithme optimal pour combiner un processus de Poisson (ou un process Poisson composé) avec un processus de Wiener (avec éventuellement un drift, voire une diffusion plus générale). En fait, pour générer des processus de Poisson, j’ai toujours eu l’habitude de simuler les durées entre sauts (avec des lois exponentielles, indépendantes, comme dans des vieux billets). Jean François me suggérait d’utiliser une propriété d’uniformité des sauts sur un intervalle de temps donné, conditionnellement aux nombres de sauts.
Commençons par la première piste. On peut générer un processus de Wiener, éventuellement avec un drift, et à coté, on peut générer les lois exponentielles (qui vont correspondre aux durées entre sauts), et éventuellement aussi des amplitudes de sauts (e.g. des pertes qui suivent des lois exponentielles). On a ici
où . On commence par générer en notant que
où les incréments sont Gaussiens (centrés et de variance ) et indépendants les uns des autres. Quant aux durées entre sauts, les , ce sont des lois exponentielles indépendantes, de moyenne . Voilà le code qui permet de générer les trois composantes,
n=1000 h=1/n lambda=5 set.seed(2) W=c(0,cumsum(rnorm(n,sd=sqrt(h)))) W=rexp(100,lambda) N=sum(cumsum(W)<1) T=cumsum(W[1:N]) X=-rexp(N)
Le hic est que pour le processus de Wiener, on a du discrétiser, alors que pour le processus de Poisson composé, non. Pourtant, il va bien se ramener sur une même échelle de temps. Une première piste est de créer vraiment la fonction
Lt=function(t){ W[trunc(n*t)+1]+sum(X[T<=t])+lambda*t }
et pour faire un dessin ensuite, c’est un jeu d’enfant
L=Vectorize(Lt) u=seq(0,1,length=n+1) plot(u,L(u),type="l",col="blue")
Une autre possibilité est d’utiliser une propriété d’uniformité du processus de Poisson que j’évoquais en introduction. Car le processus de Poisson vérifie une propriété remarquable: si est la date où survient le ième saut, , alors conditionnellement au fait que , les variables correspondent aux statistiques d’ordres de variables indépendantes, uniformément distribuées sur , i.e.
Cette propriété se trouve dans Wolff (1982). L’idée de la démonstration est relativement simple. Commençons avec un (unique) saut, alors pour ,
i.e. on retrouve la fonction de répartition d’une loi uniforme sur . On itère ensuite avec 2 sauts, 3 sauts, etc.
La traduction en R de cette idée est tout simplement (car on se place sur )
N=rpois(1,lambda) T=runif(N) X=-rexp(N)
Ensuite, une stratégie est de discrétiser le processus de Poisson, avec le même pas de temps que le processus de Wiener,
indice=trunc(T*n)+1 saut=rep(0,n+1) saut[indice]=X processus=W+cumsum(saut)+lambda*u
On retrouve la même trajectoire qu’auparavant
plot(u,processus,type="l",col="red")
,,
Sauf qu’on a eu de la chance. Avec cette procédure, il ne faut pas que l’on ait deux sauts dans le même intervalle de temps ! Bon, il est vrai qu’une caractérisation du processus de Poisson est que
et donc on doit avoir très peu de chance d’avoir deux sauts au même instant d’autant plus que le pas de temps est petit. Mais “peu de chance” ne veut pas dire nul, et si on génère des milliers de trajectoires, la probabilité d’avoir une fois un soucis n’est pas négligeable.
Jean-François a eu l’idée brillante de proposer de tirer non pas des lois uniformes sur , mais des lois uniformes discrètes, dans
T=c(0,sort(sample((1:(n-1)/n),size=N,replace=FALSE)))
sans remise afin d’éviter d’avoir deux sauts au même moment. L’idée était séduisante, mais il me restait à etre convaincu que les durées entre sauts… continuaient à être (presque) exponentielles.
Pour ça, on peut faire quelques tests. Par exemple, générer quelques simulations pour avoir une centaines de sauts (et donc une centaine de durées entre sauts), puis faire un test de loi exponentielle (de moyenne )
VT=0 for(ns in 1:20){ N=rpois(1,lambda) if(N>0){ T=c(0,sort(sample((1:(n-1)/n),size=N,replace=FALSE))) VT=c(VT,diff(T)) }}
On fait ici 20 boucles car on avait fixé
lambda=5
et j’avais dit que je voulais une centaine d’observations pour faire un test de loi (ce qui est purement arbitraire, on en conviendra). On peut ensuite faire un test d’ajustement de loi exponentielle,
ks.test(VT[-1],"pexp",lambda)$p.value
Si on répète un grand nombre de fois, en changeant le pas de temps (ou le nombre de subdivisons de l’intervalle de temps), on notera qu’effectivement, avec un grand pas de temps (à gauche ci-dessous) on rejette souvent, voire presque toujours, l’hypothèse de loi exponentielle. Mais qu’assez vite, c’est une hypothèse qui n’est pas invraisemblable,
Je ne sais pas entre ces deux fonctions ce qui serait le plus rapide, mais on a deux jolis algorithmes pour générer les processus de Lévy. Non ?