Refactoring streams and fixin various bugs
This commit is contained in:
+91
-61
@@ -1,73 +1,103 @@
|
||||
(do
|
||||
;; ---------------------------------------------------------
|
||||
;; 1. Hilfsfunktion: Berechnet den WMA für einen gegebenen
|
||||
;; Zeitpunkt auf einer Series.
|
||||
;; ---------------------------------------------------------
|
||||
(def calc-wma
|
||||
(fn [s len]
|
||||
(do
|
||||
(def cnt (count s))
|
||||
;; Wenn nicht genug Daten da sind, gib 0 oder den letzten Wert zurück
|
||||
(if (< cnt len)
|
||||
0.0
|
||||
(do
|
||||
;; Summe der Gewichte: n * (n + 1) / 2
|
||||
(def weight-sum (/ (* len (+ len 1)) 2))
|
||||
|
||||
;; Rekursive Berechnung der gewichteten Summe
|
||||
;; Wir iterieren von 0 bis len-1 rückwärts
|
||||
(def w-total
|
||||
((fn [i acc]
|
||||
(if (>= i len)
|
||||
acc
|
||||
(do
|
||||
;; Gewicht: (len - i) -> Höchstes Gewicht für aktuelles Element
|
||||
(def w (- len i))
|
||||
;; Wert holen: (get s (count - 1 - i))
|
||||
(def val (get s (- (- cnt 1) i)))
|
||||
;; Tail-Recursion
|
||||
(recur (+ i 1) (+ acc (* w val)))
|
||||
)))
|
||||
0 0.0)) ;; Start bei i=0, acc=0.0
|
||||
|
||||
;; Ergebnis: Gewichtete Summe / Summe der Gewichte
|
||||
(/ w-total weight-sum)
|
||||
)))))
|
||||
;; ===========================================================================
|
||||
;; 1. DEFINITIONEN (Wie zuvor besprochen)
|
||||
;; ===========================================================================
|
||||
|
||||
;; ---------------------------------------------------------
|
||||
;; 2. Die HMA Factory
|
||||
;; ---------------------------------------------------------
|
||||
;; --- WMA Factory (O(1)) ---
|
||||
(def create-wma
|
||||
(fn [len]
|
||||
(do
|
||||
(def prev-w-sum 0.0)
|
||||
(def prev-s-sum 0.0)
|
||||
(def weight-div (/ (* len (+ len 1)) 2))
|
||||
|
||||
(fn [src]
|
||||
(do
|
||||
(def cnt (count src))
|
||||
(if (< cnt (+ len 1))
|
||||
0.0
|
||||
(do
|
||||
(def val-new (get src 0))
|
||||
(def val-out (get src len))
|
||||
(def w-sum (+ prev-w-sum (- (* len val-new) prev-s-sum)))
|
||||
(def s-sum (+ (- prev-s-sum val-out) val-new))
|
||||
(assign prev-w-sum w-sum)
|
||||
(assign prev-s-sum s-sum)
|
||||
(/ w-sum weight-div)
|
||||
))
|
||||
))
|
||||
)))
|
||||
|
||||
;; --- HMA Factory ---
|
||||
(def create-hma
|
||||
(fn [len]
|
||||
(do
|
||||
;; Konstanten vorberechnen
|
||||
(def half-len (round (/ len 2)))
|
||||
(def sqrt-len (round (sqrt len)))
|
||||
(def wma-half (create-wma half-len))
|
||||
(def wma-full (create-wma len))
|
||||
(def wma-smooth (create-wma sqrt-len))
|
||||
(def diff-series (new-series [[:val :Float]]))
|
||||
|
||||
;; !!! WICHTIG !!!
|
||||
;; HMA benötigt eine Glättung der Differenz.
|
||||
;; Da 'calc-wma' eine Series als Input erwartet, müssen wir
|
||||
;; die Zwischenwerte (diff) in einer eigenen Series speichern.
|
||||
;; Diese Series wird in der Closure "gefangen" (captured).
|
||||
(def diff-series (new-series :Float))
|
||||
|
||||
;; Die eigentliche Funktion, die zurückgegeben wird
|
||||
(fn [source-series]
|
||||
(fn [src]
|
||||
(do
|
||||
;; Schritt 1: WMA(n/2) * 2
|
||||
(def wma-half (calc-wma source-series half-len))
|
||||
|
||||
;; Schritt 2: WMA(n)
|
||||
(def wma-full (calc-wma source-series len))
|
||||
|
||||
;; Schritt 3: Differenz berechnen
|
||||
(def diff (- (* 2 wma-half) wma-full))
|
||||
|
||||
;; Schritt 4: Differenz in die interne Series schieben
|
||||
(add-item diff-series diff)
|
||||
|
||||
;; Schritt 5: WMA(sqrt(n)) auf der Differenz-Series berechnen
|
||||
(calc-wma diff-series sqrt-len)
|
||||
(def v1 (wma-half src))
|
||||
(def v2 (wma-full src))
|
||||
(def diff (- (* 2 v1) v2))
|
||||
(add-item diff-series {:val diff})
|
||||
(wma-smooth (get diff-series :val))
|
||||
))
|
||||
)))
|
||||
|
||||
;; --- Repeat Macro ---
|
||||
(defmacro repeat [n body]
|
||||
`((fn [cnt]
|
||||
(if (> cnt 0)
|
||||
(do
|
||||
~body
|
||||
(recur (- cnt 1)))))
|
||||
~n))
|
||||
|
||||
;; ===========================================================================
|
||||
;; 2. SIMULATION & TEST
|
||||
;; ===========================================================================
|
||||
|
||||
;; Konfiguration
|
||||
(def hma-length 14)
|
||||
(def simulation-steps 50)
|
||||
|
||||
;; Initialisierung der Komponenten
|
||||
(def hma-calc (create-hma hma-length)) ; Die HMA-Closure
|
||||
(def prices (new-series [[:close :Float]])) ; Die Preis-Series
|
||||
(def current-price 100.0) ; Startpreis
|
||||
|
||||
;; Header Ausgabe (falls print verfügbar ist)
|
||||
(print "Step | Price | HMA(14)")
|
||||
(print "-----|----------|----------")
|
||||
|
||||
;; Simulations-Schleife
|
||||
(repeat simulation-steps
|
||||
(do
|
||||
;; 1. Preis simulieren (Random Walk)
|
||||
;; (random) gibt 0.0 bis 1.0 zurück.
|
||||
;; (- (random) 0.5) erzeugt eine Änderung zwischen -0.5 und +0.5
|
||||
(assign current-price (+ current-price (- (random) 0.5)))
|
||||
|
||||
;; 2. Preis zur Series hinzufügen
|
||||
(add-item prices {:close current-price})
|
||||
|
||||
;; 3. HMA berechnen
|
||||
(def hma-val 0.0)
|
||||
|
||||
;; 3. HMA berechnen
|
||||
(def price-series (get prices :close))
|
||||
(assign hma-val (hma-calc price-series))
|
||||
|
||||
;; 4. Ausgabe
|
||||
;; Wir geben nur Werte aus, wenn der HMA "eingeschwungen" ist (Wert > 0)
|
||||
(if (> hma-val 0.0)
|
||||
(print (count prices) " |" current-price " | " hma-val)
|
||||
(print (count prices) " |" current-price " | (warming up...)"))
|
||||
)
|
||||
)
|
||||
)
|
||||
Reference in New Issue
Block a user