def curation_stats(self):
        trailing_24hr_t = time.time() - datetime.timedelta(
            hours=24).total_seconds()
        trailing_7d_t = time.time() - datetime.timedelta(
            days=7).total_seconds()

        reward_24h = 0.0
        reward_7d = 0.0

        for reward in self.history2(filter_by="curation_reward", take=10000):

            timestamp = parse_time(reward['timestamp']).timestamp()
            if timestamp > trailing_7d_t:
                reward_7d += Amount(reward['reward']).amount

            if timestamp > trailing_24hr_t:
                reward_24h += Amount(reward['reward']).amount

        reward_7d = self.converter.vests_to_sp(reward_7d)
        reward_24h = self.converter.vests_to_sp(reward_24h)
        return {
            "24hr": reward_24h,
            "7d": reward_7d,
            "avg": reward_7d / 7,
        }
Beispiel #2
0
def have_bandwidth(steem, account):
    '''
        Determine if the given account has enough bandwidth to do stuff.
        Note that this is just an estimate to return approximately >20% bandwidth remaining.
    '''
    # FIXME: rewrite this once we get a better calculation for determining available bandwidth

    props = steem.get_dynamic_global_properties()
    log.debug("got global properties", props=props)

    total_vests = Amount(props['total_vesting_shares']).amount
    max_bandwidth = int(props['max_virtual_bandwidth'])

    vests = Amount(account['vesting_shares']).amount
    bw_post = steem.get_account_bandwidth(account.name, "post")
    bw_forum = steem.get_account_bandwidth(account.name, "forum")
    bw_market = steem.get_account_bandwidth(account.name, "market")
    log.debug("account bandwidth information",
              vests=vests,
              post=bw_post,
              forum=bw_forum,
              market=bw_market)

    bw_allocated = vests / total_vests
    bw_used = (int(bw_market['average_bandwidth']) +
               int(bw_forum['average_bandwidth'])) / max_bandwidth
    ratio = bw_used / bw_allocated
    log.debug("bandwidth calculation",
              allocated=bw_allocated,
              used=bw_used,
              ratio=ratio)

    return ratio < 9
Beispiel #3
0
 def check_balances(self, account=None):
     if account is None:
         account = self.mainaccount
     try:
         self.votepower
     except:
         pass
     else:
         if account == self.checkedaccount:
             return [
                 self.sbdbal, self.steembal, self.steempower,
                 self.votepower, self.lastvotetime
             ]
     self.checkedaccount = account
     try:
         acct = self.steem_instance().get_account(account)
     except Exception as e:
         self.msg.error_message(e)
         return False
     else:
         c = Converter()
         self.sbdbal = Amount(acct['sbd_balance']).amount or 0
         self.steembal = Amount(acct['balance']).amount or 0
         self.votepower = acct['voting_power']
         self.lastvotetime = acct['last_vote_time']
         vs = Amount(acct['vesting_shares']).amount
         dvests = Amount(acct['delegated_vesting_shares']).amount
         rvests = Amount(acct['received_vesting_shares']).amount
         vests = (float(vs) - float(dvests)) + float(rvests)
         self.steempower = c.vests_to_sp(vests) or 0
         time.sleep(5)
         return [
             self.sbdbal, self.steembal, self.steempower, self.votepower,
             self.lastvotetime
         ]
Beispiel #4
0
 def check_balances(self, account=None):
     ''' Fetches an account balance and makes
     necessary conversions
     '''
     a = self.account(account)
     if a is not False and a is not None:
         self.sbdbal = Amount(a['sbd_balance']).amount
         self.steembal = Amount(a['balance']).amount
         self.votepower = a['voting_power']
         self.lastvotetime = a['last_vote_time']
         vs = Amount(a['vesting_shares']).amount
         dvests = Amount(a['delegated_vesting_shares']).amount
         rvests = Amount(a['received_vesting_shares']).amount
         vests = (float(vs) - float(dvests)) + float(rvests)
         try:
             self.global_props()
             self.steempower_delegated = self.util.vests_to_sp(dvests)
             self.steempower_raw = self.util.vests_to_sp(vs)
             self.steempower = self.util.vests_to_sp(vests)
         except Exception as e:
             self.msg.error_message(e)
             self.e = e
         else:
             return [self.sbdbal, self.steembal, self.steempower, 
                     self.votepower, self.lastvotetime]
     return False
Beispiel #5
0
def vests_to_sp(vests, info):
    steem_per_mvests = (
        Amount(info["total_vesting_fund_steem"]).amount /
        (Amount(info["total_vesting_shares"]).amount / 1e6)
    )

    return vests / 1e6 * steem_per_mvests
Beispiel #6
0
 def action(self):
     return "%s claimed rewards: %s sbd, %s steem, %.2f vests." % (
         self.actor,
         Amount(self.raw_data["reward_sbd"]),
         Amount(self.raw_data["reward_steem"]),
         Amount(self.raw_data["reward_vests"])
     )
Beispiel #7
0
 def action(self):
     return '%s got %s for <a href="%s">%s</a>. ' \
            '<br>%s sbd, %s steem, %.2f vests.' % \
            (self.actor, self.exact_action, self.link,
             self.raw_data["permlink"],
             Amount(self.raw_data["sbd_payout"]).amount,
             Amount(self.raw_data["steem_payout"]).amount,
             Amount(self.raw_data["vesting_payout"]).amount)
    def convert_rshares(self, rshares):
        reward_fund = self.steem.get_reward_fund()
        reward_balance, recent_claims = (reward_fund["reward_balance"],
                                         reward_fund["recent_claims"])
        base_price = self.steem.get_current_median_history_price()["base"]

        fund_per_share = Amount(reward_balance).amount / float(recent_claims)
        payout = float(rshares) * fund_per_share * Amount(base_price).amount
        return payout
Beispiel #9
0
    def balances(self):
        steem_balance = "%.3f" % Amount(self.account_data['balance']).amount
        sbd_balance = "%.3f" % Amount(self.account_data['sbd_balance']).amount
        vests = "%.3f" % Amount(self.account_data['vesting_shares']).amount

        return {
            'STEEM': steem_balance,
            'SBD': sbd_balance,
            'VESTS': vests,
        }
Beispiel #10
0
def getvotevalue(SP, VotingPower, VotingWeight):
    POWER = SP / (float(Amount(steem.steemd.get_dynamic_global_properties()['total_vesting_fund_steem']).amount) \
        / float(steem.steemd.get_dynamic_global_properties()['total_vesting_shares'].rstrip(' VESTS')))
    VOTING = ((100 * VotingPower * (100 * VotingWeight) / 10000) + 49) / 50
    REW = float(Amount(steem.steemd.get_reward_fund()['reward_balance']).amount) \
        / float(steem.steemd.get_reward_fund()['recent_claims'])
    PRICE = float(Amount(steem.steemd.get_current_median_history_price()['base']).amount) \
        / float(Amount(steem.steemd.get_current_median_history_price()['quote']).amount)
    VoteValue = (POWER * VOTING * 100) * REW * PRICE
    return VoteValue
Beispiel #11
0
def getvoteweight(SP, VoteValue, VotingPower):
    POWER = SP / (float(Amount(steem.steemd.get_dynamic_global_properties()['total_vesting_fund_steem']).amount) \
        / float(steem.steemd.get_dynamic_global_properties()['total_vesting_shares'].rstrip(' VESTS')))
    REW = float(Amount(steem.steemd.get_reward_fund()['reward_balance']).amount) \
        / float(steem.steemd.get_reward_fund()['recent_claims'])
    PRICE = float(Amount(steem.steemd.get_current_median_history_price()['base']).amount) \
        / float(Amount(steem.steemd.get_current_median_history_price()['quote']).amount)
    VOTING = VoteValue / (POWER * 100 * REW * PRICE)
    VotingWeight = ((VOTING * 50 - 49) * 10000) / (100 * 100 * VotingPower)
    return VotingWeight
Beispiel #12
0
 def reward_pool_balances(self):
     try:
         self.reward_balance
     except:
         reward_fund = self.steem_instance().get_reward_fund()
         self.reward_balance = Amount(reward_fund["reward_balance"]).amount
         self.recent_claims = float(reward_fund["recent_claims"])
         self.base = Amount(
             self.steem_instance().get_current_median_history_price()
             ["base"]).amount
     return [self.reward_balance, self.recent_claims, self.base]
Beispiel #13
0
def pending_payout(username):
    context = {}
    for post in steem.get_blog(username, 500, 500):
        post = Post(post["comment"])
        if post.is_main_post() and post["author"] == username:
            if "1970-01-01 00:00:00" == str(post["last_payout"]):
                payout = Amount(post["pending_payout_value"]).amount
                if payout == 0:
                    payout = (Amount(post["total_payout_value"]).amount +
                              Amount(post["curator_payout_value"]).amount)
                context[post.title] = payout * 0.56 * 0.5
    return context
Beispiel #14
0
 def calculate_voteworth(self):  # To calculate the vote worth
     reward_fund = s.get_reward_fund()
     sbd_median_price = s.get_current_median_history_price()
     vests = Amount(self.data['vesting_shares']) + Amount(
         self.data['received_vesting_shares']) - Amount(
             self.data['delegated_vesting_shares'])
     vestingShares = int(vests * 1e6)
     rshares = 0.02 * vestingShares
     estimated_upvote = rshares / float(
         reward_fund['recent_claims']) * Amount(
             reward_fund['reward_balance']).amount * Amount(
                 sbd_median_price['base']).amount
     estimated_upvote = estimated_upvote * (
         float(self.data['voting_power']) / 10000)
     return ('$' + str(round(estimated_upvote, 2)))
Beispiel #15
0
def x_get_steemit_balances(mode):

    results = steemax.axdb.x_fetch_reward_fund(mode)

    if steemax.axdb.x_check_reward_fund_renewal(results[3]):

        # Get and the current Steemit reward fund steem-python object used to retreive the following values

        reward_fund = s.get_reward_fund()

        # The current Steemit reward balance (reward pool)

        reward_balance = Amount(reward_fund["reward_balance"]).amount

        # The recent claims made on the reward balance (upvotes for the day subtracting from the reward pool)

        recent_claims = float(reward_fund["recent_claims"])

        # The price of Steem in USD

        base = Amount(s.get_current_median_history_price()["base"]).amount

        # Save to database

        steemax.axdb.x_save_reward_fund(reward_balance, recent_claims, base,
                                        mode)

        # Print to screen

        if mode == "verbose":
            print("\n------------------------------------------------")
            print("   Reward balance: " + str(reward_balance))
            print("   Recent claims: " + str(recent_claims))
            print("   Steem = $" + str(base))
            print("------------------------------------------------\n")

        return [reward_balance, recent_claims, base]

    else:

        if mode == "verbose":
            print("\n------------------------------------------------")
            print("   Reward balance: " + str(results[0]))
            print("   Recent claims: " + str(results[1]))
            print("   Steem = $" + str(results[0]))
            print("------------------------------------------------\n")

        return [results[0], results[1], results[2]]
Beispiel #16
0
def rewards(USERNAME):

    print()
    print(WHITEONBLUE + " " + USERNAME.upper() + " ACCOUNT " + GREENONBLACK)
    print()

    acc = steem.get_account(USERNAME)
    account = Account(USERNAME)

    reward_SBD = acc["reward_sbd_balance"]
    reward_SP = acc["reward_vesting_steem"]
    print("\n\nYour current rewards: {} and {} POWER".format(
        reward_SBD, reward_SP))

    allSP = float(acc.get('vesting_shares').rstrip(' VESTS'))
    delSP = float(acc.get('delegated_vesting_shares').rstrip(' VESTS'))
    recSP = float(acc.get('received_vesting_shares').rstrip(' VESTS'))
    activeSP = account.converter.vests_to_sp(allSP - delSP + recSP)

    print("\n\nSTEEM POWER\t{:0.6f}".format(activeSP))

    sbd_balance = Amount(acc["sbd_balance"]).amount
    lowest_ask = float(steem.get_ticker()["lowest_ask"])
    print("\n\nSBD BALANCE\t{:0.6f}".format(sbd_balance))
    print("\n\nSTEEMSBD:\t{:0.6f}".format(lowest_ask, ))

    sbdbase = float(
        Amount(steem.steemd.get_feed_history()['current_median_history']
               ['base']).amount)

    print("\n\nMARKET:")
    print("\nSTEEMUSD:\t{}".format(locale.currency(get_steem_price())))
    print("\nSBDUSD:\t{}".format(locale.currency(get_sbd_price())))

    print("\n\nINTERNAL:")
    print("\n\nSTEEMUSD:\t{}".format(locale.currency(sbdbase)))

    sbdusd = sbdbase / lowest_ask
    print("\n\nSBDUSD:\t{}".format(locale.currency(sbdusd)))

    print("\n\nSBD USD BALANCE\t\t{}".format(
        locale.currency(sbd_balance * sbdusd)))
    print("\n\nSP USD BALANCE\t\t{}".format(locale.currency(activeSP *
                                                            sbdbase)))
    print("\n\n{}TOTAL BALANCE\t\t{}{}\n\n\n".format(
        GREENONGREY,
        locale.currency((activeSP * sbdbase) + (sbd_balance * sbdusd)),
        GREENONBLACK))
Beispiel #17
0
def claim_all_reward_balance(steem, account):
    """Helper funtion to claim rewards because of bug in Steem"""
    acc = Account(account, steem)
    reward_steem = acc['reward_steem_balance']
    reward_sbd = acc['reward_sbd_balance']
    reward_vests = acc['reward_vesting_balance']
    logger.info('Claiming {}, {}, and {} for {}'.format(reward_sbd,
                                                        reward_vests,
                                                        reward_steem,
                                                        account))
    op = operations.ClaimRewardBalance(account=account,
                                       reward_steem=reward_steem,
                                       reward_sbd=reward_sbd,
                                       reward_vests=reward_vests)

    can_claim = any(Amount(x).amount > 0 for x in (reward_sbd, reward_vests, reward_steem))
    if can_claim:
        try:
            return error_retry(steem.commit.finalizeOp)(op, account, "posting")
        except Exception:
            logger.exception('Could not claim rewards {}. '
                             'Reconnecting...'.format((reward_sbd,
                                                      reward_vests,
                                                      reward_steem)))
            steem.reconnect()
    else:
        logger.info('Nothing to claim!')
Beispiel #18
0
def getrsharesvalue(rshares):
    conv = Converter()
    rew_bal = float(
        Amount(steem.steemd.get_reward_fund()['reward_balance']).amount)
    rec_claim = float(steem.steemd.get_reward_fund()['recent_claims'])
    steemvalue = rshares * rew_bal / rec_claim
    return conv.steem_to_sbd(steemvalue)
Beispiel #19
0
def update():
    """Update witness properties."""
    c = get_config()
    c['witness']['url'] = click.prompt(
        'What should be your witness URL?',
        default=c['witness']['url'],
    )
    creation_fee = click.prompt(
        'How much do you want the account creation fee to be (STEEM)?',
        default=c['props']['account_creation_fee'],
    )
    if silent(float)(creation_fee):
        creation_fee = "%s STEEM" % float(creation_fee)
    c['props']['account_creation_fee'] = str(Amount(creation_fee))

    c['props']['maximum_block_size'] = click.prompt(
        'What should be the maximum block size?',
        default=c['props']['maximum_block_size'],
    )
    c['props']['sbd_interest_rate'] = click.prompt(
        'What should be the SBD interest rate?',
        default=c['props']['sbd_interest_rate'],
    )

    # verify
    output(c, '\nConfiguration')
    click.confirm('Do you want to commit the updated values?', abort=True)

    # update
    set_config(c)
    witness_set_props(c['witness']['url'], c['props'])
    output('Witness %s Updated' % c['witness']['name'])
Beispiel #20
0
 def global_props(self):
     ''' Retrieves the global properties
     used to determine rates used for calculations
     in converting steempower to vests etc.
     Stores these in the Utilities class as that
     is where the conversions take place, however
     SimpleSteem is the class that contains
     steem_instance, so to to preserve heirarchy 
     and to avoid "spaghetti code", this method
     exists in this class.
     '''
     if self.util.info is None:
         self.util.info = self.steem_instance().get_dynamic_global_properties()
         self.util.total_vesting_fund_steem = Amount(self.util.info["total_vesting_fund_steem"]).amount
         self.util.total_vesting_shares = Amount(self.util.info["total_vesting_shares"]).amount
         self.util.vote_power_reserve_rate = self.util.info["vote_power_reserve_rate"]
     return self.util.info
Beispiel #21
0
def getvotevalue(SP, VotingPower, VotingWeight):
    """Calculates the SBD value of a vote.

    Args:
        SP: The Steem Power value.
        VotingPower: The Voting Power value, percentage from 0-100.
        VotingWeight: The Voting Weight, percentage from 0-100.
    Returns:
        the upvote value in SBD.
    """
    POWER = SP / (float(Amount(steem.steemd.get_dynamic_global_properties()['total_vesting_fund_steem']).amount) \
        / float(steem.steemd.get_dynamic_global_properties()['total_vesting_shares'].rstrip(' VESTS')))
    VOTING = ((100 * VotingPower * (100 * VotingWeight) / 10000) + 49) / 50
    REW = float(Amount(steem.steemd.get_reward_fund()['reward_balance']).amount) \
        / float(steem.steemd.get_reward_fund()['recent_claims'])
    PRICE = float(Amount(steem.steemd.get_current_median_history_price()['base']).amount) \
        / float(Amount(steem.steemd.get_current_median_history_price()['quote']).amount)
    VoteValue = (POWER * VOTING * 100) * REW * PRICE
    return VoteValue
Beispiel #22
0
def getvoteweight(SP, VoteValue, VotingPower):
    """Calculates the Vote Weight needed to achieve a specific upvote value.

    Args:
        SP: The Steem Power value.
        VotingValue: SBD value to achieve.
        VotingPower: The Voting Power value, percentage from 0-100.
    Returns:
        the Voting Weight, percentage from 0-100.
    """
    POWER = SP / (float(Amount(steem.steemd.get_dynamic_global_properties()['total_vesting_fund_steem']).amount) \
        / float(steem.steemd.get_dynamic_global_properties()['total_vesting_shares'].rstrip(' VESTS')))
    REW = float(Amount(steem.steemd.get_reward_fund()['reward_balance']).amount) \
        / float(steem.steemd.get_reward_fund()['recent_claims'])
    PRICE = float(Amount(steem.steemd.get_current_median_history_price()['base']).amount) \
        / float(Amount(steem.steemd.get_current_median_history_price()['quote']).amount)
    VOTING = VoteValue / (POWER * 100 * REW * PRICE)
    VotingWeight = ((VOTING * 50 - 49) * 10000) / (100 * 100 * VotingPower)
    return VotingWeight
Beispiel #23
0
 def worth_sp(self):
     s = get_steem_conn()
     info = state.load_state()
     p = 10000
     sp = self.total_sp  # steem power
     vp = 100  # voting power
     vw = 100  # voting weight
     tvf = Amount(info['total_vesting_fund_steem']).amount
     tvs = Amount(info['total_vesting_shares']).amount
     r = float(sp / (tvf / tvs))
     m = float(100 * vp * (100 * vw) / p)
     m = float((m + 49) / 50)
     quote = Amount(s.get_current_median_history_price()['quote']).amount
     base = Amount(s.get_current_median_history_price()['base']).amount
     o = base / quote
     rb = Amount(s.get_reward_fund('post')['reward_balance']).amount
     rc = float(s.get_reward_fund('post')['recent_claims'])
     i = rb / rc
     return "%.4f" % (r * m * 100 * i * o)
Beispiel #24
0
    def fetch_tag(self,
                  tag,
                  start_author=None,
                  start_permlink=None,
                  posts=[],
                  scanned_pages=0):
        logger.info("Fetching tag: #%s", tag)
        query = {
            "limit": 100,
            "tag": tag,
        }
        if start_author:
            query.update({
                "start_author": start_author,
                "start_permlink": start_permlink,
            })
        post_list = list(
            self.steemd_instance.get_discussions_by_created(query))
        for post in post_list:
            created_at = parse(post["created"])

            if (datetime.utcnow() - created_at).days > 5:
                return posts

            # Check if post age is older than MINIMUM_POST_AGE (IN MINUTE!)
            elapsed_minutes = (datetime.utcnow() -
                               created_at).total_seconds() // 60
            if self.config.get("MINIMUM_POST_AGE_MIN"):
                if self.config.get("MINIMUM_POST_AGE_MIN") > elapsed_minutes:
                    continue

            if self.config.get("MAXIMUM_POST_REWARDS"):
                pending_payout = Amount(post.get("pending_payout_value"))
                if pending_payout.amount > self.config.get(
                        "MAXIMUM_POST_REWARDS"):
                    continue

            posts.append(post)

        if scanned_pages > 100 or len(posts) > 50:
            logger.info("%s posts found at #%s tag.", len(posts), tag)
            return posts

        if not len(post_list):
            logger.info("No article Found with this tag")
            return posts

        return self.fetch_tag(
            tag,
            start_author=post["author"],
            start_permlink=post["permlink"],
            posts=posts,
            scanned_pages=scanned_pages + 1,
        )
Beispiel #25
0
def detail(full_address):
    detail = {}
    author, permlink = full_address.split("/")[4:]
    post = steem.get_content(author.replace("@", ""), permlink)
    detail["payout"] = Amount(post["pending_payout_value"]).amount * 0.56 * 0.5
    detail["net_votes"] = post["net_votes"]
    detail["votes"] = [
        i["voter"]
        for i in steem.get_active_votes(author.replace("@", ""), permlink)
    ]
    return detail
Beispiel #26
0
def compute_total_sbd(upvote_payments):
    sbd = 0
    steem = 0
    for (author, permalink), payments in upvote_payments.items():
        for payment in payments.values():
            amount = Amount(payment['amount'])
            value = amount.amount
            asset = amount.asset
            if asset == 'SBD':
                sbd += value
            elif asset == 'STEEM':
                steem += value
    return sbd, steem
Beispiel #27
0
def calculate_producer_rewards(steemd_instance, witness_account):
    account = Account(witness_account, steemd_instance=steemd_instance)

    total_vests = 0

    for producer_reward in account.history_reverse(
            filter_by=["producer_reward"]):
        total_vests += Amount(producer_reward["vesting_shares"]).amount

    converter = Converter(steemd_instance=s)
    total_sp = converter.vests_to_sp(total_vests)

    return total_vests, total_sp
Beispiel #28
0
def getrsharesvalue(rshares):
    """Converts a vote's rshares value to current SBD value.

    Args:
        rshares: the rshares value of an upvote.
    Returns:
        the current SBD upvote value.
    """
    conv = Converter()
    rew_bal = float(Amount(steem.steemd.get_reward_fund()['reward_balance']).amount)
    rec_claim = float(steem.steemd.get_reward_fund()['recent_claims'])
    steemvalue = rshares * rew_bal / rec_claim
    return conv.steem_to_sbd(steemvalue)
Beispiel #29
0
def delegations(username):
    if username.startswith("@"):
        username = username.replace("@", "")
    s = get_steem_conn()
    account = Account(username, s).set_account_deta()

    outgoing_delegations = s.get_vesting_delegations(username, 0, 100)
    eight_days_ago = datetime.utcnow() - timedelta(days=8)
    expiring_delegations = s.get_expiring_vesting_delegations(
        username, eight_days_ago.strftime("%Y-%m-%dT%H:%M:%S"), 1000)
    info = state.load_state()
    outgoing_delegations_fixed = []
    for outgoing_delegation in outgoing_delegations:
        created_at = parse(outgoing_delegation["min_delegation_time"])
        amount = Amount(outgoing_delegation["vesting_shares"]).amount
        outgoing_delegation.update({
            "min_delegation_time": created_at,
            "sp": round(vests_to_sp(amount, info), 2),
            "vesting_shares": round(amount / 1e6, 4),
        })
        outgoing_delegations_fixed.append(outgoing_delegation)

    expiring_delegations_fixed = []
    for expiring_delegation in expiring_delegations:
        created_at = parse(expiring_delegation["expiration"])
        amount = Amount(expiring_delegation["vesting_shares"]).amount
        expiring_delegation.update({
            "expiration": created_at,
            "sp": round(vests_to_sp(amount, info), 2),
            "vesting_shares": round(amount / 1e6, 4),
        })
        expiring_delegations_fixed.append(expiring_delegation)

    return render_template(
        "delegations.html",
        account=account,
        outgoing_delegations=outgoing_delegations_fixed,
        expiring_delegations=expiring_delegations,
    )
Beispiel #30
0
def compute_bidbot_correction(post_frame,
                              upvote_payments,
                              sbd_punishment_factor=2.2,
                              steem_punishment_factor=2.0):
    post_frame['sbd_bought_reward'] = 0.
    post_frame['steem_bought_reward'] = 0.
    post_frame['bought_votes'] = 0

    post_frame.set_index(['author', 'permalink'], inplace=True)

    for (author, permalink), payments in upvote_payments.items():
        if (author, permalink) in post_frame.index:
            sbd = 0
            steem = 0
            votes = 0
            for payment in payments.values():
                amount = Amount(payment['amount'])
                value = amount.amount
                asset = amount.asset
                votes += 1
                if asset == 'SBD':
                    sbd += value
                elif asset == 'STEEM':
                    steem += value
                else:
                    raise RuntimeError('W00t?')
            post_frame.loc[
                (author, permalink),
                ['sbd_bought_reward', 'steem_bought_reward', 'bought_votes'
                 ]] = sbd, steem, votes

    post_frame.reset_index(inplace=True)
    post_frame['adjusted_reward'] = post_frame.reward - \
                                    post_frame.sbd_bought_reward * sbd_punishment_factor - \
                                    post_frame.steem_bought_reward * steem_punishment_factor
    post_frame.loc[post_frame.adjusted_reward < 0, 'adjusted_reward'] = 0
    post_frame['adjusted_votes'] = post_frame.votes - post_frame.bought_votes
    post_frame.loc[post_frame.adjusted_votes < 0, 'adjusted_votes'] = 0

    num_articles = (post_frame.bought_votes > 0).sum()
    percent = num_articles / len(post_frame) * 100
    total_steem = post_frame.steem_bought_reward.sum()
    total_sbd = post_frame.sbd_bought_reward.sum()
    total_votes = post_frame.bought_votes.sum()
    logger.info('Found {} upvoted articles ({:.2f}%) with '
                'total {:.3f} STEEM {:.3f} SBD, and {} bought votes!'.format(
                    num_articles, percent, total_steem, total_sbd,
                    total_votes))
    return post_frame