2016-12-09 6 views
1

Ich habe ein seltsames Problem mit einer Monte-Carlo-Simulation, die ich gebaut habe. Es ist eine geschachtelte Schleife, um den erwarteten Wert der Investitionen zu berechnen (eigentlich Poker Turniere). Nehmen wir zum Beispiel an, dass es sich um Heads-Up-Pokerturniere handelt, die einem Münzwurf gleichkommen. Nehmen wir an, dass wir einen ROI von 25% pro Münzwurf haben und der Buy-In eins ist, also der EV nach 100 (500, 1000) Coin-Flips 25 (125, 250) Einheiten ist. Die Simulation gibt jedoch 24,6, 123,6 bzw. 246 zurück. Die kritische Linie im Code ist hier:Monte-Carlo-Simulation in VBA unterschätzt konsequent den wahren Wert

Randomize 
randomnumber = Rnd() 
If randomnumber > adjustedITM Then 
MC_array(m, n) = -tournamentvariables(k, 6) 
Else: 
Randomize 
MC_array(m, n) = CDec(tournamentstructures(Int(Rnd() * (tournamentvariables(k, 7)) + 1), k) * tournamentvariables(k, 6) * (1 - tournamentvariables(k, 5)) * tournamentvariables(k, 2) - tournamentvariables(k, 6)) 
End If 

Die 2. MC_array (m, n) die kritische Code-Zeile ist. Es gibt den Nettogewinn, wenn der Spieler gewinnt. Im Falle eines Münzwurfs ist dies eine Einheit. Wenn ich die zweite Zeile in

ändern

Die Ergebnisse sind korrekt. Der Code nach dem 2. MCarray simpliefies für das Coin-Flip zu:

CDec(tournamentstructures(Int(Rnd() * (tournamentvariables(k, 7)) + 1), k) * tournamentvariables(k, 6) * (1 - tournamentvariables(k, 5)) * tournamentvariables(k, 2) - tournamentvariables(k, 6)) 

= 
CDec(tournamentstructures(1,1) * 1 * (1 - 0%) * 2 - 1) 

So ist es genau das gleiche wie ein. Das Array turnierstructures() hat die Größe (1,1), also kann es nichts einlesen. Ich habe überprüft, dass alle Ergebnisse ganze Zahlen sind (wie bei einem Münzwurf kann man nur eine Einheit gewinnen oder verlieren), vermute ich stark der Zufallszahlengenerator ist irgendwie vorgespannt.

Ich erklärte so ziemlich alles im Code als Variante und schloss das zweite Randomize aus, ohne dass es die Verzerrung änderte. Also Leute, was geht hier hin?

Antwort

1

Es sieht so aus, als ob Sie wiederholt Randomize aufrufen, vermutlich als Teil einer engen Schleife. Bei jedem Aufruf wird der Zufallsgenerator aus der Systemuhr resettet. Dies führt bei jedem Durchgang durch die Schleife zu Autokorrelationen (obwohl das genau nicht ganz klar ist).

Betrachten Sie das folgende Experiment:

Sub Test() 
    Dim i As Long, A As Variant 
    Dim count1 As Long, count2 As Long 
    ReDim A(1 To 10000) 

    For i = 1 To 10000 
     Randomize 
     A(i) = IIf(Rnd() < 0.5, 0, 1) 
    Next i 

    'count how often A(i) = A(i+1) 
    For i = 1 To 9999 
     If A(i) = A(i + 1) Then count1 = count1 + 1 
    Next i 

    For i = 1 To 10000 
     A(i) = IIf(Rnd() < 0.5, 0, 1) 
    Next i 

    'count how often A(i) = A(i+1) 
    For i = 1 To 9999 
     If A(i) = A(i + 1) Then count2 = count2 + 1 
    Next i 

    Debug.Print "First Loop: " & count1 
    Debug.Print "Second Loop: " & count2 & vbCrLf 

End Sub 

typische Ausgabe:

First Loop: 5452 
Second Loop: 4996 

Ich betreibe habe es mehrmals. Die erste Schleife erzeugt fast immer eine Zahl, die sich von 5000 um einen großen Betrag unterscheidet, während die zweite Schleife fast immer eine Zahl nahe 5000 erzeugt (der erwartete Wert ist 4999.5, wenn aufeinanderfolgende Aufrufe an Rnd unabhängigen Zufallsvariablen entsprechen) ein deutlicher Mangel an Unabhängigkeit beim wiederholten Nachsäen).

Moral der Geschichte: Anruf Randomize nur einmal in der Simulation, sagen wie die erste Zeile des Hauptunters. Alternativ können Sie auch Application.WorksheetFunction.RandBetween(0,1) verwenden und Excel über das Seeding sorgen lassen.

Wenn diese Autokorrelation den Fehler nicht erklärt, liegt das Problem in dem Code, den Sie nicht angezeigt haben, also müssen Sie diesen Code einfügen.

+0

danke, das ist genau was passiert ist! – IschaIschratioh

Verwandte Themen