lumibot 4.2.4__py3-none-any.whl → 4.2.5__py3-none-any.whl

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 lumibot might be problematic. Click here for more details.

@@ -124,6 +124,17 @@ class Vars:
124
124
 
125
125
 
126
126
  class _Strategy:
127
+ @staticmethod
128
+ def _normalize_backtest_datetime(value):
129
+ """Convert backtest boundary datetimes to the LumiBot default timezone."""
130
+ if value is None:
131
+ return None
132
+ aware = to_datetime_aware(value)
133
+ tzinfo = getattr(aware, "tzinfo", None)
134
+ if tzinfo is not None and tzinfo != LUMIBOT_DEFAULT_PYTZ:
135
+ return aware.astimezone(LUMIBOT_DEFAULT_PYTZ)
136
+ return aware
137
+
127
138
  @property
128
139
  def is_backtesting(self) -> bool:
129
140
  """Boolean flag indicating whether the strategy is running in backtesting mode."""
@@ -1389,8 +1400,8 @@ class _Strategy:
1389
1400
  raise ValueError(f"`optionsource_class` must be a class. You passed in {optionsource_class}")
1390
1401
 
1391
1402
  try:
1392
- backtesting_start = to_datetime_aware(backtesting_start)
1393
- backtesting_end = to_datetime_aware(backtesting_end)
1403
+ backtesting_start = self._normalize_backtest_datetime(backtesting_start)
1404
+ backtesting_end = self._normalize_backtest_datetime(backtesting_end)
1394
1405
  except AttributeError:
1395
1406
  get_logger(__name__).error(
1396
1407
  "`backtesting_start` and `backtesting_end` must be datetime objects. \n"
@@ -1399,6 +1410,9 @@ class _Strategy:
1399
1410
  )
1400
1411
  return None
1401
1412
 
1413
+ get_logger(__name__).info("Backtest start = %s", backtesting_start)
1414
+ get_logger(__name__).info("Backtest end = %s", backtesting_end)
1415
+
1402
1416
  self.verify_backtest_inputs(backtesting_start, backtesting_end)
1403
1417
 
1404
1418
  if not self.IS_BACKTESTABLE:
@@ -1628,8 +1642,8 @@ class _Strategy:
1628
1642
  if not isinstance(backtesting_end, datetime.datetime):
1629
1643
  raise ValueError(f"`backtesting_end` must be a datetime object. You passed in {backtesting_end}")
1630
1644
 
1631
- start_dt = to_datetime_aware(backtesting_start)
1632
- end_dt = to_datetime_aware(backtesting_end)
1645
+ start_dt = cls._normalize_backtest_datetime(backtesting_start)
1646
+ end_dt = cls._normalize_backtest_datetime(backtesting_end)
1633
1647
 
1634
1648
  # Check that backtesting end is after backtesting start
1635
1649
  if end_dt <= start_dt:
@@ -13,8 +13,6 @@ import pandas_market_calendars as mcal
13
13
  from apscheduler.jobstores.memory import MemoryJobStore
14
14
  from apscheduler.schedulers.background import BackgroundScheduler
15
15
  from apscheduler.triggers.cron import CronTrigger
16
- from termcolor import colored
17
-
18
16
  from lumibot.constants import LUMIBOT_DEFAULT_PYTZ
19
17
  from lumibot.entities import Asset, Order
20
18
  from lumibot.entities import Asset
@@ -1166,7 +1164,7 @@ class StrategyExecutor(Thread):
1166
1164
  # For live trading, stop when market closes
1167
1165
  return False
1168
1166
 
1169
- self.strategy.log_message(colored(f"Sleeping for {strategy_sleeptime} seconds", color="blue"))
1167
+ self.strategy.logger.debug("Sleeping for %s seconds", strategy_sleeptime)
1170
1168
 
1171
1169
  # Run process orders at the market close time first (if not continuous market)
1172
1170
  if not is_continuous_market:
@@ -311,7 +311,13 @@ def get_price_data(
311
311
  )
312
312
 
313
313
  if cache_file.exists():
314
- logger.info(f"\nLoading '{datastyle}' pricing data for {asset} / {quote_asset} with '{timespan}' timespan from cache file...")
314
+ logger.debug(
315
+ "\nLoading '%s' pricing data for %s / %s with '%s' timespan from cache file...",
316
+ datastyle,
317
+ asset,
318
+ quote_asset,
319
+ timespan,
320
+ )
315
321
  df_cached = load_cache(cache_file)
316
322
  if df_cached is not None and not df_cached.empty:
317
323
  df_all = df_cached.copy() # Make a copy so we can check the original later for differences
@@ -372,7 +378,7 @@ def get_price_data(
372
378
  )
373
379
  if not missing_dates:
374
380
  if df_all is not None and not df_all.empty:
375
- logger.info("ThetaData cache HIT for %s %s %s (%d rows).", asset, timespan, datastyle, len(df_all))
381
+ logger.debug("ThetaData cache HIT for %s %s %s (%d rows).", asset, timespan, datastyle, len(df_all))
376
382
  # DEBUG-LOG: Cache hit
377
383
  logger.debug(
378
384
  "[THETA][DEBUG][CACHE][HIT] asset=%s timespan=%s datastyle=%s rows=%d start=%s end=%s",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lumibot
3
- Version: 4.2.4
3
+ Version: 4.2.5
4
4
  Summary: Backtesting and Trading Library, Made by Lumiwealth
5
5
  Home-page: https://github.com/Lumiwealth/lumibot
6
6
  Author: Robert Grzesik
@@ -104,10 +104,10 @@ lumibot/example_strategies/test_broker_functions.py,sha256=wnVS-M_OtzMgaXVBgshVE
104
104
  lumibot/resources/ThetaTerminal.jar,sha256=K6GeeFcN8-gvyL2x5iq5pzD79KfPJvMK8iiezi3TmNQ,11834389
105
105
  lumibot/resources/conf.yaml,sha256=rjB9-10JP7saZ_edjX5bQDGfuc3amOQTUUUr-UiMpNA,597
106
106
  lumibot/strategies/__init__.py,sha256=jEZ95K5hG0f595EXYKWwL2_UsnWWk5Pug361PK2My2E,79
107
- lumibot/strategies/_strategy.py,sha256=jfKU4NpYiGJexTEeHz-pi-8NtSdcX1BXBTcjr7wsUuY,110825
107
+ lumibot/strategies/_strategy.py,sha256=wWx2te98kwMTuusioKR24KsKW8Djs3yhOb2nNmvgbiU,111467
108
108
  lumibot/strategies/session_manager.py,sha256=Nze6UYNSPlCsf-tyHvtFqUeL44WSNHjwsKrIepvsyCY,12956
109
109
  lumibot/strategies/strategy.py,sha256=toPeL5oIVWmCxBNcfXqIuTCF_EeCfIVj425PrSYImCo,170021
110
- lumibot/strategies/strategy_executor.py,sha256=IrHwDOu5s3gG65dz7FL-0kllWy7COci7JFyB4iiPUrg,70801
110
+ lumibot/strategies/strategy_executor.py,sha256=AnmXlKD2eMgKXs3TrD1u8T_Zsn_8GnG5KRcM_Pq-JBQ,70749
111
111
  lumibot/tools/__init__.py,sha256=oRRoK2NBkfnc0kueAfY0HrWVKgzRBO1hlglVMR4jr5M,1501
112
112
  lumibot/tools/alpaca_helpers.py,sha256=nhBS-sv28lZfIQ85szC9El8VHLrCw5a5KbsGOOEjm6w,3147
113
113
  lumibot/tools/backtest_cache.py,sha256=A-Juzu0swZI_FP4U7cd7ruYTgJYgV8BPf_WJDI-NtrM,9556
@@ -132,7 +132,7 @@ lumibot/tools/polygon_helper_async.py,sha256=YHDXa9kmkkn8jh7hToY6GP5etyXS9Tj-uky
132
132
  lumibot/tools/polygon_helper_polars_optimized.py,sha256=NaIZ-5Av-G2McPEKHyJ-x65W72W_Agnz4lRgvXfQp8c,30415
133
133
  lumibot/tools/projectx_helpers.py,sha256=EIemLfbG923T_RBV_i6s6A9xgs7dt0et0oCnhFwdWfA,58299
134
134
  lumibot/tools/schwab_helper.py,sha256=CXnYhgsXOIb5MgmIYOp86aLxsBF9oeVrMGrjwl_GEv0,11768
135
- lumibot/tools/thetadata_helper.py,sha256=-FJm_NXSBJoyYLcdNQXGytMbmr-wx7F1gItnRnBUWf0,80072
135
+ lumibot/tools/thetadata_helper.py,sha256=Guutp_2QAZe22_r6pftCojpTb3DpDp4Ul_szf6N7X1I,80152
136
136
  lumibot/tools/types.py,sha256=x-aQBeC6ZTN2-pUyxyo69Q0j5e0c_swdfe06kfrWSVc,1978
137
137
  lumibot/tools/yahoo_helper.py,sha256=htcKKkuktatIckVKfLc_ms0X75mXColysQhrZW244z8,19497
138
138
  lumibot/tools/yahoo_helper_polars_optimized.py,sha256=g9xBN-ReHSW4Aj9EMU_OncBXVS1HpfL8LTHit9ZxFY4,7417
@@ -142,7 +142,7 @@ lumibot/traders/trader.py,sha256=KMif3WoZtnSxA0BzoK3kvkTITNELrDFIortx1BYBv8s,967
142
142
  lumibot/trading_builtins/__init__.py,sha256=vH2QL5zLjL3slfEV1YW-BvQHtEYLCFkIWTZDfh3y8LE,87
143
143
  lumibot/trading_builtins/custom_stream.py,sha256=8_XiPT0JzyXrgnXCXoovGGUrWEfnG4ohIYMPfB_Nook,5264
144
144
  lumibot/trading_builtins/safe_list.py,sha256=IIjZOHSiZYK25A4WBts0oJaZNOJDsjZL65MOSHhE3Ig,1975
145
- lumibot-4.2.4.dist-info/licenses/LICENSE,sha256=fYhGIyxjyNXACgpNQS3xxpxDOaVOWRVxZMCRbsDv8k0,35130
145
+ lumibot-4.2.5.dist-info/licenses/LICENSE,sha256=fYhGIyxjyNXACgpNQS3xxpxDOaVOWRVxZMCRbsDv8k0,35130
146
146
  tests/__init__.py,sha256=3-VoT-nAuqMfwufd4ceN6fXaHl_zCfDCSXJOTp1ywYQ,393
147
147
  tests/conftest.py,sha256=UBw_2fx7r6TZPKus2b1Qxrzmd4bg8EEBnX1vCHUuSVA,3311
148
148
  tests/fixtures.py,sha256=wOHQsh1SGHnXe_PGi6kDWI30CS_Righi7Ig7vwSEKT4,9082
@@ -163,7 +163,7 @@ tests/test_backtesting_broker_await_close.py,sha256=WbehY7E4Qet3_Mo7lpfgjmhtI9pn
163
163
  tests/test_backtesting_broker_time_advance.py,sha256=FCv0nKG8BQlEjNft7kmQYm9M2CsLIZ0b7mWCllOHQxc,6378
164
164
  tests/test_backtesting_crypto_cash_unit.py,sha256=4EO9jVajdZNV0M7zSyp4gpR_msZFoM4x5tb-6g-mHO8,11399
165
165
  tests/test_backtesting_data_source_env.py,sha256=ZzpF42-tMc8qqETuy_nf43UsSZMbHtS_ivH93ZqV5P0,12460
166
- tests/test_backtesting_datetime_normalization.py,sha256=8NjxiZbSIOzE4I2qDwEqkN3M7jnIdTfjPPE2Qp_0ySE,2984
166
+ tests/test_backtesting_datetime_normalization.py,sha256=n1ObwObTI_V4uQOQw_WIii7Ph_OgPZYIZGbx5Jv_19U,3245
167
167
  tests/test_backtesting_flow_control.py,sha256=pBqW-fa-HnZq0apUBltalGMM-vNJ_2A5W2SoJzMK8Mg,7208
168
168
  tests/test_backtesting_multileg_unit.py,sha256=h1DPfVuYXXx-uq6KtUjr6_nasZuXPm_5gFat1XxCKIo,6456
169
169
  tests/test_backtesting_quiet_logs_complete.py,sha256=x-GfOiqkiUu8pYKCzB0UUacn13Nx_cPRth7_jmPY2Y8,14155
@@ -281,7 +281,7 @@ tests/backtest/test_thetadata.py,sha256=xWYfC9C4EhbMDb29qyZWHO3sSWaLIPzzvcMbHCt5
281
281
  tests/backtest/test_thetadata_comprehensive.py,sha256=-gN3xLJcJtlB-k4vlaK82DCZDGDmr0LNZZDzn-aN3l4,26120
282
282
  tests/backtest/test_thetadata_vs_polygon.py,sha256=dZqsrOx3u3cz-1onIO6o5BDRjI1ey7U9vIkZupfXoig,22831
283
283
  tests/backtest/test_yahoo.py,sha256=2FguUTUMC9_A20eqxnZ17rN3tT9n6hyvJHaL98QKpqY,3443
284
- lumibot-4.2.4.dist-info/METADATA,sha256=tTX4FY9DKXc8JjeCMImHK3NgzlR1h_U9dSvQqyOnQ28,12092
285
- lumibot-4.2.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
286
- lumibot-4.2.4.dist-info/top_level.txt,sha256=otUnUjDFVASauEDiTiAzNgMyqQ1B6jjS3QqqP-WSx38,14
287
- lumibot-4.2.4.dist-info/RECORD,,
284
+ lumibot-4.2.5.dist-info/METADATA,sha256=lK1f_O0TcWv79IUVPehgpO2s_dQE1jrsj69_LCqeKM8,12092
285
+ lumibot-4.2.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
286
+ lumibot-4.2.5.dist-info/top_level.txt,sha256=otUnUjDFVASauEDiTiAzNgMyqQ1B6jjS3QqqP-WSx38,14
287
+ lumibot-4.2.5.dist-info/RECORD,,
@@ -3,6 +3,7 @@ from unittest.mock import patch
3
3
 
4
4
  import pytest
5
5
 
6
+ from lumibot.constants import LUMIBOT_DEFAULT_PYTZ
6
7
  from lumibot.strategies import Strategy
7
8
  from lumibot.strategies._strategy import _Strategy
8
9
 
@@ -88,3 +89,6 @@ def test_run_backtest_normalizes_mixed_timezones():
88
89
 
89
90
  assert "start" in captured and captured["start"].tzinfo is not None
90
91
  assert "end" in captured and captured["end"].tzinfo is not None
92
+ assert captured["start"].tzinfo.zone == LUMIBOT_DEFAULT_PYTZ.zone
93
+ assert captured["end"].tzinfo.zone == LUMIBOT_DEFAULT_PYTZ.zone
94
+ assert captured["start"].tzinfo.zone == captured["end"].tzinfo.zone