trendvisdata 1.0.4__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.
- trendvisdata/__init__.py +5 -0
- trendvisdata/chart_data.py +400 -0
- trendvisdata/chart_prep.py +637 -0
- trendvisdata/market_data.py +541 -0
- trendvisdata/sector_mappings.py +666 -0
- trendvisdata/trend.py +316 -0
- trendvisdata/trend_data.py +785 -0
- trendvisdata/trend_params.py +197 -0
- trendvisdata-1.0.4.dist-info/LICENSE +21 -0
- trendvisdata-1.0.4.dist-info/METADATA +29 -0
- trendvisdata-1.0.4.dist-info/RECORD +13 -0
- trendvisdata-1.0.4.dist-info/WHEEL +5 -0
- trendvisdata-1.0.4.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,541 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Data extraction functions
|
|
3
|
+
|
|
4
|
+
"""
|
|
5
|
+
import datetime as dt
|
|
6
|
+
from io import StringIO
|
|
7
|
+
import norgatedata
|
|
8
|
+
import pandas as pd
|
|
9
|
+
import requests
|
|
10
|
+
from pandas.tseries.offsets import BDay
|
|
11
|
+
# from yahoofinancials import YahooFinancials
|
|
12
|
+
import yfinance as yf
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class NorgateExtract():
|
|
16
|
+
"""
|
|
17
|
+
Functions to extract data from Norgate Data
|
|
18
|
+
|
|
19
|
+
"""
|
|
20
|
+
@staticmethod
|
|
21
|
+
def get_norgate_tickers(params: dict) -> dict:
|
|
22
|
+
"""
|
|
23
|
+
Create list of all available Norgate Commodity tickers
|
|
24
|
+
|
|
25
|
+
Returns
|
|
26
|
+
-------
|
|
27
|
+
tickers : List
|
|
28
|
+
Returns a list of ticker codes.
|
|
29
|
+
init_ticker_dict : Dict
|
|
30
|
+
Dictionary of ticker-security name pairs
|
|
31
|
+
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
# Specify Norgate Cash Commodities database and extract data
|
|
35
|
+
databasename = 'Cash Commodities'
|
|
36
|
+
databasecontents = norgatedata.database(databasename)
|
|
37
|
+
|
|
38
|
+
# Create empty dictionary to store tickers
|
|
39
|
+
init_ticker_dict = {}
|
|
40
|
+
|
|
41
|
+
# For each dictionary in the data extract
|
|
42
|
+
for dicto in databasecontents:
|
|
43
|
+
|
|
44
|
+
# Add the symbol and security name to the ticker dict as a
|
|
45
|
+
# key-value pair
|
|
46
|
+
key = dicto['symbol']
|
|
47
|
+
value = dicto['securityname']
|
|
48
|
+
if 'Stocks' not in value:
|
|
49
|
+
init_ticker_dict[key] = value
|
|
50
|
+
|
|
51
|
+
# Specify Norgate Continuous Futures database and extract data
|
|
52
|
+
databasename = 'Continuous Futures'
|
|
53
|
+
databasecontents = norgatedata.database(databasename)
|
|
54
|
+
|
|
55
|
+
# For each dictionary in the data extract
|
|
56
|
+
for dicto in databasecontents:
|
|
57
|
+
|
|
58
|
+
# Add the symbol and security name to the ticker dict as a
|
|
59
|
+
# key-value pair
|
|
60
|
+
key = dicto['symbol']
|
|
61
|
+
value = dicto['securityname']
|
|
62
|
+
|
|
63
|
+
if params['tickers_adjusted']:
|
|
64
|
+
# Only take the back-adjusted tickers
|
|
65
|
+
if '_CCB' in key:
|
|
66
|
+
init_ticker_dict[key] = value
|
|
67
|
+
|
|
68
|
+
else:
|
|
69
|
+
if key.startswith('&') and '_CCB' not in key:
|
|
70
|
+
init_ticker_dict[key] = value
|
|
71
|
+
|
|
72
|
+
# Convert the ticker dict keys into a list
|
|
73
|
+
tickers = list(init_ticker_dict.keys())
|
|
74
|
+
|
|
75
|
+
params['tickers'] = tickers
|
|
76
|
+
params['init_ticker_dict'] = init_ticker_dict
|
|
77
|
+
|
|
78
|
+
return params
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
@classmethod
|
|
82
|
+
def import_norgate(
|
|
83
|
+
cls,
|
|
84
|
+
params: dict,
|
|
85
|
+
tables: dict,
|
|
86
|
+
mappings: dict) -> tuple[dict, dict, dict]:
|
|
87
|
+
"""
|
|
88
|
+
Return dictionary of price histories from Norgate Data.
|
|
89
|
+
|
|
90
|
+
Parameters
|
|
91
|
+
----------
|
|
92
|
+
params : Dict
|
|
93
|
+
Dictionary of key parameters.
|
|
94
|
+
tables : Dict
|
|
95
|
+
Dictionary of key tables.
|
|
96
|
+
mappings : Dict
|
|
97
|
+
Dictionary of sector mappings.
|
|
98
|
+
|
|
99
|
+
Returns
|
|
100
|
+
-------
|
|
101
|
+
tables : Dict
|
|
102
|
+
raw_ticker_dict : Dict
|
|
103
|
+
Dictionary of price history DataFrames, one for each ticker.
|
|
104
|
+
params : Dict
|
|
105
|
+
ticker_name_dict : Dict
|
|
106
|
+
Dictionary mapping ticker to long name for each ticker.
|
|
107
|
+
ticker_short_name_dict : Dict
|
|
108
|
+
Dictionary mapping ticker to short name for each ticker.
|
|
109
|
+
mappings : Dict
|
|
110
|
+
Dictionary of sector mappings
|
|
111
|
+
|
|
112
|
+
"""
|
|
113
|
+
# Create empty dictionaries
|
|
114
|
+
tables['raw_ticker_dict'] = {}
|
|
115
|
+
params['ticker_name_dict'] = {}
|
|
116
|
+
params['ticker_short_name_dict'] = {}
|
|
117
|
+
|
|
118
|
+
# Loop through list of tickers
|
|
119
|
+
for ticker in params['tickers'][:params['ticker_limit']]:
|
|
120
|
+
|
|
121
|
+
# Append character to each ticker to represent its type and create
|
|
122
|
+
# lowercase value
|
|
123
|
+
tick = params['ticker_types'][ticker[0]]+ticker[1:]
|
|
124
|
+
lowtick = tick.lower()
|
|
125
|
+
|
|
126
|
+
# Set data format and extract each DataFrame, storing as
|
|
127
|
+
# a key-value pair in ticker_dict
|
|
128
|
+
timeseriesformat = 'pandas-dataframe'
|
|
129
|
+
try:
|
|
130
|
+
data = norgatedata.price_timeseries(
|
|
131
|
+
ticker, start_date=params['start_date'],
|
|
132
|
+
end_date=params['end_date'],
|
|
133
|
+
format=timeseriesformat,)
|
|
134
|
+
|
|
135
|
+
if type(data) == pd.DataFrame:
|
|
136
|
+
data = data[['Open', 'High', 'Low', 'Close']]
|
|
137
|
+
|
|
138
|
+
tables['raw_ticker_dict'][lowtick] = data
|
|
139
|
+
|
|
140
|
+
# Extract the security name and store in ticker_name_dict
|
|
141
|
+
ticker_name = norgatedata.security_name(ticker)
|
|
142
|
+
params['ticker_name_dict'][lowtick] = ticker_name
|
|
143
|
+
|
|
144
|
+
# Set the proper length of DataFrame to help filter out
|
|
145
|
+
# missing data
|
|
146
|
+
params = MktUtils.window_set(frame=data, params=params)
|
|
147
|
+
|
|
148
|
+
except IndexError:
|
|
149
|
+
print('Error importing : ', ticker)
|
|
150
|
+
|
|
151
|
+
#try:
|
|
152
|
+
# Truncate the ticker name to improve charting legibility
|
|
153
|
+
# and store in ticker_short_name_dict
|
|
154
|
+
params['ticker_short_name_dict'][
|
|
155
|
+
lowtick] = ticker_name.partition(" Continuous")[0]
|
|
156
|
+
|
|
157
|
+
#except:
|
|
158
|
+
# params['ticker_short_name_dict'][lowtick] = ticker_name
|
|
159
|
+
|
|
160
|
+
# Create sector mappings DataFrame
|
|
161
|
+
mappings['sector_mappings_df'] = cls._commodity_sector_mappings(
|
|
162
|
+
params, mappings)
|
|
163
|
+
|
|
164
|
+
return params, tables, mappings
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
@staticmethod
|
|
168
|
+
def _commodity_sector_mappings(
|
|
169
|
+
params: dict,
|
|
170
|
+
mappings: dict) -> pd.DataFrame:
|
|
171
|
+
"""
|
|
172
|
+
Create sector mappings DataFrame
|
|
173
|
+
|
|
174
|
+
Parameters
|
|
175
|
+
----------
|
|
176
|
+
params : Dict
|
|
177
|
+
Dictionary of key parameters.
|
|
178
|
+
mappings : Dict
|
|
179
|
+
Dictionary of sector mappings.
|
|
180
|
+
|
|
181
|
+
Returns
|
|
182
|
+
-------
|
|
183
|
+
sector_mappings_df : DataFrame
|
|
184
|
+
Sector mappings DataFrame.
|
|
185
|
+
|
|
186
|
+
"""
|
|
187
|
+
# Create empty dictionary
|
|
188
|
+
sectors = {}
|
|
189
|
+
|
|
190
|
+
# For each key-value pair in the default sector mappings dictionary
|
|
191
|
+
for key, value in mappings['commodity_sector_mappings'].items():
|
|
192
|
+
|
|
193
|
+
# If the first character in the key is in the list of keys from the
|
|
194
|
+
# ticker types dictionary
|
|
195
|
+
if key[0] in list(params['ticker_types'].keys()):
|
|
196
|
+
|
|
197
|
+
# Create a new key equal to the lower case original key with
|
|
198
|
+
# the first character replaced by the value in the ticker types
|
|
199
|
+
# dictionary
|
|
200
|
+
new_key = key.lower().replace(
|
|
201
|
+
key[0], params['ticker_types'][key[0]])
|
|
202
|
+
|
|
203
|
+
# create an entry in the sectors dictionary
|
|
204
|
+
sectors[new_key] = value
|
|
205
|
+
|
|
206
|
+
# Create a sector mappings DataFrame from the sectors dictionary using
|
|
207
|
+
# the default commodity sector levels list as the column headers
|
|
208
|
+
sector_mappings_df = pd.DataFrame.from_dict(
|
|
209
|
+
sectors,
|
|
210
|
+
orient='index',
|
|
211
|
+
columns=params['commodity_sector_levels'])
|
|
212
|
+
|
|
213
|
+
return sector_mappings_df
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
class YahooExtract():
|
|
217
|
+
"""
|
|
218
|
+
Functions to extract data from Yahoo Finance
|
|
219
|
+
|
|
220
|
+
"""
|
|
221
|
+
@staticmethod
|
|
222
|
+
def ticker_extract(
|
|
223
|
+
params: dict,
|
|
224
|
+
mappings: dict) -> tuple[dict, dict]:
|
|
225
|
+
"""
|
|
226
|
+
Extract list of S&P 500 Companies from Wikipedia.
|
|
227
|
+
|
|
228
|
+
Parameters
|
|
229
|
+
----------
|
|
230
|
+
params : Dict
|
|
231
|
+
Dictionary of key parameters.
|
|
232
|
+
mappings : Dict
|
|
233
|
+
Dictionary of sector mappings.
|
|
234
|
+
|
|
235
|
+
Returns
|
|
236
|
+
-------
|
|
237
|
+
params : Dict
|
|
238
|
+
tickers : List
|
|
239
|
+
List of stock tickers in the form of Reuters RIC codes
|
|
240
|
+
as strings.
|
|
241
|
+
ticker_name_dict : Dict
|
|
242
|
+
Dictionary mapping ticker to long name for each ticker.
|
|
243
|
+
mappings : Dict
|
|
244
|
+
Dictionary of sector mappings.
|
|
245
|
+
|
|
246
|
+
"""
|
|
247
|
+
|
|
248
|
+
# Extract data from the Wikipedia SPX page
|
|
249
|
+
url = 'https://en.wikipedia.org/wiki/List_of_S%26P_500_companies'
|
|
250
|
+
req = requests.get(url, timeout=10)
|
|
251
|
+
html_doc = req.text
|
|
252
|
+
spx_list = pd.read_html(StringIO(html_doc))
|
|
253
|
+
|
|
254
|
+
# the first table on the page contains the stock data
|
|
255
|
+
spx_table = spx_list[0]
|
|
256
|
+
|
|
257
|
+
# create a list of the tickers from the 'Symbol' column
|
|
258
|
+
params['tickers'] = list(spx_table['Symbol'])
|
|
259
|
+
|
|
260
|
+
# create a dictionary mapping ticker to Security Name
|
|
261
|
+
params['ticker_name_dict'] = dict(
|
|
262
|
+
zip(spx_table['Symbol'], spx_table['Security']))
|
|
263
|
+
|
|
264
|
+
# Create a DataFrame from the default equity sectors dictionary
|
|
265
|
+
equity_sectors_df = pd.DataFrame.from_dict(
|
|
266
|
+
mappings['equity_sector_mappings'],
|
|
267
|
+
orient='index',
|
|
268
|
+
columns=['Sector',
|
|
269
|
+
'Industry Group',
|
|
270
|
+
'Industry'])
|
|
271
|
+
|
|
272
|
+
# Reset the index and rename as Sub-Industry column
|
|
273
|
+
equity_sectors_df = equity_sectors_df.reset_index()
|
|
274
|
+
equity_sectors_df = equity_sectors_df.rename(
|
|
275
|
+
columns={'index':'Sub-Industry'})
|
|
276
|
+
|
|
277
|
+
# Create a sector mappings DataFrame by joining the SPX table from
|
|
278
|
+
# Wikipedia to the Equity Sectors DataFrame
|
|
279
|
+
mappings['sector_mappings_df'] = spx_table.merge(
|
|
280
|
+
equity_sectors_df,
|
|
281
|
+
how='left',
|
|
282
|
+
left_on='GICS Sub-Industry',
|
|
283
|
+
right_on='Sub-Industry')
|
|
284
|
+
|
|
285
|
+
# Set the Index to the Ticker symbol
|
|
286
|
+
mappings['sector_mappings_df'] = mappings[
|
|
287
|
+
'sector_mappings_df'].set_index('Symbol')
|
|
288
|
+
|
|
289
|
+
# Keep only the columns related to the sector levels
|
|
290
|
+
mappings['sector_mappings_df'] = mappings['sector_mappings_df'][
|
|
291
|
+
['Sector', 'Industry Group', 'Industry', 'Sub-Industry',
|
|
292
|
+
'Security']]
|
|
293
|
+
|
|
294
|
+
return params, mappings
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
@classmethod
|
|
298
|
+
def import_yahoo(
|
|
299
|
+
cls,
|
|
300
|
+
params: dict,
|
|
301
|
+
tables: dict) -> tuple[dict, dict]:
|
|
302
|
+
"""
|
|
303
|
+
Return dictionary of price histories from Yahoo Finance.
|
|
304
|
+
|
|
305
|
+
Parameters
|
|
306
|
+
----------
|
|
307
|
+
params : Dict
|
|
308
|
+
Dictionary of key parameters.
|
|
309
|
+
tables : Dict
|
|
310
|
+
Dictionary of key tables.
|
|
311
|
+
|
|
312
|
+
Returns
|
|
313
|
+
-------
|
|
314
|
+
tables : Dict
|
|
315
|
+
raw_ticker_dict : Dict
|
|
316
|
+
Dictionary of price history DataFrames, one for each
|
|
317
|
+
ticker.
|
|
318
|
+
params : Dict
|
|
319
|
+
exceptions : List
|
|
320
|
+
List of tickers that could not be returned.
|
|
321
|
+
|
|
322
|
+
"""
|
|
323
|
+
|
|
324
|
+
# Create empty dictionary and list
|
|
325
|
+
tables['raw_ticker_dict'] = {}
|
|
326
|
+
params['exceptions'] = []
|
|
327
|
+
|
|
328
|
+
# Loop through the tickers
|
|
329
|
+
for sym in params['tickers'][:params['ticker_limit']]:
|
|
330
|
+
|
|
331
|
+
# Attempt to return the data for given ticker
|
|
332
|
+
try:
|
|
333
|
+
tables['raw_ticker_dict'][sym], params = cls._return_data(
|
|
334
|
+
ticker=sym, params=params)
|
|
335
|
+
|
|
336
|
+
# If error, try replacing '.' with '-' in ticker
|
|
337
|
+
except KeyError:
|
|
338
|
+
try:
|
|
339
|
+
sym_alt = sym.replace('.','-')
|
|
340
|
+
tables['raw_ticker_dict'][sym], params = cls._return_data(
|
|
341
|
+
ticker=sym_alt, params=params)
|
|
342
|
+
|
|
343
|
+
# If error, add to list of exceptions and move to next
|
|
344
|
+
# ticker
|
|
345
|
+
except KeyError:
|
|
346
|
+
print("Error with "+sym)
|
|
347
|
+
params['exceptions'].append(sym)
|
|
348
|
+
continue
|
|
349
|
+
|
|
350
|
+
return params, tables
|
|
351
|
+
|
|
352
|
+
|
|
353
|
+
@staticmethod
|
|
354
|
+
def _return_data(
|
|
355
|
+
ticker: str,
|
|
356
|
+
params: dict) -> tuple[pd.DataFrame, dict]:
|
|
357
|
+
"""
|
|
358
|
+
Create DataFrame of historic prices for specified ticker.
|
|
359
|
+
|
|
360
|
+
Parameters
|
|
361
|
+
----------
|
|
362
|
+
ticker : Str
|
|
363
|
+
Stock to be returned in the form of Reuters RIC code as a
|
|
364
|
+
string.
|
|
365
|
+
params : Dict
|
|
366
|
+
start_date : Str
|
|
367
|
+
Start Date represented as a string in the
|
|
368
|
+
format 'YYYY-MM-DD'.
|
|
369
|
+
end_date : Str
|
|
370
|
+
End Date represented as a string in the
|
|
371
|
+
format 'YYYY-MM-DD'.
|
|
372
|
+
|
|
373
|
+
Returns
|
|
374
|
+
-------
|
|
375
|
+
frame : DataFrame
|
|
376
|
+
DataFrame of historic prices for given ticker.
|
|
377
|
+
params : Dict
|
|
378
|
+
Dictionary of key parameters.
|
|
379
|
+
|
|
380
|
+
"""
|
|
381
|
+
|
|
382
|
+
# Initialize a YahooFinancials object with the supplied ticker
|
|
383
|
+
# yahoo_financials = YahooFinancials(ticker)
|
|
384
|
+
|
|
385
|
+
# # Set frequency to daily
|
|
386
|
+
# freq='daily'
|
|
387
|
+
|
|
388
|
+
# # Extract historic prices
|
|
389
|
+
# frame = yahoo_financials.get_historical_price_data(
|
|
390
|
+
# params['start_date'], params['end_date'], freq)
|
|
391
|
+
|
|
392
|
+
# # Reformat columns
|
|
393
|
+
# frame = pd.DataFrame(frame[ticker]['prices']).drop(['date'], axis=1) \
|
|
394
|
+
# .rename(columns={'formatted_date':'Date',
|
|
395
|
+
# 'open': 'Open',
|
|
396
|
+
# 'high': 'High',
|
|
397
|
+
# 'low': 'Low',
|
|
398
|
+
# 'close': 'Close',
|
|
399
|
+
# 'volume': 'Volume'}) \
|
|
400
|
+
# .loc[:, ['Date','Open','High','Low','Close','Volume']] \
|
|
401
|
+
# .set_index('Date')
|
|
402
|
+
|
|
403
|
+
# Initialize a yFinance object with the supplied ticker
|
|
404
|
+
asset = yf.Ticker(ticker)
|
|
405
|
+
|
|
406
|
+
# Extract historic prices
|
|
407
|
+
frame = asset.history(start=params['start_date'], end=params['end_date'])
|
|
408
|
+
|
|
409
|
+
# Reformat columns
|
|
410
|
+
frame = frame.drop(['Dividends', 'Stock Splits'], axis=1)
|
|
411
|
+
|
|
412
|
+
# Set Index to Datetime
|
|
413
|
+
frame.index = frame.index.tz_localize(None)
|
|
414
|
+
|
|
415
|
+
# Set the proper length of DataFrame to help filter out missing data
|
|
416
|
+
params = MktUtils.window_set(frame=frame, params=params)
|
|
417
|
+
|
|
418
|
+
return frame, params
|
|
419
|
+
|
|
420
|
+
|
|
421
|
+
class MktUtils():
|
|
422
|
+
"""
|
|
423
|
+
Various market data cleaning utilities
|
|
424
|
+
|
|
425
|
+
"""
|
|
426
|
+
@staticmethod
|
|
427
|
+
def ticker_clean(
|
|
428
|
+
params: dict,
|
|
429
|
+
tables: dict) -> dict:
|
|
430
|
+
"""
|
|
431
|
+
Remove tickers with incomplete history
|
|
432
|
+
|
|
433
|
+
Parameters
|
|
434
|
+
----------
|
|
435
|
+
params : Dict
|
|
436
|
+
Dictionary of key parameters.
|
|
437
|
+
tables : Dict
|
|
438
|
+
Dictionary of key tables.
|
|
439
|
+
|
|
440
|
+
Returns
|
|
441
|
+
-------
|
|
442
|
+
tables : Dict
|
|
443
|
+
Dictionary of key tables.
|
|
444
|
+
|
|
445
|
+
"""
|
|
446
|
+
# Create empty list of tickers to be removed
|
|
447
|
+
params['drop_list'] = []
|
|
448
|
+
|
|
449
|
+
# Loop through each DataFrame in raw ticker dict
|
|
450
|
+
for ticker, frame in tables['raw_ticker_dict'].items():
|
|
451
|
+
|
|
452
|
+
# If the DataFrame has less than 90% full history or has too many
|
|
453
|
+
# repeated values
|
|
454
|
+
if (len(frame) < (params['window'] * 0.9)
|
|
455
|
+
or frame['Close'].nunique() < (params['lookback'] / 15)):
|
|
456
|
+
|
|
457
|
+
# Add ticker to the drop list
|
|
458
|
+
params['drop_list'].append(ticker)
|
|
459
|
+
|
|
460
|
+
# For each ticker in the drop list
|
|
461
|
+
for ticker in params['drop_list']:
|
|
462
|
+
|
|
463
|
+
# Delete the ticker from the dictionary
|
|
464
|
+
del tables['raw_ticker_dict'][ticker]
|
|
465
|
+
|
|
466
|
+
return tables
|
|
467
|
+
|
|
468
|
+
|
|
469
|
+
@staticmethod
|
|
470
|
+
def window_set(
|
|
471
|
+
frame: pd.DataFrame,
|
|
472
|
+
params: dict) -> dict:
|
|
473
|
+
"""
|
|
474
|
+
Set the correct length of the selected data
|
|
475
|
+
|
|
476
|
+
Parameters
|
|
477
|
+
----------
|
|
478
|
+
frame : DataFrame
|
|
479
|
+
The historical prices.
|
|
480
|
+
params : Dict
|
|
481
|
+
start_date : Str
|
|
482
|
+
The chosen start date.
|
|
483
|
+
|
|
484
|
+
Returns
|
|
485
|
+
-------
|
|
486
|
+
params : Dict
|
|
487
|
+
Dictionary of key parameters.
|
|
488
|
+
|
|
489
|
+
"""
|
|
490
|
+
# If the history window has not yet been set
|
|
491
|
+
if params['window'] is None:
|
|
492
|
+
|
|
493
|
+
# If the difference in start dates between the chosen start date
|
|
494
|
+
# and the first value in the index is less than 5 days
|
|
495
|
+
if ((pd.to_datetime(params['start_date'])
|
|
496
|
+
- frame.index[0]).days < 5):
|
|
497
|
+
|
|
498
|
+
# Set the window length to the length of the DataFrame
|
|
499
|
+
params['window'] = len(frame)
|
|
500
|
+
|
|
501
|
+
return params
|
|
502
|
+
|
|
503
|
+
|
|
504
|
+
@staticmethod
|
|
505
|
+
def date_set(params: dict) -> dict:
|
|
506
|
+
"""
|
|
507
|
+
Create start and end dates if not supplied
|
|
508
|
+
|
|
509
|
+
Parameters
|
|
510
|
+
----------
|
|
511
|
+
params : Dict
|
|
512
|
+
start_date : Str, optional
|
|
513
|
+
Date to begin backtest. Format is YYYY-MM-DD. The default is
|
|
514
|
+
500 business days prior (circa 2 years).
|
|
515
|
+
end_date : Str, optional
|
|
516
|
+
Date to end backtest. Format is YYYY-MM-DD. The default is the
|
|
517
|
+
last business day.
|
|
518
|
+
lookback : Int, optional
|
|
519
|
+
Number of business days to use for the backtest. The default
|
|
520
|
+
is 500 business days (circa 2 years).
|
|
521
|
+
|
|
522
|
+
Returns
|
|
523
|
+
-------
|
|
524
|
+
params : Dict
|
|
525
|
+
Dictionary of key parameters.
|
|
526
|
+
|
|
527
|
+
"""
|
|
528
|
+
|
|
529
|
+
# If end date is not supplied, set to previous working day
|
|
530
|
+
if params['end_date'] is None:
|
|
531
|
+
end_date_as_dt = (dt.datetime.today() - BDay(1)).date()
|
|
532
|
+
params['end_date'] = str(end_date_as_dt)
|
|
533
|
+
|
|
534
|
+
# If start date is not supplied, set to today minus lookback period
|
|
535
|
+
if params['start_date'] is None:
|
|
536
|
+
start_date_as_dt = (
|
|
537
|
+
dt.datetime.today()
|
|
538
|
+
- pd.Timedelta(days=params['lookback']*(365/250))).date()
|
|
539
|
+
params['start_date'] = str(start_date_as_dt)
|
|
540
|
+
|
|
541
|
+
return params
|