Laden...

Mit Parse nach dem größten/niedrigsten Wert in einer spezifischen Periode suchen

Erstellt von Branpo vor 4 Jahren Letzter Beitrag vor 4 Jahren 2.127 Views
B
Branpo Themenstarter:in
11 Beiträge seit 2019
vor 4 Jahren
Mit Parse nach dem größten/niedrigsten Wert in einer spezifischen Periode suchen

Guten Abend,

gibt es die möglichkeit mit der Parse Funktion Daten auszulesen und Zeitlich die größten/kleinsten Werte aus einer Periode auszugeben?

ich nutze zur Zeit diese Funktion:

								MyCotDataList.Add(new COTData_Obj
				{
					Time =  DateTime.Parse(split[0]), 
					CL  = double.Parse(split[5]),	
					CS = double.Parse(split[6]) *-1,
					CN = double.Parse(split[5]) - double.Parse(split[6]),	
					VARMAX = 
					VARMIN =
						
				});

jetzt würde ich gerne bei VARMAX = die größte Zahl der letzten 130 Werte von CN ausgeben und bie VARMIN die kleinste aus der Zeit.
Gibt es dazu eine Möglichkeit mit Parse oder muss ich das komplett anders lösen?
Vielen Dank für die Hilfe!

2.078 Beiträge seit 2012
vor 4 Jahren

Wo findest Du denn die letzten 130 Werte? In MyCotDataList?

var last130CnValues = MyCotDataList
    .Reverse()
    .Take(130)
    .Select(x => x.CN)
    .ToArray();

var min = last130CnValues.Min();
var max = last130CnValues.Max();
B
Branpo Themenstarter:in
11 Beiträge seit 2019
vor 4 Jahren

Danke Palladin007 für Deine Antwort.
Leider kann ich es versuchen ein- und umzubauen wie ich möchte ich bekomme immer Fehler zurück.

Zu Deiner Frage, die Werte werden aus einer CSV ausgelesen, ich hänge mal die komplette Methode an dann wird die Sache eventuell etwas klarer.
Es sollten aber die CN Werte verwendet werden.


				public static List<COTData_Obj> MakeListOfCOTData(string FilePath)

		{

			MyCotDataList = new List<COTData_Obj>();
			
			
			int Date_SplitIndexNum=0;
			int OI_SplitIndexNum=8;
					
			string p1 = FilePath ;
			
			if (!File.Exists(p1))
			{
	
				NinjaTrader.Code.Output.Process("File does not exist.", PrintTo.OutputTab1);	
			
				return null;
			}		
			
			StreamReader s1;
		
			s1 = new System.IO.StreamReader(p1);
		
			string Line1;
			string[] split;
			
			while ((Line1 = s1.ReadLine()) != null) 
			{
				
				int splitCounter = 0;
				
				split =  Line1.Split(new char[] {','}, StringSplitOptions.None);			
				
				
	
					foreach(string s in split)
					{
					
						//If it finds Date in row, then proper header found, and we should use this apporach.
						if(s.Equals("Date"))
						{
							Date_SplitIndexNum = splitCounter;
								
						}
						else if(s.Equals("Previous Day Open Interest"))
						{
							OI_SplitIndexNum = splitCounter;
								
						}
							splitCounter++;
					}
							
				string myString;
				DateTime dateFortmated;


				try
				{
		
					
			
					myString=split[Date_SplitIndexNum];

					dateFortmated=	ParseDateFromString(myString);
					
					
					
				}
				catch
				{
					NinjaTrader.Code.Output.Process("Header was caught", PrintTo.OutputTab1);
					continue;	
				}
				
				double OIToUse =0; 
				
				
				
				try
				{		
						if(double.TryParse(split[OI_SplitIndexNum], out OIToUse));	
						
						
						
						
				}
				catch(Exception e)
				{
					continue;  
				}
				
				

				MyCotDataList.Add(new COTData_Obj
				{
					Time =  DateTime.Parse(split[0]), 
					CL  = double.Parse(split[5]),	
					CS = double.Parse(split[6]) *-1,
					CN = double.Parse(split[5]) - double.Parse(split[6]),	


				});

Ich hab es folgendermaßen versucht:

																			MyCotDataList.Add(new COTData_Obj
				{
					Time =  DateTime.Parse(split[0]), 
					CL  = double.Parse(split[5]),	
					CS = double.Parse(split[6]) *-1,
					CN = double.Parse(split[5]) - double.Parse(split[6]),	
					var last130CnValues = MyCotDataList[3].CN

					.Reverse()
    				.Take(130)
   				    .Select(x => MyCotDataList.CN)
    			    .ToArray(),
					var MIN = last130CnValues.Min(),
					var MAX = last130CnValues.Max(),

						
						

				});

leider bekomme ich da aber dann Syntaxfehler "," erwartet nach jedem var.

Und wenn ich es so versuche:

				MyCotDataList.Add(new COTData_Obj
				{
					Time =  DateTime.Parse(split[0]), 
					CL  = double.Parse(split[5]),	
					CS = double.Parse(split[6]) *-1,
					CN = double.Parse(split[5]) - double.Parse(split[6]),	
					last130CnValues = MyCotDataList[3].CN

					.Reverse()
    				.Take(130)
   				    .Select(x => x.CN)
    			    .ToArray(),
					MIN = last130CnValues.Min(),
					MAX = last130CnValues.Max(),

						
						

				});

bekomme ich den Fehler: 'double' enthält keine Definition für 'Reverse', und es konnte keine Erweiterungsmethode 'Reverse' gefunden werden, die ein erstes Argument vom Typ 'double' akzeptiert (Fehlt eine Using-Direktive oder ein Assemblyverweis?).

				MyCotDataList.Add(new COTData_Obj
				{
					Time =  DateTime.Parse(split[0]), 
					CL  = double.Parse(split[5]),	
					CS = double.Parse(split[6]) *-1,
					CN = double.Parse(split[5]) - double.Parse(split[6]),	
					last130CnValues = MyCotDataList

					.Reverse()
    				.Take(130)
   				    .Select(x => x.CN)
    			    .ToArray(),
					MIN = last130CnValues.Min(),
					MAX = last130CnValues.Max(),

				});

Error Code Line Column
CommercialsOszilator.cs Der Operator '.' kann nicht auf einen Operanden vom Typ 'void' angewendet werden.

U
69 Beiträge seit 2019
vor 4 Jahren

Wie Palladin007 schrieb müsste es wahrscheinlich so heissen:

last130CnValues = MyCotDataList
    .Reverse()
    .Take(130)
    .Select(x => x.CN)
    .ToArray();

Mit

last130CnValues = MyCotDataList[3].CN

                    .Reverse()
                    .Take(130)
                       .Select(x => MyCotDataList.CN)

rufst du das Reverse auf MyCotDataList[3].CN auf. CN ist ein double der kein Reverse kennt.

“Knowledge cannot replace friendship. I'd rather be an idiot than lose you.”

  • Patrick to Spongebob
B
Branpo Themenstarter:in
11 Beiträge seit 2019
vor 4 Jahren

Vielen Dank für die Antwort Urza.
Das hatte ich am Anfang probiert allerdings bekomm ich da folgenden Fehler:

					MyCotDataList.Add(new COTData_Obj
				{
					Time =  DateTime.Parse(split[0]), 
					CL  = double.Parse(split[5]),	
					CS = double.Parse(split[6]) *-1,
					CN = double.Parse(split[5]) - double.Parse(split[6]),	
					OBEN = 90,
					UNTEN = 10,
					last130CnValues = MyCotDataList

					.Reverse()
    				.Take(130)
   				    .Select(x => x.CN)
    			    .ToArray();
			//		MIN = last130CnValues.Min(),
			//		MAX = last130CnValues.Max(),

				});

Error Code Line Column
Syntaxfehler. ',' erwartet. hinter .ToArray();
wenn ich das ; auf , ändere bekomme ich allerdings den Fehler

Der Operator '.' kann nicht auf einen Operanden vom Typ 'void' angewendet werden.

U
69 Beiträge seit 2019
vor 4 Jahren

[Reverse](https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.list-1.reverse?view=netframework-4.8) gibt void zurück. Darauf kannst du das Take also nicht aufrufen.

Mache das Reverse einfach vorher.
Ich habs jetzt nicht getestet, müsste aber so oder so ähnlich ausshen.

                   
var myCotDataListReversed = new List<COTData_Obj>(MyCotDataList);
myCotDataListReversed.Reverse();
 MyCotDataList.Add(new COTData_Obj
                {
                    Time =  DateTime.Parse(split[0]),
                    CL  = double.Parse(split[5]),
                    CS = double.Parse(split[6]) *-1,
                    CN = double.Parse(split[5]) - double.Parse(split[6]),
                    OBEN = 90,
                    UNTEN = 10,
                    last130CnValues = myCotDataListReversed
                        .Take(130)
                       .Select(x => x.CN)
                       .ToArray(),
                });

“Knowledge cannot replace friendship. I'd rather be an idiot than lose you.”

  • Patrick to Spongebob
B
Branpo Themenstarter:in
11 Beiträge seit 2019
vor 4 Jahren

Vielen Dank Urza,

mit

				MyCotDataList.Add(new COTData_Obj
				{
					Time =  DateTime.Parse(split[0]), 
					CL  = double.Parse(split[5]),	
					CS = double.Parse(split[6]) *-1,
					CN = double.Parse(split[5]) - double.Parse(split[6]),	
					OBEN = 90,
					UNTEN = 10,

				}); 
				 var myCotDataListReversed = new List<COTData_Obj>(MyCotDataList);
					myCotDataListReversed.Reverse();
					MyCotDataList.Add(new COTData_Obj
                {

                   CNR = double.Parse(split[5]) - double.Parse(split[6]),

                   last26CnValues = myCotDataListReversed
                        .Take(26)
                       .Select(x => x.CNR)
                       .ToArray(),
                });

hat es jetzt funktioniert bzw gibt zumindest keinen Fehler mehr bei de Kompilierung an.
ich musste allerdings last26CnValues von double auf double[] ändern was eventuell bei anderen Dingen später Probleme machen könnte aber ich denke das geht nicht ohne oder?

public double[] last26CnValues {get; set;}

Das Problem das ich nun habe ist das ich Max und Min nicht in den Code bekomme.
Füge ich es wie im Ursprünglichen Beispiel von Palladin007 ein bekomme ich den Fehler
Der Name 'last130CnValues' ist im aktuellen Kontext nicht vorhanden.

				MyCotDataList.Add(new COTData_Obj
				{
					Time =  DateTime.Parse(split[0]), 
					CL  = double.Parse(split[5]),	
					CS = double.Parse(split[6]) *-1,
					CN = double.Parse(split[5]) - double.Parse(split[6]),	
					OBEN = 90,
					UNTEN = 10,

				}); 
				 var myCotDataListReversed = new List<COTData_Obj>(MyCotDataList);
					myCotDataListReversed.Reverse();
					MyCotDataList.Add(new COTData_Obj
                {

                   CNR = double.Parse(split[5]) - double.Parse(split[6]),

                   last26CnValues = myCotDataListReversed
                        .Take(26)
                       .Select(x => x.CNR)
                       .ToArray(),
						MIN = last130CnValues.Min(),
                            MAX = last130CnValues.Max(),
                });
87 Beiträge seit 2016
vor 4 Jahren

Hallo,

wo ist denn 'last130CnValues' deklariert?

Oder sollte es doch 'last26CnValues' sein.

glandorf

B
Branpo Themenstarter:in
11 Beiträge seit 2019
vor 4 Jahren

Hi Glandorf,

ja ich gebe zu das war etwas ungeschickt ich hab die 130 auf 26 geändert. Ab jetzt ist daher alles mit 26anstatt 130 mir viel nebenbei ein Logikfehler auf den ich hatte.

2.078 Beiträge seit 2012
vor 4 Jahren

[ &gt; ](https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.list-1.reverse?view=netframework-4.8) gibt void zurück. Darauf kannst du das Take also nicht aufrufen.

Tatsache, ich war gedanklich bei LINQ to Objects, da gibt's nämlich auch eine Reverse-Methode, die ein IEnumerable zurück gibt.

Ich als LINQ-Fanboy würde daher trotzdem so arbeiten 😄

var last130CnValues = MyCotDataList
    .AsEnumerable()
    .Reverse()
    .Take(130)
    .Select(x => x.CN)
    .ToArray();

var min = last130CnValues.Min();
var max = last130CnValues.Max();

Ist am Ende des Tages aber Geschmackssache, man hat halt eine Variable weniger.

Wenn ich mit deinen Schnipsel Mal nehme:

var myCotDataListReversed = new List<COTData_Obj>(MyCotDataList);
myCotDataListReversed.Reverse();
MyCotDataList.Add(new COTData_Obj
{
    CNR = double.Parse(split[5]) - double.Parse(split[6]),

    last26CnValues = myCotDataListReversed
        .Take(26)
        .Select(x => x.CNR)
        .ToArray(),
});

Das sieht für mich aus, als hättest Du "last26CnValues" als Property definiert? Warum?

Warum nicht einfach davor als Variable? Das spart eine für spätere Anwendungen völlig nutzlose Property.

var myCotDataListReversed = new List<COTData_Obj>(MyCotDataList);
myCotDataListReversed.Reverse();

var last26CnValues = myCotDataListReversed
    .Take(26)
    .Select(x => x.CNR)
    .ToArray();

MyCotDataList.Add(new COTData_Obj
{
    CNR = double.Parse(split[5]) - double.Parse(split[6]),

    Min = last26CnValues.Min(),
    Max = last26CnValues.Max(),
});

Oder wie ich es lieber mag:

var last26CnValues = MyCotDataList
    .AsEnumerable()
    .Reverse()
    .Take(26)
    .Select(x => x.CNR)
    .ToArray();

MyCotDataList.Add(new COTData_Obj
{
    CNR = double.Parse(split[5]) - double.Parse(split[6]),

    Min = last26CnValues.Min(),
    Max = last26CnValues.Max(),
});
B
Branpo Themenstarter:in
11 Beiträge seit 2019
vor 4 Jahren

Vielen lieben Dank Paladin007 ich habe mich für die letzte deiner Varianten entschieden.

Jetzt hab ich das nächste Problem ^^
wenn ich die Daten ausgebe sollte bei min -570469 bei max -322423 ausgegeben werden.
tatsächlich gibt mir min -4316K und bei max immer 0 aus.

ich gebe die Liste mit

						private void SetPlotMin(List<COTData_Obj> cotDataList, int barCount)
		{
			int numberOfPlotsToSet = Math.Min(barCount, cotDataList.Count);

			
			for(int i=0;  i < numberOfPlotsToSet-2; i++)		
			Values[5][i]=  cotDataList[i].Min;

	
		}		
						private void SetPlotMax(List<COTData_Obj> cotDataList, int barCount)
		{
			int numberOfPlotsToSet = Math.Min(barCount, cotDataList.Count);

			
			for(int i=0;  i < numberOfPlotsToSet-2; i++)		
			Values[6][i]=  cotDataList[i].Max;

	
		}	

aus.
da ich aus den ganzen werten dann am Schluss einen Oszilator ((CN-Min)/(Max-Min)*100) berechnen möchte den ich benötige müssen die Basiswerte stimmen.

2.078 Beiträge seit 2012
vor 4 Jahren

Ich glaube nicht, dass der Fehler in der Methode zu suchen ist, denn die weist nur die Min/Max-Werte anderen Properties zu, sie berechnet nichts.

Mein Code-Snippet macht nix, außer den höchsten bzw. niedrigsten Wert zu suchen. Wenn dein Ergebnis anders ist, als Du es erwartest, dann wird der Fehler weit davor liegen, nämlich wenn Du die CN-Werte berechnest.

B
Branpo Themenstarter:in
11 Beiträge seit 2019
vor 4 Jahren

Ich habe mir gerade nochmal den CN Wert und oben Min/Max auf dem Chart anzeigen lassen.
Die angezeigten CN Werte stimmen. Nur leider zeigt mir Min/Max eben nicht die Extrempunkte der letzten 26 Werte an. Hab ich irgendwo einen Logikfehler in der Methode?

Ist es möglich das es daran liegt das die Einträge dem falschen oder sogar gar keinem Datum zugeordnet werden so wie ich das mache?

				MyCotDataList.Add(new COTData_Obj
				{
					Time =  DateTime.Parse(split[0]), 
					CL  = double.Parse(split[5]),	
					CS = double.Parse(split[6]) *-1,
					CN = double.Parse(split[5]) - double.Parse(split[6]),	
					OBEN = 90,
					UNTEN = 10,

				}); 
				
var last26CnValues = MyCotDataList
    .AsEnumerable()
    .Reverse()
    .Take(26)
    .Select(x => x.CNR)
    .ToArray();

MyCotDataList.Add(new COTData_Obj
{
    CNR = double.Parse(split[5]) - double.Parse(split[6]),

 Min = last26CnValues.Min(),
 Max = last26CnValues.Max(),
});

wenn ich es so versuche:

var last26CnValues = MyCotDataList
    .AsEnumerable()
    .Reverse()
    .Take(26)
    .Select(x => x.CNR)
    .ToArray();				

				MyCotDataList.Add(new COTData_Obj
				{
					Time =  DateTime.Parse(split[0]), 
					CL  = double.Parse(split[5]),	
					CS = double.Parse(split[6]) *-1,
					CN = double.Parse(split[5]) - double.Parse(split[6]),
					CNR = double.Parse(split[5]) - double.Parse(split[6]),
 					Min = last26CnValues.Min(),
 					Max = last26CnValues.Max(),
					OBEN = 90,
					UNTEN = 10,

				}); 

bekomme ich zwar keinen Kompilierungsfehler der Indikator kann jedoch nicht geladen werden was dafür spricht das ich etwas versuche das aus irgendeinem Grund nicht geht.
Abgesehen davon is mir aufgefallen das ich CNR eigentlich nicht brauche da CN genau das Selbe macht^^

2.078 Beiträge seit 2012
vor 4 Jahren

Hast Du dir alle Werte angeschaut, oder nur die letzten 26?
Musst Du die Liste vielleicht nach einem Datum sortieren?

Und guck dir die Werte nach dem parse an, nicht davor.
Die parse-Methoden können auch eine CultureInfo (bzw. IFormatProvider, aber CultureInfo implementiert das) entgegen nehmen. Gibst Du das nicht mit, nutzen sie CultureInfo.CurrentCulture (bzw. Thread.CurrentThread.CurrentCulture) und das ist deine Windows-Einstellung.
Bei Deutsch und Englisch kann das einen erheblichen Unterschied machen, da die Seperatur-Zeichen (1000er, Nachkommastellen) vertauscht sind.

B
Branpo Themenstarter:in
11 Beiträge seit 2019
vor 4 Jahren

ich hatte mir im Grafen die letzten 365 Werte in der Ausgabe angeschaut.
Ich habe mal einen Screenshot angehängt.
Das ist beides mal die Ausgabe von CN. Alle anderen Werte habe ich absichtlich nicht mit ausgeben lassen. Der einzige Unterschied zwischen den beiden Ausgaben ist das der obere mit code

                MyCotDataList.Add(new COTData_Obj
                {
                    Time =  DateTime.Parse(split[0]),
                    CL  = double.Parse(split[5]),
                    CS = double.Parse(split[6]) *-1,
                    CN = double.Parse(split[5]) - double.Parse(split[6]),
                    OBEN = 90,
                    UNTEN = 10,

                });

var last26CnValues = MyCotDataList
    .AsEnumerable()
    .Reverse()
    .Take(26)
    .Select(x => x.CNR)
    .ToArray();

MyCotDataList.Add(new COTData_Obj
{
    CNR = double.Parse(split[5]) - double.Parse(split[6]),

Min = last26CnValues.Min(),
Max = last26CnValues.Max(),
});

ist und die untere mit dem Code:

				MyCotDataList.Add(new COTData_Obj
				{
					Time =  DateTime.Parse(split[0]), 
					CL  = double.Parse(split[5]),	
					CS = double.Parse(split[6]) *-1,
					CN = double.Parse(split[5]) - double.Parse(split[6]),

					OBEN = 90,
					UNTEN = 10,

				}); 
/*			
var last26CnValues = MyCotDataList
    .AsEnumerable()
    .Reverse()
    .Take(26)
    .Select(x => x.CN)
    .ToArray();

MyCotDataList.Add(new COTData_Obj
{
    

 Min = last26CnValues.Min(),
 Max = last26CnValues.Max(),
});   
				*/

Es kommt scheinbar immer wieder zu einem Bruch bzw 0 Werten in der Liste. Daher wie gesagt die Vermutung das irgendwas mit der Time zuordnung nicht so passt.
Gibt es die Möglichkeit alles den Text so zusammenzufügen das dies nicht mehr passiert?

2.078 Beiträge seit 2012
vor 4 Jahren

Schau dir den oberen Code Mal an und geh Stück für Stück durch, was Du da tust.

Du fügst dort ein neues Objekt nochmal der Liste hinzu, obwohl Du das vorher schon getan hast. Dieses Mal lässt Du die anderen Werte weg, schreibst dafür aber Min, Max und CNR.
Wenn Du im Grafen z.B. die CN-Werte anzeigen lässt, ist also jeder zweite Wert 0 und das liegt denke ich nicht in deinem Interesse.

B
Branpo Themenstarter:in
11 Beiträge seit 2019
vor 4 Jahren

Jetzt bin ich endlich draufgekommen was genau das Problem war und wie ich es behebe =)

				COTData_Obj row = new COTData_Obj
                {
                    Time =  DateTime.Parse(split[0]), 
                    CN = double.Parse(split[5]) - double.Parse(split[6]),
                };
				
				MyCotDataList.Add(row); 


                var last26CnValues = MyCotDataList
                    .AsEnumerable()
                       .Reverse()
                        .Take(26)
                          .Select(x => x.CN)
                        .ToArray();

                row.Min = last26CnValues.Min();
                row.Max = last26CnValues.Max();

natürlich wär es aber ja zu schön gewesen wenn es dann auch so funktioniert wie es soll...

Nun sieht das ganze so aus wie unten auf dem angehängten Screenshot

Blau ist CN Grün Max und Rot Min.
Eigentlich sollte ja der eine niedrigste bzw höchste Wert der letzten 26 Werte ausgegeben werden jedoch wirkt es mir so als das er jedesmal rückwirkend die letzten 26 Werte überschreibt kann das sein?

5.657 Beiträge seit 2006
vor 4 Jahren

natürlich wär es aber ja zu schön gewesen wenn es dann auch so funktioniert wie es soll...

Softwareentwicklung ist doch kein Rätelraten oder Glücksspiel 😃

Du hast alle Werkzeuge zur Verfügung, um herauszufinden, was dein Code macht, bzw. nicht macht:
[Artikel] Debugger: Wie verwende ich den von Visual Studio?
[Artikel] Unit-Tests: Einführung in das Unit-Testing mit VisualStudio

Weeks of programming can save you hours of planning