@@ -254,10 +254,12 @@ def _initialize_app_for_backtest(
254
254
before running a backtest or a set of backtests and should be called
255
255
once.
256
256
257
- :param backtest_date_range: instance of BacktestDateRange
258
- :param pending_order_check_interval: The interval at which to check
259
- pending orders (e.g. 1h, 1d, 1w)
260
- :return: None
257
+ Args:
258
+ backtest_date_range: instance of BacktestDateRange
259
+ pending_order_check_interval: The interval at which to check
260
+ pending orders (e.g. 1h, 1d, 1w)
261
+
262
+ Return None
261
263
"""
262
264
# Set all config vars for backtesting
263
265
configuration_service = self .container .configuration_service ()
@@ -275,7 +277,18 @@ def _initialize_app_for_backtest(
275
277
# Create resource dir if not exits
276
278
self ._create_resource_directory_if_not_exists ()
277
279
278
- def _initialize_algorithm_for_backtest (self , algorithm ):
280
+ def _create_backtest_database_if_not_exists (self ):
281
+ """
282
+ Create the backtest database if it does not exist. This method
283
+ should be called before running a backtest for an algorithm.
284
+ It creates the database if it does not exist.
285
+
286
+ Args:
287
+ None
288
+
289
+ Returns
290
+ None
291
+ """
279
292
configuration_service = self .container .configuration_service ()
280
293
resource_dir = configuration_service .config [RESOURCE_DIRECTORY ]
281
294
@@ -301,15 +314,27 @@ def _initialize_algorithm_for_backtest(self, algorithm):
301
314
setup_sqlalchemy (self )
302
315
create_all_tables ()
303
316
304
- # Override the MarketDataSourceService service with the backtest
305
- # market data source service equivalent. Additionally, convert the
306
- # market data sources to backtest market data sources
307
- # Get all market data source services
308
- market_data_sources = self ._market_data_source_service \
317
+ def _initialize_backtest_data_sources (self , algorithm ):
318
+ """
319
+ Initialize the backtest data sources for the algorithm. This method
320
+ should be called before running a backtest. It initializes the
321
+ backtest data sources for the algorithm. It takes all registered
322
+ data sources and converts them to backtest equivalents
323
+
324
+ Args:
325
+ algorithm: The algorithm to initialize for backtesting
326
+
327
+ Returns
328
+ None
329
+ """
330
+
331
+ market_data_sources = self ._market_data_source_service \
309
332
.get_market_data_sources ()
333
+ backtest_market_data_sources = []
310
334
311
335
if algorithm .data_sources is not None \
312
336
and len (algorithm .data_sources ) > 0 :
337
+
313
338
for data_source in algorithm .data_sources :
314
339
self .add_market_data_source (data_source )
315
340
@@ -324,16 +349,36 @@ def _initialize_algorithm_for_backtest(self, algorithm):
324
349
if market_data_source is not None :
325
350
market_data_source .config = self .config
326
351
327
- self .container .market_data_source_service .override (
328
- BacktestMarketDataSourceService (
329
- market_data_sources = backtest_market_data_sources ,
330
- market_service = self .container .market_service (),
331
- market_credential_service = self .container
332
- .market_credential_service (),
333
- configuration_service = self .container
334
- .configuration_service (),
335
- )
352
+ # Override the market data source service with the backtest market
353
+ # data source service
354
+ self .container .market_data_source_service .override (
355
+ BacktestMarketDataSourceService (
356
+ market_data_sources = backtest_market_data_sources ,
357
+ market_service = self .container .market_service (),
358
+ market_credential_service = self .container
359
+ .market_credential_service (),
360
+ configuration_service = self .container
361
+ .configuration_service (),
336
362
)
363
+ )
364
+
365
+ # Set all data sources to the algorithm
366
+ algorithm .add_data_sources (backtest_market_data_sources )
367
+
368
+ def _initialize_algorithm_for_backtest (self , algorithm ):
369
+ """
370
+ Function to initialize the algorithm for backtesting. This method
371
+ should be called before running a backtest. It initializes the
372
+ all data sources to backtest data sources and overrides the services
373
+ with the backtest services equivalents.
374
+
375
+ Args:
376
+ algorithm: The algorithm to initialize for backtesting
377
+
378
+ Return None
379
+ """
380
+ self ._create_backtest_database_if_not_exists ()
381
+ self ._initialize_backtest_data_sources (algorithm )
337
382
338
383
# Override the portfolio service with the backtest portfolio service
339
384
self .container .portfolio_service .override (
@@ -385,7 +430,6 @@ def _initialize_algorithm_for_backtest(self, algorithm):
385
430
market_credential_service = self .container .market_credential_service ()
386
431
market_data_source_service = \
387
432
self .container .market_data_source_service ()
388
-
389
433
# Initialize all services in the algorithm
390
434
algorithm .initialize_services (
391
435
configuration_service = self .container .configuration_service (),
@@ -444,17 +488,19 @@ def run(
444
488
raises an OperationalException. Then it initializes the algorithm
445
489
with the services and the configuration.
446
490
447
- After the algorithm is initialized, it initializes the app and starts
448
- the algorithm. If the app is running in stateless mode, it handles the
491
+ If the app is running in stateless mode, it handles the
449
492
payload. If the app is running in web mode, it starts the web app in a
450
493
separate thread.
451
494
452
- :param payload: The payload to handle if the app is running in
453
- stateless mode
454
- :param number_of_iterations: The number of iterations to run the
455
- algorithm for
456
- :param sync: Whether to sync the portfolio with the exchange
457
- :return: None
495
+ Args:
496
+ payload: The payload to handle if the app is running in
497
+ stateless mode
498
+ number_of_iterations: The number of iterations to run the
499
+ algorithm for
500
+ sync: Whether to sync the portfolio with the exchange
501
+
502
+ Returns:
503
+ None
458
504
"""
459
505
460
506
# Run all on_initialize hooks
@@ -676,21 +722,21 @@ def run_backtest(
676
722
Run a backtest for an algorithm. This method should be called when
677
723
running a backtest.
678
724
679
- :param algorithm: The algorithm to run a backtest for (instance of
680
- Algorithm)
681
- :param backtest_date_range: The date range to run the backtest for
682
- (instance of BacktestDateRange)
683
- :param pending_order_check_interval: The interval at which to check
684
- pending orders
685
- :param output_directory: The directory to write the backtest report to
686
- :return: Instance of BacktestReport
725
+ Args:
726
+ algorithm: The algorithm to run a backtest for (instance of
727
+ Algorithm)
728
+ backtest_date_range: The date range to run the backtest for
729
+ (instance of BacktestDateRange)
730
+ pending_order_check_interval: The interval at which to check
731
+ pending orders
732
+ output_directory: The directory to write the backtest report to
733
+
734
+ Returns:
735
+ Instance of BacktestReport
687
736
"""
688
737
logger .info ("Initializing backtest" )
689
738
self .algorithm = algorithm
690
739
691
- market_data_sources = self ._market_data_source_service \
692
- .get_market_data_sources ()
693
-
694
740
self ._initialize_app_for_backtest (
695
741
backtest_date_range = backtest_date_range ,
696
742
pending_order_check_interval = pending_order_check_interval ,
0 commit comments