120 lines
3.3 KiB
ReasonML
120 lines
3.3 KiB
ReasonML
open EAFunds_Data;
|
|
|
|
type yearlyNumericDiff = {
|
|
meanDiff: float,
|
|
stdDiff: float,
|
|
};
|
|
|
|
module PayoutsIfAround = {
|
|
let currentYear = 2020.;
|
|
let firstYearStdDev = 0.2;
|
|
let yearDiff = year => year -. 2020.0;
|
|
|
|
let yearlyMeanGrowthRateIfNotClosed = (group: group): yearlyNumericDiff => {
|
|
{meanDiff: 1.1, stdDiff: 1.1};
|
|
};
|
|
|
|
let calculateDifference =
|
|
(currentValue, yearInQuestion, y: yearlyNumericDiff) => {
|
|
let yearDiff = yearDiff(yearInQuestion);
|
|
let meanDiff = Js.Math.pow_float(~base=y.meanDiff, ~exp=yearDiff);
|
|
let stdDevDiff = Js.Math.pow_float(~base=y.meanDiff, ~exp=yearDiff);
|
|
Math.normal(currentValue *. meanDiff, firstYearStdDev *. stdDevDiff);
|
|
};
|
|
|
|
let rec currentValue = (group: group, output) => {
|
|
let sum = (): float =>
|
|
currentValue(Fund(ANIMAL_WELFARE), output)
|
|
+. currentValue(Fund(GLOBAL_HEALTH), output)
|
|
+. currentValue(Fund(LONG_TERM_FUTURE), output)
|
|
+. currentValue(Fund(META), output);
|
|
switch (group, output) {
|
|
| (Fund(ANIMAL_WELFARE), DONATIONS) => 300000.0
|
|
| (Fund(ANIMAL_WELFARE), PAYOUTS) => 2300000.0
|
|
| (Fund(GLOBAL_HEALTH), DONATIONS) => 1000000.0
|
|
| (Fund(GLOBAL_HEALTH), PAYOUTS) => 500000.0
|
|
| (Fund(LONG_TERM_FUTURE), DONATIONS) => 600000.0
|
|
| (Fund(LONG_TERM_FUTURE), PAYOUTS) => 120000.0
|
|
| (Fund(META), DONATIONS) => 9300000.0
|
|
| (Fund(META), PAYOUTS) => 830000.0
|
|
| (All, _) => sum()
|
|
};
|
|
};
|
|
};
|
|
|
|
let go = (group: group, year: float, output: output) => {
|
|
PayoutsIfAround.(
|
|
Model.InputTypes.FloatCdf(
|
|
calculateDifference(
|
|
currentValue(group, output),
|
|
year,
|
|
yearlyMeanGrowthRateIfNotClosed(group),
|
|
),
|
|
)
|
|
);
|
|
};
|
|
|
|
module Interface = {
|
|
open Model;
|
|
|
|
let model = {
|
|
name: "Calculate the payments and payouts of EA Funds based on existing data.",
|
|
author: "George Harrison",
|
|
assumptions: [
|
|
Input.make(~name="Yearly Growth Rate", ~parameterType=FloatPoint, ()),
|
|
Input.currentYear,
|
|
],
|
|
inputs: [
|
|
Input.make(
|
|
~name="Fund",
|
|
~parameterType=
|
|
SingleChoice({
|
|
default: Some("total"),
|
|
options: [
|
|
("Animal Welfare Fund", "animal"),
|
|
("Global Health Fund", "globalHealth"),
|
|
("Long Term Future Fund", "longTerm"),
|
|
("Meta Fund", "meta"),
|
|
("All", "all"),
|
|
],
|
|
}),
|
|
(),
|
|
),
|
|
Input.make(
|
|
~name="Year",
|
|
~parameterType=
|
|
Year({
|
|
default: Some(2030.0),
|
|
min: Some(2020.0),
|
|
max: Some(2050.0),
|
|
}),
|
|
(),
|
|
),
|
|
],
|
|
outputs: [
|
|
Output.make(~name="Payments", ~parameterType=FloatCdf, ()),
|
|
Output.make(~name="Payouts", ~parameterType=FloatCdf, ()),
|
|
],
|
|
outputConfig: Single,
|
|
};
|
|
|
|
let convertChoice = (s: string) =>
|
|
switch (s) {
|
|
| "animal" => Fund(ANIMAL_WELFARE)
|
|
| "globalHealth" => Fund(GLOBAL_HEALTH)
|
|
| "longTerm" => Fund(LONG_TERM_FUTURE)
|
|
| "meta" => Fund(META)
|
|
| _ => All
|
|
};
|
|
|
|
let run = (p: Model.modelParams) => {
|
|
switch (p.assumptions, p.inputs) {
|
|
| (
|
|
[Some(Year(intendedYear)), Some(Year(currentYear))],
|
|
[Some(SingleChoice(fund))],
|
|
) =>
|
|
Some(go(convertChoice(fund), intendedYear, DONATIONS))
|
|
| _ => None
|
|
};
|
|
};
|
|
}; |