66import unittest
77from concurrent .futures .process import ProcessPoolExecutor
88from contextlib import contextmanager
9+ from functools import partial
910from glob import glob
1011from runpy import run_path
1112from tempfile import NamedTemporaryFile , gettempdir
1516import pandas as pd
1617from pandas .testing import assert_frame_equal
1718
18- from backtesting import Backtest , Strategy
19+ from backtesting import Backtest as _Backtest , Strategy
1920from backtesting ._stats import compute_drawdown_duration_peaks
2021from backtesting ._util import _Array , _as_str , _Indicator , patch , try_
2122from backtesting .lib import (
3536
3637SHORT_DATA = GOOG .iloc [:20 ] # Short data for fast tests with no indicator lag
3738
39+ # Avoid the 'Some trades remain open' warning in many tests
40+ Backtest = partial (_Backtest , finalize_trades = True )
41+
3842
3943@contextmanager
4044def _tempfile ():
@@ -591,7 +595,7 @@ def test_optimize(self):
591595 res = bt .optimize (** OPT_PARAMS )
592596 self .assertIsInstance (res , pd .Series )
593597
594- default_maximize = inspect .signature (Backtest .optimize ).parameters ['maximize' ].default
598+ default_maximize = inspect .signature (bt .optimize ).parameters ['maximize' ].default
595599 res2 = bt .optimize (** OPT_PARAMS , maximize = lambda s : s [default_maximize ])
596600 self .assertDictEqual (res .filter (regex = '^[^_]' ).fillna (- 1 ).to_dict (),
597601 res2 .filter (regex = '^[^_]' ).fillna (- 1 ).to_dict ())
@@ -999,7 +1003,8 @@ def init(self):
9991003 self .set_signal (self .data .Close > sma ,
10001004 self .data .Close < sma )
10011005
1002- stats = Backtest (GOOG , S ).run ()
1006+ with self .assertWarnsRegex (UserWarning , 'margin' ):
1007+ stats = Backtest (GOOG , S ).run ()
10031008 self .assertIn (stats ['# Trades' ], (1179 , 1180 )) # varies on different archs?
10041009
10051010 def test_TrailingStrategy (self ):
@@ -1020,7 +1025,9 @@ def next(self):
10201025 self .assertEqual (stats ['# Trades' ], 56 )
10211026
10221027 def test_FractionalBacktest (self ):
1023- ubtc_bt = FractionalBacktest (BTCUSD ['2015' :], SmaCross , fractional_unit = 1 / 1e6 , cash = 100 )
1028+ ubtc_bt = FractionalBacktest (
1029+ BTCUSD ['2015' :], SmaCross , fractional_unit = 1 / 1e6 , cash = 100 ,
1030+ finalize_trades = True )
10241031 stats = ubtc_bt .run (fast = 2 , slow = 3 )
10251032 self .assertEqual (stats ['# Trades' ], 41 )
10261033 trades = stats ['_trades' ]
@@ -1036,7 +1043,8 @@ def test_MultiBacktest(self):
10361043 with self .subTest (start_method = start_method ), \
10371044 patch (backtesting , 'Pool' , mp .get_context (start_method ).Pool ):
10381045 start_time = time .monotonic ()
1039- btm = MultiBacktest ([GOOG , EURUSD , BTCUSD ], SmaCross , cash = 100_000 )
1046+ btm = MultiBacktest ([GOOG , EURUSD , BTCUSD ], SmaCross , cash = 100_000 ,
1047+ finalize_trades = True )
10401048 res = btm .run (fast = 2 )
10411049 self .assertIsInstance (res , pd .DataFrame )
10421050 self .assertEqual (res .columns .tolist (), [0 , 1 , 2 ])
@@ -1096,7 +1104,7 @@ def next(self):
10961104 def test_indicators_picklable (self ):
10971105 bt = Backtest (SHORT_DATA , SmaCross )
10981106 with ProcessPoolExecutor () as executor :
1099- stats = executor .submit (Backtest .run , bt ).result ()
1107+ stats = executor .submit (_Backtest .run , bt ).result ()
11001108 assert stats ._strategy ._indicators [0 ]._opts , '._opts and .name were not unpickled'
11011109 bt .plot (results = stats , resample = '2D' , open_browser = False )
11021110
@@ -1111,15 +1119,16 @@ def test_examples(self):
11111119 examples = glob (os .path .join (self .DOCS_DIR , 'examples' , '*.py' ))
11121120 self .assertGreaterEqual (len (examples ), 4 )
11131121 with chdir (gettempdir ()), \
1114- patch (backtesting , 'Pool' , mp .get_context ('fork' ).Pool ):
1122+ patch (backtesting , 'Pool' , mp .get_context ('fork' ).Pool ), \
1123+ self .assertWarnsRegex (UserWarning , 'finalize_trades=True' ):
11151124 for file in examples :
11161125 with self .subTest (example = os .path .basename (file )):
11171126 run_path (file )
11181127
11191128 def test_backtest_run_docstring_contains_stats_keys (self ):
11201129 stats = Backtest (SHORT_DATA , SmaCross ).run ()
11211130 for key in stats .index :
1122- self .assertIn (key , Backtest .run .__doc__ )
1131+ self .assertIn (key , _Backtest .run .__doc__ )
11231132
11241133 def test_readme_contains_stats_keys (self ):
11251134 with open (os .path .join (os .path .dirname (__file__ ),
@@ -1141,7 +1150,8 @@ def next(self):
11411150 df = pd .DataFrame ({'Open' : arr , 'High' : arr , 'Low' : arr , 'Close' : arr })
11421151 with self .assertWarnsRegex (UserWarning , 'index is not datetime' ):
11431152 bt = Backtest (df , S , cash = 100 , trade_on_close = True )
1144- self .assertEqual (bt .run ()._trades ['ExitPrice' ][0 ], 50 )
1153+ with self .assertWarnsRegex (UserWarning , 'margin' ):
1154+ self .assertEqual (bt .run ()._trades ['ExitPrice' ][0 ], 50 )
11451155
11461156 def test_stats_annualized (self ):
11471157 stats = Backtest (GOOG .resample ('W' ).agg (OHLCV_AGG ), SmaCross ).run ()
0 commit comments