bquant 0.0.0__py3-none-any.whl

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.
Files changed (49) hide show
  1. bquant/__init__.py +31 -0
  2. bquant/analysis/__init__.py +297 -0
  3. bquant/analysis/candlestick/__init__.py +100 -0
  4. bquant/analysis/chart/__init__.py +98 -0
  5. bquant/analysis/statistical/__init__.py +414 -0
  6. bquant/analysis/statistical/hypothesis_testing.py +657 -0
  7. bquant/analysis/technical/__init__.py +98 -0
  8. bquant/analysis/timeseries/__init__.py +102 -0
  9. bquant/analysis/zones/__init__.py +547 -0
  10. bquant/analysis/zones/sequence_analysis.py +661 -0
  11. bquant/analysis/zones/zone_features.py +520 -0
  12. bquant/cli.py +160 -0
  13. bquant/core/__init__.py +112 -0
  14. bquant/core/cache.py +534 -0
  15. bquant/core/config.py +328 -0
  16. bquant/core/exceptions.py +351 -0
  17. bquant/core/logging_config.py +368 -0
  18. bquant/core/numpy_fix.py +99 -0
  19. bquant/core/performance.py +554 -0
  20. bquant/core/utils.py +327 -0
  21. bquant/data/__init__.py +85 -0
  22. bquant/data/loader.py +436 -0
  23. bquant/data/processor.py +644 -0
  24. bquant/data/samples/__init__.py +442 -0
  25. bquant/data/samples/datasets.py +246 -0
  26. bquant/data/samples/embedded/__init__.py +16 -0
  27. bquant/data/samples/embedded/mt_xauusd_m15.py +9018 -0
  28. bquant/data/samples/embedded/tv_xauusd_1h.py +17018 -0
  29. bquant/data/samples/utils.py +393 -0
  30. bquant/data/schemas.py +285 -0
  31. bquant/data/validator.py +498 -0
  32. bquant/indicators/__init__.py +115 -0
  33. bquant/indicators/base.py +487 -0
  34. bquant/indicators/calculators.py +404 -0
  35. bquant/indicators/library.py +514 -0
  36. bquant/indicators/loaders.py +413 -0
  37. bquant/indicators/macd.py +754 -0
  38. bquant/ml/__init__.py +19 -0
  39. bquant/visualization/__init__.py +316 -0
  40. bquant/visualization/charts.py +616 -0
  41. bquant/visualization/statistical.py +812 -0
  42. bquant/visualization/themes.py +599 -0
  43. bquant/visualization/zones.py +775 -0
  44. bquant-0.0.0.dist-info/METADATA +167 -0
  45. bquant-0.0.0.dist-info/RECORD +49 -0
  46. bquant-0.0.0.dist-info/WHEEL +5 -0
  47. bquant-0.0.0.dist-info/entry_points.txt +2 -0
  48. bquant-0.0.0.dist-info/licenses/LICENSE +21 -0
  49. bquant-0.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,414 @@
1
+ """
2
+ Модуль статистического анализа BQuant
3
+
4
+ Предоставляет функции для статистического анализа финансовых данных:
5
+ - Тестирование гипотез
6
+ - Корреляционный анализ
7
+ - Распределения данных
8
+ - Описательная статистика
9
+ - Временные ряды статистика
10
+ """
11
+
12
+ from typing import Dict, List, Any, Optional, Tuple
13
+ import pandas as pd
14
+ import numpy as np
15
+ from scipy import stats
16
+ from datetime import datetime
17
+
18
+ from ...core.logging_config import get_logger
19
+ from .. import BaseAnalyzer, AnalysisResult
20
+
21
+ logger = get_logger(__name__)
22
+
23
+ # Версия модуля статистического анализа
24
+ __version__ = "0.0.0"
25
+
26
+
27
+ class StatisticalAnalyzer(BaseAnalyzer):
28
+ """
29
+ Базовый класс для статистических анализаторов.
30
+ """
31
+
32
+ def __init__(self, config: Optional[Dict[str, Any]] = None):
33
+ """
34
+ Инициализация статистического анализатора.
35
+
36
+ Args:
37
+ config: Конфигурация анализатора
38
+ """
39
+ super().__init__("StatisticalAnalyzer", config)
40
+
41
+ # Параметры по умолчанию
42
+ self.default_alpha = self.config.get('alpha', 0.05)
43
+ self.min_sample_size = self.config.get('min_sample_size', 30)
44
+
45
+ def descriptive_statistics(self, data: pd.Series, name: str = "data") -> Dict[str, float]:
46
+ """
47
+ Вычисление описательных статистик.
48
+
49
+ Args:
50
+ data: Временной ряд данных
51
+ name: Название данных
52
+
53
+ Returns:
54
+ Словарь с описательными статистиками
55
+ """
56
+ if data.empty:
57
+ return {}
58
+
59
+ stats_dict = {
60
+ 'count': len(data),
61
+ 'mean': data.mean(),
62
+ 'std': data.std(),
63
+ 'min': data.min(),
64
+ 'max': data.max(),
65
+ 'median': data.median(),
66
+ 'q25': data.quantile(0.25),
67
+ 'q75': data.quantile(0.75),
68
+ 'skewness': data.skew(),
69
+ 'kurtosis': data.kurtosis(),
70
+ 'variance': data.var()
71
+ }
72
+
73
+ # Добавляем коэффициент вариации
74
+ if stats_dict['mean'] != 0:
75
+ stats_dict['cv'] = stats_dict['std'] / abs(stats_dict['mean'])
76
+ else:
77
+ stats_dict['cv'] = np.nan
78
+
79
+ self.logger.debug(f"Calculated descriptive statistics for {name}")
80
+ return stats_dict
81
+
82
+ def normality_test(self, data: pd.Series, alpha: float = None) -> Dict[str, Any]:
83
+ """
84
+ Тест на нормальность распределения.
85
+
86
+ Args:
87
+ data: Данные для тестирования
88
+ alpha: Уровень значимости
89
+
90
+ Returns:
91
+ Результаты тестов нормальности
92
+ """
93
+ if alpha is None:
94
+ alpha = self.default_alpha
95
+
96
+ results = {}
97
+
98
+ if len(data) < 3:
99
+ return {'error': 'Insufficient data for normality tests'}
100
+
101
+ # Shapiro-Wilk test (для небольших выборок)
102
+ if len(data) <= 5000:
103
+ try:
104
+ shapiro_stat, shapiro_p = stats.shapiro(data.dropna())
105
+ results['shapiro'] = {
106
+ 'statistic': shapiro_stat,
107
+ 'p_value': shapiro_p,
108
+ 'is_normal': shapiro_p > alpha
109
+ }
110
+ except Exception as e:
111
+ self.logger.warning(f"Shapiro-Wilk test failed: {e}")
112
+
113
+ # Kolmogorov-Smirnov test
114
+ try:
115
+ ks_stat, ks_p = stats.kstest(data.dropna(), 'norm',
116
+ args=(data.mean(), data.std()))
117
+ results['kolmogorov_smirnov'] = {
118
+ 'statistic': ks_stat,
119
+ 'p_value': ks_p,
120
+ 'is_normal': ks_p > alpha
121
+ }
122
+ except Exception as e:
123
+ self.logger.warning(f"Kolmogorov-Smirnov test failed: {e}")
124
+
125
+ # Anderson-Darling test
126
+ try:
127
+ ad_result = stats.anderson(data.dropna(), dist='norm')
128
+ # Сравниваем с критическим значением для alpha=0.05
129
+ critical_idx = 2 # Индекс для 5% уровня значимости
130
+ results['anderson_darling'] = {
131
+ 'statistic': ad_result.statistic,
132
+ 'critical_value': ad_result.critical_values[critical_idx],
133
+ 'is_normal': ad_result.statistic < ad_result.critical_values[critical_idx]
134
+ }
135
+ except Exception as e:
136
+ self.logger.warning(f"Anderson-Darling test failed: {e}")
137
+
138
+ self.logger.debug(f"Performed normality tests on {len(data)} data points")
139
+ return results
140
+
141
+ def correlation_analysis(self, x: pd.Series, y: pd.Series,
142
+ methods: List[str] = None) -> Dict[str, Any]:
143
+ """
144
+ Анализ корреляции между двумя переменными.
145
+
146
+ Args:
147
+ x: Первая переменная
148
+ y: Вторая переменная
149
+ methods: Методы корреляции для использования
150
+
151
+ Returns:
152
+ Результаты корреляционного анализа
153
+ """
154
+ if methods is None:
155
+ methods = ['pearson', 'spearman', 'kendall']
156
+
157
+ results = {}
158
+
159
+ # Убираем NaN значения
160
+ combined = pd.DataFrame({'x': x, 'y': y}).dropna()
161
+ if len(combined) < self.min_sample_size:
162
+ return {'error': f'Insufficient data after cleaning: {len(combined)} < {self.min_sample_size}'}
163
+
164
+ x_clean = combined['x']
165
+ y_clean = combined['y']
166
+
167
+ for method in methods:
168
+ try:
169
+ if method == 'pearson':
170
+ corr, p_value = stats.pearsonr(x_clean, y_clean)
171
+ elif method == 'spearman':
172
+ corr, p_value = stats.spearmanr(x_clean, y_clean)
173
+ elif method == 'kendall':
174
+ corr, p_value = stats.kendalltau(x_clean, y_clean)
175
+ else:
176
+ self.logger.warning(f"Unknown correlation method: {method}")
177
+ continue
178
+
179
+ results[method] = {
180
+ 'correlation': corr,
181
+ 'p_value': p_value,
182
+ 'is_significant': p_value < self.default_alpha,
183
+ 'sample_size': len(x_clean)
184
+ }
185
+ except Exception as e:
186
+ self.logger.error(f"Correlation analysis failed for {method}: {e}")
187
+ results[method] = {'error': str(e)}
188
+
189
+ self.logger.debug(f"Performed correlation analysis using {methods}")
190
+ return results
191
+
192
+ def t_test(self, sample1: pd.Series, sample2: pd.Series = None,
193
+ mu: float = 0, alternative: str = 'two-sided') -> Dict[str, Any]:
194
+ """
195
+ Выполнение t-теста.
196
+
197
+ Args:
198
+ sample1: Первая выборка
199
+ sample2: Вторая выборка (для независимых выборок)
200
+ mu: Гипотетическое среднее (для одновыборочного теста)
201
+ alternative: Альтернативная гипотеза ('two-sided', 'less', 'greater')
202
+
203
+ Returns:
204
+ Результаты t-теста
205
+ """
206
+ sample1_clean = sample1.dropna()
207
+
208
+ if sample2 is None:
209
+ # Одновыборочный t-тест
210
+ if len(sample1_clean) < 2:
211
+ return {'error': 'Insufficient data for one-sample t-test'}
212
+
213
+ t_stat, p_value = stats.ttest_1samp(sample1_clean, mu, alternative=alternative)
214
+ test_type = 'one_sample'
215
+ df = len(sample1_clean) - 1
216
+ else:
217
+ # Двухвыборочный t-тест
218
+ sample2_clean = sample2.dropna()
219
+
220
+ if len(sample1_clean) < 2 or len(sample2_clean) < 2:
221
+ return {'error': 'Insufficient data for two-sample t-test'}
222
+
223
+ t_stat, p_value = stats.ttest_ind(sample1_clean, sample2_clean, alternative=alternative)
224
+ test_type = 'two_sample'
225
+ df = len(sample1_clean) + len(sample2_clean) - 2
226
+
227
+ result = {
228
+ 'test_type': test_type,
229
+ 't_statistic': t_stat,
230
+ 'p_value': p_value,
231
+ 'degrees_of_freedom': df,
232
+ 'alternative': alternative,
233
+ 'is_significant': p_value < self.default_alpha,
234
+ 'alpha': self.default_alpha
235
+ }
236
+
237
+ if sample2 is None:
238
+ result['sample_size'] = len(sample1_clean)
239
+ result['sample_mean'] = sample1_clean.mean()
240
+ result['hypothesized_mean'] = mu
241
+ else:
242
+ result['sample1_size'] = len(sample1_clean)
243
+ result['sample2_size'] = len(sample2_clean)
244
+ result['sample1_mean'] = sample1_clean.mean()
245
+ result['sample2_mean'] = sample2_clean.mean()
246
+
247
+ self.logger.debug(f"Performed {test_type} t-test")
248
+ return result
249
+
250
+ def analyze(self, data: pd.DataFrame, **kwargs) -> AnalysisResult:
251
+ """
252
+ Выполнение комплексного статистического анализа.
253
+
254
+ Args:
255
+ data: DataFrame с данными
256
+ **kwargs: Дополнительные параметры
257
+
258
+ Returns:
259
+ AnalysisResult с результатами статистического анализа
260
+ """
261
+ if not self.validate_data(data):
262
+ raise ValueError("Data validation failed")
263
+
264
+ results = {}
265
+
266
+ # Анализируем числовые колонки
267
+ numeric_columns = data.select_dtypes(include=[np.number]).columns
268
+
269
+ for col in numeric_columns:
270
+ col_results = {}
271
+
272
+ # Описательная статистика
273
+ col_results['descriptive'] = self.descriptive_statistics(data[col], col)
274
+
275
+ # Тест на нормальность
276
+ col_results['normality'] = self.normality_test(data[col])
277
+
278
+ results[col] = col_results
279
+
280
+ # Корреляционный анализ между числовыми колонками
281
+ if len(numeric_columns) > 1:
282
+ correlations = {}
283
+ for i, col1 in enumerate(numeric_columns):
284
+ for col2 in numeric_columns[i+1:]:
285
+ pair_key = f"{col1}_vs_{col2}"
286
+ correlations[pair_key] = self.correlation_analysis(data[col1], data[col2])
287
+
288
+ results['correlations'] = correlations
289
+
290
+ metadata = {
291
+ 'analyzer': 'StatisticalAnalyzer',
292
+ 'columns_analyzed': list(numeric_columns),
293
+ 'total_columns': len(data.columns),
294
+ 'config': self.config
295
+ }
296
+
297
+ return AnalysisResult(
298
+ analysis_type='statistical',
299
+ results=results,
300
+ data_size=len(data),
301
+ metadata=metadata
302
+ )
303
+
304
+
305
+ def get_statistical_analyzers() -> Dict[str, str]:
306
+ """
307
+ Получить список доступных статистических анализаторов.
308
+
309
+ Returns:
310
+ Словарь {анализатор: описание}
311
+ """
312
+ return {
313
+ 'statistical': 'Комплексный статистический анализ',
314
+ 'hypothesis': 'Тестирование статистических гипотез',
315
+ 'correlation': 'Корреляционный анализ',
316
+ 'distribution': 'Анализ распределений'
317
+ }
318
+
319
+
320
+ # Удобные функции для быстрого анализа
321
+ def quick_stats(data: pd.Series) -> Dict[str, float]:
322
+ """
323
+ Быстрые описательные статистики.
324
+
325
+ Args:
326
+ data: Данные для анализа
327
+
328
+ Returns:
329
+ Основные статистики
330
+ """
331
+ analyzer = StatisticalAnalyzer()
332
+ return analyzer.descriptive_statistics(data)
333
+
334
+
335
+ def test_normality(data: pd.Series, alpha: float = 0.05) -> bool:
336
+ """
337
+ Быстрый тест нормальности.
338
+
339
+ Args:
340
+ data: Данные для тестирования
341
+ alpha: Уровень значимости
342
+
343
+ Returns:
344
+ True если данные имеют нормальное распределение
345
+ """
346
+ analyzer = StatisticalAnalyzer({'alpha': alpha})
347
+ results = analyzer.normality_test(data, alpha)
348
+
349
+ # Возвращаем True если хотя бы один тест показал нормальность
350
+ for test_name, test_result in results.items():
351
+ if isinstance(test_result, dict) and 'is_normal' in test_result:
352
+ if test_result['is_normal']:
353
+ return True
354
+
355
+ return False
356
+
357
+
358
+ def correlation_matrix(data: pd.DataFrame, method: str = 'pearson') -> pd.DataFrame:
359
+ """
360
+ Матрица корреляций с p-values.
361
+
362
+ Args:
363
+ data: DataFrame с данными
364
+ method: Метод корреляции
365
+
366
+ Returns:
367
+ DataFrame с корреляциями
368
+ """
369
+ numeric_data = data.select_dtypes(include=[np.number])
370
+
371
+ if method == 'pearson':
372
+ corr_matrix = numeric_data.corr()
373
+ elif method == 'spearman':
374
+ corr_matrix = numeric_data.corr(method='spearman')
375
+ elif method == 'kendall':
376
+ corr_matrix = numeric_data.corr(method='kendall')
377
+ else:
378
+ raise ValueError(f"Unknown correlation method: {method}")
379
+
380
+ return corr_matrix
381
+
382
+
383
+ # Импорт функций hypothesis testing
384
+ try:
385
+ from .hypothesis_testing import (
386
+ HypothesisTestResult,
387
+ HypothesisTestSuite,
388
+ run_all_hypothesis_tests,
389
+ test_single_hypothesis
390
+ )
391
+ _hypothesis_testing_available = True
392
+ except ImportError as e:
393
+ logger.warning(f"Hypothesis testing module not available: {e}")
394
+ _hypothesis_testing_available = False
395
+
396
+
397
+ # Экспорт
398
+ __all__ = [
399
+ 'StatisticalAnalyzer',
400
+ 'get_statistical_analyzers',
401
+ 'quick_stats',
402
+ 'test_normality',
403
+ 'correlation_matrix',
404
+ '__version__'
405
+ ]
406
+
407
+ # Добавляем hypothesis testing если доступен
408
+ if _hypothesis_testing_available:
409
+ __all__.extend([
410
+ 'HypothesisTestResult',
411
+ 'HypothesisTestSuite',
412
+ 'run_all_hypothesis_tests',
413
+ 'test_single_hypothesis'
414
+ ])