Erster Meilenstein erreich: Die Daten können aus der Datenbank ausgelesen und weiterverarbeitet werden. Als nächsten Schritt versuche ich daraus einen Indikator zu generieren.
Hier der Code:
//+------------------------------------------------------------------+//| SQL_EA.mq5 |//| Copyright 2021, claudius Walter |//| https://www.walter.claudius@aol.de |//+------------------------------------------------------------------+double quoteAssetVolume;
int numberOfTrades;
double takerBuyBaseAssetVolume;
double takerBuyQuoteAssetVolume;
datetime candleOne;
datetime lastM1Bar;
datetime newM1Bar;
int db;
string filename="AAVEUSDT.db";
intOnInit()
{
return(INIT_SUCCEEDED);
}
voidOnTick()
{
if(CheckNewM1Bar(_Symbol))
{
//--- Öffnen einer Datenbank im Verzeichnis Common des Terminals
db=DatabaseOpen(filename, DATABASE_OPEN_READONLY | DATABASE_OPEN_COMMON);
if(db==INVALID_HANDLE)
{
Print("DB: ", filename, " open failed with code Database open ", GetLastError());
}
//--- Zeit und Datum der 1. Kerze abfragen und in eine String variable convertieren
candleOne = iTime(_Symbol,PERIOD_CURRENT,1);
string sqlCommand = " SELECT * FROM test3 WHERE OpenTime='";
StringAdd(sqlCommand,TimeToString(candleOne));
StringAdd(sqlCommand,":00'");
//---Handle für DatabaseRead() erzeugenint request=DatabasePrepare(db, sqlCommand);
if(request==INVALID_HANDLE)
{
Print("DB: ", filename, " request failed with code Database prepare ", GetLastError());
DatabaseClose(db);
}
//--- Printe die Spalte mit dem candleOne Datum
for(int i=0; DatabaseRead(request); i++)
{
//--- read the values of each field from the obtained entryif(DatabaseColumnDouble(request, 1, quoteAssetVolume) &&
DatabaseColumnInteger(request, 2, numberOfTrades) &&
DatabaseColumnDouble(request, 3, takerBuyBaseAssetVolume)&&
DatabaseColumnDouble(request, 4, takerBuyQuoteAssetVolume))
{
Print(quoteAssetVolume," ",numberOfTrades," ",takerBuyBaseAssetVolume," ",takerBuyQuoteAssetVolume);
}
else
{
Print(i, ": DatabaseRead() failed with code database read ", GetLastError());
DatabaseFinalize(request);
DatabaseClose(db);
}
}
//--- Anfrage beendenDatabaseFinalize(request);
//--- Datenbank schließenDatabaseClose(db);
}
}
//---Gibt true aus, sobald eine neue Kerze erscheintbool CheckNewM1Bar(string CurrentSymbol)
{
datetime lastM1Bar²[];
//--- Get the opening time of the current bar// If an error occurred when getting the time, print the relevant messageif(CopyTime(CurrentSymbol,PERIOD_M1,0,1,lastM1Bar²)==-1)
Print(__FUNCTION__,": Error copying the opening time of the bar: "+IntegerToString(GetLastError()));
//--- If this is a first function call
lastM1Bar = lastM1Bar²[0];
if(newM1Bar==NULL)
{
//--- Set the time
newM1Bar=lastM1Bar;
Print(__FUNCTION__,": Initialization ["+CurrentSymbol+"]["
+TimeToString(lastM1Bar,TIME_DATE|TIME_MINUTES|TIME_SECONDS)+"]");
return(false);
}
//--- If the time is differentif(newM1Bar!=lastM1Bar)
{
//--- Set the time and exit
newM1Bar=lastM1Bar;
return(true);
}
//--- If we have reached this line, then the bar is not new, so return falsereturn(false);
}
Beispielhaft noch die verwendete Tabelle:
Ein großes Dankeschön für eure Ideen und Ratschläge!
Schön wenn jemand die Arbeit aufbringt und eine Lösung erarbeitet.
Jetzt kannst du einen Service oder ein Script programmieren und mit diesem die Datenbank füttern, während der Indikator aus der DB liest.
Schon bist du bei Multiinstanz-Lösungen...
Fürs Forum!
Möglicherweise werde ich das auch benötigen, mal sehen. Momentan sind diese Daten nur für Backtests ausgelegt. Wenn ich allerdings live gehe, müsste ich den Indikator oder die Datenbank mit echtzeitdaten speisen. Wenn das ohne andere Programmierebenen (bspw. Python) funktioniert, wäre das eine elegante und saubere Lösung.
Habe versucht, die Datenbankabfrage in einen Indikator umzusetzen. Leider zeigt mir das Journal folgenden Fehler an:
der Error steht dafür, dass die Datei der Datenbank blockiert ist. Was auch immer genau damit gemeint ist.
Laut Debugger wird mir der Buffer mit werten befüllt. Nur zeigt das Indikatorfenster nichts an.
Das hier ist der Indikator
Was sagt ihr dazu? Ich habe noch nicht so oft mit Indikatoren gearbeitet . Ich vermute allerdings, dass es mit der for_Schleife zusammenhängt
Nein Spaß, aber das habe ich mich wirklich gefragt... Du möchtest Zahlen aus der Tabelle holen und in einem "Oszillatorfenster" anzeigen lassen.
Du müsstest dazu mit der Schleife den tradesBuffer[] befüllen. Jedoch nicht immer mit dem selben Wert numberOfTrades. Auch numberOfTrades müsstest Du mit dem Index aus der Tabelle holen, indem Du "Select" wie einen Index verwendest. Dadurch gibst Du die Zeile an. Nur wo das geht ist mir nicht klar.
Das ginge aber erstmal nur für M1 TF. Für M15 müsstest Du immer 15 beieinanderliegende Werte addieren.
Warum hast Du den Index i durch j ersetzt? Der Index im Kopf der Schleife muss der selbe sein wie im Körper.
Dann zählt die Schleife durch:
tradesBuffer[0]= numberOfTrades[0]; tradesBuffer[1]= numberOfTrades[1]; tradesBuffer[2]= numberOfTrades[2]; tradesBuffer[3]= numberOfTrades[3]; tradesBuffer[4]= numberOfTrades[4]; und so weiter. Das macht Alles die Schleife für Dich, wenn Du sie richtig einrichtest. Du musst das halt irgendwie mit dem Databasekram hinbekommen, dass Du mit dem Index die Werte in der Tabelle selektierst. Select wäre die Zeile und die Spalten(Collumn) haben ja Namen. Aber wie das genau geht, weiß ich nicht. Noch nicht. Das Thema SQL ist neu für mich, aber auch interessant.
Du bist da an was dran, aber Du müsstest erstmal noch ein Bisschen sicherer in Schleifen, Arrays und Indikatoren werden. Hast Du schon mal einen MACrossover EA gebaut? Oder wenn Du einen EA machen würdest, der als Kaufbedingung prüft ob der Preis für mindestens dreißig Bars über einem 200er Durchschnitt bleibt.
https://www.mql5.com/de/articles/567 Der ist gut fürs Verständnis von Arrays.
https://www.mql5.com/de/articles/4828 Der ist vielleicht ein Bisschen schwierig aber zeigt gut was man mit Indikatoren Alles machen kann. Der Autor nimmt hier auch einen Count und lässt ihn als Linie im Oszillatorfenster anzeigen, Abschnitt "Buffer für Signalzähler".
Arrays sind zusammen mit Variablen und Funktionen ein wesentlicher Bestandteil so gut wie jeder Programmiersprache. Dieser Beitrag dürfte vor allem für Neueinsteiger in der Programmierung mit MQL5 interessant sein, bietet erfahrenen Programmierern aber gleichzeitig eine gute Gelegenheit, ihr Wissen zusammenzufassen und zu systematisieren.
Für die sqlite kannst du auch eine Desktop App benutzen. Damit kannst du sie dir genau anschauen.
Such Mal nach SQLite Browser.
Die Datenbank solltest du in OnInit öffnen und in OnDeinit schließen.
Wenn du dich mit SQL weiter auseinandersetzt, dann wirst du bald sehen, dass es hier sehr versatile Abfragemöglichkeiten gibt um die gewünschten Daten zu erhalten.
Auch kumulieren ist damit möglich.
Allerdings bist du auf den Satz der SQLite beschränkt, dieser ist nicht der gesamte SQL Umfang, leider.
Jedoch kannst du Recht einfach, später eine Anbindung an einen richtigen SQL Server umsetzen.
Ich werde dir eine MySQL Anbindung für MQL verlinken, wenn ich diese in der CodeBase veröffentlicht habe.
Nein Spaß, aber das habe ich mich wirklich gefragt... Du möchtest Zahlen aus der Tabelle holen und in einem "Oszillatorfenster" anzeigen lassen.
Du müsstest dazu mit der Schleife den tradesBuffer[] befüllen. Jedoch nicht immer mit dem selben Wert numberOfTrades. Auch numberOfTrades müsstest Du mit dem Index aus der Tabelle holen, indem Du "Select" wie einen Index verwendest. Dadurch gibst Du die Zeile an. Nur wo das geht ist mir nicht klar.
Das ginge aber erstmal nur für M1 TF. Für M15 müsstest Du immer 15 beieinanderliegende Werte addieren.
Warum hast Du den Index i durch j ersetzt? Der Index im Kopf der Schleife muss der selbe sein wie im Körper.
Dann zählt die Schleife durch:
tradesBuffer[0]= numberOfTrades[0]; tradesBuffer[1]= numberOfTrades[1]; tradesBuffer[2]= numberOfTrades[2]; tradesBuffer[3]= numberOfTrades[3]; tradesBuffer[4]= numberOfTrades[4]; und so weiter. Das macht Alles die Schleife für Dich, wenn Du sie richtig einrichtest. Du musst das halt irgendwie mit dem Databasekram hinbekommen, dass Du mit dem Index die Werte in der Tabelle selektierst. Select wäre die Zeile und die Spalten(Collumn) haben ja Namen. Aber wie das genau geht, weiß ich nicht. Noch nicht. Das Thema SQL ist neu für mich, aber auch interessant.
Du bist da an was dran, aber Du müsstest erstmal noch ein Bisschen sicherer in Schleifen, Arrays und Indikatoren werden. Hast Du schon mal einen MACrossover EA gebaut? Oder wenn Du einen EA machen würdest, der als Kaufbedingung prüft ob der Preis für mindestens dreißig Bars über einem 200er Durchschnitt bleibt.
https://www.mql5.com/de/articles/567 Der ist gut fürs Verständnis von Arrays.
https://www.mql5.com/de/articles/4828 Der ist vielleicht ein Bisschen schwierig aber zeigt gut was man mit Indikatoren Alles machen kann. Der Autor nimmt hier auch einen Count und lässt ihn als Linie im Oszillatorfenster anzeigen, Abschnitt "Buffer für Signalzähler".
Danke für deine Tipps. Werde ich mir direkt ansehen. An sich würd ich aber sagen, läuft:
Tatsächlich bin ich mit dem Indikator weiter gekommen. Allerdings frisst das Auslesen der Datenbank enorm viel Zeit. In einem anderen Beitrag habe ich dies nochmal etwas genauer erörtert: https://www.mql5.com/de/forum/369221
for(int j=0; DatabaseRead(request); j++)
{
//--- read the values of each field from the obtained entryif(DatabaseColumnDouble(request, 1, quoteAssetVolume) &&
DatabaseColumnInteger(request, 2, numberOfTrades) &&
DatabaseColumnDouble(request, 3, takerBuyBaseAssetVolume)&&
DatabaseColumnDouble(request, 4, takerBuyQuoteAssetVolume))
{
tradesBuffer[i] = numberOfTrades;
}
das j hängt in diesem Fall nicht mit dem i zusammen. Das j wird nur hochgezählt, solange die Datenbank den eingetragenen Wert noch nicht gefunden hat. Der Indikator zeigt mir nur im M1 (wie du auch schon erwähnt hast) die Werte korrekt an, was aber ersteinmal nicht das Problem ist. Um die Performance des programms zu erhöhen stehen mir zwei Optionen zur Verfügung:
1. Ich lese nur die letzten 20-30 Balken aus, sodass nicht der ganze chart bis 1840 v.Ch. geladen werden muss.
2. Ich speichere bereits in der OnInit() eine gesamt Spalte aus der Datenbank in ein Array ab, sodass es schneller abgerufen werden kann. Hierzu dachte ich, dass die Funktion DatabaseColumnBlob() eventuell dienlich sein könnte. Bin mir aber bezüglich der Doku garnicht so recht sicher..
boolDatabaseColumnBlob(
int request, // Handle der Anfrage, das durch DatabasePrepare erhalten wurde int column, // Feldindex in der Anfrage void& data[] // die Referenz der Variablen, der der Wert zugewiesen wird
);
das j hängt in diesem Fall nicht mit dem i zusammen. Das j wird nur hochgezählt, solange die Datenbank den eingetragenen Wert noch nicht gefunden hat. Der Indikator zeigt mir nur im M1 (wie du auch schon erwähnt hast) die Werte korrekt an, was aber ersteinmal nicht das Problem ist. Um die Performance des programms zu erhöhen stehen mir zwei Optionen zur Verfügung:
1. Ich lese nur die letzten 20-30 Balken aus, sodass nicht der ganze chart bis 1840 v.Ch. geladen werden muss.
2. Ich speichere bereits in der OnInit() eine gesamt Spalte aus der Datenbank in ein Array ab, sodass es schneller abgerufen werden kann. Hierzu dachte ich, dass die Funktion DatabaseColumnBlob() eventuell dienlich sein könnte. Bin mir aber bezüglich der Doku garnicht so recht sicher..
[in] Feldindex der Anfrage. Die Feldnummerierung beginnt bei Null und darf DatenbankColumnsCount() - 1. nicht überschreiten.
data[]
[out] Referenz des Arrays, dem der Feldwert zugewiesen wird.
Also ich habe mir mal den Artikel über SQLite angesehen und er ist mir nicht so reingelaufen...
Jetzt habe ich auch das i gesehen weiter oben.
Also durch das j wird bewerkstelligt, dass die Anfrage läuft bis der Wert gelesen wurde DatabaseRead(request).
Jetzt sehe ich auch, dass Du durch den Index die Balkenzeit aussuchst, welche in sqlcommand einfließt, wodurch DatabasePrepare verändert wird...
Oh das wird interessant, vergiss einfach das was ich über Schleifen, Arrays und Indikatoren gesagt habe und mach einfach weiter was Du machst :D
Könntest Du nicht db=DatabaseOpen() vor die Schleife stellen, denn sie wird ja durch den Index nicht verändert und müsste daher auch nicht mehrmals neu berechnet werden.
Jedenfalls hast du voll und ganz recht. Die DatabasOpen() muss(!) in die OnInit(), sowie die DatabaseClose() in die OnDeInit() muss. Das erhöht die performance eindeutig, trotzdem scheint mir mein Indikator noch etwas zu träge.
Hier ist nun die Version, indem dies berücksichtig wurde. Außerdem ist nun auch die Unterscheidung der einzelnen Timeframes enthalten.
Selbst der Metatrader bittet darum, den indikator umzuschreiben..
Wie wäre es, wenn ich bereits in der OnInit() alle werte in eine Struct packe?
//---Indikator Einstellungen#property indicator_buffers2#property indicator_plots1#property indicator_type1DRAW_LINE#property indicator_color1clrRed#property indicator_label1"Number of trades"double tradesBuffer[];
double quoteAssetVolume;
int numberOfTrades;
int sumNumberOfTrades;
double takerBuyBaseAssetVolume;
double takerBuyQuoteAssetVolume;
datetime lastM1Bar;
datetime newM1Bar;
datetime candleTwo;
int db;
string filename="AAVEUSDT.db";
intOnInit()
{
//--- Open a database in Terminal/Common
db=DatabaseOpen(filename, DATABASE_OPEN_READONLY | DATABASE_OPEN_COMMON);
if(db==INVALID_HANDLE)
{
Print("DB: ", filename, " open failed with code Database open ", GetLastError());
}
//--- indicator buffers mappingSetIndexBuffer(0,tradesBuffer,INDICATOR_DATA);
return(INIT_SUCCEEDED);
}
voidOnDeinit(constint reason)
{
//--- close databaseDatabaseClose(db);
}
intOnCalculate(constint rates_total,
constint prev_calculated,
constdatetime &time[],
constdouble &open[],
constdouble &high[],
constdouble &low[],
constdouble &close[],
constlong &tick_volume[],
constlong &volume[],
constint &spread[])
{
//int limit =rates_total ;int i = rates_total - 30; // Calculate only the last 30 barsfor(i ; i < rates_total; i++)
{
datetime BarTime = time[i];
if(Period() == PERIOD_M1)calcIndicator(1,i,BarTime);
if(Period() == PERIOD_M5)calcIndicator(5,i,BarTime);
if(Period() == PERIOD_M15)calcIndicator(15,i,BarTime);
if(Period() == PERIOD_H1)calcIndicator(60,i,BarTime);
if(Period() == PERIOD_H4)calcIndicator(240,i,BarTime);
if(Period() == PERIOD_D1)calcIndicator(1440,i,BarTime);
}
return(rates_total);
}
void calcIndicator(int timeframeMulitplier,int i, datetime BarTime)
{
for(int j = 0; j <= timeframeMulitplier-1; j++)
{
//--- Ask for date and time for the 1.candle and convert it into a string valuedatetime candleOne[];
ArrayResize(candleOne,j+1);
candleOne[j] = (BarTime + (60 * j));
// Print("Timestamp: ",time[i]);//--- create an SQL commandstring sqlCommand = " SELECT * FROM test3 WHERE OpenTime='";
StringAdd(sqlCommand,TimeToString(candleOne[j]));
StringAdd(sqlCommand,":00'");
//---create handle for DatabaseRead()int request=DatabasePrepare(db, sqlCommand);
if(request==INVALID_HANDLE)
{
Print("DB: ", filename, " request failed with code Database prepare ", GetLastError());
DatabaseClose(db);
}
//--- read the values of each field from the obtained entryfor(int k=0; DatabaseRead(request); k++)
{
if(//DatabaseColumnDouble(request, 1, quoteAssetVolume) && DatabaseColumnInteger(request, 2, numberOfTrades)
//DatabaseColumnDouble(request, 3, takerBuyBaseAssetVolume)&&//DatabaseColumnDouble(request, 4, takerBuyQuoteAssetVolume)
)
{
sumNumberOfTrades += numberOfTrades;
tradesBuffer[i] = sumNumberOfTrades;
//Print("numberOfTrades: ",numberOfTrades);
}
else
{
Print(j, ": DatabaseRead() failed with code database read ", GetLastError());
DatabaseFinalize(request);
DatabaseClose(db);
}
}
//--- quit the requestDatabaseFinalize(request);
}
sumNumberOfTrades = 0;
}
Jedenfalls hast du voll und ganz recht. Die DatabasOpen() muss(!) in die OnInit(), sowie die DatabaseClose() in die OnDeInit() muss. Das erhöht die performance eindeutig, trotzdem scheint mir mein Indikator noch etwas zu träge.
Hier ist nun die Version, indem dies berücksichtig wurde. Außerdem ist nun auch die Unterscheidung der einzelnen Timeframes enthalten.
Selbst der Metatrader bittet darum, den indikator umzuschreiben..
Wie wäre es, wenn ich bereits in der OnInit() alle werte in eine Struct packe?
Würde sich eine newBar Funktion hier lohnen oder brauchst Du die Informationen neu bei jedem Tick?
bool newBar()
{
staticdatetime TimeBar=0;
bool flag=false;
if(TimeBar!=iTime(Symbol(),Period(),0))
{
TimeBar=iTime(Symbol(),PERIOD_CURRENT,0);
flag=true;
Print(">>>newBar");
}
// return true if you are in new bar.return (flag);
}
Du nimmst newBar==true als Bedingung für das Starten der SQL-Rechnerei, somit wird diese auf den ersten Tick innerhalb eines Balkens beschränkt.
Hier der Code:
Beispielhaft noch die verwendete Tabelle:
Ein großes Dankeschön für eure Ideen und Ratschläge!
Möglicherweise werde ich das auch benötigen, mal sehen. Momentan sind diese Daten nur für Backtests ausgelegt. Wenn ich allerdings live gehe, müsste ich den Indikator oder die Datenbank mit echtzeitdaten speisen. Wenn das ohne andere Programmierebenen (bspw. Python) funktioniert, wäre das eine elegante und saubere Lösung.
Habe versucht, die Datenbankabfrage in einen Indikator umzusetzen. Leider zeigt mir das Journal folgenden Fehler an:

der Error steht dafür, dass die Datei der Datenbank blockiert ist. Was auch immer genau damit gemeint ist.
Laut Debugger wird mir der Buffer mit werten befüllt. Nur zeigt das Indikatorfenster nichts an.
Das hier ist der Indikator
Was sagt ihr dazu? Ich habe noch nicht so oft mit Indikatoren gearbeitet . Ich vermute allerdings, dass es mit der for_Schleife zusammenhängt
Habe versucht, die Datenbankabfrage in einen Indikator umzusetzen. Leider zeigt mir das Journal folgenden Fehler an:
der Error steht dafür, dass die Datei der Datenbank blockiert ist. Was auch immer genau damit gemeint ist.
Laut Debugger wird mir der Buffer mit werten befüllt. Nur zeigt das Indikatorfenster nichts an.
Das hier ist der Indikator
Was sagt ihr dazu? Ich habe noch nicht so oft mit Indikatoren gearbeitet . Ich vermute allerdings, dass es mit der for_Schleife zusammenhängt
Nein Spaß, aber das habe ich mich wirklich gefragt... Du möchtest Zahlen aus der Tabelle holen und in einem "Oszillatorfenster" anzeigen lassen.
Du müsstest dazu mit der Schleife den tradesBuffer[] befüllen. Jedoch nicht immer mit dem selben Wert numberOfTrades. Auch numberOfTrades müsstest Du mit dem Index aus der Tabelle holen, indem Du "Select" wie einen Index verwendest. Dadurch gibst Du die Zeile an. Nur wo das geht ist mir nicht klar.
Das ginge aber erstmal nur für M1 TF. Für M15 müsstest Du immer 15 beieinanderliegende Werte addieren.
Warum hast Du den Index i durch j ersetzt? Der Index im Kopf der Schleife muss der selbe sein wie im Körper.
Dann zählt die Schleife durch:
tradesBuffer[0]= numberOfTrades[0];
tradesBuffer[1]= numberOfTrades[1];
tradesBuffer[2]= numberOfTrades[2];
tradesBuffer[3]= numberOfTrades[3];
tradesBuffer[4]= numberOfTrades[4]; und so weiter. Das macht Alles die Schleife für Dich, wenn Du sie richtig einrichtest. Du musst das halt irgendwie mit dem Databasekram hinbekommen, dass Du mit dem Index die Werte in der Tabelle selektierst. Select wäre die Zeile und die Spalten(Collumn) haben ja Namen. Aber wie das genau geht, weiß ich nicht. Noch nicht. Das Thema SQL ist neu für mich, aber auch interessant.
Du bist da an was dran, aber Du müsstest erstmal noch ein Bisschen sicherer in Schleifen, Arrays und Indikatoren werden. Hast Du schon mal einen MACrossover EA gebaut? Oder wenn Du einen EA machen würdest, der als Kaufbedingung prüft ob der Preis für mindestens dreißig Bars über einem 200er Durchschnitt bleibt.
https://www.mql5.com/de/articles/567 Der ist gut fürs Verständnis von Arrays.
https://www.mql5.com/de/articles/4828 Der ist vielleicht ein Bisschen schwierig aber zeigt gut was man mit Indikatoren Alles machen kann. Der Autor nimmt hier auch einen Count und lässt ihn als Linie im Oszillatorfenster anzeigen, Abschnitt "Buffer für Signalzähler".
Nein Spaß, aber das habe ich mich wirklich gefragt... Du möchtest Zahlen aus der Tabelle holen und in einem "Oszillatorfenster" anzeigen lassen.
Du müsstest dazu mit der Schleife den tradesBuffer[] befüllen. Jedoch nicht immer mit dem selben Wert numberOfTrades. Auch numberOfTrades müsstest Du mit dem Index aus der Tabelle holen, indem Du "Select" wie einen Index verwendest. Dadurch gibst Du die Zeile an. Nur wo das geht ist mir nicht klar.
Das ginge aber erstmal nur für M1 TF. Für M15 müsstest Du immer 15 beieinanderliegende Werte addieren.
Warum hast Du den Index i durch j ersetzt? Der Index im Kopf der Schleife muss der selbe sein wie im Körper.
Dann zählt die Schleife durch:
tradesBuffer[0]= numberOfTrades[0];
tradesBuffer[1]= numberOfTrades[1];
tradesBuffer[2]= numberOfTrades[2];
tradesBuffer[3]= numberOfTrades[3];
tradesBuffer[4]= numberOfTrades[4]; und so weiter. Das macht Alles die Schleife für Dich, wenn Du sie richtig einrichtest. Du musst das halt irgendwie mit dem Databasekram hinbekommen, dass Du mit dem Index die Werte in der Tabelle selektierst. Select wäre die Zeile und die Spalten(Collumn) haben ja Namen. Aber wie das genau geht, weiß ich nicht. Noch nicht. Das Thema SQL ist neu für mich, aber auch interessant.
Du bist da an was dran, aber Du müsstest erstmal noch ein Bisschen sicherer in Schleifen, Arrays und Indikatoren werden. Hast Du schon mal einen MACrossover EA gebaut? Oder wenn Du einen EA machen würdest, der als Kaufbedingung prüft ob der Preis für mindestens dreißig Bars über einem 200er Durchschnitt bleibt.
https://www.mql5.com/de/articles/567 Der ist gut fürs Verständnis von Arrays.
https://www.mql5.com/de/articles/4828 Der ist vielleicht ein Bisschen schwierig aber zeigt gut was man mit Indikatoren Alles machen kann. Der Autor nimmt hier auch einen Count und lässt ihn als Linie im Oszillatorfenster anzeigen, Abschnitt "Buffer für Signalzähler".
Danke für deine Tipps. Werde ich mir direkt ansehen. An sich würd ich aber sagen, läuft:

Tatsächlich bin ich mit dem Indikator weiter gekommen. Allerdings frisst das Auslesen der Datenbank enorm viel Zeit.
In einem anderen Beitrag habe ich dies nochmal etwas genauer erörtert: https://www.mql5.com/de/forum/369221
das j hängt in diesem Fall nicht mit dem i zusammen. Das j wird nur hochgezählt, solange die Datenbank den eingetragenen Wert noch nicht gefunden hat. Der Indikator zeigt mir nur im M1 (wie du auch schon erwähnt hast) die Werte korrekt an, was aber ersteinmal nicht das Problem ist.
Um die Performance des programms zu erhöhen stehen mir zwei Optionen zur Verfügung:
1. Ich lese nur die letzten 20-30 Balken aus, sodass nicht der ganze chart bis 1840 v.Ch. geladen werden muss.
2. Ich speichere bereits in der OnInit() eine gesamt Spalte aus der Datenbank in ein Array ab, sodass es schneller abgerufen werden kann.
Hierzu dachte ich, dass die Funktion DatabaseColumnBlob() eventuell dienlich sein könnte. Bin mir aber bezüglich der Doku garnicht so recht sicher..
request
[in] Handle der Anfrage, das von DatabasePrepare() erhalten wurde.
column
[in] Feldindex der Anfrage. Die Feldnummerierung beginnt bei Null und darf DatenbankColumnsCount() - 1. nicht überschreiten.
data[]
[out] Referenz des Arrays, dem der Feldwert zugewiesen wird.
Vielen Dank Dominik! Denkst du mit der DatabaseColumnBlob () Funktion kann ich mein Vorhaben durchführen?
das j hängt in diesem Fall nicht mit dem i zusammen. Das j wird nur hochgezählt, solange die Datenbank den eingetragenen Wert noch nicht gefunden hat. Der Indikator zeigt mir nur im M1 (wie du auch schon erwähnt hast) die Werte korrekt an, was aber ersteinmal nicht das Problem ist.
Um die Performance des programms zu erhöhen stehen mir zwei Optionen zur Verfügung:
1. Ich lese nur die letzten 20-30 Balken aus, sodass nicht der ganze chart bis 1840 v.Ch. geladen werden muss.
2. Ich speichere bereits in der OnInit() eine gesamt Spalte aus der Datenbank in ein Array ab, sodass es schneller abgerufen werden kann.
Hierzu dachte ich, dass die Funktion DatabaseColumnBlob() eventuell dienlich sein könnte. Bin mir aber bezüglich der Doku garnicht so recht sicher..
request
[in] Handle der Anfrage, das von DatabasePrepare() erhalten wurde.
column
[in] Feldindex der Anfrage. Die Feldnummerierung beginnt bei Null und darf DatenbankColumnsCount() - 1. nicht überschreiten.
data[]
[out] Referenz des Arrays, dem der Feldwert zugewiesen wird.
Huch, da gabs wohl einen Bug beim absenden..

Jedenfalls hast du voll und ganz recht. Die DatabasOpen() muss(!) in die OnInit(), sowie die DatabaseClose() in die OnDeInit() muss. Das erhöht die performance eindeutig, trotzdem scheint mir mein Indikator noch etwas zu träge.
Hier ist nun die Version, indem dies berücksichtig wurde. Außerdem ist nun auch die Unterscheidung der einzelnen Timeframes enthalten.
Selbst der Metatrader bittet darum, den indikator umzuschreiben..
Wie wäre es, wenn ich bereits in der OnInit() alle werte in eine Struct packe?
Huch, da gabs wohl einen Bug beim absenden..
Jedenfalls hast du voll und ganz recht. Die DatabasOpen() muss(!) in die OnInit(), sowie die DatabaseClose() in die OnDeInit() muss. Das erhöht die performance eindeutig, trotzdem scheint mir mein Indikator noch etwas zu träge.
Hier ist nun die Version, indem dies berücksichtig wurde. Außerdem ist nun auch die Unterscheidung der einzelnen Timeframes enthalten.
Selbst der Metatrader bittet darum, den indikator umzuschreiben..
Wie wäre es, wenn ich bereits in der OnInit() alle werte in eine Struct packe?
Würde sich eine newBar Funktion hier lohnen oder brauchst Du die Informationen neu bei jedem Tick?
Du nimmst newBar==true als Bedingung für das Starten der SQL-Rechnerei, somit wird diese auf den ersten Tick innerhalb eines Balkens beschränkt.