Pagos por incentivos: listas de precios, pujas BDM, elicitación de creencias y bonificaciones de Prolific
Paga a los participantes según sus respuestas en Potato: listas de precios de Holt & Laury, pujas BDM y regla de puntuación binarizada, sorteadas tras el estudio y pagadas como bonificaciones de Prolific.
Nuevo en v2.12.0
Potato puede pagar a los participantes según sus respuestas, como hacen los estudios de economía experimental. Tres tipos de anotación recogen las respuestas:
annotation_type | Pide | Se paga con |
|---|---|---|
price_list | La opción A o la B en cada fila de una lista de precios múltiple | mpl_random_row |
bdm | Lo máximo que el participante pagaría por algo | bdm (Becker, DeGroot & Marschak, 1964) |
belief_elicitation | Una probabilidad, o una distribución de 100 puntos entre intervalos | bsr, la regla de puntuación binarizada (Hossain & Okui, 2013) |
El bloque incentives: indica cómo se paga cada esquema. Cuando un participante termina, Potato sortea los números aleatorios, calcula la ganancia y escribe un archivo de bonificaciones en el formato de carga masiva de Prolific. Nunca paga a nadie por sí mismo.
Cuándo se hacen los sorteos
No se sortea nada mientras el participante responde. La página nunca ve un precio, una fila sorteada ni un umbral, así que ninguno de ellos puede influir en una respuesta. Los sorteos se hacen cuando ejecutas la exportación incentives o llamas a la ruta de administración, y solo para los participantes que han terminado el estudio.
Cada sorteo usa una semilla derivada del ID de usuario, el nombre de la regla, el ítem o la página a la que pertenece la respuesta y un incentives.seed privado. Repetir el cálculo sobre las mismas respuestas da los mismos sorteos, añadir un ítem deja sin cambios los sorteos de los demás ítems, y cada sorteo se escribe en bonuses.csv.
Listas de precios
La lista de Holt & Laury (2002), con un punto de cambio como máximo:
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}El preajuste tiene diez filas. La opción A paga 2,00 $ con probabilidad p y 1,60 $ en caso contrario, la opción B paga 3,85 $ con probabilidad p y 0,10 $ en caso contrario, y p va de 0,1, 0,2, ... a 1,0. scale: 10 paga diez veces esas cantidades.
Una lista de preferencia temporal enfrenta una cantidad ahora con cantidades mayores más adelante:
- 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 weeksLas filas también se pueden escribir a mano. a_pays y b_pays son lo que paga la regla de incentivos, ya sea un número para una cantidad segura o [[probability, amount], ...] para una lotería, y sin ellas la lista se puede mostrar pero no pagar:
- 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]]}| Clave | Valor predeterminado | Significado |
|---|---|---|
preset | ninguno | holt_laury o time_preference. Indica preset o bien rows |
rows | ninguno | Al menos dos {a, b, a_pays, b_pays, a_after, b_after}. a_after y b_after indican un aplazamiento del pago, como in 4 weeks |
scale | 1 | Multiplica todas las cantidades de un preajuste. No se admite con rows |
currency | $ | Símbolo que se imprime delante de las cantidades |
single_switch | false | Mantiene como máximo un cambio de A a B |
option_labels | [Option A, Option B] | Encabezados de columna |
amount_now, amounts_later | ninguno | Solo time_preference: la cantidad segura ahora y una cantidad posterior por fila |
delay_label, now_label | in 4 weeks, today | Solo time_preference: cuándo paga cada opción |
Con single_switch: true, elegir B en una fila elige también B en todas las filas posteriores, y elegir A elige también A en todas las filas anteriores. Las filas que se rellenan de esta forma parpadean brevemente, para que el participante vea qué ha cambiado. Sin esta opción, cada fila es independiente, y la respuesta registra cuántas veces cambió el participante. Cada fila es un grupo de botones de opción, así que las teclas de flecha y Tab funcionan como en cualquier grupo de botones de opción.
Pujas BDM
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 es obligatorio, y min vale 0 por defecto. input: slider muestra un control deslizante en lugar de una casilla numérica, con un cursor hueco en el punto medio que se rellena en cuanto el participante lo mueve, de modo que un control deslizante sin tocar no se interpreta como una puja. El rango del sorteo y la dotación están en la regla de incentivos, no en el esquema, así que escribe las mismas cifras en instructions para que el participante conozca la regla bajo la que puja.
Elicitación de creencias
Una probabilidad:
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}Una distribución:
- 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}En el modo point, el control deslizante va de 0 a 100 % y empieza hueco en el 50 %, de modo que un control deslizante sin tocar no se interpreta como un informe del 50 %. En el modo bins, el participante escribe un número entero de puntos para cada intervalo, y un total acumulado muestra cuántos puntos quedan por asignar. Hasta que el total es exactamente 100, la pregunta se declara incompleta.
Configurar el pago
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| Clave | Valor predeterminado | Significado |
|---|---|---|
enabled | false | Activa la exportación incentives y la ruta de administración |
currency | USD | Etiqueta que se escribe en bonuses.csv. Prolific paga en la moneda del propio estudio, así que haz que coincida con ella |
seed | ninguno | Texto privado que se mezcla en cada sorteo. Sin él, cualquiera que tenga el código podría calcular los sorteos antes de responder, y la exportación avisa cuando falta o conserva todavía el valor del ejemplo |
pay | one_random_item | one_random_item paga una decisión sorteada al azar entre todas las decisiones que respondió un participante. all paga la suma de todas las decisiones, y sum es otro nombre para all |
max_bonus | ninguno | Límite superior de la bonificación de un participante |
only_finished | true | Sortea y paga solo a los participantes que llegaron al final del estudio |
rules | obligatorio | Una entrada por esquema pagado, cada una con scheme (el name del esquema) y method |
Una regla puede nombrar un esquema de annotation_schemes, que se responde una vez por ítem, o uno de una página de fase como poststudy, que se responde una sola vez. potato validate comprueba que el esquema existe y tiene el tipo adecuado para el método.
mpl_random_row
Se sortea al azar una fila de la lista de precios del participante, con todas las filas igual de probables, y se juega la opción que eligió en esa fila. Un segundo sorteo u en [0, 1) elige el resultado de la lotería, con los resultados colocados uno tras otro en el orden en que aparecen. Una lista con una fila sin responder no se paga, y una lista con más de un cambio se paga y se marca con multiple switching.
bdm
| Clave | Significado |
|---|---|
endowment | Dinero que tiene el participante para esta decisión, 0 por defecto. Con draw, debe ser al menos draw.max, de modo que una compra nunca cueste más de lo que se dio al participante |
draw | {min, max} para un precio sorteado de manera uniforme y redondeado a céntimos. Añade step para sortear uno de min, min + step, ..., max |
price_field | En lugar de draw, un campo del ítem que contiene un precio fijado de antemano |
item_value, value_field | Lo que vale el objeto en dinero para el participante que lo compra, como número o como campo del ítem. 0 por defecto, para un objeto físico que se entrega por separado |
Una puja igual o superior al precio compra al precio, no a la puja, así que ganancia = dotación - precio + valor del objeto. Una puja inferior no compra, y ganancia = dotación. Como el precio no depende de la puja, pujar cualquier cantidad distinta del valor del objeto nunca beneficia al participante y a veces le cuesta dinero, que es la propiedad que hace que el procedimiento sea compatible con los incentivos.
bsr
| Clave | Significado |
|---|---|
prize | La cantidad que se paga al ganar |
outcome_field | El campo del ítem que contiene lo que ocurrió: 1 o 0 (o true/false, yes/no) para un informe puntual, y una etiqueta de intervalo o un índice de intervalo empezando en 0 para un informe por intervalos |
outcome | En lugar de outcome_field, un único valor para una pregunta que se responde una sola vez, como una de una página de fase |
El premio se paga cuando la pérdida cuadrática del informe es inferior a un umbral sorteado de manera uniforme en [0, K]. Para un informe puntual p sobre un suceso binario, loss = (1{event} - p)² con K = 1. Para un informe por intervalos, loss = Σ (1{bin happened} - p_bin)² con K = 2. A un participante que quiera la mayor probabilidad de ganar el premio le conviene informar de lo que cree, sea cual sea su actitud ante el riesgo, porque las únicas ganancias posibles son el premio o nada.
El resultado real tiene que aportarse antes de calcular los pagos, ya sea en el archivo de datos bajo outcome_field o rellenándolo una vez ocurridos los sucesos. Potato elimina outcome_field y price_field de los datos del ítem que se envían a la página, así que mantenlos también fuera del texto del ítem. Un participante cuya decisión sorteada aún no tiene resultado figura como pendiente y queda fuera del archivo de Prolific hasta que se rellena el resultado.
Auditar los sorteos
bonuses.csv tiene una fila por cada decisión pagada, con quién era, qué regla pagó qué respuesta, la semilla, cada número aleatorio usado (como JSON en draws), la ganancia, si cuenta para la bonificación, el total del participante después de max_bonus y una note que explica por qué no se pagó una decisión. Para comprobar un pago a mano, lee los sorteos y vuelve a calcular la ganancia con las reglas anteriores. Reproducir los sorteos en sí exige las mismas respuestas, los mismos nombres de regla y el mismo incentives.seed.
Pagar a través de Prolific
Los participantes necesitan un ID de Prolific, así que haz que inicien sesión desde la URL del estudio con login: {type: url_direct, url_argument: PROLIFIC_PID} o con crowdsourcing: {provider: prolific}.
Desde la exportación:
python -m potato.export --config config.yaml --format incentives --output ./bonuses/Sube bonuses_prolific.csv en el cuadro de diálogo de bonificaciones masivas de Prolific. Cada línea es <participant_id>,<amount> con dos decimales y sin cabecera. La exportación deja fuera, con una advertencia para cada caso, a los participantes a los que no se debe nada, a los participantes sin ID de Prolific, a los que no han terminado y a aquellos cuya opción elegida paga más adelante.
Desde la API de administración, con un token de Prolific configurado:
# 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_bonusesPagar requiere "pay": true y un expected_total igual al prolific_total de la prueba en seco. Si una respuesta ha cambiado desde la prueba en seco, los totales difieren y la petición se rechaza con el estado 409.
Cada lote pagado se registra en <task_dir>/incentive_payments.json. Un lote que incluye a un participante pagado por un lote anterior se rechaza con el estado 409, lo que impide que un doble clic o una segunda ejecución del pago paguen dos veces a las mismas personas. Para pagar solo a los participantes que ningún lote registrado ha pagado, añade "skip_paid": true y fija expected_total en el unpaid_total de la prueba en seco. Para volver a pagar a propósito un lote registrado, añade "repeat": true.
Ejemplo
python potato/flask_server.py start examples/advanced/incentivized-elicitation/config.yaml -p 8000El ejemplo formula cuatro preguntas de creencias, una por ítem y pagadas mediante bsr a partir del outcome de cada ítem, y después una página posterior al estudio con una lista de precios de Holt & Laury y una puja BDM por un vale que vale 3,00 $.
Lecturas adicionales
- Flujo del experimento - Condiciones y exclusiones
- Cómo realizar un estudio de crowdsourcing - Inicios de sesión de Prolific, códigos de finalización y bonificaciones
- Suma constante - Asignaciones de puntos que no se pagan
- Experimentos conductuales en línea - Un estudio completo en Potato
Para detalles de implementación, consulta la documentación fuente.