Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 9 additions & 8 deletions boundless_profitability.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,11 @@
"\n",
"**This value will vary depending on the prover. To calculate the utilization for a specific prover, see [zerokrab/boundless-market-util](https://github.com/zerokrab/boundless-market-util).**\n",
"\n",
"`MARKET_REWARD_USD_PER_MHZ`\n",
"`MARKET_REWARD_USD_PER_BCYCLE`\n",
"\n",
"An array of potential market order prices (USD/Mhz) to be modelled.\n",
"An array of potential market order prices (USD/Bcycle) to be modelled.\n",
"\n",
"Can be estimated from [market stats](https://explorer.boundless.network/stats), (see \"Lock price per cycle distribution\"). You can divide USD/Bcycle by 1000 to get USD/Mhz.\n",
"Can be estimated from [market stats](https://explorer.boundless.network/stats), (see \"Lock price per cycle distribution\").\n",
"\n",
"`FIXED_COST_MONTHLY_USD`\n",
"\n",
Expand All @@ -88,7 +88,7 @@
"MARKET_ORDER_UTIL = 0.5\n",
"\n",
"# Average reward per million cycles in USD (range of scenarios)\n",
"MARKET_REWARD_USD_PER_MHZ = [0.00003, 0.00005, 0.00007, 0.0001]\n",
"MARKET_REWARD_USD_PER_BCYCLE = [0.03, 0.05, 0.07, 0.1]\n",
"\n",
"# Fixed cost additional expenses\n",
"FIXED_COST_MONTHLY_USD = 0\n",
Expand Down Expand Up @@ -228,7 +228,7 @@
"source": [
"## 2. Compute Cost, Revenue, Profit\n",
"\n",
"**Profit per epoch** = total revenue total cost (GPU + fixed)."
"**Profit per epoch** = total revenue \u2212 total cost (GPU + fixed)."
]
},
{
Expand All @@ -243,8 +243,9 @@
" scenario = row[\"label\"]\n",
" for zkc_price in ZKC_PRICES_USD:\n",
" povw_revenue = mhz_per_epoch * POVW_ZKC_PER_MHZ_PER_EPOCH * zkc_price\n",
" for market_reward in MARKET_REWARD_USD_PER_MHZ:\n",
" market_revenue = mhz_per_epoch * market_reward * MARKET_ORDER_UTIL\n",
" for market_reward_bcycle in MARKET_REWARD_USD_PER_BCYCLE:\n",
" market_reward_mhz = market_reward_bcycle / 1000\n",
" market_revenue = mhz_per_epoch * market_reward_mhz * MARKET_ORDER_UTIL\n",
" total_revenue = povw_revenue + market_revenue\n",
" profit = total_revenue - total_cost_epoch\n",
" results.append({\n",
Expand All @@ -253,7 +254,7 @@
" \"num_gpus\": row[\"num_gpus\"],\n",
" \"zkc_price_usd\": zkc_price,\n",
" \"market_order_util\": MARKET_ORDER_UTIL,\n",
" \"market_reward_usd_per_mhz\": market_reward,\n",
" \"market_reward_usd_per_mhz\": market_reward_mhz,\n",
" \"mhz_per_epoch\": mhz_per_epoch,\n",
" \"cost_per_epoch\": total_cost_epoch,\n",
" \"povw_revenue\": povw_revenue,\n",
Expand Down
10 changes: 6 additions & 4 deletions dashboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ def build_dashboard(df: pd.DataFrame | None = None) -> pn.viewable.Viewable:
name="ZKC Price (USD)", options=zkc_prices, value=zkc_prices[len(zkc_prices) // 2]
)
reward_slider = pn.widgets.FloatSlider(
name="Market Reward (USD/MHz)", start=0.00001, end=0.0002, step=0.00001, value=0.00007,
format="0.00000",
name="Market Reward (USD/Bcycle)", start=0.01, end=0.2, step=0.01, value=0.07,
format="0.00",
)

# ── Tab 1: Profit Explorer ────────────────────────────────────────────────
Expand All @@ -53,7 +53,8 @@ def profit_chart(zkc_price, market_reward):
# Base rows at the reference reward; scale market_revenue linearly to market_reward.
# market_revenue ∝ reward (mhz * reward * util), so scaling is exact.
sub = df[(df["zkc_price_usd"] == zkc_price) & (df["market_reward_usd_per_mhz"] == ref_reward)]
scale = market_reward / ref_reward if ref_reward > 0 else 0
market_reward_mhz = market_reward / 1000
scale = market_reward_mhz / ref_reward if ref_reward > 0 else 0

labels = sub["label"].tolist()
costs = sub["cost_per_epoch"].tolist()
Expand Down Expand Up @@ -96,7 +97,8 @@ def profit_chart(zkc_price, market_reward):
@pn.depends(reward_slider)
def breakeven_chart(market_reward):
# Scale market_revenue to the chosen reward, then find min profitable ZKC price
scale = market_reward / ref_reward if ref_reward > 0 else 0
market_reward_mhz = market_reward / 1000
scale = market_reward_mhz / ref_reward if ref_reward > 0 else 0
sub = df[df["market_reward_usd_per_mhz"] == ref_reward].copy()
sub = sub.assign(
market_revenue_scaled=sub["market_revenue"] * scale,
Expand Down
Loading