This simulator models the four core economic variables of the IYK/YK system: NFT auction mechanics, IYK ERC-20 distribution, swap signal economics, and the corrected content coin stream model (YK treasury streams content coins, not IYK).
The fastest path is Google Colab — opens in your browser, runs in the cloud, no Python needed locally.
localhost tunnel link that appears — the full Streamlit app opens in a new tab# ── IYK Sim Colab launcher ──
!pip install streamlit plotly numpy pandas pyngrok -q
import threading, time
from pyngrok import ngrok
# Write the app file
app_code = '''
import streamlit as st
import numpy as np
import pandas as pd
import plotly.graph_objects as go
import plotly.express as px
from plotly.subplots import make_subplots
st.set_page_config(page_title="IYK Tokenomics Simulator", layout="wide")
st.title("IYK · YK Tokenomics Simulator")
st.caption("NFT auction · IYK ERC-20 · Swap signals · Content streams")
tab1, tab2, tab3, tab4 = st.tabs(["NFT Auction", "IYK ERC-20", "Swap Signals", "Content Streams"])
with tab1:
st.info("Paste full iyk_sim.py content here — see Notion page for full source.")
'''
with open('iyk_sim.py', 'w') as f:
f.write(app_code)
# Start streamlit in background
def run():
import subprocess
subprocess.run(['streamlit', 'run', 'iyk_sim.py', '--server.port', '8501', '--server.headless', 'true'])
t = threading.Thread(target=run)
t.daemon = True
t.start()
time.sleep(4)
# Open tunnel
public_url = ngrok.connect(8501)
print(f'\\n\\n✅ Open the simulator here: {public_url}\\n')
Note: Replace the stub
app_codein the launcher with the full source from the code block below before running.
pip install streamlit plotly numpy pandas
streamlit run iyk_sim.py
Opens at http://localhost:8501
iyk_sim.pyCopy this entire block into a file called iyk_sim.py:
"""
IYK Tokenomics Simulator
Run: streamlit run iyk_sim.py
Requires: pip install streamlit plotly numpy pandas
"""
import streamlit as st
import numpy as np
import pandas as pd
import plotly.graph_objects as go
import plotly.express as px
from plotly.subplots import make_subplots
st.set_page_config(
page_title="IYK Tokenomics Simulator",
page_icon="📊",
layout="wide",
initial_sidebar_state="expanded",
)
st.markdown("""
<style>
.critique { background: #fff8e1; border-left: 4px solid #f9a825;
padding: 10px 14px; border-radius: 4px; font-size: 0.9rem; margin: 8px 0; }
.good { background: #e8f5e9; border-left: 4px solid #2e7d32;
padding: 10px 14px; border-radius: 4px; font-size: 0.9rem; margin: 8px 0; }
</style>
""", unsafe_allow_html=True)
st.title("IYK · YK Tokenomics Simulator")
st.caption("Explore auction mechanics, IYK ERC-20 distribution, swap signal economics, and content coin stream dynamics.")
tab1, tab2, tab3, tab4 = st.tabs([
"NFT Auction", "IYK ERC-20", "Swap Signals", "Content Streams"
])
# ── TAB 1: NFT AUCTION ───────────────────────────────────────────────────────
with tab1:
st.header("YK NFT Auction Parameters")
col_ctrl, col_out = st.columns([1, 1.6])
with col_ctrl:
cadence_h = st.slider("Auction cadence (hours)", 1, 168, 24, 1)
reserve_eth = st.slider("Reserve price (ETH)", 0.001, 2.0, 0.05, 0.001, format="%.3f ETH")
bid_mult = st.slider("Expected avg bid (x reserve)", 1.0, 10.0, 2.0, 0.1)
total_nfts = st.slider("Founding NFTs (total)", 20, 300, 100, 1)
st.markdown("---")
ordao_pct = st.slider("ORDAO Respect Council (%)", 0, 50, 30, 1)
founder_pct = st.slider("Founder allocation (%)", 0, 30, 10, 1)
airdrop_pct = st.slider("Founding airdrop (%)", 0, 30, 10, 1)
auction_pct = 100 - ordao_pct - founder_pct - airdrop_pct
lp_seed_eth = st.slider("IYK LP seed ETH", 0.01, 5.0, 0.5, 0.01)
with col_out:
auction_nfts = max(0, int(total_nfts * auction_pct / 100))
avg_bid = reserve_eth * bid_mult
auctions_per_wk = 7 * 24 / cadence_h
weeks = np.arange(1, 53)
cum_eth = np.minimum(weeks * auctions_per_wk, auction_nfts) * avg_bid
fig = go.Figure()
fig.add_trace(go.Scatter(x=weeks, y=cum_eth, fill='tozeroy',
line=dict(color='#3266ad'), name='Treasury ETH'))
fig.add_hline(y=lp_seed_eth, line_dash='dash', line_color='#c47c2f',
annotation_text=f'LP seed ({lp_seed_eth:.2f} ETH)')
fig.update_layout(title='Treasury ETH build-up (52 weeks)',
xaxis_title='Week', yaxis_title='ETH', height=300)
st.plotly_chart(fig, use_container_width=True)
days_to_lp = next((((i+1)*7) for i, e in enumerate(cum_eth) if e >= lp_seed_eth), None)
c1,c2,c3,c4 = st.columns(4)
c1.metric("Auction NFTs", auction_nfts)
c2.metric("Avg bid", f"{avg_bid:.3f} ETH")
c3.metric("Treasury at sellout", f"{auction_nfts*avg_bid:.2f} ETH")
c4.metric("Days to LP seed", f"{days_to_lp}d" if days_to_lp else ">1yr")
if auction_pct < 20:
st.warning(f"Open auction only {auction_pct}% — thin community price discovery.")
if ordao_pct + founder_pct > 50:
st.warning(f"ORDAO + founder = {ordao_pct+founder_pct}% — centralization risk at launch.")
# ── TAB 2: IYK ERC-20 ────────────────────────────────────────────────────────
with tab2:
st.header("IYK ERC-20 (Creator Coin)")
col_ctrl, col_out = st.columns([1, 1.6])
with col_ctrl:
supply_m = st.slider("Total supply (millions)", 100, 10_000, 1_000, 100)
lp_pct = st.slider("LP allocation (%)", 5, 60, 20, 1)
lock_months = st.slider("Vault lock (months)", 0, 24, 1, 1)
vest_months = st.slider("Linear vest (months)", 6, 72, 48, 1)
lp_seed_eth2 = st.slider("ETH seeded into LP", 0.01, 5.0, 0.5, 0.01)
eth_price = st.number_input("ETH price (USD)", value=3000, step=100)
epoch_m = st.slider("Sablier epoch (M tokens/qtr)", 0.5, 100.0, 10.0, 0.5)
with col_out:
supply = supply_m * 1e6
lp_tokens = supply * lp_pct / 100
vault_tokens = supply * (1 - lp_pct/100)
token_price_usd = (lp_seed_eth2 * eth_price) / lp_tokens if lp_tokens > 0 else 0
months = np.arange(0, vest_months + lock_months + 1)
def circ(m):
if m <= lock_months: return lp_tokens
return lp_tokens + min((m-lock_months)/vest_months, 1.0) * vault_tokens
circulating = np.array([circ(m) for m in months])
fig2 = go.Figure()
fig2.add_trace(go.Scatter(x=months, y=circulating/1e6, fill='tozeroy',
line=dict(color='#3266ad'), name='Circulating'))
fig2.add_hline(y=lp_tokens/1e6, line_dash='dash', line_color='#c47c2f',
annotation_text='LP floor')
fig2.update_layout(title='Circulating supply over vest schedule',
xaxis_title='Month', yaxis_title='IYK (M)', height=300)
st.plotly_chart(fig2, use_container_width=True)
vault_qtr_pct = (epoch_m*1e6/vault_tokens*100) if vault_tokens > 0 else 0
c1,c2,c3,c4 = st.columns(4)
c1.metric("Token price", f"${token_price_usd:.6f}")
c2.metric("Mkt cap", f"${supply*token_price_usd:,.0f}")
c3.metric("Stream rate", f"{vault_qtr_pct:.2f}%/qtr")
c4.metric("Vault runway", f"{vault_tokens/(epoch_m*1e6)/4:.1f} yrs")
if lp_pct < 15:
st.warning(f"LP at {lp_pct}% — thin float, expect high early volatility.")
if lock_months < 3:
st.warning(f"{lock_months}-month lock is short. Vault unlocks before community is bootstrapped.")
# ── TAB 3: SWAP SIGNALS ──────────────────────────────────────────────────────
with tab3:
st.header("Swap Signal Economics")
st.markdown("Users swap IYK → ContentCoin to vote within programs. Swap volume = stated interest signal.")
col_ctrl, col_out = st.columns([1, 1.6])
with col_ctrl:
swappers = st.slider("Monthly active swappers", 10, 5000, 200, 10)
swap_size = st.slider("Avg IYK per swap", 100, 100_000, 5_000, 100)
fee_bps = st.slider("LP swap fee (bps)", 10, 300, 100, 5)
iyk_price_usd = st.slider("IYK price (USD)", 0.0001, 0.10, 0.005, 0.0001, format="%.4f")
outflow_pct = st.slider("% IYK routed to content coins / mo", 1, 80, 15, 1)
growth_rate = st.slider("Monthly swapper growth (%)", 0, 50, 10, 1)
supply_m3 = st.number_input("Total IYK supply (M)", value=1000, step=100)
with col_out:
monthly_vol = swappers * swap_size
fee_rev_usd = monthly_vol * fee_bps/10_000 * iyk_price_usd
outflow_pct_supply = (monthly_vol * outflow_pct/100) / (supply_m3*1e6) * 100
g = 1 + growth_rate/100
months_p = np.arange(1,13)
vol_series = monthly_vol * g**(months_p-1) * iyk_price_usd / 1000
fee_series = monthly_vol * fee_bps/10_000 * iyk_price_usd * g**(months_p-1)
fig3 = make_subplots(specs=[[{"secondary_y": True}]])
fig3.add_trace(go.Bar(x=months_p, y=vol_series, name='Vol (K USD)',
marker_color='#3266ad', opacity=0.7), secondary_y=False)
fig3.add_trace(go.Scatter(x=months_p, y=fee_series, name='Fee USD',
line=dict(color='#c47c2f'), mode='lines+markers'), secondary_y=True)
fig3.update_layout(title='Swap volume & fees (12mo projection)', height=300)
st.plotly_chart(fig3, use_container_width=True)
c1,c2,c3,c4 = st.columns(4)
c1.metric("Monthly vol", f"${monthly_vol*iyk_price_usd:,.0f}")
c2.metric("Monthly fees", f"${fee_rev_usd:,.2f}")
c3.metric("Outflow/supply", f"{outflow_pct_supply:.4f}%/mo")
c4.metric("Annual fees", f"${fee_rev_usd*12:,.0f}")
if outflow_pct_supply > 0.5:
st.warning(f"Monthly outflow {outflow_pct_supply:.3f}% of supply — sustained selling creates IYK price drag.")
if swappers < 50:
st.warning(f"Only {swappers} swappers — signal statistically weak, whale manipulation risk.")
# ── TAB 4: CONTENT STREAMS ───────────────────────────────────────────────────
with tab4:
st.header("Content Coin Stream Model")
st.markdown("""
**Correct model:** YK treasury custodies content coins (WTM, CANON) at program approval.
Treasury streams a % of those content coins to program recipients via Sablier.
Recipients hold (vote), sell into ContentCoin/IYK LP, or add to LP.
Selling into LP removes IYK from the pool (IYK price up) and adds ContentCoins (ContentCoin price down).
""")
col_ctrl, col_out = st.columns([1, 1.6])
with col_ctrl:
content_supply = st.number_input("Content coin total supply", value=10_000_000, step=500_000)
treasury_custody_pct = st.slider("% custodied by YK treasury", 0, 100, 50, 1)
stream_pct_qtr = st.slider("Stream rate (% of custody / qtr)", 0.5, 25.0, 5.0, 0.5)
qtrs = st.slider("Quarters to simulate", 1, 20, 8)
iyk_in_lp = st.slider("IYK in ContentCoin/IYK LP at launch (M)", 0.1, 50.0, 5.0, 0.1)
content_in_lp = st.slider("Content coins in LP at launch (M)", 0.01, 5.0, 0.5, 0.01)
iyk_price_cc = st.slider("IYK price (USD)", 0.0001, 0.10, 0.005, 0.0001,
format="%.4f", key="cc_price")
sell_pct = st.slider("Recipient sell to LP (%)", 0, 100, 30, 5)
lp_dep_pct = st.slider("Recipient add to LP (%)", 0, 100, 20, 5)
hold_pct = 100 - sell_pct - lp_dep_pct
st.caption(f"Hold / vote: {hold_pct}%" if hold_pct >= 0 else "⚠️ Exceeds 100%")
with col_out:
if hold_pct < 0:
st.error("Sell + LP > 100%. Adjust sliders.")
else:
treasury_coins = content_supply * treasury_custody_pct / 100
coins_per_qtr = treasury_coins * stream_pct_qtr / 100
qtrs_arr = np.arange(1, qtrs+1)
# AMM simulation
iyk_lp_r, cc_lp_r = iyk_in_lp, content_in_lp
k = iyk_lp_r * cc_lp_r
cc_price_s, iyk_removed_s = [], []
for _ in range(qtrs):
dcc_sell = (coins_per_qtr * sell_pct / 100) / 1e6
dcc_lp = (coins_per_qtr * lp_dep_pct / 100) / 1e6
if sell_pct > 0:
new_cc = cc_lp_r + dcc_sell
new_iyk = k / new_cc
iyk_removed_s.append(max(iyk_lp_r - new_iyk, 0))
cc_lp_r, iyk_lp_r = new_cc, new_iyk
else:
iyk_removed_s.append(0)
if lp_dep_pct > 0:
ratio = iyk_lp_r / cc_lp_r if cc_lp_r > 0 else 1
cc_lp_r += dcc_lp
iyk_lp_r += dcc_lp * ratio
k = iyk_lp_r * cc_lp_r
cc_price_s.append(iyk_lp_r / cc_lp_r if cc_lp_r > 0 else 0)
cc_price_s = np.array(cc_price_s)
iyk_removed_s = np.array(iyk_removed_s)
fig4 = make_subplots(rows=2, cols=1,
subplot_titles=("ContentCoin price (IYK/token)",
"IYK removed from LP per quarter (M)"),
shared_xaxes=True, vertical_spacing=0.15)
fig4.add_trace(go.Scatter(x=qtrs_arr, y=cc_price_s,
line=dict(color='#3266ad'), mode='lines+markers'), row=1, col=1)
fig4.add_trace(go.Bar(x=qtrs_arr, y=iyk_removed_s,
marker_color='#e05c45'), row=2, col=1)
fig4.update_layout(height=380, showlegend=False)
st.plotly_chart(fig4, use_container_width=True)
qtr_exhaust = treasury_coins / coins_per_qtr if coins_per_qtr > 0 else 999
price_delta = (cc_price_s[-1]/cc_price_s[0]-1)*100 if len(cc_price_s)>1 and cc_price_s[0]>0 else 0
c1,c2,c3,c4 = st.columns(4)
c1.metric("Treasury custody", f"{treasury_coins/1e6:.1f}M coins")
c2.metric("Per-qtr stream", f"{coins_per_qtr/1e6:.2f}M")
c3.metric("Exhausted in", f"Q{qtr_exhaust:.0f}")
c4.metric(f"Price delta (Q{qtrs})", f"{price_delta:+.1f}%")
if sell_pct > 50:
st.warning(f"{sell_pct}% sell pressure steadily depresses ContentCoin/IYK pool.")
if iyk_removed_s.sum() > iyk_in_lp * 1e6 * 0.3:
st.warning(f"Sell pressure removed {iyk_removed_s.sum()/1e6:.1f}M IYK from LP — pool becoming thin.")
if hold_pct < 20:
st.warning(f"Only {hold_pct}% held for voting — low governance engagement signal.")
st.markdown("---")
st.caption("IYK · YK Tokenomics Simulator v0.1 — all models are approximations.")