ArrayResize funktioniert nicht

 

Hey ho!

bastel gerade an einem Indikator herum. Der Indi soll u.A. die Standardabweichung eienes Arrays bestimmen.


hierzu habe ich aus folgender bibliothek includierd:
#include <Math\Stat\Math.mqh>

da deren MathStandardDeviation() lediglich die Standardabweichung eines Arrays bestimmt, muss ich den Teil aus meinem Array rauskopieren, den ich möchte, nämlich die letzten "StdPeriod"

ArrayCopy(rawStd,raw,0,i-StdPeriod,i);
StdDev[i] = MathStandardDeviation(rawStd);


Soweit so gut.

Wenn ich allerdings die StdPeriode ändern möchte, müsste ich zugleich das Statische array rawStd[] auf die selbe größe verändern. die funktionierende aber sehr umständliche Version ist hier gepostet:

input int StdPeriod = 33;  //Std Period


//--- indicator buffers

double raw[];
double rawStd[33];


//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
{


    SetIndexBuffer(0, volNormalized, INDICATOR_DATA);
    SetIndexBuffer(1, volaC, INDICATOR_COLOR_INDEX); 
    SetIndexBuffer(2, StdDev, INDICATOR_CALCULATIONS);
    SetIndexBuffer(3, raw, INDICATOR_CALCULATIONS);  
    SetIndexBuffer(8, Max, INDICATOR_CALCULATIONS);
    SetIndexBuffer(9, Min, INDICATOR_CALCULATIONS);


Ich wollte das ganze damit lösen, dass ich ArrayResize() in der Onitinit() verwende, allerdings kommt danach nur kraut und rüben raus. das Array wird nach jedem Tick wieder dynamisch auf eine größe über 1000 verstellt. selbstwenn ich die arrayresize in die Ontick mache, und jedesmal das array neu anpasse, spuckt mein indikator alle aberr keine lofgischen Werte aus. Villeicht wisst ihr, wie ich dem entgegnen kann... :)


input int StdPeriod = 33;  //Std Period


//--- indicator buffers

double raw[];
double rawStd[];


//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
{

 ArrayResize(rawStd,StdPeriod); // ----- Array resize in oninit()

    SetIndexBuffer(0, volNormalized, INDICATOR_DATA);
    SetIndexBuffer(1, volaC, INDICATOR_COLOR_INDEX); 
    SetIndexBuffer(2, StdDev, INDICATOR_CALCULATIONS);
    SetIndexBuffer(3, raw, INDICATOR_CALCULATIONS);  
    SetIndexBuffer(8, Max, INDICATOR_CALCULATIONS);
    SetIndexBuffer(9, Min, INDICATOR_CALCULATIONS);
 

Du zeigst nicht, was mit rawStd[] in OnCalculate() passiert.

Du könntest eine Extrafunktion schreiben, der Du das ganze Array und die Von-, Bis-Indices übergibst, um ein tmp-Array der Größe mit ArrayCops() zu erstellen, um dann dort die StdAbw. zu berechnen und zurückzugeben.

 
okay, dann einfach mal den ganzen Block :)

hier, und im Anhang der Rest.. Wollte es nicht posten, weil es etwas unordentlich ist..

int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tickVolume[],
                const long &volume[],
                const int &spread[])
{
  
  if(rates_total<Vola_Period_Slow||rates_total<StdPeriod)return(0);

  int i;
  int limit = 0;

  if(prev_calculated == 0 && MaxBarsBack>0)
    limit = MathMin(MathMax(rates_total - MaxBarsBack, 0), rates_total-Vola_Period_Fast*2);
  else
    limit = MathMax(prev_calculated - 1, 0);
//--- the main loop of calculations

  for ( i =limit; i < rates_total; i++)
  {
    if(i<=Vola_Period_Fast||i<=StdPeriod)continue;

//+------------------------------------------------------------------+
//|main calculation                                                  |
//+------------------------------------------------------------------+
     raw[i] = MathLog(close[i]/close[i-1]);
    if(i<=StdPeriod)continue;


ArrayCopy(rawStd,raw,0,i-StdPeriod,i);
StdDev[i] = MathStandardDeviation(rawStd);//Coeff;


//+------------------------------------------------------------------+
//|normalize it                                                      |
//+------------------------------------------------------------------+
     if(i<=100)continue;
      Max[i] = StdDev[ArrayMaximum(StdDev, i-100+1, 100)]; //finde das Maxima im High[] von i-DensityPeriod bis zur aktuellen Kerze i
      Min[i] =  StdDev [ArrayMinimum(StdDev, i-100+1, 100)]; //finde das Minima im Low[] von i-DensityPeriod bis zur aktuellen Kerze i

      if(!CalcRelVol)
      {
        if(Max[i]-Min[i] == 0)volNormalized[i] = 0;
        else volNormalized[i] = (StdDev[i] - Min[i]) / (Max[i] - Min[i]);
      }
      
Dateien:
 

Ich hab's jetzt nicht kontrolliert und auswendig weiß ich es jetzt auch nicht, aber

ArrayCopy(rawStd,raw,0,i-StdPeriod,i);
StdDev[i] = MathStandardDeviation(rawStd);//Coeff;

ist die Größe jetzt genau StdPeriod oder eins mehr => Debugger?

raw[i] = MathLog(close[i]/close[i-1]);

Weißt Du welche Werte raw[i] annehmen kann, die snd nicht symetrisch um 1: 0,8=> -0.223 und 1,2 = 0.182, damit hätte die StdAbw. einen Hang nach unten.

Mach Dir inmal eine Excel- (LO-) Tabelle mit den Werten und schau, ob das einen Sinn ergibt.

Übrigens, die Gleicheit von double-Werten ist kritisch, daher würde ich statt:

if(Max[i]-Min[i] == 0)
if(Max[i]-Min[i] < _Point*0.001)

schreiben.

 
Carl Schreiber #:

Ich hab's jetzt nicht kontrolliert und auswendig weiß ich es jetzt auch nicht, aber

ist die Größe jetzt genau StdPeriod oder eins mehr => Debugger?

Weißt Du welche Werte raw[i] annehmen kann, die snd nicht symetrisch um 1: 0,8=> -0.223 und 1,2 = 0.182, damit hätte die StdAbw. einen Hang nach unten.

Mach Dir inmal eine Excel- (LO-) Tabelle mit den Werten und schau, ob das einen Sinn ergibt.

Übrigens, die Gleicheit von double-Werten ist kritisch, daher würde ich statt:

schreiben.

Danke für den _Point*0.001 tipp :)!

zu: " ist die Größe jetzt genau StdPeriod oder eins mehr => Debugger? "

die korrigierte Arraycopy() lautet so:

ArrayCopy(rawStd,raw,0,i-StdPeriod+1,StdPeriod);


Wenn ich nicht ganz falsch liege, dann ist der ln() sowie ich ihn verwende symmetrisch.

bsp:

ist close[i-1] = 10

unf für einen Kursanstieg ist close[i] =100
und für einen Kursabfall ist close[i]=1

demnach wären für beide fälle mit:

ln(close[i]/close[i-1])

für Kursanstieg = ln(1/10) = -2,302

für Kursabfall = ln(100/10) = +2,302

bei starken Kursbewegeungen, also wenn close[i] >> oder << close[i-1] ist, schlägt der ln() sozusagen aus.

davon dann die Standardabweichung, sollte eine Range relativ gut filtern können:


 

Schau Dir die LN-Funktion, sie ist eine immer ansteigende Funktion, wobei die Steigung steig abnimmt - d.h. der Unterschied links ist immer(!) größer als rechts (die Ableitung von ln(x) = 1/x) - hier an:

https://rechneronline.de/funktionsgraphen/

Der Quotient von close[i]/close[i-1] pendelt um Eins.

Spiel mit der Tabelle, der blaue Wert ist gedacht zu ändern.

Funktionsgraphen zeichnen - Plotter
  • rechneronline.de
Hier können Funktionsgraphen von zahlreichen mathematischen Funktionen gezeichnet werden, inklusive Ableitung und Integral.
Dateien:
Ln.zip  20 kb
 
ich muss schon sagen carl...

DANKE!
 
du hast absolut recht, weder speigel, noch punktsymmetrisch. Echt hilfreich.

ich bräuchte eher sowas wie ne parabel um 1.

sowas wie: (x-1)^2
 
Man sollte nicht einfach so seiner Vorstellung glauben, sondern sie immer überprüfen.
 
oder eine andere Idee. Für Werte >1 den roten graph & für werte <1 den blauen graph

 

Da könntest Du dann das versuchen: e^(abs(0,5*(x-1)))-1.  // statt 0,5 gehen 0,1 .. 0,9

Die Frage ist, was ist für Dein Ziel am besten geeignet.