diff --git a/lib/threefold/incatokens/charts.v b/lib/threefold/incatokens/charts.v index 211ac9e6..ddbc2a0c 100644 --- a/lib/threefold/incatokens/charts.v +++ b/lib/threefold/incatokens/charts.v @@ -25,7 +25,7 @@ pub fn (sim Simulation) generate_market_cap_chart() !echarts.EChartsOption { mut mc_sheet := spreadsheet.sheet_new( name: '${sim.name}_market_cap' nrcol: sim.price_sheet.nrcol - curr: sim.currency + curr: sim.params.simulation.currency )! for name, scenario in sim.scenarios { @@ -37,7 +37,7 @@ pub fn (sim Simulation) generate_market_cap_chart() !echarts.EChartsOption { price_row := sim.price_sheet.row_get('scenario_${name}_price')! for i, cell in price_row.cells { - mc_row.cells[i].val = cell.val * sim.total_supply + mc_row.cells[i].val = cell.val * sim.params.distribution.total_supply } } diff --git a/lib/threefold/incatokens/export.v b/lib/threefold/incatokens/export.v index 1eae3a4c..97e6da11 100644 --- a/lib/threefold/incatokens/export.v +++ b/lib/threefold/incatokens/export.v @@ -4,99 +4,6 @@ import freeflowuniverse.herolib.core.pathlib import freeflowuniverse.herolib.ui.console import time -const report_template = '# INCA Token Economic Simulation Report - -## Executive Summary - -This report presents the results of the INCA token economic simulation **{{.name}}**, analyzing various market scenarios and their impact on token distribution, pricing, and investor returns. - -### Key Parameters - -- **Total Token Supply**: {{.total_supply}} INCA -- **Simulation Period**: {{.nrcol}} months -- **Base Currency**: {{.currency}} - -## Token Distribution & Allocation - -{{.distribution_section}} - -## Vesting Schedules - -### Team Vesting -- **Cliff Period**: {{.team_cliff_months}} months -- **Vesting Period**: {{.team_vesting_months}} months -- **Total Team Allocation**: {{.team_allocation}} INCA ({{.team_pct}}%) - -### Treasury Vesting -- **Cliff Period**: {{.treasury_cliff_months}} months -- **Vesting Period**: {{.treasury_vesting_months}} months -- **Total Treasury Allocation**: {{.treasury_allocation}} INCA ({{.treasury_pct}}%) - -## Economic Parameters - -- **Epoch 1 Floor Uplift**: {{.epoch1_floor_uplift}}x -- **Subsequent Epoch Floor Uplift**: {{.epochn_floor_uplift}}x -- **AMM Liquidity Depth Factor**: {{.amm_liquidity_depth_factor}}x - -## Simulation Scenarios - -{{.scenarios_section}} - -## Financial Summary - -{{.financial_summary}} - -## Investment Analysis - -### Return on Investment by Round - -{{.roi_analysis}} - -## Market Dynamics - -### Price Evolution -The token price evolution across different scenarios shows: - -{{.price_analysis}} - -### Market Capitalization -The projected market capitalization ranges show: - -{{.market_cap_analysis}} - -## Risk Analysis - -### Scenario Sensitivity -The simulation reveals the following sensitivities: - -- **Low Demand Scenario**: Conservative market conditions with limited speculation -- **Medium Demand Scenario**: Moderate market interest and trading activity -- **High Demand Scenario**: Strong market demand and active secondary trading - -### Key Risk Factors -1. **Market Demand Volatility**: Significant impact on final token prices -2. **AMM Pool Dynamics**: Trading activity affects liquidity and price stability -3. **Vesting Schedule Impact**: Lock-up periods influence circulating supply - -## Conclusions - -{{.conclusions}} - -## Appendices - -### A. Methodology -This simulation uses a simplified Dutch auction model combined with AMM (Automated Market Maker) dynamics to project token price evolution. - -### B. Assumptions -- All investor rounds are fully subscribed -- Vesting schedules are strictly enforced -- Market dynamics follow the implemented auction and AMM models - ---- - -*Report generated on {{.generation_date}} using INCA Token Simulation Framework* -' - // Export data to CSV pub fn (sim Simulation) export_csv(sheet_name string, path string) ! { mut sheet := match sheet_name { @@ -119,11 +26,11 @@ pub fn (sim Simulation) export_csv(sheet_name string, path string) ! { pub fn (sim Simulation) generate_distribution_section() !string { mut lines := []string{} - lines << '- **Total supply:** ${sim.total_supply} INCA' - lines << '- **Public (TGE):** ${(sim.public_pct * 100).str()}% (No lockup)' - lines << '- **Team:** ${(sim.team_pct * 100).str()}% (${sim.team_vesting.cliff_months}mo cliff, ${sim.team_vesting.vesting_months}mo vest)' - lines << '- **Treasury:** ${(sim.treasury_pct * 100).str()}% (${sim.treasury_vesting.cliff_months}mo cliff, ${sim.treasury_vesting.vesting_months}mo vest)' - lines << '- **Investors:** ${(sim.investor_pct * 100).str()}%' + lines << '- **Total supply:** ${sim.params.distribution.total_supply} INCA' + lines << '- **Public (TGE):** ${(sim.params.distribution.public_pct * 100).str()}% (No lockup)' + lines << '- **Team:** ${(sim.params.distribution.team_pct * 100).str()}% (${sim.team_vesting.cliff_months}mo cliff, ${sim.team_vesting.vesting_months}mo vest)' + lines << '- **Treasury:** ${(sim.params.distribution.treasury_pct * 100).str()}% (${sim.treasury_vesting.cliff_months}mo cliff, ${sim.treasury_vesting.vesting_months}mo vest)' + lines << '- **Investors:** ${(sim.params.distribution.investor_pct * 100).str()}%' lines << '' lines << '### Investor Rounds & Vesting' lines << '| Round | Allocation | Price (USD) | Vesting Schedule |' @@ -167,7 +74,7 @@ pub fn (sim Simulation) generate_financial_summary() !string { mut total_raised := 0.0 for round in sim.investor_rounds { - raised := round.allocation_pct * sim.total_supply * round.price + raised := round.allocation_pct * sim.params.distribution.total_supply * round.price total_raised += raised lines << '| **${round.name}** | \$${raised} |' } diff --git a/lib/threefold/incatokens/factory.v b/lib/threefold/incatokens/factory.v index f67dbd7a..5933e773 100644 --- a/lib/threefold/incatokens/factory.v +++ b/lib/threefold/incatokens/factory.v @@ -7,71 +7,32 @@ __global ( simulations map[string]&Simulation ) -// Create simulation from parameters struct -pub fn simulation_new_from_params(params SimulationParams) !&Simulation { - return simulation_new( - name: params.name - total_supply: params.distribution.total_supply - public_pct: params.distribution.public_pct - team_pct: params.distribution.team_pct - treasury_pct: params.distribution.treasury_pct - investor_pct: params.distribution.investor_pct - nrcol: params.simulation.nrcol - currency: params.simulation.currency - )! -} - -@[params] -pub struct SimulationNewArgs { -pub mut: - // name of the simulation, used for identification and file naming - name string = 'default' - // total supply of INCA tokens - total_supply f64 = 10_000_000_000 - // percentage of tokens allocated to public sale (TGE) - public_pct f64 = 0.50 - // percentage of tokens allocated to the team - team_pct f64 = 0.15 - // percentage of tokens allocated to the treasury - treasury_pct f64 = 0.15 - // percentage of tokens allocated to investors - investor_pct f64 = 0.20 - // number of columns (months) for the simulation spreadsheets - nrcol int = 60 // 60 months default - // currency used in the simulation (e.g., 'USD') - currency string = 'USD' -} - -pub fn simulation_new(args SimulationNewArgs) !&Simulation { - name := texttools.name_fix(args.name) +// Create simulation from parameters struct - MAIN ENTRY POINT +pub fn simulation_new(params SimulationParams) !&Simulation { + name := texttools.name_fix(params.name) // Initialize spreadsheets for tracking price_sheet := spreadsheet.sheet_new( name: '${name}_prices' - nrcol: args.nrcol - curr: args.currency + nrcol: params.simulation.nrcol + curr: params.simulation.currency )! token_sheet := spreadsheet.sheet_new( name: '${name}_tokens' - nrcol: args.nrcol - curr: args.currency + nrcol: params.simulation.nrcol + curr: params.simulation.currency )! investment_sheet := spreadsheet.sheet_new( name: '${name}_investments' - nrcol: args.nrcol - curr: args.currency + nrcol: params.simulation.nrcol + curr: params.simulation.currency )! mut sim := &Simulation{ name: name - total_supply: args.total_supply - public_pct: args.public_pct - team_pct: args.team_pct - treasury_pct: args.treasury_pct - investor_pct: args.investor_pct - currency: args.currency + params: params price_sheet: price_sheet token_sheet: token_sheet investment_sheet: investment_sheet diff --git a/lib/threefold/incatokens/incatokens_test.v b/lib/threefold/incatokens/incatokens_test.v index 5a3f0d27..2a9c0f6d 100644 --- a/lib/threefold/incatokens/incatokens_test.v +++ b/lib/threefold/incatokens/incatokens_test.v @@ -1,16 +1,18 @@ module incatokens import freeflowuniverse.herolib.biz.spreadsheet import os +import incatokens.defaults +import incatokens.factory fn test_simulation_creation() { mut params := default_params() params.name = 'test_sim_creation' - mut sim := simulation_new_from_params(params)! - sim.run_full_simulation(params)! // Initialize investor_rounds and vesting schedules + mut sim := factory.simulation_new(params)! + sim.run_simulation()! // Run the simulation assert sim.name == 'test_sim_creation' - assert sim.total_supply == params.distribution.total_supply + assert sim.params.distribution.total_supply == params.distribution.total_supply assert sim.investor_rounds.len == params.investor_rounds.len } @@ -18,8 +20,8 @@ fn test_scenario_execution() { mut params := default_params() params.name = 'test_scenario_exec' - mut sim := simulation_new_from_params(params)! - sim.run_full_simulation(params)! + mut sim := factory.simulation_new(params)! + sim.run_simulation()! // Get the 'Low' scenario results low_scenario := sim.scenarios['Low']! @@ -39,8 +41,8 @@ fn test_vesting_schedules() { mut params := default_params() params.name = 'test_vesting_schedules' - mut sim := simulation_new_from_params(params)! - sim.run_full_simulation(params)! + mut sim := factory.simulation_new(params)! + sim.run_simulation()! // Check team vesting team_row := sim.vesting_sheet.row_get('team_vesting')! @@ -52,7 +54,7 @@ fn test_vesting_schedules() { assert team_row.cells[12].val > 0 // After full vesting (month 48), should have all tokens - total_team_tokens := sim.total_supply * sim.team_pct + total_team_tokens := sim.params.distribution.total_supply * sim.params.distribution.team_pct assert team_row.cells[48].val == total_team_tokens } @@ -63,19 +65,23 @@ fn test_export_functionality() { params.output.generate_csv = true params.output.generate_report = true - mut sim := simulation_new_from_params(params)! - sim.run_full_simulation(params)! + mut sim := factory.simulation_new(params)! + sim.run_simulation()! // Ensure price sheet has data before export assert sim.price_sheet.rows.len > 0 - // Test CSV export (handled by run_full_simulation if generate_csv is true) + // Export all data + os.mkdir_all(params.output.export_dir)! + sim.export_all(params.output.export_dir)! + + // Test CSV export assert os.exists('${params.output.export_dir}/${params.name}_prices.csv') assert os.exists('${params.output.export_dir}/${params.name}_tokens.csv') assert os.exists('${params.output.export_dir}/${params.name}_investments.csv') assert os.exists('${params.output.export_dir}/${params.name}_vesting.csv') - // Test report generation (already handled by run_full_simulation if generate_report is true) + // Test report generation assert os.exists('${params.output.export_dir}/${params.name}_report.md') } diff --git a/lib/threefold/incatokens/params.v b/lib/threefold/incatokens/params.v index b5fb19be..52ebd4ae 100644 --- a/lib/threefold/incatokens/params.v +++ b/lib/threefold/incatokens/params.v @@ -1,6 +1,20 @@ module incatokens import os + +// SimulationParams is the main configuration struct containing all parameters +pub struct SimulationParams { +pub mut: + name string + distribution TokenDistribution + investor_rounds []InvestorRoundConfig + vesting VestingConfigs + economics EconomicsConfig + simulation SimulationConfig + scenarios []ScenarioConfig + output OutputConfig +} + // TokenDistribution defines how tokens are allocated across different categories pub struct TokenDistribution { pub mut: @@ -14,8 +28,8 @@ pub mut: // VestingConfig defines cliff and vesting periods pub struct VestingConfig { pub mut: - cliff_months int - vesting_months int + cliff_months int = 6 + vesting_months int = 24 } // InvestorRoundConfig defines parameters for each investment round @@ -60,82 +74,9 @@ pub mut: // OutputConfig defines where and how to generate outputs pub struct OutputConfig { pub mut: - export_dir string = './output' - generate_csv bool = true - generate_charts bool = true - generate_report bool = true + export_dir string = './output' + generate_csv bool = true + generate_charts bool = true + generate_report bool = true } -// SimulationParams is the main configuration struct containing all parameters -pub struct SimulationParams { -pub mut: - name string - distribution TokenDistribution - investor_rounds []InvestorRoundConfig - vesting VestingConfigs - economics EconomicsConfig - simulation SimulationConfig - scenarios []ScenarioConfig - output OutputConfig -} - -// run_simulation executes the simulation with the given parameters -pub fn (params SimulationParams) run_simulation() ! { - mut sim := simulation_new( - name: params.name - total_supply: params.distribution.total_supply - public_pct: params.distribution.public_pct - team_pct: params.distribution.team_pct - treasury_pct: params.distribution.treasury_pct - investor_pct: params.distribution.investor_pct - nrcol: params.simulation.nrcol - currency: params.simulation.currency - )! - - // Configure economics - sim.epoch1_floor_uplift = params.economics.epoch1_floor_uplift - sim.epochn_floor_uplift = params.economics.epochn_floor_uplift - sim.amm_liquidity_depth_factor = params.economics.amm_liquidity_depth_factor - - // Set up investor rounds - sim.investor_rounds = params.investor_rounds.map(InvestorRound{ - name: it.name - allocation_pct: it.allocation_pct - price: it.price - vesting: VestingSchedule{ - cliff_months: it.vesting.cliff_months - vesting_months: it.vesting.vesting_months - } - }) - - // Set up vesting schedules - sim.team_vesting = VestingSchedule{ - cliff_months: params.vesting.team.cliff_months - vesting_months: params.vesting.team.vesting_months - } - sim.treasury_vesting = VestingSchedule{ - cliff_months: params.vesting.treasury.cliff_months - vesting_months: params.vesting.treasury.vesting_months - } - - // Run scenarios - for scenario in params.scenarios { - sim.run_scenario(scenario.name, scenario.demands, scenario.amm_trades)! - } - - // Generate vesting schedules - sim.create_vesting_schedules()! - - // Generate outputs - if params.output.generate_csv { - os.mkdir_all(params.output.export_dir)! - sim.export_csv('prices', '${params.output.export_dir}/${params.name}_prices.csv')! - sim.export_csv('tokens', '${params.output.export_dir}/${params.name}_tokens.csv')! - sim.export_csv('investments', '${params.output.export_dir}/${params.name}_investments.csv')! - sim.export_csv('vesting', '${params.output.export_dir}/${params.name}_vesting.csv')! - } - - if params.output.generate_report { - sim.generate_report(params.output.export_dir)! - } -} \ No newline at end of file diff --git a/lib/threefold/incatokens/play.v b/lib/threefold/incatokens/play.v index 0cbb95d8..1a904e1f 100644 --- a/lib/threefold/incatokens/play.v +++ b/lib/threefold/incatokens/play.v @@ -8,6 +8,18 @@ import os pub fn play(mut plbook PlayBook) ! { console.print_header('INCA Token Simulation') + // Collect all configurations first + mut simulations_to_run := []SimulationParams{} + mut export_path := '' + + // Process export configuration + if plbook.exists_once(filter: 'incatokens.export') { + mut action := plbook.get(filter: 'incatokens.export')! + mut p := action.params + export_path = p.get('path')! + console.print_item('Export directory configured: ${export_path}') + } + // Process simulation definitions for action in plbook.find(filter: 'incatokens.simulate')! { mut p := action.params @@ -39,47 +51,67 @@ pub fn play(mut plbook PlayBook) ! { params.vesting.treasury.cliff_months = p.get_int_default('treasury_cliff_months', 12)! params.vesting.treasury.vesting_months = p.get_int_default('treasury_vesting_months', 48)! - // Configure output - params.output.export_dir = p.get_default('export_dir', './output')! + // Configure output - use export_path if provided, otherwise use param + if export_path != '' { + params.output.export_dir = export_path + } else { + params.output.export_dir = p.get_default('export_dir', './output')! + } params.output.generate_csv = p.get_default_true('generate_csv') params.output.generate_charts = p.get_default_true('generate_charts') params.output.generate_report = p.get_default_true('generate_report') + // Collect investor rounds for this simulation + mut investor_rounds := []InvestorRoundConfig{} + for round_action in plbook.find(filter: 'incatokens.investor_round')! { + mut rp := round_action.params + + round := InvestorRoundConfig{ + name: rp.get('name')! + allocation_pct: rp.get_float('allocation_pct')! + price: rp.get_float('price')! + vesting: VestingConfig{ + cliff_months: rp.get_int('cliff_months')! + vesting_months: rp.get_int('vesting_months')! + } + } + investor_rounds << round + console.print_item('Configured investor round: ${round.name} at \$${round.price}') + } + params.investor_rounds = investor_rounds + + // Collect scenarios for this simulation + mut scenarios := []ScenarioConfig{} + for scenario_action in plbook.find(filter: 'incatokens.scenario')! { + mut sp := scenario_action.params + + scenario := ScenarioConfig{ + name: sp.get('name')! + demands: sp.get_list_f64('demands')! + amm_trades: sp.get_list_f64('amm_trades')! + } + scenarios << scenario + console.print_item('Configured scenario: ${scenario.name}') + } + params.scenarios = scenarios + + simulations_to_run << params + } + + // Run all simulations + for params in simulations_to_run { console.print_item('Running simulation: ${params.name}') - // Run the simulation - params.run_simulation()! + // Create and run simulation + mut sim := simulation_new(params)! + sim.run_simulation()! - console.print_green('✓ Simulation completed successfully') - } - - // Process investor round definitions - for action in plbook.find(filter: 'incatokens.investor_round')! { - mut p := action.params + // Create export directory if needed + os.mkdir_all(params.output.export_dir)! - round := InvestorRoundConfig{ - name: p.get('name')! - allocation_pct: p.get_float('allocation_pct')! - price: p.get_float('price')! - vesting: VestingConfig{ - cliff_months: p.get_int('cliff_months')! - vesting_months: p.get_int('vesting_months')! - } - } + // Export all data in one call + sim.export_all(params.output.export_dir)! - console.print_item('Configured investor round: ${round.name} at \$${round.price}') - } - - // Process scenario definitions - for action in plbook.find(filter: 'incatokens.scenario')! { - mut p := action.params - - scenario := ScenarioConfig{ - name: p.get('name')! - demands: p.get_list_f64('demands')! - amm_trades: p.get_list_f64('amm_trades')! - } - - console.print_item('Configured scenario: ${scenario.name}') + console.print_green('✓ Simulation "${params.name}" completed and exported to: ${params.output.export_dir}') } } \ No newline at end of file diff --git a/lib/threefold/incatokens/readme.md b/lib/threefold/incatokens/readme.md new file mode 100644 index 00000000..7a601efe --- /dev/null +++ b/lib/threefold/incatokens/readme.md @@ -0,0 +1,2 @@ + +see examples/threefold/incatokens/incatokens_simulate.vsh for example of how to use \ No newline at end of file diff --git a/lib/threefold/incatokens/simulation.v b/lib/threefold/incatokens/simulation.v index b1872f4e..b43e42e1 100644 --- a/lib/threefold/incatokens/simulation.v +++ b/lib/threefold/incatokens/simulation.v @@ -1,17 +1,35 @@ module incatokens -// import freeflowuniverse.herolib.biz.spreadsheet +import freeflowuniverse.herolib.biz.spreadsheet +// Simulation holds the main simulation state +pub struct Simulation { +pub mut: + // Core identification + name string -// Generate comprehensive report with all scenarios -pub fn (mut sim Simulation) simulate(params SimulationParams) ! { - // Configure from parameters - sim.epoch1_floor_uplift = params.economics.epoch1_floor_uplift - sim.epochn_floor_uplift = params.economics.epochn_floor_uplift - sim.amm_liquidity_depth_factor = params.economics.amm_liquidity_depth_factor + // Configuration (embedded) + params SimulationParams + + // Derived data + investor_rounds []InvestorRound + team_vesting VestingSchedule + treasury_vesting VestingSchedule + + // Runtime state + scenarios map[string]&Scenario + + // Spreadsheets for tracking + price_sheet &spreadsheet.Sheet + token_sheet &spreadsheet.Sheet + investment_sheet &spreadsheet.Sheet + vesting_sheet &spreadsheet.Sheet +} - // Set up investor rounds - sim.investor_rounds = params.investor_rounds.map(InvestorRound{ +// Main simulation runner - single entry point +pub fn (mut sim Simulation) run_simulation() ! { + // Set up investor rounds from params + sim.investor_rounds = sim.params.investor_rounds.map(InvestorRound{ name: it.name allocation_pct: it.allocation_pct price: it.price @@ -21,18 +39,18 @@ pub fn (mut sim Simulation) simulate(params SimulationParams) ! { } }) - // Set up vesting schedules + // Set up vesting schedules from params sim.team_vesting = VestingSchedule{ - cliff_months: params.vesting.team.cliff_months - vesting_months: params.vesting.team.vesting_months + cliff_months: sim.params.vesting.team.cliff_months + vesting_months: sim.params.vesting.team.vesting_months } sim.treasury_vesting = VestingSchedule{ - cliff_months: params.vesting.treasury.cliff_months - vesting_months: params.vesting.treasury.vesting_months + cliff_months: sim.params.vesting.treasury.cliff_months + vesting_months: sim.params.vesting.treasury.vesting_months } - // Run all scenarios - for scenario_config in params.scenarios { + // Run all scenarios from params + for scenario_config in sim.params.scenarios { sim.run_scenario(scenario_config.name, scenario_config.demands, scenario_config.amm_trades)! } @@ -70,7 +88,7 @@ pub fn (mut sim Simulation) run_scenario(name string, demands []f64, amm_trades )! // Calculate public tokens per epoch - total_public := sim.total_supply * sim.public_pct + total_public := sim.params.distribution.total_supply * sim.params.distribution.public_pct tokens_per_epoch := total_public / 3.0 mut last_auction_price := sim.get_last_investor_price() @@ -110,7 +128,7 @@ pub fn (mut sim Simulation) run_scenario(name string, demands []f64, amm_trades spillover = 0 // Seed AMM pool - amm_usdc_to_add := sim.amm_liquidity_depth_factor * epoch.treasury_raised + amm_usdc_to_add := sim.params.economics.amm_liquidity_depth_factor * epoch.treasury_raised amm_pool.add_liquidity(amm_tokens, amm_usdc_to_add) // Simulate trading @@ -149,7 +167,7 @@ fn (sim Simulation) calculate_metrics(scenario &Scenario, treasury_total f64) !S treasury_total: treasury_total final_price: final_price investor_roi: investor_roi - market_cap_final: final_price * sim.total_supply + market_cap_final: final_price * sim.params.distribution.total_supply circulating_supply_final: sim.calculate_circulating_supply(12) // at month 12 } } @@ -168,19 +186,33 @@ fn (sim Simulation) calculate_floor_price(epoch_idx int, last_auction_price f64) last_investor_price := sim.get_last_investor_price() if epoch_idx == 0 { - return last_investor_price * sim.epoch1_floor_uplift + return last_investor_price * sim.params.economics.epoch1_floor_uplift } - return last_auction_price * sim.epochn_floor_uplift + return last_auction_price * sim.params.economics.epochn_floor_uplift } fn (sim Simulation) calculate_circulating_supply(month int) f64 { // Base circulation (non-public allocations) - investor_tokens := sim.investor_pct * sim.total_supply - team_tokens := sim.team_pct * sim.total_supply - treasury_tokens := sim.treasury_pct * sim.total_supply + investor_tokens := sim.params.distribution.investor_pct * sim.params.distribution.total_supply + team_tokens := sim.params.distribution.team_pct * sim.params.distribution.total_supply + treasury_tokens := sim.params.distribution.treasury_pct * sim.params.distribution.total_supply // For simplicity, assume all public tokens are circulating after TGE - public_tokens := sim.public_pct * sim.total_supply + public_tokens := sim.params.distribution.public_pct * sim.params.distribution.total_supply return investor_tokens + team_tokens + treasury_tokens + public_tokens +} + +// Export all simulation data +pub fn (sim Simulation) export_all(export_dir string) ! { + if sim.params.output.generate_csv { + sim.export_csv('prices', '${export_dir}/${sim.name}_prices.csv')! + sim.export_csv('tokens', '${export_dir}/${sim.name}_tokens.csv')! + sim.export_csv('investments', '${export_dir}/${sim.name}_investments.csv')! + sim.export_csv('vesting', '${export_dir}/${sim.name}_vesting.csv')! + } + + if sim.params.output.generate_report { + sim.generate_report(export_dir)! + } } \ No newline at end of file diff --git a/lib/threefold/incatokens/simulation_model.v b/lib/threefold/incatokens/simulation_model.v deleted file mode 100644 index c4a16795..00000000 --- a/lib/threefold/incatokens/simulation_model.v +++ /dev/null @@ -1,76 +0,0 @@ -module incatokens - -import freeflowuniverse.herolib.biz.spreadsheet - -pub struct VestingSchedule { -pub mut: - cliff_months int - vesting_months int -} - -pub struct InvestorRound { -pub mut: - name string - allocation_pct f64 - price f64 - vesting VestingSchedule -} - -pub enum EpochType { - auction_only - hybrid - amm_only -} - -pub struct Epoch { -pub mut: - index int - type_ EpochType - start_month int - end_month int - auction_share f64 - amm_share f64 - tokens_allocated f64 - tokens_spillover f64 - auction_demand f64 - amm_net_trade f64 - final_price f64 - treasury_raised f64 -} - -pub struct Scenario { -pub mut: - name string - demands []f64 - amm_trades []f64 - epochs []Epoch - final_metrics ScenarioMetrics -} - -pub struct ScenarioMetrics { -pub mut: - treasury_total f64 - final_price f64 - investor_roi map[string]f64 - market_cap_final f64 - circulating_supply_final f64 -} - -@[heap] -pub struct Simulation { -pub: - params SimulationParams //all config info comes here -pub mut: - name string - - //THE DATA WE ACTIVELY NEED TO SIMULATE IS HERE - - // Tracking sheets - price_sheet &spreadsheet.Sheet - token_sheet &spreadsheet.Sheet - investment_sheet &spreadsheet.Sheet - vesting_sheet &spreadsheet.Sheet - - // Scenarios - scenarios map[string]&Scenario -} \ No newline at end of file diff --git a/lib/threefold/incatokens/templates/example.hero b/lib/threefold/incatokens/templates/example.hero new file mode 100644 index 00000000..2e24866f --- /dev/null +++ b/lib/threefold/incatokens/templates/example.hero @@ -0,0 +1,58 @@ +!!incatokens.simulate + name: 'inca_mainnet_simulation' + total_supply: 10000000000 + public_pct: 0.50 + team_pct: 0.15 + treasury_pct: 0.15 + investor_pct: 0.20 + nrcol: 60 + currency: 'USD' + epoch1_floor_uplift: 1.20 + epochn_floor_uplift: 1.20 + amm_liquidity_depth_factor: 2.0 + team_cliff_months: 12 + team_vesting_months: 36 + treasury_cliff_months: 12 + treasury_vesting_months: 48 + export_dir: './simulation_output' + generate_csv: true + generate_charts: true + generate_report: true + +!!incatokens.scenario + name: 'Conservative' + demands: [8000000, 8000000, 0] + amm_trades: [0, 0, 0] + +!!incatokens.scenario + name: 'Moderate' + demands: [25000000, 50000000, 0] + amm_trades: [0, 0, 0] + +!!incatokens.scenario + name: 'Optimistic' + demands: [50000000, 100000000, 0] + amm_trades: [5000000, 10000000, 0] + +!!incatokens.investor_round + name: 'Seed' + allocation_pct: 0.03 + price: 0.003 + cliff_months: 6 + vesting_months: 24 + +!!incatokens.investor_round + name: 'Series_A' + allocation_pct: 0.07 + price: 0.008 + cliff_months: 6 + vesting_months: 24 + +!!incatokens.investor_round + name: 'Series_B' + allocation_pct: 0.10 + price: 0.012 + cliff_months: 3 + vesting_months: 18 + +!!incatokens.export path:"/tmp/incatokens_export" \ No newline at end of file diff --git a/lib/threefold/incatokens/types.v b/lib/threefold/incatokens/types.v new file mode 100644 index 00000000..2114106c --- /dev/null +++ b/lib/threefold/incatokens/types.v @@ -0,0 +1,63 @@ +module incatokens + +import freeflowuniverse.herolib.biz.spreadsheet + +// VestingSchedule defines cliff and vesting periods +pub struct VestingSchedule { +pub mut: + cliff_months int + vesting_months int +} + +// InvestorRound represents an investment round +pub struct InvestorRound { +pub mut: + name string + allocation_pct f64 + price f64 + vesting VestingSchedule +} + +// Epoch represents a phase in the token release schedule +pub struct Epoch { +pub mut: + index int + type_ EpochType + start_month int + end_month int + auction_share f64 + amm_share f64 + tokens_allocated f64 + auction_demand f64 + amm_net_trade f64 + treasury_raised f64 + final_price f64 + tokens_spillover f64 +} + +pub enum EpochType { + auction_only + hybrid + amm_only +} + +// ScenarioMetrics holds the final results of a scenario +pub struct ScenarioMetrics { +pub mut: + treasury_total f64 + final_price f64 + investor_roi map[string]f64 + market_cap_final f64 + circulating_supply_final f64 +} + +// Scenario represents a market scenario +pub struct Scenario { +pub mut: + name string + demands []f64 + amm_trades []f64 + epochs []Epoch + final_metrics ScenarioMetrics +} +