dquant 1.2.0__tar.gz → 1.2.2__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dquant
3
- Version: 1.2.0
3
+ Version: 1.2.2
4
4
  Summary: DQuant is an open-source Python library for automated volatility forecasting of financial time series. It handles all stages of model construction, from raw prices to the final forecast.
5
5
  Author: Denis Makarov
6
6
  Project-URL: Homepage, https://dquant.space
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "dquant"
7
- version = "1.2.0"
7
+ version = "1.2.2"
8
8
  authors = [
9
9
  { name="Denis Makarov" },
10
10
  ]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dquant
3
- Version: 1.2.0
3
+ Version: 1.2.2
4
4
  Summary: DQuant is an open-source Python library for automated volatility forecasting of financial time series. It handles all stages of model construction, from raw prices to the final forecast.
5
5
  Author: Denis Makarov
6
6
  Project-URL: Homepage, https://dquant.space
@@ -0,0 +1,8 @@
1
+ import numpy as np
2
+
3
+
4
+ def qlike_score(y_true, y_pred):
5
+ sigma2_true = y_true ** 2
6
+ sigma2_pred = np.maximum(y_pred, 1e-10)
7
+ return np.mean(np.log(sigma2_pred) + sigma2_true / sigma2_pred)
8
+
@@ -12,7 +12,7 @@ import numpy as np
12
12
  import xgboost
13
13
  from sklearn.ensemble import GradientBoostingRegressor
14
14
  from sklearn.model_selection import train_test_split
15
- from sklearn.metrics import mean_squared_error, r2_score
15
+ from sklearn.metrics import mean_squared_error, r2_score, mean_absolute_error
16
16
  from .metrics import qlike_score
17
17
  from sklearn.preprocessing import StandardScaler
18
18
  from typing import Tuple
@@ -33,7 +33,6 @@ class FichEn:
33
33
  eps = 1e-8
34
34
  y_pred = np.clip(y_pred, eps, None)
35
35
 
36
- # Градиент (оставляем истинный)
37
36
  grad = 1.0 / y_pred - y_true / (y_pred ** 2)
38
37
 
39
38
  hess_approx = 1.0 / (y_pred ** 2)
@@ -44,16 +43,13 @@ class FichEn:
44
43
  if self.output == False:
45
44
  return
46
45
  if file is None:
47
- file = sys.stdout # по умолчанию вывод в консоль
46
+ file = sys.stdout
48
47
 
49
- # Преобразуем все аргументы в строки и соединяем через sep
50
48
  output = sep.join(str(arg) for arg in args)
51
- output += end # добавляем завершающий символ
49
+ output += end
52
50
 
53
- # Записываем в файловый объект
54
51
  file.write(output)
55
52
 
56
- # Принудительно сбрасываем буфер, если нужно
57
53
  if flush:
58
54
  file.flush()
59
55
 
@@ -71,14 +67,14 @@ class FichEn:
71
67
 
72
68
  for col in required:
73
69
  if col not in data.columns:
74
- raise ValueError(f"Колонка '{col}' не найдена")
70
+ raise ValueError(f"Column '{col}' is not found")
75
71
 
76
72
  raw_windows_X = []
77
73
  raw_windows_y = []
78
74
 
79
- for i in range(window_in + 1, len(data) - window_out + 1):
75
+ for i in range(window_in + 1, len(data) - (window_out + 2)):
80
76
  x_window = data.iloc[i - window_in: i]
81
- y_window = data.iloc[i - 1: i + window_out]
77
+ y_window = data.iloc[i: i + window_out+1]
82
78
 
83
79
  raw_windows_X.append(x_window)
84
80
  raw_windows_y.append(y_window)
@@ -95,13 +91,12 @@ class FichEn:
95
91
 
96
92
  for col in required:
97
93
  if col not in data.columns:
98
- raise ValueError(f"Колонка '{col}' не найдена")
94
+ raise ValueError(f"Column '{col}' is not found")
99
95
 
100
96
  feature_list_final = []
101
97
  single_feature_list_final = []
102
98
  single_feature_dict = {}
103
99
 
104
- # Сначала рассчитываем TR, так как он нужен для ATR
105
100
  if 'TR' in feature_list or any(f.startswith('atr_') for f in feature_list) or any(
106
101
  f.startswith('roll_atr_') for f in feature_list):
107
102
  prev_close = data['close'].shift(1).fillna(data['close'])
@@ -145,7 +140,6 @@ class FichEn:
145
140
  feature_list_final.append(i)
146
141
 
147
142
  elif i == 'abs_returns':
148
- # Используем уже рассчитанные returns
149
143
  if 'returns' in data.columns:
150
144
  data[i] = data['returns'].abs()
151
145
  else:
@@ -265,7 +259,7 @@ class FichEn:
265
259
  f'Not enough data to calculate BB: max BB period is {len(close_values)} and yours {window}')
266
260
  sma = close_values.mean()
267
261
  std = close_values.std()
268
- single_feature_dict[f'bb_{window}'] = (4 * std) / (sma + epsilon) # упрощено
262
+ single_feature_dict[f'bb_{window}'] = (4 * std) / (sma + epsilon)
269
263
  single_feature_list_final.append(f'bb_{window}')
270
264
 
271
265
  elif i[:9] == 'roll_rsi_':
@@ -316,7 +310,7 @@ class FichEn:
316
310
  window = int(window)
317
311
  sma = data['close'].rolling(window=window, min_periods=window).mean()
318
312
  std = data['close'].rolling(window=window, min_periods=window).std()
319
- data[f'roll_bb_{window}'] = (4 * std) / (sma + epsilon) # упрощено
313
+ data[f'roll_bb_{window}'] = (4 * std) / (sma + epsilon)
320
314
  feature_list_final.append(f'roll_bb_{window}')
321
315
 
322
316
  else:
@@ -327,14 +321,6 @@ class FichEn:
327
321
 
328
322
  data = data.fillna(0)
329
323
 
330
- """feature_vector = []
331
- for i in range(1, len(data)):
332
- for feat in existing_features:
333
- feature_vector.append(data[feat].iloc[i])
334
-
335
- for i in single_feature_list_final:
336
- feature_vector.append(single_feature_dict[i])"""
337
-
338
324
  feature_vector = data[existing_features].iloc[1:].to_numpy(dtype=np.float64).ravel()
339
325
  single_vals = np.array([single_feature_dict[f] for f in single_feature_list_final], dtype=np.float64)
340
326
  feature_vector = np.concatenate([feature_vector, single_vals])
@@ -352,20 +338,7 @@ class FichEn:
352
338
 
353
339
  for col in required:
354
340
  if col not in data.columns:
355
- raise ValueError(f"Колонка '{col}' не найдена")
356
-
357
- """tr_values = []
358
-
359
- for i in range(1, len(data)):
360
- if i == 0:
361
- tr = (data['high'].iloc[i] - data['low'].iloc[i]) / data['close'].iloc[i]
362
- else:
363
- hl = data['high'].iloc[i] - data['low'].iloc[i]
364
- hc = abs(data['high'].iloc[i] - data['close'].iloc[i - 1])
365
- lc = abs(data['low'].iloc[i] - data['close'].iloc[i - 1])
366
- tr = max(hl/data['close'].iloc[i], hc/data['close'].iloc[i], lc/data['close'].iloc[i])
367
-
368
- tr_values.append(tr)"""
341
+ raise ValueError(f"Column '{col}' is not found")
369
342
 
370
343
  high = data['high']
371
344
  low = data['low']
@@ -419,35 +392,32 @@ class FichEn:
419
392
  bar = '█' * filled_chars + '░' * (50 - filled_chars)
420
393
  time_per = time.time() - startt
421
394
  if percent < 10:
422
- self.dquantprint(f'\rПодготовка данных: |{bar}| {percent:.2f}% Осталось {time_per*(lx-i):.2f} секунд', end='', flush=True)
395
+ self.dquantprint(f'\rData preparation: |{bar}| {percent:.2f}% {time_per*(lx-i):.2f} seconds left', end='', flush=True)
423
396
  elif percent >= 10 and percent < 100:
424
- self.dquantprint(f'\rПодготовка данных: |{bar}| {percent:.2f}% Осталось {time_per*(lx-i):.2f} секунд', end='', flush=True)
397
+ self.dquantprint(f'\rData preparation: |{bar}| {percent:.2f}% {time_per*(lx-i):.2f} seconds left', end='', flush=True)
425
398
  else:
426
- self.dquantprint(f'\rПодготовка данных: |{bar}| {percent:.2f}% Осталось {time_per*(lx-i):.2f} секунд', end='', flush=True)
399
+ self.dquantprint(f'\rData preparation: |{bar}| {percent:.2f}% {time_per*(lx-i):.2f} seconds left', end='', flush=True)
427
400
 
428
401
  self.dquantprint()
429
402
  x = np.array(XX)
430
403
  y = np.array(YY)
431
404
 
432
- # Параметры фиксированного окна h
433
- train_window_size = input_bars # сколько последних окон использовать для обучения
434
- # Минимальный индекс, с которого можно начинать валидацию (должен быть >= train_window_size)
405
+ train_window_size = input_bars
435
406
  start_val_idx = train_window_size
436
407
 
437
408
  total_iterations = len(x) - start_val_idx
438
409
  if total_iterations <= 0:
439
- raise ValueError(f"Слишком мало данных: всего окон {len(x)}, а train_window_size={train_window_size}")
410
+ raise ValueError(f"Too little data: total windows {len(x)}, and train_window_size={train_window_size}")
440
411
 
441
- self.dquantprint(f"Всего окон: {len(x)}")
442
- self.dquantprint(f"Размер окна обучения: {train_window_size}")
443
- self.dquantprint(f"Шагов валидации: {total_iterations}")
412
+ self.dquantprint(f"Total windows: {len(x)}")
413
+ self.dquantprint(f"Training window size: {train_window_size}")
414
+ self.dquantprint(f"Validation steps: {total_iterations}")
444
415
 
445
416
  all_train_errors = []
446
417
  all_val_errors = []
447
418
  all_train_r2 = []
448
419
  all_val_r2 = []
449
420
 
450
- # horizon может быть числом или списком, приведём к списку индексов
451
421
  if isinstance(horizon, int):
452
422
  horizon_list = list(range(horizon))
453
423
  else:
@@ -457,16 +427,15 @@ class FichEn:
457
427
  start_it = time.time()
458
428
  iter_num = val_idx - start_val_idx + 1
459
429
 
460
- # === Обучающая выборка: последние train_window_size окон перед val_idx ===
461
430
  train_indices = list(range(val_idx - train_window_size, val_idx))
462
431
  X_train = x[train_indices]
463
432
  y_train = y[train_indices]
464
433
 
465
- # === Валидационное окно (одно) ===
466
- X_val = x[val_idx:val_idx + 1] # форма (1, n_features)
467
- y_val_true = y[val_idx] # форма (horizon,)
434
+ # === Validation window ===
435
+ X_val = x[val_idx:val_idx + 1] # form (1, n_features)
436
+ y_val_true = y[val_idx] # form (horizon,)
468
437
 
469
- # === Нормализация (обучаем scaler ТОЛЬКО на тренировочных данных) ===
438
+ # === Normalization ===
470
439
  scaler_X = StandardScaler()
471
440
  scaler_y_local = StandardScaler()
472
441
 
@@ -475,46 +444,40 @@ class FichEn:
475
444
 
476
445
  X_val_scaled = scaler_X.transform(X_val)
477
446
 
478
- # === Обучение моделей для каждого горизонта ===
447
+ # === training for each horizon ===
479
448
  model_ex = self.base_model.__class__(**self.base_model.get_params())
480
449
  model_ex.set_params(n_estimators=trees)
481
450
  models_temp = []
482
451
  for h_idx in horizon_list:
483
452
  if h_idx >= y_train_scaled.shape[1]:
484
- continue # на всякий случай, если горизонт больше доступного
453
+ continue
485
454
 
486
455
  y_h = y_train_scaled[:, h_idx]
487
456
 
488
- # Создаём модель с параметрами, как у self.base_model
489
457
  model = model_ex
490
- # При желании можно задать n_estimators из self.trees_count, но для чистоты
491
- # walk-forward оставим обучение до конца (или фиксированное число деревьев).
492
- # Если нужен early_stopping по числу деревьев - можно добавить.
493
458
  model.fit(X_train_scaled, y_h)
494
459
  models_temp.append(model)
495
460
 
496
- # === Предсказания ===
497
- # На тренировочных данных
461
+ # === Foracesting train ===
498
462
  train_preds_list = []
499
463
  for model in models_temp:
500
464
  train_preds_list.append(model.predict(X_train_scaled))
501
465
  train_preds = np.column_stack(train_preds_list) # (train_windows, horizon)
502
466
 
503
- # На валидационном окне
467
+ # Forecasting on validation data
504
468
  val_preds_list = []
505
469
  for model in models_temp:
506
470
  val_preds_list.append(model.predict(X_val_scaled))
507
471
  val_preds = np.array(val_preds_list).flatten() # (horizon,)
508
472
 
509
- # === Обратное масштабирование для расчёта метрик в исходных единицах ===
473
+
510
474
  y_train_inv = scaler_y_local.inverse_transform(y_train_scaled)
511
475
  train_preds_inv = scaler_y_local.inverse_transform(train_preds)
512
476
 
513
- y_val_true_inv = y_val_true # уже в исходных единицах
477
+ y_val_true_inv = y_val_true
514
478
  val_preds_inv = scaler_y_local.inverse_transform(val_preds.reshape(1, -1)).flatten()
515
479
 
516
- # === Метрики ===
517
- # Усредняем MSE по всем горизонтам
480
+ # === Metrics ===
518
481
  train_error = mean_squared_error(y_train_inv.flatten(), train_preds_inv.flatten())
519
482
  val_error = mean_squared_error(y_val_true_inv, val_preds_inv)
520
483
  train_r2 = r2_score(y_train_inv.flatten(), train_preds_inv.flatten())
@@ -525,7 +488,7 @@ class FichEn:
525
488
  all_train_r2.append(train_r2)
526
489
  all_val_r2.append(val_r2)
527
490
 
528
- # === Прогресс-бар ===
491
+ # === Progress bar ===
529
492
  percent = (iter_num / total_iterations) * 100
530
493
  filled = int(percent / 2)
531
494
  bar = '█' * filled + '░' * (50 - filled)
@@ -533,11 +496,11 @@ class FichEn:
533
496
  f'\rWalk-Forward: |{bar}| {percent:.1f}% - Iteration {iter_num}/{total_iterations} - Val MSE: {val_error:.6f} - need time: {(time.time()-start_it)*(total_iterations-iter_num)} seconds',
534
497
  end='', flush=True)
535
498
 
536
- #self.dquantprint("\nWalk-Forward валидация завершена!")
537
- self.dquantprint(f"Средняя ошибка валидации (MSE): {np.mean(all_val_errors):.6f} +/- {np.std(all_val_errors):.6f}")
538
- self.dquantprint(f"Средний R² валидации: {np.mean(all_val_r2):.4f} +/- {np.std(all_val_r2):.4f}")
539
- self.dquantprint(f"Максимальная ошибка валидации: {np.max(all_val_errors):.6f}")
540
- self.dquantprint(f"Минимальная ошибка валидации: {np.min(all_val_errors):.6f}")
499
+
500
+ self.dquantprint(f"Mean validation error (MSE): {np.mean(all_val_errors):.6f} +/- {np.std(all_val_errors):.6f}")
501
+ self.dquantprint(f"Mean validation R²: {np.mean(all_val_r2):.4f} +/- {np.std(all_val_r2):.4f}")
502
+ self.dquantprint(f"Maximum validation error: {np.max(all_val_errors):.6f}")
503
+ self.dquantprint(f"Minimum validation error: {np.min(all_val_errors):.6f}")
541
504
  if show_results:
542
505
  self.V.forward_validation_errors(all_val_errors, all_val_r2)
543
506
  return
@@ -571,7 +534,6 @@ class FichEn:
571
534
  else:
572
535
  window_targets = target_func(y[i])
573
536
 
574
- #self.dquantprint(len(window_features))
575
537
  XX.append(window_features)
576
538
  YY.append(window_targets)
577
539
 
@@ -580,11 +542,11 @@ class FichEn:
580
542
  bar = '█' * filled_chars + '░' * (50 - filled_chars)
581
543
  time_per = time.time() - startt
582
544
  if percent < 10:
583
- self.dquantprint(f'\rПодготовка данных: |{bar}| {percent:.2f}% Осталось {time_per*(lx-i):.2f} секунд', end='', flush=True)
545
+ self.dquantprint(f'\rData preparation: |{bar}| {percent:.2f}% {time_per*(lx-i):.2f} seconds left', end='', flush=True)
584
546
  elif percent >= 10 and percent < 100:
585
- self.dquantprint(f'\rПодготовка данных: |{bar}| {percent:.2f}% Осталось {time_per*(lx-i):.2f} секунд', end='', flush=True)
547
+ self.dquantprint(f'\rData preparation: |{bar}| {percent:.2f}% {time_per*(lx-i):.2f} seconds left', end='', flush=True)
586
548
  else:
587
- self.dquantprint(f'\rПодготовка данных: |{bar}| {percent:.2f}% Осталось {time_per*(lx-i):.2f} секунд', end='', flush=True)
549
+ self.dquantprint(f'\rData preparation: |{bar}| {percent:.2f}% {time_per*(lx-i):.2f} seconds left', end='', flush=True)
588
550
 
589
551
  self.dquantprint()
590
552
  self.dquantprint("time spended: ", time.time() - start_)
@@ -601,12 +563,15 @@ class FichEn:
601
563
 
602
564
  self.train_errors = []
603
565
  self.val_errors = []
566
+ self.train_mae = []
567
+ self.val_mae = []
604
568
  self.train_qlike = []
605
569
  self.val_qlike = []
606
570
  self.train_r2 = []
607
571
  self.val_r2 = []
608
572
 
609
573
  self.best_val_error = float('inf')
574
+ self.best_val_mae = float('inf')
610
575
  self.best_val_qlike = float('inf')
611
576
  self.best_r2 = -float('inf')
612
577
  self.patience_counter = 0
@@ -619,6 +584,8 @@ class FichEn:
619
584
  self.dquantprint(f'{i} trees')
620
585
  t_error = 0
621
586
  v_error = 0
587
+ t_mae = 0
588
+ v_mae = 0
622
589
  t_qlike = 0
623
590
  v_qlike = 0
624
591
  t_r2 = 0
@@ -627,11 +594,10 @@ class FichEn:
627
594
  horizon_list = list(range(horizon))
628
595
  else:
629
596
  horizon_list = horizon
630
-
631
- if len(Y_scaled.shape) == 2 and Y_scaled.shape[1] > 1:
597
+ if len(Y_scaled.shape) == 2 and Y_scaled.shape[1] > 0:
632
598
  for h_idx, h in enumerate(horizon_list):
633
599
  if h_idx >= Y_scaled.shape[1]:
634
- self.dquantprint(f"Предупреждение: горизонт {h} выходит за пределы y, пропускаем")
600
+ self.dquantprint(f"Warning: horizon {h} extends beyond y, skipping")
635
601
  continue
636
602
 
637
603
  y_h = Y_scaled.iloc[:, h_idx] if hasattr(Y_scaled, 'iloc') else Y_scaled[:, h_idx]
@@ -657,6 +623,8 @@ class FichEn:
657
623
  if i != 1:
658
624
  t_error += mean_squared_error(y_h_clean, self.models[h_idx].predict(X_h))
659
625
  v_error += mean_squared_error(y_h_v_clean, self.models[h_idx].predict(X_h_v))
626
+ t_mae += mean_absolute_error(y_h_clean, self.models[h_idx].predict(X_h))
627
+ v_mae += mean_absolute_error(y_h_v_clean, self.models[h_idx].predict(X_h_v))
660
628
  t_qlike += qlike_score(y_h_clean, self.models[h_idx].predict(X_h))
661
629
  v_qlike += qlike_score(y_h_v_clean, self.models[h_idx].predict(X_h_v))
662
630
  t_r2 += r2_score(y_h_clean, self.models[h_idx].predict(X_h))
@@ -664,6 +632,8 @@ class FichEn:
664
632
  else:
665
633
  t_error += mean_squared_error(y_h_clean, model.predict(X_h))
666
634
  v_error += mean_squared_error(y_h_v_clean, model.predict(X_h_v))
635
+ t_mae += mean_absolute_error(y_h_clean, model.predict(X_h))
636
+ v_mae += mean_absolute_error(y_h_v_clean, model.predict(X_h_v))
667
637
  t_qlike += qlike_score(y_h_clean, model.predict(X_h))
668
638
  v_qlike += qlike_score(y_h_v_clean, model.predict(X_h_v))
669
639
  t_r2 += r2_score(y_h_clean, model.predict(X_h))
@@ -672,6 +642,8 @@ class FichEn:
672
642
 
673
643
  var_test_error = float(t_error)/horizon
674
644
  var_val_error = float(v_error)/horizon
645
+ var_test_mae = float(t_mae) / horizon
646
+ var_val_mae = float(v_mae) / horizon
675
647
  var_test_qlike = float(t_qlike) / horizon
676
648
  var_val_qlike = float(v_qlike) / horizon
677
649
  var_test_r2 = float(t_r2)/horizon
@@ -679,10 +651,20 @@ class FichEn:
679
651
 
680
652
  if self.early_stopping:
681
653
  if len(self.val_errors) > 0:
682
- current_min = min(self.val_errors)
683
- best_so_far = min(self.best_val_error, current_min)
684
-
685
- no_improvement_count = len(self.val_errors) - self.val_errors.index(best_so_far) - 1
654
+ if self.loss == "MAE":
655
+ current_min = min(self.val_mae)
656
+ best_so_far = min(self.best_val_mae, current_min)
657
+ no_improvement_count = len(self.val_mae) - self.val_mae.index(best_so_far) - 1
658
+ elif self.loss == "MSE":
659
+ current_min = min(self.val_errors)
660
+ best_so_far = min(self.best_val_error, current_min)
661
+ no_improvement_count = len(self.val_errors) - self.val_errors.index(best_so_far) - 1
662
+ elif self.loss == "QLIKE":
663
+ current_min = min(self.val_qlike)
664
+ best_so_far = min(self.best_val_qlike, current_min)
665
+ no_improvement_count = len(self.val_qlike) - self.val_qlike.index(best_so_far) - 1
666
+ else:
667
+ raise "Unavailable loss function"
686
668
 
687
669
  if no_improvement_count >= self.patience:
688
670
  self.dquantprint(f'Early stopping at {i} trees (no improvement for {self.patience} steps)')
@@ -694,6 +676,8 @@ class FichEn:
694
676
 
695
677
  self.train_errors.append(var_test_error)
696
678
  self.val_errors.append(var_val_error)
679
+ self.train_mae.append(var_test_mae)
680
+ self.val_mae.append(var_val_mae)
697
681
  self.train_qlike.append(var_test_qlike)
698
682
  self.val_qlike.append(var_val_qlike)
699
683
  self.train_r2.append(var_test_r2)
@@ -702,12 +686,14 @@ class FichEn:
702
686
  self.dquantprint('Validation QLIKE: ', var_val_qlike)
703
687
  self.dquantprint('Train MSE: ', var_test_error)
704
688
  self.dquantprint('Validation MSE: ', var_val_error)
689
+ self.dquantprint('Train MAE: ', var_test_mae)
690
+ self.dquantprint('Validation MAE: ', var_val_mae)
705
691
  self.dquantprint('Train r2: ', var_test_r2)
706
692
  self.dquantprint('Validation r2: ', var_val_r2)
707
- self.dquantprint(f"Затрачено времени: {time.time() - start} сек")
693
+ self.dquantprint(f"{time.time() - start} seconds spent")
708
694
 
709
695
  except KeyboardInterrupt:
710
- self.dquantprint("\nОбучение прервано по Ctrl+C!")
696
+ self.dquantprint("\nTraining interrupted by Ctrl+C!")
711
697
 
712
698
  if show_results:
713
699
  self.V.show_errors(self.train_errors, self.val_errors, self.train_r2, self.val_r2)
@@ -724,7 +710,7 @@ class FichEn:
724
710
  X = feature_func(latest_data)
725
711
 
726
712
  if not self.is_fitted and not self.onnx_load:
727
- raise ValueError("Модель еще не обучена!")
713
+ raise ValueError("The model is not trained yet!")
728
714
 
729
715
  if self.onnx_load:
730
716
  predictions = []
@@ -743,20 +729,15 @@ class FichEn:
743
729
 
744
730
  pred_array = np.array(predictions)
745
731
 
746
- # ИСПРАВЛЕНИЕ ЗДЕСЬ:
747
732
  if pred_array.ndim == 1:
748
- # Для одного сэмпла с 30 таргетами: (30,) -> (1, 30)
749
733
  pred_array = pred_array.reshape(1, -1)
750
734
  elif pred_array.ndim == 2:
751
735
  if pred_array.shape[0] == 1 and pred_array.shape[1] == 30:
752
- # Уже правильно (1, 30) - ничего не делаем
753
736
  pass
754
737
  elif pred_array.shape[0] == 30 and pred_array.shape[1] == 1:
755
- # Неправильная форма (30, 1) -> (1, 30)
756
738
  pred_array = pred_array.T
757
739
  elif pred_array.shape[0] > 1 and pred_array.shape[1] == 30:
758
- # Несколько моделей: (n_models, 30) - берем первую или усредняем
759
- pred_array = pred_array[0:1, :] # Берем первую модель
740
+ pred_array = pred_array[0:1, :]
760
741
  predictions = self.scaler_y.inverse_transform(pred_array).flatten()
761
742
 
762
743
  if show:
@@ -792,20 +773,15 @@ class FichEn:
792
773
 
793
774
  pred_array = np.array(predictions)
794
775
 
795
- # ИСПРАВЛЕНИЕ ЗДЕСЬ:
796
776
  if pred_array.ndim == 1:
797
- # Для одного сэмпла с 30 таргетами: (30,) -> (1, 30)
798
777
  pred_array = pred_array.reshape(1, -1)
799
778
  elif pred_array.ndim == 2:
800
779
  if pred_array.shape[0] == 1 and pred_array.shape[1] == 30:
801
- # Уже правильно (1, 30) - ничего не делаем
802
780
  pass
803
781
  elif pred_array.shape[0] == 30 and pred_array.shape[1] == 1:
804
- # Неправильная форма (30, 1) -> (1, 30)
805
782
  pred_array = pred_array.T
806
783
  elif pred_array.shape[0] > 1 and pred_array.shape[1] == 30:
807
- # Несколько моделей: (n_models, 30) - берем первую или усредняем
808
- pred_array = pred_array[0:1, :] # Берем первую модель
784
+ pred_array = pred_array[0:1, :]
809
785
  predictions = self.scaler_y.inverse_transform(pred_array).flatten()
810
786
 
811
787
  if show:
@@ -835,7 +811,6 @@ class FichEn:
835
811
  scaler_data = {
836
812
  "mean": self.scaler.mean_.tolist() if self.scaler.mean_ is not None else [],
837
813
  "std": self.scaler.scale_.tolist() if self.scaler.scale_ is not None else [],
838
- # scale_ = стандартное отклонение
839
814
  "var": self.scaler.var_.tolist() if self.scaler.var_ is not None else []
840
815
  }
841
816
  mean_str = ','.join(str(x) for x in scaler_data['mean'])
@@ -844,7 +819,6 @@ class FichEn:
844
819
  scaler_data_y = {
845
820
  "mean": self.scaler_y.mean_.tolist() if self.scaler_y.mean_ is not None else [],
846
821
  "std": self.scaler_y.scale_.tolist() if self.scaler_y.scale_ is not None else [],
847
- # scale_ = стандартное отклонение
848
822
  "var": self.scaler_y.var_.tolist() if self.scaler_y.var_ is not None else []
849
823
  }
850
824
  mean_str_y = ','.join(str(x) for x in scaler_data_y['mean'])
@@ -852,14 +826,12 @@ class FichEn:
852
826
 
853
827
 
854
828
  os.makedirs(name, exist_ok=True)
855
- self.dquantprint(f"Директория '{name}' создана или уже существует")
829
+ self.dquantprint(f"Directory '{name}' has been created or already exists")
856
830
 
857
- # 2. Создаём папку для ONNX файлов
858
831
  onnx_dir = os.path.join(name, f"{name}_onnx")
859
832
  os.makedirs(onnx_dir, exist_ok=True)
860
833
 
861
- # 3. Создаём основной файл исходного кода MQL5 (.mq5)
862
- mq5_file_path = os.path.join(name, f"{name}.mq5") # Изменено с .mql5 на .mq5
834
+ mq5_file_path = os.path.join(name, f"{name}.mq5")
863
835
  with open(mq5_file_path, "w", encoding="utf-8") as f:
864
836
  f.write("//+------------------------------------------------------------------+\n")
865
837
  f.write(f"//| {name}.mq5 |\n")
@@ -914,10 +886,9 @@ class FichEn:
914
886
  f.write(f' model_handle{i} = OnnxCreateFromBuffer(ExtModelData{i}, ONNX_USE_CPU_ONLY);\n')
915
887
  f.write(f' if (model_handle{i} == INVALID_HANDLE)\n')
916
888
  f.write(' {\n')
917
- f.write(f' Print("Ошибка загрузки ONNX-модели {i}: ", GetLastError());\n')
889
+ f.write(f' Print("Error loading ONNX model {i}: ", GetLastError());\n')
918
890
  f.write(' return INIT_FAILED;\n')
919
891
  f.write(' }\n')
920
- # f.write(f' Print("ONNX-модель {i} успешно загружена");\n\n')
921
892
 
922
893
  f.write(' return(INIT_SUCCEEDED);\n')
923
894
  f.write('}\n\n')
@@ -1419,7 +1390,6 @@ class FichEn:
1419
1390
  f.write(' return true;\n')
1420
1391
  f.write('}\n\n')
1421
1392
 
1422
- # GetForecast function
1423
1393
  f.write('//+------------------------------------------------------------------+\n')
1424
1394
  f.write('//| Get forecast from ONNX model |\n')
1425
1395
  f.write('//+------------------------------------------------------------------+\n')
@@ -1455,9 +1425,8 @@ class FichEn:
1455
1425
  f.write(' }\n')
1456
1426
  f.write('}\n\n')
1457
1427
 
1458
- self.dquantprint(f"Файл {mq5_file_path} успешно создан")
1428
+ self.dquantprint(f"File {mq5_file_path} created successfully")
1459
1429
 
1460
- # 4. Создаём файл проекта MQL5 (.mqproj)
1461
1430
  proj_file_path = os.path.join(name, f"{name}.mqproj")
1462
1431
  with open(proj_file_path, "w", encoding="utf-8-sig") as f:
1463
1432
  f.write('{\n')
@@ -1490,12 +1459,13 @@ class FichEn:
1490
1459
  f.write(' ]\n')
1491
1460
  f.write('}\n')
1492
1461
 
1493
- self.dquantprint(f"Файл {proj_file_path} успешно создан")
1462
+ self.dquantprint(f"File {proj_file_path} created successfully")
1494
1463
 
1495
1464
 
1496
1465
 
1497
1466
  class VolClustGB(FichEn):
1498
- def __init__(self, sett, early_stopping=True, output=True):
1467
+ def __init__(self, sett, early_stopping=True, output=True, loss="MAE"):
1468
+ self.loss = loss
1499
1469
  self.output = output
1500
1470
  self.models = []
1501
1471
  self.scaler = StandardScaler()
@@ -1518,7 +1488,8 @@ class VolClustGB(FichEn):
1518
1488
  }
1519
1489
  self.meta = {
1520
1490
  "model_type": "gb",
1521
- "model_settings": self.default_sett
1491
+ "model_settings": self.default_sett,
1492
+ "model_loss": loss
1522
1493
  }
1523
1494
  if sett == {}:
1524
1495
  self.base_model = GradientBoostingRegressor(**self.default_sett)
@@ -1564,36 +1535,35 @@ class VolClustGB(FichEn):
1564
1535
  self.save_mql5(name)
1565
1536
  onnx_dir = os.path.join(name, f"{name}_onnx")
1566
1537
  os.makedirs(onnx_dir, exist_ok=True)
1567
- self.dquantprint(f"Директория для ONNX файлов создана: {onnx_dir}")
1538
+ self.dquantprint(f"Directory for ONNX files created: {onnx_dir}")
1568
1539
 
1569
- # 4. Сохраняем модели и scaler в поддиректорию
1570
1540
  initial_type = [('float_input', FloatTensorType([None, self.X_shape]))]
1571
1541
 
1572
1542
  if hasattr(self, 'scaler') and self.scaler is not None:
1573
1543
  scaler_path = os.path.join(onnx_dir, f"{name}_scaler.pkl")
1574
1544
  joblib.dump(self.scaler, scaler_path)
1575
- self.dquantprint(f"Scaler сохранён в {scaler_path}")
1545
+ self.dquantprint(f"Scaler is saved in {scaler_path}")
1576
1546
 
1577
1547
  if hasattr(self, 'scaler_y') and self.scaler_y is not None:
1578
1548
  scaler_path = os.path.join(onnx_dir, f"{name}_scaler_y.pkl")
1579
1549
  joblib.dump(self.scaler_y, scaler_path)
1580
- self.dquantprint(f"Scalery сохранён в {scaler_path}")
1550
+ self.dquantprint(f"Scalery is saved in {scaler_path}")
1581
1551
 
1582
1552
  for i in range(len(self.models)):
1583
1553
  onx = convert_sklearn(self.models[i], initial_types=initial_type, target_opset=12)
1584
1554
  file_path = os.path.join(onnx_dir, f"{name}_{i}.onnx")
1585
1555
  with open(file_path, "wb") as f:
1586
1556
  f.write(onx.SerializeToString())
1587
- self.dquantprint(f"Модель {i} сохранена в {file_path}")
1557
+ self.dquantprint(f"Model {i} is saved in {file_path}")
1588
1558
 
1589
- self.dquantprint(f"Все операции в директории '{name}' успешно завершены!")
1559
+ self.dquantprint(f"All operations in directory '{name}' completed successfully!")
1590
1560
 
1591
1561
 
1592
1562
  def load(self, name):
1593
1563
  self.loaded_models = []
1594
1564
 
1595
1565
  if not os.path.exists(name):
1596
- raise FileNotFoundError(f"Папка {name} не найдена")
1566
+ raise FileNotFoundError(f"Directory {name} not found")
1597
1567
 
1598
1568
  try:
1599
1569
  file_path = os.path.join(name, f"{name}_features.json")
@@ -1627,7 +1597,7 @@ class VolClustGB(FichEn):
1627
1597
  model_files = [f for f in os.listdir(name) if f.endswith('.onnx')]
1628
1598
 
1629
1599
  if not model_files:
1630
- raise FileNotFoundError(f"В папке {name} не найдено .onnx файлов")
1600
+ raise FileNotFoundError(f"No .onnx files found in directory {name}")
1631
1601
 
1632
1602
  model_files.sort()
1633
1603
  ml = len(model_files)
@@ -1656,7 +1626,8 @@ class VolClustGB(FichEn):
1656
1626
 
1657
1627
 
1658
1628
  class VolClustXGB(FichEn):
1659
- def __init__(self, sett, early_stopping=True, output=True, qlike=True):
1629
+ def __init__(self, sett, early_stopping=True, output=True, loss="QLIKE"):
1630
+ self.loss = loss
1660
1631
  self.output = output
1661
1632
  self.models = []
1662
1633
  self.scaler = StandardScaler()
@@ -1666,31 +1637,41 @@ class VolClustXGB(FichEn):
1666
1637
  self.onnx_load = False
1667
1638
  self.early_stopping = early_stopping
1668
1639
  self.V = Visualization('dark')
1669
- # qlike_obj
1670
1640
  self.default_sett = {
1671
- #'objective': 'reg:squarederror',
1672
1641
  'learning_rate': 0.1,
1673
- 'n_estimators': 1,
1674
- 'max_depth': 3,
1642
+ 'max_depth': 6,
1675
1643
  'min_child_weight': 5,
1644
+ 'gamma': 0.1,
1676
1645
  'subsample': 0.8,
1677
- 'random_state': 42
1646
+ 'colsample_bytree': 0.8,
1647
+ 'reg_alpha': 0.0,
1648
+ 'reg_lambda': 1.0,
1649
+ 'random_state': 42,
1650
+ 'tree_method': 'hist',
1651
+ 'device': 'cpu'
1678
1652
  }
1679
- if qlike == False:
1653
+
1654
+ if loss == "MSE":
1680
1655
  self.default_sett['objective'] = 'reg:squarederror'
1656
+ elif loss == "MAE":
1657
+ self.default_sett['objective'] = 'reg:absoluteerror'
1681
1658
 
1682
1659
  self.meta = {
1683
1660
  "model_type": "xgb",
1684
- "model_settings": self.default_sett
1661
+ "model_settings": self.default_sett,
1662
+ "model_loss": loss
1685
1663
  }
1686
1664
  if sett == {}:
1687
- if qlike:
1665
+ if loss == "QLIKE":
1688
1666
  self.base_model = xgboost.XGBRegressor(**self.default_sett, objective=self.qlike_obj)
1689
1667
  else:
1690
1668
  self.base_model = xgboost.XGBRegressor(**self.default_sett)
1691
1669
  else:
1692
- del sett['objective']
1693
- if qlike:
1670
+ try:
1671
+ if sett['objective']: del sett['objective']
1672
+ except KeyError:
1673
+ pass
1674
+ if loss == "QLIKE":
1694
1675
  self.base_model = xgboost.XGBRegressor(**sett, objective=self.qlike_obj)
1695
1676
  else:
1696
1677
  self.base_model = xgboost.XGBRegressor(**sett)
@@ -1733,28 +1714,27 @@ class VolClustXGB(FichEn):
1733
1714
  self.save_mql5(name)
1734
1715
  onnx_dir = os.path.join(name, f"{name}_onnx")
1735
1716
  os.makedirs(onnx_dir, exist_ok=True)
1736
- self.dquantprint(f"Директория для ONNX файлов создана: {onnx_dir}")
1717
+ self.dquantprint(f"Directory for ONNX files created: {onnx_dir}")
1737
1718
 
1738
- # 4. Сохраняем модели и scaler в поддиректорию
1739
1719
  initial_type = [('float_input', FloatTensorType([None, self.X_shape]))]
1740
1720
 
1741
1721
  if hasattr(self, 'scaler') and self.scaler is not None:
1742
1722
  scaler_path = os.path.join(onnx_dir, f"{name}_scaler.pkl")
1743
1723
  joblib.dump(self.scaler, scaler_path)
1744
- self.dquantprint(f"Scaler сохранён в {scaler_path}")
1724
+ self.dquantprint(f"Scaler is saved in {scaler_path}")
1745
1725
 
1746
1726
  if hasattr(self, 'scaler_y') and self.scaler_y is not None:
1747
1727
  scaler_path = os.path.join(onnx_dir, f"{name}_scaler_y.pkl")
1748
1728
  joblib.dump(self.scaler_y, scaler_path)
1749
- self.dquantprint(f"Scalery сохранён в {scaler_path}")
1729
+ self.dquantprint(f"Scalery is saved in {scaler_path}")
1750
1730
 
1751
1731
  for i in range(len(self.models)):
1752
1732
  onx = onnxmltools.convert_xgboost(self.models[i], initial_types=initial_type, target_opset=9)
1753
1733
  model_path = os.path.join(onnx_dir, f"{name}_{i}.onnx")
1754
1734
  onnxmltools.utils.save_model(onx, model_path)
1755
- self.dquantprint(f"Модель {i} сохранена в {model_path}")
1735
+ self.dquantprint(f"Model {i} is saved in {model_path}")
1756
1736
 
1757
- self.dquantprint(f"Все операции в директории '{name}' успешно завершены!")
1737
+ self.dquantprint(f"All operations in directory '{name}' completed successfully!")
1758
1738
 
1759
1739
 
1760
1740
 
@@ -1762,7 +1742,7 @@ class VolClustXGB(FichEn):
1762
1742
  self.loaded_models = []
1763
1743
 
1764
1744
  if not os.path.exists(name):
1765
- raise FileNotFoundError(f"Папка {name} не найдена")
1745
+ raise FileNotFoundError(f"Directory {name} not found")
1766
1746
 
1767
1747
  try:
1768
1748
  file_path = os.path.join(name, f"{name}_features.json")
@@ -1796,7 +1776,7 @@ class VolClustXGB(FichEn):
1796
1776
  model_files = [f for f in os.listdir(name) if f.endswith('.onnx')]
1797
1777
 
1798
1778
  if not model_files:
1799
- raise FileNotFoundError(f"В папке {name} не найдено .onnx файлов")
1779
+ raise FileNotFoundError(f"No .onnx files found in directory {name}")
1800
1780
 
1801
1781
  model_files.sort()
1802
1782
  ml = len(model_files)
@@ -1823,7 +1803,8 @@ class VolClustXGB(FichEn):
1823
1803
 
1824
1804
 
1825
1805
  class VolClustLightGBM(FichEn):
1826
- def __init__(self, sett, early_stopping=True, output=True, qlike=True):
1806
+ def __init__(self, sett, early_stopping=True, output=True, loss="QLIKE"):
1807
+ self.loss = loss
1827
1808
  self.output = output
1828
1809
  self.models = []
1829
1810
  self.scaler = StandardScaler()
@@ -1834,28 +1815,42 @@ class VolClustLightGBM(FichEn):
1834
1815
  self.early_stopping = early_stopping
1835
1816
  self.V = Visualization('dark')
1836
1817
  self.default_sett = {
1837
- 'num_leaves': 7,
1838
- 'min_data_in_leaf': 3,
1839
- 'min_data_in_bin': 3,
1840
1818
  'learning_rate': 0.1,
1819
+ 'max_depth': 6,
1820
+ 'num_leaves': 2**6 - 1,
1821
+ 'min_child_samples': 5,
1822
+ 'min_split_gain': 0.1,
1823
+ 'bagging_fraction': 0.8,
1824
+ 'bagging_freq': 1,
1825
+ 'feature_fraction': 0.8,
1826
+ 'reg_alpha': 0.0,
1827
+ 'reg_lambda': 1.0,
1828
+ 'random_state': 42,
1841
1829
  'verbosity': -1,
1842
- 'seed': 42
1830
+ 'boosting_type': 'gbdt'
1843
1831
  }
1844
- if qlike == False:
1845
- self.default_sett['objective'] = 'regression'
1832
+
1833
+ if loss == "MSE":
1834
+ self.default_sett['objective'] = 'mse'
1835
+ elif loss == "MAE":
1836
+ self.default_sett['objective'] = 'mae'
1846
1837
 
1847
1838
  self.meta = {
1848
1839
  "model_type": "lgbm",
1849
- "model_settings": self.default_sett
1840
+ "model_settings": self.default_sett,
1841
+ "models_loss": loss
1850
1842
  }
1851
1843
  if sett == {}:
1852
- if qlike:
1844
+ if loss == "QLIKE":
1853
1845
  self.base_model = lgb.LGBMRegressor(**self.default_sett, objective=self.qlike_obj)
1854
1846
  else:
1855
1847
  self.base_model = lgb.LGBMRegressor(**self.default_sett)
1856
1848
  else:
1857
- del sett['objective']
1858
- if qlike:
1849
+ try:
1850
+ if sett['objective']: del sett['objective']
1851
+ except KeyError:
1852
+ pass
1853
+ if loss == "QLIKE":
1859
1854
  self.base_model = lgb.LGBMRegressor(**sett, objective=self.qlike_obj)
1860
1855
  else:
1861
1856
  self.base_model = lgb.LGBMRegressor(**sett)
@@ -1898,36 +1893,35 @@ class VolClustLightGBM(FichEn):
1898
1893
  self.save_mql5(name)
1899
1894
  onnx_dir = os.path.join(name, f"{name}_onnx")
1900
1895
  os.makedirs(onnx_dir, exist_ok=True)
1901
- self.dquantprint(f"Директория для ONNX файлов создана: {onnx_dir}")
1896
+ self.dquantprint(f"Directory for ONNX files created: {onnx_dir}")
1902
1897
 
1903
- # 4. Сохраняем модели и scaler в поддиректорию
1904
1898
  initial_type = [('float_input', FloatTensorType([None, self.X_shape]))]
1905
1899
 
1906
1900
  if hasattr(self, 'scaler') and self.scaler is not None:
1907
1901
  scaler_path = os.path.join(onnx_dir, f"{name}_scaler.pkl")
1908
1902
  joblib.dump(self.scaler, scaler_path)
1909
- self.dquantprint(f"Scaler сохранён в {scaler_path}")
1903
+ self.dquantprint(f"Scaler is saved in {scaler_path}")
1910
1904
 
1911
1905
  if hasattr(self, 'scaler_y') and self.scaler_y is not None:
1912
1906
  scaler_path = os.path.join(onnx_dir, f"{name}_scaler_y.pkl")
1913
1907
  joblib.dump(self.scaler_y, scaler_path)
1914
- self.dquantprint(f"Scalery сохранён в {scaler_path}")
1908
+ self.dquantprint(f"Scalery is saved in {scaler_path}")
1915
1909
 
1916
1910
  for i in range(len(self.models)):
1917
1911
  onx = onnxmltools.convert_lightgbm(self.models[i], initial_types=initial_type, zipmap=False,
1918
1912
  target_opset=12)
1919
1913
  file_path = os.path.join(onnx_dir, f"{name}_{i}.onnx")
1920
1914
  onnxmltools.utils.save_model(onx, file_path)
1921
- self.dquantprint(f"Модель {i} сохранена в {file_path}")
1915
+ self.dquantprint(f"Model {i} is saved in {file_path}")
1922
1916
 
1923
- self.dquantprint(f"Все операции в директории '{name}' успешно завершены!")
1917
+ self.dquantprint(f"All operations in directory '{name}' completed successfully!")
1924
1918
 
1925
1919
 
1926
1920
  def load(self, name):
1927
1921
  self.loaded_models = []
1928
1922
 
1929
1923
  if not os.path.exists(name):
1930
- raise FileNotFoundError(f"Папка {name} не найдена")
1924
+ raise FileNotFoundError(f"Directory {name} not found")
1931
1925
 
1932
1926
  try:
1933
1927
  file_path = os.path.join(name, f"{name}_features.json")
@@ -1961,7 +1955,7 @@ class VolClustLightGBM(FichEn):
1961
1955
  model_files = [f for f in os.listdir(name) if f.endswith('.onnx')]
1962
1956
 
1963
1957
  if not model_files:
1964
- raise FileNotFoundError(f"В папке {name} не найдено .onnx файлов")
1958
+ raise FileNotFoundError(f"No .onnx files found in directory {name}")
1965
1959
 
1966
1960
  model_files.sort()
1967
1961
  ml = len(model_files)
@@ -1985,170 +1979,3 @@ class VolClustLightGBM(FichEn):
1985
1979
  self.loaded_models.append(session)
1986
1980
 
1987
1981
  self.onnx_load = True
1988
-
1989
-
1990
- """
1991
- time spended: 65.44393944740295
1992
- [ 1.00901477e-02 6.06840734e-03 7.89991808e-03 2.40415813e-03
1993
- 1.30973943e-04 2.53802438e-03 7.55212328e-03 6.40525625e-01
1994
- 0.00000000e+00 2.81739978e-02 1.71405577e-02 7.20318643e-03
1995
- 2.66850655e-02 1.37758612e-05 2.63183893e-02 1.85560851e-03
1996
- 9.53905366e-01 0.00000000e+00 4.29736387e-02 2.55626153e-02
1997
- 2.36549673e-02 2.80319922e-02 -3.03892649e-04 2.81246929e-02
1998
- 1.48489457e-02 2.72801986e-01 0.00000000e+00 3.72218795e-02
1999
- 2.20329899e-02 1.21903154e-02 3.24872375e-02 1.21786687e-04
2000
- 3.31424959e-02 4.07938359e-03 1.05498777e-01 0.00000000e+00
2001
- 7.37316373e-02 4.32737643e-02 3.21723278e-02 5.74076879e-02
2002
- -3.87169703e-04 5.87003299e-02 1.50313074e-02 1.78512223e-01
2003
- 0.00000000e+00 4.04910463e-02 2.44025016e-02 2.97286458e-02
2004
- 4.09296639e-03 5.20381594e-04 4.62173561e-03 3.58693107e-02
2005
- 5.82791094e-01 0.00000000e+00 4.58374744e-02 2.74720640e-02
2006
- 3.16518085e-02 1.28362178e-02 4.88255628e-04 1.34072113e-02
2007
- 3.24302631e-02 4.51602205e-01 0.00000000e+00 2.04805939e-02
2008
- 1.21755897e-02 1.55781241e-02 8.44683596e-03 -1.44448658e-04
2009
- 8.33816248e-03 1.21424314e-02 0.00000000e+00 0.00000000e+00
2010
- 2.98493845e-02 1.78514990e-02 2.09793890e-02 4.31824090e-03
2011
- 2.91972368e-05 4.35677518e-03 2.54926093e-02 3.56991113e-01
2012
- 0.00000000e+00 4.38209920e-02 2.67519393e-02 1.94066006e-02
2013
- 3.52507396e-02 9.13841081e-05 3.45452848e-02 9.27570718e-03
2014
- 8.67142706e-01 0.00000000e+00 2.23729157e-02 1.34131927e-02
2015
- 1.50097284e-02 9.27476481e-03 -4.87292988e-04 8.83061573e-03
2016
- 1.35423000e-02 4.21120863e-01 0.00000000e+00 1.49549846e-02
2017
- 8.95837170e-03 1.02428690e-02 3.70974367e-03 8.63321678e-05
2018
- 3.80296545e-03 1.11520191e-02 3.26991207e-01 0.00000000e+00
2019
- 4.26058712e-02 2.58258056e-02 1.75734110e-02 3.62848420e-02
2020
- 5.55038464e-04 3.50793990e-02 7.30531730e-03 8.35520105e-01
2021
- 0.00000000e+00 1.48660486e-02 8.95036835e-03 9.96263886e-03
2022
- 4.81100437e-03 -4.97779422e-05 4.84922797e-03 1.00168207e-02
2023
- 6.67079520e-01 0.00000000e+00 3.05811410e-02 1.81291235e-02
2024
- 1.35250294e-02 2.35798305e-02 -1.06096226e-04 2.37539365e-02
2025
- 6.82720443e-03 7.05013333e-02 0.00000000e+00 9.97877681e-02
2026
- 5.71429634e-02 9.93251430e-03 9.43035288e-02 -2.15592232e-04
2027
- 9.86776488e-02 1.11011933e-03 3.53888733e-03 0.00000000e+00
2028
- 6.15493679e-02 3.69277996e-02 4.30480571e-02 2.30142933e-02
2029
- 3.82434298e-04 2.36635998e-02 3.78857681e-02 4.78877653e-01
2030
- 0.00000000e+00 4.07323827e-02 2.42627809e-02 3.03729349e-02
2031
- 1.75768508e-03 -1.89331202e-04 1.56989951e-03 3.91624832e-02
2032
- 2.94759703e-01 0.00000000e+00 3.89312610e-02 2.37273964e-02
2033
- 3.48261445e-02 2.14988488e-04 4.55482200e-05 1.69417160e-04
2034
- 3.87618438e-02 8.72129781e-01 0.00000000e+00 6.17359291e-01
2035
- 2.93932853e-01 1.08930483e-01 4.64730175e-01 4.39776373e-04
2036
- 5.92024459e-01 2.53348322e-02 3.59865231e-02 0.00000000e+00
2037
- 3.11147546e-01 2.11229224e-01 2.60957183e-01 1.12686222e-01
2038
- 8.45532816e-03 9.81137169e-02 2.13033829e-01 8.41486709e-01
2039
- 0.00000000e+00 9.61773087e-02 5.59225605e-02 4.42007214e-02
2040
- 6.75355700e-02 1.80191261e-03 7.16702268e-02 2.45070819e-02
2041
- 1.50546410e-01 0.00000000e+00 1.23761654e-01 7.29214118e-02
2042
- 9.68913447e-02 3.62457326e-02 1.29941148e-04 3.54667798e-02
2043
- 8.82948742e-02 3.34199130e-01 0.00000000e+00 1.62919592e-01
2044
- 9.78764618e-02 1.22212154e-01 7.26450577e-02 -1.41299781e-03
2045
- 7.39357846e-02 8.75708093e-02 5.42211975e-01 0.00000000e+00
2046
- 7.45248895e-02 4.52017387e-02 4.64108595e-02 4.12455257e-02
2047
- -2.27759272e-03 4.26840965e-02 3.18407930e-02 6.25823123e-01
2048
- 0.00000000e+00 5.01099799e-02 3.03195942e-02 3.68273961e-02
2049
- 2.44820439e-03 2.83362114e-04 2.16184786e-03 4.79481321e-02
2050
- 6.44204942e-01 0.00000000e+00 1.76503480e-01 1.13815750e-01
2051
- 6.65450214e-02 1.67104324e-01 1.12708932e-03 1.52761574e-01
2052
- 2.37419066e-02 8.73218209e-01 0.00000000e+00 1.57850455e-01
2053
- 9.26514801e-02 1.13630263e-01 1.22445001e-03 7.43594102e-05
2054
- 1.14934127e-03 1.56701114e-01 3.40320281e-01 0.00000000e+00
2055
- 7.19979354e-02 4.34659656e-02 5.21177072e-02 2.21448508e-03
2056
- 1.25191284e-03 3.46885170e-03 6.85290837e-02 5.66441411e-01
2057
- 0.00000000e+00 9.19313837e-02 5.28749679e-02 4.98083731e-02
2058
- 5.90770239e-02 8.43358015e-05 6.09412847e-02 3.09900990e-02
2059
- 1.22037653e-02 0.00000000e+00 1.02696046e-01 6.47826521e-02
2060
- 3.54393880e-02 9.57832377e-02 1.74497187e-04 9.11645446e-02
2061
- 1.15315016e-02 9.58084134e-01 0.00000000e+00 5.61199048e-02
2062
- 3.44009941e-02 2.49703201e-02 4.84447086e-02 3.01829683e-03
2063
- 4.42716886e-02 1.18482162e-02 8.56546369e-01 0.00000000e+00
2064
- 5.32228122e-02 3.18107827e-02 3.69621168e-02 8.01155994e-03
2065
- 5.85698106e-04 8.62943647e-03 4.45933758e-02 4.05350998e-01
2066
- 0.00000000e+00 2.15145177e-02 1.30245089e-02 1.62742830e-02
2067
- 5.28121136e-03 -8.77263769e-04 6.14455405e-03 1.53699637e-02
2068
- 8.68350803e-01 0.00000000e+00 5.05633636e-02 2.96374579e-02
2069
- 2.35973846e-02 3.74133767e-02 4.55768528e-04 3.85778362e-02
2070
- 1.19855274e-02 9.46606724e-03 0.00000000e+00 5.63840947e-02
2071
- 3.33798150e-02 3.34520599e-02 3.58132408e-02 -4.07618484e-04
2072
- 3.60546411e-02 1.99614159e-02 3.55645082e-01 0.00000000e+00
2073
- 5.57884077e-02 3.26136331e-02 7.71543102e-03 5.26502133e-02
2074
- 5.79304149e-04 5.46401883e-02 1.14821941e-03 5.92355248e-03
2075
- 0.00000000e+00 9.54862414e-02 5.94218027e-02 4.00815346e-02
2076
- 8.22684486e-02 5.43653418e-04 7.84316689e-02 1.70545725e-02
2077
- 8.57720697e-01 0.00000000e+00 2.02454145e-02 1.21577151e-02
2078
- 1.43197749e-02 1.36810741e-03 1.18759225e-04 1.24841275e-03
2079
- 1.89970017e-02 4.94675292e-01 0.00000000e+00 6.20877978e-02
2080
- 3.84604802e-02 4.87031762e-02 2.57778032e-02 -2.00581227e-04
2081
- 2.56489734e-02 3.64388244e-02 9.85866990e-01 0.00000000e+00
2082
- 7.24692836e-02 4.32326577e-02 5.50895288e-02 2.78887560e-02
2083
- 0.00000000e+00 2.75034548e-02 4.49658288e-02 4.01572960e-01
2084
- 0.00000000e+00 4.89923950e-02 2.89772392e-02 3.65664667e-02
2085
- 8.90628383e-03 5.60189477e-04 9.50625226e-03 3.94861427e-02
2086
- 1.82037110e-01 0.00000000e+00 2.65697886e-02 1.61453720e-02
2087
- 1.38432176e-02 1.97258038e-02 7.27424183e-04 1.88050990e-02
2088
- 7.76468969e-03 9.37379581e-01 0.00000000e+00 2.46622989e-02
2089
- 1.47933610e-02 1.67767982e-02 1.11868608e-02 -7.34744665e-04
2090
- 1.05149231e-02 1.41473759e-02 4.48996965e-01 0.00000000e+00
2091
- 6.72313405e-02 4.17978961e-02 7.27511817e-03 6.83840155e-02
2092
- -4.23498691e-04 6.65217268e-02 7.09613790e-04 1.00000000e+00
2093
- 0.00000000e+00 4.05808633e-02 2.40200436e-02 2.87843914e-02
2094
- 1.32013831e-02 2.59571539e-04 1.35484777e-02 2.70323856e-02
2095
- 1.36321339e-01 0.00000000e+00 2.76677447e-02 1.67989744e-02
2096
- 1.27991081e-02 2.17346261e-02 3.91139046e-04 2.11089920e-02
2097
- 6.55875268e-03 8.90965792e-01 0.00000000e+00 2.22339109e-02
2098
- 1.34302943e-02 1.93488183e-02 4.37399798e-03 5.29667003e-04
2099
- 4.91324488e-03 1.73206660e-02 7.57573661e-01 0.00000000e+00
2100
- 7.30232075e-02 4.27061128e-02 2.56072816e-02 6.16526462e-02
2101
- 2.51412998e-04 6.38442505e-02 9.17895698e-03 1.25699176e-01
2102
- 0.00000000e+00 1.98494355e-02 1.19230831e-02 1.40594483e-02
2103
- 9.34113613e-04 2.83895912e-04 1.21844594e-03 1.86309896e-02
2104
- 5.07988653e-01 0.00000000e+00 4.43071401e-02 2.66348271e-02
2105
- 3.08453405e-02 1.61980943e-02 -1.45620908e-04 1.62132316e-02
2106
- 2.80939085e-02 5.18062994e-01 0.00000000e+00 4.42411056e-02
2107
- 2.62008186e-02 3.37862051e-02 1.82479034e-02 -7.99863781e-04
2108
- 1.76155499e-02 2.58256919e-02 5.94497091e-01 0.00000000e+00
2109
- 2.40756419e-02 1.43885928e-02 1.82440682e-02 3.81350856e-04
2110
- -2.56613507e-04 1.24810073e-04 2.39508318e-02 2.95056894e-01
2111
- 0.00000000e+00 4.44530014e-02 2.61539413e-02 2.34725191e-02
2112
- 2.97129371e-02 4.71806267e-04 3.06305774e-02 1.38224240e-02
2113
- 2.94891979e-02 0.00000000e+00 8.13491945e-02 5.08256128e-02
2114
- 3.51490041e-02 6.90291127e-02 -2.32655230e-04 6.69331464e-02
2115
- 1.44160481e-02 9.69519652e-01 0.00000000e+00 1.64667468e-02
2116
- 9.87202072e-03 1.14533989e-02 2.90152110e-03 -3.54366267e-05
2117
- 2.87029796e-03 1.35964488e-02 3.92401519e-01 0.00000000e+00
2118
- 2.48991200e-02 1.51168312e-02 7.20748225e-03 2.25009020e-02
2119
- -5.36407562e-04 2.27860523e-02 2.11306769e-03 9.31981961e-01
2120
- 0.00000000e+00 1.57825262e-02 9.43347831e-03 8.63093904e-03
2121
- 9.44698796e-03 4.53071603e-04 9.94482320e-03 5.83770297e-03
2122
- 1.97150369e-01 0.00000000e+00 5.88186630e-02 3.45510576e-02
2123
- 2.67466667e-02 4.37078926e-02 -3.70718529e-04 4.43064339e-02
2124
- 1.45122291e-02 1.14765291e-01 0.00000000e+00 1.45500976e-02
2125
- 8.73308037e-03 1.03194872e-02 2.37642848e-04 -3.16019514e-04
2126
- 7.83484265e-05 1.44717492e-02 4.58307320e-01 0.00000000e+00
2127
- 3.90720635e-02 2.38379593e-02 1.46013508e-02 3.38498125e-02
2128
- -1.24039168e-04 3.34073566e-02 5.66470690e-03 8.96944072e-01
2129
- 0.00000000e+00 5.52093720e-02 3.38163892e-02 2.62722462e-02
2130
- 4.29733472e-02 5.51653396e-04 4.15114252e-02 1.36979468e-02
2131
- 8.48703084e-01 0.00000000e+00 1.91329742e-02 1.12056766e-02
2132
- 7.58118553e-03 1.61780845e-02 5.90264833e-04 1.54576573e-02
2133
- 3.08505200e-03 8.33624529e-01 0.00000000e+00 1.58114158e-02
2134
- 9.48141355e-03 1.16968974e-02 2.51773978e-03 -5.52143041e-05
2135
- 2.56978724e-03 1.32416286e-02 4.03234229e-01 0.00000000e+00
2136
- 1.81235587e-02 1.09543091e-02 7.99943802e-03 1.44176361e-02
2137
- 2.64490251e-05 1.42877506e-02 3.83580801e-03 8.51084356e-01
2138
- 0.00000000e+00 1.49035498e-02 9.01786107e-03 0.00000000e+00
2139
- 1.49573560e-02 -5.74993747e-05 1.49035498e-02 0.00000000e+00
2140
- 1.00000000e+00 0.00000000e+00 1.07237191e-02 6.46880826e-03
2141
- 9.26255244e-03 1.46866263e-03 1.75372147e-04 1.29221253e-03
2142
- 9.43150654e-03 9.10789689e-01 0.00000000e+00 1.23360969e-01
2143
- 7.83966160e-02 3.67183038e-02 1.19841406e-01 -3.93352924e-05
2144
- 1.12978228e-01 1.03827418e-02 9.34866426e-01 0.00000000e+00
2145
- 1.04797471e-01 6.06890467e-02 8.08996063e-02 1.63219782e-02
2146
- -3.88998460e-04 1.60669109e-02 8.87305601e-02 1.38085306e-01
2147
- 0.00000000e+00 4.39345720e-02 2.57854018e-02 2.96597192e-02
2148
- 2.35369104e-02 1.60506376e-03 2.16570141e-02 2.12386179e-02
2149
- 5.18074610e-01 0.00000000e+00]
2150
- [0.02178552 0.03785454 0.03499315 0.02283531 0.04798502 0.08585039
2151
- 0.023324 0.03473237 0.13709623 0.07662905 0.04318881 0.05538318
2152
- 0.05529575 0.05300378 0.03236753 0.04895759 0.0345107 0.03046795
2153
- 0.03755051 0.0754602 ]
2154
- """
@@ -269,7 +269,7 @@ class Visualization:
269
269
  }
270
270
 
271
271
  fig.savefig(filename, **save_kwargs)
272
- print(f"График сохранен как {filename}")
272
+ print(f"The graph saved as {filename}")
273
273
 
274
274
  def show_vol(self, df, pred, save_path=None):
275
275
  fig, ax = self.__create_figure(figsize=(15, 6))
@@ -299,9 +299,9 @@ class Visualization:
299
299
 
300
300
  ax.set_xlim(-1, len(df))
301
301
  ax.set_ylim(0, max_bar_height * 1.3)
302
- ax.set_xlabel('Время')
302
+ ax.set_xlabel('Time')
303
303
  ax.set_ylabel('')
304
- ax.set_title('Объемный график')
304
+ ax.set_title('Volumetric graph')
305
305
 
306
306
  self.__style_axes(ax)
307
307
 
@@ -315,10 +315,8 @@ class Visualization:
315
315
  plt.show()
316
316
 
317
317
  def forward_validation_errors(self, mse_errors, r2_errors, save_path=None):
318
- # Первый график - MSE Loss
319
318
  fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(15, 6))
320
319
 
321
- # Первый график - MSE Loss
322
320
  ax1.plot(list(mse_errors), label='Train Loss',
323
321
  color=self.config['colors']['primary'])
324
322
  ax1.set_xlabel('Trees')
@@ -329,7 +327,6 @@ class Visualization:
329
327
  self.__style_axes(ax1)
330
328
  self.__style_legend(ax1)
331
329
 
332
- # Второй график - R² Score
333
330
  ax2.plot(list(r2_errors), label='Train R²',
334
331
  color=self.config['colors']['primary'])
335
332
 
@@ -350,10 +347,8 @@ class Visualization:
350
347
 
351
348
 
352
349
  def show_errors(self, train_errors, val_errors, train_r2, val_r2, save_path=None):
353
- # Первый график - MSE Loss
354
350
  fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(15, 6))
355
351
 
356
- # Первый график - MSE Loss
357
352
  ax1.plot(list(train_errors), label='Train Loss',
358
353
  color=self.config['colors']['primary'])
359
354
  ax1.plot(list(val_errors), label='Validation Loss',
@@ -366,7 +361,6 @@ class Visualization:
366
361
  self.__style_axes(ax1)
367
362
  self.__style_legend(ax1)
368
363
 
369
- # Второй график - R² Score
370
364
  ax2.plot(list(train_r2), label='Train R²',
371
365
  color=self.config['colors']['primary'])
372
366
  ax2.plot(list(val_r2), label='Validation R²',
@@ -1,10 +0,0 @@
1
- import numpy as np
2
-
3
-
4
- def qlike_score(y_true, y_pred):
5
- y_true = np.asarray(y_true, dtype=np.float64)
6
- y_pred = np.asarray(y_pred, dtype=np.float64)
7
- eps = 1e-10
8
- y_pred = np.clip(y_pred, eps, None)
9
- loss = np.log(y_pred) + y_true / y_pred
10
- return np.mean(loss)
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes