88import os
99import re
1010import unittest
11+ from datetime import datetime , timezone
12+ from pathlib import Path
1113from unittest import TestCase
1214
15+ from investing_algorithm_framework import (
16+ BacktestDateRange ,
17+ DATA_DIRECTORY ,
18+ RESOURCE_DIRECTORY ,
19+ SnapshotInterval ,
20+ create_app ,
21+ )
22+
1323
1424def extract_python_code_blocks_from_readme (readme_path : str ) -> list [str ]:
1525 """
@@ -56,6 +66,19 @@ def extract_main_example_from_readme(readme_path: str) -> str:
5666 )
5767
5868
69+ def prepare_readme_example_for_test (main_example : str ) -> str :
70+ """Adapt the README strategy to the compact offline test fixture set."""
71+ return (
72+ main_example
73+ .replace ('symbols = ["BTC", "ETH"]' , 'symbols = ["BTC", "DOT"]' )
74+ .replace (
75+ 'identifier="ETH_ohlcv", symbol="ETH/EUR"' ,
76+ 'identifier="DOT_ohlcv", symbol="DOT/EUR"' ,
77+ )
78+ .replace ('symbol="ETH"' , 'symbol="DOT"' )
79+ )
80+
81+
5982class TestReadmeExample (TestCase ):
6083 """
6184 Test class to verify the README example implementation works correctly.
@@ -71,6 +94,9 @@ def setUp(self):
7194 os .path .dirname (os .path .dirname (os .path .dirname (__file__ ))),
7295 'README.md'
7396 )
97+ self .resource_directory = str (
98+ Path (__file__ ).parent .parent / 'resources'
99+ )
74100
75101 def test_readme_code_can_be_extracted (self ):
76102 """README.md exists and contains extractable Python code blocks."""
@@ -135,6 +161,45 @@ def test_readme_strategy_class_can_be_loaded(self):
135161 # Verify stop losses are defined
136162 self .assertGreater (len (cls .stop_losses ), 0 )
137163
164+ def test_readme_strategy_runs_fast_vector_backtest_with_offline_data (self ):
165+ """The README strategy runs using only compact offline test data."""
166+ main_example = extract_main_example_from_readme (self .readme_path )
167+ class_code = prepare_readme_example_for_test (main_example )
168+
169+ namespace = {}
170+ exec (class_code , namespace )
171+ strategy_class = namespace ['RSIEMACrossoverStrategy' ]
172+
173+ app = create_app (
174+ name = "ReadmeExampleTest" ,
175+ config = {
176+ RESOURCE_DIRECTORY : self .resource_directory ,
177+ DATA_DIRECTORY : "test_data/ohlcv" ,
178+ },
179+ )
180+ app .add_market (
181+ market = "BITVAVO" , trading_symbol = "EUR" , initial_balance = 1000
182+ )
183+
184+ strategy = strategy_class (algorithm_id = "readme-example-test" )
185+ backtest = app .run_vector_backtest (
186+ initial_amount = 1000 ,
187+ backtest_date_range = BacktestDateRange (
188+ start_date = datetime (2023 , 9 , 1 , tzinfo = timezone .utc ),
189+ end_date = datetime (2023 , 11 , 15 , tzinfo = timezone .utc ),
190+ ),
191+ strategy = strategy ,
192+ snapshot_interval = SnapshotInterval .DAILY ,
193+ risk_free_rate = 0.027 ,
194+ trading_symbol = "EUR" ,
195+ market = "BITVAVO" ,
196+ use_checkpoints = False ,
197+ )
198+
199+ self .assertIsNotNone (backtest )
200+ self .assertEqual (len (backtest .get_all_backtest_runs ()), 1 )
201+ self .assertEqual (len (backtest .get_all_backtest_metrics ()), 1 )
202+
138203
139204if __name__ == "__main__" :
140205 unittest .main ()
0 commit comments