Monday, 6 February 2017

Javascript Array Gleitenden Durchschnitt

Ein einfaches Moving Average Implementierung in Java Bei mehreren Gelegenheiten wollte ich einfache Metriken in meinem Java-Anwendungen, zum Beispiel die Anzahl der Treffer pro Stunde, oder Fehler während eines Zeitraums zu berechnen. Während der Berechnung einfacher Metriken ist nicht schrecklich schwierig, seine nur extra Arbeit und Id eher verbringen diese Zeit auf der Problem-Domain. Ich war überrascht, keine allgemein akzeptierten Lösungen für Metriken in Java zu finden. Ich fand Metrics, aber es schien ein wenig zu kompliziert und nicht gut dokumentiert - Alles, was ich wollte, war es, einen gleitenden Durchschnitt zu berechnen. Ich dachte über das Problem einiges mehr und entschied es nicht ein schwieriges Problem. Heres meine Lösung Dies funktioniert durch die Schaffung eines Arrays von Fenster-Update-Frequenz Größe, dann ein Thread setzt die Zählung auf den nächsten Index im Array auf die Aktualisierungsfrequenz. Die Zählung für das Intervall ist einfach arrayi - arrayi1, das ist die jüngste Zählung minus der ältesten Zählung. Für ein 10-Minuten-Intervall ist die älteste Zählung (i1) genau 10 Minuten alt. Um einen gleitenden Durchschnitt zu unserem Code hinzuzufügen, benötigen Sie zunächst einen Zähler mit AtomicLong. Dieser Zähler sollte basierend auf den Ereignissen inkrementiert werden, die für das Berechnen interessant sind (z. B. POST-Anforderungen für einen REST-Dienst). Wir müssen die Implementierung mit Zugriff auf den Zähler bereitstellen und das wird durch die GetCount-Schnittstelle erreicht. Hier Ill erstellen einen gleitenden Durchschnitt mit einem 5-Minuten-Fenster, das jede Sekunde aktualisiert. Und um den aktuellen Durchschnitt zu erhalten, rufen wir einfach die getAverage-Methode auf: Ein Schlüsselimplementierungsdetail ist, wie die Arraygröße bestimmt wird: indem das Fenster durch die Aktualisierungshäufigkeit dividiert wird. So kann ein großes Fenster mit einer häufigen Aktualisierungshäufigkeit eine beträchtliche Menge an Speicher verbrauchen. In diesem Beispiel ist die Array-Größe vernünftig 300. Wenn wir jedoch einen 24-Stunden-gleitenden Durchschnitt mit einem Intervall von 1 Sekunde erstellt haben, wäre die Größe 86400 Eine vernünftigere Aktualisierungsfrequenz für einen Zeitraum von 24 Stunden kann alle 5 Minuten betragen (Arraygröße von 288 ). Eine weitere Überlegung der Auswahl der Fenster-und Update-Frequenz ist das Fenster muss durch die Frequenz teilbar. Zum Beispiel ist ein 2-minütiges Fenster mit einer 6-Sekunden-Aktualisierungsfrequenz ok, aber eine 7-Sekunden-Aktualisierungsfrequenz ist nicht vorhanden, da es nicht durch 120 teilbar ist. Eine IllegalArgumentException wird geworfen, wenn die Fenstermodul-Aktualisierungsfrequenz nicht Null ist. Diese Implementierung erfordert einen Thread pro gleitenden Durchschnitt, was nicht sehr effizient ist. Eine bessere Lösung wäre, einen Thread über viele Durchschnitte zu teilen. Aktualisieren. Ich habe den Code aktualisiert, um einen Thread hier zu teilen. Schließlich theres ein Anfangszustandproblem: wir dont haben Daten noch für das gesamte Fenster. Zum Beispiel, wenn Sie ein 5-Minuten-Fenster und nur 15 Sekunden Daten haben. Diese Implementierung gibt null zurück, bis wir 5 Minuten Daten haben. Ein anderer Ansatz ist, den Durchschnitt abzuschätzen. Angenommen, wir haben eine Zählung von 10 in 30 Sekunden, dann können wir den Durchschnitt als 40 in 2 Minuten abschätzen. Es besteht jedoch das Risiko eines signifikanten Fehlers, indem unvollständige Daten extrapoliert werden. ZB wenn wir einen Sprung von 20 Treffern in 2 Sekunden hatten, würden wir 1200 pro 2 Minuten schätzen, die in aller Wahrscheinlichkeit Weise weg ist. Ihre innere für iterating die ganze Reihe also thats, warum Sie immer den gleichen Durchschnitt erhalten (das Eine für das gesamte Array), sollten Sie stattdessen von 0 bis zur aktuellen Nummer des äußeren Feldes iterieren. Ihr gleitender Durchschnitt wird aktualisiert, basierend auf j Ihrer inneren für das bedeutet, dass es vorherige Werte überschreibt jede neue Schleife, sollte diese innerhalb der äußeren für statt der inneren mit i als Index sein. Sie teilen sumj, um Mittelwerte zu berechnen, jede neue innere Schleife j Sie teilen durch 0 die erste Summe. Ich glaube, Sie wollten j1 verwenden, Index ist nicht das gleiche wie aktuelle Länge Tipps zur Fehlerbehebung: Vermeiden Sie die Verwendung von Variablen zu Loop-Arrays, sollten Sie array. length stattdessen verwenden. Für eine Frage der Reproduktion Ihres Problems könnten Sie uns das isolierte Problem anstelle des aktuellen Codes. Dh: Stellen Sie sich vor, wenn der Fehler in Ihren Eingaben ist, wie könnten wir glauben, dass Sie wirklich verwendet sie beantwortet werden Sie sind Looping über alle Daten jedes Mal. Sie sollten für (int j (igtaverageLengthi-averageLength2: 0) jlt iaverageLength2 ampamp jltnumDataPoints j) (oder etwas ähnliches) für Ihren innersten Durchschnitt haben. Auch MovingAverageisumj sollte modifiziert werden, um den Fall zu behandeln, wenn j 0 ist. Insbesondere sollte es wahrscheinlich movingAverageisumaverageLength sein und es sollte auf den movingAveragei-Slot außerhalb der Mittelungsschleife angewendet werden. Antwortete Oct 4 13 am 20:42 Nächstes Mal, nehmen Sie die Kommentare über die Zuweisung aus der Frage, bevor Sie es. Aber da Sie scheinen ziemlich neu in diesem, darüber nachzudenken, wie würden Sie durch die Daten gehen, und machen es tun. Sie sollten sicherstellen, dass jede Schleife an dem richtigen Punkt stoppt, und denken Sie daran, dass wenn Sie stoppen würden, wenn es keine Zahlen mehr gibt (wie wenn Sie die innere Schleife machen und nur 3 weitere Zahlen anstelle von 4 erhalten können) Muss das Programm auch stoppen. Stellen Sie sicher, dass Ihr Code für diese Überprüfung ist. Antwortete ohne weitere Details, benötigen Sie wahrscheinlich einen ungewichteten gleitenden Durchschnitt. An einem beliebigen Punkt Ai im Eingabefeld A der Länge N (mit 0ltiltN) ist das einfach der Mittelwert der vorherigen K Einträge des Arrays, bis zu und einschließlich Ai. Wenn es arent K solche Werte, dann die durchschnittlichen (i1) Werte von A0 bis Ai. Einschließlich. Ein wenig Gedanke zeigt Ihnen, dass Sie nicht alle K-Werte addieren müssen jedes Mal. Halten Sie einfach die Summe, und beim Bewegen zum nächsten Punkt (dies ist ein gleitender Durchschnitt), subtrahieren Sie den Wert, der ersetzt wird, und fügen Sie den neuen Wert hinzu, der es ersetzt. (Bei den ersten K-1-Punkten fügen Sie einfach den neuen Wert zur Summe hinzu und erhöhen Sie den Zählwert um 1.) Der gleitende Durchschnitt ist an jedem Punkt der aktuelle Summe dividiert durch den aktuellen Zählwert. In einem gleitenden Durchschnitt, müssen Sie eine Art von Fenstergröße haben. Ihre Fenstergröße ist averageLength, so wird es etwa so aussehen: Die for-Schleife startet bei den aktuellen Daten und geht zurück AverageLength Datenpunkte und fügt sie hinzu. Sie haben nur einen gleitenden Durchschnitt, wenn Sie haben, wenn Sie genügend Datenpunkte haben und der Durchschnitt wird die Summe geteilt durch die durchschnittliche Länge haben. Hinweis: Nicht getestet nur Sudo-Code, aber das ist die Idee. Beantwortet Ihre Antwort 2017 Stack Exchange, Inctraderema die traderema () - Funktion nicht richtig funktioniert. Es berechnet nur Durchschnitt der letzten Periodeneinträge. Führen Sie den folgenden Code für traderema aus: function EMACalculator (limit, array) EMApreviousday array0 printr (array) multiplier1 (2limit1) EMAarray () EMA array0 Close array1 while (limit) echoEMA ist EMAn EMA (EMApreviousday) EMApreviousday EMApreviousday EMA - - return EMA, wobei limit den Zeitraum von ema und array akzeptiert. Akzeptieren Array von Daten für ema Berechnung.


No comments:

Post a Comment