Example #1
0
def evaluate_amounts_received_after_window_closes():
    """
    Finds any amount which is
    - received on or after the Future_Price window closes and
    - has not yet been returned and
    - has at least 6 confirmations
    Return it to itself.    
    """
    received_amounts = Received_Amount.objects.filter(confirmations__gte=6, returned_amount__isnull=True, time__gte=F('prediction__future_price__time_window_closes'))
    for received_amount in received_amounts:
        returned_amount = {
            "amount": received_amount.amount,
            "from_received_amount": received_amount,
            "to_prediction": received_amount.prediction,
            }
        returned_amount_obj = Returned_Amount(**returned_amount)
        returned_amount_obj.save()
Example #2
0
def evaluate_amounts_received_after_window_closes():
    """
    Finds any amount which is
    - received on or after the Future_Price window closes and
    - has not yet been returned and
    - has at least 6 confirmations
    Return it to itself.    
    """
    received_amounts = Received_Amount.objects.filter(
        confirmations__gte=6,
        returned_amount__isnull=True,
        time__gte=F('prediction__future_price__time_window_closes'))
    for received_amount in received_amounts:
        returned_amount = {
            "amount": received_amount.amount,
            "from_received_amount": received_amount,
            "to_prediction": received_amount.prediction,
        }
        returned_amount_obj = Returned_Amount(**returned_amount)
        returned_amount_obj.save()
Example #3
0
def evaluate_winners_and_losers(future_price):
    """
    This function creates Returned_Amount objects according to who wins
    and loses the future_price wager.
    Winners always get their initial deposit back.
    The loser payments go to the winners in chronological order, until the
    winner has received up to their original deposit amount (less commission),
    and then the next winner begins to receive loser payouts, until there
    are no more loser payments to make.
    If there are more losers than winners, the losers who are not paid to
    winners are returned to the losers.
    """

    winners = []
    losers = []

    target_price = future_price.target_price
    try:
        actual_price_obj = Bitcoin_Price.objects.get(time=future_price.time_to_match_price)
    except:
        return # there is no bitcoin price for this time so this future_price cannot be evaluated
    actual_price = actual_price_obj.price
    price_is_less_than_target = actual_price < target_price
    price_is_equal_to_target = target_price == actual_price

    amounts = Received_Amount.objects.filter(
        amount__gt=0,
        prediction__future_price=future_price,
        time__lt=future_price.time_window_closes
    ).order_by('time', 'id')

    # Split into winners and losers
    for received_amount in amounts:
        guessed_correctly = (received_amount.prediction.price_will_be_less_than_target and price_is_less_than_target) or \
            (not received_amount.prediction.price_will_be_less_than_target and not price_is_less_than_target)
        if guessed_correctly:
            # This is a winner
            returned_amount = {
                "amount": received_amount.amount,
                "from_received_amount": received_amount,
                "to_prediction": received_amount.prediction,
                }
            returned_amount_obj = Returned_Amount(**returned_amount)
            returned_amount_obj.save()
            winners.append({
                "received_amount": received_amount,
                "from_losers": 0
                })
        elif price_is_equal_to_target:
            # Eligible for refund but not for winnings
            # TODO: If the received amount is not confirmed, it will still be
            # returned
            returned_amount = {
                "amount": received_amount.amount,
                "from_received_amount": received_amount,
                "to_prediction": received_amount.prediction,
                }
            returned_amount_obj = Returned_Amount(**returned_amount)
            returned_amount_obj.save()
        else:
            # Record this so in the next step this can be allocated to winners
            losers.append({
                "received_amount": received_amount,
                "to_winners": 0,
                "commission": 0
                })

    for loser in losers:
        # Pay the winners
        for winner in winners:
            loser_funds_remaining = loser["received_amount"].amount - loser["to_winners"] - loser["commission"]
            loser_is_broke = loser_funds_remaining == 0
            if loser_is_broke:
                break
            winner_received_from_losers = winner["from_losers"]
            winner_total_owed_from_losers = winner["received_amount"].amount * (1-COMMISSION)
            amount_remaining_to_pay_winner = winner_total_owed_from_losers - winner_received_from_losers
            if amount_remaining_to_pay_winner > 0:
                amount_to_pay_winner = min(amount_remaining_to_pay_winner, loser_funds_remaining * (1-COMMISSION))
                commission = amount_to_pay_winner / (1-COMMISSION) * COMMISSION
                loser["to_winners"] = loser["to_winners"] + amount_to_pay_winner
                loser["commission"] = loser["commission"] + commission
                winner["from_losers"] = winner["from_losers"] + amount_to_pay_winner
                returned_amount = {
                    "amount": amount_to_pay_winner,
                    "from_received_amount": loser["received_amount"],
                    "to_prediction": winner["received_amount"].prediction,
                    }
                returned_amount_obj = Returned_Amount(**returned_amount)
                returned_amount_obj.save()

                commission_amount = {
                    "returned_amount": returned_amount_obj,
                    "amount": commission
                    }
                commission_amount_obj = Commission_Amount(**commission_amount)
                commission_amount_obj.save()
        # Return any amount remaining after all the winners are paid
        loser_funds_remaining = loser["received_amount"].amount - loser["to_winners"] - loser["commission"]
        if loser_funds_remaining > 0:
            returned_amount = {
                "amount": loser_funds_remaining,
                "from_received_amount": loser["received_amount"],
                "to_prediction": loser["received_amount"].prediction,
                }
            returned_amount_obj = Returned_Amount(**returned_amount)
            returned_amount_obj.save()
Example #4
0
def evaluate_winners_and_losers(future_price):
    """
    This function creates Returned_Amount objects according to who wins
    and loses the future_price wager.
    Winners always get their initial deposit back.
    The loser payments go to the winners in chronological order, until the
    winner has received up to their original deposit amount (less commission),
    and then the next winner begins to receive loser payouts, until there
    are no more loser payments to make.
    If there are more losers than winners, the losers who are not paid to
    winners are returned to the losers.
    """

    winners = []
    losers = []

    target_price = future_price.target_price
    try:
        actual_price_obj = Bitcoin_Price.objects.get(
            time=future_price.time_to_match_price)
    except:
        return  # there is no bitcoin price for this time so this future_price cannot be evaluated
    actual_price = actual_price_obj.price
    price_is_less_than_target = actual_price < target_price
    price_is_equal_to_target = target_price == actual_price

    amounts = Received_Amount.objects.filter(
        amount__gt=0,
        prediction__future_price=future_price,
        time__lt=future_price.time_window_closes).order_by('time', 'id')

    # Split into winners and losers
    for received_amount in amounts:
        guessed_correctly = (received_amount.prediction.price_will_be_less_than_target and price_is_less_than_target) or \
            (not received_amount.prediction.price_will_be_less_than_target and not price_is_less_than_target)
        if guessed_correctly:
            # This is a winner
            returned_amount = {
                "amount": received_amount.amount,
                "from_received_amount": received_amount,
                "to_prediction": received_amount.prediction,
            }
            returned_amount_obj = Returned_Amount(**returned_amount)
            returned_amount_obj.save()
            winners.append({
                "received_amount": received_amount,
                "from_losers": 0
            })
        elif price_is_equal_to_target:
            # Eligible for refund but not for winnings
            # TODO: If the received amount is not confirmed, it will still be
            # returned
            returned_amount = {
                "amount": received_amount.amount,
                "from_received_amount": received_amount,
                "to_prediction": received_amount.prediction,
            }
            returned_amount_obj = Returned_Amount(**returned_amount)
            returned_amount_obj.save()
        else:
            # Record this so in the next step this can be allocated to winners
            losers.append({
                "received_amount": received_amount,
                "to_winners": 0,
                "commission": 0
            })

    for loser in losers:
        # Pay the winners
        for winner in winners:
            loser_funds_remaining = loser["received_amount"].amount - loser[
                "to_winners"] - loser["commission"]
            loser_is_broke = loser_funds_remaining == 0
            if loser_is_broke:
                break
            winner_received_from_losers = winner["from_losers"]
            winner_total_owed_from_losers = winner[
                "received_amount"].amount * (1 - COMMISSION)
            amount_remaining_to_pay_winner = winner_total_owed_from_losers - winner_received_from_losers
            if amount_remaining_to_pay_winner > 0:
                amount_to_pay_winner = min(
                    amount_remaining_to_pay_winner,
                    loser_funds_remaining * (1 - COMMISSION))
                commission = amount_to_pay_winner / (1 -
                                                     COMMISSION) * COMMISSION
                loser[
                    "to_winners"] = loser["to_winners"] + amount_to_pay_winner
                loser["commission"] = loser["commission"] + commission
                winner["from_losers"] = winner[
                    "from_losers"] + amount_to_pay_winner
                returned_amount = {
                    "amount": amount_to_pay_winner,
                    "from_received_amount": loser["received_amount"],
                    "to_prediction": winner["received_amount"].prediction,
                }
                returned_amount_obj = Returned_Amount(**returned_amount)
                returned_amount_obj.save()

                commission_amount = {
                    "returned_amount": returned_amount_obj,
                    "amount": commission
                }
                commission_amount_obj = Commission_Amount(**commission_amount)
                commission_amount_obj.save()
        # Return any amount remaining after all the winners are paid
        loser_funds_remaining = loser["received_amount"].amount - loser[
            "to_winners"] - loser["commission"]
        if loser_funds_remaining > 0:
            returned_amount = {
                "amount": loser_funds_remaining,
                "from_received_amount": loser["received_amount"],
                "to_prediction": loser["received_amount"].prediction,
            }
            returned_amount_obj = Returned_Amount(**returned_amount)
            returned_amount_obj.save()