Class: Quant::Indicators::DominantCycles::DominantCycle

Inherits:
Indicator
  • Object
show all
Defined in:
lib/quant/indicators/dominant_cycles/dominant_cycle.rb

Constant Summary

Constants inherited from Indicator

Indicator::PRIORITIES

Constants included from Mixins::UniversalFilters

Mixins::UniversalFilters::K

Instance Attribute Summary collapse

Attributes inherited from Indicator

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

Instance Method Summary collapse

Methods inherited from Indicator

#<<, #[], #adaptive_half_period, #adaptive_period, dependent_indicator_classes, depends_on, #dominant_cycle, #dominant_cycle_kind, #each, #half_period, #indicator_name, #initialize, #input, #inspect, #max_period, #micro_period, #min_period, #p, #period_points, #pivot_kind, register, #size, #t, #ticks, #values, #warmed_up?

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 Attribute Details

#pointsObject (readonly)

Returns the value of attribute points.



65
66
67
# File 'lib/quant/indicators/dominant_cycles/dominant_cycle.rb', line 65

def points
  @points
end

Instance Method Details

#computeObject



88
89
90
91
92
93
94
95
# File 'lib/quant/indicators/dominant_cycles/dominant_cycle.rb', line 88

def compute
  compute_input_data_points
  compute_quadrature_components
  compute_period
  compute_smooth_period
  compute_mean_period
  compute_phase
end

#compute_input_data_pointsObject



97
98
99
100
# File 'lib/quant/indicators/dominant_cycles/dominant_cycle.rb', line 97

def compute_input_data_points
  p0.smooth = wma :input
  p0.detrend = hilbert_transform :smooth, period: p1.inst_period
end

#compute_mean_periodObject



79
80
81
82
# File 'lib/quant/indicators/dominant_cycles/dominant_cycle.rb', line 79

def compute_mean_period
  ss_period = super_smoother(:smooth_period, previous: :mean_period, period: micro_period)
  p0.mean_period = ss_period.clamp(min_period, max_period)
end

#compute_periodObject

Raises:

  • (NotImplementedError)


118
119
120
# File 'lib/quant/indicators/dominant_cycles/dominant_cycle.rb', line 118

def compute_period
  raise NotImplementedError
end

#compute_phaseObject



122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'lib/quant/indicators/dominant_cycles/dominant_cycle.rb', line 122

def compute_phase
  raise "must compute period before calling!" unless p0.period

  period_points(dominant_cycle_period).map(&:smooth).each_with_index do |smooth, index|
    radians = deg2rad((1 + index) * 360.0 / dominant_cycle_period)
    p0.real_part += smooth * Math.sin(radians)
    p0.imag_part += smooth * Math.cos(radians)
  end

  if p0.imag_part.zero?
    p0.phase = 90.0 * (p0.real_part.positive? ? 1 : 0)
  else
    radians = deg2rad(p0.real_part / p0.imag_part)
    p0.phase = rad2deg(Math.atan(radians))
  end
  p0.phase += 90
  # { Compensate for one bar lag of the Weighted Moving Average }
  p0.phase += (360.0 / p0.inst_period)

  p0.phase += 180.0 if p0.imag_part < 0.0
  p0.phase -= 360.0 if p0.phase > 315.0
  p0.delta_phase = [1.0, p1.phase - p0.phase].max
end

#compute_quadrature_componentsObject

NOTE: The phase lag of q1 and ‘i1 is (360 * 7 / Period - 90)` degrees where Period is the dominant cycle period.



104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/quant/indicators/dominant_cycles/dominant_cycle.rb', line 104

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

  # { Advance the phase of I1 and Q1 by 90 degrees }
  p0.ji = hilbert_transform :i1, period: p1.inst_period
  p0.jq = hilbert_transform :q1, period: p1.inst_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))
end

#compute_smooth_periodObject

amplitude correction using previous period value



74
75
76
77
# File 'lib/quant/indicators/dominant_cycles/dominant_cycle.rb', line 74

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

#constrain_period_barsObject

constrain between min_period and max_period bars



61
62
63
# File 'lib/quant/indicators/dominant_cycles/dominant_cycle.rb', line 61

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

#constrain_period_magnitude_changeObject

constrain magnitude of change in phase



68
69
70
71
# File 'lib/quant/indicators/dominant_cycles/dominant_cycle.rb', line 68

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

#dominant_cycle_indicator_classObject

Dominant Cycle Indicators should not themselves have a dominant cycle indicator



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

def dominant_cycle_indicator_class
  nil
end

#dominant_cycle_periodObject



84
85
86
# File 'lib/quant/indicators/dominant_cycles/dominant_cycle.rb', line 84

def dominant_cycle_period
  [p0.period.to_i, min_period].max
end

#points_classObject



54
55
56
57
58
# File 'lib/quant/indicators/dominant_cycles/dominant_cycle.rb', line 54

def points_class
  Object.const_get "Quant::Indicators::DominantCycles::#{indicator_name}Point"
rescue NameError
  DominantCyclePoint
end

#priorityObject



45
46
47
# File 'lib/quant/indicators/dominant_cycles/dominant_cycle.rb', line 45

def priority
  DOMINANT_CYCLES_PRIORITY
end