Viktiga rörliga medelvärden: Grunderna Under åren har tekniker hittat två problem med det enkla glidande medlet. Det första problemet ligger i tidsramen för glidande medelvärdet (MA). De flesta tekniska analytiker tror att prisåtgärder. det öppnande eller stängande aktiekurset räcker inte för att bero på att man korrekt förutsäger köp - eller försäljningssignaler för MAs-crossover-åtgärden. För att lösa detta problem, tilldelar analytiker nu mer vikt till de senaste prisuppgifterna med hjälp av det exponentiellt jämnaste glidande genomsnittet (EMA). (Läs mer om att utforska exponentiellt vägda rörliga medelvärdet.) Ett exempel Till exempel, med en 10-dagars MA, skulle en analytiker ta slutkursen för den 10: e dagen och multiplicera detta nummer med 10, den nionde dagen med nio, den åttonde dag med åtta och så vidare till den första av MA. Så snart summan har bestämts, fördelar analytikern sedan numret genom tillsatsen av multiplikatorerna. Om du lägger till multiplikatorerna i 10-dagars MA-exemplet är numret 55. Denna indikator kallas det linjärt vägda glidande medlet. (För relaterad läsning, kolla in Enkla rörliga genomsnittsvärden. Utveckla tendenser.) Många tekniker är fasta troende i det exponentiellt jämnaste glidande genomsnittet (EMA). Denna indikator har förklarats på så många sätt att det både förvirrar studenter och investerare. Kanske kommer den bästa förklaringen från John J. Murphys tekniska analys av finansmarknaderna (publicerad av New York Institute of Finance, 1999). Det exponentiellt jämnaste glidande genomsnittet adresserar båda problemen i samband med det enkla glidande medlet. För det första tilldelas det exponentiellt glatt genomsnittet en större vikt till de senaste data. Därför är det ett viktat glidande medelvärde. Men medan det tilldelas mindre betydelse för tidigare prisuppgifter, ingår det i beräkningen av alla data i instrumentets livstid. Dessutom kan användaren justera viktningen för att ge större eller mindre vikt till det senaste dagspriset, vilket läggs till i procent av värdet för tidigare dagar. Summan av båda procentvärdena lägger till 100. Till exempel kan det sista dagspriset tilldelas en vikt av 10 (.10), som läggs till föregående dagsvikt på 90 (.90). Detta ger den sista dagen 10 av den totala vikten. Detta skulle motsvara ett 20-dagars medelvärde genom att ge sista dagens pris ett mindre värde av 5 (.05). Figur 1: Exponentially Sloothed Moving Average Ovanstående diagram visar Nasdaq Composite Index från den första veckan i augusti 2000 till 1 juni 2001. Som du tydligt kan se, EMA, som i detta fall använder slutkursdata över en nio dagars period, har bestämda försäljningssignaler den 8 september (markerad med en svart nedåtpil). Det här var den dag då indexet gick ner under 4 000-nivån. Den andra svarta pilen visar ett annat nedben som teknikerna faktiskt förväntade sig. Nasdaq kunde inte generera tillräckligt med volym och intresse från detaljhandeln för att bryta 3 000 mark. Därefter dyker ner igen till botten ut vid 1619.58 den 4 april. Upptrenden av 12 april markeras med en pil. Här stängde indexet 1961.46, och tekniker började se att institutionella fondförvaltare började hämta några fynd som Cisco, Microsoft och några av de energirelaterade frågorna. (Läs våra relaterade artiklar: Flytta genomsnittliga kuvert: Raffinera ett populärt handelsverktyg och flytta genomsnittlig studs.) Som andra har nämnt, bör du överväga ett filter med filterlösning (infinit impulse response) i stället för filtret FIR (finite impulse response) som du använder nu. Det finns mer till det, men vid första anblicken implementeras FIR-filter som uttryckliga omvälvningar och IIR-filter med ekvationer. Det speciella IIR-filtret som jag använder mycket i mikrokontroller är ett enkeltpoligt lågpassfilter. Detta är den digitala motsvarigheten till ett enkelt R-C-analogfilter. För de flesta applikationer kommer dessa att ha bättre egenskaper än det boxfilter som du använder. De flesta användningarna av ett lådfilter som jag stött på är ett resultat av att någon inte uppmärksammar sig i digital signalbehandlingsklass, inte som ett resultat av att de behöver sina speciella egenskaper. Om du bara vill dämpa högfrekvenser som du vet är buller, är ett enkelspalt lågpassfilter bättre. Det bästa sättet att implementera en digitalt i en mikrokontroller är vanligtvis: FILT lt-- FILT FF (NEW - FILT) FILT är en del av kvarhållande tillstånd. Detta är den enda beständiga variabeln du behöver för att beräkna detta filter. NEW är det nya värdet som filtret uppdateras med denna iteration. FF är filterfraktionen. vilket justerar filtrets tyngd. Titta på denna algoritm och se till att för FF 0 är filtret oändligt tungt eftersom utmatningen aldrig ändras. För FF 1 är det verkligen inget filter alls eftersom utmatningen bara följer ingången. Användbara värden är däremellan. På små system väljer du FF för att vara 12 N så att multipliceringen med FF kan utföras som ett rätt skift med N bitar. FF kan till exempel vara 116 och multiplicera med FF därför en högerväxling av 4 bitar. Annars behöver det här filtret endast en subtrahera och ett tillägg, även om siffrorna vanligtvis behöver vara bredare än ingångsvärdet (mer om numerisk precision i ett separat avsnitt nedan). Jag brukar ta AD-avläsningar betydligt snabbare än de behövs och tillämpa två av dessa filter kaskad. Detta är den digitala ekvivalenten av två R-C-filter i serie, och dämpas med 12 dBoctave ovanför rullningsfrekvensen. Men för AD-avläsningar är det vanligtvis mer relevant att titta på filtret i tidsdomänen genom att överväga sitt stegsvar. Detta berättar hur snabbt ditt system kommer att se en förändring när den sak du mäter ändras. För att underlätta utformningen av dessa filter (vilket bara betyder att välja FF och bestämma hur många av dem som ska kaskad) använder jag mitt program FILTBITS. Du anger antalet skiftbitar för varje FF i den kaskadade serien med filter, och det beräknar stegsvaret och andra värden. Egentligen kör jag vanligtvis det här via mitt wrapper script PLOTFILT. Detta kör FILTBITS, vilket gör en CSV-fil, sedan plottar CSV-filen. Till exempel här är resultatet av PLOTFILT 4 4: De två parametrarna till PLOTFILT betyder att det kommer att finnas två filter kaskad av typen som beskrivits ovan. Värdena på 4 indikerar antalet skiftbitar för att inse multipliceringen med FF. De två FF-värdena är därför 116 i detta fall. Det röda spåret är enhetens stegsvar, och är det viktigaste att titta på. Detta säger till exempel att om ingången ändras omedelbart, kommer utmatningen av det kombinerade filtret att lösa sig till 90 av det nya värdet i 60 iterationer. Om du bryr dig om 95 avvecklingstid måste du vänta på 73 iterationer, och för 50 avvecklingstid bara 26 iterationer. Det gröna spåret visar utmatningen från en enda fullamplitudspik. Detta ger dig en uppfattning om slumpmässigt brusundertryck. Det verkar som om inget enskilt prov kommer att orsaka mer än en 2,5 förändring i utmatningen. Det blå spåret är att ge en subjektiv känsla av vad detta filter gör med vitt brus. Det här är inte ett strikt test eftersom det inte finns någon garanti för vad exakt innehållet av slumpmässiga nummer valts som den vita brusinmatningen för denna körning av PLOTFILT. Dess enda för att ge dig en grov känsla av hur mycket det kommer att squashed och hur smidig det är. PLOTFILT, kanske FILTBITS, och massor av andra användbara saker, särskilt för PIC-firmwareutveckling, finns i programvarulicens för PIC Development Tools på min nedladdningssida för program. Tillagt om numerisk precision jag ser från kommentarerna och nu ett nytt svar att det finns intresse att diskutera antalet bitar som behövs för att implementera detta filter. Observera att multipliceringen med FF kommer att skapa logg 2 (FF) nya bitar under binärpunkten. På små system är FF vanligtvis valt att vara 12 N så att denna multiplication faktiskt realiseras av en rättväxling av N bitar. FILT är därför vanligtvis ett fast punkts heltal. Observera att detta inte ändrar någon av matematiken från processorns synvinkel. Om du till exempel filtrerar 10 bitars AD-avläsningar och N 4 (FF 116) behöver du 4 fraktion bitar under 10 bitars heltal AD-värden. En av de flesta processorer, du gör 16 bitars heltalstransaktioner på grund av 10-bitars AD-avläsningar. I det här fallet kan du fortfarande göra exakt samma 16 bitars heltalsoperationer, men börja med AD-avläsningarna vänster skiftad med 4 bitar. Processorn känner inte skillnaden och behöver inte. Att göra matte på hela 16 bitars heltal fungerar om du anser att de är 12,4 fixa eller äkta 16 bitars heltal (16,0 fast punkt). I allmänhet behöver du lägga till N bitar varje filterpole om du inte vill lägga till ljud på grund av den numeriska representationen. I exemplet ovan skulle det andra filtret av två behöva ha 1044 18 bitar för att inte förlora information. I praktiken på en 8-bitars maskin betyder det att du använder 24-bitars värden. Tekniskt sett skulle bara den andra polen av två behöva det bredare värdet, men för enkelhetsgraden för firmware använder jag vanligtvis samma representation, och därmed samma kod, för alla poler i ett filter. Vanligtvis skriver jag en subrutin eller ett makro för att utföra en filterpoleoperation och applicera sedan den på varje pol. Om en subrutin eller ett makro beror på huruvida cykler eller programminne är viktigare för det aktuella projektet. Hur som helst använder jag en del repetillstånd för att skicka NEW till subroutinemacro, som uppdaterar FILT, men laddar också det i samma repetillstånd NYHET var in. Det gör det enkelt att tillämpa flera poler eftersom den uppdaterade filmen av en pol är den nya av nästa. När en subrutin är användbar är det en pekare som pekar på FILT på vägen in, vilket uppdateras till strax efter FILT på väg ut. På så sätt fungerar subrutinen automatiskt på efterföljande filter i minnet om det kallas flera gånger. Med ett makro behöver du inte en pekare eftersom du skickar in adressen för att fungera vid varje iteration. Kodsexempel Här är ett exempel på ett makro som beskrivits ovan för en PIC 18: Och här är ett liknande makro för en PIC 24 eller dsPIC 30 eller 33: Båda dessa exempel implementeras som makron med min PIC assembler preprocessor. som är mer kapabel än någon av de inbyggda makroanläggningarna. clabacchio: Ett annat problem som jag borde ha nämnt är implementering av firmware. Du kan skriva en enkelpolig lågpassfilter subrutin en gång och applicera den flera gånger. Faktum är att jag vanligtvis skriver en sådan subrutin för att ta en pekare i minnet till filtertillståndet, sedan få det framåt pekaren så att det kan kallas i följd lätt för att realisera flera poliga filter. ndash Olin Lathrop Apr 20 12 på 15:03 1. Tack så mycket för dina svar - alla av dem. Jag bestämde mig för att använda det här IIR-filtret, men det här filtret används inte som ett Standard LowPass-filter, eftersom jag behöver genomsnittliga räknevärden och jämför dem för att upptäcka ändringar i en viss räckvidd. eftersom dessa värdena har mycket olika dimensioner beroende på maskinvaran ville jag ta ett genomsnitt för att kunna reagera på dessa maskinvarespecifika ändringar automatiskt. ndash sensslen 21 maj 12 kl 12:06 Om du kan leva med begränsningen av en kraft av två antal objekt i genomsnitt (dvs 2,4,8,16,32 etc) så kan delningen enkelt och effektivt göras på en lågpresterande mikro med ingen dedikerad delning eftersom det kan göras som en bitskift. Varje växlingsrättighet är en kraft av två t. ex.: OP-enheten trodde att han hade två problem, delade i en PIC16 och minne för hans ringbuffert. Detta svar visar att uppdelningen inte är svår. Visserligen behandlar det inte minnesproblemet, men SE-systemet tillåter partiella svar, och användare kan ta någonting från varje svar för sig själva, eller till och med redigera och kombinera andras svar. Eftersom några av de andra svaren kräver en delningsoperation är de lika ofullständiga eftersom de inte visar hur man effektivt uppnår detta på en PIC16. ndash Martin Apr 20 12 at 13:01 Det finns ett svar för ett riktigt glidande medelfilter (aka boxcar filter) med mindre minne krav, om du inte har något emot downsampling. Dess kallas ett kaskad integratorkamfilter (CIC). Tanken är att du har en integrator som du tar skillnader över över en tidsperiod, och den viktigaste minnesbesparande enheten är att genom downsampling behöver du inte lagra alla värden på integratorn. Den kan implementeras med hjälp av följande pseudokod: Din effektiva glidande medellängd är decimationFactorstatesize, men du behöver bara behålla programpunkter med stateize. Självfallet kan du få bättre prestanda om din stateize och decimationFactor är krafter på 2, så att divisionen och återstående operatörer blir ersatta av skift och mask-ands. Postscript: Jag håller med Olin om att du alltid bör överväga enkla IIR-filter före ett glidande medelfilter. Om du inte behöver boxboxfilterets frekvens-nuller, kommer ett 1-poligt eller 2-poligt lågpassfilter troligen att fungera bra. Å andra sidan, om du filtrerar i syfte att decimera (med en högprovsränta inmatning och medelvärdet för att användas av en lågprocess) kan ett CIC-filter vara precis vad du letar efter. (speciellt om du kan använda stateize1 och undvika ringbufferten helt och hållet med bara ett enda tidigare integratorvärde) Det finns en fördjupad analys av matematiken bakom det första ordningens IIR-filter som Olin Lathrop redan har beskrivit på Digital Signal Processing stack exchange (innehåller massor av vackra bilder.) Ekvationen för detta IIR-filter är: Detta kan implementeras med bara heltal och ingen delning med följande kod (kan behöva lite felsökning när jag skriver från minnet.) Detta filter approximerar ett glidande medelvärde av de sista K-proverna genom att ange värdet av alfa till 1K. Gör detta i den föregående koden genom att definiera BITS till LOG2 (K), dvs för K 16 set BITS till 4, för K 4 set BITS till 2, etc. (Jag bekräftar koden som anges här så snart jag får en ändring och redigera det här svaret om det behövs.) svarat den 23 juni kl 12:04 Häri ett enkelpoligt lågpassfilter (glidande medelvärde, med cutoff-frekvens CutoffFrequency). Mycket enkelt, väldigt snabbt, fungerar bra och nästan inget minne. Obs! Alla variabler har räckvidd bortom filterfunktionen, förutom det som passerat i nyInput-anmärkning: Detta är ett enstegsfilter. Flera steg kan kaskadas tillsammans för att öka filterets skärpa. Om du använder mer än ett steg måste du justera DecayFactor (som gäller Cutoff-Frequency) för att kompensera. Och självklart allt du behöver är de två linjerna placerade någonstans, de behöver inte sin egen funktion. Detta filter har en ramp-up tid innan det glidande medelvärdet representerar insignalens. Om du behöver förbi denna ramp-up tid kan du bara initiera MovingAverage till det första värdet av newInput istället för 0, och hoppas att den första newInput inte är en outlier. (CutoffFrequencySampleRate) har ett intervall mellan 0 och 0,5. DecayFactor är ett värde mellan 0 och 1, vanligtvis nära 1. Envärdig flotta är tillräckligt bra för de flesta saker, jag föredrar bara dubblar. Om du behöver hålla fast med heltal kan du konvertera DecayFactor och Amplitude Factor till fraktionella heltal, där täljaren lagras som heltalet och nämnaren är ett heltalseffekt på 2 (så att du kan byta till höger som nämnare snarare än att behöva delas under filterslingan). Om du exempelvis använder DecayFactor 0.99 och du vill använda heltal kan du ange DecayFactor 0.99 65536 64881. Och sedan när du multiplicerar med DecayFactor i din filterslinga, skiftar du bara resultatet 16. För mer information om detta, en utmärkt bok online, kapitel 19 om rekursiva filter: dspguidech19.htm PS För det Moving Average-paradigmet kan ett annat sätt att ställa in DecayFactor och AmplitudeFactor som kan vara mer relevant för dina behov, vi kan säga att du vill ha det föregående, cirka 6 objekt i genomsnitt, gör det diskret, youd lägg till 6 objekt och dela med 6, så Du kan ställa in AmplitudeFactor till 16 och DecayFactor till (1.0 - AmplitudeFactor). svarade 14 maj 12 kl 22:55 Alla andra har kommenterat grundligt om nyttan av IIR vs FIR, och på power-of-two division. Jag tycker bara om att ge några detaljer om genomförandet. Nedan fungerar bra på små mikrokontroller utan FPU. Theres ingen multiplikation, och om du behåller N en kraft av två, är hela divisionen enkelscykelbitskiftande. Grundläggande FIR-ringbuffert: Håll en löpbuffert med de sista N-värdena och en kör SUM av alla värden i bufferten. Varje gång ett nytt prov kommer in, subtrahera det äldsta värdet i bufferten från SUM, ersätt det med det nya provet, lägg till det nya provet till SUM och mata ut SUMN. Modifierad IIR ringbuffert: Håll en SUM av de sista N-värdena. Varje gång ett nytt prov kommer in, SUM - SUMN, lägg till i det nya provet och mata ut SUMN. svarat 28 aug 13 kl 13:45 Om jag läser dig rätt, beskriver du ett första-order IIR-filter, det värde som du subtraherar är det äldsta värdet som faller ut men istället är det genomsnittet av tidigare värden. Första ordningens IIR-filter kan säkert vara användbart, men jag är inte säker på vad du menar när du föreslår att utsignalen är densamma för alla periodiska signaler. Vid en provkvot på 10 kHz matar en 100 Hz kvadratvåg i ett 20-stegs filter med en signal som stiger jämnt för 20 prover, sitter högt för 30, sjunker jämnt för 20 prover och sitter lågt för 30. En första order IIR-filter. ndash supercat Aug 28 13 på 15:31 kommer att ge en våg som kraftigt börjar stiga och gradvis nivåer av nära (men inte vid) inmatnings maximalt, så börjar det kraftigt och faller gradvis av nära (men inte vid) inmatningsminimum. Mycket annorlunda beteende. ndash supercat Aug 28 13 på 15:32 Ett problem är att ett enkelt glidande medel kan eller inte kan vara användbart. Med ett IIR-filter kan du få ett fint filter med relativt få beräkningar. Den FIR du beskriver kan bara ge dig en rektangel i tid - en sync i freq - och du kan inte hantera sidlobben. Det kan vara väl värt att kasta in ett fåtal heltal multipliceras för att göra det till en fin symmetrisk avstämningsbar FIR om du kan spara klockan. Scott Scott Seidman Aug 29 13 på 13:50 ScottSeidman: Inget behov av multiplicerar om man helt enkelt har varje steg i FIR-enheten, antingen matar in genomsnittet av inmatningen till det aktuella läget och dess tidigare lagrade värde och lagrar sedan inmatningen (om man har det numeriska området, man kan använda summan snarare än genomsnittet). Huruvida det är bättre än ett lådfilter beror på applikationen (stegresponsen av ett lådfilter med en total fördröjning på 1ms, till exempel, kommer att ha en otäck d2dt-spik när ingången ändras och igen 1ms senare men kommer att ha det minsta möjligt ddt för ett filter med totalt 1ms fördröjning). ndash supercat Aug 29 13 på 15:25 Som mikeselektronik sagt, om du verkligen behöver minska dina minnesbehov och du inte har något emot att ditt impulsrespons är en exponentiell (istället för en rektangulär puls) skulle jag gå för ett exponentiellt glidande medelfilter . Jag använder dem i stor utsträckning. Med den typen av filter behöver du ingen buffert. Du behöver inte lagra N tidigare prover. Bara en. Så, dina minneskrav får skära ner med en faktor N. Dessutom behöver du ingen delning för det. Endast multiplikationer. Om du har tillgång till flytande punkträkning, använd flytande punktmultiplikationer. Annars gör du multipelantal och går till höger. Vi är dock 2012, och jag rekommenderar dig att använda kompilatorer (och MCU) som låter dig arbeta med flytande punktnummer. Förutom att vara mer minneseffektivt och snabbare (du behöver inte uppdatera objekt i någon cirkulär buffert), skulle jag säga att det också är mer naturligt. eftersom ett exponentiellt impulsrespons matchar bättre hur naturen beter sig, i de flesta fall. svarat 20 apr 12 kl 9:59 Ett problem med IIR-filtret som nästan berört av olin och supercat men tydligen ignoreras av andra är att avrundningen introducerar en viss oriktighet (och eventuellt biastruncation). förutsatt att N är en kraft av två, och endast heltalsräkning används, eliminerar växlingsrätten systematiskt LSB: erna i det nya provet. Det betyder att hur länge serien någonsin kan vara, kommer medlet aldrig att ta hänsyn till dem. Antag till exempel en långsamt minskande serie (8,8,8, 8,7,7,7, 7,6,6,) och antar att medlet verkligen är 8 i början. Fist 7-provet kommer att ge genomsnittet till 7, oavsett filterstyrkan. Bara för ett prov. Samma historia för 6, etc. Tänk nu på motsatt. serien går upp. Medelvärdet kommer att förbli på 7 för alltid, tills provet är stort nog för att få det att förändras. Naturligtvis kan du korrigera för bias genom att lägga till 12N2, men det går inte att lösa precisionsproblemet. i så fall kommer den minskande serien att stanna för alltid vid 8 tills provet är 8-12 (N2). För N4 till exempel behåller något prov över noll genomsnittet oförändrat. Jag tror att en lösning för det skulle innebära att en ackumulator av de förlorade LSB: erna finns. Men jag gjorde inte det tillräckligt långt för att ha kod redo, och jag är inte säker på att det inte skulle skada IIR-strömmen i några andra fall av serier (till exempel om 7,9,7,9 skulle vara genomsnittliga till 8 då). Olin, din tvåstegskaskad skulle också behöva någon förklaring. Menar du att du håller två genomsnittsvärden med resultatet av den första matas in i den andra i varje iteration. Vilken nytta av detta har jag en dataset för pris på ticker på börsen: tid - pris. Men mellanrum mellan datapunkter är inte lika - från 1 till 2 minuter. Vad är den bästa praxis för att beräkna glidande medelvärde för ett sådant fall Hur man gör det i Matlab Jag brukar tänka att vikten av punkterna ska bero på det tidsintervall som var senast sedan tidigare punkt. Har vi funktion i Matlab för att beräkna glidande medelvärde med anpassade vikter av punkterna som ställts 30 juli 14 kl 19:01 Mitt svar är ganska lik lakeshs one. Men jag kommer att tro på ditt problem när det gäller interpolering. Först av allt är ett glidande medelvärde, eller ett tidsgenomsnitt för en funktion, det integrerade av det över en tidsperiod dividerat med tidslängden. I ditt fall kan integralet ses som en summa, eftersom funktionsvärdet i allmänhet i varje minut är detsamma. Däremot har dina data ojämna tidsintervaller. Detta kan ses som saknade punkter i funktionen. Låt mig förklara: för varje minut x. du borde ha ett pris f (x). Men för några gånger säger x5. f (x) är odefinierad. Ett av de sätt som du kan bli av med diskontinuiteter av en funktion är interpolering - tilldela något värde till de saknade punkterna, enligt vissa regler för beräkning. Den enklaste algoritmen håller det tidigare värdet, vilket är i huvudsak lakeshs idé. Men fördelen med att tänka i denna aspekt ligger i förmågan att göra dina data mer exakta. Det kan inte vara tillämpligt på aktiemarknaden, men det borde vara sant i allmänhet, till exempel en temperaturmätning eller vindhastighet, som garanteras att smidigt byta över tiden (i stället för att hålla konstant i 2 minuter och plötsligt växla om en sekund). Du kan använda olika interpoleringstekniker för att polera data. Polering i den meningen är ok eftersom du på något sätt måste använda begreppet medelvärde. En bra interpolering borde göra datan närmare en modell som har visat sig fungera med det verkliga problemet. KOD - Jag ställde maxintervallet till 5 minuter för att visa stor skillnad mellan de två metoderna. Det beror på din observation och erfarenhet att bestämma vilken (eller någon annan) metod som är bäst att förutsäga förflutna. Obs: odefinierade poäng ska presenteras av NaN. men -1 verkar lättare att leka med. svarade den 30 juli kl 14:20
No comments:
Post a Comment