...
This commit is contained in:
@@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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} |'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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)!
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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
|
|
||||||
for action in plbook.find(filter: 'incatokens.investor_round')! {
|
|
||||||
mut p := action.params
|
|
||||||
|
|
||||||
round := InvestorRoundConfig{
|
// Export all data in one call
|
||||||
name: p.get('name')!
|
sim.export_all(params.output.export_dir)!
|
||||||
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}')
|
console.print_green('✓ Simulation "${params.name}" completed and exported to: ${params.output.export_dir}')
|
||||||
}
|
|
||||||
|
|
||||||
// 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}')
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
2
lib/threefold/incatokens/readme.md
Normal file
2
lib/threefold/incatokens/readme.md
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
|
||||||
|
see examples/threefold/incatokens/incatokens_simulate.vsh for example of how to use
|
||||||
@@ -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
|
// Derived data
|
||||||
sim.epochn_floor_uplift = params.economics.epochn_floor_uplift
|
investor_rounds []InvestorRound
|
||||||
sim.amm_liquidity_depth_factor = params.economics.amm_liquidity_depth_factor
|
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
|
// Main simulation runner - single entry point
|
||||||
sim.investor_rounds = params.investor_rounds.map(InvestorRound{
|
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)!
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -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
|
|
||||||
}
|
|
||||||
58
lib/threefold/incatokens/templates/example.hero
Normal file
58
lib/threefold/incatokens/templates/example.hero
Normal 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"
|
||||||
63
lib/threefold/incatokens/types.v
Normal file
63
lib/threefold/incatokens/types.v
Normal 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
|
||||||
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user