Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions example_monowave.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
dates = np.array(list(df['Date']))

# find a monowave down starting from the low at the 3rd index
mw_up = MonoWaveUp(lows=lows, highs=highs, dates=dates, idx_start=3, skip=5)
mw_up = MonoWaveUp(lows=lows, highs=highs, dates=dates, idx_start=3, skip=2)
plot_monowave(df, mw_up)

# find a monowave down from the end of the monowave up
mw_down = MonoWaveDown(lows=lows, highs=highs, dates=dates, idx_start=mw_up.idx_end, skip=0)
mw_down = MonoWaveDown(lows=lows, highs=highs, dates=dates, idx_start=mw_up.idx_end, skip=3)
plot_monowave(df, mw_down)
199 changes: 183 additions & 16 deletions models/MonoWave.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,60 @@
from __future__ import annotations

import numpy as np

from models.functions import hi, lo, next_hi, next_lo


class MonoWave:
"""
A class representing a monowave pattern in financial time series data.

Attributes:
- lows_arr (numpy.array): An array containing the lows of the monowave pattern.
- highs_arr (numpy.array): An array containing the highs of the monowave pattern.
- dates_arr (numpy.array): An array containing the dates corresponding to the monowave pattern.
- idx_start (int): The index of the starting point of the monowave pattern.
- skip_n (int, optional): The number of elements to skip during pattern analysis (default is 0).
- idx_end (int): The index of the ending point of the monowave pattern.
- count (int): The count of the monowave (e.g., 1, 2, A, B, etc.).
- degree (int): The degree of the monowave (1 = lowest timeframe level, 2 as soon as a pattern like 12345 is found,
etc.).
- date_start (str): The start date of the monowave pattern.
- date_end (str): The end date of the monowave pattern.
- low (float): The lowest value in the monowave pattern.
- high (float): The highest value in the monowave pattern.
- low_idx (int): The index of the lowest value in the monowave pattern.
- high_idx (int): The index of the highest value in the monowave pattern.

Properties:
- labels (str): A property that returns the count of the monowave as a string.
- length (float): A property that returns the absolute difference between high and low values.
- duration (int): A property that returns the duration (index difference) of the monowave.

Methods:
- from_wavepattern(cls, wave_pattern): A class method to create a MonoWave object from a given wave pattern.

Note:
- This class is designed for analyzing financial time series data and identifying monowave patterns.
"""

def __init__(self,
lows: np.array,
highs: np.array,
dates: np.array,
idx_start: int,
skip: int = 0):

# Constructor initializes the attributes
self.lows_arr = lows
self.highs_arr = highs
self.dates_arr = dates
self.skip_n = skip
self.idx_start = idx_start
self.idx_end = int

self.count = int # the count of the monowave, e.g. 1, 2, A, B, etc
self.degree = 1 # 1 = lowest timeframe level, 2 as soon as a e.g. 12345 is found etc.
self.count = int
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be more like .count = 0 or .count: int as type hint not assigned to class int (but i know that its old code anyway and i m overdue to clean it up myself :-) )

self.degree = 1

self.date_start = str
self.date_end = str
Expand All @@ -28,21 +64,66 @@ def __init__(self,
self.low_idx = int
self.high_idx = int

def __sub__(self, other):
"""
Subtracts the length of another MonoWave object from the length of the current object.

Args:
- other (MonoWave): Another MonoWave object to subtract.

Returns:
float: The difference in length between the two MonoWave objects.
"""
return self.length - other.length

@property
def labels(self) -> str:
"""
Property that returns the count of the monowave as a string.

Returns:
str: The count of the monowave.
"""
return str(self.count)

@property
def length(self) -> float:
"""
Property that returns the absolute difference between the high and low values.

Returns:
float: The length of the monowave.
"""
return abs(self.high - self.low)

@property
def duration(self) -> int:
"""
Property that returns the duration (index difference) of the monowave.

Returns:
int: The duration of the monowave.
"""
return self.idx_end - self.idx_start

@classmethod
def from_wavepattern(cls, wave_pattern):
lows = highs = dates = np.zeros(10) # dummy arrays to init class
"""
Class method tocreate a MonoWave object from a given wave pattern.

Args:
- wave_pattern (WavePattern): The wave pattern object to create the MonoWave from.

Returns:
MonoWave: The created MonoWave object.

Raises:
ValueError: If the wave pattern has a number of waves other than 3 or 5.

Note:
- This method is used to convert a WavePattern object into a MonoWave object for further analysis.
"""
lows = highs = dates = np.zeros(10) # dummy arrays to initialize the class

if len(wave_pattern.waves.keys()) == 5:
low = wave_pattern.waves.get('wave1').low
Expand Down Expand Up @@ -77,15 +158,40 @@ def from_wavepattern(cls, wave_pattern):
return monowave_down

else:
raise ValueError('WavePattern other than 3 or 5 waves implemented, yet.')
raise ValueError('WavePattern other than 3 or 5 waves not implemented, yet.')


class MonoWaveUp(MonoWave):
"""
Describes a upwards movement, which can have [skip_n] smaller downtrends
A subclass of MonoWave representing an upward monowave pattern.

Attributes:
- Inherits all attributes from the parent class MonoWave.

Methods:
- __init__(*args, **kwargs): Initializes the MonoWaveUp object.
- find_end(): Finds the end of the MonoWaveUp pattern.

Properties:
- dates (list): Returns the start and end dates of the MonoWaveUp pattern.
- points: Returns the low and high values of the MonoWaveUp pattern.

Note:
- This class extends the functionality of the MonoWave class specifically for upward monowave patterns.
"""

def __init__(self, *args, **kwargs):
"""
Initializes the MonoWaveUp object.

Args:
- *args: Variable length argument list.
- **kwargs: Arbitrary keyword arguments.

Note:
- This constructor calls the constructor of the parent class (MonoWave) using super().
- It also sets additional attributes specific to MonoWaveUp.
"""
super().__init__(*args, **kwargs)

self.high, self.high_idx = self.find_end()
Expand All @@ -97,10 +203,14 @@ def __init__(self, *args, **kwargs):

def find_end(self):
"""
Finds the end of this MonoWave
Finds the end of this MonoWaveUp pattern.

Returns:
tuple: The high value and its index that marks the end of the MonoWaveUp pattern.

:param idx_start:
:return:
Note:
- This method searches for the end of the upward pattern based on the lows and highs arrays.
- It considers the skip_n attribute to skip a certain number of elements during the search.
"""
high, high_idx = hi(self.lows_arr, self.highs_arr, self.idx_start)
low_at_start = self.lows_arr[self.idx_start]
Expand All @@ -109,30 +219,71 @@ def find_end(self):
return None, None

for _ in range(self.skip_n):

act_high, act_high_idx = next_hi(self.lows_arr, self.highs_arr, high_idx, high)
if act_high is None:
return None, None

if act_high > high:
high = act_high
high_idx = act_high_idx
if np.min(self.lows_arr[self.idx_start:act_high_idx] < low_at_start):
# if np.min(self.lows_arr[self.idx_start:act_high_idx] < low_at_start):
# return None, None
if self.idx_start <= act_high_idx and np.min(self.lows_arr[self.idx_start:act_high_idx]) < low_at_start:
return None, None

return high, high_idx

@property
def dates(self) -> list:
"""
Property that returns the start and end dates of the MonoWaveUp pattern.

Returns:
list: The start and end dates of the MonoWaveUp pattern.
"""
return [self.date_start, self.date_end]

@property
def points(self):
"""
Property that returns the low and high values of the MonoWaveUp pattern.

Returns:
tuple: The low and high values of the MonoWaveUp pattern.
"""
return self.low, self.high


class MonoWaveDown(MonoWave):
"""
A subclass of MonoWave representing a downward monowave pattern.

Attributes:
- Inherits all attributes from the parent class MonoWave.

Methods:
- __init__(*args, **kwargs): Initializes the MonoWaveDown object.
- find_end(): Finds the end of the MonoWaveDown pattern.

Properties:
- dates (list): Returns the start and end dates of the MonoWaveDown pattern.
- points: Returns the high and low values of the MonoWaveDown pattern.

Note:
- This class extends the functionality of the MonoWave class specifically for downward monowave patterns.
"""

def __init__(self, *args, **kwargs):
"""
Initializes the MonoWaveDown object.

Args:
- *args: Variable length argument list.
- **kwargs: Arbitrary keyword arguments.

Note:
- This constructor calls the constructor of the parent class (MonoWave) using super().
- It also sets additional attributes specific to MonoWaveDown.
"""
super().__init__(*args, **kwargs)

self.low, self.low_idx = self.find_end()
Expand All @@ -149,19 +300,35 @@ def __init__(self, *args, **kwargs):

@property
def dates(self) -> list:
"""
Property that returns the start and end dates of the MonoWaveDown pattern.

Returns:
list: The start and end dates of the MonoWaveDown pattern.
"""
return [self.date_start, self.date_end]

@property
def points(self):
"""
Property that returns the high and low values of the MonoWaveDown pattern.

Returns:
tuple: The high and low values of the MonoWaveDown pattern.
"""
return self.high, self.low

def find_end(self):
"""
Finds the end of this MonoWave (downwards)
Finds the end of this MonoWaveDown pattern.

:return:
"""
Returns:
tuple: The low value and its index that marks the end of the MonoWaveDown pattern.

Note:
- This method searches for the end of the downward pattern based on the lows and highs arrays.
- It considers the skip_n attribute to skip a certain number of elements during the search.
"""
low, low_idx = lo(self.lows_arr, self.highs_arr, self.idx_start)
high_at_start = self.highs_arr[self.idx_start]
if low is None:
Expand All @@ -181,7 +348,7 @@ def find_end(self):
# TODO what to do if no more minima can be found?
# if act_low > low:
# return None, None
#if low > np.min(self.lows_arr[low_idx:]):
# if low > np.min(self.lows_arr[low_idx:]):
# return None, None
#else:
# else:
return low, low_idx
Binary file added models/__pycache__/MonoWave.cpython-39.pyc
Binary file not shown.
Binary file added models/__pycache__/WavePattern.cpython-39.pyc
Binary file not shown.
Binary file added models/__pycache__/WaveRules.cpython-39.pyc
Binary file not shown.
Binary file added models/__pycache__/__init__.cpython-39.pyc
Binary file not shown.
Binary file added models/__pycache__/functions.cpython-39.pyc
Binary file not shown.
Binary file added models/__pycache__/helpers.cpython-39.pyc
Binary file not shown.
12 changes: 12 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Copyright (c) 2023 Nightingale Professional Services, LLC
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please remove this commercial licence text

#
# This code is licensed under a commercial License.
# See LICENSE file for full text.
from setuptools import setup, find_packages


setup(
name="Elliott Wave Analyzer",
version="0.1",
packages=find_packages(),
)
Binary file added tests/__pycache__/test_monowave.cpython-39.pyc
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can remove the cached (gitignore pycache) files from git, or are they commited on purpose?

Binary file not shown.
Loading