ivolatility-backtesting 1.10.0__tar.gz → 1.11.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.

Potentially problematic release.


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

@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ivolatility_backtesting
3
- Version: 1.10.0
3
+ Version: 1.11.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
@@ -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
  ]
@@ -1622,12 +1622,13 @@ class ChartGenerator:
1622
1622
  """Generate 6 professional charts"""
1623
1623
 
1624
1624
  @staticmethod
1625
- def create_all_charts(analyzer, filename='backtest_results.png', show_plots=True):
1625
+ def create_all_charts(analyzer, filename='backtest_results.png', show_plots=True, silent=False):
1626
1626
  r = analyzer.results
1627
1627
 
1628
1628
  if len(r.trades) == 0:
1629
- print("No trades to visualize")
1630
- return
1629
+ if not silent:
1630
+ print("No trades to visualize")
1631
+ return None
1631
1632
 
1632
1633
  trades_df = pd.DataFrame(r.trades)
1633
1634
  fig, axes = plt.subplots(3, 2, figsize=(18, 14))
@@ -1710,7 +1711,10 @@ class ChartGenerator:
1710
1711
  else:
1711
1712
  plt.close() # Close without displaying
1712
1713
 
1713
- print(f"Chart saved: {filename}")
1714
+ if not silent:
1715
+ print(f"Chart saved: {filename}")
1716
+
1717
+ return filename
1714
1718
 
1715
1719
 
1716
1720
  def create_stoploss_charts(analyzer, filename='stoploss_analysis.png', show_plots=True):
@@ -1806,13 +1810,14 @@ class ResultsExporter:
1806
1810
  """Export results to CSV"""
1807
1811
 
1808
1812
  @staticmethod
1809
- def export_all(analyzer, prefix='backtest'):
1813
+ def export_all(analyzer, prefix='backtest', silent=False):
1810
1814
  r = analyzer.results
1811
1815
  m = analyzer.metrics
1812
1816
 
1813
1817
  if len(r.trades) == 0:
1814
- print("No trades to export")
1815
- return
1818
+ if not silent:
1819
+ print("No trades to export")
1820
+ return []
1816
1821
 
1817
1822
  trades_df = pd.DataFrame(r.trades)
1818
1823
 
@@ -1882,8 +1887,12 @@ class ResultsExporter:
1882
1887
  for col in numeric_columns:
1883
1888
  trades_df[col] = trades_df[col].round(5)
1884
1889
 
1890
+ exported_files = []
1891
+
1885
1892
  trades_df.to_csv(f'{prefix}_trades.csv', index=False)
1886
- print(f"Exported: {prefix}_trades.csv ({len(ordered_columns)} columns)")
1893
+ exported_files.append((f'{prefix}_trades.csv', f"({len(ordered_columns)} columns)"))
1894
+ if not silent:
1895
+ print(f"Exported: {prefix}_trades.csv ({len(ordered_columns)} columns)")
1887
1896
 
1888
1897
  equity_df = pd.DataFrame({
1889
1898
  'date': pd.to_datetime(r.equity_dates).strftime('%Y-%m-%d'),
@@ -1891,7 +1900,9 @@ class ResultsExporter:
1891
1900
  })
1892
1901
  equity_df['equity'] = equity_df['equity'].round(5)
1893
1902
  equity_df.to_csv(f'{prefix}_equity.csv', index=False)
1894
- print(f"Exported: {prefix}_equity.csv")
1903
+ exported_files.append((f'{prefix}_equity.csv', ""))
1904
+ if not silent:
1905
+ print(f"Exported: {prefix}_equity.csv")
1895
1906
 
1896
1907
  with open(f'{prefix}_summary.txt', 'w') as f:
1897
1908
  f.write("BACKTEST SUMMARY\n")
@@ -1905,7 +1916,9 @@ class ResultsExporter:
1905
1916
  f.write(f"Max DD: {m['max_drawdown']:.2f}%\n")
1906
1917
  f.write(f"Trades: {m['total_trades']}\n")
1907
1918
 
1908
- print(f"Exported: {prefix}_summary.txt")
1919
+ exported_files.append((f'{prefix}_summary.txt', ""))
1920
+ if not silent:
1921
+ print(f"Exported: {prefix}_summary.txt")
1909
1922
 
1910
1923
  # Export metrics as JSON with rounded values
1911
1924
  import json
@@ -1919,7 +1932,11 @@ class ResultsExporter:
1919
1932
  with open(f'{prefix}_metrics.json', 'w') as f:
1920
1933
  json.dump(metrics_rounded, f, indent=2)
1921
1934
 
1922
- print(f"Exported: {prefix}_metrics.json")
1935
+ exported_files.append((f'{prefix}_metrics.json', ""))
1936
+ if not silent:
1937
+ print(f"Exported: {prefix}_metrics.json")
1938
+
1939
+ return exported_files
1923
1940
 
1924
1941
 
1925
1942
  # ============================================================
@@ -1961,13 +1978,22 @@ def run_backtest(strategy_function, config, print_report=True,
1961
1978
  print("\n" + "="*80)
1962
1979
  ResultsReporter.print_full_report(analyzer)
1963
1980
 
1981
+ # Store file info for later printing (in optimization mode)
1982
+ analyzer.chart_file = None
1983
+ analyzer.exported_files = []
1984
+
1964
1985
  # Export charts during optimization if requested
1965
1986
  if create_charts and len(results.trades) > 0:
1966
1987
  if not is_optimization:
1967
1988
  print(f"\n[*] Creating charts: {chart_filename}")
1968
1989
  try:
1969
1990
  # Don't show plots during optimization, just save them
1970
- ChartGenerator.create_all_charts(analyzer, chart_filename, show_plots=not is_optimization)
1991
+ chart_file = ChartGenerator.create_all_charts(
1992
+ analyzer, chart_filename,
1993
+ show_plots=not is_optimization,
1994
+ silent=is_optimization # ← Silent in optimization
1995
+ )
1996
+ analyzer.chart_file = chart_file
1971
1997
  except Exception as e:
1972
1998
  if not is_optimization:
1973
1999
  print(f"[ERROR] Charts failed: {e}")
@@ -1977,7 +2003,11 @@ def run_backtest(strategy_function, config, print_report=True,
1977
2003
  if not is_optimization:
1978
2004
  print(f"\n[*] Exporting: {export_prefix}_*")
1979
2005
  try:
1980
- ResultsExporter.export_all(analyzer, export_prefix)
2006
+ exported = ResultsExporter.export_all(
2007
+ analyzer, export_prefix,
2008
+ silent=is_optimization # ← Silent in optimization
2009
+ )
2010
+ analyzer.exported_files = exported
1981
2011
  except Exception as e:
1982
2012
  if not is_optimization:
1983
2013
  print(f"[ERROR] Export failed: {e}")
@@ -3159,8 +3189,24 @@ def optimize_parameters(base_config, param_grid, strategy_function,
3159
3189
  status_symbol = "✓" if is_valid else "✗"
3160
3190
  status_color = "#00cc00" if is_valid else "#ff6666"
3161
3191
 
3162
- print(f"\n[{idx}/{total_combinations}] {param_str}")
3163
- print("-" * 80)
3192
+ # Print combination header
3193
+ print(f"[{idx}/{total_combinations}] {param_str}")
3194
+ print("-" * 100)
3195
+
3196
+ # Print chart file if created
3197
+ if hasattr(analyzer, 'chart_file') and analyzer.chart_file:
3198
+ print(f"Chart saved: {analyzer.chart_file}")
3199
+
3200
+ # Print exported files
3201
+ if hasattr(analyzer, 'exported_files') and analyzer.exported_files:
3202
+ for file_path, extra_info in analyzer.exported_files:
3203
+ if extra_info:
3204
+ print(f"Exported: {file_path} {extra_info}")
3205
+ else:
3206
+ print(f"Exported: {file_path}")
3207
+
3208
+ # Print metrics with separator
3209
+ print("+" * 100)
3164
3210
  if is_valid:
3165
3211
  print(f" {status_symbol} Return: {analyzer.metrics['total_return']:>7.2f}% | "
3166
3212
  f"Sharpe: {analyzer.metrics['sharpe']:>6.2f} | "
@@ -3170,6 +3216,7 @@ def optimize_parameters(base_config, param_grid, strategy_function,
3170
3216
  f"PF: {analyzer.metrics['profit_factor']:>5.2f}")
3171
3217
  else:
3172
3218
  print(f" {status_symbol} INVALID: {invalid_reason}")
3219
+ print("+" * 100 + "\n")
3173
3220
 
3174
3221
  # Update widget status with last result
3175
3222
  if has_widgets:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ivolatility_backtesting
3
- Version: 1.10.0
3
+ Version: 1.11.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
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "ivolatility_backtesting"
7
- version = "1.10.0"
7
+ version = "1.11.0"
8
8
  description = "A universal backtesting framework for financial strategies using the IVolatility API."
9
9
  readme = "README.md"
10
10
  authors = [