pytrendy 1.2.0.dev5__tar.gz → 1.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pytrendy-1.2.0.dev5 → pytrendy-1.3.0}/PKG-INFO +2 -2
- {pytrendy-1.2.0.dev5 → pytrendy-1.3.0}/README.md +1 -1
- {pytrendy-1.2.0.dev5 → pytrendy-1.3.0}/pyproject.toml +1 -1
- {pytrendy-1.2.0.dev5 → pytrendy-1.3.0}/pytrendy/post_processing/segments_get.py +2 -0
- {pytrendy-1.2.0.dev5 → pytrendy-1.3.0}/pytrendy/post_processing/segments_refine/gradual_expand_contract.py +27 -0
- {pytrendy-1.2.0.dev5 → pytrendy-1.3.0}/LICENSE +0 -0
- {pytrendy-1.2.0.dev5 → pytrendy-1.3.0}/pytrendy/__init__.py +0 -0
- {pytrendy-1.2.0.dev5 → pytrendy-1.3.0}/pytrendy/detect_trends.py +0 -0
- {pytrendy-1.2.0.dev5 → pytrendy-1.3.0}/pytrendy/io/__init__.py +0 -0
- {pytrendy-1.2.0.dev5 → pytrendy-1.3.0}/pytrendy/io/data/classes_signals.csv +0 -0
- {pytrendy-1.2.0.dev5 → pytrendy-1.3.0}/pytrendy/io/data/series_synthetic.csv +0 -0
- {pytrendy-1.2.0.dev5 → pytrendy-1.3.0}/pytrendy/io/data_loader.py +0 -0
- {pytrendy-1.2.0.dev5 → pytrendy-1.3.0}/pytrendy/io/plot_pytrendy.py +0 -0
- {pytrendy-1.2.0.dev5 → pytrendy-1.3.0}/pytrendy/io/results_pytrendy.py +0 -0
- {pytrendy-1.2.0.dev5 → pytrendy-1.3.0}/pytrendy/post_processing/__init__.py +0 -0
- {pytrendy-1.2.0.dev5 → pytrendy-1.3.0}/pytrendy/post_processing/segments_analyse.py +0 -0
- {pytrendy-1.2.0.dev5 → pytrendy-1.3.0}/pytrendy/post_processing/segments_refine/__init__.py +0 -0
- {pytrendy-1.2.0.dev5 → pytrendy-1.3.0}/pytrendy/post_processing/segments_refine/abrupt_shaving.py +0 -0
- {pytrendy-1.2.0.dev5 → pytrendy-1.3.0}/pytrendy/post_processing/segments_refine/artifact_cleanup.py +0 -0
- {pytrendy-1.2.0.dev5 → pytrendy-1.3.0}/pytrendy/post_processing/segments_refine/segment_grouping.py +0 -0
- {pytrendy-1.2.0.dev5 → pytrendy-1.3.0}/pytrendy/post_processing/segments_refine/trend_classify.py +0 -0
- {pytrendy-1.2.0.dev5 → pytrendy-1.3.0}/pytrendy/post_processing/segments_refine/update_neighbours.py +0 -0
- {pytrendy-1.2.0.dev5 → pytrendy-1.3.0}/pytrendy/process_signals.py +0 -0
- {pytrendy-1.2.0.dev5 → pytrendy-1.3.0}/pytrendy/simpledtw.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pytrendy
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.3.0
|
|
4
4
|
Summary: Trend Detection in Python. Applicable for real-world industry use cases in time series.
|
|
5
5
|
License: MIT License
|
|
6
6
|
|
|
@@ -151,6 +151,6 @@ results.filter_segments(direction='Up', sort_by='change_rank')[:3]
|
|
|
151
151
|
|
|
152
152
|
For the full per-segment metrics table, use `results.df`.
|
|
153
153
|
|
|
154
|
-
For more examples on interpreting the results, see [Gradual
|
|
154
|
+
For more examples on interpreting the results, see [Detect Gradual Trends](https://russellsb.github.io/pytrendy/main/examples/fundamentals/gradual/).
|
|
155
155
|
|
|
156
156
|
|
|
@@ -88,5 +88,5 @@ results.filter_segments(direction='Up', sort_by='change_rank')[:3]
|
|
|
88
88
|
|
|
89
89
|
For the full per-segment metrics table, use `results.df`.
|
|
90
90
|
|
|
91
|
-
For more examples on interpreting the results, see [Gradual
|
|
91
|
+
For more examples on interpreting the results, see [Detect Gradual Trends](https://russellsb.github.io/pytrendy/main/examples/fundamentals/gradual/).
|
|
92
92
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "pytrendy"
|
|
3
|
-
version = "1.
|
|
3
|
+
version = "1.3.0"
|
|
4
4
|
description = "Trend Detection in Python. Applicable for real-world industry use cases in time series."
|
|
5
5
|
authors = [
|
|
6
6
|
{ name = "Russell Sammut Bonnici", email = "r.sammutbonnici@gmail.com" },
|
|
@@ -72,6 +72,8 @@ def get_segments(df: pd.DataFrame) -> list[dict]:
|
|
|
72
72
|
, 'end': end.strftime('%Y-%m-%d')
|
|
73
73
|
})
|
|
74
74
|
segment_length=0
|
|
75
|
+
else:
|
|
76
|
+
segment_length = 0 # Reset on fail: prevent length bleed into next segment
|
|
75
77
|
|
|
76
78
|
direction_prev = direction
|
|
77
79
|
segment_length_prev = segment_length
|
|
@@ -71,6 +71,33 @@ def expand_contract_segments(df: pd.DataFrame, value_col: str, segments: list[di
|
|
|
71
71
|
else:
|
|
72
72
|
continue
|
|
73
73
|
|
|
74
|
+
# Avoid orphaning a peak/trough that no adjacent segment covers.
|
|
75
|
+
# The +1 day pushes start past the extremum, assuming it belongs to
|
|
76
|
+
# the neighbour. When no neighbour is near and the extremum holds a
|
|
77
|
+
# significantly different value, the +1 day skips a genuine drop/rise.
|
|
78
|
+
# Skip this when the previous segment is Noise — noise boundaries are
|
|
79
|
+
# deliberately fuzzy and shouldn't anchor the orphan test.
|
|
80
|
+
prev_seg = segments_refined[i - 1] if i > 0 else None
|
|
81
|
+
prev_is_noise = prev_seg is not None and prev_seg.get('direction') == 'Noise'
|
|
82
|
+
if segment['direction'] in ('Up', 'Down') and i > 0:
|
|
83
|
+
prev_end = pd.to_datetime(segments_refined[i - 1]['end'])
|
|
84
|
+
extremum = pd.to_datetime(new_start) - pd.Timedelta(days=1)
|
|
85
|
+
distance = (extremum - prev_end).days
|
|
86
|
+
# Skip orphan check when previous segment is Noise AND the Noise
|
|
87
|
+
# is close (within 3 days) to the extremum — noise boundaries are
|
|
88
|
+
# deliberately fuzzy in that case. When Noise is far away, the
|
|
89
|
+
# extremum is genuinely orphaned and should be captured.
|
|
90
|
+
# For non-Noise neighbours, keep the original distance > 1 gate.
|
|
91
|
+
if prev_is_noise and distance <= 3:
|
|
92
|
+
pass
|
|
93
|
+
elif (not prev_is_noise and distance > 1) or (prev_is_noise and distance > 3):
|
|
94
|
+
if extremum in df.index and new_start in df.index:
|
|
95
|
+
extremum_val = df.loc[extremum, value_col]
|
|
96
|
+
start_val = df.loc[new_start, value_col]
|
|
97
|
+
max_abs = df[value_col].abs().max()
|
|
98
|
+
if max_abs > 0 and abs(extremum_val - start_val) > 0.2 * max_abs:
|
|
99
|
+
new_start -= pd.Timedelta(days=1)
|
|
100
|
+
|
|
74
101
|
# Check for any inversions
|
|
75
102
|
start_inverted = (new_start >= pd.to_datetime(segment['end']))
|
|
76
103
|
end_inverted = (new_end <= pd.to_datetime(segment['start']))
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pytrendy-1.2.0.dev5 → pytrendy-1.3.0}/pytrendy/post_processing/segments_refine/abrupt_shaving.py
RENAMED
|
File without changes
|
{pytrendy-1.2.0.dev5 → pytrendy-1.3.0}/pytrendy/post_processing/segments_refine/artifact_cleanup.py
RENAMED
|
File without changes
|
{pytrendy-1.2.0.dev5 → pytrendy-1.3.0}/pytrendy/post_processing/segments_refine/segment_grouping.py
RENAMED
|
File without changes
|
{pytrendy-1.2.0.dev5 → pytrendy-1.3.0}/pytrendy/post_processing/segments_refine/trend_classify.py
RENAMED
|
File without changes
|
{pytrendy-1.2.0.dev5 → pytrendy-1.3.0}/pytrendy/post_processing/segments_refine/update_neighbours.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|