Skip to content

Master Dag

Scope: Calculation dependency graph. For technical architecture (Jotai state, React Query, component patterns), see ARCHITECTURE.md.

Complete system in a single diagram - verified against source code.

flowchart TB
    subgraph INPUTS["📥 INPUT VARIABLES"]
        direction TB

        subgraph INC_INPUTS["Incidence Inputs"]
            BASE_INC[Base Incidence]
            POP_DATA[Population Data<br/>by geo/year]
            REG_FACTOR[Regional Factor<br/>EU5/Japan adjustments]
            GEO[Geography<br/>USA/EU5/Japan/China]
            INDICATION[Indication<br/>Disease name]
            INC_EVO[Incidence Evolution<br/>growth rates array]
        end

        subgraph STAGE_INPUTS["Stage Mix Inputs"]
            EARLY_PCT[Early Stage %]
            MET_PCT[Metastatic %]
            E2E_RELAPSE[Early→Early Relapse %]
            E2M_RELAPSE[Early→Met Relapse %]
            HC_ACCESS[Healthcare Access %]
        end

        subgraph PATIENT_INPUTS["Patient Flow Inputs"]
            TREAT_RATE[Treatment Rate %]
            TRANS_RATE[Transition Rate %]
            RETREAT[Retreatment Factor]
            CUSTOM_VARS[Custom Variables<br/>with growth rates]
        end

        subgraph PEAK_INPUTS["Peak Share Inputs"]
            LAUNCH_ORD[Launch Order<br/>1-10]
            BEST_CLASS[Best in Class<br/>true/false]
            DELAY_COMP[Delay vs Competition<br/>quarters]
            NUM_COMP[Num Competitors<br/>1-10]
            CLASS_SHARE[Class Share %<br/>default 100]
        end

        subgraph MARKET_INPUTS["Market Inputs"]
            LAUNCH_DT[Launch Date<br/>YYYY-MM-DD]
            SPEED_PEAK[Speed to Peak<br/>e.g. 3 Year Medium]
            LOE_DATE[LoE Date]
            MOL_TYPE[Molecule Type<br/>Biologic/Small Mol]
            EVENTS[Market Events<br/>impactPercent + startDate]
        end

        subgraph PRICE_INPUTS["Pricing Inputs"]
            YEAR_FIRST_LAUNCH[Year of First Launch]
            LAUNCH_PRICE[Launch Price<br/>$/month]
            ANN_PRICE_CHG[Annual Price Change %]
            NET_PRICE_EVO[Net Price Change<br/>custom array]
            MKT_EXCL_YRS[Market Exclusivity Years]
        end

        subgraph SALES_INPUTS["Sales Inputs"]
            MONTHS_THER[Months of Therapy<br/>can exceed 12]
            COMPLIANCE[Compliance %]
        end

        subgraph MC_INPUTS["Monte Carlo Inputs"]
            MC_VARS[Variable Ranges<br/>min/mode/max]
            MC_DIST[Distribution Type<br/>triangular/normal/uniform]
            MC_ITERS[Iterations<br/>default 1000]
        end
    end

    subgraph REFERENCE["📚 REFERENCE DATA"]
        LAUNCH_MATRIX[LAUNCH_ORDERS<br/>10x10 Matrix]
        BIC_ARRAY[BEST_IN_CLASS<br/>Array by competitors]
        UPTAKE_CURVES[UPTAKE_CURVE<br/>30+ curves]
        MOL_EROSION[MOLECULE_SHARE_EROSION<br/>Small molecule rates]
        BIO_EROSION[BIOLOGICS_SHARE_EROSION<br/>Biologic rates]
        COHORT_YRS[COHORT_YEARS = 5<br/>Multi-year aggregation]
    end

    subgraph CALC_INC["🧮 INCIDENCE CALCULATION"]
        POP_RATIO[Population Ratio<br/>Pop Year / Pop Base]
        YEAR_INC[Year Incidence<br/>= Base × PopRatio × RegFactor]
        INC_GROWTH[Apply Growth Rate<br/>from evolution array]
    end

    BASE_INC --> YEAR_INC
    POP_DATA --> POP_RATIO
    POP_RATIO --> YEAR_INC
    REG_FACTOR --> YEAR_INC
    GEO --> POP_RATIO
    INC_EVO --> INC_GROWTH
    YEAR_INC --> INC_GROWTH

    subgraph CALC_ADDR["🧮 ADDRESSABLE POPULATION"]
        direction TB

        subgraph EARLY_CALC["Early Stage Path"]
            EARLY_BASE[Incidence × Early%]
            EARLY_REL[× 1+E2E%]
            EARLY_HC[× HC%]
            EARLY_ADDR[Early Addressable]
        end

        subgraph MET_CALC["Metastatic Path"]
            MET_DENOVO[Incidence × Met%]
            MET_REL[+ Incidence × Early% × E2M%]
            MET_SUM[Sum]
            MET_HC[× HC%]
            MET_ADDR[Met Addressable]
        end

        subgraph THER_CALC["Therapy Path - Hematology"]
            THER_ADDR[Therapy Addressable<br/>= Incidence × HC%]
        end

        subgraph CUSTOM_CALC["Custom Variables"]
            CUSTOM_MULT[Custom Multiplier<br/>product of all custom vars]
            FINAL_ADDR[Final Addressable<br/>× customMultiplier]
        end
    end

    INC_GROWTH --> EARLY_BASE
    EARLY_PCT --> EARLY_BASE
    EARLY_BASE --> EARLY_REL
    E2E_RELAPSE --> EARLY_REL
    EARLY_REL --> EARLY_HC
    HC_ACCESS --> EARLY_HC
    EARLY_HC --> EARLY_ADDR

    INC_GROWTH --> MET_DENOVO
    MET_PCT --> MET_DENOVO
    INC_GROWTH --> MET_REL
    EARLY_PCT --> MET_REL
    E2M_RELAPSE --> MET_REL
    MET_DENOVO --> MET_SUM
    MET_REL --> MET_SUM
    MET_SUM --> MET_HC
    HC_ACCESS --> MET_HC
    MET_HC --> MET_ADDR

    INC_GROWTH --> THER_ADDR
    HC_ACCESS --> THER_ADDR

    CUSTOM_VARS --> CUSTOM_MULT
    EARLY_ADDR --> FINAL_ADDR
    MET_ADDR --> FINAL_ADDR
    THER_ADDR --> FINAL_ADDR
    CUSTOM_MULT --> FINAL_ADDR

    subgraph CALC_PEAK["🧮 PEAK SHARE CALCULATION"]
        BASE_SHARE[Base Share<br/>from LAUNCH_ORDERS matrix]
        BIC_BONUS[BIC Bonus<br/>from BEST_IN_CLASS array]
        DELAY_PEN[Delay Penalty<br/>= delay > 3 ? delay × 0.5 : 0]
        PEAK_SHARE[Peak Share %<br/>= clamp 0-100: Base + BIC - Delay]
        EFF_PEAK[Effective Peak Share<br/>= Peak × ClassShare / 100]
    end

    LAUNCH_ORD --> BASE_SHARE
    NUM_COMP --> BASE_SHARE
    LAUNCH_MATRIX --> BASE_SHARE
    BEST_CLASS --> BIC_BONUS
    NUM_COMP --> BIC_BONUS
    BIC_ARRAY --> BIC_BONUS
    DELAY_COMP --> DELAY_PEN
    BASE_SHARE --> PEAK_SHARE
    BIC_BONUS --> PEAK_SHARE
    DELAY_PEN --> PEAK_SHARE
    PEAK_SHARE --> EFF_PEAK
    CLASS_SHARE --> EFF_PEAK

    subgraph CALC_MKS["🧮 MARKET SHARE OVER TIME"]
        YEAR_OFFSET[Year Offset<br/>= Year - LaunchYear]
        UPTAKE_VAL[Uptake Value<br/>from UPTAKE_CURVE by speed and offset]
        PREV_UPTAKE[Previous Uptake<br/>from UPTAKE_CURVE by speed and offset]
        WEIGHTED_SHARE[Weighted Share<br/>month-adjusted blend]
        EVENT_IMPACT[Event Impact<br/>Σ event.impactPercent × uptake]
        BASE_MKS[Base Market Share<br/>= Weighted × Peak%]
        EROSION_LOOKUP[Erosion Rate Lookup<br/>by molecule type]
        LOE_IMPACT[LoE Impact<br/>month-weighted erosion]
        MKT_SHARE[Final Market Share %<br/>= Base + Events × LoE]
    end

    LAUNCH_DT --> YEAR_OFFSET
    YEAR_OFFSET --> UPTAKE_VAL
    SPEED_PEAK --> UPTAKE_VAL
    UPTAKE_CURVES --> UPTAKE_VAL
    UPTAKE_VAL --> WEIGHTED_SHARE
    YEAR_OFFSET --> PREV_UPTAKE
    PREV_UPTAKE --> WEIGHTED_SHARE
    LAUNCH_DT --> WEIGHTED_SHARE
    WEIGHTED_SHARE --> BASE_MKS
    EFF_PEAK --> BASE_MKS
    EVENTS --> EVENT_IMPACT
    UPTAKE_VAL --> EVENT_IMPACT
    LOE_DATE --> EROSION_LOOKUP
    MOL_TYPE --> EROSION_LOOKUP
    MOL_EROSION --> EROSION_LOOKUP
    BIO_EROSION --> EROSION_LOOKUP
    EROSION_LOOKUP --> LOE_IMPACT
    LOE_DATE --> LOE_IMPACT
    BASE_MKS --> MKT_SHARE
    EVENT_IMPACT --> MKT_SHARE
    LOE_IMPACT --> MKT_SHARE

    subgraph CALC_PAT["🧮 PATIENT FLOW BY LINE"]
        direction TB

        subgraph LINE_1["1L First Line"]
            L1_ELIG[1L Eligible<br/>= Addressable × TreatRate%]
            L1_NEW[1L New Patients<br/>= Eligible × MktShare%]
        end

        subgraph LINE_2["2L Second Line"]
            L2_POOL[2L Pool<br/>= 1L_Elig - 1L_New × Retreat]
            L2_TRANS[× Transition%]
            L2_ELIG[2L Eligible<br/>× TreatRate%]
            L2_NEW[2L New Patients<br/>= Eligible × MktShare%]
        end

        subgraph LINE_3["3L+ Third Line+"]
            L3_POOL[3L Pool<br/>= 2L_Elig - 2L_New × Retreat]
            L3_ELIG[3L+ Eligible<br/>= Pool × Transition%<br/>NO TreatRate]
            L3_NEW[3L+ New Patients<br/>= Eligible × MktShare%]
        end
    end

    FINAL_ADDR --> L1_ELIG
    TREAT_RATE --> L1_ELIG
    L1_ELIG --> L1_NEW
    MKT_SHARE --> L1_NEW

    L1_ELIG --> L2_POOL
    L1_NEW --> L2_POOL
    RETREAT --> L2_POOL
    L2_POOL --> L2_TRANS
    TRANS_RATE --> L2_TRANS
    L2_TRANS --> L2_ELIG
    TREAT_RATE --> L2_ELIG
    L2_ELIG --> L2_NEW
    MKT_SHARE --> L2_NEW

    L2_ELIG --> L3_POOL
    L2_NEW --> L3_POOL
    RETREAT --> L3_POOL
    L3_POOL --> L3_ELIG
    TRANS_RATE --> L3_ELIG
    L3_ELIG --> L3_NEW
    MKT_SHARE --> L3_NEW

    subgraph CALC_PRICE["🧮 NET PRICE CALCULATION"]
        YEARS_FROM_LAUNCH[Years from Launch<br/>= Year - YearOfFirstLaunch]
        HAS_CUSTOM{Has Custom<br/>Evolution?}
        DURATION_CALC[Duration Calculation<br/>capped near LoE by<br/>marketExclusivityYears]
        COMPOUND_PRICE[Compound Price<br/>= Launch × 1+APC% ^ duration]
        CUSTOM_PRICE[Custom Price<br/>cumulative year changes]
        NET_PRICE[Net Price $/month]
    end

    YEAR_FIRST_LAUNCH --> YEARS_FROM_LAUNCH
    NET_PRICE_EVO --> HAS_CUSTOM
    HAS_CUSTOM -->|No| COMPOUND_PRICE
    HAS_CUSTOM -->|Yes| CUSTOM_PRICE
    LAUNCH_PRICE --> COMPOUND_PRICE
    ANN_PRICE_CHG --> COMPOUND_PRICE
    YEARS_FROM_LAUNCH --> DURATION_CALC
    LOE_DATE --> DURATION_CALC
    MKT_EXCL_YRS --> DURATION_CALC
    DURATION_CALC --> COMPOUND_PRICE
    LAUNCH_PRICE --> CUSTOM_PRICE
    NET_PRICE_EVO --> CUSTOM_PRICE
    COMPOUND_PRICE --> NET_PRICE
    CUSTOM_PRICE --> NET_PRICE

    subgraph CALC_SALES["🧮 LINE SALES CALCULATION"]
        direction TB

        subgraph COHORT_AGG["Multi-Year Cohort Aggregation"]
            COHORT_LOOP[For each of 5 cohort years]
            COHORT_PATIENTS[Get patients from<br/>year - offset]
            COHORT_MONTHS[Calculate months<br/>for this cohort]
        end

        subgraph SALES_1["1L Sales"]
            S1_MULT[NewPatients × NetPrice]
            S1_COMP[× Compliance%]
            S1_MOT[× months for cohort]
            S1_DIV[÷ 1,000,000]
            L1_SALES[1L Sales $M<br/>sum of all cohorts]
        end

        subgraph SALES_2["2L Sales"]
            L2_SALES[2L Sales $M]
        end

        subgraph SALES_3["3L+ Sales"]
            L3_SALES[3L+ Sales $M]
        end
    end

    COHORT_YRS --> COHORT_LOOP
    COHORT_LOOP --> COHORT_PATIENTS
    COHORT_PATIENTS --> COHORT_MONTHS
    MONTHS_THER --> COHORT_MONTHS

    L1_NEW --> S1_MULT
    NET_PRICE --> S1_MULT
    S1_MULT --> S1_COMP
    COMPLIANCE --> S1_COMP
    S1_COMP --> S1_MOT
    COHORT_MONTHS --> S1_MOT
    S1_MOT --> S1_DIV
    S1_DIV --> L1_SALES

    L2_NEW --> L2_SALES
    NET_PRICE --> L2_SALES
    COMPLIANCE --> L2_SALES
    COHORT_MONTHS --> L2_SALES

    L3_NEW --> L3_SALES
    NET_PRICE --> L3_SALES
    COMPLIANCE --> L3_SALES
    COHORT_MONTHS --> L3_SALES

    subgraph CALC_TOTAL["🧮 TOTAL SALES"]
        SALES_SUM[Sum All Lines]
        TOTAL_SALES[Total Sales $M]
    end

    L1_SALES --> SALES_SUM
    L2_SALES --> SALES_SUM
    L3_SALES --> SALES_SUM
    SALES_SUM --> TOTAL_SALES

    subgraph CALC_MC["🎲 MONTE CARLO SIMULATION"]
        direction TB

        subgraph MC_SAMPLE["Sampling - per iteration"]
            SAMPLE_HC[Sample HC%]
            SAMPLE_TR[Sample TreatRate%]
            SAMPLE_STAGE[Sample Stage Mix<br/>Early/Met/E2E/E2M]
            SAMPLE_PS[Sample PeakShare]
            SAMPLE_MOT[Sample MOT]
            SAMPLE_LP[Sample LaunchPrice]
            SAMPLE_CUSTOM[Sample Custom Vars]
        end

        subgraph MC_ITER["Iteration Loop - 1000x"]
            CLONE_STATE[Clone Base State<br/>shallow copy]
            APPLY_SAMPLES[Apply Sampled Values<br/>to cloned state]
            RUN_CALC[Run Full Calculation<br/>using computations.ts]
            COLLECT_RESULT[Collect Year Sales]
        end

        subgraph MC_ANALYZE["Statistical Analysis"]
            ALL_RESULTS[All Results<br/>1000 × numYears]
            CALC_P10[P10 - quantile 0.1]
            CALC_P50[P50 - quantile 0.5]
            CALC_P90[P90 - quantile 0.9]
            CALC_MEAN[Mean]
        end

        subgraph MC_TORNADO["Tornado Analysis"]
            HOLD_BASE[Hold all at mostLikely]
            VAR_MIN[Run with var at min]
            VAR_MAX[Run with var at max]
            IMPACT[Impact = abs max - min]
            RANK[Sort by total impact<br/>ascending]
        end
    end

    MC_VARS --> SAMPLE_HC
    MC_VARS --> SAMPLE_TR
    MC_VARS --> SAMPLE_STAGE
    MC_VARS --> SAMPLE_PS
    MC_VARS --> SAMPLE_MOT
    MC_VARS --> SAMPLE_LP
    MC_VARS --> SAMPLE_CUSTOM
    MC_DIST --> SAMPLE_HC

    SAMPLE_HC --> APPLY_SAMPLES
    SAMPLE_TR --> APPLY_SAMPLES
    SAMPLE_STAGE --> APPLY_SAMPLES
    SAMPLE_PS --> APPLY_SAMPLES
    SAMPLE_MOT --> APPLY_SAMPLES
    SAMPLE_LP --> APPLY_SAMPLES
    SAMPLE_CUSTOM --> APPLY_SAMPLES

    CLONE_STATE --> APPLY_SAMPLES
    APPLY_SAMPLES --> RUN_CALC
    RUN_CALC --> COLLECT_RESULT
    COLLECT_RESULT --> ALL_RESULTS

    ALL_RESULTS --> CALC_P10
    ALL_RESULTS --> CALC_P50
    ALL_RESULTS --> CALC_P90
    ALL_RESULTS --> CALC_MEAN

    MC_VARS --> HOLD_BASE
    HOLD_BASE --> VAR_MIN
    HOLD_BASE --> VAR_MAX
    VAR_MIN --> IMPACT
    VAR_MAX --> IMPACT
    IMPACT --> RANK

    subgraph OUTPUTS["📤 OUTPUTS"]
        direction TB

        subgraph MODEL_OUT["Model Outputs"]
            OUT_PAT_LINE[Patients by Line/Year]
            OUT_MKS_LINE[Market Share by Line/Year]
            OUT_SALES_LINE[Sales by Line/Year]
            OUT_TOTAL[Total Sales by Year]
        end

        subgraph CHART_OUT["Chart Outputs"]
            SALES_CHART[Stacked Bar Chart<br/>Sales by Line]
        end

        subgraph MC_OUT["Monte Carlo Outputs"]
            P10_FORECAST[P10 Forecast<br/>Pessimistic]
            P50_FORECAST[P50 Forecast<br/>Median]
            P90_FORECAST[P90 Forecast<br/>Optimistic]
            TORNADO_CHART[Tornado Chart<br/>Sensitivity ranked]
        end
    end

    L1_NEW --> OUT_PAT_LINE
    L2_NEW --> OUT_PAT_LINE
    L3_NEW --> OUT_PAT_LINE
    MKT_SHARE --> OUT_MKS_LINE
    L1_SALES --> OUT_SALES_LINE
    L2_SALES --> OUT_SALES_LINE
    L3_SALES --> OUT_SALES_LINE
    TOTAL_SALES --> OUT_TOTAL

    OUT_SALES_LINE --> SALES_CHART

    CALC_P10 --> P10_FORECAST
    CALC_P50 --> P50_FORECAST
    CALC_P90 --> P90_FORECAST
    RANK --> TORNADO_CHART

    %% Container Styling per Legend - Dark colors for contrast
    style INPUTS fill:#1565c0,stroke:#0d47a1,color:#fff
    style REFERENCE fill:#e65100,stroke:#bf360c,color:#fff
    style CALC_INC fill:#2e7d32,stroke:#1b5e20,color:#fff
    style CALC_ADDR fill:#2e7d32,stroke:#1b5e20,color:#fff
    style CALC_PEAK fill:#2e7d32,stroke:#1b5e20,color:#fff
    style CALC_MKS fill:#2e7d32,stroke:#1b5e20,color:#fff
    style CALC_PAT fill:#2e7d32,stroke:#1b5e20,color:#fff
    style CALC_PRICE fill:#2e7d32,stroke:#1b5e20,color:#fff
    style CALC_SALES fill:#2e7d32,stroke:#1b5e20,color:#fff
    style CALC_TOTAL fill:#2e7d32,stroke:#1b5e20,color:#fff
    style CALC_MC fill:#ad1457,stroke:#880e4f,color:#fff
    style OUTPUTS fill:#6a1b9a,stroke:#4a148c,color:#fff
ContainerColorHexMeaning
INPUTSBlue#1565c0Input Variables
REFERENCEOrange#e65100Reference Data / Lookup Tables
CALC_*Green#2e7d32Calculated Values
CALC_MCMagenta#ad1457Monte Carlo Simulation
OUTPUTSPurple#6a1b9aOutput Values

Source: computations.ts (incidence computed via buildIncidenceEvolution in IncidenceEvolution/computations.ts)

YearIncidence = BaseIncidence × (Pop[Year] / Pop[BaseYear]) × RegionalFactor

Source: computations.ts (calculateLineFunnelForDisplay)

EarlyAddressable = Incidence × (EarlyStage% / 100) × (1 + EarlyToEarlyRelapse% / 100) × (HC% / 100)
MetAddressable = (Incidence × MetStage% / 100 + Incidence × EarlyStage% / 100 × EarlyToMetRelapse% / 100) × (HC% / 100)

Source: computations.ts (hematology path in calculateLineFunnelForDisplay)

TherapyAddressable = Incidence × (HC% / 100)

Source: computations.ts (getCustomMultiplier)

customMultiplier = Π(customVar.value / 100) for all custom variables
FinalAddressable = Addressable × customMultiplier

Source: computations.ts (calculatePeakShare)

order = clamp(launchOrder, 1, 10)
competitors = clamp(numCompetitors, 1, 10)
baseShare = LAUNCH_ORDERS[order - 1][competitors - 1]
bicBonus = bestInClass ? BEST_IN_CLASS[competitors - 1] : 0
delayPenalty = delayVsCompetition > 3 ? delayVsCompetition × 0.5 : 0
PeakShare (within class) = clamp(0, 100, baseShare + bicBonus - delayPenalty)
EffectivePeakShare = PeakShare × (classShare / 100)

The EffectivePeakShare is used in market share calculations.

Source: computations.ts (calculateMarketShare)

yearOffset = year - launchYear
uptake = UPTAKE_CURVE[speedToPeak][yearOffset + 1]
prevUptake = yearOffset > 0 ? UPTAKE_CURVE[speedToPeak][yearOffset] : 0
launchMonth = launch.getMonth() + 1
weightedShare = (uptake × (13 - launchMonth) + prevUptake × (launchMonth - 1)) / 12
erosionOffset = year - loeYear
loeMonth = loeDate.getUTCMonth() + 1
preRate = (erosionRates[erosionOffset] / 100) × (13 - loeMonth) / 12
postRate = (erosionRates[erosionOffset + 1] / 100) × (loeMonth - 1) / 12
erosion = year >= loeYear ? 1 - (preRate + postRate) : 1
MarketShare = clamp(0, 100, weightedShare × (peakShare / 100) × erosion)

Source: MonteCarlo/computations.ts (event impact applied during simulation)

marketShare = calculateMarketShare(line, year, lines)
eventImpact = Σ(event.impactPercent × monthWeightedUptake)
loeImpact = calculateLoEImpact(year, erosionData, assumptions)
MarketShareA = clamp(0, 100, (marketShare + eventImpact) × loeImpact)

Source: MonteCarlo/computations.ts (LoE erosion applied during simulation)

if year < loeYear: return 1
offset = year - loeYear
preErosion = (erosionData[offset] / 100) × (13 - loeMonth) / 12
postErosion = (erosionData[offset + 1] / 100) × (loeMonth - 1) / 12
LoEImpact = 1 - (preErosion + postErosion)

Source: computations.ts (calculateLinePatients)

1L_Eligible = Addressable × (TreatmentRate / 100)
1L_NewPatients = 1L_Eligible × (MarketShare / 100)

Source: computations.ts (calculateLinePatients, 2L case)

2L_Pool = 1L_Eligible - (1L_NewPatients × Retreatment)
2L_Eligible = (2L_Pool × TransitionRate / 100) × (TreatmentRate / 100)
2L_NewPatients = 2L_Eligible × (MarketShare / 100)

Source: computations.ts (calculateLinePatients, 3L+ case)

3L_Pool = 2L_Eligible - (2L_NewPatients × Retreatment)
3L_Eligible = 3L_Pool × (TransitionRate / 100) // NO TreatmentRate
3L_NewPatients = 3L_Eligible × (MarketShare / 100)

Source: computations.ts (calculateNetPriceFromAssumptions)

if year <= launchYear: return launchPrice
yearsFromLaunch = year - launchYear
NetPrice = launchPrice × (1 + annualPriceChange / 100) ^ yearsFromLaunch

Source: computations.ts (calculateNetPriceFromAssumptions, duration cap logic)

loeYear = parseInt(loeDate.split("-")[0])
duration = year >= loeYear - 1 ? marketExclusivityYears - 1 : year - yearOfFirstLaunch
NetPrice = launchPrice × (1 + priceChange / 100) ^ duration

Both the Model/SalesChart path (calculateLineSales) and Monte Carlo/Tornado path (calculateLineSalesTotal) use cohort-based distribution. MonthsOfTherapy is spread across calendar years, each contributing up to 12 months.

Source: computations.ts (calculateLineSales, calculateLineSalesTotal)

COHORT_YEARS = 5
For yearOffset in 0..4:
treatmentMonthThreshold = yearOffset × 12
if treatmentMonths <= treatmentMonthThreshold: break
months = yearOffset == 0
? min(treatmentMonths, 12)
: treatmentMonths > (threshold + 12) ? 12 : treatmentMonths - threshold
patients = getCohortPatients(line, year - yearOffset, ...)
sale = (patients × netPrice × compliance × months) / 1,000,000
LineSales = Σ(sale for all cohort years)

When MonthsOfTherapy ≤ 12, only yearOffset=0 iterates and the formula reduces to the simple form.

TotalSales = Σ(LineSales[i]) for all therapy lines

Source: computations.ts (triangularDistribution, normalDistribution, uniformDistribution)

Triangular:

c = (mostLikely - min) / (max - min)
u = random()
if u <= c:
value = min + sqrt(u × (max - min) × (mostLikely - min))
else:
value = max - sqrt((1 - u) × (max - min) × (max - mostLikely))

Normal (Box-Muller):

mean = (min + max) / 2
stdDev = (max - min) / 6 // NORMAL_DISTRIBUTION_SIGMAS = 6
z = sqrt(-2 × ln(u1)) × cos(2π × u2)
value = z × stdDev + mean

Uniform:

value = min + random() × (max - min)

Per FORECASTING_MODEL.md and code analysis:

  • Transition Rate
  • Compliance
  • Annual Price Change

These are held constant during Monte Carlo simulation.

Incidence Evolution in Monte Carlo/Tornado

Section titled “Incidence Evolution in Monte Carlo/Tornado”

Monte Carlo and Tornado analyses use getYearIncidence(year) for each simulated year, which applies the growth rates from the Incidence Evolution table (Custom Inputs). This ensures simulations properly reflect year-over-year incidence changes rather than using a static base incidence value.


CalculationFileFunction
Custom Multipliercomputations.tsgetCustomMultiplier
Line Funnel Displaycomputations.tscalculateLineFunnelForDisplay
Market Sharecomputations.tscalculateMarketShare
Net Pricecomputations.tscalculateNetPriceFromAssumptions
Line Patientscomputations.tscalculateLinePatients
Line Salescomputations.tscalculateLineSales
Changeable Valuescomputations.tsapplyChangeableValue
Treatment Eligible (MC)computations.tscalculateTreatmentEligiblePatients
Line Sales Total (MC)computations.tscalculateLineSalesTotal
Peak Sharecomputations.tscalculatePeakShare
Growth RatesIncidenceEvolution/computations.tscomputeGrowthRates
Incidence EvolutionIncidenceEvolution/computations.tsbuildIncidenceEvolution
Growth Rate ChangeIncidenceEvolution/computations.tsapplyGrowthRateChange
Monte Carlo EngineMonteCarlo/computations.tsrunMonteCarloSimulation
Tornado AnalysisTornado/computations.tsrunTornadoAnalysis