2016 年六月

第 31 卷,第 6 期

本文章是由機器翻譯。

測試回合 - 預測市場介紹

James McCaffrey

James McCaffrey假設您想要預測 Xrays 和 Yanks 之間即將推出的冠軍美式足球遊戲的結果。您尋找 20 美式足球專家便分成群組,並且給予每個 $500 權杖中。專家可以購買和銷售的每個股票市場的運作方式有點類似的方式在兩個小組共用。

當專家購買共用在一個小組中,假設 Xrays,該小組共用的價格增加,而且其他小組共用的價格會減少。經過一段時間,專家將買賣的兩個小組共用直到價格穩定,然後您就能夠推斷每個小組獲獎的機率。

您可以停止交易冠軍遊戲前的一天。遊戲,就會播放,並決定優勝者之後,您會支付交易關閉時,團隊根據過去的價格勝出小組擁有共用的專家。由於專家知道要支付,必須為 true 的意見提供交易期間的動機。

什麼前述稱為預測市場。本文中,我將說明預測市場背後的數學,告訴您如何在程式碼中實作的索引鍵的函式。也不太可能,您所建立的預測市場在日常工作中,但我相信您會發現想法很有趣。此外,本文中的程式設計技術的一些可以使用更常見的軟體開發案例中。

本文假設您有至少初學者程度的程式碼撰寫技巧,但不會假設您了解預測市場。我提供完整的範例程式,您也可以從本文所附的下載取得的原始程式碼。範例將使用 C# 中,但您應該會有重構另一種語言的程式碼,如果您想要毫無障礙地。

請注意,這主要適用於軟體開發人員的預測市場的非正式簡介。若要保留的主要概念盡可能清楚才能術語與定義一些有點彈性。

範例{\lang1033 }

利用具體的範例,說明預測市場也許是最佳選擇。看一看在演示程式圖 1。在一些初步的訊息之後示範輸出開頭 ︰

Setting liquidity parameter = 100.0

Initial number of shares owned of teams [0] and [1] are:
0 0

Initial inferred probabilities of winning are:
 0.5000  0.5000

預測市場示範
[圖 1] 預測市場示範

流動資產參數將會詳細說明短時間內,但目前為止已經足以知道流動資產控制多少回應買入和賣出市場價格。流動的較大的值會產生較小的變更,價格。

一開始,由專家提供擁有共用。因為每個小組所擁有的共用數目是相同的 (零),就很合理初始推斷小組贏的機率是 0.50。

示範輸出的下一個部分是 ︰

Current costs for one share of each team are:
 $0.5012  $0.5012

在任何時間點,每個小組的共用中有某些價格。專家需要了解此價格是因為他們進行遊戲為真實的金錢。因為初始獲獎的機率都相等,就很合理,每個小組的共用價格也是一樣。

示範輸出的下一個部分是 ︰

Update: expert [01] buys 20 shares of team [0]

Cost of transaction to expert was: $10.50

專家 #1 認為該小組 0,Xrays,將有機會贏得和購買的小組 0 20 共用。專家的成本是 $10.50。請注意,20 共用 ($10.50) 的價格不相同的單一共用價格 20 倍 (20 * $0.5012 = $10.02)。因為每個共用為購買,小組的其他共用的價格會增加。示範輸出的下一個部分是 ︰

New number of shares owned of teams [0] and [1] are:
20 0

New inferred probabilities of winning are:
 0.5498  0.4502

示範在每個小組,(x,y) 顯示更新的未處理的共用數目 = 20 (0) 和計算,並顯示更新推斷 (0.55、 0.45) 每個小組獲獎的機率。由於專家已購買小組小組 1 非 0 的多個共用,推斷的小組 0 獲獎的機率必須是小組的大於 1。稍後將說明機率的計算。

接下來,會顯示此示範 ︰

Current costs for one share of each team are:
 $0.5511  $0.4514

Update: expert [02] buys 20 shares of team [1]

Cost of transaction to expert was: $9.50

計算並顯示每個共用的每個小組的新成本。請注意,價格的小組 0 的共用 ($0.55) 現在稍微昂貴的小組 1 ($0.45)。這可讓專家動機購買 team 1 的共用,除非他們認為代價就是適合的值相對於小組 1 獲獎的可能性。在此情況下,示範模擬購買 20 共用小組 1,成本的 $9.50 的專家 #2。下一個:

New number of shares owned of teams [0] and [1] are:
20 20

New inferred probabilities of winning are:
 0.5000  0.5000

現在有 20 共用未處理的每個小組,因此還原成 0.50 和 0.50 的推斷每個小組成功的機率。

示範輸出的下一個部分是 ︰

Current costs for one share of each team are:
 $0.5012  $0.5012

Update: expert [03] buys 60 shares of team [0]
Cost of transaction to expert was: $34.43

New number of shares owned of teams [0] and [1] are:
80 20

New inferred probabilities of winning are:
 0.6457  0.3543

專家 #3 認為強 0 該團隊就贏了,所以他購買的 0,成本的團隊 $34.43 60 共用。此交易的未處理的共用資料夾,數目的變更 (80,20),並造成新推斷強烈偏向小組 0 (0.65、 0.35) 獲獎的機率。

接下來,專家 #1 所看到他共用小組 0 的值已大幅上升到約 $0.6468 每個共用 ︰

Current costs for one share of each team are:
 $0.6468  $0.3555

Update: expert [01] sells 10 shares of team [0]
Cost of transaction to expert was: $-6.34

New number of shares owned of teams [0] and [1] are:
70 20

New inferred probabilities of winning are:
 0.6225  0.3775

專家 #1 感覺團隊 0 現在有些訂價過高相對於其獲獎的機會,並銷售的他 20 的共用,10,取得 $6.34 (以負號表示)。新推斷機率調整回有點更相等,但仍預測機率 0.63 贏得小組 0。

示範結束關閉交易。最終的機率是預測市場的目標。遊戲 Xrays 和 Yanks 之間,就會播放之後,專家會支付它們保存在勝出的小組中,根據最終共用價格勝出的小組共用。付款鼓勵專家提供給他們,則為 true 的意見。

四個索引鍵的預測市場方程式

基本預測市場中所示,使用四個數學方程式 [圖 2。請容我;方程式不幾乎一樣複雜,因為第一次可能會出現。有數個可以用於定義預測市場的數學模型。本文中的模型根據所謂對數市場計分規則 」 (LMSR)。

四個索引鍵的預測市場方程式
[圖 2] 的四個索引鍵的預測市場方程式

公式 1 是一組未處理的共用 (x,y) 相關聯的成本函式。方程式,很難完全察覺,來自經濟體系理論。從開發人員的觀點來看,您可以將方程式當成 helper 函式。它接受 x,這是共用數目保留的選項為 0,並保留的選項 1,y,也就是共用數目,並傳回值。所有四個方程式中的變數 b 是流動的參數。假設 x = 20,y = 10。如果 b = 100.0,則 C(x,y) = 100.0 * ln(exp(20/100) + exp(10/100)) = 100.0 * ln (1.22 + 1.11) = 100.0 * 0.8444 = $84.44。傳回值用於方程式 2。

公式 2 是買方交易的成本。假設是一組目前未處理的共用 (20,10) 和專家購買 30 共用的選項為 0。專家該交易的成本計算使用方程式 2 為 C (20 + 30,10)-C (20,10) = C (50,10)-C (20,10) = 101.30 84.44 = $16.86。負數的值,指出付費的專業人員方面的專家銷售的共用,如果進行交易的成本。

方程式 3 是選項的技術上根據一組未處理的共用 (x,y) 0 臨界價格。但臨界價格鬆散解譯為一個選項,將有機會贏得的機率。方程式 4 是選項的臨界價格 (機率) 1。如果您仔細查看兩個方程式,您會發現它們的總和必須為 1.0,做為需要一組的機率。

實作的四個索引鍵的預測市場方程式很簡單。示範程式做為實作的成本,1,方程式 ︰

static double Cost(int[] outstanding, double liq)
{
  double sum = 0.0;
  for (int i = 0; i < 2; ++i)
    sum += Math.Exp(outstanding[i] / liq);
  return liq * Math.Log(sum);
}

成本方法幾乎是方程式的精確的轉譯 1。請注意方法成本會假設有兩個選項。為了簡單起見,會執行任何的錯誤檢查。

公式 2 也是相當簡單的實作 ︰

static double CostOfTrans(int[] outstanding, int idx, int nShares, double liq)
{
  int[] after = new int[2];
  Array.Copy(outstanding, after, 2);
  after[idx] += nShares;
  return Cost(after, liq) - Cost(outstanding, liq);
}

陣列之後保留新的未處理的共用數目的交易,並然後方法只會呼叫成本 helper 方法兩次。手中計算的交易成本的方法,很容易撰寫計算購買每兩個選項的單一共用的方法 ︰

static double[] CostForOneShare(int[] outstanding, double liq)
{
  double[] result = new double[2];
  result[0] = CostOfTrans(outstanding, 0, 1, liq);
  result[1] = CostOfTrans(outstanding, 1, 1, liq);
  return result;
}

單一共用的成本可由專家取得它多少錢購買選項的 n 個共用的近似值。

機率方法會傳回贏得陣列中每個選項的兩個臨界價格 (推斷機率) ︰

static double[] Probabilities(int[] outstanding, double liq)
{
  double[] result = new double[2];
  double denom = 0.0;
  for (int i = 0; i < 2; ++i)
    denom += Math.Exp(outstanding[i] / liq);
  for (int i = 0; i < 2; ++i)
    result[i] = Math.Exp(outstanding[i] / liq) / denom;
  return result;
}

如果您要比較之方程式 3 和 4 的機率方法的程式碼,您會看到,同樣地,此程式碼遵循直接從數學的定義。

示範程式

若要建立示範程式,我啟動 Visual Studio,並選取 C# 主控台應用程式範本。我命名為 PredictionMarket 的專案。示範具有不重要的 Microsoft.NET Framework 相依性,以便能使用任何版本的 Visual Studio。

範本程式碼載入後,請在 [方案總管] 視窗中我重新命名為更具描述性的 PredictionMarketProgram.cs 的 Program.cs 檔案並允許 Visual Studio 會自動重新命名為我的類別程式。在原始碼頂端,我要刪除所有 using 陳述式參考不必要的.NET 命名空間,但只是最上層系統命名空間的參考會保留。

完整的範例程式碼中,使用一些次要的編輯和刪除,以節省空間,某些 WriteLine 陳述式所示 [圖 3。在 Main 方法中,是所有程式控制邏輯。所有預測市場功能都處於四種靜態方法,並有兩個 ShowVector helper 顯示方法。

[圖 3 預測市場示範

using System;
namespace PredictionMarket
{
  class PredictionMarketProgram
  {
    static void Main(string[] args)
    {
      Console.WriteLine("Begin prediction market demo ");
      Console.WriteLine("Goal is to predict winner of Xrays");
      Console.WriteLine("vs. Yanks using expert opinions");
      double liq = 100.0;
      Console.WriteLine("Setting liquidity parameter = " +
        liq.ToString("F1"));
      int[] outstanding = new int[] { 0, 0 };
      Console.WriteLine("Initial number of shares owned are:");
      ShowVector(outstanding);
      double[] probs = Probabilities(outstanding, liq);
      Console.WriteLine("Initial probabilities of winning:");
      ShowVector(probs, 4, " ");
      Console.WriteLine("=================================");
      double[] costPerShare = CostForOneShare(outstanding, liq);
      Console.WriteLine("Current costs for one share are: ");
      ShowVector(costPerShare, 4, " $");
      Console.WriteLine("Update: expert [01] buys 20 shares " +
        "of team [0]");
      double costTrans = CostOfTrans(outstanding, 0, 20, liq);
      Console.WriteLine("Cost of transaction to expert was: $" +
        costTrans.ToString("F2"));
      outstanding = new int[] { 20, 0 };
      Console.WriteLine("New number of shares owned are: ");
      ShowVector(outstanding);
      probs = Probabilities(outstanding, liq);
      Console.WriteLine("New inferred probs of winning:");
      ShowVector(probs, 4, " ");
      Console.WriteLine("=================================");
      costPerShare = CostForOneShare(outstanding, liq);
      Console.WriteLine("Current costs for one share are:");
      ShowVector(costPerShare, 4, " $");
      Console.WriteLine("Update: expert [02] buys 20 shares " +
        "of team [1]");
      costTrans = CostOfTrans(outstanding, 1, 20, liq);
      Console.WriteLine("Cost of transaction to expert was: $" +
        costTrans.ToString("F2"));
      outstanding = new int[] { 20, 20 };
      Console.WriteLine("New number of shares owned are:");
      ShowVector(outstanding);
      probs = Probabilities(outstanding, liq);
      Console.WriteLine("New inferred probs of winning:");
      ShowVector(probs, 4, " ");
      Console.WriteLine("=================================");
      costPerShare = CostForOneShare(outstanding, liq);
      Console.WriteLine("Current costs for one share are:");
      ShowVector(costPerShare, 4, " $");
      Console.WriteLine("Update: expert [03] buys 60 shares " +
        "of team [0]");
      costTrans = CostOfTrans(outstanding, 0, 60, liq);
      Console.WriteLine("Cost of transaction to expert was: $" +
        costTrans.ToString("F2"));
      outstanding = new int[] { 80, 20 };
      Console.WriteLine("New number of shares owned are:");
      ShowVector(outstanding);
      probs = Probabilities(outstanding, liq);
      Console.WriteLine("New inferred probs of winning:");
      ShowVector(probs, 4, " ");
      Console.WriteLine("=================================");
      costPerShare = CostForOneShare(outstanding, liq);
      Console.WriteLine("Current costs for one share are: ");
      ShowVector(costPerShare, 4, " $");
      Console.WriteLine("Update: expert [01] sells 10 shares " +
        "of team [0]");
      costTrans = CostOfTrans(outstanding, 0, -10, liq);
      Console.WriteLine("Cost of transaction to expert was: $" +
        costTrans.ToString("F2"));
      outstanding = new int[] { 70, 20 };
      Console.WriteLine("New number of shares owned are:");
      ShowVector(outstanding);
      probs = Probabilities(outstanding, liq);
      Console.WriteLine("New inferred probs of winning:");
      ShowVector(probs, 4, " ");
      Console.WriteLine("=================================");
      Console.WriteLine("Update: Market Closed");
      Console.WriteLine("\nEnd prediction market demo \n");
      Console.ReadLine();
    } // Main()
    static double[]Probabilities(int[] outstanding,
      double liq)
    {
      double[] result = new double[2];
      double denom = 0.0;
      for (int i = 0; i < 2; ++i)
        denom += Math.Exp(outstanding[i] / liq);
      for (int i = 0; i < 2; ++i)
        result[i] = Math.Exp(outstanding[i] / liq) / denom;
      return result;
    }
    static double Cost(int[] outstanding, double liq)
    {
      double sum = 0.0;
      for (int i = 0; i < 2; ++i)
        sum += Math.Exp(outstanding[i] / liq);
      return liq * Math.Log(sum);
    }
    static double CostOfTrans(int[] outstanding, int idx,
      int nShares, double liq)
    {
      int[] after = new int[2];
      Array.Copy(outstanding, after, 2);
      after[idx] += nShares;
      return Cost(after, liq) - Cost(outstanding, liq);
    }
    static double[] CostForOneShare(int[] outstanding,
      double liq)
    {
      double[] result = new double[2];
      result[0] = CostOfTrans(outstanding, 0, 1, liq);
      result[1] = CostOfTrans(outstanding, 1, 1, liq);
      return result;
    }
    static void ShowVector(double[] vector, int dec, string pre)
    {
      for (int i = 0; i < vector.Length; ++i)
        Console.Write(pre + vector[i].ToString("F" + dec) + " ");
      Console.WriteLine("\n");
    }
    static void ShowVector(int[] vector)
    {
      for (int i = 0; i < vector.Length; ++i)
        Console.Write(vector[i] + " ");
      Console.WriteLine("\n");
    }
  } // Program class
} // ns

顯示一些初步的訊息之後, Main 方法中的,程式執行開始的 ︰

double liq = 100.0;
int[] outstanding = new int[] { 0, 0 };
ShowVector(outstanding);

變數 liq 是流動的參數。100.0 是正常情況,但是如果您嘗試藉由調整值,您會看到它如何影響股價的變更之後的交易。較大的流動資產值會產生較小的變更。陣列的名稱未處理的存放共用上的兩個小組的所有專家所擁有的總數。請注意流動資產參數必須傳遞到四個靜態市場預測方法。替代的設計是封裝成 C# 類別的方法,並定義流動資產做為成員欄位。

接下來,未處理的共用數目用來決定推斷每個小組成功的機率 ︰

double[] probs = Probabilities(outstanding, liq);
Console.WriteLine("Initial probabilities of winning:");
ShowVector(probs, 4, " ");

接下來,範例會顯示購買的兩個小組的單一共用的成本 ︰

double[] costPerShare = CostForOneShare(outstanding, liq);
Console.WriteLine("Current costs for one share are: ");
ShowVector(costPerShare, 4, " $");

實際的預測市場,這項資訊會很有用,幫助他們評估的小組共用代價就是太大或太小,相對於專家的錯覺,那就贏小組是否市場專家。

示範程式會模擬一個專家買一些共用,就像這樣 ︰

Console.WriteLine("Update: expert [01] buys 20 shares of team [0]");
double costTrans = CostOfTrans(outstanding, 0, 20, liq);
Console.WriteLine("Cost of transaction to expert was: $" +
  costTrans.ToString("F2"));

實際的預測的市場,系統必須維護一段專家帳戶餘額的相關資訊和擁有的共用數目。

接下來,未處理的共用數目是更新,就像這樣 ︰

outstanding = new int[] { 20, 0 };
Console.WriteLine("New number of shares owned on teams [0] " +
  "and [1] are: ");
ShowVector(outstanding);

如果您回頭參考中的數學方程式 [圖 2, ,您會發現所有方程式所需要的每個小組/選項,(x,y),未處理的共用數目。

在更新的未處理的共用數目之後,會使用該資訊來估計每個小組或選項勝出的修訂過的機率 ︰

probs = Probabilities(outstanding, liq);
Console.WriteLine("New inferred probabilities of
  winning are: ");
ShowVector(probs, 4, " ");

還記得,這些值是真的臨界價格,但最好把它們視為機率。最後,預測市場的目的是產生的可能性就贏了每個小組或選項,因此最終機率市場穩定後的集合是你之後。

示範程式結束時,會重複下列五個作業三次 ︰

  • 顯示每個小組的一個共用的目前成本
  • 執行買入還是賣出交易
  • 顯示交易的成本
  • 更新共用未處理的總數
  • 更新每個小組獲獎的機率

請注意,範例程式開頭相等之兩個小組的機率。這不是實際在許多案例中實際預測市場。可以初始化不相等的機率的預測市場解決 x 和 y 在方程式 3 和 4。

總結

這篇文章中的資訊會根據循環配置資源 Hanson 2002 的研究報告 「 對數市場計分規則的模組化組合資訊彙總,」。您可以使用任何的搜尋工具,在網際網路上的幾個地方找到紙張的 PDF 版本。

預測市場不只是抽象的理論概念。過去幾年來,多家公司已經建立在實際實作實際的金錢的預測市場。

使用中的參考資料區域是在什麼稱為組合的預測市場。而不是挑選其中一個有機會贏得兩個選項,專家可以購買組合事件中的共用,例如小組會打破 B 小組和小組 J 會打破小組 k 組合市場都比簡單的市場更複雜的預測。


Dr。James McCaffreyRedmond,華盛頓中的 Microsoft Research 的運作方式他曾在包括 Internet Explorer 和 Bing 的數個 Microsoft 產品。Dr.McCaffrey 可以到達jammc@microsoft.com

感謝下列 Microsoft 技術專家檢閱這份文件 ︰ Pallavi Choudhury、 Gaz Iqbal、 Umesh Madan 和 Lin Suwandy