Fonction DFA Detrended Fluctuation Analysis / parametre Hurst version VBA
Bonsoir,
J'essaie de faire une VBA pour calculer le paramètre de Hurst à l'aide du processus DFA Detrended Fluctuation Analysis
Mes données sont dans une feuille excel en colonne A de a2:a10000, mais cela peut etre moins
J'ai monté le code suivant :
Sub DFA()
Dim ws As Worksheet
Dim rng As Range
Dim data() As Double
Dim n As Integer, i As Integer, j As Integer
Dim scales() As Double, fluct() As Double
Dim segMean As Double
Dim alpha As Double
Dim lowerBound As Double
Dim upperBound As Double
Dim alphaSignificant As Boolean
' Définir la feuille de calcul et la plage de données
Set ws = ThisWorkbook.Sheets("rdt") '
Set rng = ws.Range("A2:A" & ws.Cells(Rows.Count, 1).End(xlUp).Row)
' Charger les données dans un tableau
n = rng.Rows.Count
ReDim data(1 To n)
For i = 1 To n
data(i) = rng.Cells(i, 1).Value
Next i
' Définir les échelles de 10^2.3 à 10^3.3
ReDim scales(1 To 11)
For i = 1 To 11
scales(i) = 10 ^ (2.3 + 0.1 * i)
Next i
' Calcul de DFA
ReDim fluct(1 To 11)
For i = 1 To 11
segMean = 0
For j = 1 To n
segMean = segMean + data(j)
If j Mod scales(i) = 0 Or j = n Then
segMean = segMean / scales(i)
fluct(i) = fluct(i) + (segMean - WorksheetFunction.Average(data)) ^ 2
segMean = 0
End If
Next j
fluct(i) = Sqr(fluct(i) / n)
Next i
' Régression linéaire pour trouver l'alpha
Dim coeffs As Variant
coeffs = WorksheetFunction.LinEst(Application.WorksheetFunction.Log(scales), Application.WorksheetFunction.Log(fluct), True, True)
alpha = -coeffs(1, 1)
' Intervalle de confiance pour alpha (ici, nous utilisons un intervalle de confiance de 95%)
lowerBound = alpha - 1.96 * coeffs(2, 1) ' 1.96 correspond au z-score pour un intervalle de confiance de 95%
upperBound = alpha + 1.96 * coeffs(2, 1)
' Tester la significativité de l'alpha (par exemple, tester si l'alpha est différent de 1)
If lowerBound > 1 Or upperBound < 1 Then
alphaSignificant = True
Else
alphaSignificant = False
End If
' Afficher l'alpha et le résultat
Et cela ne fonctionne pas !!!
Ce sont des calculs statistiques, si quelqu'un connait la modelisation et peut m'aider §§§!!!!????
Je pourrais le faire avec R mais cela semble encore plus compliqué
Merci beaucoup
bonjour,
je ne sais pas si les résultats sont okay, mais il montre des chiffres.
Bonjour
Merci bcp pour votre aide
J ai remodifié complétement mon code et cela ne fonctionne pas,
si quelqu'un a une idée, je suis preneuse ;.....
j'essaie à faire fonctionner la macro, sans savoir ce qu'elle doit faire, mais un moment donné, je dois prendre le log de 0
quand je relance ca plante
je vais dans le code et j ai en jaune : nValues(idx) = Log(currentN) ' Prenez le logarithme de n
pourquoi tu as deplace tout en haut :
Sub DFA()
Dim ws As Worksheet
Dim rng As Range
Dim data() As Double
Dim n As Integer, i As Integer
Dim mean As Double
Dim diff() As Double
Dim newY() As Double
' Tableau pour stocker les résidus
Dim residus() As Double, Boites
ReDim Boites(1 To 1)
Dim idx As Integer ' Indice pour suivre la position dans le tableau des résidus
Dim localFluctuation As Double
' Dim localFluctuation As Double
Dim overallFluctuation As Double
Dim sumFluctuations As Double
Dim totalBoxes As Integer
Dim nValues() As Double
Dim fnValues() As Double
'Dim idx As Integer
il y avait un souci dans les boites : cela doit etre :
' Définir les tailles des boîtes
boiteTailles = Array(250, 500, 1000, 1500)
les valeurs de l exposat n apparaissent pas en cellule 19,5 et 19.6
Comment se fait il que tu aies log 0 ?????
re,
il n'y a que 1000 lignes, donc ce 1500 causait un autre problème.
Mais mon plus grand problème est que je ne sais pas ce que la macro est supposé de faire, quand la macro se plante, j'essaie à penser pourquoi avec l'aide d'Alain Proviste. Donc, un peu d'explication ...
Je vais detailler cela, le plus clairement possible, et le faire suivre
J essaie de pas faire trop long et que cela soit clair
LE tout dans la journée
Je vais essayer de developper cela clairement
- Je rentre les données xt dans la colonne A, dans le cas present 1000 observations qui représentent une marche aléatoire, la longueur de la serie peut varier de 1000 observations à 10000
Colonne A, de A2:A1001
- Je calcule la moyenne des données de xt de la colonne A et je le fais apparaitre sur la feuille excel en colonne E
xbarre= moyenne (a2 :a1001)
- Je construis une serie intermediaire qui apparait en colonne B qui est la difference entre les obersations en A et la moyenne que j’ai calculé
B2 = a2- moyenne(a2:a1001)
B3 = a3- moyenne(a2 :a1001)
….
- Je calcule la série cumulative issue de la serie intermediaire et je le fais apparaitre dans la colonne C, cette serie se nomme yt
C2 = b2
C3 = c2 + b3
C4 = c3 + b4
…..
- Je divise ma serie yt en boites de donnees non chevauchantes, la longueur des boites sera de 100, 200, 250, 500, (je dois pouvoir les modifier suivant la longeur de la serie, en rentrant et en modifiant le code ce sera mieux)
Pour les boites de longueur 500 :
J aurai 2 boites distinctes de 500 observations, la premiere de c2:c501 et la seconde c502:c1001
Pour les boites de longueur 250 :
J’aurai 4 boites distinctes, ……
- Je vais calculer une regression lineaire pour chaque boites de manière distincte
Pour les boites de 500 : j’aurai deux regressions lineaires a calcuer, la premiere pour les 500 premieres données de c2 :c501 ; la seconde pour les 500 suivantes donnees de c502 :c1001
Pour les boites de 250, j’aurai 4 regressions linaires a calculer la premier de c2 :c251, la seconde de c252 :c501, la troisieme de c502 :c751 ; la derniere de c752 :c1001.
Ainsi de suite soit 5 regressions pour les boites de 200, 10regressions pour les boites de 100, et 20 regressions pour les boites de 50.
- Dernière étape, pour simplifier la procedure car je prefere faire les dernieres etapes manuellement, je souhaite avoir sur des pages excels distinctes les series de residus de mes regressions calculees
Ainsi sur une feuille nouvelle, j’aurai 2 series de residus correspondant a une longueur de boite 500, sur les colonnes A et B, la premiere colonne A aura 500 residus de a2 à 501, la colonne B aura 500 résidus de b2 à b 501
Sur une autre feuille, j’aurai 4 séries de résidus correspondant a une longueur de 250 observations, sur les colonnes a b c d
Ainsi de suite …., Le reste de la procédure je le ferai différemment, car j’aurai besoin d’examiner chaque serie de residus
En espérant avoir été claire
AD
Re
ci joint mon retour
y a un souci dans la regression
j'avais utilisé les valeurs originales (colonne A) au lieu de C, donc j'ai juste changé le 1 en 3, dans la ligne ici en dessous.
aP = Application.Index(aA, WorksheetFunction.Sequence(N, 1, 1 + (iSegment - 1) * N), 3) 'matrice avec N éléments à partir de ...
En plus, vous avez tous les variables maintenant dans les cellules à partir de AE1
TOP ! les resultats sont tous bons.
Est ce qu il est possible d utiliser le modele dela feuille regression pour mettre les residus pour chaque boite ???
1-1000 colonne A
1-500 colonne B
501-1000 colinne C
....
re, comme çà ?
nouveau PJ
Bonsoir
Merci bcp ! Ca fonctionne et les résultats sont justes !
J'ai vu et compris les correspondances des éléments des régressions en fonction des boites sur la feuille regressions (m1 b ssreg ....) par conséquent je n'ai pas besoin des résidus car j'ai tous les éléments nécessaires à savoir ssreg ssresid.
Le code se trouve dans le module 2 ??, Dans quelle partie se trouve les affichages des residus pour les enlever ?
Je vais essayer ensuite ce weekend de le tester avec plus de données et potentiellement plus de boites, je modifierai cette ligne
For Each iSegments In Array(1, 2, 4, 5, 10, 20, 50, 100) 'dviser vos données en 1,2,4,5,10,20,50 parts
et cela devrait suffire n'est ce pas ????
AD
re,
Oui, tout se trouve dans le module2.
ici dessous une partie de la macro, dans le double FOR...NEXT-loop, le texte barré est devenu inutile et remplacé par les 3 chiffres choisi (en rouge). Puis, 6 lignes plus loin, cet ancien chiffre 10 est remplace par le chiffre 3 (en rouge). C'est peut-être plus facile de cacher les lignes non-nécessaires
For i = 1 To 5 'le résultat de Linest est une matrice de 5 lignes
For j = 1 To 2 'et de 2 colonnes
'arr((i - 1) * 2 + j - 1) = x(i, j) 'vous ne voulez pas tout les 10
arr(0) = x(1, 1) 'le M1
arr(1) = x(1, 2) 'le b
arr(2) = x(5, 1) 'le ssReg
Next
Next
With Sheets("Regressions").Cells(1, ptr) 'a partir de cette cellule
.Value = "'" & 1 + (iSegment - 1) * N & "-" & iSegment * N 'ligne 1 = élements de ... à ...
.Offset(1).Value = iSegments & "." & Format(1 + (iSegment - 1) * N, "0000")
.Offset(2).Resize(3).Value = Application.Transpose(arr) 'résultat de la regression >>>>>>>>>>> maintenant seulement 3 des 10
.Offset(20).Resize(UBound(aP)).Value = aP 'les N éléments
If iSegment = 1 Then .EntireColumn.Borders(xlEdgeLeft).Weight = xlMedium 'une bordure à gauche de chaque "bloc"
ptr = ptr + 1
Puis ce règle For Each iSegments In Array(1, 2, 4, 5, 10, 20, 50, 100) 'dviser vos données en 1,2,4,5,10,20,50 parts, oui, c'est lui qui divise vos 1.000 points en 1, 2, 4 ... parties égales. 3 et 7, par exemple, seraient des mauvais choix (1.000 n'est pas un multiple). Vous pouvez ajouter ou supprimer des chiffres entre ces parenthèses. Et c'est le "currentregion" de la première ligne qui détermine les 1.000 (ou ...) lignes
With Sheets("rdt").Range("a1").CurrentRegion 'vos données
aA = .Offset(1).Resize(.Rows.Count - 1, 1) 'les éléments sans l'entête
Puis D1:F1 de rdt sont 3 chiffres de cet array et si vous lancez la macro "curves", vous recevez le graphique à côté.