oTree Forum >

'Staircase' Risk Elicitation Method for oTree Lite

#1 by Trontatuma (edited )

Has anybody implemented this for Otree 5?

https://github.com/felixholzmeister/icl
https://www.sciencedirect.com/science/article/pii/S2214635017300540

#2 by FEDx

I did it, and it worked pretty well with minor adjustments to adapt it to the new version of Otree

#3 by Trontatuma

Could you share the code?

#4 by FEDx

Sure: https://github.com/federicoatz/Staircase_oTreeLite.git

Let me know if you need any help.

#5 by Trontatuma

Thanks!

#6 by BonnEconLab

A drawback of using oTree rounds for the steps in a staircase procedure is that you cannot easily revert to a previous step. Given that this leads to “error propagation” in the sense that mistakes early in the sequence have a large impact on the elicited value, I find it desirable to include a “back”/“revise” button when implementing a staircase procedure.

Programming a button that allows participants to revise the choices that they have made so far is relatively easy in JavaScript.

Here is some self-contained HTML and JavaScript code that implements the “risk staircase method” from Falk et al. (2023), including a “Revise” button:


<html>


<head>

<title>Risk staircase method</title>

</head>


<body>

    <h2>Hypothetical choice between safe and risky payoff</h2>

    <p>Please imagine the following situation:</p>
    <p><ul>
        <li>You can choose between receiving a&nbsp;particular monetary amount for sure and a&nbsp;random draw.</li>
        <li>The random draw results in either a&nbsp;payment of 300&nbsp;euros or no payment at all; both outcomes have the same probability.</li>
    </ul></p>
    <p id="staircase-label">What do you prefer: a&nbsp;random draw that gives you a&nbsp;50% chance of receiving 300&nbsp;euros and the same 50% chance of receiving nothing at all&mdash;or receiving the amount of <span id="staircase-value">y</span>&nbsp;euros for sure?</p>
    <p>
        <span id="staircase-buttons">
            <button type="button" class="btn btn-primary" onclick="staircase('L')" id="staircase_left">
                300&nbsp;euros with 50% chance
            </button>
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
            <button type="button" class="btn btn-primary" onclick="staircase('S')" id="staircase_right">
                <span id="staircase-value-btn">y</span>&nbsp;euros for sure
            </button>
        </span>
        <span id="back-button" style="visibility: hidden;">
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
            <button type="button" class="btn btn-warning" onclick="staircase('B')" id="staircase_back" style="opacity: 0.5;">
                Revise previous choice
            </button>
        </span>
    </p>
    <p>
        The certainty equivalent lies in the interval
        <input type="text" id='GPS-risk-staircase' readonly></input>.
    </p>
    <p id="next-button" style="visibility: hidden; opacity: 0;">
        <button>Continue</button>
    </p>
    <p><i>Based on <a href="https://doi.org/10.1287/mnsc.2022.4455" target="_blank">Falk et&nbsp;al. (2023)</a>, <a href="https://pubsonline.informs.org/doi/suppl/10.1287/mnsc.2022.4455/suppl_file/mnsc.2022.4455.sm1.pdf" target="_blank">Online Appendix</a>, p.&nbsp;44.</i></p>

<script>
    var i = 0;  // counter for staircase step
    var j = 0;  // counter for staircase interval in step i
    var k = 0;  // counter for lower/upper bound of interval j
    let staircaseEntries = [
        [[160]],
        [[80, 240]],
        [[40, 120], [200, 280]],
        [[20, 60], [100, 140], [180, 220], [260, 300]],
        [[10, 30], [50, 70], [90, 110], [130, 150], [170, 190], [210, 230], [250, 270], [290, 310]],
        [[5, 15], [25, 35], [45, 55], [65, 75], [85, 95], [105, 115], [125, 135], [145, 155], [165, 175], [185, 195], [205, 215], [225, 235], [245, 255], [265, 275], [285, 295], [305, 315]]
    ];
    let numSteps = staircaseEntries.length;
    var safeOption = staircaseEntries[0][0][0];  // Initial safe payment
    var lowerBound = "0";  // Initial lower bound
    var upperBound = "> " + staircaseEntries[numSteps - 1][2**(numSteps - 2) - 1][1];  // Initial upper bound
    // Arrays to enable “Back” button
    var jkHist = Array(numSteps).fill([9999, 9999]);  // Initialize with nonsensical values
    var safeHist = Array(numSteps).fill("9999");  // Initialize with nonsensical values
    var lbHist = Array(numSteps).fill("9999");  // Initialize with nonsensical values
    var ubHist = Array(numSteps).fill("9999");  // Initialize with nonsensical values
    safeHist[0] = safeOption;
    jkHist[0] = [0, 0];
    lbHist[0] = lowerBound;
    ubHist[0] = upperBound;
    document.getElementById('staircase-value').innerHTML = safeOption;
    document.getElementById('staircase-value-btn').innerHTML = safeOption;
    document.getElementById('GPS-risk-staircase').value = "[" + lowerBound + ", " + upperBound + "]";
    function staircase(choice) {
        document.getElementById('staircase-label').style.opacity = "0";
        document.getElementById('staircase-buttons').style.opacity = "0";
        document.getElementById('back-button').style.opacity = "0";
        if (choice == "L") {  // Lottery chosen
            k = 1;
            lowerBound = safeOption;
        }
        if (choice == "S") {  // Safe option chosen
            k = 0;
            upperBound = safeOption;
        };
        safeHist[i] = safeOption;
        if (choice == "B") {  // “Back“ button pressed
            if (i > 0) {
                i -= 1;
                j = jkHist[i][0];
                k = jkHist[i][1];
                safeOption = safeHist[i];
                upperBound = ubHist[i];
                lowerBound = lbHist[i];
            }
        } else {
            if (i < numSteps - 1) {
                jkHist[i] = [j, k];
                i += 1;
                safeOption = staircaseEntries[i][j][k];
                j = 2 * j + k;
            } else {
                i = numSteps;
            }
            lbHist[i] = lowerBound;
            ubHist[i] = upperBound;
        };
        if (i < numSteps) {
            if (i > 0) {
                document.getElementById('back-button').style.visibility = "visible";
            } else {
                document.getElementById('back-button').style.visibility = "hidden";
            }
            document.getElementById('staircase-buttons').style.visibility = "visible";
            document.getElementById('next-button').style.visibility = "hidden";
            setTimeout(function() {
                document.getElementById('staircase-value').innerHTML = safeOption;
                document.getElementById('staircase-value-btn').innerHTML = safeOption;
            }, 1000);
            setTimeout(function() {
                document.getElementById('staircase-label').style.opacity = "1";
                document.getElementById('staircase-buttons').style.opacity = "1";
            }, 1000);
        } else {
            document.getElementById('staircase-buttons').style.visibility = "hidden";
            document.getElementById('next-button').style.visibility = "visible";
            document.getElementById('next-button').style.opacity = "1";
        };
        setTimeout(function() {
            document.getElementById('back-button').style.opacity = "1";
        }, 1000);
        document.getElementById('GPS-risk-staircase').value = "[" + lowerBound + ", " + upperBound + "]";
    };
</script>

</body>


</html>

#7 by FEDx

Thanks @BonnEconLab, you rise a very interesting point.

Write a reply

Set forum username