# Generate synthetic price data (uptrend with pullbacks) np.random.seed(42) t = np.linspace(0, 100, 500) # Simulated Elliott wave: 5 waves up wave1 = 100 + 10 * np.sin(t * 0.05) + 0.1 * t wave2 = wave1 - 4 * np.sin(t * 0.1) wave3 = wave2 + 15 * np.sin(t * 0.03) wave4 = wave3 - 6 * np.sin(t * 0.08) wave5 = wave4 + 8 * np.sin(t * 0.02)
A, B, C = waves[:3] # Typical rule: B retraces 0.382 to 0.886 of A retrace_ratio = B['magnitude'] / A['magnitude'] if A['magnitude'] != 0 else 0 if 0.382 <= retrace_ratio <= 0.886: # C often equals A in length (1.0 or 1.618) c_ratio = C['magnitude'] / A['magnitude'] if 0.618 <= c_ratio <= 1.618: return True return False
# Rule 2: Wave 3 not shortest if w3['magnitude'] <= w1['magnitude'] or w3['magnitude'] <= w5['magnitude']: if w3['magnitude'] < w1['magnitude'] and w3['magnitude'] < w5['magnitude']: return False
# Mark swing points swings = result['swing_points'] plt.scatter(swings['index'], swings['price'], c='red' if swings['type'].iloc[0]=='high' else 'green', label='Swing points')
def fibonacci_ratios(self, wave: Dict) -> Dict: """Calculate Fibonacci retracements/extensions for a wave.""" mag = wave['magnitude'] return { '0.382': mag * 0.382, '0.5': mag * 0.5, '0.618': mag * 0.618, '1.0': mag, '1.272': mag * 1.272, '1.618': mag * 1.618, }
def detect_elliott_waves(self, prices: np.ndarray) -> Dict: """ Main function: returns detected wave structure and validation. """ swings_df = self.find_swing_points(prices) waves = self.label_swing_waves(swings_df)
# Add Fibonacci ratio estimates for key waves fibs = {} if len(waves) >= 3: fibs['wave3_extension'] = self.fibonacci_ratios(waves[2]) # wave 3 if len(waves) >= 5: fibs['wave5_target'] = self.fibonacci_ratios(waves[4])['1.618']
return { 'pattern': pattern_type, 'waves': waves, 'valid': impulse_ok or corrective_ok, 'fibonacci_levels': fibs, 'swing_points': swings_df } Example usage & visualization ------------------------------- if name == " main ": import matplotlib.pyplot as plt
Drainage Swansea