More analysis WIP

This commit is contained in:
Simon Moisy 2025-05-08 16:23:25 +08:00
parent 1decd0d0ce
commit cbc6a7493d
3 changed files with 70 additions and 7 deletions

View File

@ -15,8 +15,8 @@ daily_data = data[(pd.to_datetime(data['datetime']) >= start_date) &
print(f"Number of data points: {len(daily_data)}")
trend_detector = TrendDetectorSimple(daily_data, verbose=True)
trends = trend_detector.detect_trends()
trend_detector.plot_trends(trends)
trends, analysis_results = trend_detector.detect_trends()
trend_detector.plot_trends(trends, analysis_results)
#trend_detector = TrendDetectorMACD(daily_data, True)
#trends = trend_detector.detect_trends_MACD_signal()

Binary file not shown.

View File

@ -3,6 +3,7 @@ import numpy as np
import logging
from scipy.signal import find_peaks
import matplotlib.dates as mdates
from scipy import stats
class TrendDetectorSimple:
def __init__(self, data, verbose=False):
@ -63,11 +64,50 @@ class TrendDetectorSimple:
for peak in min_peaks:
df.at[peak, 'is_min'] = True
result = df[['datetime', 'close', 'is_min', 'is_max']]
result = df[['datetime', 'close', 'is_min', 'is_max']].copy()
return result
# Perform linear regression on min_peaks and max_peaks
self.logger.info("Performing linear regression on min and max peaks")
min_prices = df['close'].iloc[min_peaks].values
max_prices = df['close'].iloc[max_peaks].values
# Linear regression for min peaks if we have at least 2 points
min_slope, min_intercept, min_r_value, _, _ = stats.linregress(min_peaks, min_prices)
# Linear regression for max peaks if we have at least 2 points
max_slope, max_intercept, max_r_value, _, _ = stats.linregress(max_peaks, max_prices)
def plot_trends(self, trend_data):
# Calculate Simple Moving Averages (SMA) for 7 and 15 periods
self.logger.info("Calculating SMA-7 and SMA-15")
# Calculate SMA values and exclude NaN values
sma_7 = df['close'].rolling(window=7).mean().dropna().values
sma_15 = df['close'].rolling(window=15).mean().dropna().values
# Add SMA values to regression_results
analysis_results = {}
analysis_results['linear_regression'] = {
'min': {
'slope': min_slope,
'intercept': min_intercept,
'r_squared': min_r_value ** 2
},
'max': {
'slope': max_slope,
'intercept': max_intercept,
'r_squared': max_r_value ** 2
}
}
analysis_results['sma'] = {
'7': sma_7,
'15': sma_15
}
self.logger.info(f"Min peaks regression: slope={min_slope:.4f}, intercept={min_intercept:.4f}, r²={min_r_value**2:.4f}")
self.logger.info(f"Max peaks regression: slope={max_slope:.4f}, intercept={max_intercept:.4f}, r²={max_r_value**2:.4f}")
return result, analysis_results
def plot_trends(self, trend_data, analysis_results):
"""
Plot the price data with detected trends using a candlestick chart.
@ -116,12 +156,35 @@ class TrendDetectorSimple:
min_indices = trend_data.index[trend_data['is_min'] == True].tolist()
if min_indices:
min_y = [df['close'].iloc[i] for i in min_indices]
ax.scatter(min_indices, min_y, color='black', s=200, marker='^', label='Local Minima', zorder=100)
ax.scatter(min_indices, min_y, color='darkred', s=200, marker='^', label='Local Minima', zorder=100)
max_indices = trend_data.index[trend_data['is_max'] == True].tolist()
if max_indices:
max_y = [df['close'].iloc[i] for i in max_indices]
ax.scatter(max_indices, max_y, color='black', s=200, marker='v', label='Local Maxima', zorder=100)
ax.scatter(max_indices, max_y, color='darkgreen', s=200, marker='v', label='Local Maxima', zorder=100)
if analysis_results:
x_vals = np.arange(len(df))
# Minima regression line (support)
min_slope = analysis_results['linear_regression']['min']['slope']
min_intercept = analysis_results['linear_regression']['min']['intercept']
min_line = min_slope * x_vals + min_intercept
ax.plot(x_vals, min_line, 'g--', linewidth=2, label='Minima Regression')
# Maxima regression line (resistance)
max_slope = analysis_results['linear_regression']['max']['slope']
max_intercept = analysis_results['linear_regression']['max']['intercept']
max_line = max_slope * x_vals + max_intercept
ax.plot(x_vals, max_line, 'r--', linewidth=2, label='Maxima Regression')
# SMA-7 line
sma_7 = analysis_results['sma']['7']
ax.plot(x_vals, sma_7, 'y-', linewidth=2, label='SMA-7')
# SMA-15 line
# sma_15 = analysis_results['sma']['15']
# valid_idx_15 = ~np.isnan(sma_15)
# ax.plot(x_vals[valid_idx_15], sma_15[valid_idx_15], 'm-', linewidth=2, label='SMA-15')
# Set title and labels
ax.set_title('Price Candlestick Chart with Local Minima and Maxima', fontsize=14)