Part 12: How To Estimate Curation Rewards Using Steem-Python

in #utopian-io7 years ago (edited)

steem-python.png

This tutorial is part of a series where we explain different aspects of programming with steem-python. Links to the other tutorials can be found in the curriculum section below. In part 9 of this series we learned how to calculate the total rewards of a post and in this tutorial we will learn how to estimate the curation rewards of a post!


What will I learn

  • How to sort votes by rshares
  • How to calculate the curation reward penalty
  • How to use this to calculate the curation reward of a vote
  • How to estimate the total curation reward of a post

Requirements

  • Python3.6
  • steem-python

Difficulty

  • Intermediate

Tutorial

If you find it easier to follow along this way you can get the entire code for this tutorial from here, where I have split everything up into the relevant sections.

Sorting votes by rshares

Before we start calculating the curation reward penalty I want to look at the information each vote provides.

{
  "voter": "juliank",
  "weight": 19987,
  "rshares": "407698665716",
  "percent": 3000,
  "reputation": "66217154475939",
  "time": "2018-01-22T18:10:33"
}

If you recall from part 10, each vote looks something like the above one. Instead of jumping to calculating the curation penalty straight away, we will print some information about each post, so you can see what each part can be used for. For example, using what we have already learned, we could print the voter, how much their vote was worth and the percent of their vote. To do this we need the code that we used in part 9 to calculate a post's rewards, then create a list of all the votes using list comprehension and loop over it, like so

# Everything we need to calculate the reward
reward_fund = steem.get_reward_fund()
reward_balance = Amount(reward_fund["reward_balance"]).amount
recent_claims = float(reward_fund["recent_claims"])
reward_share = reward_balance / recent_claims
base = Amount(steem.get_current_median_history_price()["base"]).amount

post = Post("@steempytutorials/part-11-how-to-build-a-list-of-transfers-and-broadcast-these-in-one-transaction-with-steem-python")

# Create list of all votes, sort them by reward and print the top five
votes = [vote for vote in post["active_votes"]]
for vote in sorted(votes, key=lambda x: float(x["rshares"]), reverse=True):
    print("{0:16} voted for ${1} - {2:>5}%".format(
        vote["voter"],
        str(float(vote["rshares"]) * reward_share * base)[:5],
        vote["percent"] / 100))

which outputs the following

juliank          voted for $3.849 -  30.0%
nicnas           voted for $0.390 - 100.0%
fooblic          voted for $0.176 - 100.0%
adialam          voted for $0.037 - 100.0%
cifer            voted for $0.017 -  90.0%

But here we aren't taking the curation reward penalty into account (amongst other things)! We need to use the time attribute of a vote to calculate this!

Curation reward penalty

As some of you may know there is a curation reward penalty in the first 30 minutes after a post has been published. For example, if we take a post that is 10 minutes old and vote on it, our vote would only get 33% curation rewards. In steem-python there's a function called curation_reward_pct() that takes a post and then outputs what the penalty would be if you voted on it at that moment. We don't really have a use for this function, but we can use it as inspiration to create our own function. So let's take a look at it:

def curation_reward_pct(self):
    """ If post is less than 30 minutes old, it will incur a curation reward penalty.
    """
    reward = (self.time_elapsed().seconds / 1800) * 100
    if reward > 100:
        reward = 100
    return reward

Looks pretty simple! We can create a function that takes a post and a vote on that post as arguments, then outputs the penalty the vote incurred at the time of voting. To do this we can use the function parse() to easily convert the time string to something we can use in our calculations and use timedelta to change the 1800 seconds to 30 minutes instead (just for readability)

from dateutil.parser import parse
from datetime import timedelta

def curation_penalty(post, vote):
    post_time = post["created"]
    vote_time = parse(vote["time"])
    time_elapsed = vote_time - post_time
    reward = time_elapsed / timedelta(minutes=30) * 1.0

    if reward > 1.0:
        reward = 1.0
    return reward

I have decided to return a number in the range 0 - 1.0, because then we can use this to multiple each vote's reward.

Calculating curation reward per vote

Okay, so now we have a function to calculate the curation penalty, but what do we actually use this for? Since someone's reward is calculated by their amount of rshares, we can simply multiply this with their curation penalty to get their actual rshares. Also, instead of calculating the actual reward at the end, like we did in part 9, we will calculate the reward straight away. To do this we can create a simple curation_reward() function that calculates the estimated payout that each voter will receive. We must also remember that only 25% goes to the curators, so we should take that into account as well

curation_pct = 0.25
def curation_reward(post, vote):
    rshares = float(vote["rshares"])
    base_share = reward_share * base

    return (rshares * curation_penalty(post, vote) * curation_pct) * base_share

Adding everything together

Now we can calculate the payout for each vote separately, all that's left is to sum everything together!

curation_share = sum([curation_reward(post, vote) for vote in votes])
print(f"Estimated curation reward for this post is ${curation_share:.2}")

which for the post we used outputs the following

Estimated curation reward for this post is $0.22

Revisiting the votes

Since we can now calculate the actual value that curators get, we can revisit the five votes from above and see what their actual reward is!

juliank          curation reward is $0.035 -  30.0%
nicnas           curation reward is $0.097 - 100.0%
fooblic          curation reward is $0.044 - 100.0%
adialam          curation reward is $0.009 - 100.0%
cifer            curation reward is $0.004 -  90.0%

Congratulations, you've now learned how to estimate the curation reward for a post using steem-python! You've also been introduced to using list comprehensions (if you have never used them before), which are personally one of my favourite things.

Curriculum


The code for this tutorial can be found on GitHub!

This tutorial was written by @amosbastian in conjunction with @juliank.



Posted on Utopian.io - Rewarding Open Source Contributors

Sort:  

Thank you for the contribution. It has been approved.

You can contact us on Discord.
[utopian-moderator]

Merci beaucoup!

thanks for the tutorial, it is very helpful to predict how many results we can get from the curator or author

Hey @steempytutorials I am @utopian-io. I have just upvoted you!

Achievements

  • You have less than 500 followers. Just gave you a gift to help you succeed!
  • Seems like you contribute quite often. AMAZING!

Suggestions

  • Contribute more often to get higher and higher rewards. I wish to see you often!
  • Work on your followers to increase the votes/rewards. I follow what humans do and my vote is mainly based on that. Good luck!

Get Noticed!

  • Did you know project owners can manually vote with their own voting power or by voting power delegated to their projects? Ask the project owner to review your contributions!

Community-Driven Witness!

I am the first and only Steem Community-Driven Witness. Participate on Discord. Lets GROW TOGETHER!

mooncryption-utopian-witness-gif

Up-vote this comment to grow my power and help Open Source contributions like this one. Want to chat? Join me on Discord https://discord.gg/Pc8HG9x

Coin Marketplace

STEEM 0.20
TRX 0.14
JST 0.030
BTC 68726.56
ETH 3273.79
USDT 1.00
SBD 2.67