Tuesday 14 November 2017

Php Kode Eksponentiell Moving Average


Jeg vil beregne verdien EMA (Eksponensiell Flytende Gjennomsnitt) i PHP. Ive prøvd med følgende kode, men det gir meg 500 feil. PHP: EMA beregning funksjon trader-ema Forsøkt med lang tid Googling, men ikke får noen hjelp på dette i PHP. Så, jeg har ingen anelse om hva som må gjøres for å beregne EMA-verdien. Rediger-1: Installert utvidelser Ive installert alle nødvendige utvidelser, Nå får jeg utgangen. Men det synes ikke å gi riktig utgang. Jeg tror PHP-funksjonen for å beregne EMA fungerer ikke som den skal. Eventuell hjelp i dette vil bli verdsatt. Jeg prøver å hente den siste EMA av et stort datasett (15000 verdier). Det er en veldig ressurs-sulten algoritme siden hver verdi avhenger av den forrige. Her er koden min: Hva jeg allerede gjorde: Isoler k så det ikke beregnes 10000 ganger Bare hold den siste beregnede EMAen, og ikke hold dem alle i en array bruk for () i stedet for foreach () data array har ikke nøkler det er en grunnleggende matrise Dette tillot meg å redusere kjøretid fra 2000m til 500md for 15000 verdier. Hva virket ikke: Bruk SplFixedArray (), dette barberte bare 10ms som utfører 1.000.000 verdier. Bruk PHPTrader-utvidelsen. Dette returnerer en matrise som inneholder alle EMAene i stedet for bare det siste, og dens langsommere Skriver og kjører den samme algoritmen i C og kjører den over 2.000.000 verdier tar bare 13ms. Så åpenbart, å bruke et kompilert språk på lavere nivå ser ut til å hjelpe P Hvor skal jeg gå herfra Koden vil til slutt kjøre på Ubuntu, så hvilket språk skal jeg velge Vil PHP kunne ringe og sende et så stort argument til skriptet som ble spurt 11. juli kl 19:21 Klart å implementere med en utvidelse gir deg en betydelig økning. I tillegg kan kalkulatoren forbedres som seg selv, og den gevinst du kan legge til i hvilket språk du velger. Det er lett å se at lastEMA kan beregnes som følger: Dette kan skrives på nytt for å ta ut av sløyfen så mye som mulig: For å forklare utvinningen av k tror det i den tidligere formuleringen er som om alle originale rådata blir multiplisert med k så praktisk at du i stedet kan multiplisere sluttresultatet. Legg merke til at det er omskrivet på denne måten at du har 2 operasjoner inne i sløyfen i stedet for 3 (for å være nøyaktig inne i sløyfen er det også en økning i sammenligning med sizeata og lastEMA verdi tildeling) slik at du kan forvente å oppnå en ekstra fart i området mellom 16 og 33. Videre er det andre forbedringer som i hvert fall kan vurderes under noen omstendigheter: Overvei bare siste verdier De første verdiene multipliseres flere ganger med k1m 1 - k, slik at deres bidrag kan være lite eller til og med gå under presisjonen for flytpunktet (eller den akseptable feilen). Denne ideen er spesielt nyttig hvis du kan anta at eldre data er av samme størrelsesorden som den nyere fordi hvis du bare anser de siste n-verdiene, er feilen du gjør er feil EMAofdiscardeddata (1-k) n. Så hvis størrelsesorden er stort sett den samme, kan vi fortelle at den relative feilen som er gjort, er gjenopprettet sistEMA EMAofdiscardeddata (1-k) n lastEMA som nesten er lik bare (1-k) n. Under antagelsen at lastEMA nesten lik EMAofdiscardeddata: La oss si at du kan godta en relativ feilreferanse, du kan trygt vurdere bare de siste n-verdiene der (1 - k) n lt relerr. Midler som du kan forhåndsberegne (før løkken) n log (relerr) logg (1-k) og beregne alle bare med tanke på de siste n-verdiene. Hvis datasettet er veldig stort, kan dette gi en fornuftig hastighet. Tenk på at for 64 bit flytende punktnumre har du en relativ presisjon (relatert til mantissaen) som er 2-53 (omtrent 1.1e-16 og bare 2-24 5.96e-8 for 32 bit flytende punktnumre) slik at du ikke kan få bedre enn denne relative feilen så i utgangspunktet burde du aldri ha en fordel ved å beregne mer enn n logg (1.1e-16) logg (1-k) verdier. å gi et eksempel hvis rekkevidde 2000 da n logg (1.1e-16) logg (1-22001) 36746. Jeg synes det er interessant å vite at ekstra beregninger ville gå tapt inne i avrundingene det er ubrukelig er bedre å ikke gjøre. nå et eksempel på tilfellet der du kan godta en relativ feil større enn flytpunkts presisjon relerr 1ppm 1e-6 0.00001 6 signifikante desimaltall du har n logg (1.1e-16) logg (1-22001) 13815 Jeg tror det er ganske en lite tall i forhold til de siste eksemplene dine, så i så fall kan speedupen være tydelig (Im antar at omfanget 2000 er meningsfullt eller høyt for søknaden din, men jeg vet ikke). bare andre få tall fordi jeg ikke vet hva som er typiske figurer: relerr 1e-3 rekkevidde 2000 n 6907 relerr 1e-3 rekkevidde 200 n 691 relerr 1e-3 rekkevidde 20 n 69 relerr 1e-6 rekkevidde 2000 n 13815 relerr 1e - 6 rekkevidde 200 n 1381 relerr 1e-6 rekkevidde 20 n 138 Hvis antagelsen sistEMA nesten lik EMAofdiscardeddata ikke kan tas, er ting mindre enkle, men siden fordelen kameraet er betydelig, kan det være meningsfylt å fortsette: vi må vurdere om full formel: relerr EMAofdiscardeddata (1-k) n sistEMA så n logg (relerr lastEMA EMAofdiscardeddata) logg (1-k) (logg (relerr) logg (lastEMA EMAofdiscardeddata)) logg (1-k) sentralpunktet er å beregne lastEMA EMAofdiscardeddata (uten faktisk beregning av sisteEMA eller EMAofdiscardeddata selvfølgelig) et tilfelle er når vi vet a-priori at for eksempel EMAofdiscardeddata lastEMA lt M (for eksempel M 1000 eller M 1e6) i så fall n lt (log (relerrM)) logg - K) Hvis du ikke kan gi noe M-nummer, må du finne et godt ID ea for å overskatte EMAofdiscardeddata lastEMA En rask måte kan være å ta M max (data) min (data) Parallellisering Beregningen kan skrives om på nytt i et skjema hvor det er et enkelt tillegg til uavhengige vilkår: Så hvis implementeringsspråket støtter parallellisering datasettet kan deles i 4 (eller 8 eller n. i utgangspunktet antall CPU-kjerner tilgjengelig) biter og det kan beregnes summen av termer på hver bit i parallell oppsummering av de enkelte resultatene på slutten. Jeg går ikke i detalj med dette siden dette svaret allerede er veldig lenge, og jeg tror at konseptet allerede er uttrykt. Takk for at denne I39m bruker dette på aksjemarkedsdata, så det faktum at de eldre dataene er i samme størrelsesorden som de nyere data, avhenger av hvilken tidsramme som brukes. Anta et utvalg på 200, det vil bli en mye større variasjon i prisene på en daglig tidsramme (200 dager) enn 5 minutters tidsramme (16 timer). Jeg vil eksperimentere med forskjellige scenarier på ekte og simulerte data. På nye data, med en rekkevidde lt 200, bruker jeg et 1000-datasett. Men jeg har også gjort noen tilbaketesting de siste årene, så jeg må fortsatt laste hele datasettet. Du hjalp for begge situasjoner, takk ndash Lykegenes Jul 16 14 kl 15:11 Bygg din egen forlengelse forbedrer ytelsen definitivt. Heres en god opplæring fra Zend nettsiden. Noen ytelsesfigurer: Maskinvare: Ubuntu 14.04, PHP 5.5.9, 1-kjerne Intel CPU3.3Ghz, 128MB RAM (det er en VPS). Før (kun PHP, 16.000 verdier). 500ms C forlengelse, 16.000 verdier. 0,3ms C forlengelse (100.000 verdier). 3,7 ms C forlengelse (500 000 verdier). 28.0ms Men Im minne begrenset på dette punktet, med 70MB. Jeg vil fikse det og oppdatere tallene tilsvarende. traderema funksjonen traderema () virker ikke riktig. det beregner bare gjennomsnittet for siste periodeoppføringer. Følg følgende kode for traderema: funksjon EMACalculator (limit, array) EMApreviousday array0 printr (array) multiplikator1 (2limit1) EMAarray () EMA array0 Lukk array1 mens (limit) echoEMA er EMAn EMA (Close - EMApreviousday) multiplikator1 EMApreviousday EMApreviousday EMA limit - - returner EMA hvor grense godta perioden ema og array. aksepter array av data for ema beregning. Dessverre har den viste koden to store bugs, på grunn av måten gjennomsnittet lagres som et heltall. For å se dette, la oss velge alfa til 1024. Vi starter med adcvalue 0, da dspemai32 vil returnere 0 som forventet. Deretter øker du adcvalue til 1. tmp0 i dspemai32 vil være: tmp0 (int64t) 1 (1024) (int64t) 0 (65536 - 1024) 1024 0 64512 1024 så den returnerte verdien er: (int32t) ((tmp0 32768) 65536) 1024 32768) 65536 33792 65536 0 Så dspemai32 vil fortsette å returnere 0, mens det skal (etter lenge nok filtreringstid) i sluttendringen 1. Koden implementerer effektivt et filter med en dødsonde, ikke endres til inngangen er forskjellig fra gjennomsnittlig med 32768alpha eller mer, eller forskjellig med - (32768 apha) eller mindre. Ved å følge eksemplet ovenfor øker du annonsekvaliteten til 31 (som er mindre enn 32768 apha). tmp0 i dspemai32 vil være: tmp0 (int64t) 31 (1024) (int64t) 0 (65536 - 1024) 31744 0 64512 31744 så returnert verdi er: (int32t) ((tmp0 32768) 65536) (31744 32768) 65536 64512 65536 0 Så dspemai32 vil fortsette å returnere 0. Når du øker adcvaluen til 32 i stedet, vil tmp0 i dspemai32 være: tmp0 (int64t) 32 (1024) (int64t) 0 (65536 - 1024) 32768 0 64512 32768 slik at den returnerte verdien er: int32t) ((tmp0 32768) 65536) (32768 32768) 65536 65536 65536 1 Så minst beveger gjennomsnittet seg mot inngangsverdien med 1. Det er bra. Men da: tmp0 (int64t) 32 (1024) (int64t) 1 (65536 - 1024) 32768 1 64512 97280 slik at den returnerte verdien er: (int32t) ((tmp0 97280) 65536) (97280 32768) 65536 130048 65536 1 Så dspemai32 vil fortsette å returnere 1, aldri når inngangsverdien på 32. Ikke bra. Den andre feilen er heltalldivisjonen (tmp0 32768) 65536. I C C vil heltalldivisjonen runde mot 0, så i den situasjonen er den døde sonen enda større. Mye bedre (og mye enklere) er algoritmen som vist av david. prentice på avrfreakscomment824765comment-824765: lang total 0 int gjennomsnittlig 0 int N 0 arbeider antall prøver. totalt ADCW legg til løpende totalt hvis (N gt MAXSAMPLES) nok prøver totalt - gjennomsnittlig fjern ett annet N gjennomsnittlig totalt N heltall

No comments:

Post a Comment