Live pages virtual stock market-using group and player livesend/receive functions at the same time?

107 views
Skip to first unread message

Mark Frost

unread,
Oct 8, 2021, 9:42:42 AM10/8/21
to oTree help & discussion
Hello Everyone,

I am programming my first experiment and I am fairly new to all of this so please bear with me. I am creating a virtual stock market. Mine is somewhat different from the examples I have seen here but what I am doing is as follows:

Participants own shares of stock in a company and  have enough money to buy more or sell the shares they have. If a participant clicks on the button to buy more shares, the price of the stock goes up, and if they click on the sell button the price goes down. So far, I have managed to program this function successfully using Live pages. Doing something similiar to the dollar auction example.

I am at the point now where I want to make it so when a participant clicks buy/sell the amount of money in there account goes down/up and the amount of shares they have increases/decreases. I also want to disable the buy/sell buttons depending on the situation for the individual player. I have everything up until this point using the group models but the actions I just described will of course need to take place using the player models. This is where I am a bit confused.

Should I create another live pages function using player instead of group? Or is there another way of doing this. I have pasted the code that works thus far. I would appreciate any help. Even if its something as simple as "Hey, look at this example to get some ideas." Thanks!

-Mark

Here is the html page :

{{ block content }}

<!--displays to the participant the current price-->

<p id="msg-current-price"></p>

<!--creates a button where the participant can buy or sell the asset. On click the function buyAsset-->
<!--or the function sellAsset is executed-->
<button type="button" id="btn-buy" onclick="buyAsset(this)"></button>
<button type="button" id="btn-sell" onclick="sellAsset(this)" ></button>


<br><br>


<!--Start Javascript code, define that the buttons are elements which can be changed, and define
the current price to be displayed as a message which can also change-->
<script>
    let buyBtn= document.getElementById('btn-buy');
    let sellBtn = document.getElementById('btn-sell');
    let msgCurrentPrice= document.getElementById('msg-current-price');



    //defines the buy button function
    function buyAsset(btn) {
        liveSend(parseInt(btn.value));
    }
    //defines the sell button function
    function sellAsset(btn) {
        liveSend(parseInt(btn.value));
        }

    //defines the live receive function, where the current price is changed to the new price upon
    //clicking of either button
    function liveRecv(data) {
        msgCurrentPrice.innerText = `The current price is ${data.current_price}`;
        let nextBuy = data.current_price + 10;
        buyBtn.value = nextBuy;
        buyBtn.innerText = `Buy at ${nextBuy} dollars`;

        let nextSell = data.current_price - 10;
        sellBtn.value = nextSell;
        sellBtn.innerText = `Sell at ${nextSell} dollars`;


        }
    //loads the liveSend function when the page is full loaded
    document.addEventListener("DOMContentLoaded", function (event) {
        liveSend({});
    });
</script>

{{ endblock }}


---------------------------------------
Here is the python file:
----------------------------------------
from otree.api import *

c = Currency

doc = """
Your app description
"""

#creating the roles of bad tip, middle tip, and good tip
class Constants(BaseConstants):
    name_in_url = 'stonkz'
    instructions_template = 'stonkz/instructions.html'
    players_per_group = None
    num_rounds = 1
    bad_tip_role = 'Bad tip'
    middle_tip_role = 'Middle tip'
    good_tip_role = 'Good tip'







class Subsession(BaseSubsession):
    pass


class Group(BaseGroup):
    current_price = models.IntegerField(initial=100)
    new_price = models.IntegerField(initial=100)
    auction_timeout = models.FloatField()

def get_state(group: Group):
    return dict(
        current_price=group.current_price,
        new_price=group.new_price,

    )

class Player(BasePlayer):
    pass


class Intro(Page):
    pass

#Waits for all players to arrive and sets the time of the round to 120 seconds
class WaitToStart(WaitPage):
    @staticmethod
    def after_all_players_arrive(group: Group):
        import time

        group.auction_timeout = time.time() + 120


# PAGES
class Bid(Page):
    @staticmethod
    def get_timeout_seconds(player: Player):
        import time

        group = player.group
        return group.auction_timeout - time.time()

    @staticmethod
    def js_vars(player: Player):
        return dict(my_id=player.id_in_group)



#figure out what has to happen here to change the variables
    @staticmethod
    def live_method(player: Player, data):
        group = player.group
        my_id = player.id_in_group
        if data:
            if data > group.current_price:
                group.new_price = group.current_price
                group.current_price = data
                return {0: get_state(group)}
            elif data < group.current_price:
                group.new_price = group.current_price
                group.current_price = data
                return {0: get_state(group)}
        else:
            return {0: get_state(group)}



class Results(Page):
    pass


page_sequence = [Intro, WaitToStart, Bid, Results]

Chris @ oTree

unread,
Oct 8, 2021, 10:00:25 AM10/8/21
to oTree help & discussion
You can also access player fields in the same live method. Look at the examples here: https://www.otreehub.com/code/
for example, live_volunteer.

Reply all
Reply to author
Forward
0 new messages