Extended math RTL

This commit is contained in:
Michael Schimmel
2026-01-13 18:08:52 +01:00
parent 1c6a6fe5a0
commit 629dbc97ca
6 changed files with 457 additions and 90 deletions
+79 -43
View File
@@ -1,9 +1,15 @@
(do
;; ===========================================================================
;; 1. DEFINITIONEN (Wie zuvor besprochen)
;; 1. DEFINITIONEN
;; ===========================================================================
;; --- WMA Factory (O(1)) ---
;; ---------------------------------------------------------------------------
;; Factory: create-wma
;; Berechnet WMA. Wartet, bis das Fenster voll ist.
;; Phase 1: Warten (< len)
;; Phase 2: Init (= len) -> Loop berechnung
;; Phase 3: Slide (> len) -> O(1) berechnung
;; ---------------------------------------------------------------------------
(def create-wma
(fn [len]
(do
@@ -14,17 +20,51 @@
(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)
))
;; PHASE 1: Nicht genug Daten
(if (< cnt len)
NaN
;; Genug Daten vorhanden
(if (= cnt len)
;; PHASE 2: Initialisierung (Das Fenster ist gerade voll geworden)
;; Wir müssen einmalig die Basis-Summen berechnen.
(do
(def init-w 0.0)
(def init-s 0.0)
;; Loop über die Elemente 0 bis len-1
((fn [i]
(if (< i len)
(do
(def val (get src i))
;; Gewichtung: Index 0 ist das neueste -> Gewicht 'len'
(assign init-w (+ init-w (* (- len i) val)))
(assign init-s (+ init-s val))
(recur (+ i 1)))
)) 0)
;; State speichern
(assign prev-w-sum init-w)
(assign prev-s-sum init-s)
(/ init-w weight-div))
;; PHASE 3: Sliding Window (O(1))
;; Wir haben bereits einen gültigen State aus dem vorherigen Schritt.
(do
(def val-new (get src 0)) ; Neuster Wert
(def val-out (get src len)) ; Wert der rausfällt
;; Update Formeln
(def w-sum (+ prev-w-sum (- (* len val-new) prev-s-sum)))
(def s-sum (+ (- prev-s-sum val-out) val-new))
;; State speichern
(assign prev-w-sum w-sum)
(assign prev-s-sum s-sum)
(/ w-sum weight-div))
)
)
))
)))
@@ -34,23 +74,31 @@
(do
(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]]))
(fn [src]
(do
(def v1 (wma-half src))
(def v2 (wma-full src))
;; WICHTIG: Wir dürfen erst weitermachen, wenn BEIDE WMAs gültig sind.
;; Da v2 das längere Fenster (len) braucht, diktiert es den Takt.
(def diff (- (* 2 v1) v2))
(add-item diff-series {:val diff})
(wma-smooth (get diff-series :val))
(if (not (is-NaN diff))
(add-item diff-series {:val diff}))
;; Glättung auf dem Resultat
(wma-smooth (.val diff-series))
))
)))
;; --- Repeat Macro ---
(defmacro repeat [n body]
(defmacro repeat [n body]
`((fn [cnt]
(if (> cnt 0)
(do
@@ -59,45 +107,33 @@
~n))
;; ===========================================================================
;; 2. SIMULATION & TEST
;; 2. SIMULATION
;; ===========================================================================
;; Konfiguration
(def hma-length 14)
(def simulation-steps 50)
(def hma-length 250)
(def simulation-steps 5000)
;; 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
(def hma-calc (create-hma hma-length))
(def prices (new-series [[:close :Float]]))
(def current-price 100.0)
;; 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
;; Random Walk
(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)
;; Berechnung
;; Nutzung von Member Access (.close), da es eine Record-Series ist
(def hma-val (hma-calc (.close prices)))
;; 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...)"))
;; Ausgabe
(if (not (is-NaN hma-val))
(print (count prices) " |" current-price " | " hma-val)
)
)
)
)