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!
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();
NuGet Packages im Code auslesen
lock Alternative für async/await
Beim CleanCode zählen nicht die Regeln, sondern dass wir uns mit diesen Regeln befassen, selbst wenn wir sie nicht befolgen - hoffentlich nach reiflichen Überlegungen.
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.
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.”
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.
[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.”
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(),
});
Hallo,
wo ist denn 'last130CnValues' deklariert?
Oder sollte es doch 'last26CnValues' sein.
glandorf
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.
[ > ](https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.list-1.reverse?view=netframework-4.8)
gibtvoid
zurück. Darauf kannst du dasTake
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(),
});
NuGet Packages im Code auslesen
lock Alternative für async/await
Beim CleanCode zählen nicht die Regeln, sondern dass wir uns mit diesen Regeln befassen, selbst wenn wir sie nicht befolgen - hoffentlich nach reiflichen Überlegungen.
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.
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.
NuGet Packages im Code auslesen
lock Alternative für async/await
Beim CleanCode zählen nicht die Regeln, sondern dass wir uns mit diesen Regeln befassen, selbst wenn wir sie nicht befolgen - hoffentlich nach reiflichen Überlegungen.
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^^
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.
NuGet Packages im Code auslesen
lock Alternative für async/await
Beim CleanCode zählen nicht die Regeln, sondern dass wir uns mit diesen Regeln befassen, selbst wenn wir sie nicht befolgen - hoffentlich nach reiflichen Überlegungen.
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?
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.
NuGet Packages im Code auslesen
lock Alternative für async/await
Beim CleanCode zählen nicht die Regeln, sondern dass wir uns mit diesen Regeln befassen, selbst wenn wir sie nicht befolgen - hoffentlich nach reiflichen Überlegungen.
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?
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