Abwechslungsreiche Daten sind das Salz in der Suppe. Heute untersuchen wir, ob und wie zufallsgesteuerte Simulationen direkt in DeltaMaster erstellt werden können, ohne Veränderungen in der zugrundeliegenden Datenbank durchführen zu müssen.
In MDX-Befehlen kann bei Einsatz von Microsoft Analysis Services auch die VBA-Funktion rnd() zur Erzeugung von zwischen 0 und 1 gleichverteilten Zufallszahlen genutzt werden. Diese Funktion kann mit und ohne Argument verwendet werden.
Obwohl laut VBA-Funktionsbeschreibung sowohl rnd(4), als auch rnd() jeweils eine neue Zufallszahl erzeugen sollten, wirkt hier offensichtlich auch die Optimierungslogik der Analysis-Services-Engine, die wohl keinen Anlass sieht, den Ausdruck für jeden Monat neu auszuwerten.
Verkürzt man die Anzahl der gezeigten Monate auf 4, so hat die Engine anscheinend plötzlich einen aus externer Sicht nur schwer nachvollziehbaren Grund, bei rnd(4) für April einen neuen Wert zu erzeugen – dieses Verhalten ist zumindest auf dem verwendeten System ohne Ausnahme reproduzierbar!
Wir möchten nun aber nicht der Willkür der Optimierungslogik ausgesetzt sein. Sollen wirklich für jede Zelle neue Zufallszahlen generiert werden, muss man die Engine geschickt von der Notwendigkeit einer Neuberechnung “überzeugen”.
Ein Ansatz, der zu funktionieren scheint, ist, für jede Zelle ein eigenes Argument x für rnd(x) zu verwenden. Wir nehmen hier die laufende Nummer des Monats innerhalb aller Monate in der Zeitdimension, die über die Rank-Funktion berechnet werden kann:
Hat man zwei solcher gleichverteilter Zufallszahlen zur Verfügung, können nach der Methode von Box-Muller (*) auch normalverteilte Zufallszahlen erzeugt werden. Bei der zweiten für die Anwendung dieser Methode benötigten gleichverteilten Zufallszahl haben wir zur Sicherheit zum laufenden Monat einen Lag von 1000 addiert:
Nun möchten wir beispielsweise einen ARIMA-Prozess mit monatlicher Saisonkomponente simulieren und eine Zeitreihe Y(t) erzeugen, für die gilt: Y(t) = 1.5 * Y(t-1) – 0.6 * Y(t-2) + Y(t-12) – 1.5 * Y(t-13) + 0.6 * Y(t-14) + e(t)
Für die Fehler e(t) verwenden wir die oben hergeleiteten normalverteilen Zufallszahlen. In MDX sind rekursive Definitionen möglich, die wir hier wie in der Formel angewendet haben (-> ausführlichere Darstellung des Themas Rekursion in MDX für späteren Blogbeitrag merken).
Die folgende Grafik zeigt eine erzeugte Zeitreihe bis Oktober 2015 und die Prognose für die kommenden Monate, hier im illustrierenden Beispiel unter der Annahme, dass die wahren Koeffizienten bekannt sind und nicht geschätzt werden müssen (bitte klicken Sie auf die Grafik für eine vergrößerte Darstellung):
Diese Cockpits mit Ansicht Grafik sind auch Small-Multiples-fähig, sodass auch mehrere Simulationsläufe auf einmal durchgeführt werden können:
Jedes Betätigen der Taste F9 generiert einen weiteren Satz von möglichen Verläufen.
Möchte man eine bestimmte Simulation reproduzieren können, so geht dies auf dem verwendeten System, wenn die allererste erzeugte Zufallszahl rnd(#1) im Januar 2010 mit einem negativen Argument gestartet wird; mit diesem Kniff wird dann anschließend immer dieselbe Folge von Zufallszahlen generiert. Falls #1 der lfd. Monat ist, lautet die Definition anstelle von “rnd(#1)” nun beispielsweise “iif (#1=1,rnd(-12),rnd(#1))”. Hier stellt die -12 sicher, dass die Initialisierung fest und somit die Folge aller weiteren erzeugten Zufallszahlen eindeutig bestimmt ist.
Auch wenn manchmal von außen schwer nachvollziehbare Entscheidungen der Analysis-Services-Logik auftreten – solange die rnd()-Funktion zur Erzeugung von Beispielen und nicht zur Verschlüsseln geheimer Nachrichten verwendet wird, sollte einer solchen Anwendung nichts im Wege stehen.
(*) George Edward Pelham Box, Mervin Edgar Muller: A Note on the Generation of Random Normal Deviates. Ann. Math. Statist. 29 (1958), no. 2, 610–611. (Artikel hier abrufbar)