{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Composed MYCO System\n", "\n", "Full system simulation combining financial deposits, commitment channels, and reserve management." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "import matplotlib.pyplot as plt\n", "\n", "%matplotlib inline\n", "plt.rcParams['figure.figsize'] = (14, 5)\n", "plt.rcParams['figure.dpi'] = 100" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Token Launch Scenario\n", "\n", "50 depositors over 30 days, then some redemptions at days 60-90." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from src.composed.simulator import scenario_token_launch\n", "\n", "np.random.seed(42)\n", "result = scenario_token_launch(n_assets=3, total_raise=100_000, n_depositors=50, duration=90)\n", "\n", "fig, axes = plt.subplots(2, 2, figsize=(14, 10))\n", "\n", "# Supply\n", "ax = axes[0, 0]\n", "ax.plot(result.times, result.supply, 'b-', linewidth=2)\n", "ax.set_xlabel('Day')\n", "ax.set_ylabel('MYCO Supply')\n", "ax.set_title('Token Supply Over Time')\n", "ax.axvspan(0, 30, alpha=0.1, color='green', label='Deposit phase')\n", "ax.axvspan(60, 90, alpha=0.1, color='red', label='Redemption phase')\n", "ax.legend()\n", "\n", "# Reserve Value\n", "ax = axes[0, 1]\n", "ax.plot(result.times, result.reserve_value, 'g-', linewidth=2)\n", "ax.set_xlabel('Day')\n", "ax.set_ylabel('Reserve Value (USD)')\n", "ax.set_title('Total Reserve Value')\n", "\n", "# Backing Ratio\n", "ax = axes[1, 0]\n", "ax.plot(result.times, result.backing_ratio, 'r-', linewidth=2)\n", "ax.axhline(y=1.0, color='k', linestyle='--', alpha=0.5, label='Par (1:1)')\n", "ax.set_xlabel('Day')\n", "ax.set_ylabel('Backing Ratio')\n", "ax.set_title('Backing Ratio (Reserve / Supply)')\n", "ax.legend()\n", "\n", "# Cumulative minted vs redeemed\n", "ax = axes[1, 1]\n", "ax.plot(result.times, result.financial_minted, 'b-', label='Financial minted')\n", "ax.plot(result.times, result.total_redeemed, 'r-', label='Total redeemed')\n", "ax.set_xlabel('Day')\n", "ax.set_ylabel('MYCO')\n", "ax.set_title('Cumulative Minted vs Redeemed')\n", "ax.legend()\n", "\n", "plt.tight_layout()\n", "plt.show()\n", "\n", "print(f'Final supply: {result.supply[-1]:,.2f} MYCO')\n", "print(f'Final reserve: ${result.reserve_value[-1]:,.2f}')\n", "print(f'Final backing ratio: {result.backing_ratio[-1]:.4f}')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Bank Run Scenario\n", "\n", "All holders try to redeem simultaneously. Flow dampening protects remaining holders." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from src.composed.simulator import scenario_bank_run\n", "\n", "result = scenario_bank_run(initial_reserve=100_000, n_assets=3, redemption_fraction=0.05, duration=100)\n", "\n", "fig, axes = plt.subplots(1, 3, figsize=(18, 5))\n", "\n", "ax = axes[0]\n", "ax.plot(result.times, result.supply, 'b-', linewidth=2)\n", "ax.set_xlabel('Day')\n", "ax.set_ylabel('MYCO Supply')\n", "ax.set_title('Supply During Bank Run')\n", "ax.axvline(x=10, color='r', linestyle='--', alpha=0.5, label='Run starts')\n", "ax.legend()\n", "\n", "ax = axes[1]\n", "ax.plot(result.times, result.reserve_value, 'g-', linewidth=2)\n", "ax.set_xlabel('Day')\n", "ax.set_ylabel('Reserve Value')\n", "ax.set_title('Reserve Preservation (flow dampening)')\n", "ax.axvline(x=10, color='r', linestyle='--', alpha=0.5)\n", "\n", "ax = axes[2]\n", "ax.plot(result.times, result.backing_ratio, 'r-', linewidth=2)\n", "ax.axhline(y=1.0, color='k', linestyle='--', alpha=0.5)\n", "ax.set_xlabel('Day')\n", "ax.set_ylabel('Backing Ratio')\n", "ax.set_title('Backing Ratio During Bank Run')\n", "\n", "plt.tight_layout()\n", "plt.show()\n", "\n", "print(f'Reserve preserved: ${result.reserve_value[-1]:,.2f} ({result.reserve_value[-1]/100000*100:.1f}% of initial)')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Mixed Issuance Scenario\n", "\n", "Monthly financial deposits + weekly labor contributions over 1 year." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from src.composed.simulator import scenario_mixed_issuance\n", "\n", "result = scenario_mixed_issuance(n_assets=3, duration=365)\n", "\n", "fig, axes = plt.subplots(2, 2, figsize=(14, 10))\n", "\n", "ax = axes[0, 0]\n", "ax.plot(result.times, result.supply, 'b-', linewidth=2)\n", "ax.set_xlabel('Day')\n", "ax.set_ylabel('MYCO Supply')\n", "ax.set_title('Total Supply (Financial + Commitment)')\n", "\n", "ax = axes[0, 1]\n", "ax.plot(result.times, result.financial_minted, 'b-', label='Financial')\n", "ax.plot(result.times, result.commitment_minted, 'g-', label='Commitment')\n", "ax.set_xlabel('Day')\n", "ax.set_ylabel('Cumulative MYCO')\n", "ax.set_title('Financial vs Commitment Issuance')\n", "ax.legend()\n", "\n", "ax = axes[1, 0]\n", "ax.plot(result.times, result.backing_ratio, 'r-', linewidth=2)\n", "ax.axhline(y=1.0, color='k', linestyle='--', alpha=0.5)\n", "ax.set_xlabel('Day')\n", "ax.set_ylabel('Backing Ratio')\n", "ax.set_title('Backing Ratio (diluted by commitment minting)')\n", "\n", "ax = axes[1, 1]\n", "ax.plot(result.times, result.imbalance, 'purple', linewidth=2)\n", "ax.set_xlabel('Day')\n", "ax.set_ylabel('Imbalance')\n", "ax.set_title('Reserve Imbalance Over Time')\n", "\n", "plt.tight_layout()\n", "plt.show()\n", "\n", "fin = result.financial_minted[-1]\n", "com = result.commitment_minted[-1]\n", "total = fin + com\n", "print(f'Financial minted: {fin:,.2f} ({fin/total*100:.1f}%)')\n", "print(f'Commitment minted: {com:,.2f} ({com/total*100:.1f}%)')\n", "print(f'Final backing ratio: {result.backing_ratio[-1]:.4f}')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Interactive: Custom Deposit/Redeem" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from src.composed.myco_surface import MycoSystem, MycoSystemConfig\n", "\n", "system = MycoSystem(MycoSystemConfig(n_reserve_assets=3))\n", "\n", "# Series of operations\n", "operations = [\n", " ('deposit', np.array([5000.0, 3000.0, 2000.0]), 0),\n", " ('deposit', np.array([1000.0, 1000.0, 1000.0]), 1),\n", " ('deposit', np.array([2000.0, 500.0, 500.0]), 2), # Imbalanced\n", " ('redeem', 500.0, 5),\n", " ('deposit', np.array([1000.0, 1000.0, 1000.0]), 10),\n", " ('redeem', 1000.0, 15),\n", " ('redeem', 2000.0, 16), # Rapid redemptions → flow penalty\n", "]\n", "\n", "log = []\n", "for op, amount, t in operations:\n", " if op == 'deposit':\n", " minted, meta = system.deposit(amount, float(t))\n", " metrics = system.get_metrics()\n", " log.append({\n", " 'time': t, 'op': 'deposit', 'value': float(np.sum(amount)),\n", " 'minted': minted, 'supply': metrics['supply'],\n", " 'reserve': metrics['reserve_value'], 'br': metrics['backing_ratio'],\n", " 'fee': meta.get('fee_rate', 0),\n", " })\n", " else:\n", " amounts_out, meta = system.redeem(amount, float(t))\n", " metrics = system.get_metrics()\n", " log.append({\n", " 'time': t, 'op': 'redeem', 'value': float(np.sum(amounts_out)),\n", " 'burned': amount, 'supply': metrics['supply'],\n", " 'reserve': metrics['reserve_value'], 'br': metrics['backing_ratio'],\n", " 'flow_penalty': meta.get('flow_penalty', 1.0),\n", " })\n", "\n", "# Display log\n", "print(f'{\"Time\":>5} {\"Op\":>8} {\"Value\":>10} {\"Supply\":>12} {\"Reserve\":>12} {\"BR\":>8} {\"Extra\":>15}')\n", "print('-' * 75)\n", "for entry in log:\n", " extra = ''\n", " if entry['op'] == 'deposit':\n", " extra = f'fee={entry[\"fee\"]:.4f}'\n", " else:\n", " extra = f'penalty={entry.get(\"flow_penalty\", 1.0):.4f}'\n", " print(f'{entry[\"time\"]:>5} {entry[\"op\"]:>8} {entry[\"value\"]:>10.2f} {entry[\"supply\"]:>12.2f} {entry[\"reserve\"]:>12.2f} {entry[\"br\"]:>8.4f} {extra:>15}')" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "name": "python", "version": "3.11.0" } }, "nbformat": 4, "nbformat_minor": 4 }