|
Gruppen: Kunde
Beiträge: 22
|
Hallo Market-Maker-Mitstreiter, ich habe wieder mal ein programmiertechnisches Problem bezüglich MM-Talk. Ich möchte in einer Tabelle zunächst Wertpapiere nach bestimmten Kriterien filtern (z.B. alle an XETRA gehandelten Aktien mit mindestens 5 Jahren Kurshistorie - das sind ca. 750 Stück). Danach möchte ich für diese Auswahl einen bestimmten Indikator, z.B. die Relative Stärke nach Levy auf Wochenbasis, berechnen und diesen in der Tabelle nach absteigendem RSL sortieren. Soweit funktioniert alles ganz prima. Nun zu meinem Problem: Ich möchte den Papieren zusätzlich eine Rangziffer zuordnen. Die MM-Talk-Funktion "Rank" arbeitet gewöhnlich mit einer Indexzusammenstellung (z.B. DAX): Code:$x:=#[](Close[_;_;_;7].RSL[27;"Linear"]); Rank($x.Apply[object];$x.Map[".DAX (X)".WP.WPComposition];false)
Ist es auch möglich, für die Funktion "Rank" statt der Indexzusammenstellung als Eingabeliste die vorher bereits gefilterte Tabelle zu verwendten? Wenn ja, wie geht das? Vielen Dank im Voraus für Euere Hilfe. Gruß Norbert
|
|
Gruppen: Kunde
Beiträge: 167
|
Hallo Norbert, das ist wie vieles in MM-Talk ganz einfach. Für den Ausdruck - ".DAX (X)".WP.WPComposition – setze einfach: "Name_deines_Fiters“.findfolder.wp. Findfolder erzeugt aus einem String ein Ordnerobjekt, wenn es einen Ordner mit diesem Namen gibt. WP auf ein Ordnerobjekt angewendet, erzeugt eine Liste der Wertpapiere, die in diesem Ordner enthalten sind. Und das ist dann schon Deine Lösung. Doch lass mich Dir noch ein paar Tipps geben. 1. Verwende in einer Formel nie den ausgeschriebenen Namen eines Index oder eines Ordners. Denn willst Du die Formel dann auf einen anderen Index oder Ordner anwenden, dann musst Du in der Formel ändern. Verwende dafür immer eine Variable, dann kann die Formel gleich bleiben und du änderst an der Bedienoberfläche nur den Inhalt der Variablen. Doch denke daran, zu kontrollieren, ob die Variable den korrekten Objekttyp hat. Willst Du in die Variable einen Indexnamen eingeben, dann muss die Variable den Typ „Wertpapier“ besitzen. Willst du einen Ordnernamen eingeben, dann muss die Variable vom Typ Ordner sein und Du musst zusätzlich beim Typ Ordner noch angeben, welcher Ordner Typen (Ordner, Filter, Depot, usw.) zugelassen werden soll. Die Verwendung der Variablen hat auch noch den Vorteil, Dass in die Variable nur ein Teil des Ordner Namens eingegeben werden muss und Dein Programm zeigt Dir dann alle Ordner an, die diesen Teilstring in Ihrem Namen haben. 2. Die korrekte Aktualisierung der Kurse ist das A&O eines Börsenprogramms. Aber egal welchen Anbieter Du nimmst, es kann immer mal vorkommen, dass vielleicht zu einem Papier an einem Tag kein Kurs vorhanden ist. Wenn Du dann mit Funktionen arbeitest, wie bei „Rank“, wo eine Zeitreihe gegen hunderte von Zeitreihen aus dem Ordner verglichen wird, so kann eine solche Lücke in einem Kurs dazu führen, dass das Ergebnis nicht mehr darstellbar ist. Denn wie soll das Programm A durch B teilen wenn bei B der fehlende Kurs einzusetzen wäre. Deshalb benutze ich beim Arbeiten mit Zeitreihen in Listen immer die Funktion Fillgaps["interpolate"], die solche Lücken mit dem Mittelwert aus den benachbarten Werten füllt. Deine Formel würde ich dann folgendermaßen umschreiben. Code:$OL:=$Ordner.findfolder.wp; {Wertpapiere eines Ordner, Filters,... einlesen}
{ -------------------------------------- Anonymes Makro zum berechnen des RSL --------------------------------------} $X:=#[](Close[_; _; _; 7] {Close Zeitreihe des jeweiligen Wertpapiers} .fillgaps["interpolate"] {fülle Kurslücke mit dem Mittelwert} .RSL[27;"Linear"]); {RSL Zeitreihe berechnen}
{ ---------------------------------------------------------------- Berechnen der RSL-Zeitreihen für jedes Wertpapier der Liste OL ----------------------------------------------------------------} $O_RSL:=$X.map[$OL];
{ ----------------------------------------------------------- Berechnen der Rang Zeitreihe für das jeweilige Wertpapier -----------------------------------------------------------} $X.apply[object].Rank[$O_RSL; $Aufwärts]
Und noch eins zum Abschluß: Wenn Du Deine Formel mit dem DAX als Index, als Spaltenformel in einer Tabelle benutzt, dann wird in jeder Zeile der Tabelle (Zeile = ein Wertpapier) jedesmal für alle Wertpapiere des DAX die Liste der RSL-Zeitreihen neu berechnet. Und das kostet Zeit. Bei 30 Werten des DAX ist das vielleicht noch akzeptabel, aber beim S&P500, oder wie Du es möchtest bei den ca. 750 Aktien aus Xetra, ist die Rechenzeit ganz erheblich. Um diese zu optimieren (zu verkürzen) schau Dir einmal meinen Beitrag Tipp Tabellenberechnung in der Rubrik Anwendungsbeispiele &Tipps/Tricks an. Er zeigt dazu einen Lösungsansatz auf. Ich hoffe Du kommst damit weiter. Wenn nicht, dann nachfragen. Allen noch einen schönen Tag und weiterhin erfolgreiche Trades. Chuck
|
|
Gruppen: Kunde
Beiträge: 22
|
Hallo Chuck,
zunächst mal vielen Dank für Deine Hilfe. Deine äußerst qualifizierten Beiträge im Forum sind mir schon sehr oft aufgefallen.
Leider funktioniert die Rangfolge in meiner Tabelle trotz Deiner Hilfe immer noch nicht (Rang = n/a).
Vermutlich habe ich Dir meine Aufgabe nicht ganz richtig erklärt bzw. habe ich noch ein fundamentales Verständnisproblem.
Zunächst habe ich eine Filtervorlage (siehe Seite 84, Handbuch MM 3.0) auf alle Aktien der Datenbank erstellt. Als "Parameter- und Filterbedingungen" habe ich den Börsenplatz XETRA (EDE), eine Kurshistorie von mindesten 5 Jahren in der Datenbank sowie kein Penny-Stock (aktueller Close > 0,1) ausgewählt. Dadurch bleiben von über 100.000 Werten noch etwa 750 übrig. Von diesen Werten bestimme ich die Relative Stärke nach Levy und sortiere die entsprechende Spalte absteigend. Das funktioniert alles super. Nun möchte ich in einer weiteren Spalte die Rangziffern von 1 - ca. 750 für die RSL's dieser Wertpapiere.
Meine Tabellenvorlage heißt "Rangliste_3", deshalb habe ich den Ordner für FindFolder ebenfalls "Rangliste_3" genannt, also $OL:="Rangliste_3".FindFolder.WP. Irgendwie vermute ich, das ist nicht richtig, aber was soll ich da sonst angeben? Im Explorer habe ich keinen zusätzlichen Filterordner mit den selektierten Wertpapieren angelegt. Muß ich das - was für mich eigentlich unlogisch wäre? In der Tabelle sind doch alle benötigten Informationen vorhanden. Die Parametereinstellungen für den Ordner habe ich unter "Typen definieren" auf Feldtyp "Ordner" und dann noch auf "Filter" gesetzt.
Ich kann den mme-Export meiner Vorlage auch gerne mal ins Forum stellen.
Deinen Beitrag über die Tabellenberechnung in der Rubrik Anwendungsbeispiele & Tipps/Tricks habe ich mir vor längerer Zeit schon mal angeschaut und wie ich glaube, auch Verstanden. Im 2.Beispiel wird die Arithmetik in die Präformel verlegt, dadurch entfallen viele Aufrufe der Funktion "Rank", eigentlich genial. Wenn mein Projekt prinzipiell läuft, werde ich das auch probieren.
Besten Dank für Deine Mühe.
Viele Grüße und ein erfolgreiches Handeln an den Märkten
Norbert
|
|
Gruppen: Kunde
Beiträge: 167
|
Hallo Norbert, Du schreibst: Zitat:Meine Tabellenvorlage heißt "Rangliste_3", deshalb habe ich den Ordner für FindFolder ebenfalls "Rangliste_3" genannt, also $OL:="Rangliste_3".FindFolder.WP. und weiter: Zitat:Im Explorer habe ich keinen zusätzlichen Filterordner mit den selektierten Wertpapieren angelegt. Muß ich das - was für mich eigentlich unlogisch wäre? In der Tabelle sind doch alle benötigten Informationen vorhanden. Wahrscheinlich kennst Du dich nicht mit objektorientierten Programmiersprachen aus, sonst wäre Dir das klar. Ich versuche es einmal zu erklären. Stell Dir einmal einen Stempel (Klasse) / Vorlage mit einem Hund vor. Dies entspricht Deiner Vorlage in marketmaker. Die Vorlage beschreibt ganz allgemein, wie ein Hund aussieht. Er hat Beine, Körper, Kopf, Schwanz, Augen usw. Es ist eine Vorlage, aber es ist kein bestimmter Hund (kein bestimmtes Objekt). Jetzt begegnet Dir auf der Straße ein Wesen, das diesen allgemeinen Angaben deiner Vorlage entspricht. Dann ordnest Du dieses Wesen der Klasse Hund zu. Dieser Hund auf der Straße ist eine Instanz der Klasse Hund. Er hat zu den allgemeinen Beschreibungen jetzt noch zusätzliche Eigenschaften wie z.B. eine ganz bestimmte Größe, Farbe, Gewicht, usw. Es ist ein ganz bestimmter Hund (Objekt), der existiert, aus der Tierklasse der Hunde. Genauso ist es auch in Marketmaker. Eine Vorlage ist kein reales Objekt. Deine Vorlage Rangliste_3 kannst Du auf jeden beliebigen Ordner anwenden (markieren Ordner, rechte Maustaste und im Kontextmenu „Öffnen mit Vorlage..“ auswählen) und bekommst immer ein anderes Ergebnis. Je nachdem welche Papiere in dem Ordner vorhanden sind sieht dann Dein Ergebnis in der Tabelle aus. Denn die Vorlage filtert aus den Papieren des Ordners die heraus, die auch an Xetra gehandelt werden. Damit das Verfahren wie ich es beschrieben habe funktioniert, ist ein Filterordner notwendig, der als Objekte die ca. 750 Wertpapiere Deiner Tabelle enthält. Ob dieser Filterordner im Explorer zu sehen ist oder nicht, das ist egal. Der Explorer ist die Oberfläche um Objekte der Datenbank anzuzeigen. Aber nicht alle Objekte der Datenbank müssen auf der Oberfläche / im Explorer angezeigt werden. Also erstelle einen Filterordner und dann müsste es funktionieren. Wenn nicht, dann stelle Deine Vorlage im Thread ein und ich schaue sie mir an. Noch etwas zum Schluss. Du schreibst dass in der Spalte Rang n/a erscheint. Klicke ein solches n/a an, dann rechte Maustaste und im Kontextmenue Fehler anzeigen wählen. In dem sich öffnenden Fenster sind Hinweise zu der Fehlerursache zu sehen. Stelle dieses Fenster dann mit dem Export Deiner Vorlage in das Forum. Gruß Chuck
|
|
Gruppen: Kunde
Beiträge: 22
|
Hallo Chuck, es stimmt schon, die objektorientierte Programmierung ist nicht meine Stärke. Vor ca. 25 Jahren war ich mal bezüglich GW-Basic ganz gut, aber diese Programmiersprache ist leider mittlerweile vollkommen out. Nichtsdestotrotz habe ich die RSL-Sortierung zum Laufen gebracht. Ich habe einen Filterordner angelegt mit der Eigenschaft "Automatisch auswerten bei neuen Stammdaten" und diesen mit der Filtervorlage "Rangliste_3" verknüpft. Jetzt läuft das ganze. Allerdings tritt ein neues Problem auf. Die Sortierung erfolgt nicht richtig. In der 11.Spalte habe ich den RSL-Wert berechnet und auch über den Reiter Tabelle nach dieser Spalte sortiert. In Spalte 1 taucht der Rang auf. Dieser müßte meiner Meinung nach von 1 bis Maximalwert ansteigen. Die letzten 3 Spalten sind eigentlich nur zum Debuggen, der Wert x$.Apply[object], sowie der 1. und der letzte Wert der Liste $OL_RSL. In GW-Basic war das ein Array. Ich dachte, diese Liste wird nach Größe sortiert, aber das scheint nicht zu sein. Die Filtervorlage "Rangliste_3" und einen Bildschirmauschnitt der Auswertung habe ich beigefügt: Kannst Du mir eine Anregung geben, was die Ursachen für die falsche Sortierung sein könnte? Besten Dank und viele Grüße Norbert Dateianhänge: Rangliste_3.mme (102kb) downloaded 68 time(s).
Norbert Haupt hat die folgenden Bilder hochgeladen:
|
|
Gruppen: Kunde
Beiträge: 167
|
Hallo Norbert, ich kann Dir keine Anregung geben, warum die Sortierung bei Dir nicht stimmt. Bei mir läuft die Sortierung einwandfrei. Mir ist aufgefallen, dass Deine Tabelle in der Fußzeile anzeigt, dass sie immer über alle Aktien läuft ( bei mir mehr als 38000 Aktien), obwohl der Filterordner Rangliste_3 bei mir nur knapp 730 Aktien hatte. Du hast in der Präformel keinen Ausdruck angegeben, der das Eingabeobjekt für die Tabelle beschreibt. Dies kannst Du grundsätzlich machen. Aber in einer Spaltenberechnung verwendest Du die Funktion Rank. Code:Kandidat:Zeitreihe.Rank[ZeitreihenListe;Aufwärts]→Zeitreihe Die Zeitreihenliste für Rank hast Du mit der Funktion Code:$Ordner.FindFolder.WP gebildet. Gegen die RSL-Werte dieser Papiere werden jetzt die RSL-Werte der Papiere verglichen, die Eingangsobjekte der Tabelle sind. Stimmen diese beiden Anzahlen nicht überein, dann kann in der Spalte Rang nur „Mist“ herauskommen. Um das zu demonstrieren habe die Präformel wie Du leer gelassen und habe in dem Eingabefeld Ordner den Filterordner DAX eingetragen, der bei mir die 30 Dax-Werte und den Index als statisches Element enthält, also 31 Werte. Jetzt werden bei mir die ca. 730 Eingangswerte der Tabelle gegen die Zeitreihenliste DAX mit 31 Werten in eine Rangordnung gesetzt. Das Ergebnis siehst Du im Bild mit Ordner = DAX (X). So etwas könnte möglicherweise ein Ursache für Deine Sortierung sein, aber ich konnte Dein Bild nicht reproduzieren. Vielleicht kann Lenz+Partner Dir da Unterstützung geben, zumindest sich dazu äußern. Damit diese Diskrepanz nicht passieren kann, musst Du dafür sorgen, dass die Anzahl der Tabellenzeilen auch der Anzahl der Zeitreihen in der Zeitreihenliste von Rank entspricht. Das erreichst Du, wenn Du Code:$Ordner.FindFolder.WP in die Präformel einsetzt. In der letzten Spalte Deiner Tabelle (Liste $OL_RSL[756]) willst Du wohl auf die letzte Zeitreihe der Zeitreihenlist zugreifen. Deine Programmierung ($O_RSL.nth[756]), in dem Du eine feste Zahl für den Listenzugriff einsetzt, ist schlecht! Vermeide so etwas. Die Zeitreihenliste ist aus einem Filterordner entstanden. Der Filterordner ist ein dynamisches Element. D.h. die Anzahl der Wertpapiere kann sich jederzeit ändern. Z.B. wenn morgen 2 der jetzt vorhandenen Wertpapiere in ihrem aktuellen Close unter 10 Cent schließen, dann sind sie wegen Deinen Filterbedingungen nicht mehr in der Liste und Deine Liste besteht dann aus 754 Elementen. Die Funktion nth[756] liefert dann einen Fehler und in der Spalte erscheint n/a, wie in meiner Tabelle mit dem DAX Filterordner. Statt dem festen Zahlenwert lasse lieber die Länge der Liste berechnen ($O_RSL.length-1), um den letzten Wert auszugeben. Weiterhin viel Erfolg. Chuck Dateianhänge: Rangliste_3.jpg (564kb) downloaded 304 time(s). DAX.jpg (430kb) downloaded 273 time(s).
|
|
Gruppen: Kunde
Beiträge: 22
|
Hallo Chuck, bei mir läuft die Sortierung nach Rangziffer mittlerweile auch richtig. Die Ursache war meiner Meinung nach nicht ganz trivial. Für die Berechnung des RSL hatte ich geschrieben: Code:Close[_;_;_;7].FillGaps["interpolate"].RSL[27;"Linear"] Das ist nicht ganz richtig. Laut MM-Talk-Handbuch hat die Funktion FillGaps folgende Syntax: Code:KursZeitreihe.FillGaps[OutOfRange;Mode;Default]→Zeitreihe Den Parameter "Out of Range" hatte ich nicht gesetzt bzw. vergessen. Wenn ich schreibe: Code:Close[_;_;_;7].FillGaps[ja;"interpolate"].RSL[27;"Linear"] läuft alles richtig und die Sortierung passt. Gestatte mir bitte noch eine - für einen erfahrenen Anwender vielleicht blöde - Frage: Die Funktion "Rank" benötigt neben dem Zeitreihenkandidaten eine Zeitreihenliste mit allen in die Rangfolge zu bringenden Werten. Diese Zeitreihenliste kann ich entweder aus einer Indexzusammenstellung "[Index].WP.WPComposition" oder einem Filterordner "[Ordner].FindFolder.WP" generieren. Es ist aber offensichtlich nicht möglich, als Input für diese Zeitreihenliste das gefilterte Ergebnis einer Tabellenvorlage selbst (siehe Seite 84 Benutzerhandbuch MM3.0) zu verwenden, Für mich ist das moch ein bißchen merkwürdig, da ich ja in der Tabelle alle benötigten Angaben zur Verfügung hätte. Ich könnte zum Beispiel ja auch das Ergebnis einer Tabellenvorlage über die Zwischenablage in Excel exportieren und dann dort mit der Excel-Funktion RANG(Kandidat;Zeitreihenliste bzw. Spalte) gezielt nach einer Spalte sortieren, ohne den Umweg über einen (Filter-)Ordner. Sind meine Gedanken so richtig oder mache ich da noch einen gewaltigen Denkfehler? Ich möchte mich nochmals für Deine fundierte Hilfe bedanken und wünsche Dir alles Gute und viel Erfolg bei Deinen Anlagen Norbert
|
|
Gruppen: Kunde
Beiträge: 167
|
Hallo Norbert, Zitat:Es ist aber offensichtlich nicht möglich, als Input für diese Zeitreihenliste das gefilterte Ergebnis einer Tabellenvorlage selbst (siehe Seite 84 Benutzerhandbuch MM3.0) zu verwenden, Für mich ist das doch ein bißchen merkwürdig, da ich ja in der Tabelle alle benötigten Angaben zur Verfügung hätte. Das liegt an der Funktion der Tabelle. Eine Tabelle wird zeilenweise aufgebaut. Alle Objekte (Wertpapiere), die in der Tabelle dargestellt werden sollen, werden nacheinander an die Tabelle übergeben und für jedes Objekt einer Zeile, werden nacheinander die Spaltenformeln angewendet, bevor dann das nächste Objekt (Wertpapier) für die nächste Zeile an die Tabelle übergeben wird. Den Spaltenformeln steht für die Berechnung nur zur Verfügung, was Du ihnen für die jeweilige Zeile übergibst. Und dies ist bei Dir ein Wertpapierobjekt. Wenn z.B. das Wertpapierobjekt der 1. Zeile die Aktie der SMA Solar Technologie ist, dann können die Spaltenformeln nur die Daten in der Zeile darstellen, die sich aus diesem Objekt und seinen Eigenschaften berechnen lassen. Dies sind z.B. der Name des Wertpapiers, seine ISIN, sein Close-Kurs an einem beliebigen Datum, usw. Das sind aber alles Dinge die einzig und allein ohne zusätzliche Informationen aus dem einen Wertpapierobjekt der jeweiligen Zeile errechnen lassen. Schaust Du dir die Funktionen genauer an, so wirst Du feststellen, dass diese alle nur 1 Eingabe-Objekt benötigen. Nur 1 Objekt heißt, du kannst nur 1-stellige Funktionen anwenden. Die Funktion Rank (2-stellige Funktion) benötigt aber 2 Eingabe-Objekte. Diese sind: 1. Die Zeitreihe des zu bewertenden Kandidaten (z.B. RSL des Objektes der Zeile , z.B. RSL der SMA Solar Technologie Aktie) 2. Die ZeitreihenListe der RSL-Werte aller Aktien, gegen die die Zeitreihe des Kandidaten zu bewerten ist. Du übergibst in der Zeile nur die Aktie. Aus dieser kannst Du über die 1-stellige Funktion (Close[Parameter].RSL[Parameter]) die RSL-Zeitreihe des Kandidaten berechnen. Da die Eingabe zur Tabellenzeile nur dieses eine Objekt der Zeile übergibt, musst du in der Spaltenformel für Rang das 2. Objekt (die Zeitreihenliste) benennen. Und dies machst Du in dem Du den Ordner mit den Wertpapieren angibst gegen die verglichen werden soll. Und für jedes dieser Wertpapiere errechnest Du dann in jeder Tabellenzeile die RSL Zeitreihen. Und genau das ist der Grund warum Du das 2. Objekt (die Zeitreihenliste) übergeben musst. Ich hoffe ich konnte Dir das etwas verständlich machen.
|
|
Gruppen: Kunde
Beiträge: 22
|
Hallo Chuck,
ich glaube, dank Deiner tollen Erklärung habe ich es jetzt verstanden.
Nochmals vielen Dank und Gruß
Norbert
|
|
Gruppen: Kunde
Beiträge: 167
|
Hallo Norbert und alle market maker User, da keine weiteren Fragen mehr aufgekommen sind, möchte jetzt noch einige Bemerkungen über etwas loswerden, das mir im Verlaufe dieses Threads aufgefallen ist, worauf ich aber bisher nicht eingegangen bin, um niemanden zu verwirren. Wegen der besseren Darstellung von Grafik in Text findet Ihr die Erklärungen als PDF in der Anlage. Chuck Dateianhänge: Filter und Auswertung.pdf (354kb) downloaded 92 time(s). Aktien_Xetra.mme (32kb) downloaded 52 time(s).
|
|
Guest |