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.
- {ivolatility_backtesting-1.10.0 → ivolatility_backtesting-1.11.0}/PKG-INFO +1 -1
- {ivolatility_backtesting-1.10.0 → ivolatility_backtesting-1.11.0}/ivolatility_backtesting/__init__.py +4 -2
- {ivolatility_backtesting-1.10.0 → ivolatility_backtesting-1.11.0}/ivolatility_backtesting/ivolatility_backtesting.py +62 -15
- {ivolatility_backtesting-1.10.0 → ivolatility_backtesting-1.11.0}/ivolatility_backtesting.egg-info/PKG-INFO +1 -1
- {ivolatility_backtesting-1.10.0 → ivolatility_backtesting-1.11.0}/pyproject.toml +1 -1
- {ivolatility_backtesting-1.10.0 → ivolatility_backtesting-1.11.0}/LICENSE +0 -0
- {ivolatility_backtesting-1.10.0 → ivolatility_backtesting-1.11.0}/README.md +0 -0
- {ivolatility_backtesting-1.10.0 → ivolatility_backtesting-1.11.0}/ivolatility_backtesting.egg-info/SOURCES.txt +0 -0
- {ivolatility_backtesting-1.10.0 → ivolatility_backtesting-1.11.0}/ivolatility_backtesting.egg-info/dependency_links.txt +0 -0
- {ivolatility_backtesting-1.10.0 → ivolatility_backtesting-1.11.0}/ivolatility_backtesting.egg-info/requires.txt +0 -0
- {ivolatility_backtesting-1.10.0 → ivolatility_backtesting-1.11.0}/ivolatility_backtesting.egg-info/top_level.txt +0 -0
- {ivolatility_backtesting-1.10.0 → ivolatility_backtesting-1.11.0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ivolatility_backtesting
|
|
3
|
-
Version: 1.
|
|
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
|
-
|
|
1630
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1815
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
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(
|
|
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
|
-
|
|
3163
|
-
print("
|
|
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.
|
|
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.
|
|
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 = [
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|