Fast Fourier Transform

Stel hier uw vragen over TA-script, of help anderen met het oplossen van hun probleem
Plaats reactie
Janus
Berichten: 1463
Lid geworden op: wo jan 30, 2008 2:07 am
Contacteer:

Fast Fourier Transform

Bericht door Janus »

Dit onderwerp is gestart in de topic "Gann', maar is dermate interessant dat het onderwerp daaruit is gelicht en hier in een aparte topic is gestopt.
.

Het begint allemaal bij de Franse natuurkundige Jean-Baptiste Joseph Fourier.
Hij ontwikkelde een nieuwe wiskundige techniek, later naar hem fourieranalyse genoemd, waarmee hij een willekeurige beginvoorwaarde kon uitdrukken als een lineaire combinatie van sinussen.
.
Ik wil er een keer een 'werkstukje' over schrijven, maar in het kort komt het op het volgende neer:
Stel: iemand fluit op een blokfluit een bepaalde toonhoogte en een ander persoon die er naast staat speelt tegelijkertijd op een andere fluit een andere toonhoogte.
Wat je als toeschouwer dan hoort is een klank die opgebouwd is uit die twee verschillende toonhoogtes.
Via de Fourier analyse en de Fourier transform (James Cooley en John Tukey in 1965) zijn we dan in staat om uit die samengestelde klank weer de oorspronkelijke fluitsignalen te herleiden waaruit die klank is opgebouwd.
Hieruit is weer de Fast-Fourier-Transform ontwikkeld.
Wie er meer over wil lezen kijkt even op Wikipedia onder de link: https://nl.wikipedia.org/wiki/Fourieranalyse en ook: https://nl.wikipedia.org/wiki/Fast_Fourier_transform
.
Op dit forum zijn we natuurlijk vooral gefocust op de beurs-koersen; en in verband met de Fast Fourier Analyse stellen we dan ook dat ook de beurskoersen zijn opgebouwd uit allemaal onderliggende cycli (sinussen) die we dan door middel van deze Fast-Fourier-Transform proberen te ontleden.
Wanneer we eenmaal weten uit welke sinusgolf bewegingen (met elk hun eigen frequentie, amplitude en fase) de beurskoers is opgebouwd, kunnen we deze onderliggende sinussen door laten lopen en een verwachting maken voor de koersen op de korte termijn.
Wie wat wil lezen over Sinus, Frequentie, Amplitude etc. etc. kan het volgende stukje lezen wat ik eerder al eens heb geschreven --> http://www.jstas.com/cycles/cyclus.htm
We moeten daarbij altijd in het achterhoofd houden dat Sinussen kunnen toenemen of afnemen in amplitude of zelfs uitdoven.
Verder kunnen er nieuwe sinussen ontstaan, en ook 'plotselinge' gebeurtenissen zullen de koers positief of negatief beïnvloeden en een overheersend karakter kunnen krijgen op de 'lopende- sinussen'.
.
Ik heb een aantal weken geleden een eerste poging ondernomen om een stukje ta-script code te schrijven die probeert de onderliggende sinussen uit de koers te halen.
De code geeft als eerste een soort van spectrum analyse weer, op z'n Jan-boeren-fluitjes gezegd: de code laat zien welke sinussen (met een bepaalde periode) invloed hebben op de koers en hun sterkte ervan.
Een voorbeeld hiervan is het volgende plaatje:
Figuur 1:
Afbeelding
.
De gecombineerde sinusvorm die daaruit rolde was:
Grafiek 2:
Afbeelding
.
Nu is alles meestal niet zo eenvoudig als het in eerste instantie lijkt, en des te dieper je spit des te meer je tegen komt.
En dat maakt het natuurlijk steeds leuker ;)
Ik moet nog heel veel dingen bekijken en bestuderen, er zijn namelijk veel -ongewenste effecten-, die hun oorzaak hebben en waarvoor een oplossing moet worden gezocht.
.
De code waarmee ik nu werk is zeer uitgebreid omdat ik er van allerlei effecten in probeer weer te geven voor onderzoek etc.
.
Ik zal proberen komende tijd even een basis-code neer te zetten, die is niet zo ingewikkeld als dat het lijkt wanneer je voor de eerste keer de genoemde Wikipedia pagina's bekijkt.
.
Zondagavond (30-08-2015) plaatste ik nog de volgende grafiek:

Grafiek 3:
Afbeelding
.
Grafiek 3 is opgebouwd uit de onderliggende sinussen en verwacht rond Dinsdag 1-9-2015 een draai omlaag.
.
We gaan het meemaken, handel er a.u.b. niet op.
.
Vriendelijke groet,
JanS ;)
Janus
Berichten: 1463
Lid geworden op: wo jan 30, 2008 2:07 am
Contacteer:

Re: Fast Fourier Transform

Bericht door Janus »

Nu weet ik wel dat veel bezoekers hier alleen komen voor de code van een indicator, en die ga ik ook plaatsen, maar het is ZO belangrijk dat je weet wat een indicator eigenlijk doet voordat je 'm gebruikt, omdat wanneer je niet weet wat die indicator doet er al snel misbruik ontstaat met alle gevolgen van dien.
Zo zal ik in de komende tijd ook laten zien door middel van mijn 'spectrum analyzer code' hoe gevaarlijk het is om zomaar een waarde voor een gemiddelde te kiezen; bij een verkeerde keuze gooi je namelijk heel kostbare informatie weg.
.
Om te begrijpen wat de Fourier analyse eigenlijk doet moeten we eerst weer even wat goniometrie ophalen.
Ik zal proberen dat zeer kort te houden, en haal alleen even de basis aan van dat wat we nodig hebben op dit moment.
In de goniometrie werken we met Sinus, Cosinus en Tangens.
Voor Fourier analyse hebben we de Tangens niet nodig, dus houden we over de Sinus en de Cosinus.
De Sinus en de Cosinus zijn waarden die behoren bij een hoek.
Stel de volgende rechthoekige driehoek:
Figuur 1:
Afbeelding
.
We zien hier een rechthoekige driehoek, met in het zwart aangeduid hoek A.
Het maakt in dit verband niet uit hoeveel graden die hoek is.
Een afspraak is nu dat de Sinus van hoek A vertegenwoordigt wordt door de verhouding: --> lengte overliggende zijde O/lengte schuine zijde S; ofwel Sinus(A) is O/S.
De volgende afspraak is nu dat de Cosinus van hoek A vertegenwoordigt wordt door de verhouding: -> lengte aanliggende zijde A / lengte schuine zijde S; ofwel Sinus(A) is A/S.
Simpel hè?
.
Oké, dan pakken we nu even een afbeelding erbij vanuit het stukje cyclus wat ik aangeraden heb om even door te lezen.
Figuur 2:
Afbeelding
U herkent deze afbeelding wel vanuit dat cyclus 'werkstukje'.
Stel nu dat we een bepaald punt van de Sinusvorm lijn een waarde willen geven, hoe doen we dat?
Ik heb in onderstaande figuur even een willekeurig punt gepakt.
Figuur 3:
Afbeelding
.
Het idee is nu als volgt: ik heb in een blauwe kleur punt X aangegeven op de weergeven Sinus vorm.
De verticale waarde (in dit geval weer kwaliteit omdat ik geen zin had een nieuwe tekening te maken ;) ) kunnen we herleiden via de Sin van hoek A.
Immers Sin(hoek-A) is overstaande gedeeld door de schuine, ofwel de overstaande zijde is de schuine S * Sin(hoek-A).
Zo kan ook de horizontale component worden berekend, wat immers onderdeel van de Cosinus van hoek A is.
De aanliggende zijde (de tijd in dit geval) is dan Schuine zijde S * Cos(hoek-A);
.
Om kort te gaan (ik wil de bedstee in) kunnen we dus elk punt van de sinus golfvorm aanduiden via de Sinus en Cosinus waarden.
.
We kunnen dit natuurlijk ook omdraaien.
We pakken een waarde voor de sinus vorm wat betreft tijd (= de inverse van frequentie) en kijken dan voor elk punt in de cirkel van 0 - 360 graden of de sinus golfvorm aanwezig is.
De integraal berekening die we in de huidige context daarvoor gebruiken geeft dan vanzelf aan via de output waarde of de onderzochte cyclus (wat betreft tijd/frequentie) wel of niet aanwezig is.
.
Dit was hoop ik een eenvoudige uitleg van het onderliggende van de Fourier analyse.
In de praktijk draait de richting van de pijl in de cirkel van bovenstaande figuren tegen de klok in.
In de praktijk gebruiken we geen graden maar radialen.
In de praktijk gebruiken we voor tijd de hoeksnelheid.
Maar ik wilde het eenvoudig houden, ik hoop dat dat gelukt is.
.
Komende avonden geen tijd, ik hoop in het komende weekend wat over de gebruikte code te plaatsen, maar ik wilde wat inzicht verschaffen over de ondergrond.
Ik hoop dat dit gelukt is.
.
Bij onduidelijkheden graag een bericht in deze topic, ik probeer dat dan toe te lichten.
Bedenk: domme vragen bestaan niet, wel domme mensen die niet willen vragen wat ze niet in eerste instantie begrijpen en daardoor de boot missen, behoor niet tot die laatste groep!
.
Vriendelijke groet,
JanS ;)
Janus
Berichten: 1463
Lid geworden op: wo jan 30, 2008 2:07 am
Contacteer:

Re: Fast Fourier Transform

Bericht door Janus »

Even wat toelichting op wat ik gisteravond snel neer schreef.
.
Figuur 1:
Afbeelding

In figuur 1 heb ik even wat tekst geplaatst in de cirkel links in de figuur.
U ziet een vector weergegeven in een dik-zwarte lijn, die draait tegen de klok in met de hoeksnelheid Afbeelding.
Hoe groter de hoeksnelheid, des te minder tijd om een Sinusgolf te plaatsen, dus kortere golflengte, een hogere frequentie dus.

Wanneer de cirkel wordt doorlopen ziet u dat er 2*Pi radialen worden doorlopen.
Bij punt B is de vector ten opzichte van punt A 90 graden gedraaid, en we zien dat dit een 1/2*Pi radialen is.
Bij punt C is dit 180 graden wat overeenkomt met Pi radialen etc.

TA-script werkt met radialen, dus we werken hier ook mee en we hoeven niets te vertalen naar graden.
De 2*Pi welke u 'straks' in de formule tegen komt heeft dan ook betrekking op een volledige cyclus (360-graden).

Wat wellicht gister avond ook niet helemaal uit de verf kwam is de noodzaak van differentiaal rekenen.
Laat u niet uit het veld slaan door de notatie wijze van dergelijke berekeningen die u ziet op de gegeven Wikipedia-links.
Het is gewoon een wiskundige noteringswijze om de limieten aan te geven waarbinnen gewerkt wordt, en de functie waarmee gewerkt wordt, en het aantal stukjes waarin het te bewerken traject wordt gehakt.
De rare lange f die altijd vooraf gaat aan zo'n notatie, met bovenaan en onderaan aan die f een getal geeft gewoon de limieten aan, en de vreemde f geeft aan dat alles opgeteld wordt.
Of is die vreemde f een s van sommatie?
.
Wellicht ook leuk om te bekijken is het stukje wat ik ooit geschreven heb genaamd: "onder de motorkap'.. te bereiken via de link: http://www.jstas.com/Motorkap/motorkap.htm.
.
Vriendelijke groet,
JanS ;)
Janus
Berichten: 1463
Lid geworden op: wo jan 30, 2008 2:07 am
Contacteer:

Re: Fast Fourier Transform

Bericht door Janus »

Ik had afgelopen dagen beloofd om een stukje code te plaatsen wat ik gebruik bij dit onderzoek.

Het idee kwam niet van mezelf, u kan het lezen in het werk van Henry Ludwell Moore en om precies te zijn in zijn in 1914 geschreven boek: 'Economic Cycles: Their Law and Couse'.
Een pdf van dit boek is te downloaden onder de volgende link:
http://socserv2.socsci.mcmaster.ca/econ ... Cycles.pdf
Op pagina 12 en 13 vind u zijn uitwerking van het idee van Fourier.
A0, A1 en B1 zijn de formules die ik gebruik in dit stukje code.

Toevoeging per April-2023:
Ik zag dat dit boekwerk niet meer te vinden is onder bovenstaande link.
Omdat het boek vrij beschikbaar is in: -the public domain- heb ik het op mijn website gezet als een pdf.
De pdf start met een zwart scherm / pagina.
De betreffende link is:
http://www.jstas.com/Books/Economic%20c ... 0Moore.pdf


Met deze code moet u niet gaan handelen, het is alleen maar bedoelt om een idee te geven, het moet verder uitgewerkt worden voordat u er echt wat mee kan.
Ook het input filter wat ik in deze versie gebruik zal ik waarschijnlijk gaan vervangen door iets anders, ik loop te kijken op de wikipedia site:
https://en.wikipedia.org/wiki/Window_fu ... .29_window

Hieronder het stukje code, bedenk dat ik niet kan programmeren maar net zolang knutsel totdat er iets uitkomt ;)
Er kunnen stukjes in de code staan die niet meer gebruikt worden maar een restant zijn van eerder stukje code.
De code is traag, reken op 3-4 seconden reactie tijd.

Code: Selecteer alles

{- Filename: FFT-proef -}

// Fast Fourier transformatie
// ideeën voor verdere uitwerking
// www.jstas.com
// versie 1.00
// 06-09-2015

Type
      TStrength = record
                   Index: integer;
                   Value: real;
                  End;
TTabelStrength = array of TStrength;

Var
Tllr,MaxCycle,Squelch : Integer;
SquelchNiv : Real;
HpsC, FiltC   : TSeries;
OutputFilter : Boolean;
TabelA1 : Array [0..300] Of Extended;
TabelB1 : Array [0..300] Of Extended;
TopValue : Array[0..300] Of Integer;
Spectrum,Spectrum2,sHulp : TSeries;
StrengthUnSort,TabelStrength:  TTabelStrength;

//******************************************************************************

Procedure Init(DatB,DatE:TDateTime);
Begin
With Indicator Do
 Begin
  RequiredBars := 2*Trunc(DatE-DatB);
  If (RequiredBars<600) Then RequiredBars := 600;
 End;
End;
//******************************************************************************

Function A_zero(DatB,DatE:TDateTime):Real;
Var
i : Integer;
Begin
Tllr := 0;
For i := 1 To BarCount-1 Do
 Begin
  If (DateTime[i] >= DatB) And (DateTime[i]<= DatE)Then
   Begin
    If IsValid(FiltC[i]) Then
     Begin
       Tllr := Tllr+1;
       Result := (Result + FiltC[i]);
     End;
   End;
 End;
If (Tllr>0) Then  Result := Result/Tllr;
End;
//******************************************************************************

Function A_one(Mcycle,Cycle:Integer;DatB,DatE:TDateTime):Real;
Var
i,Sample: Integer;
Begin
For i := 0 To BarCount-1 Do
 Begin
  If (DateTime[i] >= DatB) And (DateTime[i]<= DatE) Then
   Begin
    Result := Result+((2/Mcycle)*FiltC[i]*Cos((2*Pi*Sample/Cycle)));
   Sample := Sample+1;
   End;
 End;
 Result := Result/Cycle;
End;
//******************************************************************************

Function B_one(Mcycle,Cycle:Integer;DatB,DatE:TDateTime):Real;
Var
i,Sample : Integer;
Begin
For i:= 0 To BarCount-1 Do
 Begin
  If (DateTime[i] >= DatB) And (DateTime[i]<= DatE) Then
   Begin
     Result := Result+((2/Mcycle)*FiltC[i]*Sin((2*Pi*Sample/Cycle)));
    Sample := Sample +1;
   End;
 End;
 Result := Result/Cycle;
End;
//******************************************************************************
Procedure QSortTabel(Tabel: TTabelStrength;Left,Right:Integer);
Var
Pivot: TStrength;
p_ptr, l_ptr, r_ptr: integer;
Begin
 l_ptr := left;
 r_ptr := right;
 pivot := Tabel[left];
  While left < right do
   Begin
    While (Tabel[right].Value <= pivot.Value) and (left < right) do dec(right);
     If left <> right Then
      Begin
       Tabel[left] := Tabel[right];
       inc(left);
      End;
    While (Tabel[left].Value >= pivot.Value) and (left < right) do inc(left);
     If left <> right Then
      Begin
       Tabel[right] := Tabel[left];
       dec(right);
      End;
   End;
 Tabel[left] := pivot;
 p_ptr := left;
 left  := l_ptr;
 right := r_ptr;
  If left  < p_ptr Then QSortTabel(Tabel, left, p_ptr-1);
  If right > p_ptr Then QSortTabel(Tabel, p_ptr+1, right);
End;
//******************************************************************************
Procedure SortTabel(Var Tabel: TTabelStrength);
Var
lTabel: Integer;
Begin
 lTabel := GetArrayLength(Tabel);
 If lTabel > 0 Then QSortTabel(Tabel, 0, lTabel-1);
End;

//*****************************************************************************
Function Sinus(Per:Integer;Ampl,Fase:Real):TSeries;
Var
i : Integer;
Begin
 For i := 0 To BarCount-1 Do
   Begin
     Result[i] := Sin(2*Pi*(i+fase)/Per)*Ampl;
   End;
End;
//******************************************************************************

Function Ehlersband(sData:TSeries;SelectFilter,vHp,vLp:Integer):Tseries;
Var
i : Integer;
c1,c2,c3,Alpha1,PerLl  : Double;
Begin
HpsC   := FillSeries(CreateSeries(BarCount),0);
PerLl  := 1/vLp;
Alpha1 := (Cos(Sqrt(2)*Pi/vHp)+Sin(Sqrt(2)*Pi/vHp)-1)/Cos(Sqrt(2)*Pi/vHp);
c1 := (1-2*Exp(-PerLl*Sqrt(2)*Pi)*Cos(PerLl*Sqrt(2)*Pi)
                                                  +Sqr(Exp(-PerLl*Sqrt(2)*Pi)));
c2 := 2*Exp(-PerLl*Sqrt(2)*Pi)*Cos(PerLl* Sqrt(2)*Pi);
c3 := Sqr(Exp(-PerLl*Sqrt(2)*Pi));

If (SelectFilter=0) Or (SelectFilter=1)Then
Begin
 For i := 2 To BarCount-1 Do
  Begin
   HpsC[i] := Sqr(1-Alpha1/2)*(sData[i]-2*sData[i-1] + sData[i-2])+
              2*(1-Alpha1)*HpsC[i-1]-Sqr(1-Alpha1)*HpsC[i-2];
  End;
End;

If (SelectFilter=2) Then HpsC := sData;

If (SelectFilter=0) Or (SelectFilter=2) Then
Begin
 For i := 3 To BarCount-1 Do
  Begin
   Result[i] := c1*0.5*(HpsC[i]+HpsC[i-1])+c2*FiltC[i-1]-c3*FiltC[i-2];
  End;

End;

If (SelectFilter=1) Then Result := HpsC;

End;
//******************************************************************************

Procedure FillTables_A1_A2(DatB,DatE:TDateTime);
Var
j,n: Integer;
hlpA,HlpB : Extended;
Begin
HlpA:=0;
HlpB:=0;
 For j := 3 To MaxCycle Do
 Begin
  N := Trunc(Tllr/j)*j;
  If N<1 Then N:=1;
  TabelA1[j]:=A_one(N,j,DatB,DatE);
  TabelB1[j]:=B_one(N,j,DatB,DatE);
  TabelStrength[j].Index  := j;
  StrengthUnSort[j].Index := j;
  TabelStrength[j].Value  := Sqrt(Sqr(TabelA1[j])+Sqr(TabelB1[j]));
  StrengthUnSort[j].Value := Sqrt(Sqr(TabelA1[j])+Sqr(TabelB1[j]));
 End;
End;
//******************************************************************************

Procedure SpecTrumWeergHor(Display:Integer);
Var
Hulp,i,j : Integer;
Deler : Real;
Weergave : Array[1..300] Of TDateTime;
Begin

If (Display=0) Then sHulp := MultiplySeriesBy(RSI(C,14),(MaxCycle/100));
Deler := TabelStrength[0].Value/300;
If (Deler <=0) Then Deler := 1;

j:= 300;
If BarCount>=300 Then Begin
For i :=  BarCount-300 To BarCount-1 Do
 Begin
   Weergave[j] := DateTime[i];
   j := j-1;
  End;
 End;

For j := 3 To MaxCycle Do
 Begin
  Hulp := Trunc(Ceil(StrengthUnSort[j].Value/Deler));
  If (Hulp>-0) And (Hulp<=300) Then
     CreateTrendLine(now            ,StrengthUnSort[j].index,
                     Weergave[Hulp] ,StrengthUnsort[j].Index);
 End;
End;
//******************************************************************************
Procedure FillTopValueTable_sSpectrum(Display:Integer);
Var
Hlp2 : Real;
Hlp3 : Boolean;
Hlp4,i,j : Integer;

Begin

For j:= 0 To 300 Do
 Begin
   TopValue[j] := -1;
 End;
 
 j := 3;
If (BarCount>=MaxCycle) Then
Begin
   For i := (BarCount-MaxCycle) To BarCount-1 Do
    Begin
     If (i=(BarCount-MaxCycle)) Then Hlp4 := i;
     Spectrum[i] := StrengthUnsort[j].Value;
     j := j +1;
    End;

   For i := (BarCount-(MaxCycle-1)) To BarCount-1 Do
    Begin

     If Spectrum[i] > Spectrum[i-1] Then
      Begin
       Hlp2 := Spectrum[i];
       Hlp3 := True;
      End;

      If (Spectrum[i] < Spectrum[i-1]) And (Hlp3) Then
       Begin
        Spectrum2[i-1] := Hlp2;
        Hlp3 := False;
       End;

    End;
End;

SquelchNiv := Squelch/100 * TabelStrength[0].Value;
 If (Display=1) Then
     With CreateTrendLine(0,SquelchNiv,0,SquelchNiv) Do
      Begin
        Color := ClRed;
        X1Pct := 0;
        X2Pct := 100;
      End;
      
For i := 1 To BarCount-1 Do
Begin
 If IsValid(Spectrum2[i]) Then
  Begin
   TopValue[i-Hlp4+3] := 1;
   If (Display=1) Then
    Begin
     With CreateText(DateTime[i],0,IntToStr(i-Hlp4+3)) Do
      Begin
       Color := ClRed;
       Font.Size  := 8;
      End;
    End;
  End;
End;

End;
//******************************************************************************

Function Compositie(DatB:TDateTime):TSeries;
Var
DTimeLast,cDate,rDate : TDateTime;
ValueLast : Real;
Hulp : Real;
hulpi : Boolean;
DatBi : Integer;
Sample,i,j,fhelp : Integer;
CycleDisplay,sResultA: TSeries;
FutureTable : Array[0..50] Of Real;

Begin
CycleDisplay  := FillSeries(CreateSeries(BarCount+50+2),0);
Sample := 0;
sResultA   := FillSeries(CreateSeries(BarCount+50+2),0);

Hulpi :=True;
For i:= 1 To BarCount-1 Do
 Begin
   If (DateTime[i]>=DatB) And Hulpi Then
    Begin
     DatBi:= i;
     Hulpi := False;
    End;
 End;

For j := 1 To MaxCycle Do      //300
 Begin
   Hulp :=Abs(TabelA1[j])+Abs(TabelB1[j]);
  If (TopValue[j]=1) And (Hulp >=SquelchNiv) Then
     Begin

      For i := 0 To (BarCount-1+50+2) Do
       Begin
         If  (i>=DatBi) THen
          Begin
           CycleDisplay[i] :=   (TabelA1[j]*Cos((2*Pi*Sample/j)))
                              + (TabelB1[j]*Sin((2*Pi*Sample/j)));
           CycleDisplay[i] := CycleDisplay[i] * StrengthUnsort[j].Value;

           sResultA[i] := sResultA[i] + CycleDisPlay[i];
           Sample := Sample +1;
          End;
         If (i=BarCount-1) Then DTimeLast := DateTime[i];
         If (i=BarCount-1) Then ValueLast := sResultA[i];
       End;

   End; //topvalue
 End; //j


For i := 0 To BarCount-1 Do
 Begin
  Result[i] := sResultA[i];
 End;

For i:= BarCount To (BarCount-1+50) Do
 Begin
  fhelp := i-BarCount+1;
  FutureTable[fhelp] := sResultA[i];
 End;

/////////////////

FutureTable[0] := ValueLast;

cDate := DTimeLast;
rDate := cDate+1;
If (DayOfWeek(cDate)=6) Then rDate := cDate+3;

For i := 0 To 49 Do
 Begin
   With    CreateTrendLine(cDate,FutureTable[i] ,rDate,FutureTable[i+1]) Do
    Begin
     Color := ClGreen;
     Width := 2;
    End;

   cDate := cDate+1;
   If (DayOfWeek(cDate)=7) Then CDate := cDate+2;
   rDate := rDate+1;
   If (DayOfWeek(rDate)=7) Then rDate := rDate+2;
 End;
 
End;
//******************************************************************************

Procedure Series_Weergave(sSinus1,sSinus2,sSinusTot,sSpecWrgv,
                          sSpecWrgv2,DisplayComp,sHulp:TSeries);
//Var
//per : Integer;
Begin
With CreateLine(sSinus1) Do
       Begin
        Name := 'Sinus1';
        Color := ClBlue;
       End;
With CreateLine(sSinus2) Do
       Begin
        Name := 'Sinus2';
        Color := ClRed;
       End;

With CreateLine(sSinusTot) Do
       Begin
        Name := 'SinusTot';
        Color := ClBlack;
       End;

With CreateLine(sSpecWrgv) Do
   Begin
    Color := ClGray;
    LineType := LtBar;
   End;

With CreateLine(sSpecWrgv2) Do
   Begin
    Color := ClRed;
    LineType := LtBar;
   End;
   
With CreateLine(DisplayComp) Do
   Begin
    Color := ClPurple;
    Name := 'Compositie';
   End;

With CreateLine(sHulp) Do
   Begin
    Color := ClWhite;
    Name := 'hulplijn';
   End;
   
End;
//******************************************************************************
// ****************  MAIN  ************************
Var
DatBeg, DatEnd                               : TDateTime;
WgvSin1, WgvSin2, WgvSinT                    : Boolean;
sSpecWrgv, sSpecWrgv2, DisplayComp, sSinus1,
sSinus2, sSinusTot, sData1, sData2, sDataTot : TSeries;
Venster, DataKeuze, FilterKeuze, EhlerFilter : String;
Datachoice, FilterChoice, BandFilter, ValHp,
ValLp, MAper, Display, PerSin1, PerSIn2      : Integer;
A0,AmpSin1,AmpSIn2,FasSin1,FasSin2           : Real;

Begin
SetArrayLength(TabelStrength ,300);
SetArrayLength(StrengthUnSort,300);
Spectrum    := CreateSeries(BarCount);
Spectrum2   := CreateSeries(BarCount);
sSpecWrgv   := CreateSeries(BarCount);
sSpecWrgv2  := CreateSeries(BarCount);
sHulp       := CreateSeries(BarCount);
DisplayComp := CreateSeries(BarCount);
sSinus1     := CreateSeries(BarCount);
sSinus2     := CreateSeries(BarCount);
sSinusTot   := CreateSeries(BarCount);
FiltC       := FillSeries(CreateSeries(BarCount),0);
sData1      := FillSeries(CreateSeries(BarCount),0);
sData2      := FillSeries(CreateSeries(BarCount),0);
sDataTot    := FillSeries(CreateSeries(BarCount),0);

DataKeuze   := 'Koers Fonds/Index ' #9
               'Enkelvoudige Sinus' #9
               'Twee-voudige Sinus'   ;

FilterKeuze := 'Geen                ' #9
               'Ehlers band-doorlaat' #9
               'MA                  '   ;

EhlerFilter := 'HighPass + LowPass'#9
               'HighPass  '        #9
               'LowPass   '          ;
               
Venster     := 'Spectrum Horizontaal'#9
               'Spectrum Verticaal  '#9
               'Sinus en/of Composite';

DatBeg := CreateParameterDate('StartDatum',EncodeDate(2013,8,20));
DatEnd := CreateParameterDate('EindDatum',Now);

Display := CreateParameterSelect('Weergave in venster:',Venster,1,False);

DataChoice :=
         CreateParameterSelect('Welke Data te analyseren:',DataKeuze,0,False);
FilterChoice :=
         CreateParameterSelect('Te gebruiken filter',Filterkeuze,1,False);
BandFilter :=
         CreateParameterSelect('Stel Ehler filter in:',EhlerFilter,0,False);
OutputFilter := CreateParameterBoolean('Output filter gebruiken?',False,False);
ValHp := CreateParameterInteger('Waarde HighPass filter:',15,200,48,False);
ValLp := CreateParameterInteger('WaardeLowPass filter:',3,20,10,False);
MAper := CreateParameterInteger('Moving Average Period:',0,200,14,False);
Squelch := CreateParameterInteger('Squelch in % ',0,100,80,False);
WgvSin1 := CreateParameterBoolean('Sinus-1 Weergeven?',True,False);
WgvSin2 := CreateParameterBoolean('Sinus-2 Weergeven?',True,False);
WgvSinT := CreateParameterBoolean('Sinus-Opgeteld Weergeven?',True,False);
PerSin1 := CreateParameterInteger('Periode Sinus-1:',1,300,30,False);
AmpSin1 := CreateParameterReal('Amplitude Sinus-1:',0.1,10000,100,False);
FasSin1 := CreateParameterReal('Fase Sinus-1:',0,1000,0,False);
PerSIn2 := CreateParameterInteger('Periode Sinus-2:',1,300,52,False);
AmpSIn2 := CreateparameterReal('Amplitude Sinus-2:',0.1,10000,100,False);
FasSin2 := CreateParameterReal('Fase Sinus-2:',0,1000,0,False);

Case DataChoice Of
 0:  sDataTot := C;
 1:  Begin
      sData1 := Sinus(PerSin1,AmpSin1,FasSin1);
      sDataTot := sData1;
      If WgvSin1 And (Display=2) Then sSinus1 := sData1;
     End;
 2:  Begin
      sData1 := Sinus(PerSin1,AmpSin1,FasSin1);
      sData2 := Sinus(PerSin2,AmpSin2,FasSin2);
      sDataTot    := AddSeries(sData1,sData2);
      If (Display=2) Then
       Begin
        If WgvSin1 Then sSinus1 := sData1;
        If WgvSin2 Then sSinus2 := sData2;
        If WgvSinT Then sSinusTot := sDataTot;
       End;
     End;
End;

Case FilterChoice Of
 0 : FiltC := sDataTot;
 1 : FiltC := EhlersBand(sDataTot,BandFilter,ValHp,ValLp);
 2 : FiltC := MA(sDataTot,MAWeighted,MAper);
 End;

Init(DatBeg,DatEnd);
A0 := A_zero(DatBeg,DatEnd);   //return Tllr

MaxCycle := CreateParameterInteger('Maximale cycl:',3,300,100,False);
   If (MaxCycle>(Tllr/2)) Then MaxCycle := Trunc(Tllr/2);
   If (MaxCycle<1) Then MaxCycle := 3;

FillTables_A1_A2(DatBeg,DatEnd);
SortTabel(TabelStrength);
FillTopValueTable_sSpectrum(Display);

Case Display Of
 0 : SpectrumWeergHor(Display);
 1 : Begin
      sSpecWrgv  :=  Spectrum ;
      sSpecWrgv2 :=  Spectrum2;
     End;
 2 : DisplayComp := Compositie(DatBeg);
End;

Series_Weergave(sSinus1, sSinus2, sSinusTot, sSpecWrgv,
                                             sSpecWrgv2, DisplayComp, sHulp);
End.
.
Laatst gewijzigd door Janus op vr apr 07, 2023 11:49 pm, 1 keer totaal gewijzigd.
Vriendelijke groet,
JanS ;)
Janus
Berichten: 1463
Lid geworden op: wo jan 30, 2008 2:07 am
Contacteer:

Re: Fast Fourier Transform

Bericht door Janus »

Leuk, ik kwam deze topic weer tegen toen ik een bepaald stukje code zocht.
In grafiek 3 in de eerste topic hierboven was de verwachting dat begin september-2015 de koers een draai omlaag zou geven.
Dit was via de in de laatste topic gegeven experimentele code.
*
Ik had in de topic net hierboven een link geplaatst naar het boekwerk van Henry Ludwell Moore, die helaas niet meer werkt, maar het boek zit in het public-domain, dus ik denk dat ik het mag vrijgeven.
Ik heb de link naar dat boek op mijn website in de topic hierboven geplaatst.

Ik plaats even de grafiek van augustus-september-2015 waarin te zien is dat de koers begin september inderdaad omlaag draaide.
Dat is leuk om te zien, en een stimulans om de komende tijd wellicht weer wat tijd in dit fenomeen te steken.
Wanneer u geïnteresseerd bent in dit model dan is daar veel info over te vinden op de website van Lars von Thienen: https://whentotrade.com/ , en natuurlijk in zijn twee boeken die hij heeft gepubliceerd omtrent dat onderwerp.
.
Hieronder vindt u de grafiek die het koersverloop van begin September 2015 laat zien.
Niet om mijn 'gelijk' aan te tonen, maar om te laten zien dat er potentie in deze manier van 'koers-verwachting' zit.
.
Afbeelding
.
Vriendelijke groet,
JanS ;)
Plaats reactie