openalgo-script 0.6.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +105 -0
- package/README.md +12 -12
- package/dist/core/engine/channels.js +2 -2
- package/dist/core/engine/channels.js.map +1 -1
- package/dist/core/engine/engine.js +2 -3
- package/dist/core/engine/engine.js.map +1 -1
- package/dist/core/engine/library/maths.js +2 -2
- package/dist/core/engine/library/maths.js.map +1 -1
- package/dist/core/engine/machine.js +5 -5
- package/dist/core/engine/machine.js.map +1 -1
- package/dist/core/engine/memory.js +2 -2
- package/dist/core/engine/memory.js.map +1 -1
- package/dist/core/engine/registers.js +2 -2
- package/dist/core/engine/registers.js.map +1 -1
- package/dist/core/engine/values/index.d.ts +1 -1
- package/dist/core/engine/values/index.d.ts.map +1 -1
- package/dist/core/engine/values/index.js +1 -1
- package/dist/core/engine/values/index.js.map +1 -1
- package/dist/core/engine/values/value.d.ts +2 -0
- package/dist/core/engine/values/value.d.ts.map +1 -1
- package/dist/core/engine/values/value.js +4 -0
- package/dist/core/engine/values/value.js.map +1 -1
- package/dist/core/stdlib/averages/exponential.d.ts.map +1 -1
- package/dist/core/stdlib/averages/exponential.js +3 -6
- package/dist/core/stdlib/averages/exponential.js.map +1 -1
- package/dist/core/stdlib/averages/gaussian.d.ts +15 -0
- package/dist/core/stdlib/averages/gaussian.d.ts.map +1 -0
- package/dist/core/stdlib/averages/gaussian.js +55 -0
- package/dist/core/stdlib/averages/gaussian.js.map +1 -0
- package/dist/core/stdlib/averages/shaped.d.ts +2 -6
- package/dist/core/stdlib/averages/shaped.d.ts.map +1 -1
- package/dist/core/stdlib/averages/shaped.js +8 -22
- package/dist/core/stdlib/averages/shaped.js.map +1 -1
- package/dist/core/stdlib/maths/arithmetic.d.ts.map +1 -1
- package/dist/core/stdlib/maths/arithmetic.js +2 -1
- package/dist/core/stdlib/maths/arithmetic.js.map +1 -1
- package/dist/core/stdlib/maths/elementary.d.ts +3 -20
- package/dist/core/stdlib/maths/elementary.d.ts.map +1 -1
- package/dist/core/stdlib/maths/elementary.js +17 -13
- package/dist/core/stdlib/maths/elementary.js.map +1 -1
- package/dist/core/stdlib/maths/hypot.d.ts +8 -0
- package/dist/core/stdlib/maths/hypot.d.ts.map +1 -0
- package/dist/core/stdlib/maths/hypot.js +68 -0
- package/dist/core/stdlib/maths/hypot.js.map +1 -0
- package/dist/core/stdlib/maths/power.d.ts +3 -0
- package/dist/core/stdlib/maths/power.d.ts.map +1 -0
- package/dist/core/stdlib/maths/power.js +83 -0
- package/dist/core/stdlib/maths/power.js.map +1 -0
- package/dist/core/stdlib/maths/transcendental.d.ts +15 -0
- package/dist/core/stdlib/maths/transcendental.d.ts.map +1 -0
- package/dist/core/stdlib/maths/transcendental.js +185 -0
- package/dist/core/stdlib/maths/transcendental.js.map +1 -0
- package/dist/core/stdlib/maths/trigonometric.d.ts +4 -0
- package/dist/core/stdlib/maths/trigonometric.d.ts.map +1 -0
- package/dist/core/stdlib/maths/trigonometric.js +196 -0
- package/dist/core/stdlib/maths/trigonometric.js.map +1 -0
- package/dist/core/stdlib/series/conditions.d.ts +2 -4
- package/dist/core/stdlib/series/conditions.d.ts.map +1 -1
- package/dist/core/stdlib/series/conditions.js +9 -13
- package/dist/core/stdlib/series/conditions.js.map +1 -1
- package/dist/core/stdlib/series/statistics.d.ts.map +1 -1
- package/dist/core/stdlib/series/statistics.js +2 -0
- package/dist/core/stdlib/series/statistics.js.map +1 -1
- package/dist/core/stdlib/values/history.d.ts +26 -0
- package/dist/core/stdlib/values/history.d.ts.map +1 -0
- package/dist/core/stdlib/values/history.js +52 -0
- package/dist/core/stdlib/values/history.js.map +1 -0
- package/dist/core/stdlib/values/index.d.ts +1 -0
- package/dist/core/stdlib/values/index.d.ts.map +1 -1
- package/dist/core/stdlib/values/index.js +1 -0
- package/dist/core/stdlib/values/index.js.map +1 -1
- package/dist/core/stdlib/values/lookback.d.ts +4 -1
- package/dist/core/stdlib/values/lookback.d.ts.map +1 -1
- package/dist/core/stdlib/values/lookback.js +48 -45
- package/dist/core/stdlib/values/lookback.js.map +1 -1
- package/dist/core/stdlib/values/region.d.ts +6 -5
- package/dist/core/stdlib/values/region.d.ts.map +1 -1
- package/dist/core/stdlib/values/region.js +3 -3
- package/dist/core/stdlib/values/region.js.map +1 -1
- package/dist/core/stdlib/volatility/measures.d.ts.map +1 -1
- package/dist/core/stdlib/volatility/measures.js +6 -4
- package/dist/core/stdlib/volatility/measures.js.map +1 -1
- package/dist/core/version/version.generated.d.ts +1 -1
- package/dist/core/version/version.generated.js +1 -1
- package/package.json +9 -1
- package/src/core/engine/channels.ts +2 -2
- package/src/core/engine/engine.ts +3 -3
- package/src/core/engine/library/maths.ts +2 -2
- package/src/core/engine/machine.ts +5 -5
- package/src/core/engine/memory.ts +2 -2
- package/src/core/engine/registers.ts +2 -2
- package/src/core/engine/values/index.ts +1 -0
- package/src/core/engine/values/value.ts +5 -0
- package/src/core/stdlib/averages/exponential.ts +3 -4
- package/src/core/stdlib/averages/gaussian.ts +52 -0
- package/src/core/stdlib/averages/shaped.ts +8 -21
- package/src/core/stdlib/maths/arithmetic.ts +2 -1
- package/src/core/stdlib/maths/elementary.ts +20 -33
- package/src/core/stdlib/maths/hypot.ts +63 -0
- package/src/core/stdlib/maths/power.ts +57 -0
- package/src/core/stdlib/maths/transcendental.ts +160 -0
- package/src/core/stdlib/maths/trigonometric.ts +160 -0
- package/src/core/stdlib/series/conditions.ts +9 -12
- package/src/core/stdlib/series/statistics.ts +1 -0
- package/src/core/stdlib/values/history.ts +70 -0
- package/src/core/stdlib/values/index.ts +1 -0
- package/src/core/stdlib/values/lookback.ts +51 -47
- package/src/core/stdlib/values/region.ts +7 -5
- package/src/core/stdlib/volatility/measures.ts +6 -4
- package/src/core/version/version.generated.ts +1 -1
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
const WIDTH = 32;
|
|
2
|
+
/** Appending copies at most one short tail, never the contributed prefix. */
|
|
3
|
+
export class ContributionHistory {
|
|
4
|
+
head;
|
|
5
|
+
tail;
|
|
6
|
+
count;
|
|
7
|
+
constructor(head = null, tail = Object.freeze([]), count = 0) {
|
|
8
|
+
this.head = head;
|
|
9
|
+
this.tail = tail;
|
|
10
|
+
this.count = count;
|
|
11
|
+
Object.freeze(this);
|
|
12
|
+
}
|
|
13
|
+
append(value) {
|
|
14
|
+
const full = this.tail.length === WIDTH;
|
|
15
|
+
const head = full ? Object.freeze({ values: this.tail, prior: this.head }) : this.head;
|
|
16
|
+
const tail = Object.freeze(full ? [value] : [...this.tail, value]);
|
|
17
|
+
return new ContributionHistory(head, tail, this.count + 1);
|
|
18
|
+
}
|
|
19
|
+
/** Index chunk references once; each subsequent newest-first read is constant work. */
|
|
20
|
+
view(length) {
|
|
21
|
+
const size = Math.min(length, this.count);
|
|
22
|
+
const chunks = [];
|
|
23
|
+
let remaining = size - this.tail.length;
|
|
24
|
+
let head = this.head;
|
|
25
|
+
while (remaining > 0 && head !== null) {
|
|
26
|
+
chunks.push(head.values);
|
|
27
|
+
head = head.prior;
|
|
28
|
+
remaining -= WIDTH;
|
|
29
|
+
}
|
|
30
|
+
return new ContributionView(this.tail, chunks, size);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/** A transient index into the current window. It is not retained in state. */
|
|
34
|
+
export class ContributionView {
|
|
35
|
+
tail;
|
|
36
|
+
chunks;
|
|
37
|
+
size;
|
|
38
|
+
constructor(tail, chunks, size) {
|
|
39
|
+
this.tail = tail;
|
|
40
|
+
this.chunks = chunks;
|
|
41
|
+
this.size = size;
|
|
42
|
+
}
|
|
43
|
+
at(back) {
|
|
44
|
+
if (back < 0 || back >= this.size || !Number.isInteger(back))
|
|
45
|
+
return null;
|
|
46
|
+
if (back < this.tail.length)
|
|
47
|
+
return this.tail[this.tail.length - 1 - back];
|
|
48
|
+
const before = back - this.tail.length;
|
|
49
|
+
return this.chunks[Math.floor(before / WIDTH)][WIDTH - 1 - before % WIDTH];
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=history.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"history.js","sourceRoot":"","sources":["../../../../src/core/stdlib/values/history.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,6 +2,7 @@ export type { Flag, Flags, Series, Value } from './value.js';
|
|
|
2
2
|
export { NONE, at, isLength, isPresent, result } from './value.js';
|
|
3
3
|
export type { StateField, StateRecord, StateSlot } from './region.js';
|
|
4
4
|
export { copyState, flag, held, newState, queue, slot } from './region.js';
|
|
5
|
+
export { ContributionHistory, ContributionView } from './history.js';
|
|
5
6
|
export type { Tail } from './tail.js';
|
|
6
7
|
export { fold, tailOf } from './tail.js';
|
|
7
8
|
export type { Lookback, Recurrence } from './lookback.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/core/stdlib/values/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAC7D,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEnE,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACtE,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/core/stdlib/values/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAC7D,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEnE,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACtE,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAC3E,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAErE,YAAY,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAEzC,YAAY,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE7D,YAAY,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AACpC,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { NONE, at, isLength, isPresent, result } from './value.js';
|
|
2
2
|
export { copyState, flag, held, newState, queue, slot } from './region.js';
|
|
3
|
+
export { ContributionHistory, ContributionView } from './history.js';
|
|
3
4
|
export { fold, tailOf } from './tail.js';
|
|
4
5
|
export { makeLookback, ring, smoothed } from './lookback.js';
|
|
5
6
|
export { hl2, hlc3, hlcc4, ohlc4 } from './bar.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/core/stdlib/values/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAGnE,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/core/stdlib/values/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAGnE,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAC3E,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAGrE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAGzC,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAG7D,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC"}
|
|
@@ -36,7 +36,7 @@ import type { Value } from './value.js';
|
|
|
36
36
|
export interface Lookback {
|
|
37
37
|
/** Advance by one bar. */
|
|
38
38
|
push(value: Value): void;
|
|
39
|
-
/** True
|
|
39
|
+
/** True after the largest observed length's contributions, present or not. */
|
|
40
40
|
filled(): boolean;
|
|
41
41
|
/** True when the lookback is filled and every bar in it has a value. */
|
|
42
42
|
complete(): boolean;
|
|
@@ -78,6 +78,9 @@ export type Recurrence = (previous: number, value: number) => number;
|
|
|
78
78
|
* next present bar continues from where the last one left off. The alternatives
|
|
79
79
|
* are worse: consuming absence as zero would drag the average toward nothing,
|
|
80
80
|
* and re-seeding would let one missing bar restart a two hundred bar average.
|
|
81
|
+
* Missing lengths also freeze it. Readiness tracks all contributions and the
|
|
82
|
+
* largest observed length, independently from the running value. A valid step
|
|
83
|
+
* still advances that value while a later, larger length hides its output.
|
|
81
84
|
*/
|
|
82
85
|
export declare function smoothed(record: StateRecord, key: string, len: number | null, value: Value, step: Recurrence): Value;
|
|
83
86
|
//# sourceMappingURL=lookback.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lookback.d.ts","sourceRoot":"","sources":["../../../../src/core/stdlib/values/lookback.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"lookback.d.ts","sourceRoot":"","sources":["../../../../src/core/stdlib/values/lookback.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAG/C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAGxC,mDAAmD;AACnD,MAAM,WAAW,QAAQ;IACvB,0BAA0B;IAC1B,IAAI,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACzB,8EAA8E;IAC9E,MAAM,IAAI,OAAO,CAAC;IAClB,wEAAwE;IACxE,QAAQ,IAAI,OAAO,CAAC;IACpB,8DAA8D;IAC9D,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK,CAAC;IACxB,kDAAkD;IAClD,YAAY,IAAI,MAAM,CAAC;IACvB,uFAAuF;IACvF,GAAG,IAAI,KAAK,CAAC;IACb,yFAAyF;IACzF,UAAU,IAAI,KAAK,CAAC;IACpB,qFAAqF;IACrF,IAAI,IAAI,KAAK,CAAC;CACf;AAED;;;;;;GAMG;AACH,wBAAgB,IAAI,CAAC,MAAM,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,QAAQ,CAenF;AAkDD,mFAAmF;AACnF,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,CAElD;AAED,gFAAgF;AAChF,MAAM,MAAM,UAAU,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;AAErE;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,QAAQ,CACtB,MAAM,EAAE,WAAW,EACnB,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,MAAM,GAAG,IAAI,EAClB,KAAK,EAAE,KAAK,EACZ,IAAI,EAAE,UAAU,GACf,KAAK,CAsCP"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { newState } from './region.js';
|
|
1
|
+
import { newState, slot } from './region.js';
|
|
2
|
+
import { ContributionHistory } from './history.js';
|
|
2
3
|
import { NONE, isLength, isPresent, result } from './value.js';
|
|
3
4
|
/**
|
|
4
5
|
* A lookback of `len` bars, held in a region under `key`.
|
|
@@ -9,47 +10,24 @@ import { NONE, isLength, isPresent, result } from './value.js';
|
|
|
9
10
|
*/
|
|
10
11
|
export function ring(record, key, len) {
|
|
11
12
|
const size = len !== null && isLength(len) ? len : 0;
|
|
12
|
-
const bars = `${key}:
|
|
13
|
-
const
|
|
14
|
-
const seenKey = `${key}:s`;
|
|
13
|
+
const bars = `${key}:h`;
|
|
14
|
+
const maximumKey = `${key}:m`;
|
|
15
15
|
const held = record[bars];
|
|
16
|
-
let
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
record[
|
|
24
|
-
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
};
|
|
30
|
-
const index = (back) => {
|
|
31
|
-
const from = count(nextKey) - 1 - back;
|
|
32
|
-
return ((from % size) + size) % size;
|
|
33
|
-
};
|
|
16
|
+
let history = held instanceof ContributionHistory ? held : new ContributionHistory();
|
|
17
|
+
const before = record[maximumKey];
|
|
18
|
+
const maximum = Math.max(typeof before === 'number' ? before : 0, size);
|
|
19
|
+
record[maximumKey] = maximum;
|
|
20
|
+
let view = history.view(size);
|
|
21
|
+
return lookback(size, (value) => {
|
|
22
|
+
history = history.append(value);
|
|
23
|
+
record[bars] = history;
|
|
24
|
+
view = history.view(size);
|
|
25
|
+
}, () => size > 0 && history.count >= maximum, (back) => view.at(back));
|
|
26
|
+
}
|
|
27
|
+
/** The arithmetic is shared so fixed-length accumulation keeps its exact order. */
|
|
28
|
+
function lookback(size, push, filled, at) {
|
|
34
29
|
const lookback = {
|
|
35
|
-
push
|
|
36
|
-
if (size === 0)
|
|
37
|
-
return;
|
|
38
|
-
items[count(nextKey)] = value;
|
|
39
|
-
const next = count(nextKey) + 1;
|
|
40
|
-
record[nextKey] = next === size ? 0 : next;
|
|
41
|
-
if (count(seenKey) < size)
|
|
42
|
-
record[seenKey] = count(seenKey) + 1;
|
|
43
|
-
},
|
|
44
|
-
filled() {
|
|
45
|
-
return size > 0 && count(seenKey) === size;
|
|
46
|
-
},
|
|
47
|
-
at(back) {
|
|
48
|
-
if (size === 0 || back < 0 || back >= size)
|
|
49
|
-
return NONE;
|
|
50
|
-
const value = items[index(back)];
|
|
51
|
-
return typeof value === 'number' ? value : NONE;
|
|
52
|
-
},
|
|
30
|
+
push, filled, at,
|
|
53
31
|
presentCount() {
|
|
54
32
|
let counted = 0;
|
|
55
33
|
for (let back = size - 1; back >= 0; back -= 1) {
|
|
@@ -108,27 +86,52 @@ export function makeLookback(len) {
|
|
|
108
86
|
* next present bar continues from where the last one left off. The alternatives
|
|
109
87
|
* are worse: consuming absence as zero would drag the average toward nothing,
|
|
110
88
|
* and re-seeding would let one missing bar restart a two hundred bar average.
|
|
89
|
+
* Missing lengths also freeze it. Readiness tracks all contributions and the
|
|
90
|
+
* largest observed length, independently from the running value. A valid step
|
|
91
|
+
* still advances that value while a later, larger length hides its output.
|
|
111
92
|
*/
|
|
112
93
|
export function smoothed(record, key, len, value, step) {
|
|
113
|
-
const
|
|
94
|
+
const countKey = `${key}:n`;
|
|
95
|
+
const maximumKey = `${key}:m`;
|
|
96
|
+
const historyKey = `${key}~:h`;
|
|
114
97
|
const runningKey = `${key}:r`;
|
|
115
98
|
const startedKey = `${key}:o`;
|
|
99
|
+
const valid = len !== null && isLength(len);
|
|
100
|
+
const count = slot(record, countKey, 0) + 1;
|
|
101
|
+
const maximum = Math.max(slot(record, maximumKey, 0), valid ? len : 0);
|
|
102
|
+
record[countKey] = count;
|
|
103
|
+
record[maximumKey] = maximum;
|
|
116
104
|
if (record[startedKey] !== true) {
|
|
117
|
-
|
|
118
|
-
const
|
|
105
|
+
const held = record[historyKey];
|
|
106
|
+
const before = held instanceof ContributionHistory ? held : new ContributionHistory();
|
|
107
|
+
const history = before.append(value);
|
|
108
|
+
record[historyKey] = history;
|
|
109
|
+
if (!valid || count < maximum)
|
|
110
|
+
return NONE;
|
|
111
|
+
const view = history.view(len);
|
|
112
|
+
let total = 0;
|
|
113
|
+
for (let back = len - 1; back >= 0; back -= 1) {
|
|
114
|
+
const next = view.at(back);
|
|
115
|
+
if (!isPresent(next))
|
|
116
|
+
return NONE;
|
|
117
|
+
total += next;
|
|
118
|
+
}
|
|
119
|
+
const mean = result(total / len);
|
|
119
120
|
if (!isPresent(mean))
|
|
120
121
|
return NONE;
|
|
121
122
|
record[startedKey] = true;
|
|
122
123
|
record[runningKey] = mean;
|
|
124
|
+
// Checkpoints retain their immutable version; this live state needs only scalars.
|
|
125
|
+
delete record[historyKey];
|
|
123
126
|
return result(mean);
|
|
124
127
|
}
|
|
125
|
-
if (!isPresent(value))
|
|
128
|
+
if (!valid || !isPresent(value))
|
|
126
129
|
return NONE;
|
|
127
130
|
const previous = record[runningKey];
|
|
128
131
|
if (typeof previous !== 'number')
|
|
129
132
|
return NONE;
|
|
130
133
|
const next = step(previous, value);
|
|
131
134
|
record[runningKey] = next;
|
|
132
|
-
return result(next);
|
|
135
|
+
return count >= maximum ? result(next) : NONE;
|
|
133
136
|
}
|
|
134
137
|
//# sourceMappingURL=lookback.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lookback.js","sourceRoot":"","sources":["../../../../src/core/stdlib/values/lookback.ts"],"names":[],"mappings":"AAiCA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"lookback.js","sourceRoot":"","sources":["../../../../src/core/stdlib/values/lookback.ts"],"names":[],"mappings":"AAiCA,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAEnD,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAsB/D;;;;;;GAMG;AACH,MAAM,UAAU,IAAI,CAAC,MAAmB,EAAE,GAAW,EAAE,GAAkB;IACvE,MAAM,IAAI,GAAG,GAAG,KAAK,IAAI,IAAI,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACrD,MAAM,IAAI,GAAG,GAAG,GAAG,IAAI,CAAC;IACxB,MAAM,UAAU,GAAG,GAAG,GAAG,IAAI,CAAC;IAC9B,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;IAC1B,IAAI,OAAO,GAAG,IAAI,YAAY,mBAAmB,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,mBAAmB,EAAE,CAAC;IACrF,MAAM,MAAM,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC;IAClC,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;IACxE,MAAM,CAAC,UAAU,CAAC,GAAG,OAAO,CAAC;IAC7B,IAAI,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC9B,OAAO,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,EAAE;QAC9B,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAChC,MAAM,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC;QACvB,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC,EAAE,GAAG,EAAE,CAAC,IAAI,GAAG,CAAC,IAAI,OAAO,CAAC,KAAK,IAAI,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;AAC1E,CAAC;AAED,mFAAmF;AACnF,SAAS,QAAQ,CACf,IAAY,EAAE,IAA4B,EAAE,MAAqB,EACjE,EAA2B;IAE3B,MAAM,QAAQ,GAAa;QACzB,IAAI,EAAE,MAAM,EAAE,EAAE;QAChB,YAAY;YACV,IAAI,OAAO,GAAG,CAAC,CAAC;YAChB,KAAK,IAAI,IAAI,GAAG,IAAI,GAAG,CAAC,EAAE,IAAI,IAAI,CAAC,EAAE,IAAI,IAAI,CAAC,EAAE,CAAC;gBAC/C,IAAI,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;oBAAE,OAAO,IAAI,CAAC,CAAC;YACjD,CAAC;YACD,OAAO,OAAO,CAAC;QACjB,CAAC;QAED,QAAQ;YACN,OAAO,QAAQ,CAAC,MAAM,EAAE,IAAI,QAAQ,CAAC,YAAY,EAAE,KAAK,IAAI,CAAC;QAC/D,CAAC;QAED,GAAG;YACD,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE;gBAAE,OAAO,IAAI,CAAC;YACtC,IAAI,KAAK,GAAG,CAAC,CAAC;YACd,2DAA2D;YAC3D,KAAK,IAAI,IAAI,GAAG,IAAI,GAAG,CAAC,EAAE,IAAI,IAAI,CAAC,EAAE,IAAI,IAAI,CAAC,EAAE,CAAC;gBAC/C,KAAK,IAAI,QAAQ,CAAC,EAAE,CAAC,IAAI,CAAW,CAAC;YACvC,CAAC;YACD,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;QACvB,CAAC;QAED,UAAU;YACR,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE;gBAAE,OAAO,IAAI,CAAC;YACpC,IAAI,KAAK,GAAG,CAAC,CAAC;YACd,KAAK,IAAI,IAAI,GAAG,IAAI,GAAG,CAAC,EAAE,IAAI,IAAI,CAAC,EAAE,IAAI,IAAI,CAAC,EAAE,CAAC;gBAC/C,MAAM,KAAK,GAAG,QAAQ,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;gBAChC,IAAI,SAAS,CAAC,KAAK,CAAC;oBAAE,KAAK,IAAI,KAAK,CAAC;YACvC,CAAC;YACD,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;QACvB,CAAC;QAED,IAAI;YACF,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,EAAE,CAAC;YAC7B,OAAO,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QACxD,CAAC;KACF,CAAC;IAEF,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,YAAY,CAAC,GAAW;IACtC,OAAO,IAAI,CAAC,QAAQ,EAAE,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;AACpC,CAAC;AAKD;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,QAAQ,CACtB,MAAmB,EACnB,GAAW,EACX,GAAkB,EAClB,KAAY,EACZ,IAAgB;IAEhB,MAAM,QAAQ,GAAG,GAAG,GAAG,IAAI,CAAC;IAC5B,MAAM,UAAU,GAAG,GAAG,GAAG,IAAI,CAAC;IAC9B,MAAM,UAAU,GAAG,GAAG,GAAG,KAAK,CAAC;IAC/B,MAAM,UAAU,GAAG,GAAG,GAAG,IAAI,CAAC;IAC9B,MAAM,UAAU,GAAG,GAAG,GAAG,IAAI,CAAC;IAC9B,MAAM,KAAK,GAAG,GAAG,KAAK,IAAI,IAAI,QAAQ,CAAC,GAAG,CAAC,CAAC;IAC5C,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC;IAC5C,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACvE,MAAM,CAAC,QAAQ,CAAC,GAAG,KAAK,CAAC;IACzB,MAAM,CAAC,UAAU,CAAC,GAAG,OAAO,CAAC;IAC7B,IAAI,MAAM,CAAC,UAAU,CAAC,KAAK,IAAI,EAAE,CAAC;QAChC,MAAM,IAAI,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC;QAChC,MAAM,MAAM,GAAG,IAAI,YAAY,mBAAmB,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,mBAAmB,EAAE,CAAC;QACtF,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACrC,MAAM,CAAC,UAAU,CAAC,GAAG,OAAO,CAAC;QAC7B,IAAI,CAAC,KAAK,IAAI,KAAK,GAAG,OAAO;YAAE,OAAO,IAAI,CAAC;QAC3C,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC/B,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,KAAK,IAAI,IAAI,GAAG,GAAG,GAAG,CAAC,EAAE,IAAI,IAAI,CAAC,EAAE,IAAI,IAAI,CAAC,EAAE,CAAC;YAC9C,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;YAC3B,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;gBAAE,OAAO,IAAI,CAAC;YAClC,KAAK,IAAI,IAAI,CAAC;QAChB,CAAC;QACD,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,GAAG,GAAG,CAAC,CAAC;QACjC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC;QAClC,MAAM,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC;QAC1B,MAAM,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC;QAC1B,kFAAkF;QAClF,OAAO,MAAM,CAAC,UAAU,CAAC,CAAC;QAC1B,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC;IACtB,CAAC;IACD,IAAI,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAC7C,MAAM,QAAQ,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC;IACpC,IAAI,OAAO,QAAQ,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IAC9C,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IACnC,MAAM,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC;IAC1B,OAAO,KAAK,IAAI,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AAChD,CAAC"}
|
|
@@ -11,8 +11,8 @@
|
|
|
11
11
|
* is what 6.2 refuses in as many words: an engine does not re-seed an average
|
|
12
12
|
* from history, it puts back the record it copied.
|
|
13
13
|
*
|
|
14
|
-
* So a region is a flat record of
|
|
15
|
-
*
|
|
14
|
+
* So a region is a flat record of scalars, bounded mutable queues and immutable
|
|
15
|
+
* contribution history, and `copyState` is the mechanical copy. Every function in this
|
|
16
16
|
* library is written against one, and the tail form in `tail.ts` is the same
|
|
17
17
|
* step over a region nobody else can reach. That is what lets the one
|
|
18
18
|
* implementation serve both a library call folded over a series and an engine
|
|
@@ -22,15 +22,16 @@
|
|
|
22
22
|
* how a study built from three others keeps one flat record rather than a tree
|
|
23
23
|
* of them.
|
|
24
24
|
*/
|
|
25
|
-
|
|
25
|
+
import type { ContributionHistory } from './history.js';
|
|
26
|
+
/** One scalar field of a state region. */
|
|
26
27
|
export type StateField = number | boolean | string | null;
|
|
27
28
|
/** What a single key holds. */
|
|
28
|
-
export type StateSlot = StateField | StateField[];
|
|
29
|
+
export type StateSlot = StateField | StateField[] | ContributionHistory;
|
|
29
30
|
/** A state region: a flat record, copyable without knowing what owns it. */
|
|
30
31
|
export type StateRecord = Record<string, StateSlot | undefined>;
|
|
31
32
|
/** A region with nothing in it yet, which is what bar 0 finds. */
|
|
32
33
|
export declare function newState(): StateRecord;
|
|
33
|
-
/**
|
|
34
|
+
/** Mutable queues are cloned; immutable history versions are safely shared. */
|
|
34
35
|
export declare function copyState(record: StateRecord): StateRecord;
|
|
35
36
|
/** A number held in a region, with a default for the bar it is first read on. */
|
|
36
37
|
export declare function slot(record: StateRecord, key: string, fallback: number): number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"region.d.ts","sourceRoot":"","sources":["../../../../src/core/stdlib/values/region.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,
|
|
1
|
+
{"version":3,"file":"region.d.ts","sourceRoot":"","sources":["../../../../src/core/stdlib/values/region.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAExD,0CAA0C;AAC1C,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,IAAI,CAAC;AAE1D,+BAA+B;AAC/B,MAAM,MAAM,SAAS,GAAG,UAAU,GAAG,UAAU,EAAE,GAAG,mBAAmB,CAAC;AAExE,4EAA4E;AAC5E,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,SAAS,GAAG,SAAS,CAAC,CAAC;AAEhE,kEAAkE;AAClE,wBAAgB,QAAQ,IAAI,WAAW,CAEtC;AAED,+EAA+E;AAC/E,wBAAgB,SAAS,CAAC,MAAM,EAAE,WAAW,GAAG,WAAW,CAO1D;AAED,iFAAiF;AACjF,wBAAgB,IAAI,CAAC,MAAM,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAG/E;AAED,mEAAmE;AACnE,wBAAgB,IAAI,CAAC,MAAM,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAE9D;AAED;;;;;GAKG;AACH,wBAAgB,KAAK,CAAC,MAAM,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,GAAG,UAAU,EAAE,CAMpE;AAED;;;;;;;GAOG;AACH,wBAAgB,IAAI,CAAC,MAAM,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAGpE"}
|
|
@@ -11,8 +11,8 @@
|
|
|
11
11
|
* is what 6.2 refuses in as many words: an engine does not re-seed an average
|
|
12
12
|
* from history, it puts back the record it copied.
|
|
13
13
|
*
|
|
14
|
-
* So a region is a flat record of
|
|
15
|
-
*
|
|
14
|
+
* So a region is a flat record of scalars, bounded mutable queues and immutable
|
|
15
|
+
* contribution history, and `copyState` is the mechanical copy. Every function in this
|
|
16
16
|
* library is written against one, and the tail form in `tail.ts` is the same
|
|
17
17
|
* step over a region nobody else can reach. That is what lets the one
|
|
18
18
|
* implementation serve both a library call folded over a series and an engine
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
export function newState() {
|
|
27
27
|
return {};
|
|
28
28
|
}
|
|
29
|
-
/**
|
|
29
|
+
/** Mutable queues are cloned; immutable history versions are safely shared. */
|
|
30
30
|
export function copyState(record) {
|
|
31
31
|
const out = {};
|
|
32
32
|
for (const key of Object.keys(record)) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"region.js","sourceRoot":"","sources":["../../../../src/core/stdlib/values/region.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;
|
|
1
|
+
{"version":3,"file":"region.js","sourceRoot":"","sources":["../../../../src/core/stdlib/values/region.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAaH,kEAAkE;AAClE,MAAM,UAAU,QAAQ;IACtB,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,SAAS,CAAC,MAAmB;IAC3C,MAAM,GAAG,GAAgB,EAAE,CAAC;IAC5B,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QACtC,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;QAC1B,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IACvD,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,IAAI,CAAC,MAAmB,EAAE,GAAW,EAAE,QAAgB;IACrE,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;IAC1B,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC;AACtD,CAAC;AAED,mEAAmE;AACnE,MAAM,UAAU,IAAI,CAAC,MAAmB,EAAE,GAAW;IACnD,OAAO,MAAM,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC;AAC9B,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,KAAK,CAAC,MAAmB,EAAE,GAAW;IACpD,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;IACzB,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACrC,MAAM,IAAI,GAAiB,EAAE,CAAC;IAC9B,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;IACnB,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,IAAI,CAAC,MAAmB,EAAE,GAAW;IACnD,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;IAC1B,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;AAClD,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"measures.d.ts","sourceRoot":"","sources":["../../../../src/core/stdlib/volatility/measures.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"measures.d.ts","sourceRoot":"","sources":["../../../../src/core/stdlib/volatility/measures.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAKhF,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;AAItC;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,QAAQ,CACtB,KAAK,EAAE,WAAW,EAClB,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,GAAG,EACR,GAAG,EAAE,MAAM,GAAG,IAAI,GACjB,KAAK,CAWP;AAED,6BAA6B;AAC7B,wBAAgB,QAAQ,CAAC,GAAG,SAAK,GAAG,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,CAEnD;AAED,sCAAsC;AACtC,wBAAgB,IAAI,CAAC,IAAI,EAAE,SAAS,GAAG,EAAE,EAAE,GAAG,SAAK,GAAG,KAAK,EAAE,CAE5D;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,MAAM,CACpB,KAAK,EAAE,WAAW,EAClB,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,KAAK,EACZ,GAAG,EAAE,MAAM,GAAG,IAAI,EAClB,cAAc,EAAE,MAAM,GAAG,IAAI,GAC5B,KAAK,CASP;AAED,gDAAgD;AAChD,wBAAgB,MAAM,CAAC,GAAG,SAAK,EAAE,cAAc,SAAM,GAAG,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,CAEzE;AAED,0DAA0D;AAC1D,wBAAgB,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,SAAK,EAAE,cAAc,SAAM,GAAG,KAAK,EAAE,CAEvE"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { NONE, fold, isPresent, result, tailOf } from '../values/index.js';
|
|
2
2
|
import { extremeStep, historyStep, sumStep } from '../series/index.js';
|
|
3
|
+
import { log, log10 } from '../maths/index.js';
|
|
3
4
|
import { gapOf, trueRangeOf } from './range.js';
|
|
4
5
|
import { stdevStep } from './deviation.js';
|
|
5
6
|
/**
|
|
@@ -26,10 +27,11 @@ export function chopStep(state, key, gap, len) {
|
|
|
26
27
|
if (!isPresent(distance) || !isPresent(upper) || !isPresent(lower))
|
|
27
28
|
return NONE;
|
|
28
29
|
const span = upper - lower;
|
|
29
|
-
const scale =
|
|
30
|
-
if (!(span > 0) || !(distance > 0) || scale === 0)
|
|
30
|
+
const scale = log10(len);
|
|
31
|
+
if (!(span > 0) || !(distance > 0) || !isPresent(scale) || scale === 0)
|
|
31
32
|
return NONE;
|
|
32
|
-
|
|
33
|
+
const travelled = log10(distance / span);
|
|
34
|
+
return isPresent(travelled) ? result((100 * travelled) / scale) : NONE;
|
|
33
35
|
}
|
|
34
36
|
/** `chop(len)` as a tail. */
|
|
35
37
|
export function chopTail(len = 14) {
|
|
@@ -55,7 +57,7 @@ export function hvStep(state, key, value, len, periodsPerYear) {
|
|
|
55
57
|
const previous = historyStep(state, `${key}h`, value, 1);
|
|
56
58
|
let logReturn = NONE;
|
|
57
59
|
if (isPresent(value) && isPresent(previous) && value > 0 && previous > 0) {
|
|
58
|
-
logReturn =
|
|
60
|
+
logReturn = log(value / previous);
|
|
59
61
|
}
|
|
60
62
|
const deviation = stdevStep(state, `${key}q`, logReturn, len, false);
|
|
61
63
|
if (!isPresent(deviation) || periodsPerYear === null || !(periodsPerYear > 0))
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"measures.js","sourceRoot":"","sources":["../../../../src/core/stdlib/volatility/measures.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC3E,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"measures.js","sourceRoot":"","sources":["../../../../src/core/stdlib/volatility/measures.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// VERSION comes from package.json and COMPILED_FORMAT_VERSION from
|
|
4
4
|
// spec/compiled-program.md, so neither can drift from the thing it names.
|
|
5
5
|
/** This build's package version. The release refuses to publish unless the tag, the manifest and this agree. */
|
|
6
|
-
export const VERSION = "0.
|
|
6
|
+
export const VERSION = "0.7.0";
|
|
7
7
|
/**
|
|
8
8
|
* The compiled program format this compiler emits.
|
|
9
9
|
*
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openalgo-script",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "An open trading language. Write a study or a strategy once, plot it, backtest it, trade it.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"trading",
|
|
@@ -50,6 +50,14 @@
|
|
|
50
50
|
"src"
|
|
51
51
|
],
|
|
52
52
|
"scripts": {
|
|
53
|
+
"audit:stateful": "node --disallow-code-generation-from-strings scripts/check-stateful-numerics.mjs",
|
|
54
|
+
"audit:stateful:report": "node --disallow-code-generation-from-strings scripts/check-stateful-numerics.mjs --report-only",
|
|
55
|
+
"audit:stateless": "node --disallow-code-generation-from-strings scripts/check-stateless-numerics.mjs",
|
|
56
|
+
"audit:stateless:report": "node --disallow-code-generation-from-strings scripts/check-stateless-numerics.mjs --report-only",
|
|
57
|
+
"audit:varying": "node --disallow-code-generation-from-strings scripts/check-varying-numerics.mjs",
|
|
58
|
+
"audit:varying:report": "node --disallow-code-generation-from-strings scripts/check-varying-numerics.mjs --report-only",
|
|
59
|
+
"audit:numerics": "npm run test:audit && npm run audit:stateful && npm run audit:stateless && npm run audit:varying",
|
|
60
|
+
"test:audit": "node --disallow-code-generation-from-strings --test scripts/test-stateful-numerics.mjs scripts/test-stateless-numerics.mjs scripts/test-varying-numerics.mjs",
|
|
53
61
|
"check:names": "node --disallow-code-generation-from-strings scripts/check-names.mjs",
|
|
54
62
|
"check:no-eval": "npm run build && npm run build:test && node --disallow-code-generation-from-strings scripts/check-no-eval.mjs",
|
|
55
63
|
"check:examples": "node --disallow-code-generation-from-strings scripts/check-examples.mjs",
|
|
@@ -29,7 +29,7 @@ import type { Span } from '../span/index.js';
|
|
|
29
29
|
import type { Effect } from './library/index.js';
|
|
30
30
|
import type { Channel } from './types.js';
|
|
31
31
|
import type { Value } from './values/index.js';
|
|
32
|
-
import { ABSENT } from './values/index.js';
|
|
32
|
+
import { ABSENT, storedValue } from './values/index.js';
|
|
33
33
|
|
|
34
34
|
/** A library call with an effect, held until the bar is decided. */
|
|
35
35
|
export interface PendingEffect {
|
|
@@ -89,7 +89,7 @@ export class Channels {
|
|
|
89
89
|
|
|
90
90
|
/** `EMIT`: the last write on a bar is the one that counts. */
|
|
91
91
|
write(channel: number, value: Value): void {
|
|
92
|
-
this.current[channel] = value;
|
|
92
|
+
this.current[channel] = storedValue(value);
|
|
93
93
|
}
|
|
94
94
|
|
|
95
95
|
read(channel: number): Value {
|
|
@@ -55,7 +55,7 @@ import type { BarColumns } from './bar-source.js';
|
|
|
55
55
|
import { barMinutesOf } from './timeframe.js';
|
|
56
56
|
import { RequestSet } from './requests.js';
|
|
57
57
|
import type { Value } from './values/index.js';
|
|
58
|
-
import { Heap } from './values/index.js';
|
|
58
|
+
import { Heap, storedValue } from './values/index.js';
|
|
59
59
|
import { drawingsIn } from './drawings.js';
|
|
60
60
|
import type { Drawing } from './drawings.js';
|
|
61
61
|
import type { BarResult, RunResult } from './results.js';
|
|
@@ -383,8 +383,8 @@ export class Engine {
|
|
|
383
383
|
// Step 5. An input's value and a grid's handle land in their slots here,
|
|
384
384
|
// and nothing is resolved: that happened once, at load.
|
|
385
385
|
for (const input of this.inputs) {
|
|
386
|
-
slots[input.slot] =
|
|
387
|
-
input.field === undefined ? input.value : barField(input.field, bar, this.facts);
|
|
386
|
+
slots[input.slot] = storedValue(
|
|
387
|
+
input.field === undefined ? input.value : barField(input.field, bar, this.facts));
|
|
388
388
|
}
|
|
389
389
|
this.grids.fill(slots);
|
|
390
390
|
|
|
@@ -44,7 +44,7 @@ import {
|
|
|
44
44
|
toRadians,
|
|
45
45
|
trunc,
|
|
46
46
|
} from '../../stdlib/index.js';
|
|
47
|
-
import { isNumber } from '../values/index.js';
|
|
47
|
+
import { isNumber, storedValue } from '../values/index.js';
|
|
48
48
|
import { entry, numberAt, valueAt, wholeAt } from './binding.js';
|
|
49
49
|
import type { ManifestEntry } from './binding.js';
|
|
50
50
|
|
|
@@ -125,7 +125,7 @@ export const MATHS_ENTRIES: readonly ManifestEntry[] = [
|
|
|
125
125
|
entry('isNone', 'x', (_ctx, args) => valueAt(args, 0) === null),
|
|
126
126
|
entry('orElse', 'x fallback', (_ctx, args) => {
|
|
127
127
|
const value = valueAt(args, 0);
|
|
128
|
-
return value === null ? valueAt(args, 1) : value;
|
|
128
|
+
return storedValue(value === null ? valueAt(args, 1) : value);
|
|
129
129
|
}),
|
|
130
130
|
// `toBool(x)`: absence to false, a bool to itself. A number is a type error
|
|
131
131
|
// the checker refuses, so an engine that reaches one is looking at a program
|
|
@@ -62,7 +62,7 @@ import type { Ops } from './operations.js';
|
|
|
62
62
|
import type { Registers } from './registers.js';
|
|
63
63
|
import type { CompiledProgram, Instruction, Position } from './types.js';
|
|
64
64
|
import type { Heap, Value } from './values/index.js';
|
|
65
|
-
import { ABSENT, reference } from './values/index.js';
|
|
65
|
+
import { ABSENT, reference, storedValue } from './values/index.js';
|
|
66
66
|
|
|
67
67
|
/** Everything the interpreter is handed once, at load. */
|
|
68
68
|
export interface MachineParts {
|
|
@@ -201,7 +201,7 @@ export class Machine {
|
|
|
201
201
|
|
|
202
202
|
switch (instruction[0]) {
|
|
203
203
|
case 'CONST':
|
|
204
|
-
stack.push(constantValueOf(this.parts.program.consts[instruction[1] as number]));
|
|
204
|
+
stack.push(storedValue(constantValueOf(this.parts.program.consts[instruction[1] as number])));
|
|
205
205
|
break;
|
|
206
206
|
case 'DUP':
|
|
207
207
|
stack.push(stack[stack.length - 1] ?? ABSENT);
|
|
@@ -213,7 +213,7 @@ export class Machine {
|
|
|
213
213
|
stack.push(frame.slots[instruction[1] as number] ?? ABSENT);
|
|
214
214
|
break;
|
|
215
215
|
case 'STORE':
|
|
216
|
-
frame.slots[instruction[1] as number] = pop(stack);
|
|
216
|
+
frame.slots[instruction[1] as number] = storedValue(pop(stack));
|
|
217
217
|
break;
|
|
218
218
|
case 'CELL_INIT':
|
|
219
219
|
if (memory.initialise(frame.cellBase + (instruction[1] as number))) {
|
|
@@ -405,7 +405,7 @@ export class Machine {
|
|
|
405
405
|
|
|
406
406
|
this.ctx.state =
|
|
407
407
|
state < 0 ? NO_STATE : this.parts.memory.region(this.frame.stateBase + state);
|
|
408
|
-
stack.push(of.call(this.ctx, args));
|
|
408
|
+
stack.push(storedValue(of.call(this.ctx, args)));
|
|
409
409
|
}
|
|
410
410
|
|
|
411
411
|
/** `CALL_FN`: everything it needs is in the call site, 4.10. */
|
|
@@ -424,7 +424,7 @@ export class Machine {
|
|
|
424
424
|
call.series,
|
|
425
425
|
fnPositions[call.fn] ?? [],
|
|
426
426
|
);
|
|
427
|
-
for (let i = 0; i < args.length; i += 1) frame.slots[i] = args[i] ?? ABSENT;
|
|
427
|
+
for (let i = 0; i < args.length; i += 1) frame.slots[i] = storedValue(args[i] ?? ABSENT);
|
|
428
428
|
this.callers.push(this.frame);
|
|
429
429
|
this.frame = frame;
|
|
430
430
|
}
|
|
@@ -27,7 +27,7 @@ import type { StateRecord } from './library/index.js';
|
|
|
27
27
|
import { copyState } from './library/index.js';
|
|
28
28
|
import type { Cell, StateRegion } from './types.js';
|
|
29
29
|
import type { Value } from './values/index.js';
|
|
30
|
-
import { ABSENT } from './values/index.js';
|
|
30
|
+
import { ABSENT, storedValue } from './values/index.js';
|
|
31
31
|
|
|
32
32
|
interface CellSnapshot {
|
|
33
33
|
readonly value: Value;
|
|
@@ -71,7 +71,7 @@ export class Memory {
|
|
|
71
71
|
|
|
72
72
|
store(cell: number, value: Value): void {
|
|
73
73
|
this.recordCell(cell);
|
|
74
|
-
this.values[cell] = value;
|
|
74
|
+
this.values[cell] = storedValue(value);
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
/** The region a `CALL_LIB` names, created on first use and kept across bars. */
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
* reaches the array.
|
|
20
20
|
*/
|
|
21
21
|
import type { Value } from './values/index.js';
|
|
22
|
-
import { ABSENT } from './values/index.js';
|
|
22
|
+
import { ABSENT, storedValue } from './values/index.js';
|
|
23
23
|
|
|
24
24
|
export class Registers {
|
|
25
25
|
private readonly histories: Value[][];
|
|
@@ -51,7 +51,7 @@ export class Registers {
|
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
set(register: number, value: Value): void {
|
|
54
|
-
this.current[register] = value;
|
|
54
|
+
this.current[register] = storedValue(value);
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
/** `SLOAD`: the register's value for the bar being executed. */
|
|
@@ -89,6 +89,11 @@ export function numberValue(x: number): Value {
|
|
|
89
89
|
return x === 0 ? 0 : x;
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
+
/** Normalise numeric zero at a store or identity result, preserving every other tag. */
|
|
93
|
+
export function storedValue(value: Value): Value {
|
|
94
|
+
return typeof value === 'number' && value === 0 ? 0 : value;
|
|
95
|
+
}
|
|
96
|
+
|
|
92
97
|
/** The name of a value's tag, for a diagnostic that has to say what it found. */
|
|
93
98
|
export function tagOf(value: Value): string {
|
|
94
99
|
if (value === null) return 'none';
|