Home  >  Q&A  >  body text

Nodejs MetaAPI Cloud / Calculate Moving Average

<p>I am making a trading bot using metaapi.cloud and I am trying to calculate moving average (fast/exponential) but it returns me invalid values, here is my code: </p> <pre class="brush:js;toolbar:false;">async movingAverage(symbol, period, type = "S") { let candles = (await this.account.getHistoricalCandles(symbol, this.params.timeframe, null, period)).map(c => c.close); const result = []; let sum = 0; if (type === "S") { for (let i = 0; i < period; i ) { sum = candles[i]; } result.push(sum / period); for (let i = period; i < candles.length; i ) { sum = sum - candles[i - period] candles[i]; result.push(sum / period) } } else if (type === "E") { const weight = 2 / (period 1); for (let i = 0; i < period; i ) { sum = candles[i]; } sum /= period; result.push(sum); for (let i = period; i < candles.length; i ) { sum = (candles[i] * weight) (sum * (1 - weight)); result.push(sum); } } else { // throwError() } return result; } </pre> <p>Here’s how I use it: </p> <pre class="brush:js;toolbar:false;">async onTick(infos) { let sma = await this.movingAverage(infos.symbol, this.params.fast, "S"); console.log('SMA ' sma[0]); } </pre> <p>Now when I test it, the SMA should return "1906.6963" but it gives me "1900.7813" Maybe I'm using the wrong way to calculate them? If anyone has a solution! Thanks in advance. </p>
P粉715274052P粉715274052433 days ago489

reply all(2)I'll reply

  • P粉071743732

    P粉0717437322023-09-04 00:37:22

    • SMA looks correct, EMA has many different patterns. Since you didn't post a sample dataset, it's hard to guess what is being passed from the server, but there could be a lot of values ​​that cannot be converted, such as NaN, null, empty strings or numbers with commas, exponents, etc. Just replaced the candles with an array with wrong values. Do some filtering and then do the calculation
    • Consider period > dataset. In this case, set period to length.

    In the example below, set period to 1 to see all values ​​processed, and set period to a very large number to see the entire average.

    There are definitely other edge cases that I haven't thought of. For brevity, the following examples use SMA.

    async function movingAverage(symbol, period, type = "S") {
            let candles = [1,2,3,"","",4, "0",0, null, "99,9123", undefined,"0.123e5", "wrongval", 9, 10, 20, 100]
            .map(d => parseFloat((d ?? "").toString().replace(",",".")))
            .filter(d => +d || +d === 0);
            const result = [];
            if (candles.length <= 0){return result}
            let sum = 0;
            period = Math.min(candles.length, period) || 1;
            for (let i = 0; i < period; i++) {
                sum += candles[i];
            }
            result.push(sum / period);
            for (let i = period; i < candles.length; i++) {
                sum = sum - candles[i - period] + candles[i];
                result.push(sum / period)
            }
            return result;
        }
        movingAverage("SPX",500).then(x => document.getElementById("result").textContent = x)
    <div id="result"></div>

    reply
    0
  • P粉563446579

    P粉5634465792023-09-04 00:18:21

    I found the problem. It comes from MetaTrader's api, "getHistoricalCandles" not working as expected. What is written in the api is:

    getHistoricalCandles(symbol, timeframe, startTime, limit)
    symbol: symbol to retrieve candles for
    TimeFrame: define the timeframe according to which the candles must be generated
    StartTime: time to start loading candles from. Note that candles are loaded in backward direction, so this should be the latest time, **leave it empty to request latest candles**
    Limit: maximum of candles to retrieve, must be less or equals to 1000

    The problem here is the StartTime parameter, it definitely doesn't work like they say it does, when I leave it empty, or when I put Date.now() it retrieves Candles from 5 hours ago, in order to retrieve the absolute last candle, I have to enter Date.now() 10000000000, so this may be a time zone error that cannot be solved for now since it comes from the api side.. .

    reply
    0
  • Cancelreply