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,8 @@ 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+ with self .assertWarns (UserWarning ):
1029+ ubtc_bt = FractionalBacktest (BTCUSD ['2015' :], SmaCross , fractional_unit = 1 / 1e6 , cash = 100 )
10241030 stats = ubtc_bt .run (fast = 2 , slow = 3 )
10251031 self .assertEqual (stats ['# Trades' ], 41 )
10261032 trades = stats ['_trades' ]
@@ -1036,7 +1042,8 @@ def test_MultiBacktest(self):
10361042 with self .subTest (start_method = start_method ), \
10371043 patch (backtesting , 'Pool' , mp .get_context (start_method ).Pool ):
10381044 start_time = time .monotonic ()
1039- btm = MultiBacktest ([GOOG , EURUSD , BTCUSD ], SmaCross , cash = 100_000 )
1045+ btm = MultiBacktest ([GOOG , EURUSD , BTCUSD ], SmaCross , cash = 100_000 ,
1046+ finalize_trades = True )
10401047 res = btm .run (fast = 2 )
10411048 self .assertIsInstance (res , pd .DataFrame )
10421049 self .assertEqual (res .columns .tolist (), [0 , 1 , 2 ])
@@ -1096,7 +1103,7 @@ def next(self):
10961103 def test_indicators_picklable (self ):
10971104 bt = Backtest (SHORT_DATA , SmaCross )
10981105 with ProcessPoolExecutor () as executor :
1099- stats = executor .submit (Backtest .run , bt ).result ()
1106+ stats = executor .submit (_Backtest .run , bt ).result ()
11001107 assert stats ._strategy ._indicators [0 ]._opts , '._opts and .name were not unpickled'
11011108 bt .plot (results = stats , resample = '2D' , open_browser = False )
11021109
@@ -1111,15 +1118,16 @@ def test_examples(self):
11111118 examples = glob (os .path .join (self .DOCS_DIR , 'examples' , '*.py' ))
11121119 self .assertGreaterEqual (len (examples ), 4 )
11131120 with chdir (gettempdir ()), \
1114- patch (backtesting , 'Pool' , mp .get_context ('fork' ).Pool ):
1121+ patch (backtesting , 'Pool' , mp .get_context ('fork' ).Pool ), \
1122+ self .assertWarnsRegex (UserWarning , 'finalize_trades=True' ):
11151123 for file in examples :
11161124 with self .subTest (example = os .path .basename (file )):
11171125 run_path (file )
11181126
11191127 def test_backtest_run_docstring_contains_stats_keys (self ):
11201128 stats = Backtest (SHORT_DATA , SmaCross ).run ()
11211129 for key in stats .index :
1122- self .assertIn (key , Backtest .run .__doc__ )
1130+ self .assertIn (key , _Backtest .run .__doc__ )
11231131
11241132 def test_readme_contains_stats_keys (self ):
11251133 with open (os .path .join (os .path .dirname (__file__ ),
@@ -1141,7 +1149,8 @@ def next(self):
11411149 df = pd .DataFrame ({'Open' : arr , 'High' : arr , 'Low' : arr , 'Close' : arr })
11421150 with self .assertWarnsRegex (UserWarning , 'index is not datetime' ):
11431151 bt = Backtest (df , S , cash = 100 , trade_on_close = True )
1144- self .assertEqual (bt .run ()._trades ['ExitPrice' ][0 ], 50 )
1152+ with self .assertWarnsRegex (UserWarning , 'margin' ):
1153+ self .assertEqual (bt .run ()._trades ['ExitPrice' ][0 ], 50 )
11451154
11461155 def test_stats_annualized (self ):
11471156 stats = Backtest (GOOG .resample ('W' ).agg (OHLCV_AGG ), SmaCross ).run ()
0 commit comments