oTree Forum >

Payoff generation

#1 by Anwesha

Hi there,

Hope you are well. I am quite new to otree and have started programming my first experiment. So in this experiment, subjects need to choose between Asset A and Asset B. The way their payoff gets determined is like this:
1. Once a subject makes a choice, there is 50% probability for each of the assets to get randomly selected for payment. If Asset A gets selected, then the subjects get paid for the asset if the subject also chose Asset A. Or else, they just get the participation fee.
2. Similar structure if the subject chooses Asset B.

The problem is that once I go to the server, everything seems to be fine except that one a selection is made, every subject (that is me testing the links), get paid just the participation fee. I am afraid there is an error and possibly in the way I have coded the payments, but I am unable to pin-point the error days after trying. Could you kindly help me? BTW, I am using PyCharm to program my experiment.  The code is below:

class C(BaseConstants):
    NAME_IN_URL = 'wealth'
    PLAYERS_PER_GROUP = None
    NUM_ROUNDS = 1
    ENDOWMENT = cu(100)
    payment_assetA = cu(110)
    payment_assetB = cu(115)
    payment_otherwise = cu(100)


class Subsession(BaseSubsession):
    pass


class Group(BaseGroup):
    pass


class Player(BasePlayer):
    decision = models.BooleanField(
        label="Please make a selection between Asset A and Asset B",
        choices=[
            [True, "Asset A"],
            [False, "Asset B"],
        ]
    )


    pchoice = np.random.choice(['Asset A', 'AssetB'], p=[0.5, 0.5])



# PAGES
class MyPage(Page):
    form_model = "player"
    form_fields = ["decision"]


class ResultsWaitPage(WaitPage):
    pass


class Results(Page):
    pass


def set_payoffs(player: BasePlayer):
    if BasePlayer.pchoice == 'Asset A':
        player.payoff = BaseConstants.payment_assetA
    else:
        player.payoff = BaseConstants.payment_otherwise
    if BasePlayer.pchoice == 'Asset B':
        player.payoff = BaseConstants.payment_assetB
    else:
        player.payoff = BaseConstants.payment_otherwise

#2 by Fanist

Hi, I have checked your code, and there are some errors:

1. no need to use cu() in 'ENDOWMENT = cu(100)', just let it be a integer
2. do not include 'pchoice' in Player, do it in your payoff determination
3. for set_payoffs: you should rewrite 'BaseConstants.payment_assetA' as 'C.payment_assetA' and rewrite 'BasePlayer.pchoice' as 'player.pchoice'
4. In BasePlayer.pchoice == 'Asset A', the pchoice should be value either True or False which is specified in your Player field

Let me give you a revised version of code:


class C(BaseConstants):
    NAME_IN_URL = 'wealth'
    PLAYERS_PER_GROUP = None
    NUM_ROUNDS = 1
    ENDOWMENT = 100
    payment_assetA = 110
    payment_assetB = 115
    payment_otherwise = 100


class Subsession(BaseSubsession):
    pass


class Group(BaseGroup):
    pass


class Player(BasePlayer):
    decision = models.BooleanField(
        label="Please make a selection between Asset A and Asset B",
        choices=[
            [True, "Asset A"],
            [False, "Asset B"],
        ],
        widget=widgets.RadioSelectHorizontal
    )
    get_payoff = models.IntegerField()

# PAGES
class MyPage(Page):
    form_model = "player"
    form_fields = ["decision"]

class Results(Page):
    @staticmethod
    def vars_for_template(player: Player):
        # generate a random outcome as "pchoice"
        # determine whether they can get payoff == whether a random number from [0,1] can be less than 0.5
        pchoice = np.random.random()
        if pchoice <= 0.5:
            player.get_payoff = 1
        else:
            player.get_payoff = 0
        # determine the payoff
        # since get_payoff = 1 or 0, we can multiply directly to get the final payoff
        if player.decision == True:
            player.payoff += C.payment_assetA*player.get_payoff
        if player.decision == False:
            player.payoff += C.payment_assetB*player.get_payoff

Hope that helps.

#3 by Anwesha

@Fanist Thank you so much for your help. However, there still appears to be an error when asset B gets selected. It still gives the payoff of Asset A. I tried my best but was unable to spot the mistake.

One more question. I would like the players to get payment_otherwise if their choice does not get randomly selected. But I am not sure if your code takes that into account.

Could you kindly advise me on these?

#4 by Anwesha

@Fanist I played with the codes and for my first question, I realised that it was a mistake I made in MyPage.html file nd now the problem is sorted out. I only have one concern which can be a bit silly. But beside some codes in PyCharm, a disk with red arrow appears. Do you know what that means?

To accommodate payment_otherwise, I added this to your amended code:
class Results(Page):
    @staticmethod
    def vars_for_template(player: Player):
        # generate a random outcome as "pchoice"
        # determine whether they can get payoff == whether a random number from [0,1] can be less than 0.5
        pchoice = np.random.random()
        if pchoice <= 0.5:
            player.get_payoff = 1
        else:
            player.get_payoff = 0
        # determine the payoff
        # since get_payoff = 1 or 0, we can multiply directly to get the final payoff
        if player.decision == True:
            player.payoff += C.payment_assetA*player.get_payoff
        if player.decision == False:
            player.payoff += C.payment_assetB*player.get_payoff
        if player.get_payoff == 0:
            player.payoff += C.payment_otherwise
            
 Thank you so much for your help. Now the codes run just fine.

#5 by Fanist

@Anwesha I am unsure about the so-called "red arrow" issue since I am using VS Code, but I have heard about PyCharm that they will make strict coding suggestions for users. Check the code and ensure the code goes well. 

And good job for adding "C.payment_otherwise"!

Shawn

#6 by Anwesha (edited )

@Shawn Thanks a lot.

Write a reply

Set forum username