You are viewing a single comment's thread from:

RE: A little script to figure out what witnesses to vote for.

in #python6 days ago

Thanks for the feedback, updated my script. Fixed the HFSCORE, added a hours behind metric and now weighing top 21 accounts stronger for their price feed.

#!/usr/bin/env python3
import json
import datetime

HFSCORE = {
        "1.28.0": 100,
        "default": -30000,
        "nondef": -30000
        }
EXCHSCORET20 = {
        "0.059": 500,
        "0.060": 500,
        "0.061": 500,
        "default": -500,
        "nondef": -500
        }

EXCHSCORE = {
        "0.059": 50,
        "0.060": 50,
        "0.061": 50,
        "default": -50,
        "nondef": 0
        }

CFEETABLE = [
        [3.0, 5.0, 20],
        [5.0, 16.0, 50],
        [16.0, 49.0, 20]]

IRTABLE = [
        [0, 300, 100],
        [300, 700, 3000],
        [700, 1100, 1800],
        [1100, 1400, 500],
        [1400, 1800, 0],
        [1800, 2200, -1000]]

BAGE = [
        [0,4,0],
        [4,24,-600],
        [24, 24*5, -1800],
        [24*5, 24*14, -4000]]

MBTABLE = [
        [30000,100000,0],
        [100000,150000, 30]]

def getscore(val, table):
    if val is None:
        return table["nondef"]
    rval = table.get(val,None)
    if rval is None:
        rval = table["default"]
    return rval

def range_score(val, ranges, default, nondef):
    if val is None:
        return nondef
    for onerange in ranges:
        if val >= onerange[0] and val <= onerange[1]:
            return onerange[2]
    return default
    
def getval(key, obj):
    if "." in key:
        first, more = key.split(".",1)
        if first in obj:
            return getval(more, obj[first])
        return None
    if key in obj:
        return obj[key]
    return None

def numeric(val):
    if val is None:
        return val
    return float(val.split(" ")[0])

def hbd_update_age_score(witn):
    if "last_hbd_exchange_update" in witn:
        dt = (datetime.datetime.now() - datetime.datetime.fromisoformat(witn["last_hbd_exchange_update"])).total_seconds()
        if dt < 3600*2:
            return 40
        if dt < 3600*12:
            return 20
        if dt < 3600*24*2:
            return 10
        if dt < 3600*24*7:
            return 0
    return -300

with open("witnesses.json") as f:
    last_block_num = -1
    witnesses = json.load(f)
    for witness in witnesses["result"]:
        lcb = witness.get("last_confirmed_block_num", -1)
        if lcb > last_block_num:
            last_block_num = lcb
    wno = 0
    print("| score | witness | hours behind | apr | max-bs | creation-fee | exchange-rate | top 21 |")
    print("| --- | --- | --- | --- | --- | --- | --- | --- |")
    for witness in witnesses["result"]:
        wno += 1
        top21 = True
        if wno > 21:
            top21 = False
        behind = (last_block_num - witness.get("last_confirmed_block_num", -1)) // 1200
        score = 0
        score += getscore(getval("hardfork_version_vote", witness), HFSCORE)
        if top21:
            score += getscore(getval("hbd_exchange_rate.base", witness), EXCHSCORET20)
        else:
            score += getscore(getval("hbd_exchange_rate.base", witness), EXCHSCORE)
        score += range_score(numeric(getval("props.account_creation_fee", witness)),CFEETABLE, 0, 0)
        score += range_score(getval("props.hbd_interest_rate", witness),IRTABLE, -4000, -4000) 
        score += range_score(getval("props.maximum_block_size", witness),MBTABLE, -30, -30)
        score += hbd_update_age_score(witness)
        score += range_score(behind, BAGE, -30000, -30000)
        if score > 579:
            print("|", score, "| @" + witness["owner"], "|", behind, "|", 
                    getval("props.hbd_interest_rate", witness), "|", 
                    getval("props.maximum_block_size", witness), "|",
                    getval("props.account_creation_fee", witness),"|",
                    getval("hbd_exchange_rate.base", witness), "|", top21, "|")

New result:

scorewitnesshours behindaprmax-bscreation-feeexchange-ratetop 21
1440@gtg01000655363.000 HIVE0.059 HBDTrue
1440@stoodkev01000655363.000 HIVE0.059 HBDTrue
1440@roelandp01010655363.000 HIVE0.059 HBDTrue
2640@threespeak0600655363.000 HIVE0.059 HBDTrue
1440@guiltyparties01000655363.000 HIVE0.060 HBDTrue
2640@abit0700655363.000 HIVE0.059 HBDTrue
1890@howo01000655363.000 HIVE0.059 HBDFalse
1890@actifit01000655363.000 HIVE0.059 HBDFalse
590@quochuy01400655363.000 HIVE0.059 HBDFalse
1890@oflyhigh01000655363.000 HIVE0.059 HBDFalse
590@techcoderx01200655363.000 HIVE0.059 HBDFalse
3090@rishi5560600655363.000 HIVE0.059 HBDFalse
1890@neoxian01000655363.000 HIVE0.059 HBDFalse
3090@brianoflondon0500655363.000 HIVE0.060 HBDFalse
3090@vsc.network0500655363.000 HIVE0.059 HBDFalse
590@hextech01200655363.000 HIVE0.059 HBDFalse
1890@aliento01000655363.000 HIVE0.059 HBDFalse
1890@sagarkothari8801000655363.000 HIVE0.059 HBDFalse
1890@mengao01000655363.000 HIVE0.059 HBDFalse
1890@c0ff33a01000655363.000 HIVE0.059 HBDFalse
3090@holoz0r0570655363.000 HIVE0.072 HBDFalse
1890@liotes11000655363.000 HIVE0.059 HBDFalse
1890@thebbhproject01000655363.000 HIVE0.085 HBDFalse
1890@stresskiller11000655363.000 HIVE0.059 HBDFalse
1600@innerhive210001310723.000 HIVE0.137 HBDFalse
3080@condeas0500655363.000 HIVE0.061 HBDFalse
1890@hispapro31100655363.000 HIVE0.059 HBDFalse
1870@whiterosecoffee41000655362.000 HIVE0.059 HBDFalse
1890@borislavzlatanov31000655363.000 HIVE0.059 HBDFalse
2150@sn0n7420655361.000 HIVE0.000 HIVEFalse