2020-02-10 20:37:12 +00:00
|
|
|
module Data = {
|
|
|
|
type fund =
|
|
|
|
| ANIMAL_WELFARE
|
|
|
|
| GLOBAL_HEALTH
|
|
|
|
| LONG_TERM_FUTURE
|
|
|
|
| META;
|
|
|
|
|
|
|
|
type group =
|
|
|
|
| Fund(fund)
|
|
|
|
| All;
|
|
|
|
|
|
|
|
type output =
|
|
|
|
| DONATIONS
|
2020-02-10 23:10:03 +00:00
|
|
|
| CHANCE_OF_EXISTENCE
|
2020-02-10 20:37:12 +00:00
|
|
|
| PAYOUTS;
|
|
|
|
|
2020-02-10 23:10:03 +00:00
|
|
|
type conditionals =
|
|
|
|
| WORLD_CATASTROPHE;
|
|
|
|
|
2020-02-10 20:37:12 +00:00
|
|
|
type fundWithInfo = {
|
|
|
|
group,
|
|
|
|
name: string,
|
|
|
|
existingDonations: option(float),
|
|
|
|
existingPayouts: option(float),
|
|
|
|
};
|
|
|
|
|
|
|
|
let makeFundWithInfo = (name, group, existingDonations, existingPayouts) => {
|
|
|
|
group,
|
|
|
|
name,
|
|
|
|
existingDonations,
|
|
|
|
existingPayouts,
|
|
|
|
};
|
|
|
|
|
|
|
|
let funds = [|
|
|
|
|
makeFundWithInfo(
|
|
|
|
"Animal Welfare Fund",
|
|
|
|
Fund(ANIMAL_WELFARE),
|
|
|
|
Some(4000.0),
|
|
|
|
Some(10.0),
|
|
|
|
),
|
|
|
|
makeFundWithInfo(
|
|
|
|
"Global Health Fund",
|
|
|
|
Fund(GLOBAL_HEALTH),
|
|
|
|
Some(4000.0),
|
|
|
|
Some(10.0),
|
|
|
|
),
|
|
|
|
makeFundWithInfo(
|
|
|
|
"Long Term Future Fund",
|
|
|
|
Fund(LONG_TERM_FUTURE),
|
|
|
|
Some(4000.0),
|
|
|
|
Some(10.0),
|
|
|
|
),
|
|
|
|
makeFundWithInfo(
|
|
|
|
"Meta Fund",
|
|
|
|
Fund(ANIMAL_WELFARE),
|
|
|
|
Some(4000.0),
|
|
|
|
Some(10.0),
|
|
|
|
),
|
|
|
|
makeFundWithInfo("All", All, None, None),
|
|
|
|
|];
|
|
|
|
};
|
|
|
|
|
|
|
|
module Model = {
|
|
|
|
open Data;
|
|
|
|
let currentYear = 2020.;
|
|
|
|
let firstYearStdDev = 0.2;
|
|
|
|
type yearlyNumericDiff = {
|
|
|
|
meanDiff: float,
|
|
|
|
stdDiff: float,
|
|
|
|
};
|
|
|
|
|
|
|
|
let yearlyMeanGrowthRateIfNotClosed = (group: group): yearlyNumericDiff => {
|
2020-02-25 20:08:53 +00:00
|
|
|
{meanDiff: 1.1, stdDiff: 1.08};
|
2020-02-10 20:37:12 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
let calculateDifference =
|
|
|
|
(currentValue, dateTime, currentDateTime, y: yearlyNumericDiff) => {
|
|
|
|
let yearDiff = MomentRe.diff(dateTime, currentDateTime, `days) /. 365.;
|
|
|
|
let meanDiff = Js.Math.pow_float(~base=y.meanDiff, ~exp=yearDiff);
|
2020-02-25 20:08:53 +00:00
|
|
|
let stdDevDiff = Js.Math.pow_float(~base=y.stdDiff, ~exp=yearDiff);
|
2020-02-16 12:27:44 +00:00
|
|
|
GuesstimatorDist.logNormal(
|
2020-02-13 12:40:04 +00:00
|
|
|
currentValue *. meanDiff,
|
|
|
|
firstYearStdDev *. stdDevDiff,
|
|
|
|
);
|
2020-02-10 20:37:12 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
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()
|
2020-02-10 23:10:03 +00:00
|
|
|
| (_, CHANCE_OF_EXISTENCE) => 0.0
|
2020-02-10 20:37:12 +00:00
|
|
|
};
|
|
|
|
};
|
2020-02-17 19:45:32 +00:00
|
|
|
|
|
|
|
let xRisk = conditionals =>
|
|
|
|
Prop.Value.ConditionalArray.get(conditionals, "Global Existential Event");
|
|
|
|
|
2020-02-21 11:45:32 +00:00
|
|
|
// TODO: Fixe number that integral is calculated for
|
|
|
|
let getGlobalCatastropheChance = dateTime => {
|
2020-02-23 18:34:34 +00:00
|
|
|
GlobalCatastrophe.makeI(MomentRe.momentNow())
|
2020-02-25 19:27:30 +00:00
|
|
|
|> DistPlusIngredients.toDistPlus
|
|
|
|
|> E.O.bind(_, Distributions.DistPlusTime.Integral.xToY(Time(dateTime)));
|
2020-02-21 11:45:32 +00:00
|
|
|
};
|
|
|
|
|
2020-02-10 20:37:12 +00:00
|
|
|
let make =
|
|
|
|
(
|
|
|
|
group: group,
|
|
|
|
dateTime: MomentRe.Moment.t,
|
|
|
|
currentDateTime: MomentRe.Moment.t,
|
|
|
|
output: output,
|
2020-02-17 19:45:32 +00:00
|
|
|
conditionals: array(Prop.Value.conditional),
|
2020-02-10 20:37:12 +00:00
|
|
|
) => {
|
2020-02-17 19:45:32 +00:00
|
|
|
let xRisk = xRisk(conditionals);
|
2020-02-10 23:10:03 +00:00
|
|
|
switch (output) {
|
|
|
|
| DONATIONS
|
|
|
|
| PAYOUTS =>
|
2020-02-15 23:01:59 +00:00
|
|
|
let difference =
|
2020-02-10 23:10:03 +00:00
|
|
|
calculateDifference(
|
|
|
|
currentValue(group, output),
|
|
|
|
dateTime,
|
|
|
|
currentDateTime,
|
|
|
|
yearlyMeanGrowthRateIfNotClosed(group),
|
2020-02-15 23:01:59 +00:00
|
|
|
);
|
2020-02-18 13:23:02 +00:00
|
|
|
|
2020-02-17 19:45:32 +00:00
|
|
|
let str =
|
|
|
|
switch (xRisk) {
|
|
|
|
| Some({truthValue: true}) => "0"
|
|
|
|
| Some({truthValue: false}) => difference
|
2020-02-21 11:45:32 +00:00
|
|
|
| None =>
|
|
|
|
let foo =
|
2020-02-25 19:27:30 +00:00
|
|
|
getGlobalCatastropheChance(dateTime)
|
2020-02-21 11:45:32 +00:00
|
|
|
|> E.O.fmap(E.Float.with2DigitsPrecision)
|
|
|
|
|> E.O.fmap((r: string) =>
|
|
|
|
"uniform(0,1) > " ++ r ++ " ? " ++ difference ++ ": 0"
|
|
|
|
);
|
|
|
|
foo |> E.O.default("");
|
2020-02-17 19:45:32 +00:00
|
|
|
};
|
2020-02-18 13:23:02 +00:00
|
|
|
|
2020-02-23 12:49:33 +00:00
|
|
|
let distPlusIngredients =
|
|
|
|
DistPlusIngredients.make(
|
|
|
|
~guesstimatorString=str,
|
2020-02-15 23:01:59 +00:00
|
|
|
~domain=Complete,
|
2020-02-19 07:54:40 +00:00
|
|
|
~unit=UnspecifiedDistribution,
|
2020-02-15 23:01:59 +00:00
|
|
|
(),
|
|
|
|
);
|
2020-02-23 12:49:33 +00:00
|
|
|
Prop.Value.DistPlusIngredients(distPlusIngredients);
|
2020-02-19 07:54:40 +00:00
|
|
|
|
2020-02-17 19:45:32 +00:00
|
|
|
| CHANCE_OF_EXISTENCE =>
|
2020-02-23 12:49:33 +00:00
|
|
|
Prop.Value.DistPlusIngredients(
|
|
|
|
DistPlusIngredients.make(
|
|
|
|
~guesstimatorString=
|
|
|
|
GuesstimatorDist.min(
|
|
|
|
GlobalCatastrophe.guesstimatorString,
|
2020-02-25 20:08:53 +00:00
|
|
|
GuesstimatorDist.logNormal(20., 2.),
|
2020-02-17 19:45:32 +00:00
|
|
|
),
|
2020-02-25 20:08:53 +00:00
|
|
|
~unit=TimeDistribution({zero: currentDateTime, unit: `years}),
|
2020-02-17 19:45:32 +00:00
|
|
|
~domain=RightLimited({xPoint: 100., excludingProbabilityMass: 0.3}),
|
|
|
|
(),
|
|
|
|
),
|
|
|
|
)
|
2020-02-10 23:10:03 +00:00
|
|
|
};
|
2020-02-10 20:37:12 +00:00
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
module Interface = {
|
|
|
|
open Data;
|
|
|
|
|
2020-02-10 21:16:17 +00:00
|
|
|
let fundKey = "Fund";
|
|
|
|
let dayKey = "Day";
|
|
|
|
let outputKey = "Output";
|
|
|
|
|
|
|
|
let choiceFromString = (s: string) =>
|
|
|
|
funds |> E.A.getBy(_, r => r.name == s);
|
|
|
|
|
|
|
|
let outputFromString = (s: string) =>
|
2020-02-10 20:37:12 +00:00
|
|
|
switch (s) {
|
|
|
|
| "donations" => DONATIONS
|
2020-02-10 23:10:03 +00:00
|
|
|
| "exists" => CHANCE_OF_EXISTENCE
|
2020-02-10 20:37:12 +00:00
|
|
|
| _ => PAYOUTS
|
|
|
|
};
|
|
|
|
|
2020-02-17 16:53:30 +00:00
|
|
|
let run = (p: array(option(Prop.Value.t))) => {
|
|
|
|
switch (p) {
|
2020-02-10 21:16:17 +00:00
|
|
|
| [|
|
2020-02-10 20:37:12 +00:00
|
|
|
Some(SelectSingle(fund)),
|
|
|
|
Some(DateTime(intendedYear)),
|
|
|
|
Some(DateTime(currentYear)),
|
|
|
|
Some(SelectSingle(output)),
|
2020-02-17 19:45:32 +00:00
|
|
|
Some(ConditionalArray(conditionals)),
|
2020-02-10 21:16:17 +00:00
|
|
|
|] =>
|
|
|
|
choiceFromString(fund)
|
|
|
|
|> E.O.fmap(fund =>
|
|
|
|
Model.make(
|
|
|
|
fund.group,
|
|
|
|
intendedYear,
|
|
|
|
currentYear,
|
|
|
|
outputFromString(output),
|
2020-02-17 19:45:32 +00:00
|
|
|
conditionals,
|
2020-02-10 21:16:17 +00:00
|
|
|
)
|
|
|
|
)
|
2020-02-10 20:37:12 +00:00
|
|
|
| _ => None
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
let model: Prop.Model.t =
|
|
|
|
Prop.{
|
2020-02-26 09:36:26 +00:00
|
|
|
id: "ea-funds",
|
|
|
|
name: "EA Funds: Donations & Payouts",
|
2020-02-13 11:29:06 +00:00
|
|
|
description: "Calculate the payments and payouts of CEA Funds based on existing data.",
|
2020-02-10 20:37:12 +00:00
|
|
|
version: "1.0.0",
|
2020-02-26 10:32:10 +00:00
|
|
|
fileName: "EAFunds.re",
|
2020-02-10 20:37:12 +00:00
|
|
|
author: "Ozzie Gooen",
|
|
|
|
inputTypes: [|
|
|
|
|
TypeWithMetadata.make(
|
2020-02-10 21:16:17 +00:00
|
|
|
~name=fundKey,
|
2020-02-10 20:37:12 +00:00
|
|
|
~type_=
|
|
|
|
SelectSingle({
|
2020-02-10 21:16:17 +00:00
|
|
|
default: Some(Array.unsafe_get(Data.funds, 0).name),
|
|
|
|
options:
|
|
|
|
Data.funds
|
|
|
|
|> E.A.fmap((r) =>
|
|
|
|
({name: r.name, id: r.name}: Prop.Type.selectOption)
|
|
|
|
)
|
|
|
|
|> Array.to_list,
|
2020-02-10 20:37:12 +00:00
|
|
|
}),
|
|
|
|
(),
|
|
|
|
),
|
|
|
|
TypeWithMetadata.make(
|
2020-02-10 21:16:17 +00:00
|
|
|
~name=dayKey,
|
2020-02-10 20:37:12 +00:00
|
|
|
~type_=
|
|
|
|
DateTime({
|
|
|
|
default:
|
|
|
|
Some(
|
|
|
|
MomentRe.Moment.add(
|
|
|
|
~duration=MomentRe.duration(5., `years),
|
|
|
|
MomentRe.momentNow(),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
min:
|
|
|
|
Some(
|
|
|
|
MomentRe.Moment.subtract(
|
|
|
|
~duration=MomentRe.duration(20., `years),
|
|
|
|
MomentRe.momentNow(),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
max:
|
|
|
|
Some(
|
|
|
|
MomentRe.Moment.add(
|
|
|
|
~duration=MomentRe.duration(20., `years),
|
|
|
|
MomentRe.momentNow(),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
}),
|
|
|
|
(),
|
|
|
|
),
|
|
|
|
TypeWithMetadata.currentYear,
|
|
|
|
TypeWithMetadata.make(
|
2020-02-10 21:16:17 +00:00
|
|
|
~name=outputKey,
|
2020-02-10 20:37:12 +00:00
|
|
|
~type_=
|
|
|
|
SelectSingle({
|
|
|
|
default: Some("Output"),
|
|
|
|
options: [
|
2020-02-17 19:45:32 +00:00
|
|
|
{name: "Donations", id: "donations"},
|
|
|
|
{name: "Funding", id: "funding"},
|
|
|
|
{name: "Closing", id: "exists"},
|
2020-02-10 20:37:12 +00:00
|
|
|
],
|
|
|
|
}),
|
|
|
|
(),
|
|
|
|
),
|
2020-02-13 21:24:47 +00:00
|
|
|
TypeWithMetadata.make(
|
2020-02-13 22:04:13 +00:00
|
|
|
~name="Conditionals",
|
|
|
|
~id="conditionals",
|
2020-02-13 21:24:47 +00:00
|
|
|
~type_=
|
|
|
|
Conditionals(
|
2020-02-13 22:04:13 +00:00
|
|
|
Prop.Type.makeConditionals(
|
|
|
|
[||],
|
|
|
|
[|"Global Existential Event"|],
|
|
|
|
),
|
2020-02-13 21:24:47 +00:00
|
|
|
),
|
|
|
|
(),
|
|
|
|
),
|
2020-02-10 20:37:12 +00:00
|
|
|
|],
|
|
|
|
outputTypes: [||],
|
|
|
|
run,
|
|
|
|
};
|
2020-02-13 21:24:47 +00:00
|
|
|
};
|