ivolatility-backtesting 1.10.0__py3-none-any.whl → 1.12.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.

Potentially problematic release.


This version of ivolatility-backtesting might be problematic. Click here for more details.

@@ -12,7 +12,8 @@ from .ivolatility_backtesting import (
12
12
  preload_data_universal,
13
13
  apply_optimization_preset, list_optimization_presets,
14
14
  calculate_combinations_count, print_preset_info,
15
- get_cache_config, UniversalCacheManager
15
+ get_cache_config, UniversalCacheManager,
16
+ _process_options_df
16
17
  )
17
18
 
18
19
  __all__ = [
@@ -29,5 +30,6 @@ __all__ = [
29
30
  'preload_data_universal',
30
31
  'apply_optimization_preset', 'list_optimization_presets',
31
32
  'calculate_combinations_count', 'print_preset_info',
32
- 'get_cache_config', 'UniversalCacheManager'
33
+ 'get_cache_config', 'UniversalCacheManager',
34
+ '_process_options_df'
33
35
  ]
@@ -19,6 +19,7 @@ import psutil
19
19
  import warnings
20
20
  from itertools import product
21
21
  import sys
22
+ import gc
22
23
  from typing import Dict, List, Optional, Tuple, Union, Any
23
24
  warnings.filterwarnings('ignore', category=pd.errors.SettingWithCopyWarning)
24
25
  warnings.filterwarnings('ignore', message='.*SettingWithCopyWarning.*')
@@ -1622,12 +1623,13 @@ class ChartGenerator:
1622
1623
  """Generate 6 professional charts"""
1623
1624
 
1624
1625
  @staticmethod
1625
- def create_all_charts(analyzer, filename='backtest_results.png', show_plots=True):
1626
+ def create_all_charts(analyzer, filename='backtest_results.png', show_plots=True, silent=False):
1626
1627
  r = analyzer.results
1627
1628
 
1628
1629
  if len(r.trades) == 0:
1629
- print("No trades to visualize")
1630
- return
1630
+ if not silent:
1631
+ print("No trades to visualize")
1632
+ return None
1631
1633
 
1632
1634
  trades_df = pd.DataFrame(r.trades)
1633
1635
  fig, axes = plt.subplots(3, 2, figsize=(18, 14))
@@ -1710,7 +1712,10 @@ class ChartGenerator:
1710
1712
  else:
1711
1713
  plt.close() # Close without displaying
1712
1714
 
1713
- print(f"Chart saved: {filename}")
1715
+ if not silent:
1716
+ print(f"Chart saved: {filename}")
1717
+
1718
+ return filename
1714
1719
 
1715
1720
 
1716
1721
  def create_stoploss_charts(analyzer, filename='stoploss_analysis.png', show_plots=True):
@@ -1806,13 +1811,14 @@ class ResultsExporter:
1806
1811
  """Export results to CSV"""
1807
1812
 
1808
1813
  @staticmethod
1809
- def export_all(analyzer, prefix='backtest'):
1814
+ def export_all(analyzer, prefix='backtest', silent=False):
1810
1815
  r = analyzer.results
1811
1816
  m = analyzer.metrics
1812
1817
 
1813
1818
  if len(r.trades) == 0:
1814
- print("No trades to export")
1815
- return
1819
+ if not silent:
1820
+ print("No trades to export")
1821
+ return []
1816
1822
 
1817
1823
  trades_df = pd.DataFrame(r.trades)
1818
1824
 
@@ -1882,8 +1888,12 @@ class ResultsExporter:
1882
1888
  for col in numeric_columns:
1883
1889
  trades_df[col] = trades_df[col].round(5)
1884
1890
 
1891
+ exported_files = []
1892
+
1885
1893
  trades_df.to_csv(f'{prefix}_trades.csv', index=False)
1886
- print(f"Exported: {prefix}_trades.csv ({len(ordered_columns)} columns)")
1894
+ exported_files.append((f'{prefix}_trades.csv', f"({len(ordered_columns)} columns)"))
1895
+ if not silent:
1896
+ print(f"Exported: {prefix}_trades.csv ({len(ordered_columns)} columns)")
1887
1897
 
1888
1898
  equity_df = pd.DataFrame({
1889
1899
  'date': pd.to_datetime(r.equity_dates).strftime('%Y-%m-%d'),
@@ -1891,7 +1901,9 @@ class ResultsExporter:
1891
1901
  })
1892
1902
  equity_df['equity'] = equity_df['equity'].round(5)
1893
1903
  equity_df.to_csv(f'{prefix}_equity.csv', index=False)
1894
- print(f"Exported: {prefix}_equity.csv")
1904
+ exported_files.append((f'{prefix}_equity.csv', ""))
1905
+ if not silent:
1906
+ print(f"Exported: {prefix}_equity.csv")
1895
1907
 
1896
1908
  with open(f'{prefix}_summary.txt', 'w') as f:
1897
1909
  f.write("BACKTEST SUMMARY\n")
@@ -1905,7 +1917,9 @@ class ResultsExporter:
1905
1917
  f.write(f"Max DD: {m['max_drawdown']:.2f}%\n")
1906
1918
  f.write(f"Trades: {m['total_trades']}\n")
1907
1919
 
1908
- print(f"Exported: {prefix}_summary.txt")
1920
+ exported_files.append((f'{prefix}_summary.txt', ""))
1921
+ if not silent:
1922
+ print(f"Exported: {prefix}_summary.txt")
1909
1923
 
1910
1924
  # Export metrics as JSON with rounded values
1911
1925
  import json
@@ -1919,7 +1933,11 @@ class ResultsExporter:
1919
1933
  with open(f'{prefix}_metrics.json', 'w') as f:
1920
1934
  json.dump(metrics_rounded, f, indent=2)
1921
1935
 
1922
- print(f"Exported: {prefix}_metrics.json")
1936
+ exported_files.append((f'{prefix}_metrics.json', ""))
1937
+ if not silent:
1938
+ print(f"Exported: {prefix}_metrics.json")
1939
+
1940
+ return exported_files
1923
1941
 
1924
1942
 
1925
1943
  # ============================================================
@@ -1961,13 +1979,22 @@ def run_backtest(strategy_function, config, print_report=True,
1961
1979
  print("\n" + "="*80)
1962
1980
  ResultsReporter.print_full_report(analyzer)
1963
1981
 
1982
+ # Store file info for later printing (in optimization mode)
1983
+ analyzer.chart_file = None
1984
+ analyzer.exported_files = []
1985
+
1964
1986
  # Export charts during optimization if requested
1965
1987
  if create_charts and len(results.trades) > 0:
1966
1988
  if not is_optimization:
1967
1989
  print(f"\n[*] Creating charts: {chart_filename}")
1968
1990
  try:
1969
1991
  # Don't show plots during optimization, just save them
1970
- ChartGenerator.create_all_charts(analyzer, chart_filename, show_plots=not is_optimization)
1992
+ chart_file = ChartGenerator.create_all_charts(
1993
+ analyzer, chart_filename,
1994
+ show_plots=not is_optimization,
1995
+ silent=is_optimization # ← Silent in optimization
1996
+ )
1997
+ analyzer.chart_file = chart_file
1971
1998
  except Exception as e:
1972
1999
  if not is_optimization:
1973
2000
  print(f"[ERROR] Charts failed: {e}")
@@ -1977,7 +2004,11 @@ def run_backtest(strategy_function, config, print_report=True,
1977
2004
  if not is_optimization:
1978
2005
  print(f"\n[*] Exporting: {export_prefix}_*")
1979
2006
  try:
1980
- ResultsExporter.export_all(analyzer, export_prefix)
2007
+ exported = ResultsExporter.export_all(
2008
+ analyzer, export_prefix,
2009
+ silent=is_optimization # ← Silent in optimization
2010
+ )
2011
+ analyzer.exported_files = exported
1981
2012
  except Exception as e:
1982
2013
  if not is_optimization:
1983
2014
  print(f"[ERROR] Export failed: {e}")
@@ -3159,8 +3190,24 @@ def optimize_parameters(base_config, param_grid, strategy_function,
3159
3190
  status_symbol = "✓" if is_valid else "✗"
3160
3191
  status_color = "#00cc00" if is_valid else "#ff6666"
3161
3192
 
3162
- print(f"\n[{idx}/{total_combinations}] {param_str}")
3163
- print("-" * 80)
3193
+ # Print combination header
3194
+ print(f"[{idx}/{total_combinations}] {param_str}")
3195
+ print("-" * 100)
3196
+
3197
+ # Print chart file if created
3198
+ if hasattr(analyzer, 'chart_file') and analyzer.chart_file:
3199
+ print(f"Chart saved: {analyzer.chart_file}")
3200
+
3201
+ # Print exported files
3202
+ if hasattr(analyzer, 'exported_files') and analyzer.exported_files:
3203
+ for file_path, extra_info in analyzer.exported_files:
3204
+ if extra_info:
3205
+ print(f"Exported: {file_path} {extra_info}")
3206
+ else:
3207
+ print(f"Exported: {file_path}")
3208
+
3209
+ # Print metrics with separator
3210
+ print("+" * 100)
3164
3211
  if is_valid:
3165
3212
  print(f" {status_symbol} Return: {analyzer.metrics['total_return']:>7.2f}% | "
3166
3213
  f"Sharpe: {analyzer.metrics['sharpe']:>6.2f} | "
@@ -3170,6 +3217,7 @@ def optimize_parameters(base_config, param_grid, strategy_function,
3170
3217
  f"PF: {analyzer.metrics['profit_factor']:>5.2f}")
3171
3218
  else:
3172
3219
  print(f" {status_symbol} INVALID: {invalid_reason}")
3220
+ print("+" * 100 + "\n")
3173
3221
 
3174
3222
  # Update widget status with last result
3175
3223
  if has_widgets:
@@ -3208,6 +3256,11 @@ def optimize_parameters(base_config, param_grid, strategy_function,
3208
3256
 
3209
3257
  results.append(result)
3210
3258
 
3259
+ # ═══ MEMORY CLEANUP AFTER EACH TEST ═══
3260
+ # Delete large objects to free RAM for next iteration
3261
+ del analyzer, test_config
3262
+ gc.collect()
3263
+
3211
3264
  # Show intermediate summary every 10 combinations (or at end)
3212
3265
  if idx % 10 == 0 or idx == total_combinations:
3213
3266
  valid_so_far = [r for r in results if r['is_valid']]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ivolatility_backtesting
3
- Version: 1.10.0
3
+ Version: 1.12.0
4
4
  Summary: A universal backtesting framework for financial strategies using the IVolatility API.
5
5
  Author-email: IVolatility <support@ivolatility.com>
6
6
  Project-URL: Homepage, https://ivolatility.com
@@ -0,0 +1,7 @@
1
+ ivolatility_backtesting/__init__.py,sha256=MWcT7Bb8svHsOouQYMBkwwNzscbZmGN8UCEh2KwT7uY,1616
2
+ ivolatility_backtesting/ivolatility_backtesting.py,sha256=3jKzE1fYXPQWENG6OdBrRRu_ASaHS4vpGQggpRzYCI0,176956
3
+ ivolatility_backtesting-1.12.0.dist-info/licenses/LICENSE,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
+ ivolatility_backtesting-1.12.0.dist-info/METADATA,sha256=IayxoVNFPUsOba2T--UnZitlOL-bqLHcByN8UBxKTjI,2053
5
+ ivolatility_backtesting-1.12.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
6
+ ivolatility_backtesting-1.12.0.dist-info/top_level.txt,sha256=Qv3irUBntr8b11WIKNN6zzCSguwaWC4nWR-ZKq8NsjY,24
7
+ ivolatility_backtesting-1.12.0.dist-info/RECORD,,
@@ -1,7 +0,0 @@
1
- ivolatility_backtesting/__init__.py,sha256=xZh8uDYGCylBJ3CK4BOOmuBWNWLOyWpfwQumc8BclQ0,1563
2
- ivolatility_backtesting/ivolatility_backtesting.py,sha256=8CaQnt1blFIkLDwWQGrTeEIG0gELInbCupfyNIiEVig,174924
3
- ivolatility_backtesting-1.10.0.dist-info/licenses/LICENSE,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
- ivolatility_backtesting-1.10.0.dist-info/METADATA,sha256=AJdlDlTh557W8NZ0UoAm5QcdZR8s5Fle3Ds7NfF_OuU,2053
5
- ivolatility_backtesting-1.10.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
6
- ivolatility_backtesting-1.10.0.dist-info/top_level.txt,sha256=Qv3irUBntr8b11WIKNN6zzCSguwaWC4nWR-ZKq8NsjY,24
7
- ivolatility_backtesting-1.10.0.dist-info/RECORD,,