Skip to content

Commit 628aecd

Browse files
committed
HMA reconceptualized. HMA required 3 WMA, but I have decided, for some strange
reason, that I don't want to use WMA, I want to use SMA, EMA, and VWMA as the basis of Hull. Why? I'm weird. The HMA now provides this functionality. See the sw-zl-hma demo. It slows how to do the traditional HMA, but innovation and edge require flexibility. Changes to be committed: modified: Base/Library/JRRtechnical.py modified: Extras/CodeProofs/jrrTA/demo.sw-zl-hma
1 parent e4d9a3d commit 628aecd

3 files changed

Lines changed: 56 additions & 30 deletions

File tree

Base/Library/.JRRtechnical.py.swp

-1 KB
Binary file not shown.

Base/Library/JRRtechnical.py

Lines changed: 33 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -346,9 +346,11 @@ def WMA(self, idx, period=17):
346346
return self.window
347347

348348
# Calculate a Hull Moving Average (HMA) using the existing WMA
349-
# Problem Child.
350349

351-
def HMA(self, idx, period=21):
350+
# The default is WMA, but by using a column, I can give ANY moving average
351+
# to HMA or even change the WMA parameters externally.
352+
353+
def HMA(self, wmaIDX, wma2IDX, period=21):
352354
"""
353355
Calculate the Hull Moving Average (HMA) for the series at column `idx`.
354356
@@ -374,21 +376,21 @@ def HMA(self, idx, period=21):
374376
"""
375377

376378
# Step 0: Ensure enough historical data
377-
closes = [row[idx] for row in self.window[-period:] if len(row)>idx and row[idx] is not None]
378-
if len(closes) < period:
379+
if len(self.window)<period+1:
379380
self.AddColumn(None)
380381
self.AddColumn(None)
382+
return self.window
383+
384+
if len(self.window[-1])<wmaIDX+1 or len(self.window[-1])<wma2IDX+1:
381385
self.AddColumn(None)
382386
self.AddColumn(None)
383387
return self.window
384388

385-
# Step 1: WMA(period/2)
386-
self.WMA(idx, period // 2)
387-
wma_half = self.window[-1][-1]
389+
# Step 1: WMA(period)
390+
wma_full = self.window[-1][wmaIDX]
388391

389-
# Step 2: WMA(period)
390-
self.WMA(idx, period)
391-
wma_full = self.window[-1][-1]
392+
# Step 2: WMA(period/2)
393+
wma_half = self.window[-1][wma2IDX]
392394

393395
# Check validity
394396
if wma_half is None or wma_full is None:
@@ -402,8 +404,7 @@ def HMA(self, idx, period=21):
402404

403405
# Step 4: WMA(synthetic, sqrt(period))
404406
sqrt_period = max(1, int(period ** 0.5))
405-
synthetic_idx = len(self.window[-1]) - 1
406-
self.WMA(synthetic_idx, sqrt_period) # HMA value, last column
407+
self.AddColumn(sqrt_period)
407408

408409
return self.window
409410

@@ -758,14 +759,18 @@ def MACD(self, idxFAST, idxSLOW, period=9, signal_func=None):
758759

759760
# Ensure enough history
760761
if len(self.window) < 1 or len(self.window[-1]) <= max(idxFAST, idxSLOW):
761-
self.window[-1].extend([None, None, None])
762+
self.AddColumn(None)
763+
self.AddColumn(None)
764+
self.AddColumn(None)
762765
return self.window
763766

764767
fast = self.window[-1][idxFAST]
765768
slow = self.window[-1][idxSLOW]
766769

767770
if fast is None or slow is None:
768-
self.window[-1].extend([None, None, None])
771+
self.AddColumn(None)
772+
self.AddColumn(None)
773+
self.AddColumn(None)
769774
return self.window
770775

771776
# MACD line
@@ -814,20 +819,20 @@ def ATR(self, high_idx=1, low_idx=2, close_idx=4, period=14, malen=14, smooth_fu
814819

815820
# Ensure at least one previous candle exists
816821
if len(self.window) < 2:
817-
self.window[-1].extend([None, None])
822+
self.AddColumn(None)
823+
self.AddColumn(None)
818824
return self.window
819825

820826
row = self.window[-1]
821827
prev_row = self.window[-2]
822828

823829
# Check for missing data
824-
if (len(row) <= max(high_idx, low_idx, close_idx) or
825-
len(prev_row) <= close_idx or
826-
row[high_idx] is None or
827-
row[low_idx] is None or
828-
row[close_idx] is None or
829-
prev_row[close_idx] is None):
830-
self.window[-1].extend([None, None])
830+
if (len(row) <= max(high_idx, low_idx, close_idx)
831+
or len(prev_row) <= close_idx or row[high_idx] is None
832+
or row[low_idx] is None or row[close_idx] is None
833+
or prev_row[close_idx] is None):
834+
self.AddColumn(None)
835+
self.AddColumn(None)
831836
return self.window
832837

833838
# Calculate True Range (TR)
@@ -876,7 +881,9 @@ def Stochastic(self, high_idx, low_idx, close_idx, k_period=14, k_smooth=3, d_sm
876881

877882
n = len(self.window)
878883
if n < k_period:
879-
self.window[-1].extend([None, None, None])
884+
self.AddColumn(None)
885+
self.AddColumn(None)
886+
self.AddColumn(None)
880887
return self.window
881888

882889
# Extract last k_period highs, lows, closes
@@ -885,7 +892,9 @@ def Stochastic(self, high_idx, low_idx, close_idx, k_period=14, k_smooth=3, d_sm
885892
closes = [row[close_idx] for row in self.window[-k_period:] if len(row) > close_idx and row[close_idx] is not None]
886893

887894
if len(highs) < k_period or len(lows) < k_period or len(closes) < k_period:
888-
self.window[-1].extend([None, None,None])
895+
self.AddColumn(None)
896+
self.AddColumn(None)
897+
self.AddColumn(None)
889898
return self.window
890899

891900
high_max = max(highs)

Extras/CodeProofs/jrrTA/demo.sw-zl-hma

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,6 @@ def main():
2121
ta=jrTA.TechnicalAnalysis('kraken','MAIN','ADA/USD','1m',197)
2222
ohlcv=ta.ReadOHLCV('ADAUSD.txt')
2323

24-
SlowLength=50
25-
2624
Opening=1
2725
HighIDX=2
2826
LowIDX=3
@@ -50,11 +48,30 @@ def main():
5048
# intermediates, which can also be re-used if you want to layer
5149
# indicators in more complex ways, for example: a double HMA.
5250

53-
hmaIDX=9
54-
zlIDX=10
55-
swIDX=11
51+
SlowLength=50
52+
period=21
53+
54+
wmaIDX=6 # WMA of Closing, for period
55+
wma2IDX=7 # WMA of Closing, for period/2
56+
synIDX=8 # 2*WMA(p/2) - WMA(p)
57+
sqpIDX=9 # sqrt(p)
58+
59+
hmaIDX=10
60+
zlIDX=11
61+
swIDX=12
62+
63+
# WMA can be ANY desired moving average, and even DIFFERENT moving
64+
# averages. To get a FULL HMA, ALL four of these lines are required.
65+
# Total of 5 columns are required for a complete Hull moving average.
66+
# NEVER forget: Your edge is really YOU, not the indicators.
67+
68+
ta.WMA(Closing,period) # WMA(p) <---*
69+
ta.WMA(Closing,int(period/2)) # WMA(p/2) |
70+
ta.HMA(wmaIDX,wma2IDX,period) # HMA math |
71+
ta.WMA(synIDX,sqpIDX) # Actual HMA based on WMA, this example
72+
73+
# Zero lag and sine weighted values
5674

57-
ta.HMA(Closing,SlowLength) # HMA
5875
ta.ZeroLag(hmaIDX,SlowLength) # ZL-HMA
5976
ta.SineWeight(zlIDX,SlowLength) # Sine weighted: SW-ZL-HMA
6077

0 commit comments

Comments
 (0)