Skip to content

Commit e5ca1aa

Browse files
committed
ama failed test but working prototype
1 parent 0e1d243 commit e5ca1aa

File tree

4 files changed

+63688
-180227
lines changed

4 files changed

+63688
-180227
lines changed

src/ama.ts

Lines changed: 25 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -3,67 +3,51 @@ import { CircularBuffer } from './providers/circular-buffer';
33
export class AMA {
44
private circular: CircularBuffer;
55
private sumNoise = 0;
6-
private prevAMA: number | null = null;
6+
private prevPrice: number;
7+
private prevAMA: number;
78
private nfastend: number;
89
private nslowend: number;
910

1011
constructor(length: number, fastend: number = 4, slowend: number = 30) {
1112
this.circular = new CircularBuffer(length);
1213
this.nfastend = 2 / (fastend + 1);
1314
this.nslowend = 2 / (slowend + 1);
15+
this.prevPrice = 0; // Можно инициализировать значением, например, первым полученным значением цены
16+
this.prevAMA = 0; // Аналогично
1417
}
1518

1619
nextValue(price: number) {
1720
// Add the new value to the circular buffer and get the noise
18-
const noise = this.circular.push(Math.abs(price - (this.circular.peek() ?? price)));
19-
20-
// Sum of absolute price differences (noise)
21-
this.sumNoise += noise;
21+
const prevPrice = this.prevPrice;
22+
const priceChange = Math.abs(price - prevPrice);
23+
const prevChange = this.circular.push(priceChange) ?? 0;
24+
this.sumNoise += priceChange - (this.circular.filled ? prevChange : 0);
2225

2326
if (!this.circular.filled) {
24-
// Not enough data to calculate yet
27+
// Not enough data to calculate yet, return undefined
28+
this.prevAMA = price;
29+
this.prevPrice = price; // Update prevPrice
2530
return;
2631
}
2732

28-
this.nextValue = (price: number) => {
29-
const prevPrice = this.circular.peek() ?? price;
30-
const priceChange = Math.abs(price - prevPrice);
31-
this.sumNoise = this.sumNoise - this.circular.push(priceChange) + priceChange;
32-
33-
// Efficiency Ratio (ER)
34-
const signal = Math.abs(price - prevPrice);
35-
const noiseSum = this.sumNoise;
36-
const er = noiseSum !== 0 ? signal / noiseSum : 0;
37-
38-
// Smoothing Constant (SC)
39-
const smooth = Math.pow(er * (this.nfastend - this.nslowend) + this.nslowend, 2);
40-
41-
// AMA Calculation
42-
const currentAMA = this.prevAMA !== null
43-
? this.prevAMA + smooth * (price - this.prevAMA)
44-
: price; // Initialize with the price if first value
45-
46-
this.prevAMA = currentAMA;
47-
return currentAMA;
48-
};
33+
// Efficiency Ratio (ER)
34+
const signal = Math.abs(price - prevPrice);
35+
const noiseSum = this.sumNoise;
36+
const er = noiseSum !== 0 ? signal / noiseSum : 0;
4937

50-
this.momentValue = (price: number) => {
51-
const prevPrice = this.circular.peek() ?? price;
52-
const signal = Math.abs(price - prevPrice);
53-
const noiseSum = this.sumNoise;
54-
const er = noiseSum !== 0 ? signal / noiseSum : 0;
55-
const smooth = Math.pow(er * (this.nfastend - this.nslowend) + this.nslowend, 2);
38+
// Smoothing Constant (SC)
39+
const smooth = Math.pow(er * (this.nfastend - this.nslowend) + this.nslowend, 2);
5640

57-
return this.prevAMA !== null
58-
? this.prevAMA + smooth * (price - this.prevAMA)
59-
: price; // Use price as initial value if no previous AMA
60-
};
41+
// AMA Calculation
42+
const currentAMA = this.prevAMA + smooth * (price - this.prevAMA);
6143

62-
// Calculate the initial AMA value when enough data is available
63-
return price;
44+
this.prevAMA = currentAMA;
45+
this.prevPrice = price; // Update prevPrice
46+
return currentAMA;
6447
}
6548

66-
momentValue(price: number): number {
67-
return price; // Placeholder until `nextValue` is fully initialized
49+
momentValue(): number {
50+
// Return the last calculated AMA value
51+
return this.prevAMA;
6852
}
6953
}

tests/.DS_Store

0 Bytes
Binary file not shown.

tests/ama/ama.spec.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,17 @@ import { data } from './data';
33

44
describe('Adaptive Moving Average', () => {
55
const ama = new AMA(15, 2, 30);
6-
const EPSILON = 0.0001;
6+
const EPSILON = 0.01;
77

88
it('Excel validate', () => {
99
data.forEach((tick, idx) => {
10-
const amaValue = ama.nextValue(Number(tick.Close));
11-
const expected = Number(tick.AMA);
10+
const amaValue = ama.nextValue(tick.c);
11+
const expected = Number(tick.ama);
1212

13-
console.log(amaValue, expected);
13+
if (amaValue) {
14+
expect(Math.abs(amaValue - expected)).toBeLessThan(EPSILON);
15+
}
1416

15-
// expect(amaValue).toBe(Number(expected));
1617
});
1718
});
1819
});

0 commit comments

Comments
 (0)