Skip to content

Anreizzahlungen: Preislisten, BDM-Gebote, Belief Elicitation und Prolific-Boni

Teilnehmende in Potato nach ihren Antworten bezahlen: Preislisten nach Holt & Laury, BDM-Gebote und binarisierte Bewertungsregel, nach der Studie gezogen und als Prolific-Boni ausgezahlt.

Neu in v2.12.0

Potato kann Teilnehmende nach ihren Antworten bezahlen, wie es Studien der experimentellen Ökonomie tun. Drei Annotationstypen erheben die Antworten:

annotation_typeFragt nachBezahlt über
price_listOption A oder B in jeder Zeile einer Multiple Price Listmpl_random_row
bdmDem Höchstbetrag, den die teilnehmende Person für etwas zahlen würdebdm (Becker, DeGroot & Marschak, 1964)
belief_elicitationEiner Wahrscheinlichkeit oder einer Verteilung von 100 Punkten auf Klassenbsr, der binarisierten Bewertungsregel (Hossain & Okui, 2013)

Der Block incentives: legt fest, wie jedes Schema bezahlt wird. Nachdem eine teilnehmende Person fertig ist, zieht Potato die Zufallszahlen, berechnet die Auszahlung und schreibt eine Bonusdatei im Sammelformat von Prolific. Es zahlt nie selbstständig jemanden aus.

Wann gezogen wird

Während die teilnehmende Person antwortet, wird nichts gezogen. Die Seite sieht nie einen Preis, eine gezogene Zeile oder einen Schwellenwert, sodass keines davon eine Antwort beeinflussen kann. Gezogen wird, wenn Sie den Export incentives ausführen oder die Admin-Route aufrufen, und nur für Teilnehmende, die die Studie abgeschlossen haben.

Jede Ziehung wird aus der Benutzer-ID, dem Regelnamen, dem Item oder der Seite, zu der die Antwort gehört, und einem privaten incentives.seed geseedet. Eine erneute Berechnung mit denselben Antworten ergibt dieselben Ziehungen, ein hinzugefügtes Item lässt die Ziehungen für die anderen Items unverändert, und jede Ziehung wird in bonuses.csv geschrieben.

Preislisten

Die Liste nach Holt & Laury (2002), mit höchstens einem Wechselpunkt:

yaml
annotation_schemes:
  - annotation_type: price_list
    name: risk
    description: For each decision, choose the option you prefer.
    preset: holt_laury
    single_switch: true
    label_requirement: {required: true}

Das Preset hat zehn Zeilen. Option A zahlt $2.00 mit Wahrscheinlichkeit p und sonst $1.60, Option B zahlt $3.85 mit Wahrscheinlichkeit p und sonst $0.10, und p läuft von 0.1, 0.2, ... bis 1.0. scale: 10 zahlt das Zehnfache dieser Beträge.

Eine Liste zur Zeitpräferenz stellt einen Betrag jetzt größeren späteren Beträgen gegenüber:

yaml
  - annotation_type: price_list
    name: patience
    description: Which would you rather receive?
    preset: time_preference
    amount_now: 10
    amounts_later: [10, 10.5, 11, 12, 13, 15]
    delay_label: in 4 weeks

Zeilen lassen sich auch von Hand schreiben. a_pays und b_pays geben an, was die Anreizregel zahlt, entweder eine Zahl für einen sicheren Betrag oder [[probability, amount], ...] für eine Lotterie. Ohne sie kann die Liste angezeigt, aber nicht ausgezahlt werden:

yaml
  - annotation_type: price_list
    name: insurance
    description: Choose one option in each row.
    rows:
      - {a: "$5 for sure", b: "50% chance of $12, otherwise $0",
         a_pays: 5, b_pays: [[0.5, 12], [0.5, 0]]}
      - {a: "$6 for sure", b: "50% chance of $12, otherwise $0",
         a_pays: 6, b_pays: [[0.5, 12], [0.5, 0]]}
SchlüsselStandardwertBedeutung
presetkeinerholt_laury oder time_preference. Geben Sie entweder preset oder rows an
rowskeinerMindestens zwei {a, b, a_pays, b_pays, a_after, b_after}. a_after und b_after nennen eine Zahlungsverzögerung, etwa in 4 weeks
scale1Multipliziert jeden Betrag eines Presets. Mit rows nicht erlaubt
currency$Symbol, das vor Beträgen ausgegeben wird
single_switchfalseErlaubt höchstens einen Wechsel von A zu B
option_labels[Option A, Option B]Spaltenüberschriften
amount_now, amounts_laterkeinerNur time_preference: der sichere Betrag jetzt und ein späterer Betrag pro Zeile
delay_label, now_labelin 4 weeks, todayNur time_preference: wann jede Option zahlt

Mit single_switch: true wählt die Wahl von B in einer Zeile auch B in jeder späteren Zeile, und die Wahl von A wählt auch A in jeder früheren Zeile. Die auf diese Weise ausgefüllten Zeilen blinken kurz auf, sodass die teilnehmende Person sieht, was sich geändert hat. Ohne diese Option ist jede Zeile unabhängig, und die Antwort hält fest, wie oft die Person gewechselt hat. Jede Zeile ist eine Radio-Gruppe, sodass die Pfeiltasten und Tab wie in jeder Radio-Gruppe funktionieren.

BDM-Gebote

yaml
annotation_schemes:
  - annotation_type: bdm
    name: voucher
    description: What is the most you would pay for a voucher worth $3.00?
    min: 0
    max: 5
    step: 0.05
    input: number
    instructions: >-
      You have $5.00 to spend. A price between $0.00 and $5.00 is drawn after
      the study. If your bid is at least the price, you buy the voucher and pay
      the price, not your bid; otherwise you keep the $5.00.
    label_requirement: {required: true}

max ist erforderlich, und min hat den Standardwert 0. input: slider zeigt statt eines Zahlenfelds einen Schieberegler mit einem hohlen Regler in der Mitte, der sich füllt, sobald die teilnehmende Person ihn bewegt, sodass ein unberührter Regler nicht als Gebot gelesen wird. Der Ziehungsbereich und die Ausstattung stehen in der Anreizregel, nicht im Schema. Schreiben Sie dieselben Zahlen daher in instructions, damit die teilnehmende Person die Regel kennt, unter der sie bietet.

Belief Elicitation

Eine Wahrscheinlichkeit:

yaml
annotation_schemes:
  - annotation_type: belief_elicitation
    name: forecast
    description: How likely is it that this happens?
    mode: point
    left_label: Certainly not
    right_label: Certainly
    label_requirement: {required: true}

Eine Verteilung:

yaml
  - annotation_type: belief_elicitation
    name: rainfall
    description: How much rain will fall next week?
    mode: bins
    bins: ["0-9 mm", "10-19 mm", "20-29 mm", "30 mm or more"]
    label_requirement: {required: true}

Im Modus point reicht der Schieberegler von 0 bis 100 % und beginnt hohl bei 50 %, sodass ein unberührter Regler nicht als Angabe von 50 % gelesen wird. Im Modus bins gibt die teilnehmende Person für jede Klasse eine ganze Zahl von Punkten ein, und eine laufende Summe zeigt, wie viele Punkte noch zu verteilen sind. Solange die Summe nicht genau 100 beträgt, meldet sich die Frage als unvollständig.

Zahlung konfigurieren

yaml
incentives:
  enabled: true
  currency: USD
  seed: "a private string, kept out of the repository"
  pay: one_random_item            # one_random_item | all | sum
  max_bonus: 6.00
  only_finished: true
  rules:
    - scheme: risk                # a price_list scheme
      method: mpl_random_row
    - scheme: voucher             # a bdm scheme
      method: bdm
      endowment: 5.00
      item_value: 3.00
      draw: {min: 0, max: 5, step: 0.25}
    - scheme: forecast            # a belief_elicitation scheme
      method: bsr
      prize: 2.00
      outcome_field: outcome
SchlüsselStandardwertBedeutung
enabledfalseSchaltet den Export incentives und die Admin-Route ein
currencyUSDBezeichnung, die in bonuses.csv geschrieben wird. Prolific zahlt in der Währung der Studie, setzen Sie den Wert daher passend dazu
seedkeinerPrivater Text, der in jede Ziehung einfließt. Ohne ihn könnte jeder mit dem Code die Ziehungen vor dem Antworten berechnen, und der Export warnt, wenn er fehlt oder noch den Wert des Beispiels hat
payone_random_itemone_random_item zahlt eine Entscheidung aus, die zufällig aus allen beantworteten Entscheidungen der teilnehmenden Person gezogen wird. all zahlt die Summe aller Entscheidungen, und sum ist ein anderer Name für all
max_bonuskeinerObergrenze für den Bonus einer teilnehmenden Person
only_finishedtrueZieht und zahlt nur für Teilnehmende, die das Ende der Studie erreicht haben
ruleserforderlichEin Eintrag pro bezahltem Schema, jeweils mit scheme (dem name des Schemas) und method

Eine Regel kann ein Schema in annotation_schemes nennen, das einmal pro Item beantwortet wird, oder eines auf einer Phasenseite wie poststudy, das einmal beantwortet wird. potato validate prüft, dass das Schema existiert und den richtigen Typ für die Methode hat.

mpl_random_row

Eine Zeile der Preisliste der teilnehmenden Person wird zufällig gezogen, jede Zeile mit gleicher Wahrscheinlichkeit, und die in dieser Zeile gewählte Option wird gespielt. Eine zweite Ziehung u in [0, 1) bestimmt das Ergebnis der Lotterie, wobei die Ergebnisse in der aufgeführten Reihenfolge aneinandergereiht werden. Eine Liste mit einer unbeantworteten Zeile wird nicht ausgezahlt, und eine Liste mit mehr als einem Wechsel wird ausgezahlt und als multiple switching markiert.

bdm

SchlüsselBedeutung
endowmentGeld, das die teilnehmende Person für diese Entscheidung hält, Standardwert 0. Mit draw muss es mindestens draw.max betragen, sodass ein Kauf nie mehr kostet, als die Person erhalten hat
draw{min, max} für einen gleichverteilt gezogenen, auf Cent gerundeten Preis. Fügen Sie step hinzu, um einen von min, min + step, ..., max zu ziehen
price_fieldStatt draw ein Item-Feld mit einem im Voraus festgelegten Preis
item_value, value_fieldWas das Objekt der kaufenden Person in Geld wert ist, als Zahl oder Item-Feld. Standardwert 0, für ein physisches Objekt, das separat übergeben wird

Ein Gebot in Höhe des Preises oder darüber kauft zum Preis, nicht zum Gebot, also Auszahlung = Ausstattung - Preis + Wert des Objekts. Ein niedrigeres Gebot kauft nicht, und Auszahlung = Ausstattung. Weil der Preis nicht vom Gebot abhängt, hilft es der teilnehmenden Person nie, etwas anderes als den Wert des Objekts zu bieten, und manchmal kostet es sie etwas. Diese Eigenschaft macht das Verfahren anreizkompatibel.

bsr

SchlüsselBedeutung
prizeDer Betrag, der bei einem Gewinn gezahlt wird
outcome_fieldDas Item-Feld, das festhält, was eingetreten ist: 1 oder 0 (oder true/false, yes/no) für eine Punktangabe und ein Klassen-Label oder ein 0-basierter Klassenindex für eine Klassenangabe
outcomeStatt outcome_field ein einzelner Wert für eine einmal beantwortete Frage, etwa eine auf einer Phasenseite

Der Preis wird gezahlt, wenn der quadratische Verlust der Angabe unter einem Schwellenwert liegt, der gleichverteilt aus [0, K] gezogen wird. Für eine Punktangabe p zu einem binären Ereignis gilt loss = (1{event} - p)² mit K = 1. Für eine Klassenangabe gilt loss = Σ (1{bin happened} - p_bin)² mit K = 2. Eine teilnehmende Person, die die beste Chance auf den Preis haben möchte, fährt am besten, wenn sie angibt, was sie glaubt, unabhängig von ihrer Risikoeinstellung, weil die einzigen Auszahlungen der Preis und nichts sind.

Das tatsächliche Ergebnis muss vorliegen, bevor Sie Zahlungen berechnen, entweder in der Datendatei unter outcome_field oder nachträglich eingetragen, sobald die Ereignisse eingetreten sind. Potato entfernt outcome_field und price_field aus den Item-Daten, die an die Seite gesendet werden. Halten Sie sie daher auch aus dem Item-Text heraus. Eine teilnehmende Person, deren gezogene Entscheidung noch kein Ergebnis hat, wird als ausstehend geführt und aus der Prolific-Datei herausgelassen, bis das Ergebnis eingetragen ist.

Ziehungen prüfen

bonuses.csv hat eine Zeile pro bezahlter Entscheidung, mit der Person, welche Regel welche Antwort bezahlt hat, dem Seed, jeder verwendeten Zufallszahl (als JSON in draws), der Auszahlung, ob sie zum Bonus zählt, der Gesamtsumme der Person nach max_bonus und einer note, die angibt, warum eine Entscheidung nicht bezahlt wurde. Um eine Zahlung von Hand zu prüfen, lesen Sie die Ziehungen und berechnen die Auszahlung nach den obigen Regeln neu. Die Ziehungen selbst zu reproduzieren erfordert dieselben Antworten, dieselben Regelnamen und denselben incentives.seed.

Auszahlung über Prolific

Teilnehmende brauchen eine Prolific-ID. Melden Sie sie daher über die Studien-URL mit login: {type: url_direct, url_argument: PROLIFIC_PID} oder mit crowdsourcing: {provider: prolific} an.

Über den Export:

bash
python -m potato.export --config config.yaml --format incentives --output ./bonuses/

Laden Sie bonuses_prolific.csv im Dialog für Sammelboni von Prolific hoch. Jede Zeile lautet <participant_id>,<amount> mit zwei Nachkommastellen und ohne Kopfzeile. Der Export lässt, jeweils mit einer Warnung, Teilnehmende weg, denen nichts zusteht, Teilnehmende ohne Prolific-ID, Teilnehmende, die nicht fertig sind, und Teilnehmende, deren gewählte Option später zahlt.

Über die Admin-API, mit einem konfigurierten Prolific-Token:

bash
# Dry run: nothing is sent to Prolific
curl -H "X-API-Key: $KEY" http://localhost:8000/admin/api/crowd/incentive_bonuses
 
# Pay: echo the dry run's prolific_total
curl -X POST -H "X-API-Key: $KEY" -H "Content-Type: application/json" \
     -d '{"pay": true, "expected_total": "12.40", "study_id": "<study id>"}' \
     http://localhost:8000/admin/api/crowd/incentive_bonuses

Für die Auszahlung braucht es "pay": true und ein expected_total, das dem prolific_total des Probelaufs entspricht. Hat sich seit dem Probelauf eine Antwort geändert, weichen die Summen ab, und die Anfrage wird mit Status 409 abgelehnt.

Jeder bezahlte Batch wird in <task_dir>/incentive_payments.json aufgezeichnet. Ein Batch, der eine Person enthält, die ein früherer Batch bereits bezahlt hat, wird mit Status 409 abgelehnt. Das verhindert, dass ein Doppelklick oder ein zweiter Zahlungslauf dieselben Personen zweimal bezahlt. Um nur die Teilnehmenden zu bezahlen, die noch kein aufgezeichneter Batch bezahlt hat, fügen Sie "skip_paid": true hinzu und setzen expected_total auf das unpaid_total des Probelaufs. Um einen aufgezeichneten Batch absichtlich erneut zu bezahlen, fügen Sie "repeat": true hinzu.

Beispiel

bash
python potato/flask_server.py start examples/advanced/incentivized-elicitation/config.yaml -p 8000

Das Beispiel stellt vier Fragen zu Überzeugungen, eine pro Item und bezahlt per bsr aus dem outcome jedes Items, dann eine poststudy-Seite mit einer Preisliste nach Holt & Laury und einem BDM-Gebot für einen Gutschein im Wert von $3.00.

Weiterführende Informationen

Implementierungsdetails finden Sie in der Quelldokumentation.