-
Notifications
You must be signed in to change notification settings - Fork 0
/
stopAtrHighLowLinesIndicator.js
101 lines (81 loc) · 2.95 KB
/
stopAtrHighLowLinesIndicator.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
// Stop ATR - High Low Lines
const { roundNumber } = require("./utils");
// Função para calcular o Average True Range (ATR)
function atr(high, low, close, length) {
let trueRanges = [];
for (let i = 1; i < high.length; i++) {
let trueRange = null;
// Calculate true range
if (i === 1 || isNaN(high[i - 1])) {
trueRange = high[i] - low[i];
} else {
trueRange = Math.max(
high[i] - low[i],
Math.abs(high[i] - close[i - 1]),
Math.abs(low[i] - close[i - 1])
);
}
trueRanges.push(trueRange);
}
// Calculate the Running Moving Average (RMA) of true ranges
let sum = 0;
for (let i = 0; i < length; i++) {
sum += trueRanges[i];
}
let rmaValue = sum / length;
for (let j = length; j < trueRanges.length; j++) {
rmaValue = (trueRanges[j] + (length - 1) * rmaValue) / length;
}
return rmaValue;
}
// Função para calcular o trailing stop
function calculateTrail(inputData, AP2, AF2) {
let Trail2 = [];
let prevTrail2 = 0;
for (let i = 0; i < inputData.length; i++) {
let SC = inputData[i].close;
// Verificar se o índice anterior é válido
let prevClose = i > 0 ? inputData[i - 1].close : null;
let SL2 = AF2 * atr(
inputData.slice(0, i + 1).map(item => item.high),
inputData.slice(0, i + 1).map(item => item.low),
inputData.slice(0, i + 1).map(item => item.close),
AP2
);
// Verificar se o índice anterior é válido
if (prevClose !== null) {
if (SC > prevTrail2 && prevClose > prevTrail2) {
Trail2.push(Math.max(prevTrail2, SC - SL2));
} else if (SC < prevTrail2 && prevClose < prevTrail2) {
Trail2.push(Math.min(prevTrail2, SC + SL2));
} else if (SC > prevTrail2) {
Trail2.push(SC - SL2);
} else {
Trail2.push(SC + SL2);
}
} else {
// Se o índice anterior não for válido, não é possível determinar a direção da vela
// Então, adicionaremos o valor do SC diretamente ao Trail2
Trail2.push(SC);
}
prevTrail2 = Trail2[i];
}
return Trail2;
}
const calculateStopAtr = async (candles, AP2, AF2) => {
const Trail2 = calculateTrail(candles, AP2, AF2);
// Determine the color for each candle
for (let i = 0; i < candles.length; i++) {
const signal = roundNumber(Trail2[i], candles[i].close);
const signalColor = candles[i].close > Trail2[i] ? "green" : "red";
const signalBuy = candles[i].close > Trail2[i] ? true : false;
candles[i].trailAtr = Trail2[i];
candles[i].signalAtr = signal;
candles[i].signalColorAtr = signalColor;
candles[i].signalBuyAtr = signalBuy;
}
return candles;
}
module.exports = {
calculateStopAtr,
}