ich mache (privat) schon seit 2 Monaten an einem Problem rum, und nun muss ich mir Hilfe holen. Ich glaube das Problem ist nicht ganz trivial und mir fehlen da Lösungsansätze - oder mangelt es einfach an der Logik?
Folgendes:
Ich habe mehrere Formeln der Art als Strings:
Code: Alles auswählen
result = sqrt(sma(delay(x, 15), 22) + sin(x) + wma(sma(y, 15), 62)) + sma(z, 2)
- x, y, z sind Variablen, deren Werte in einer SQLITE Datenbank gespeichert werden. Die ganzen Werte sind als eine Zeitserie zu sehen - fortlaufend kommen da neue dazu und auch entsprechend neue Spalten, wobei Spaltenname = Variablenname. Tabellen-Index ist ein date Objekt. Der Index (value) wird zu einem fortlaufenden Zähler (key) in ein dict gemapt und ist (global) zugänglich. Variablen sind durch den jeweiligen String gegeben, also ohne Vorverarbeitung unbekannt / während Evaluation zur Laufzeit zu ermitteln.
- delay(), sqrt(), sma(), mma(), sin(),... sind Funktionen. Der Großteil der Funktionen kann von math importiert werden, aber diese delay(), sma(), mma() sind custom.
Grundsätzlich ist der Aufbau aller custom-Funktionen so:
func(var, int), mit var = Variablenname, int = positive Ganzzahl (könnte aber auch ein pos. float werden..)
Jede custom-Funktion hat einen Zweck:
- delay(var, 5) -> bezogen auf einen Startpunkt -> gehe 5 rows zurück (also, die 6te Reihe inkl. Startpunkt), Rückgabe: float/int
- sma(var, 5) -> simple moving average, bezogen auf einen Startpunkt -> geom. Durchschnitt der letzen 5 rows inkl dem Startpunkt, Rückgabe: float
- wma(var, 5) -> weighted moving average, bezogen auf einen Startpunkt -> gewichteter Durchschnitt der letzten 5 rows inkl. dem Startpunkt, Rückgabe: float
Startpunkt (start_point) ist als ein Zähler definiert, dann muss nicht die ganze Zeit mit den date-Objects hantiert werden. Sprich, über das dict und dem key kommt das date Objekt zurück, mit dem dann die DB Abfrage erfolgt.
Soweit so gut. Relativ einfaches Umsetzen der custom-Funktionen per
Code: Alles auswählen
def func(var, int):
new_start = start_point - int
get_start_date(new_start)
get_valueDB(var, start_date)
... do magic ...
return value
Die Evaluierung habe ich dem eval() überlassen. Entsprechend globale und lokale Variablen und Funktionen sind mitgegeben. Das funktioniert soweit.
Stufe schwieriger an die obigen Beispiele angelehnt:
Code: Alles auswählen
res = sma(delay(x, 3), 5)
Das habe ich auch hinbekommen. Die Funktion delay() liefert zurück den Wert "value" und einen delay_counter. Die Funktion sma() überprüft, ob ein delay_counter gesetzt ist und verwendet diesen entsprechend als (start_point - delay_counter) und führt dann die Datenabnkabfragen entsprechend durch. Damit werden auch ganz ganz komische Konstruktionen wie delay(delay(delay(var, 1), 2), 3) möglich (-> delay_counter = 6, (1+2+3)).
Noch eine Stufe schwieriger. Da hat alles angefangen:
Code: Alles auswählen
wma(sma(delay(x, 3), 4), 2)
Und da komm ich nicht weiter.
Mein erster Ansatz war alles in einer globalen Variable zu speichern und die Funktionen liefern nur die Werte, die dann in Funktionen wie sin() weiterverwendet werden. Daraus ist eine If-Hölle entstanden, die alles überprüft. Woher kam der Eingabewert (Funktionsrückgabe? oder einfacher String?), was ist schon mal wie oft durchlaufen, welche Werte sind vorhanden, zu welchem moving average gehören die?? usw.. *hände überm kopp zusammenschlag*
Mein zweiter Ansatz war mit func(var, in, *args) zu arbeiten und am Ende ein einigermaßen schlankes dict zu übergeben, das ständig weitergeschleppt wird. Die If-Hölle habe ich damit nur minimal verkleinert.
Und dann kam es durch einen Tippfehler zufällig zur folgenden Situation und mein Kopf ist vollends explodiert:
Code: Alles auswählen
wma(sma(delay(x, 3), 4), [b]6[/b])
Um noch eine logische Schwierigkeit draufzusetzen:
Code: Alles auswählen
delay(wma(sma(delay(x, 3), 4), 6), 2)
Wie geht man hier am besten vor?