Class: Quant::Indicators::Mama

Inherits:
Indicator show all
Defined in:
lib/quant/indicators/mama.rb

Overview

www.mesasoftware.com/papers/MAMA.pdf MESA Adaptive Moving Average (MAMA) adapts to price movement in an entirely new and unique way. The adapation is based on the rate change of phase as measured by the Hilbert Transform Discriminator.

This version of Ehler’s MAMA indicator duplicates the computations present in the homodyne version of the dominant cycle indicator. Use this version of the indicator when you’re using a different dominant cycle indicator other than the homodyne for the rest of your indicators.

Constant Summary collapse

FAMA =
0.500
GAMA =
0.950
DAMA =
0.125
LAMA =
0.100
FAGA =
0.050

Constants inherited from Indicator

Indicator::PRIORITIES

Constants included from Mixins::UniversalFilters

Mixins::UniversalFilters::K

Instance Attribute Summary

Attributes inherited from Indicator

#p0, #p1, #p2, #p3, #series, #source, #t0, #t1, #t2, #t3

Instance Method Summary collapse

Methods inherited from Indicator

#<<, #[], #dc_period, dependent_indicator_classes, depends_on, #dominant_cycle, #dominant_cycle_indicator_class, #dominant_cycle_kind, #each, #half_period, #indicator_name, #initialize, #input, #inspect, #max_period, #micro_period, #min_period, #p, #period_points, #pivot_kind, #points_class, #priority, #size, #t, #ticks, #values

Methods included from Mixins::FisherTransform

#fisher_transform, #inverse_fisher_transform, #relative_fisher_transform

Methods included from Mixins::Stochastic

#stochastic

Methods included from Mixins::SuperSmoother

#three_pole_super_smooth, #two_pole_super_smooth

Methods included from Mixins::HilbertTransform

#hilbert_transform

Methods included from Mixins::ExponentialMovingAverage

#exponential_moving_average

Methods included from Mixins::SimpleMovingAverage

#simple_moving_average

Methods included from Mixins::WeightedMovingAverage

#extended_weighted_moving_average, #weighted_moving_average

Methods included from Mixins::UniversalFilters

#universal_band_pass, #universal_ema, #universal_filter, #universal_one_pole_high_pass, #universal_one_pole_low_pass, #universal_two_pole_high_pass, #universal_two_pole_low_pass

Methods included from Mixins::ButterworthFilters

#three_pole_butterworth, #two_pole_butterworth

Methods included from Mixins::HighPassFilters

#high_pass_filter, #hpf2, #two_pole_high_pass_filter

Methods included from Mixins::Functions

#angle, #bars_to_alpha, #deg2rad, #period_to_alpha, #rad2deg

Constructor Details

This class inherits a constructor from Quant::Indicators::Indicator

Instance Method Details

#computeObject



135
136
137
138
139
140
# File 'lib/quant/indicators/mama.rb', line 135

def compute
  compute_dominant_cycle
  compute_dominant_cycle_phase
  compute_moving_averages
  compute_oscillator
end

#compute_dominant_cycleObject



80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/quant/indicators/mama.rb', line 80

def compute_dominant_cycle
  p0.smooth = wma :input
  p0.detrend = hilbert_transform :smooth, period: p1.period

  # { Compute Inphase and Quadrature components }
  p0.q1 = hilbert_transform :detrend, period: p1.period
  p0.i1 = p3.detrend

  # { Advance the phase of I1 and Q1 by 90 degrees }
  p0.ji = hilbert_transform :i1, period: p1.period
  p0.jq = hilbert_transform :q1, period: p1.period

  # { Smooth the I and Q components before applying the discriminator }
  p0.i2 = (0.2 * (p0.i1 - p0.jq)) + 0.8 * (p1.i2 || (p0.i1 - p0.jq))
  p0.q2 = (0.2 * (p0.q1 + p0.ji)) + 0.8 * (p1.q2 || (p0.q1 + p0.ji))

  homodyne_discriminator
end

#compute_dominant_cycle_phaseObject



107
108
109
110
# File 'lib/quant/indicators/mama.rb', line 107

def compute_dominant_cycle_phase
  p0.delta_phase = p1.phase - p0.phase
  p0.delta_phase = 1.0 if p0.delta_phase < 1.0
end

#compute_moving_averagesObject



118
119
120
121
122
123
124
125
126
127
# File 'lib/quant/indicators/mama.rb', line 118

def compute_moving_averages
  alpha = [fast_limit / p0.delta_phase, slow_limit].max
  p0.mama = (alpha * p0.input) + ((1.0 - alpha) * p1.mama)

  p0.fama = (FAMA * alpha * p0.mama) + ((1.0 - (FAMA * alpha)) * p1.fama)
  p0.gama = (GAMA * alpha * p0.mama) + ((1.0 - (GAMA * alpha)) * p1.gama)
  p0.dama = (DAMA * alpha * p0.mama) + ((1.0 - (DAMA * alpha)) * p1.dama)
  p0.lama = (LAMA * alpha * p0.mama) + ((1.0 - (LAMA * alpha)) * p1.lama)
  p0.faga = (FAGA * alpha * p0.fama) + ((1.0 - (FAGA * alpha)) * p1.faga)
end

#compute_oscillatorObject



129
130
131
132
133
# File 'lib/quant/indicators/mama.rb', line 129

def compute_oscillator
  p0.osc = p0.mama - p0.fama
  p0.crossed = :up if p0.osc >= 0 && p1.osc < 0
  p0.crossed = :down if p0.osc <= 0 && p1.osc > 0
end

#compute_smooth_periodObject

amplitude correction using previous period value



61
62
63
64
# File 'lib/quant/indicators/mama.rb', line 61

def compute_smooth_period
  p0.period = ((0.2 * p0.period) + (0.8 * p1.period)).round
  p0.smooth_period = ((0.33333 * p0.period) + (0.666667 * p1.smooth_period)).round
end

#constrain_period_barsObject

constrain between 6 and 50 bars



50
51
52
# File 'lib/quant/indicators/mama.rb', line 50

def constrain_period_bars
  p0.period = p0.period.clamp(min_period, max_period)
end

#constrain_period_magnitude_changeObject

constrain magnitude of change in phase



55
56
57
58
# File 'lib/quant/indicators/mama.rb', line 55

def constrain_period_magnitude_change
  p0.period = [1.5 * p1.period, p0.period].min
  p0.period = [0.67 * p1.period, p0.period].max
end

#fast_limitObject



99
100
101
# File 'lib/quant/indicators/mama.rb', line 99

def fast_limit
  @fast_limit ||= bars_to_alpha(min_period / 2)
end

#homodyne_discriminatorObject



66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/quant/indicators/mama.rb', line 66

def homodyne_discriminator
  p0.re = (p0.i2 * p1.i2) + (p0.q2 * p1.q2)
  p0.im = (p0.i2 * p1.q2) - (p0.q2 * p1.i2)

  p0.re = (0.2 * p0.re) + (0.8 * p1.re)
  p0.im = (0.2 * p0.im) + (0.8 * p1.im)

  p0.period = 360.0 / rad2deg(Math.atan(p0.im / p0.re)) if (p0.im != 0) && (p0.re != 0)

  constrain_period_magnitude_change
  constrain_period_bars
  compute_smooth_period
end

#slow_limitObject



103
104
105
# File 'lib/quant/indicators/mama.rb', line 103

def slow_limit
  @slow_limit ||= bars_to_alpha(max_period)
end