计算有些复杂赌注的“差异”

时间:2018-03-12 15:22:50

标签: vb.net math probability variance gambling

我有一个程序可以计算某种投注的各种指标,例如EV,获胜机会等等。我还想要的是衡量投注“差异多大”的指标。而我明确指出的是:“经过多次重复下注后,你将有多少时间用完X现金。”我目前通过运行模拟来做到这一点,但这非常慢。我正在寻找一种方法来使用更直接的数学/计算解决方案。

赌注不只有两个结果。它有一个失败状态,任何给定数量的获胜状态,具有不同的概率和不同的支出,数据全部提供给该计划。

这就是我目前使用模拟的方式:

Function GetOutcomeList() As List(Of Integer)
    Dim result As New List(Of Integer)
    For i = 1 To combos
        Dim addcount As Integer = Math.Round((windistribution(i, 0, 1) / winchance(0)) * 500000)
        For j = 1 To addcount
            result.Add(windistribution(i, 0, 0))
        Next
    Next
    Return result
End Function

上面的函数填充一个列表,使得该列表中任何随机挑选的元素都有被挑选的相同概率。

Function GetVarianceMetric(bankroll As Integer) As Double
    Dim simcount As Integer = 4000
    Dim numofgames As Integer = bankroll / (bet ^ 0.6)
    Dim simspassed As Integer = 0
    Dim outcomeList As List(Of Integer) = GetOutcomeList()
    For sims = 1 To simcount
        Dim cash As Double = bankroll
        For i = 1 To numofgames
            Dim roll As Double = generator.NextDouble
            cash -= bet
            If roll <= winchance(0) AndAlso cash >= 0 Then
                cash += outcomelist(generator.Next(1, outcomelist.Count))
            ElseIf cash <= 0 Then
                Exit For
            End If
        Next
        If cash > 0 Then
            simspassed += 1
        End If
    Next
    Return (simspassed / simcount) * 100
End Function

以下是我尝试实施meowgoesthedog的解决方案,最终比我的monte carlo解决方案慢得多,当时需要更多的赌注/结果:

 Structure OutCome
    Dim prob As Double
    Dim cashChange As Integer
End Structure

Function GetNewVarianceMetric(bankroll As Integer) As Double
    Dim n As Integer = 10
    Dim out_list(winstates) As OutCome
    Dim taken(winstates) As Boolean

    For i = 0 To winstates - 1
        Dim biggest() As Integer = {0, 0}
        For j = 1 To winstates
            If taken(j) = False AndAlso (windistribution(j, 0, 0) - betsize) >= biggest(1) Then
                biggest(1) = windistribution(j, 0, 0)
                biggest(0) = j
            End If
        Next
        Dim oc As New OutCome
        oc.cashChange = windistribution(biggest(0), 0, 0) - betsize
        oc.prob = windistribution(biggest(0), 0, 1)
        out_list(i) = oc
        taken(biggest(0)) = True
    Next
    Dim ocLose As New OutCome
    ocLose.cashChange = -betsize
    ocLose.prob = 1 - winchance(0)
    out_list(winstates) = ocLose
    Dim prob_list(winstates) As Double
    Dim c As Double = 0
    For i = winstates To 0 Step -1
        c += out_list(i).prob
        prob_list(i) = c
    Next
    Dim prob_runout As Double = prob_enough(n, bankroll, out_list, prob_list) * 100
    Return prob_runout
End Function

Function prob_enough(n As Integer, x As Integer, out() As OutCome, probs() As Double) As Double
    If x <= 0 Then
        Return 0
    End If
    If n <= 1 Then
        Dim i As Integer = search_smallest(out, x)
        If (i < winstates) Then
            Return probs(i)
        Else
            Return 0
        End If
    End If
    Dim S As Double = 0
    For i = winstates To 0 Step -1
        If out(i).cashChange < -x Then
            Exit For
        End If
        S += out(i).prob * prob_enough(n - 1, x + out(i).cashChange, out, probs)
    Next
    Return S
End Function

Function search_smallest(out() As OutCome, x As Integer) As Integer
    Dim left As Integer = 0
    Dim right As Integer = winstates
    While left < right
        Dim i As Integer = (left + right) / 2
        If out(i).cashChange >= -x Then
            right = i
        Else
            left = i + 1
        End If
    End While
    Return left
End Function

2 个答案:

答案 0 :(得分:0)

如果我正确地阅读了您的问题,您可以通过多种不同的方式下注并赢得&#34;或者&#34;输掉&#34;。我相信你首先需要确定每次输赢的适当分配函数。然后,您需要将这些函数中的每一个作为一个独立变量进行评估,并确定一个代表您的函数集合的分布函数。简而言之,您需要找到这组概率函数的联合密度函数。这不是一个简单的操作,尽管有几种方法可以解决它。您使用的确切方法取决于每个结果所代表的分布函数的类型以及这些函数的行为。

这不是一个简单的操作,你可能更容易(但更慢)从经验方法中去做。

答案 1 :(得分:0)

你提出的问题听起来并不像我所知道的那种“差异”,所以我只能把它搁置一边。此外,我将假设您的问题具体关于计算资金耗尽的可能性,而不是关于一般统计计算(这将太宽泛)。< / p>

对于n投注和m结果,有一种确定性方法可以在enter image description here时间内解决此问题:

  1. 假设我们最初有Am个结果数组,每个结果的相关概率p货币变化 y (支付减去初始存款)。按y排序此数组。

  2. 从数组的 end 开始计算累积概率。最后应该加1。

  3. 使用n, X调用例程,其中n是剩余投注数,X是当前预算。

  4. 如果n = 1使用二进制搜索,请找到i索引A[i:] >= -X。这是玩家能负担得起的最昂贵的结果。返回此指数的累积概率。

  5. 如果n > 1,请为输出概率保留变量S,并将其初始化为0.从上面开始,对于A[i] >= -X的所有值,如上所述:

    • 从(3)开始执行递归调用,预算为n - 1, X + A[j].y
    • 将返回结果乘以A[j].p并添加到S
    • 最后,返回S
  6. 以上内容可能会让您感到困惑。该算法探讨了所有可能的方式下注n而没有用完资金,并以连续投注独立为由积累其概率。

    请注意,这是 1减去您想要的数量(超出预算的概率);计算这个数量的原因是,因为我们在预算范围内,我们可以花费的金额总是从上面限制,这意味着我们需要测试的案例更少。

    编辑:示例实施:

    struct outcome
    {
       double prob;   // probability "p"
       int change;    // change in money "y"
    };
    
    // search for the most expensive bet
    static size_t search_smallest(const vector<outcome> & out, int X)
    {
       size_t left = 0, right = out.size();
       while (left < right)
       {
          size_t i = (left + right) / 2;
          if (out[i].change >= -X)
             right = i;
          else
             left = i + 1;
       }
       return left;
    }
    
    // compute the probability that it is enough
    static double prob_enough(unsigned n, int X,
       const vector<outcome> & out, const vector<double> & probs)
    {
       if (X <= 0) return 0.0;
    
       if (n <= 1) {
          size_t i = search_smallest(out, X);
          return (i < out.size()) ? probs[i] : 0.0;
       }
    
       double S = 0.0;
       for (size_t i = out.size(); i > 0; i--)
       {
          if (out[i - 1].change < -X) break;
          S += out[i - 1].prob * prob_enough(n - 1, X + out[i - 1].change, out, probs);
       }
       return S;
    }
    
    int main()
    {
       int n, X;
       // input number of bets and budget
       // ...
    
       vector<outcome> out_list;
       // input different outcomes and fill out_list
       // ...
    
       // sort out_list with respect to y
       sort(out_list.begin(), out_list.end(),
          [](const outcome & a, const outcome & b) { return a.change < b.change; });
    
       // create cumulative list
       vector<double> prob_list(out_list.size());
       {
          double c = 0.0;
          for (size_t i = out_list.size(); i > 0; i--)
          {
             c += out_list[i - 1].prob;
             prob_list[i - 1] = c;
          }
       }
    
       double prob_runout = 1.0 - prob_enough(n, X, out_list, prob_list);
    }
    

    测试用例:

    X = 7, n = 3
    
    Outcome no.     |  1     2     3
    ----------------------------------- 
    Change      (y) | -10    1     2
    Probability (p) | 0.5   0.4   0.1
    
    --> prob_runout = 0.83
    

    确认 - 在所有投注完成之前用尽的不同方式:

    Outcomes  | Probability
    ----------|---------------------
    [1, ., .] | 0.5         = 0.5
    [2, 1, .] | 0.4*0.5     = 0.2
    [3, 1, .] | 0.1*0.5     = 0.05
    [2, 2, .] | 0.4*0.4*0.5 = 0.08
                      Total = 0.83