HS: EquityCurve mit verschiedenen Parametern in einem Chart darstellen

Hallo,

eine Frage an die Systemprogrammierer hier im Forum:

In meinem Handelssystem habe ich in der MultiChart eine EquityCurve erzeugt. Die kann ich nach bedarf ins Excel exportieren. Nun meine Frage:

Ich möchte gern mein Handelssystem, also die erzeugte EquityCurve, mit verschiedenen Parametern in einer Grafik mit Excel erstellen/anzeigen. Also nicht den Weg wählen, verschiedene EquityCurve zusammenfügen, sondern die einzelnen Parameter-Einstellungen bewusst anzeigen (siehe Chart).

Wie kann ich das umsetzen?

Am liebsten wäre mir ein Weg, wenn ich meine z.b. 10 verschiedenen EquityCurve in Multichart in einem Workspace zusammenfassen könnte (DLL?) und dann die Ergebnisse ins Excel exportiere.

Habt Ihr Ideen oder Anregungen?

Danke!

Geschrieben von select am
wuelle
Mitglied seit
12 Jahre 6 Monate

@ select [#1]

Verstehe ich Deine Frage richtig: Du möchtest die unterschiedlichen Kapitalkurven, die ein Handelssystem mit z.B. 10 verschiedenen Eingabewerten erzeugt, in einer Excelgrafik darstellen?

select
Mitglied seit
12 Jahre 6 Monate

@ wuelle [#2]

" Du möchtest die unterschiedlichen Kapitalkurven..........in einer Excelgrafik darstellen?"

Genau, das ist die Bestrebung.

Asamat
Mitglied seit
12 Jahre 6 Monate

Ich hab keine Antwort; nur eine Bemerkung.

Normalerweise macht man ja etwas anderes. Man sucht sich ein geeignetes Maß für das, was man untersuchen oder bewerten will (z.B. Steigung der Kurve, Glattheit, max. DD, ...), und plottet das Maß gegen (ein- oder zweidimensionale) Schnitte im Parameterraum. Der Grund ist, daß der (mathematische) Raum der Parameterkombinationen zu groß ist, als daß man ihn sinnvoll anhand von einzelnen Kurven beurteilen kann.

wuelle
Mitglied seit
12 Jahre 6 Monate

@ select [#3]

Mittels FileAppend Befehl kann man die verschiedenen Kapitalkurven des Systems in einer Spalte der Excel-Tabelle untereinander aneinanderhängen.

//Ausgabe in Datei
if EQT<>EQT[1] then
begin
FileAppend(Datei, ELDateToString(date[1]) + "; " +
numtostr(EQT,2) + "; " + Newline);
end;

Wie man in Excel diese einspaltige Liste automatisch in eine Liste mit mehreren Spalten nebeneinander umformatiert, weiß ich leider nicht. Vielleicht können die Excel-Experten hier weiterhelfen.

wuelle
Mitglied seit
12 Jahre 6 Monate

Gibt es eine Möglichkeit mit ein Signal über einen Batch-Prozess (Inputvariablen per Zählschleife verändern) verschiedene csv.Dateien mit den Kapitalkurven zu generieren?

Profile picture for user ke45
ke45
Mitglied seit
12 Jahre 6 Monate

Ich würde dazu keinen Batch-Prozess sondern (in der TradeStation) eine ganz normale Optimierung der gewünschten Inputs machen. Zusätzlich muss man im Signal dafür sorgen, dass der jeweilige Dateinamen für die CSV-Datei die Werte der Input-Variablen beeinhaltet, sonst hängt die TS alle Ergebnisse hintereinander bzw. überschreibt die Datei immer wieder.

wuelle
Mitglied seit
12 Jahre 6 Monate

@ ke45 [#7]

Dein Lösungsvorschlag gefällt mir sehr gut!

Bisher erzeuge ich eine einzelne Kapitalkurve mittels eines Indikators über die Funktion I_ClosedEquity. Diese Funktion kann man ja bekanntlich in einem Signal nicht anwenden.

Kannst Du bitte beispielhaft einen Code für den Print-Befehl in einem Signal aufzeigen, damit ich eine Idee bekomme, wie man so etwas programmiert? Danke!

Profile picture for user ke45
ke45
Mitglied seit
12 Jahre 6 Monate

@ wuelle [#8]

Anstatt I_ClosedEquity verwendest Du in dem Signal einfach NetProfit. Und den Dateinamen für das FileAppend würde ich aus den Werten der zu optimierenden Parameter zusammenbauen (z.B. P1 und P2 sind die 2 zu optimierenden Parameter, beide numerisch ganzzahlig):

Datei = "C:\tmp\MyEQ+" + "NumToStr(P1, 0) + "+" + NumToStr(P2, 0) + ".csv";
FileAppend(Datei, ELDateToString(date) + "; " + numtostr(NetProfit,2) + "; " + Newline);

wuelle
Mitglied seit
12 Jahre 6 Monate

@ ke45 [#9]

Funktioniert super, vielen Dank! Vor dem ersten NumToStr(P1, 0) ist allerdings ein " zuviel.

Siehst Du eine Möglichkeit die einzelnen Dateien durchzunummerieren (MyEQ_1 bis MyEQ_100), um den Textimport in Excel zu vereinfachen?

Zur Unterscheidung könnte man die Inputvariablen mit in die csv-Datei schreiben lassen und somit in Excel einmal eine Datei für den Textimport anlegen, die MyEQ 1 bis 100 importiert, unabhängig von den sich ändernden Dateinamen, die sich durch Variation der Inputvariablen bei verschiedenen Handelsinstrumenten ergeben.

select
Mitglied seit
12 Jahre 6 Monate

@ ke45 [#9]
@ wuelle [#8]

Vielen Dank für die professionelle Unterstützung.

@ wuelle [#10]

"Siehst Du eine Möglichkeit die einzelnen Dateien durchzunummerieren (MyEQ_1 bis MyEQ_100), um den Textimport in Excel zu vereinfachen?"

Meine zusätzlichen Researchen ergaben/ergeben, dass es mit Easylanguage nicht möglich ist, verschiedene Dateinamen dynamisch generieren zu lassen.

Profile picture for user ke45
ke45
Mitglied seit
12 Jahre 6 Monate

@ select [#11]

Meine zusätzlichen Researchen ergaben/ergeben, dass es mit Easylanguage nicht möglich ist, verschiedene Dateinamen dynamisch generieren zu lassen.

Das sehe ich anders! Da Dateinamen auch nur normale Strings sind kann man sie ganz nach belieben zusammensetzen. Um allerdings die Anzahl der Optimierungsläufe in den Dateinamen zu bringen benötigt man Globale Variablen.

select
Mitglied seit
12 Jahre 6 Monate

@ ke45 [#12]

"Um allerdings die Anzahl der Optimierungsläufe in den Dateinamen zu bringen benötigt man Globale Variablen."

Oh, Du erstaunst mich, eben wie immer. Könntest Du mir vielleicht bitte in EL noch etwas Unterstützung zollen? Als Ergebnis zur Anschauung liegen 6 Optimierungsgänge zu Grunde:

if LastBarOnChart then begin
FileAppend("C:\temp\Neuer Ordner\EQT.txt",ELDateToString(Date) + " 'Lkbk = " + NumToStr(lkbk,0) + newline);
exitlong;
exitshort;
end;

{originale Output-Datei}
09/21/2001 'Lkbk = 10
09/22/2001 'Lkbk = 12
09/23/2001 'Lkbk = 14
09/24/2001 'Lkbk = 16
09/25/2001 'Lkbk = 18
09/28/2001 'Lkbk = 20

in

{so soll die Formatierung am Ende als Beispiel aussehen}
EQT1.txt {09/21/2001 'Lkbk = 10}
EQT2.txt {09/22/2001 'Lkbk = 12}
EQT3.txt {09/23/2001 'Lkbk = 14}
EQT4.txt {09/24/2001 'Lkbk = 16}
EQT5.txt {09/25/2001 'Lkbk = 18}
EQT6.txt {09/28/2001 'Lkbk = 20}

Wie müsste man nun Globale Variablen einfügen?

Vielen Dank!

So sollen die Output-Datei umbenannt als txt vorliegen.

wuelle
Mitglied seit
12 Jahre 6 Monate

@ ke45 [#12]

Wie adressiert man denn die Nummer des Optimierungslaufs, um diesen Wert einer globalen Variable zu übergeben?

Die Drei Fragezeichen

Wenn ich die Dokumentation der GlobalVariable.dll richtig verstanden habe, müsste man z.B. die Variable EQTNr über den Befehl EQTNr = GVSetInteger(0, ???) initialisieren.

Kannst Du die Lösung dieses Falls übernehmen? :-)

Profile picture for user ke45
ke45
Mitglied seit
12 Jahre 6 Monate

@ wuelle [#14]

Ja, natürlich kann ich Euch helfen! Aber erstmal ein gutes Jahr 2010 an alle!

Zum ELA Problem. Da es viele verschiedene GV Pakete gibt verwende ich hier einen Pseudo Aufruf "GVsetInt" und "GVgetInt" zum Setzen bzw. Lesen einer GV. Um die GV im Normalbetrieb auf 0 zu setzen verwende ich den Aufruf "GetAppInfo(aiOptimizing)" der leider nur in der TS8 funktioniert. Bei der 2000i muss man sich da was einfallen lassen oder die GV von Hand oder mit einer anderen Applikation vor der Optimierung zurückseten.

Der nachfolgende ELA-Code ist nicht getestet und soll nur die prinzipielle Vorgehensweise erläutern:

Var: x(0), Filename(""); .... if GetAppInfo(aiOptimizing) = 0 then begin { keine Optimierung, GV auf 0 setzen } x = GVsetInt("GV1", 0); end else begin { Optimierung läuft, GV inkrementieren } x = GVgetInt("GV1") + 1; Filename = "C:\tmp\Opt" + NumToStr(x, 0) + ".csv"; x = GVsetInt("GV1", x); end; { ab jetzt Filename verwenden für Optimierungsergebnisse } ...

Gruss
-Klaus

wuelle
Mitglied seit
12 Jahre 6 Monate

Dir, und auch allen anderen TMWlern, alles Gute im neuen Jahrzehnt!

Nach Aussagen einer Mitarbeiterin von Multichart, wird die EL-Funktion GetAppInfo(aiOptimizing) von der Software unterstützt.

Folgenden Code habe ich eingegeben, der zwar compiliert wird, aber leider keine Dateien auswirft. :-(

//Dateinnamen durchnumerieren
if GetAppInfo(aiOptimizing) = 0 then
begin {wenn keine Optimierung laueft, dann GV auf 0 setzen }
x = GVSetInteger(1, 0);
end
else
begin {wenn Optimierung laeuft, GV inkrementieren }
x = GVGetInteger(1) + 1;
Datei = "C:\Temp\" + NumToStr(x, 0) + ".txt";
x = GVSetInteger(1, x);
end;

//Dateiformat Excel
if Date <> Date[1] then
begin
FileAppend(Datei, ELDateToString(date[1]) + ", " +
numtostr(NetProfit,0) + ", " +
numtostr(MaxIDDrawDown,0)+ NewLine);
end;

Kannst Du einen Fehler erkennen?

Verwendete Funktionen:

{Funktion: GVSetInteger}

DefineDLLFunc: "GlobalVariable.dll", int, "GV_SetInteger", int, int ;

inputs: ElementLocation( numeric ),
GVValue( numeric ) ;

variables: RtnVal( -1 ) ;

if LastBarOnChart then
RtnVal = GV_SetInteger( ElementLocation, GVValue ) ;

GVSetInteger = RtnVal ;

Value1 = Ticks ; { Force RadarScreen to update every tick. }

{Funktion: GVGetInteger}

DefineDLLFunc: "GlobalVariable.dll", int, "GV_GetInteger", int ;

inputs: ElementLocation( numeric ) ;

variables: RtnVal( -1 ) ;

if LastBarOnChart then
RtnVal = GV_GetInteger( ElementLocation ) ;
{ Get the value from the global buffer }

GVGetInteger = RtnVal ;
{ Assign the obtained value to the function name }

Value1 = Ticks ; { Force RadarScreen to update every tick. }

Profile picture for user ke45
ke45
Mitglied seit
12 Jahre 6 Monate

@ wuelle [#16]

Ja, ich sehe da noch 3 Probleme:

1.) In den unteren Funktionen (GVSetInteger und GVGetInteger) ist die Abfrage "LastBarOnChart" drin, die muss raus damit das funktionieren kann (ist sowieso Quatsch, warum soll eine GV nur in der letzten kerze funktionieren?)!

2.) Da wo die Ausgabe in die Datei stattfindet solltest Du vorher nochmal abfragen ob der Dateiname überhaupt gesetzt ist (bzw. alternativ mit GetAppInfo auf Optimierungslauf abfragen) damit im Normalbetrieb ohne Optimierung nicht auch versucht wird eine Datei zu schreiben.

3.) In meinem Code fehlt auch noch eine Abfrage ob Filename (bzw. Datei) schon gesetzt wurde. Ohne diese Abfrage wird im Fall der Optimierung mit jeder Kerze der Dateiname um 1 hochgezählt. Also meinen Code noch erweitern um:

Var: init(True); if init then begin init = False; if GetAppInfo(..... ... end;

Ich kann natürlich zu MultiCharts nichts sagen, aber trotz der angesprochenen Fehler sollte mit Deinem Code oben im Falle der Optimierung zumindest eine Datei "C:\temp\0.txt" ausgegeben werden (GVGetInteger liefert ja immer -1) sofern das mit dem GetAppInfo in MultiCharts wirklich funktioniert...

-Klaus

wuelle
Mitglied seit
12 Jahre 6 Monate

@ ke45 [#17]

Vielen Dank! Das ist der aktuelle Code. Die Funktionen der DLL werden im Unterschied zur Vorgängerversion jetzt ohne Funktionen, direkt im Code definiert.

Wenn ich die Abfrage nach LastBarOnChart am Anfang ausklammere (so wie hier dargestellt) bekomme ich die Fehlermeldung "Can´t open/create file". Wenn ich die Abfrage zulasse, bekomme ich zwar keine Fehlermeldung, aber auch keine Datei exportiert. :-(

Was nun sprach Zeus?

//Ausgabe in Datei
if Drucken = true then //and LastBarOnChart then
begin

var: x(0), init(true), Datei(" ");

//Dateinnamen durchnumerieren
DefineDLLFunc: "GlobalVariable.dll", int, "GV_SetNamedInt", lpstr, int ;
DefineDLLFunc: "GlobalVariable.dll", int, "GV_GetNamedInt", lpstr, int ;
external: "GlobalVariable.dll", int, "GV_ResetAllNmdInts" ;

if init then
begin
init = False;
if GetAppInfo(aiOptimizing) = 0 then
begin {wenn keine Optimierung laueft, dann GV auf 0 setzen }
x = GV_ResetAllNmdInts;
// x = GV_SetNamedInt("GV1", 0);
end
else
begin {wenn Optimierung laeuft, GV inkrementieren }
x = GV_GetNamedInt("GV1",1) + 1;
Datei = "C:\Temp\" + NumToStr(x, 0) + ".txt";
x = GV_SetNamedInt("GV1", x);
end;
end;

//Dateiformat Excel

//Kopfzeilen erzeugen fuer Excel
if currentbar = 1 then
begin
FileAppend(Datei,
"BoxSize:" + " " +
numtostr(RenkoBoxSize,2) + " " +
"TradingStyle:" + " " +
numtostr(TradingStyle,0) + Newline +
"Tgt:" + "" +
numtostr(TargetPerc,2) + " " +
"Stp:" + "" +
numtostr(StopLossPerc,2) + " " +
"Rkl:" + "" +
numtostr(RuecklaufPerc,2) + Newline);
end;

if Date <> Date[1] then
begin
FileAppend(Datei, ELDateToString(date[1]) + ", " +
numtostr(NetProfit,0) + ", " +
numtostr(MaxIDDrawDown,0)+ NewLine);
end;

end; //Ende der Schleife if Drucken is true

Profile picture for user ke45
ke45
Mitglied seit
12 Jahre 6 Monate

@ wuelle [#18]

Die Fehlermeldung kommt daher, dass Du das, was ich vorher unter 2.) geschrieben hatte nicht berücksichtigt hast. Versuche mal "Datei" sinnvoll zu initialisieren, z.B. :

Var: Datei("C:\temp\noopt.txt");

Das "LastBarOnChart" muss auf jeden Fall weg!

Jetzt solltest Du immer die Datei C:\temp\noopt.txt bekommen und nur bei einer Optimierung zusätzlich die Dateien 1.txt, 2.txt usw. Werden die Dateien mit den Nummern im Namen jedoch trotz Optimierung nicht angelegt, dann funktioniert das "GetAppInfo(aiOptimizing)" offensichtlich nicht (oder anders) in MultiChart?!

Mehr fällt mir dazu nicht mehr ein...

Gruss
-Klaus

wuelle
Mitglied seit
12 Jahre 6 Monate

@ ke45 [#19]

Hurra, die Ausgabe von txt-Dateien funktioniert jetzt! Komischerweise wird aber nicht für jeden Optimierungslauf eine eigene Datei angelegt. Beispielsweise werden bei 9 Optimierungläufen, die Dateien 1.txt bis 4.txt erzeugt. In manchen Datei sind mehrere Optimierungsläufe abgespeichert.

Wenn Multicharts die Dateinamen anhand der Inputvariablen erzeugt, werden die neun verschiedenen Text-Dateien korrekt erzeugt. It makes me wonder.


//Ausgabe in Datei
if Drucken = true then
begin
var: x(0), init(true), Datei("C:\temp\noopt.txt");

//Dateinnamen durchnumerieren
DefineDLLFunc: "GlobalVariable.dll", int, "GV_SetNamedInt", lpstr, int ;
DefineDLLFunc: "GlobalVariable.dll", int, "GV_GetNamedInt", lpstr, int ;
external: "GlobalVariable.dll", int, "GV_ResetAllNmdInts" ;

if init then
begin
init = False;
if GetAppInfo(aiOptimizing) = 0 then
begin {wenn keine Optimierung laueft, globale Variable auf 0 setzen }
x = GV_ResetAllNmdInts;
end
else
begin {wenn Optimierung laeuft, GV inkrementieren }
x = GV_GetNamedInt("GV1",0) + 1;
Datei = "C:\Temp\" + NumToStr(x,0) + ".txt";
x = GV_SetNamedInt("GV1", x);
end;
end;

{
//Dateinname vergeben in Abhaengikeit der Inputvariabeln
Datei = "C:\Temp\" +
getsymbolname + "_" +
NumToStr(TradingStyle, 0) + "+" +
NumToStr(TargetPerc, 2) + "+" +
NumToStr(StopLossPerc, 2) + "+" +
NumToStr(RuecklaufPerc, 2) + ".txt";
}

//Dateiformat fuer Excelimport

//Kopfzeilen erzeugen fuer Excel
if currentbar = 1 then
begin
FileAppend(Datei,
"BoxSize:" + " " +
numtostr(RenkoBoxSize,2) + " " +
"TradingStyle:" + " " +
numtostr(TradingStyle,0) + Newline +
"Tgt:" + "" +
numtostr(TargetPerc,2) + " " +
"Stp:" + "" +
numtostr(StopLossPerc,2) + " " +
"Rkl:" + "" +
numtostr(RuecklaufPerc,2) + Newline);
end;

if Date <> Date[1] then
begin
FileAppend(Datei, ELDateToString(date[1]) + ", " +
numtostr(NetProfit,0) + ", " +
numtostr(MaxIDDrawDown,0)+ NewLine);
end;

Profile picture for user ke45
ke45
Mitglied seit
12 Jahre 6 Monate

@ wuelle [#20]

.. Komischerweise wird aber nicht für jeden Optimierungslauf eine eigene Datei angelegt. Beispielsweise werden bei 9 Optimierungläufen, die Dateien 1.txt bis 4.txt erzeugt. In manchen Datei sind mehrere Optimierungsläufe abgespeichert...
Hast Du evtl. die Dateien zwischendurch nicht gelöscht? Denn bei jeder neuen Optimierung wird das Ergebnis natürlich nur angehängt! Zur Sicherheit kann man noch ein FileDelete an der Stelle einbauen, wo der Dateiname erstellt wird.

Warum weniger Dateien angelegt werden als Optimierungsläufe stattfinden kann ich mir nicht erklären? Macht MultiCharts (anders als die TS) evtl. mehrere Optimierungsläufe parallel bei einem MultiCore Prozessor?

wuelle
Mitglied seit
12 Jahre 6 Monate

@ ke45 [#21]

Bis jetzt habe ich die Dateien zwischen jedem Optimierungslauf von Hand gelöscht. Jetzt habe ich den Code, wie unten stehend erweitert.

if init then
begin
init = False;
if GetAppInfo(aiOptimizing) = 0 then
begin {wenn keine Optimierung laueft, globale Variable auf 0 setzen }
x = GV_ResetAllNmdInts;
end
else
begin {wenn Optimierung laeuft, GV inkrementieren }
x = GV_GetNamedInt("GV1",0) + 1;
Datei = "C:\Temp\" + NumToStr(x,0) + ".txt";
x = GV_SetNamedInt("GV1", x);
FileDelete(Datei);
end;
end;

Ja, Multicharts unterstützt die vier Prozessorkerne meines Rechners. Nach der Erweiterung des Codes, bekomme ich bei manchen Optimierungsläufen die Fehlermeldung: Can´t Open/create file C:\2.txt. Wenn diese Fehlermeldung nicht erscheint, werden vier Txt-Dateien erzeugt, entspechend der Anzahl der Prozessorkerne in meinem Rechner. Diese beinhalten dann das Ergebnis eines Optimierungsdurchlaufs.

Das unterstützt eindeutig Deine Vermutung, dass dieses Phänomen auf das parallele Verarbeiten zurückzuführen ist.

Gibt es einen Trick 17, mit dem man das lösen kann?

Profile picture for user ke45
ke45
Mitglied seit
12 Jahre 6 Monate

@ wuelle [#22]

Tja, da hast Du dann ein Problem... Kritisch sind die 3 Zeilen, in denen die GV ausgelesen, inkrementiert und wieder zurück geschrieben wird. Diese müssten ohne Unterbrechung "in einem Rutsch" ausgeführt werden damit das funktioniert. Wenn MultiCharts jetzt aber 4 Optimierungsläufe parallel abarbeitet ist das wohl nicht mehr gegeben und damit klappt der Trick mit der GV nicht mehr zuverlässig.

Ich sehe 3 Lösungsansätze:

1.) Wenn GV_SetNamedInt("GV1", x) den Wert x auch zurück gibt (ausprobieren!) dann kann man die 3 entscheidenden Zeilen auch so umschreiben:

x = GV_SetNamedInt("GV1", GV_GetNamedInt("GV1") + 1); Datei = "C:\Temp\" + NumToStr(x,0) + ".txt";

Dadurch sind Auslesen und Setzen der GV direkt zusammen und das könnte evtl. was bringen?

2.) Du benötigst ein GV-Paket, welches das Auslesen und Setzen éinr GV in einem Arbeitsschritt anbietet (quasi so etwas wie in der Programmiersprache "C" der Ausdruck x++ ). Wenn Deine GV DLL auch im Sourcecode vorliegt, dann könnte man die DLL um so einen Aufruf erweitern.

3.) Die parallele Optimierung abschalten (geht das in MultiCharts?) oder TS verwenden.

-Klaus

Gast

@ ke45 [#23]

mir kräuseln sich bei solch Konstrukten die Zehnägel...

Warum nicht statt GV und 'Datei = "C:\Temp\" + NumToStr(x,0) + ".txt";' besser nur die gute alte Windows(DLL) Funktion GetTickCount() nehmen?

Also nur noch 'Datei = "C:\Temp\" + NumToStr(GetTickCount(),0) + ".txt";'? Die Sache wäre Millisekunden genau und sollte auch bei Simultan-Optimierung zu 99,999% eindeutige Werte liefern.
Ansonsten für 100% eindeutige Werte ist es ein einfach sich selbst so eine kleine DLL schreiben und per Mutex/CriticalSection den Parallelzugriff verhindern.
Ich würde wetten, auf diese "Idee" sind auch schon andere gekommen, also in den existierenden GV Paketen einfach mal nach Lock/UnLock Funktionen suchen...

Ansonsten, wie heißt es so schön... für Geld mache ich fast alles;)
Eine SyncronizeDLL mit einem globalen Lock/Unlock sogar noch mit einem variablen ID-String wären 4 simple "C"-Funktionen in einer DLL. So wäre es dann in TS und MC sicher lauffähig:

Lock("MeinSystem");
x = GV_GetNamedInt("GV1",0) + 1;
Datei = "C:\Temp\" + NumToStr(x,0) + ".txt";
x = GV_SetNamedInt("GV1", x);
UnLock("MeinSystem");

Profile picture for user ke45
ke45
Mitglied seit
12 Jahre 6 Monate

@ TimeTrade [#24]

Tja, das das ganze am Ende noch auf ein Synchronisationsproblem wegen Parallelverarbeitung rauslaufen würde hätte ich anfangs auch nicht geahnt!

Die DLL mit dem Lock / Unlock ist sicher hierfür die beste Lösung. Mir ist nur keine DLL in dem Umfeld bekannt, die das schon beeinhaltet. Sollte "wuelle" Dich beauftragen so was zu schreiben dann hätte ich bitte auch gerne eine Kopie davon :-) Danke!

Gruss
-Klaus

wuelle
Mitglied seit
12 Jahre 6 Monate

Der Code

x = GV_SetNamedInt("GV1", (GV_GetNamedInt("GV1",x) + 1) );
Datei = "C:\Temp\" + NumToStr(x,0) + ".txt";

erzeugt die Datei 0.txt, in der die Ergebnisse geschrieben werden.

Wie sieht denn der Easy Language Code unter Verwendung der GetTickCount()-Funktion aus? Der naive (Pseudo-) Code

if GetAppInfo(aiOptimizing) = 1 then
Datei = "C:\Temp\" + NumToStr(GetTickCount(),0) + ".txt";

kann nicht kompiliert werden.

Gast

@ wuelle [#26]

ich kenne mich mit EL nicht aus, aber ich denke das man vorher "GetTickCount" als DLL Funktion anmelden muss, also etwas so:

DefineDLLFunc: "Kernel32.dll", int, "GetTickCount";

Das sollte dann zum Testen reichen... und wenn es doch eine DLL mit Lock/Unlock werden soll, dann muss man auch da vorher sicher diese Funktionen so anmelden.

wuelle
Mitglied seit
12 Jahre 6 Monate

@ TimeTrade [#27]

Die Initialisierung der DLL hat mit Deinem Code geklappt. Es werden zwar mehr als vier, aber immer noch nicht für jeden Optimierungslauf eine eigene Datei angelegt.

Es ist einen Versuch wert, mit Deiner SyncronizeDLL die Sache zu lösen. Ich habe allerdings nicht verstanden, was diese DLL macht bzw. was ein globales Lock/Unlock ist. Verstehe ich es richtig, das der variable ID-String für eine Benennung der Dateien von EQT1.txt bis EQTxyz.txt sorgt?

Nimm doch bitte mal Kontakt mit mir auf. Mein Adresse ist hier hinterlegt.

Profile picture for user ke45
ke45
Mitglied seit
12 Jahre 6 Monate

@ wuelle [#28]

Zur Erklärung: Dieses Lock/UnLock sorgt dafür, dass der dazwischenliegende Code exklusiv ohne Unterbrechung ausgeführt wird. Sind mehrere parallele Tasks/Threads an dieser Stelle (so wie es bei MultiCharts bei Dir gerade passiert) dann müssen diese warten, bis der 1. Thread das Unlock gemacht hat. Der 3. und 4. Thread warten dann immer noch während der 2. die Zeilen durchläuft usw.

Dadurch erreicht man, dass die kritischen Codezeilen auch bei Multithreading sequentiell exklusiv abgearbeitet werden und somit jeder Optimierungslauf seinen eigenen individuellen Dateinamen bekommt.

Der ID-String ist dabei beliebig wählbar, alle Threads mit der gleichen ID werden an der entsprechenden Stelle synchronisiert.

-Klaus

wuelle
Mitglied seit
12 Jahre 6 Monate

@ ke45 [#29]

Liege ich mich meiner Vermutung richtig, dass durch den Lock/Unlock Befehl, ein Optimierungslauf um den Faktor 4 langsamer wird, weil quasi immer nur ein Prozessorkern arbeitet und auf die Freigabe wartet?

Gast

@ wuelle [#30]

nein, es wird nich um Faktor 4 langsamer!
Du solltest nur darauf achten, das sowenig wie möglich im "gesperrten" Codebereich gemacht wird. Nachfolgende Variante wäre also optimaler, weil hier der Stringbefehl zur Erzeugung des eindeutigen Dateinamens jetzt nicht mehr im gesperrten Bereich ist...

Lock("MeinSystem");
x = GV_GetNamedInt("GV1",0) + 1;
GV_SetNamedInt("GV1", x);
UnLock("MeinSystem");
Datei = "C:\Temp\" + NumToStr(x,0) + ".txt";

Je mehr eigentlichen Systemcode du hast, um so unbedeutender wirkt sich der kurze Teil welcher nicht parallel läuft aus.
...
Wenn du 400 Zeilen Code hast und 4 Zeilen (1%) sind gesperrt, dann hast du grob gesagt wahrscheinlich ca. 396% statt 400% max. Verarbeitungsgeschwindigkeit.
...
Wenn du 40 Zeilen Code hast und 4 Zeilen (10%) sind gesperrt, dann hast du grob gesagt wahrscheinlich ca. 360% statt 400% max. Verarbeitungsgeschwindigkeit.
...

(ist nur eine Schätzung, bitte das mit den %-Werten nicht exact nachrechnen, und den Rest hab ich dir ja per Mail geschrieben:)

Rückrufservice
Beschreiben Sie bitte Ihr Anliegen, damit wir uns auf den Rückruf vorbereiten können.
Ja, ich habe die Datenschutzerklärung zur Kenntnis genommen und willige ein, dass die von mir angegebenen Daten inklusive der Kontaktdaten zwecks Bearbeitung der Anfrage und für den Fall von Anschlussfragen elektronisch erhoben und gespeichert werden. Meine Daten werden dabei nur streng zweckgebunden zur Bearbeitung meiner Anfrage genutzt und nicht ohne Einwilligung weitergegeben. Diese Einwilligung kann jederzeit mit Wirkung für die Zukunft widerrufen werden.

Register now

Jetzt registrieren und ZMP Live+ 14 Tage kostenlos testen!
  • Dauerhaft kostenfrei
  • Keine Zahlungsinformationen erforderlich
Hilfe?

Sie haben Fragen zu ZMP Live? Unser Team steht gerne hilfsbereit zu Ihrer Verfügung. Senden Sie uns gerne eine Nachricht:

Es gilt unsere Datenschutzerklärung