<jupyter_start><jupyter_text>single epoch<jupyter_code>epoch = 20
bp_key = "<KEY>"

results = lib.get_epoch_df(epoch, block_producer_key=bp_key)

df = results['df']
stakes_df = results['stakes_df']<jupyter_output><empty_output><jupyter_text>data quick look<jupyter_code>results.keys()
df.head()
df.shape
stakes_df.head()
df.winner_pk.value_counts()
df[df.outcome == 'FUTURE'][['winner_pk', 'super_charged', 'next_block_in']]<jupyter_output><empty_output><jupyter_text>outcome per epoch<jupyter_code>sns.set(rc={"figure.figsize": (8, 5)})


counts_df = (
    df.groupby("epoch")
    .outcome.value_counts()
    .to_frame()
    .rename(columns={"outcome": "outcome_count"})
    .reset_index()
)

sns.barplot(x="epoch", y="outcome_count", data=counts_df, hue="outcome")<jupyter_output><empty_output><jupyter_text>outcome grouped by super_charged<jupyter_code>df.groupby(["epoch", "super_charged"]).outcome.value_counts()<jupyter_output><empty_output><jupyter_text>slot luck - example of a super unlucky epochtry to visualize "slot luck"<jupyter_code>fig, ax = plt.subplots(1, 1, figsize=(10, 10))

SLOTS_PER_EPOCH = 7140

def get_slot_win_perc(stake, total_currency):
    return (1 - ((1 / 4) ** (stake / total_currency)))


epoch_data = []

total_currency = results['epoch_data']['total_currency']
total_staking_balance = results['stakes_df'].balance.sum()

slot_win_pct = get_slot_win_perc(
    total_staking_balance, total_currency
)    
expected_blocks_value = slot_win_pct * SLOTS_PER_EPOCH 

won_blocks = df[(df.epoch == epoch) & (df.outcome == 'WON')].block.count()
slots_won = df[(df.epoch == epoch)].slot.nunique()

data = binom.rvs(n=SLOTS_PER_EPOCH, p=slot_win_pct, size=100000)

k = np.arange(int(expected_blocks_value - 50), int(expected_blocks_value) + 50, 1)

plt.figure(epoch)

sns.histplot(data, kde=True, bins=k, ax=ax)
ax.axvline(df[(df.epoch == epoch)].block.nunique(), 0, 1, color="r")
ax.set_title(f"epoch {epoch}")

epoch_data.append({
    'epoch': epoch,
    'expected_slots': expected_blocks_value,
    'expected_slots_binom': binom(SLOTS_PER_EPOCH, slot_win_pct).expect(),
    'slot_win_pct': slot_win_pct,
    'won_slots': slots_won,
    'won_blocks': won_blocks,
    'orphan_rate': 1 - (won_blocks/slots_won)
})

print(f"epoch {epoch} - expected {round(expected_blocks_value)} slots - got {slots_won}... ")


plt.show()
# this us SUPER unlucky

epoch_slots_df = pd.DataFrame(epoch_data)

epoch_slots_df["cdf"] = epoch_slots_df.apply(
    lambda row: binom.cdf(row["won_slots"], SLOTS_PER_EPOCH, row["slot_win_pct"]),
    axis=1,
)
epoch_slots_df<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.15846153846153846, 'fraction_numerical': 0.012307692307692308, 'mean_word_length': 6.605263157894737, 'pattern_counts': {'":': 2, '<': 22, '<?xml version=': 0, '>': 22, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '5', 'dir': 'jupyter-structured-clean-dedup', 'id': '616853', 'license': 'MIT', 'n_tokens_mistral': 1098, 'n_tokens_neox': 1076, 'n_words': 150, 'path': 'examples/current_epoch.ipynb', 'repo_name': 'bakebrain/mina-vrf-py', 'size': '2650'}