feat: initial commit
This commit is contained in:
commit
3c3c919a44
59
README.md
Normal file
59
README.md
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
## About
|
||||||
|
|
||||||
|
![](decision-method.png)
|
||||||
|
|
||||||
|
This package contains a series of utilities related to forecasting. It is currently in _alpha_. So far, it only contains utilities related to forecast aggregation, but I may add content related to scoring, charts, etc.
|
||||||
|
|
||||||
|
## Built with
|
||||||
|
|
||||||
|
- vanilla javascript
|
||||||
|
- [Best readme template](https://github.com/othneildrew/Best-README-Template)
|
||||||
|
|
||||||
|
## Getting started
|
||||||
|
|
||||||
|
### Installation
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npm install forecasting
|
||||||
|
```
|
||||||
|
|
||||||
|
### Usage
|
||||||
|
|
||||||
|
#### Aggregation
|
||||||
|
|
||||||
|
```js
|
||||||
|
import {
|
||||||
|
median,
|
||||||
|
arithmeticMean,
|
||||||
|
geometricMean,
|
||||||
|
geometricMeanOfOdds,
|
||||||
|
extremizedGeometricMeanOfOdds,
|
||||||
|
neyman,
|
||||||
|
} from "forecasting";
|
||||||
|
|
||||||
|
let ps = [0.1, 0.2, 0.4, 0.5];
|
||||||
|
console.log(ps);
|
||||||
|
|
||||||
|
console.log(median(ps));
|
||||||
|
console.log(arithmeticMean(ps));
|
||||||
|
console.log(geometricMean(ps));
|
||||||
|
console.log(geometricMeanOfOdds(ps));
|
||||||
|
console.log(extremizedGeometricMeanOfOdds(ps, 1.5)); // 1.5 is the extremization factor
|
||||||
|
console.log(extremizedGeometricMeanOfOdds(ps, 2.5));
|
||||||
|
console.log(neyman(ps));
|
||||||
|
```
|
||||||
|
|
||||||
|
You may also install [@forecasting/aggregation](https://www.npmjs.com/package/@forecasting/aggregation) directly
|
||||||
|
|
||||||
|
#### Scoring
|
||||||
|
|
||||||
|
To be done
|
||||||
|
|
||||||
|
#### Charts
|
||||||
|
|
||||||
|
To be done
|
||||||
|
|
||||||
|
## Roadmap
|
||||||
|
|
||||||
|
- [ ] Do another repository for scoring methods
|
||||||
|
- [ ] Do another repository for charts
|
17
index.js
Normal file
17
index.js
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
import {
|
||||||
|
median,
|
||||||
|
arithmeticMean,
|
||||||
|
geometricMean,
|
||||||
|
geometricMeanOfOdds,
|
||||||
|
extremizedGeometricMeanOfOdds,
|
||||||
|
neyman,
|
||||||
|
} from "@forecasting/aggregation";
|
||||||
|
|
||||||
|
export {
|
||||||
|
median,
|
||||||
|
arithmeticMean,
|
||||||
|
geometricMean,
|
||||||
|
geometricMeanOfOdds,
|
||||||
|
extremizedGeometricMeanOfOdds,
|
||||||
|
neyman,
|
||||||
|
};
|
13
node_modules/.package-lock.json
generated
vendored
Normal file
13
node_modules/.package-lock.json
generated
vendored
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
{
|
||||||
|
"name": "forecasting",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"lockfileVersion": 2,
|
||||||
|
"requires": true,
|
||||||
|
"packages": {
|
||||||
|
"node_modules/@forecasting/aggregation": {
|
||||||
|
"version": "0.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@forecasting/aggregation/-/aggregation-0.0.1.tgz",
|
||||||
|
"integrity": "sha512-N6NwJaHioyJQZwjvbNYQCknegrQoWne5I1TILA0jSu+8xkCIN+16cYumc1hZSYAKTzfBsiQWXZbuubfVMpgXFg=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
55
node_modules/@forecasting/aggregation/README.md
generated
vendored
Normal file
55
node_modules/@forecasting/aggregation/README.md
generated
vendored
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
## About
|
||||||
|
|
||||||
|
![](decision-method.png)
|
||||||
|
|
||||||
|
This package contains a series of utilities for forecast aggregation. It is currently in _alpha_, meaning that the code itself works, but there isn't error checking.
|
||||||
|
|
||||||
|
For an introduction to different aggregation methods, see Jaime Sevilla's [Aggregation](https://forum.effectivealtruism.org/s/hjiBqAJNKhfJFq7kf) series. For an explanation of the neyman method, see [here](https://forum.effectivealtruism.org/s/hjiBqAJNKhfJFq7kf/p/biL94PKfeHmgHY6qe).
|
||||||
|
|
||||||
|
## Built with
|
||||||
|
|
||||||
|
- vanilla javascript
|
||||||
|
- [Best readme template](https://github.com/othneildrew/Best-README-Template)
|
||||||
|
|
||||||
|
## Getting started
|
||||||
|
|
||||||
|
### Installation
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npm install @forecasting/aggregation
|
||||||
|
```
|
||||||
|
|
||||||
|
### Usage
|
||||||
|
|
||||||
|
```js
|
||||||
|
import {
|
||||||
|
median,
|
||||||
|
arithmeticMean,
|
||||||
|
geometricMean,
|
||||||
|
geometricMeanOfOdds,
|
||||||
|
extremizedGeometricMeanOfOdds,
|
||||||
|
neyman,
|
||||||
|
} from "@forecasting/aggregation";
|
||||||
|
|
||||||
|
let ps = [0.1, 0.2, 0.4, 0.5];
|
||||||
|
console.log(ps);
|
||||||
|
|
||||||
|
console.log(median(ps));
|
||||||
|
console.log(arithmeticMean(ps));
|
||||||
|
console.log(geometricMean(ps));
|
||||||
|
console.log(geometricMeanOfOdds(ps));
|
||||||
|
console.log(extremizedGeometricMeanOfOdds(ps, 1.5)); // 1.5 is the extremization factor
|
||||||
|
console.log(extremizedGeometricMeanOfOdds(ps, 2.5));
|
||||||
|
console.log(neyman(ps));
|
||||||
|
```
|
||||||
|
|
||||||
|
## Roadmap
|
||||||
|
|
||||||
|
- [ ] validate probabilities (must be 0<= p <=1)
|
||||||
|
- [ ] Decide on a return type if probabilities are not validated (-1? / null?)
|
||||||
|
- [ ] Write wrapper code for validation
|
||||||
|
- [ ] Validate that array.length > 0
|
||||||
|
- [ ] add weighting? by recency?
|
||||||
|
- [ ] filter outliers?
|
||||||
|
- [ ] Write documentation
|
||||||
|
- [ ] Do another repository for scoring methods
|
BIN
node_modules/@forecasting/aggregation/decision-method.png
generated
vendored
Normal file
BIN
node_modules/@forecasting/aggregation/decision-method.png
generated
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 232 KiB |
64
node_modules/@forecasting/aggregation/index.js
generated
vendored
Normal file
64
node_modules/@forecasting/aggregation/index.js
generated
vendored
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
// Helpers
|
||||||
|
const sum = (array) => array.reduce((a, b) => a + b, 0);
|
||||||
|
const probabilityToOdds = (p) => p / (1 - p);
|
||||||
|
const oddsToProbability = (o) => o / (1 + o);
|
||||||
|
|
||||||
|
// Main functions
|
||||||
|
export const median = (array) => {
|
||||||
|
// needs validation array not empty
|
||||||
|
let midway = Math.floor(array.length);
|
||||||
|
let arrayToBeSorted = [...array];
|
||||||
|
// sorting mutates the array, which I am averse to
|
||||||
|
let arraySorted = arrayToBeSorted.sort((a, b) => a - b);
|
||||||
|
if (midway % 2) {
|
||||||
|
return arraySorted[midway];
|
||||||
|
} else {
|
||||||
|
return (arraySorted[midway - 1] + arraySorted[midway]) / 2;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const arithmeticMean = (array) => {
|
||||||
|
let result = sum(array) / array.length;
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const geometricMean = (array) => {
|
||||||
|
// sum of logs seems more numerically stable than multiplying a lot of numbers 0<=p<=1
|
||||||
|
let arrayAsLog = array.map((p) => Math.log(p));
|
||||||
|
let sumOfLogs = sum(arrayAsLog) / arrayAsLog.length;
|
||||||
|
let result = Math.exp(sumOfLogs);
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const geometricMeanOfOdds = (array) => {
|
||||||
|
let arrayOfOdds = array.map((p) => probabilityToOdds(p));
|
||||||
|
let arrayOfLogsOfOdds = arrayOfOdds.map((p) => Math.log(p));
|
||||||
|
let sumOfLogsOfOdds = sum(arrayOfLogsOfOdds) / arrayOfLogsOfOdds.length;
|
||||||
|
let geomMeanOfOdds = Math.exp(sumOfLogsOfOdds);
|
||||||
|
let result = oddsToProbability(geomMeanOfOdds);
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const extremizedGeometricMeanOfOdds = (
|
||||||
|
array,
|
||||||
|
extremizationParameter = 1.5
|
||||||
|
) => {
|
||||||
|
let arrayOfOdds = array.map((p) => probabilityToOdds(p));
|
||||||
|
let arrayOfLogsOfOdds = arrayOfOdds.map((p) => Math.log(p));
|
||||||
|
let extremizedSumOfLogsOfOdds =
|
||||||
|
(extremizationParameter * sum(arrayOfLogsOfOdds)) /
|
||||||
|
arrayOfLogsOfOdds.length;
|
||||||
|
let extremizedGeomMeanOfOdds = Math.exp(extremizedSumOfLogsOfOdds);
|
||||||
|
let result = oddsToProbability(extremizedGeomMeanOfOdds);
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const neyman = (array) => {
|
||||||
|
let n = array.length;
|
||||||
|
|
||||||
|
let d =
|
||||||
|
(n * (Math.sqrt(3 * Math.pow(n, 2) - 3 * n + 1) - 2)) /
|
||||||
|
(Math.pow(n, 2) - n - 1);
|
||||||
|
let result = extremizedGeometricMeanOfOdds(array, d);
|
||||||
|
return result;
|
||||||
|
};
|
18
node_modules/@forecasting/aggregation/package.json
generated
vendored
Normal file
18
node_modules/@forecasting/aggregation/package.json
generated
vendored
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
{
|
||||||
|
"name": "@forecasting/aggregation",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"description": "Forecasting aggregation utilities",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "node test.js"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"forecasting",
|
||||||
|
"aggregation",
|
||||||
|
"prediction",
|
||||||
|
"prediction",
|
||||||
|
"markets"
|
||||||
|
],
|
||||||
|
"author": "Nuño Sempere",
|
||||||
|
"license": "MIT"
|
||||||
|
}
|
19
node_modules/@forecasting/aggregation/tests.js
generated
vendored
Normal file
19
node_modules/@forecasting/aggregation/tests.js
generated
vendored
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
import {
|
||||||
|
median,
|
||||||
|
arithmeticMean,
|
||||||
|
geometricMean,
|
||||||
|
geometricMeanOfOdds,
|
||||||
|
extremizedGeometricMeanOfOdds,
|
||||||
|
neyman,
|
||||||
|
} from "./index.js";
|
||||||
|
|
||||||
|
let ps = [0.1, 0.2, 0.4, 0.5];
|
||||||
|
console.log(ps);
|
||||||
|
|
||||||
|
console.log(median(ps));
|
||||||
|
console.log(arithmeticMean(ps));
|
||||||
|
console.log(geometricMean(ps));
|
||||||
|
console.log(geometricMeanOfOdds(ps));
|
||||||
|
console.log(extremizedGeometricMeanOfOdds(ps, 1.5));
|
||||||
|
console.log(extremizedGeometricMeanOfOdds(ps, 2.5));
|
||||||
|
console.log(neyman(ps));
|
28
package-lock.json
generated
Normal file
28
package-lock.json
generated
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
{
|
||||||
|
"name": "forecasting",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"lockfileVersion": 2,
|
||||||
|
"requires": true,
|
||||||
|
"packages": {
|
||||||
|
"": {
|
||||||
|
"name": "forecasting",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"@forecasting/aggregation": "^0.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@forecasting/aggregation": {
|
||||||
|
"version": "0.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@forecasting/aggregation/-/aggregation-0.0.1.tgz",
|
||||||
|
"integrity": "sha512-N6NwJaHioyJQZwjvbNYQCknegrQoWne5I1TILA0jSu+8xkCIN+16cYumc1hZSYAKTzfBsiQWXZbuubfVMpgXFg=="
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@forecasting/aggregation": {
|
||||||
|
"version": "0.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@forecasting/aggregation/-/aggregation-0.0.1.tgz",
|
||||||
|
"integrity": "sha512-N6NwJaHioyJQZwjvbNYQCknegrQoWne5I1TILA0jSu+8xkCIN+16cYumc1hZSYAKTzfBsiQWXZbuubfVMpgXFg=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
18
package.json
Normal file
18
package.json
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
{
|
||||||
|
"name": "forecasting",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"description": "Forecasting related utilities.",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"forecasting",
|
||||||
|
"prediction"
|
||||||
|
],
|
||||||
|
"author": "Nuño Sempere",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"@forecasting/aggregation": "^0.0.1"
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user