This commit is contained in:
2025-08-27 09:57:06 +02:00
parent cbc6a9df2d
commit 791988c420
11 changed files with 301 additions and 375 deletions

View File

@@ -25,7 +25,7 @@ pub fn (sim Simulation) generate_market_cap_chart() !echarts.EChartsOption {
mut mc_sheet := spreadsheet.sheet_new( mut mc_sheet := spreadsheet.sheet_new(
name: '${sim.name}_market_cap' name: '${sim.name}_market_cap'
nrcol: sim.price_sheet.nrcol nrcol: sim.price_sheet.nrcol
curr: sim.currency curr: sim.params.simulation.currency
)! )!
for name, scenario in sim.scenarios { 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')! price_row := sim.price_sheet.row_get('scenario_${name}_price')!
for i, cell in price_row.cells { 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
} }
} }

View File

@@ -4,99 +4,6 @@ import freeflowuniverse.herolib.core.pathlib
import freeflowuniverse.herolib.ui.console import freeflowuniverse.herolib.ui.console
import time 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 // Export data to CSV
pub fn (sim Simulation) export_csv(sheet_name string, path string) ! { pub fn (sim Simulation) export_csv(sheet_name string, path string) ! {
mut sheet := match sheet_name { 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 { pub fn (sim Simulation) generate_distribution_section() !string {
mut lines := []string{} mut lines := []string{}
lines << '- **Total supply:** ${sim.total_supply} INCA' lines << '- **Total supply:** ${sim.params.distribution.total_supply} INCA'
lines << '- **Public (TGE):** ${(sim.public_pct * 100).str()}% (No lockup)' lines << '- **Public (TGE):** ${(sim.params.distribution.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 << '- **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.treasury_pct * 100).str()}% (${sim.treasury_vesting.cliff_months}mo cliff, ${sim.treasury_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.investor_pct * 100).str()}%' lines << '- **Investors:** ${(sim.params.distribution.investor_pct * 100).str()}%'
lines << '' lines << ''
lines << '### Investor Rounds & Vesting' lines << '### Investor Rounds & Vesting'
lines << '| Round | Allocation | Price (USD) | Vesting Schedule |' lines << '| Round | Allocation | Price (USD) | Vesting Schedule |'
@@ -167,7 +74,7 @@ pub fn (sim Simulation) generate_financial_summary() !string {
mut total_raised := 0.0 mut total_raised := 0.0
for round in sim.investor_rounds { 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 total_raised += raised
lines << '| **${round.name}** | \$${raised} |' lines << '| **${round.name}** | \$${raised} |'
} }

View File

@@ -7,71 +7,32 @@ __global (
simulations map[string]&Simulation simulations map[string]&Simulation
) )
// Create simulation from parameters struct // Create simulation from parameters struct - MAIN ENTRY POINT
pub fn simulation_new_from_params(params SimulationParams) !&Simulation { pub fn simulation_new(params SimulationParams) !&Simulation {
return simulation_new( name := texttools.name_fix(params.name)
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)
// Initialize spreadsheets for tracking // Initialize spreadsheets for tracking
price_sheet := spreadsheet.sheet_new( price_sheet := spreadsheet.sheet_new(
name: '${name}_prices' name: '${name}_prices'
nrcol: args.nrcol nrcol: params.simulation.nrcol
curr: args.currency curr: params.simulation.currency
)! )!
token_sheet := spreadsheet.sheet_new( token_sheet := spreadsheet.sheet_new(
name: '${name}_tokens' name: '${name}_tokens'
nrcol: args.nrcol nrcol: params.simulation.nrcol
curr: args.currency curr: params.simulation.currency
)! )!
investment_sheet := spreadsheet.sheet_new( investment_sheet := spreadsheet.sheet_new(
name: '${name}_investments' name: '${name}_investments'
nrcol: args.nrcol nrcol: params.simulation.nrcol
curr: args.currency curr: params.simulation.currency
)! )!
mut sim := &Simulation{ mut sim := &Simulation{
name: name name: name
total_supply: args.total_supply params: params
public_pct: args.public_pct
team_pct: args.team_pct
treasury_pct: args.treasury_pct
investor_pct: args.investor_pct
currency: args.currency
price_sheet: price_sheet price_sheet: price_sheet
token_sheet: token_sheet token_sheet: token_sheet
investment_sheet: investment_sheet investment_sheet: investment_sheet

View File

@@ -1,16 +1,18 @@
module incatokens module incatokens
import freeflowuniverse.herolib.biz.spreadsheet import freeflowuniverse.herolib.biz.spreadsheet
import os import os
import incatokens.defaults
import incatokens.factory
fn test_simulation_creation() { fn test_simulation_creation() {
mut params := default_params() mut params := default_params()
params.name = 'test_sim_creation' params.name = 'test_sim_creation'
mut sim := simulation_new_from_params(params)! mut sim := factory.simulation_new(params)!
sim.run_full_simulation(params)! // Initialize investor_rounds and vesting schedules sim.run_simulation()! // Run the simulation
assert sim.name == 'test_sim_creation' 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 assert sim.investor_rounds.len == params.investor_rounds.len
} }
@@ -18,8 +20,8 @@ fn test_scenario_execution() {
mut params := default_params() mut params := default_params()
params.name = 'test_scenario_exec' params.name = 'test_scenario_exec'
mut sim := simulation_new_from_params(params)! mut sim := factory.simulation_new(params)!
sim.run_full_simulation(params)! sim.run_simulation()!
// Get the 'Low' scenario results // Get the 'Low' scenario results
low_scenario := sim.scenarios['Low']! low_scenario := sim.scenarios['Low']!
@@ -39,8 +41,8 @@ fn test_vesting_schedules() {
mut params := default_params() mut params := default_params()
params.name = 'test_vesting_schedules' params.name = 'test_vesting_schedules'
mut sim := simulation_new_from_params(params)! mut sim := factory.simulation_new(params)!
sim.run_full_simulation(params)! sim.run_simulation()!
// Check team vesting // Check team vesting
team_row := sim.vesting_sheet.row_get('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 assert team_row.cells[12].val > 0
// After full vesting (month 48), should have all tokens // 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 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_csv = true
params.output.generate_report = true params.output.generate_report = true
mut sim := simulation_new_from_params(params)! mut sim := factory.simulation_new(params)!
sim.run_full_simulation(params)! sim.run_simulation()!
// Ensure price sheet has data before export // Ensure price sheet has data before export
assert sim.price_sheet.rows.len > 0 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}_prices.csv')
assert os.exists('${params.output.export_dir}/${params.name}_tokens.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}_investments.csv')
assert os.exists('${params.output.export_dir}/${params.name}_vesting.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') assert os.exists('${params.output.export_dir}/${params.name}_report.md')
} }

View File

@@ -1,6 +1,20 @@
module incatokens module incatokens
import os 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 // TokenDistribution defines how tokens are allocated across different categories
pub struct TokenDistribution { pub struct TokenDistribution {
pub mut: pub mut:
@@ -14,8 +28,8 @@ pub mut:
// VestingConfig defines cliff and vesting periods // VestingConfig defines cliff and vesting periods
pub struct VestingConfig { pub struct VestingConfig {
pub mut: pub mut:
cliff_months int cliff_months int = 6
vesting_months int vesting_months int = 24
} }
// InvestorRoundConfig defines parameters for each investment round // InvestorRoundConfig defines parameters for each investment round
@@ -60,82 +74,9 @@ pub mut:
// OutputConfig defines where and how to generate outputs // OutputConfig defines where and how to generate outputs
pub struct OutputConfig { pub struct OutputConfig {
pub mut: pub mut:
export_dir string = './output' export_dir string = './output'
generate_csv bool = true generate_csv bool = true
generate_charts bool = true generate_charts bool = true
generate_report 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)!
}
}

View File

@@ -8,6 +8,18 @@ import os
pub fn play(mut plbook PlayBook) ! { pub fn play(mut plbook PlayBook) ! {
console.print_header('INCA Token Simulation') 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 // Process simulation definitions
for action in plbook.find(filter: 'incatokens.simulate')! { for action in plbook.find(filter: 'incatokens.simulate')! {
mut p := action.params 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.cliff_months = p.get_int_default('treasury_cliff_months', 12)!
params.vesting.treasury.vesting_months = p.get_int_default('treasury_vesting_months', 48)! params.vesting.treasury.vesting_months = p.get_int_default('treasury_vesting_months', 48)!
// Configure output // Configure output - use export_path if provided, otherwise use param
params.output.export_dir = p.get_default('export_dir', './output')! 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_csv = p.get_default_true('generate_csv')
params.output.generate_charts = p.get_default_true('generate_charts') params.output.generate_charts = p.get_default_true('generate_charts')
params.output.generate_report = p.get_default_true('generate_report') 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}') console.print_item('Running simulation: ${params.name}')
// Run the simulation // Create and run simulation
params.run_simulation()! mut sim := simulation_new(params)!
sim.run_simulation()!
console.print_green(' Simulation completed successfully') // Create export directory if needed
} os.mkdir_all(params.output.export_dir)!
// Process investor round definitions // Export all data in one call
for action in plbook.find(filter: 'incatokens.investor_round')! { sim.export_all(params.output.export_dir)!
mut p := action.params
round := InvestorRoundConfig{ console.print_green(' Simulation "${params.name}" completed and exported to: ${params.output.export_dir}')
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')!
}
}
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}')
} }
} }

View File

@@ -0,0 +1,2 @@
see examples/threefold/incatokens/incatokens_simulate.vsh for example of how to use

View File

@@ -1,17 +1,35 @@
module incatokens 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 // Configuration (embedded)
pub fn (mut sim Simulation) simulate(params SimulationParams) ! { 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
// Set up investor rounds // Derived data
sim.investor_rounds = params.investor_rounds.map(InvestorRound{ 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
}
// 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 name: it.name
allocation_pct: it.allocation_pct allocation_pct: it.allocation_pct
price: it.price 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{ sim.team_vesting = VestingSchedule{
cliff_months: params.vesting.team.cliff_months cliff_months: sim.params.vesting.team.cliff_months
vesting_months: params.vesting.team.vesting_months vesting_months: sim.params.vesting.team.vesting_months
} }
sim.treasury_vesting = VestingSchedule{ sim.treasury_vesting = VestingSchedule{
cliff_months: params.vesting.treasury.cliff_months cliff_months: sim.params.vesting.treasury.cliff_months
vesting_months: params.vesting.treasury.vesting_months vesting_months: sim.params.vesting.treasury.vesting_months
} }
// Run all scenarios // Run all scenarios from params
for scenario_config in params.scenarios { for scenario_config in sim.params.scenarios {
sim.run_scenario(scenario_config.name, scenario_config.demands, scenario_config.amm_trades)! 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 // 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 tokens_per_epoch := total_public / 3.0
mut last_auction_price := sim.get_last_investor_price() 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 spillover = 0
// Seed AMM pool // 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) amm_pool.add_liquidity(amm_tokens, amm_usdc_to_add)
// Simulate trading // Simulate trading
@@ -149,7 +167,7 @@ fn (sim Simulation) calculate_metrics(scenario &Scenario, treasury_total f64) !S
treasury_total: treasury_total treasury_total: treasury_total
final_price: final_price final_price: final_price
investor_roi: investor_roi 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 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() last_investor_price := sim.get_last_investor_price()
if epoch_idx == 0 { 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 { fn (sim Simulation) calculate_circulating_supply(month int) f64 {
// Base circulation (non-public allocations) // Base circulation (non-public allocations)
investor_tokens := sim.investor_pct * sim.total_supply investor_tokens := sim.params.distribution.investor_pct * sim.params.distribution.total_supply
team_tokens := sim.team_pct * sim.total_supply team_tokens := sim.params.distribution.team_pct * sim.params.distribution.total_supply
treasury_tokens := sim.treasury_pct * sim.total_supply treasury_tokens := sim.params.distribution.treasury_pct * sim.params.distribution.total_supply
// For simplicity, assume all public tokens are circulating after TGE // 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 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)!
}
}

View File

@@ -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
}

View File

@@ -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"

View File

@@ -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
}