ziplime 0.1.11__tar.gz

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.
Files changed (47) hide show
  1. ziplime-0.1.11/PKG-INFO +56 -0
  2. ziplime-0.1.11/README.md +36 -0
  3. ziplime-0.1.11/pyproject.toml +24 -0
  4. ziplime-0.1.11/ziplime/__init__.py +0 -0
  5. ziplime-0.1.11/ziplime/__main__.py +507 -0
  6. ziplime-0.1.11/ziplime/algorithm.py +2342 -0
  7. ziplime-0.1.11/ziplime/config/__init__.py +0 -0
  8. ziplime-0.1.11/ziplime/config/register_bundles.py +25 -0
  9. ziplime-0.1.11/ziplime/constants/__init__.py +0 -0
  10. ziplime-0.1.11/ziplime/constants/bundles.py +1 -0
  11. ziplime-0.1.11/ziplime/constants/default_columns.py +17 -0
  12. ziplime-0.1.11/ziplime/constants/fundamental_data.py +57 -0
  13. ziplime-0.1.11/ziplime/data/__init__.py +0 -0
  14. ziplime-0.1.11/ziplime/data/abstract_data_bundle.py +15 -0
  15. ziplime-0.1.11/ziplime/data/abstract_fundamendal_data_provider.py +18 -0
  16. ziplime-0.1.11/ziplime/data/abstract_historical_market_data_provider.py +15 -0
  17. ziplime-0.1.11/ziplime/data/abstract_live_market_data_provider.py +16 -0
  18. ziplime-0.1.11/ziplime/data/bcolz_daily_bars.py +154 -0
  19. ziplime-0.1.11/ziplime/data/bcolz_minute_bars.py +1323 -0
  20. ziplime-0.1.11/ziplime/data/bundles/__init__.py +30 -0
  21. ziplime-0.1.11/ziplime/data/bundles/core.py +690 -0
  22. ziplime-0.1.11/ziplime/data/bundles/lime.py +202 -0
  23. ziplime-0.1.11/ziplime/data/data_portal.py +1238 -0
  24. ziplime-0.1.11/ziplime/data/data_portal_live.py +86 -0
  25. ziplime-0.1.11/ziplime/data/history_loader.py +570 -0
  26. ziplime-0.1.11/ziplime/data/lime_data_provider.py +255 -0
  27. ziplime-0.1.11/ziplime/data/providers/__init__.py +0 -0
  28. ziplime-0.1.11/ziplime/data/providers/fundamental_data/__init__.py +0 -0
  29. ziplime-0.1.11/ziplime/data/providers/fundamental_data/limex_hub_fundamental_data_provider.py +143 -0
  30. ziplime-0.1.11/ziplime/data/providers/historical_market_data/__init__.py +0 -0
  31. ziplime-0.1.11/ziplime/data/providers/historical_market_data/limex_hub_historical_market_data_provider.py +97 -0
  32. ziplime-0.1.11/ziplime/data/providers/live_market_data/__init__.py +0 -0
  33. ziplime-0.1.11/ziplime/data/providers/live_market_data/lime_trader_sdk_live_market_data_provider.py +77 -0
  34. ziplime-0.1.11/ziplime/data/storages/__init__.py +0 -0
  35. ziplime-0.1.11/ziplime/data/storages/bcolz_data_bundle.py +690 -0
  36. ziplime-0.1.11/ziplime/domain/__init__.py +0 -0
  37. ziplime-0.1.11/ziplime/domain/column_specification.py +11 -0
  38. ziplime-0.1.11/ziplime/domain/lime_quote.py +9 -0
  39. ziplime-0.1.11/ziplime/finance/__init__.py +0 -0
  40. ziplime-0.1.11/ziplime/finance/blotter/__init__.py +0 -0
  41. ziplime-0.1.11/ziplime/finance/blotter/lime_trader_sdk_blotter.py +429 -0
  42. ziplime-0.1.11/ziplime/utils/__init__.py +0 -0
  43. ziplime-0.1.11/ziplime/utils/bundle_utils.py +59 -0
  44. ziplime-0.1.11/ziplime/utils/calendar_utils.py +20 -0
  45. ziplime-0.1.11/ziplime/utils/data.py +68 -0
  46. ziplime-0.1.11/ziplime/utils/paths.py +213 -0
  47. ziplime-0.1.11/ziplime/utils/run_algo.py +587 -0
@@ -0,0 +1,56 @@
1
+ Metadata-Version: 2.1
2
+ Name: ziplime
3
+ Version: 0.1.11
4
+ Summary:
5
+ Author: Lime Financial
6
+ Author-email: support@lime.co
7
+ Requires-Python: >=3.12,<4.0
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: Programming Language :: Python :: 3.12
10
+ Classifier: Programming Language :: Python :: 3.13
11
+ Requires-Dist: dask (>=2024.9.1,<2025.0.0)
12
+ Requires-Dist: joblib (>=1.4.2,<2.0.0)
13
+ Requires-Dist: lime-trader-sdk (>=0.3.9,<0.4.0)
14
+ Requires-Dist: limexhub (>=0.1.27,<0.2.0)
15
+ Requires-Dist: pygments (>=2.18.0,<3.0.0)
16
+ Requires-Dist: setuptools (>=72.1.0,<73.0.0)
17
+ Requires-Dist: zipline-reloaded (==3.1)
18
+ Description-Content-Type: text/markdown
19
+
20
+ # ziplime
21
+
22
+ Zipline wrapper which enables using Lime data for backtesting
23
+
24
+ ## Installation
25
+
26
+ ```Bash
27
+ poetry add ziplime
28
+ ```
29
+
30
+ ## Usage
31
+
32
+ You can find usage examples below. All commands supported by `zipline` are also supported by `ziplime` with extended
33
+ list of parameters for easier usage.
34
+
35
+ ### Data ingestion
36
+
37
+ Data ingestion works by first fetching historical data and then and then running live data fetch in the background.
38
+
39
+ Difference from original zipline:
40
+
41
+ - `--start-date` and `--end-date` parameters - used to fetch bundle data only for specific date period
42
+ - `--symbols` parameter - specifies symbols to fetch data for directly in the command
43
+ - Running live data fetch in the background
44
+
45
+ Example:
46
+
47
+ Ingest data:
48
+ ```Bash
49
+ poetry run python -m ziplime ingest -b lime --period day --start-date 2024-06-01 --end-date 2024-07-31 --symbols AAPL,TSLA,AMZN
50
+ ```
51
+ Run strategy
52
+ ```Bash
53
+ poetry run python -m ziplime run -b lime --start 2024-06-01 --end 2024-07-31 --data-frequency daily --capital-base 100000 --no-benchmark -f test.py
54
+ ```
55
+
56
+
@@ -0,0 +1,36 @@
1
+ # ziplime
2
+
3
+ Zipline wrapper which enables using Lime data for backtesting
4
+
5
+ ## Installation
6
+
7
+ ```Bash
8
+ poetry add ziplime
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ You can find usage examples below. All commands supported by `zipline` are also supported by `ziplime` with extended
14
+ list of parameters for easier usage.
15
+
16
+ ### Data ingestion
17
+
18
+ Data ingestion works by first fetching historical data and then and then running live data fetch in the background.
19
+
20
+ Difference from original zipline:
21
+
22
+ - `--start-date` and `--end-date` parameters - used to fetch bundle data only for specific date period
23
+ - `--symbols` parameter - specifies symbols to fetch data for directly in the command
24
+ - Running live data fetch in the background
25
+
26
+ Example:
27
+
28
+ Ingest data:
29
+ ```Bash
30
+ poetry run python -m ziplime ingest -b lime --period day --start-date 2024-06-01 --end-date 2024-07-31 --symbols AAPL,TSLA,AMZN
31
+ ```
32
+ Run strategy
33
+ ```Bash
34
+ poetry run python -m ziplime run -b lime --start 2024-06-01 --end 2024-07-31 --data-frequency daily --capital-base 100000 --no-benchmark -f test.py
35
+ ```
36
+
@@ -0,0 +1,24 @@
1
+ [tool.poetry]
2
+ name = "ziplime"
3
+ version = "0.1.11"
4
+ description = ""
5
+ authors = ["Lime Financial <support@lime.co>"]
6
+ readme = "README.md"
7
+ packages = [{include = "ziplime"}]
8
+
9
+ [tool.poetry.dependencies]
10
+ python = "^3.12"
11
+ zipline-reloaded = "3.1"
12
+ dask = "^2024.9.1"
13
+ setuptools = "^72.1.0"
14
+ lime-trader-sdk = "^0.3.9"
15
+ limexhub = "^0.1.27"
16
+ joblib = "^1.4.2"
17
+ pygments = "^2.18.0"
18
+
19
+ [tool.poetry.scripts]
20
+ weather = "ziplime.cli:cli"
21
+
22
+ [build-system]
23
+ requires = ["poetry-core"]
24
+ build-backend = "poetry.core.masonry.api"
File without changes
@@ -0,0 +1,507 @@
1
+ import datetime
2
+ import logging
3
+ import os
4
+ from functools import partial
5
+
6
+ import pandas as pd
7
+ from zipline.__main__ import ipython_only
8
+
9
+ from zipline.utils.calendar_utils import get_calendar
10
+ from zipline.utils.cli import Date
11
+
12
+ from ziplime.constants.default_columns import DEFAULT_COLUMNS, OHLCV_COLUMNS
13
+ from ziplime.constants.fundamental_data import FUNDAMENTAL_DATA_COLUMNS
14
+ from ziplime.data.storages.bcolz_data_bundle import BcolzDataBundle
15
+ from ziplime.utils.run_algo import _run, BenchmarkSpec
16
+
17
+ import click
18
+ import zipline
19
+ from ziplime.data import bundles as bundles_module
20
+
21
+ from click import DateTime
22
+ from lime_trader.models.market import Period
23
+ from zipline.utils.cli import Timestamp
24
+ from zipline.utils.paths import data_root
25
+
26
+ from ziplime.config.register_bundles import register_lime_symbol_list_equities_bundle
27
+
28
+ from zipline import __main__ as zipline__main__
29
+ from zipline.utils.run_algo import load_extensions
30
+ from zipline.extensions import create_args
31
+
32
+ from ziplime.data.bcolz_daily_bars import ZiplimeBcolzDailyBarWriter
33
+ from ziplime.data.bcolz_minute_bars import ZiplimeBcolzMinuteBarWriter
34
+ from ziplime.utils.bundle_utils import register_default_bundles, get_historical_market_data_provider, \
35
+ get_fundamental_data_provider, get_live_market_data_provider
36
+
37
+ DEFAULT_BUNDLE = "lime"
38
+
39
+
40
+ def validate_date_range(date_min: datetime.datetime, date_max: datetime.datetime):
41
+ def _validate_date_range(ctx, param, value):
42
+ if not date_min < value.replace(tzinfo=datetime.timezone.utc) < date_max:
43
+ raise click.BadParameter(f"Must be between {date_min} and {date_max}")
44
+ return value
45
+
46
+ return _validate_date_range
47
+
48
+
49
+ @click.group()
50
+ @click.option(
51
+ "-e",
52
+ "--extension",
53
+ multiple=True,
54
+ help="File or module path to a zipline extension to load.",
55
+ )
56
+ @click.option(
57
+ "--strict-extensions/--non-strict-extensions",
58
+ is_flag=True,
59
+ help="If --strict-extensions is passed then zipline will not "
60
+ "run if it cannot load all of the specified extensions. "
61
+ "If this is not passed or --non-strict-extensions is passed "
62
+ "then the failure will be logged but execution will continue.",
63
+ )
64
+ @click.option(
65
+ "--default-extension/--no-default-extension",
66
+ is_flag=True,
67
+ default=True,
68
+ help="Don't load the default zipline extension.py file in $ZIPLINE_HOME.",
69
+ )
70
+ @click.option(
71
+ "-x",
72
+ multiple=True,
73
+ help="Any custom command line arguments to define, in key=value form.",
74
+ )
75
+ @click.pass_context
76
+ def main(ctx, extension, strict_extensions, default_extension, x):
77
+ """Top level ziplime entry point."""
78
+ # install a logging handler before performing any other operations
79
+
80
+ logging.basicConfig(
81
+ format="[%(asctime)s-%(levelname)s][%(name)s]\n %(message)s",
82
+ level=logging.INFO,
83
+ datefmt="%Y-%m-%dT%H:%M:%S%z",
84
+ )
85
+
86
+ register_default_bundles()
87
+
88
+ create_args(x, zipline.extension_args)
89
+ load_extensions(
90
+ default_extension,
91
+ extension,
92
+ strict_extensions,
93
+ os.environ,
94
+ )
95
+
96
+
97
+ @main.command(context_settings=dict(
98
+ # ignore_unknown_options=True,
99
+ # allow_extra_args=True,
100
+ ))
101
+ @click.option(
102
+ "-b",
103
+ "--bundle",
104
+ default=DEFAULT_BUNDLE,
105
+ metavar="BUNDLE-NAME",
106
+ show_default=True,
107
+ help="The data bundle to ingest.",
108
+ )
109
+ @click.option(
110
+ "-c",
111
+ "--calendar",
112
+ default="NYSE",
113
+ show_default=True,
114
+ help="Default calendar to use.",
115
+ )
116
+ @click.option('--new-bundle-name', default=None)
117
+ @click.option(
118
+ "--start-date",
119
+ type=DateTime(),
120
+ callback=validate_date_range(date_min=datetime.datetime(year=1800,
121
+ month=1,
122
+ day=1,
123
+ tzinfo=datetime.timezone.utc
124
+ ),
125
+ date_max=datetime.datetime.now(tz=datetime.timezone.utc),
126
+ )
127
+ )
128
+ @click.option(
129
+ "--end-date",
130
+ type=DateTime(),
131
+ callback=validate_date_range(date_min=datetime.datetime(year=1800,
132
+ month=1,
133
+ day=1,
134
+ tzinfo=datetime.timezone.utc
135
+ ),
136
+ date_max=datetime.datetime.now(tz=datetime.timezone.utc),
137
+ )
138
+ )
139
+ @click.option(
140
+ "--period",
141
+ default="day",
142
+ type=click.Choice(['minute', 'hour', 'day', 'week', 'month', 'quarter'], case_sensitive=False),
143
+ )
144
+ @click.option("-s", '--symbols')
145
+ @click.option('--fundamental-data')
146
+ @click.option(
147
+ "--assets-version",
148
+ type=int,
149
+ multiple=True,
150
+ help="Version of the assets db to which to downgrade.",
151
+ )
152
+ @click.option(
153
+ "--show-progress/--no-show-progress",
154
+ default=True,
155
+ help="Print progress information to the terminal.",
156
+ )
157
+ @click.option(
158
+ "--historical-market-data-provider",
159
+ default="limex-hub",
160
+ help="Market data provider for historical data",
161
+ show_default=True,
162
+ )
163
+ @click.option(
164
+ "--fundamental-data-provider",
165
+ default="limex-hub",
166
+ help="Fundamental data provider",
167
+ show_default=True,
168
+ )
169
+ @click.pass_context
170
+ def ingest(ctx, bundle, new_bundle_name, start_date, end_date, period, symbols, fundamental_data, show_progress,
171
+ assets_version, calendar,
172
+ historical_market_data_provider,
173
+ fundamental_data_provider
174
+ ):
175
+ """Top level ziplime entry point."""
176
+ symbols_parsed = symbols.split(',') if symbols else None
177
+ fundamental_data_list = fundamental_data.split(",") if fundamental_data else None
178
+ if new_bundle_name:
179
+ bundle_name = f"{DEFAULT_BUNDLE}-{new_bundle_name}"
180
+ ctx.args = ['-b', new_bundle_name] + ctx.args
181
+ else:
182
+ bundle_name = bundle
183
+ ctx.args = ['-b', bundle] + ctx.args
184
+ # install a logging handler before performing any other operations
185
+ register_lime_symbol_list_equities_bundle(
186
+ bundle_name=bundle_name,
187
+ symbols=symbols_parsed,
188
+ start_session=start_date,
189
+ end_session=end_date,
190
+ period=Period(period),
191
+ calendar_name=calendar,
192
+ fundamental_data_list=fundamental_data_list if fundamental_data_list is not None else [
193
+ col.name for col in
194
+ FUNDAMENTAL_DATA_COLUMNS
195
+ ]
196
+ )
197
+
198
+ new_params = dict(**ctx.params)
199
+
200
+ # clean up lime only params and set new bundle name
201
+ new_params["bundle"] = bundle_name
202
+
203
+ fundamental_data_cols = ([
204
+ col
205
+ for col in FUNDAMENTAL_DATA_COLUMNS
206
+ if col.name in set(fundamental_data_list)
207
+ ]
208
+ if fundamental_data_list is not None
209
+ else DEFAULT_COLUMNS)
210
+ bundles_module.ingest(
211
+ name=bundle_name,
212
+ environ=os.environ,
213
+ timestamp=pd.Timestamp.utcnow(),
214
+ assets_version=assets_version,
215
+ show_progress=show_progress,
216
+ historical_market_data_provider=get_historical_market_data_provider(code=historical_market_data_provider),
217
+ fundamental_data_provider=get_fundamental_data_provider(code=fundamental_data_provider),
218
+ minute_bar_writer_class=ZiplimeBcolzMinuteBarWriter,
219
+ daily_bar_writer_class=BcolzDataBundle,
220
+ fundamental_data_writer_class=BcolzDataBundle,
221
+ market_data_fields=OHLCV_COLUMNS,
222
+ fundamental_data_fields=fundamental_data_cols,
223
+ minute_bar_writer_cols=fundamental_data_cols,
224
+ )
225
+
226
+
227
+ @main.command(context_settings=dict(
228
+ ignore_unknown_options=True,
229
+ allow_extra_args=True,
230
+ ))
231
+ @click.option(
232
+ "-b",
233
+ "--bundle",
234
+ default=DEFAULT_BUNDLE,
235
+ metavar="BUNDLE-NAME",
236
+ show_default=True,
237
+ help="The data bundle to clean.",
238
+ )
239
+ @click.option(
240
+ "-e",
241
+ "--before",
242
+ type=Timestamp(),
243
+ help="Clear all data before TIMESTAMP."
244
+ " This may not be passed with -k / --keep-last",
245
+ )
246
+ @click.option(
247
+ "-a",
248
+ "--after",
249
+ type=Timestamp(),
250
+ help="Clear all data after TIMESTAMP"
251
+ " This may not be passed with -k / --keep-last",
252
+ )
253
+ @click.option(
254
+ "-k",
255
+ "--keep-last",
256
+ type=int,
257
+ metavar="N",
258
+ help="Clear all but the last N downloads."
259
+ " This may not be passed with -e / --before or -a / --after",
260
+ )
261
+ @click.pass_context
262
+ def clean(ctx, bundle, before, after, keep_last):
263
+ """Top level ziplime entry point."""
264
+
265
+ func = getattr(zipline__main__, "clean")
266
+ ctx.forward(func)
267
+
268
+
269
+ @main.command(context_settings=dict(
270
+ ignore_unknown_options=True,
271
+ allow_extra_args=True,
272
+ ))
273
+ @click.pass_context
274
+ def bundles(ctx):
275
+ """Top level ziplime entry point."""
276
+ func = getattr(zipline__main__, "bundles")
277
+ ctx.forward(func)
278
+
279
+
280
+ @main.command()
281
+ @click.option(
282
+ "-f",
283
+ "--algofile",
284
+ default=None,
285
+ type=click.File("r"),
286
+ help="The file that contains the algorithm to run.",
287
+ )
288
+ @click.option(
289
+ "-t",
290
+ "--algotext",
291
+ help="The algorithm script to run.",
292
+ )
293
+ @click.option(
294
+ "-D",
295
+ "--define",
296
+ multiple=True,
297
+ help="Define a name to be bound in the namespace before executing"
298
+ " the algotext. For example '-Dname=value'. The value may be any "
299
+ "python expression. These are evaluated in order so they may refer "
300
+ "to previously defined names.",
301
+ )
302
+ @click.option(
303
+ "--data-frequency",
304
+ type=click.Choice({"daily", "minute"}),
305
+ default="daily",
306
+ show_default=True,
307
+ help="The data frequency of the simulation.",
308
+ )
309
+ @click.option(
310
+ "--capital-base",
311
+ type=float,
312
+ default=10e6,
313
+ show_default=True,
314
+ help="The starting capital for the simulation.",
315
+ )
316
+ @click.option(
317
+ "-b",
318
+ "--bundle",
319
+ default=DEFAULT_BUNDLE,
320
+ metavar="BUNDLE-NAME",
321
+ show_default=True,
322
+ help="The data bundle to use for the simulation.",
323
+ )
324
+ @click.option(
325
+ "--bundle-timestamp",
326
+ type=Timestamp(),
327
+ default=pd.Timestamp.utcnow(),
328
+ show_default=False,
329
+ help="The date to lookup data on or before.\n" "[default: <current-time>]",
330
+ )
331
+ @click.option(
332
+ "-bf",
333
+ "--benchmark-file",
334
+ default=None,
335
+ type=click.Path(exists=True, dir_okay=False, readable=True, path_type=str),
336
+ help="The csv file that contains the benchmark returns",
337
+ )
338
+ @click.option(
339
+ "--benchmark-symbol",
340
+ default=None,
341
+ type=click.STRING,
342
+ help="The symbol of the instrument to be used as a benchmark "
343
+ "(should exist in the ingested bundle)",
344
+ )
345
+ @click.option(
346
+ "--benchmark-sid",
347
+ default=None,
348
+ type=int,
349
+ help="The sid of the instrument to be used as a benchmark "
350
+ "(should exist in the ingested bundle)",
351
+ )
352
+ @click.option(
353
+ "--no-benchmark",
354
+ is_flag=True,
355
+ default=False,
356
+ help="If passed, use a benchmark of zero returns.",
357
+ )
358
+ @click.option(
359
+ "-s",
360
+ "--start",
361
+ type=Date(as_timestamp=True),
362
+ help="The start date of the simulation.",
363
+ )
364
+ @click.option(
365
+ "-e",
366
+ "--end",
367
+ type=Date(as_timestamp=True),
368
+ help="The end date of the simulation.",
369
+ )
370
+ @click.option(
371
+ "-o",
372
+ "--output",
373
+ default="-",
374
+ metavar="FILENAME",
375
+ show_default=True,
376
+ help="The location to write the perf data. If this is '-' the perf will"
377
+ " be written to stdout.",
378
+ )
379
+ @click.option(
380
+ "--trading-calendar",
381
+ metavar="TRADING-CALENDAR",
382
+ default="XNYS",
383
+ help="The calendar you want to use e.g. XLON. XNYS is the default.",
384
+ )
385
+ @click.option(
386
+ "--print-algo/--no-print-algo",
387
+ is_flag=True,
388
+ default=False,
389
+ help="Print the algorithm to stdout.",
390
+ )
391
+ @click.option(
392
+ "--metrics-set",
393
+ default="default",
394
+ help="The metrics set to use. New metrics sets may be registered in your"
395
+ " extension.py.",
396
+ )
397
+ @click.option(
398
+ "--blotter",
399
+ default="default",
400
+ help="The blotter to use.",
401
+ show_default=True,
402
+ )
403
+ @click.option(
404
+ "--broker",
405
+ default=None,
406
+ help="The broker to use for live trading.",
407
+ show_default=True,
408
+ )
409
+ @click.option(
410
+ "--live-market-data-provider",
411
+ default="lime-trader-sdk",
412
+ help="Market data provider for live trading",
413
+ show_default=True,
414
+ )
415
+ @ipython_only(
416
+ click.option(
417
+ "--local-namespace/--no-local-namespace",
418
+ is_flag=True,
419
+ default=None,
420
+ help="Should the algorithm methods be " "resolved in the local namespace.",
421
+ )
422
+ )
423
+ @click.pass_context
424
+ def run(
425
+ ctx,
426
+ algofile,
427
+ algotext,
428
+ define,
429
+ data_frequency,
430
+ capital_base,
431
+ bundle,
432
+ bundle_timestamp,
433
+ benchmark_file,
434
+ benchmark_symbol,
435
+ benchmark_sid,
436
+ no_benchmark,
437
+ start,
438
+ end,
439
+ output,
440
+ trading_calendar,
441
+ print_algo,
442
+ metrics_set,
443
+ local_namespace,
444
+ blotter,
445
+ broker: str | None,
446
+ live_market_data_provider: str,
447
+ ):
448
+ """Run a backtest for the given algorithm."""
449
+ # check that the start and end dates are passed correctly
450
+ if start is None and end is None:
451
+ # check both at the same time to avoid the case where a user
452
+ # does not pass either of these and then passes the first only
453
+ # to be told they need to pass the second argument also
454
+ ctx.fail(
455
+ "must specify dates with '-s' / '--start' and '-e' / '--end'",
456
+ )
457
+ if start is None:
458
+ ctx.fail("must specify a start date with '-s' / '--start'")
459
+ if end is None:
460
+ ctx.fail("must specify an end date with '-e' / '--end'")
461
+
462
+ if (algotext is not None) == (algofile is not None):
463
+ ctx.fail(
464
+ "must specify exactly one of '-f' / "
465
+ "'--algofile' or"
466
+ " '-t' / '--algotext'",
467
+ )
468
+
469
+ trading_calendar = get_calendar(trading_calendar)
470
+
471
+ benchmark_spec = BenchmarkSpec.from_cli_params(
472
+ no_benchmark=no_benchmark,
473
+ benchmark_sid=benchmark_sid,
474
+ benchmark_symbol=benchmark_symbol,
475
+ benchmark_file=benchmark_file,
476
+ )
477
+
478
+ return _run(
479
+ initialize=None,
480
+ handle_data=None,
481
+ before_trading_start=None,
482
+ analyze=None,
483
+ algofile=algofile,
484
+ algotext=algotext,
485
+ defines=define,
486
+ data_frequency=data_frequency,
487
+ capital_base=capital_base,
488
+ bundle=bundle,
489
+ bundle_timestamp=bundle_timestamp,
490
+ start=start,
491
+ end=end,
492
+ output=output,
493
+ trading_calendar=trading_calendar,
494
+ print_algo=print_algo,
495
+ metrics_set=metrics_set,
496
+ local_namespace=local_namespace,
497
+ environ=os.environ,
498
+ blotter=blotter,
499
+ benchmark_spec=benchmark_spec,
500
+ custom_loader=None,
501
+ broker=broker,
502
+ market_data_provider=get_live_market_data_provider(live_market_data_provider)
503
+ )
504
+
505
+
506
+ if __name__ == "__main__":
507
+ main()