├── zipline-bundles ├── __init__.py ├── iex.py ├── yahoo.py ├── binance.py ├── extension.py └── ingester.py ├── requirements.txt ├── tests ├── context.py ├── tests_all.py ├── buy_and_hold.py ├── csv_ingester_test.py └── direct_ingester_test.py ├── setup.py ├── LICENSE ├── install.py ├── README.md └── data ├── AAPL.csv └── SPY.csv /zipline-bundles/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | yahoofinancials 2 | iexfinance 3 | python-binance 4 | -------------------------------------------------------------------------------- /tests/context.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) 4 | 5 | import lib.ingester as ingester 6 | -------------------------------------------------------------------------------- /tests/tests_all.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | import csv_ingester_test 4 | import direct_ingester_test 5 | 6 | loader=unittest.TestLoader() 7 | suite=unittest.TestSuite() 8 | 9 | suite.addTest(loader.loadTestsFromModule(csv_ingester_test)) 10 | suite.addTest(loader.loadTestsFromModule(direct_ingester_test)) 11 | 12 | runner=unittest.TextTestRunner(verbosity=3) 13 | result=runner.run(suite) 14 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import os 2 | from setuptools import setup, find_packages 3 | 4 | setup( 5 | name="zipline_bundles", 6 | version="0.1", 7 | packages=[".", "zipline-bundles"], 8 | entry_points = { 9 | 'console_scripts': ['zipline-bundles-install=install:main'], 10 | }, 11 | install_requires=[ 12 | 'yahoofinancials', 13 | 'iexfinance', 14 | 'python-binance', 15 | 'logbook', 16 | ] 17 | ) 18 | -------------------------------------------------------------------------------- /zipline-bundles/iex.py: -------------------------------------------------------------------------------- 1 | from pandas import Timestamp 2 | from iexfinance.stocks import get_historical_data 3 | 4 | def get_downloader(start_date, 5 | end_date,): 6 | """returns a downloader closure for iex cloud 7 | :param start_date: the first day on which dat are downloaded 8 | :param end_date: the last day on which data are downloaded 9 | :type start_date: str in format YYYY-MM-DD 10 | :type end_date: str in format YYYY-MM-DD 11 | """ 12 | dt_start=Timestamp(start_date).date() 13 | dt_end=Timestamp(end_date).date() 14 | 15 | def downloader(symbol): 16 | """downloads symbol price data using iex cloud API 17 | :param symbol: the symbol name 18 | :type symbol: str 19 | """ 20 | df = get_historical_data(symbol, dt_start, dt_end, output_format='pandas') 21 | 22 | return df 23 | 24 | return downloader 25 | -------------------------------------------------------------------------------- /tests/buy_and_hold.py: -------------------------------------------------------------------------------- 1 | # imports 2 | from zipline.api import (symbol, set_benchmark, order_target_percent, 3 | schedule_function, time_rules) 4 | from zipline.finance import commission 5 | #import numpy as np 6 | import pandas as pd 7 | import matplotlib.pyplot as plt 8 | 9 | def initialize(context): 10 | context.set_commission(commission.PerShare(cost=0.0, min_trade_cost=0)) 11 | set_benchmark(symbol('SPY')) 12 | context.asset = symbol('AAPL') 13 | context.has_ordered = False 14 | 15 | schedule_function(place_order, None, 16 | time_rules.market_open()) 17 | 18 | def place_order(context, data): 19 | if not context.has_ordered: 20 | order_target_percent(context.asset, 1.0) 21 | context.has_ordered = True 22 | 23 | def analyze(context, perf): 24 | fig = plt.figure(figsize=(12,8)) 25 | perf.algorithm_period_return.plot(x='strategy return', legend=True) 26 | perf.benchmark_period_return.plot(legend=True) 27 | plt.show() 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Hassan Hatefi 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /zipline-bundles/yahoo.py: -------------------------------------------------------------------------------- 1 | from yahoofinancials import YahooFinancials 2 | import pandas as pd 3 | 4 | 5 | def get_downloader(start_date, 6 | end_date, 7 | granularity='daily',): 8 | """returns a downloader closure for yahoo 9 | :param start_date: the first day on which dat are downloaded 10 | :param end_date: the last day on which data are downloaded 11 | :param granularity: the frequency of price data, 'D' for daily and 'M1' for 1-minute data 12 | :type start_date: str in format YYYY-MM-DD 13 | :type end_date: str in format YYYY-MM-DD 14 | :type granularity: str 15 | """ 16 | 17 | def downloader(symbol): 18 | """downloads symbol price data using yahoo REST API 19 | :param symbol: the symbol name 20 | :type symbol: str 21 | """ 22 | yf = YahooFinancials(symbol) 23 | 24 | res = yf.get_historical_price_data(str(start_date), str(end_date), granularity) 25 | 26 | if not res or symbol not in res or 'prices' not in res[symbol]: 27 | raise ValueError('Fetching price data for "{}" failed.'.format(symbol)) 28 | 29 | prices=res[symbol]['prices'] 30 | df = pd.DataFrame({'open': [p['open'] for p in prices], 31 | 'close': [p['close'] for p in prices], 32 | 'low': [p['low'] for p in prices], 33 | 'high': [p['high'] for p in prices], 34 | 'volume': [p['volume'] for p in prices],}, index=[pd.Timestamp(d['formatted_date']) for d in prices]) 35 | if 'dividend' in prices: 36 | df['dividend'] = [p['dividend'] for p in prices] 37 | else: 38 | df['dividend'] = 0 39 | 40 | if 'split' in prices: 41 | df['split'] = [p['split'] for p in prices] 42 | else: 43 | df['split'] = 1 44 | 45 | return df 46 | 47 | return downloader 48 | -------------------------------------------------------------------------------- /tests/csv_ingester_test.py: -------------------------------------------------------------------------------- 1 | from context import ingester as ig 2 | 3 | import os 4 | import unittest 5 | 6 | class CSVIngesterTest(unittest.TestCase): 7 | def __init__(self, *args, **kwargs): 8 | super().__init__(*args, **kwargs) 9 | 10 | def test_get_csvdir(self): 11 | with self.assertRaises(ValueError): 12 | ig.csv_ingester.get_csvdir(csvdir=None, csvdir_env=None) 13 | 14 | with self.assertRaises(ValueError): 15 | ig.csv_ingester.get_csvdir(csvdir='some nonexisting directory', csvdir_env=None) 16 | 17 | self.assertEqual(ig.csv_ingester.get_csvdir(csvdir='/tmp', csvdir_env=None), '/tmp') 18 | 19 | with self.assertRaises(ValueError): 20 | ig.csv_ingester.get_csvdir(csvdir=None, csvdir_env='some nonexisting environment variable') 21 | 22 | with self.assertRaises(ValueError): 23 | ig.csv_ingester.get_csvdir(csvdir='some nonexisting directory', csvdir_env='some nonexisting environment variable') 24 | 25 | self.assertEqual(ig.csv_ingester.get_csvdir(csvdir='/tmp', csvdir_env='some nonexisting environment variable'), '/tmp') 26 | 27 | os.environ['CSVDIR_TEST']='some nonexisting directory' 28 | with self.assertRaises(ValueError): 29 | ig.csv_ingester.get_csvdir(csvdir=None, csvdir_env='CSVDIR_TEST') 30 | 31 | with self.assertRaises(ValueError): 32 | ig.csv_ingester.get_csvdir(csvdir='some nonexisting directory', csvdir_env='CSVDIR_TEST') 33 | 34 | self.assertEqual(ig.csv_ingester.get_csvdir(csvdir='/tmp', csvdir_env='CSVDIR_TEST'), '/tmp') 35 | 36 | os.environ['CSVDIR_TEST']='/etc' 37 | self.assertEqual(ig.csv_ingester.get_csvdir(csvdir=None, csvdir_env='CSVDIR_TEST'), '/etc') 38 | 39 | self.assertEqual(ig.csv_ingester.get_csvdir(csvdir='some nonexisting directory', csvdir_env='CSVDIR_TEST'), '/etc') 40 | 41 | self.assertEqual(ig.csv_ingester.get_csvdir(csvdir='/tmp', csvdir_env='CSVDIR_TEST'), '/etc') 42 | if __name__ == '__main__': 43 | unittest.main() 44 | -------------------------------------------------------------------------------- /install.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import logging 3 | import sys, os 4 | import shutil 5 | 6 | def copy(filelist, dest, src, force): 7 | for f in filelist: 8 | dstf=os.path.join(dest, f) 9 | if not force and os.path.exists(dstf): 10 | logging.error("'{}' already exists.".format(dstf)) 11 | sys.exit(1) 12 | else: 13 | srcf=os.path.join(src, f) 14 | logging.info("copying '{}' to '{}'".format(srcf, dest)) 15 | try: 16 | shutil.copyfile(srcf, dstf) 17 | except Exception as exp: 18 | logging.error("error while copying '{}' to '{}': {}".format(srcf, dest, exp)) 19 | sys.exit(1) 20 | 21 | def main(force=True): 22 | ### configure logging 23 | logging.basicConfig(format='%(levelname)s:%(message)s', level=logging.INFO) 24 | 25 | # check if zipline is installed 26 | try: 27 | import zipline.data.bundles as bld 28 | except ImportError: 29 | logging.error('cannot found zipline. Run the installer in an environment where zipline is installed.') 30 | sys.exit(1) 31 | 32 | ### source files and directory 33 | src_dir=os.path.join(os.path.abspath(os.path.dirname(__file__)), 'zipline-bundles') 34 | src_ext=['extension.py'] 35 | src_ing=['ingester.py', 'iex.py', 'yahoo.py', 'binance.py'] 36 | 37 | ### destination directories 38 | dst_ext=os.path.join(os.path.expanduser('~'), '.zipline') 39 | # check the existence of zipline home 40 | if not os.path.isdir(dst_ext): 41 | logging.error(f"zipline home ('{dst_ext}') does not exist.") 42 | sys.exit(1) 43 | 44 | dst_ing=bld.__path__[0] 45 | 46 | copy(src_ext, dst_ext, src_dir, force) 47 | copy(src_ing, dst_ing, src_dir, force) 48 | 49 | if __name__ == "__main__": 50 | ### initialize the input argument parser 51 | parser=argparse.ArgumentParser(description='Add zipline bundles') 52 | parser.add_argument('-f', '--force', action='store_true') 53 | 54 | ### parse input arguments 55 | input_args=parser.parse_args() 56 | 57 | main(input_args.force) 58 | -------------------------------------------------------------------------------- /zipline-bundles/binance.py: -------------------------------------------------------------------------------- 1 | import os 2 | from pandas import Timestamp, DataFrame 3 | from binance.client import Client 4 | 5 | API_KEY_ENV='BINANCE_API_KEY' 6 | SECRET_KEY_ENV='BINANCE_SECRET_KEY' 7 | 8 | 9 | def klines2ohlcv(klines): 10 | """converts klines downloaded from binace via python binance module 11 | into pandas dataframe complaint with OHLCV 12 | :param klines: The list of klines 13 | :type klines: list of price data, see https://sammchardy 14 | """ 15 | ohlcv=[(Timestamp(l[0], unit='ms'), # timestamp 16 | float(l[1]), # open 17 | float(l[2]), # high 18 | float(l[3]), # low 19 | float(l[4]), # close 20 | float(l[5]) # volume 21 | ) 22 | for l in klines] 23 | 24 | df=DataFrame(ohlcv, columns=['date', 'open', 'high', 'low', 'close', 'volume']) 25 | df.set_index('date', inplace=True) 26 | 27 | return df 28 | 29 | def get_downloader(start_date, end_date, every_min_bar): 30 | """returns a downloader closure for iex cloud 31 | :param start_date: the first day on which dat are downloaded 32 | :param end_date: the last day on which data are downloaded 33 | :type start_date: str in format YYYY-MM-DD 34 | :type end_date: str in format YYYY-MM-DD 35 | :param every_min_bar: True if the the price time series must be 36 | downloaded for every minute. Otherwise the daily price is fetched. 37 | :type every_min_bar: bool 38 | """ 39 | dt_start=int(Timestamp(start_date).timestamp()*1000) 40 | dt_end=int(Timestamp(end_date).timestamp()*1000) 41 | 42 | def downloader(symbol): 43 | """downloads symbol price data using iex cloud API 44 | :param symbol: the symbol name 45 | :type symbol: str 46 | """ 47 | api_key=os.environ.get(API_KEY_ENV) 48 | secret_key=os.environ.get(SECRET_KEY_ENV) 49 | if api_key is None or secret_key is None: 50 | raise Exception('Both {} and {} environment variables must be defined'.format(API_KEY_ENV, SECRET_KEY_ENV)) 51 | cl=Client(api_key, secret_key) 52 | freq=Client.KLINE_INTERVAL_1MINUTE if every_min_bar else Client.KLINE_INTERVAL_1DAY 53 | klines=cl.get_historical_klines(symbol, freq, dt_start, dt_end) 54 | 55 | df=klines2ohlcv(klines) 56 | return df 57 | 58 | return downloader 59 | -------------------------------------------------------------------------------- /zipline-bundles/extension.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | from pathlib import Path 5 | from zipline.data.bundles import register 6 | from zipline.data.bundles.ingester import csv_ingester # ingester.py need to be placed in zipline.data.bundles 7 | 8 | _DEFAULT_PATH = str(Path.home() / '.zipline/csv/yahoo') 9 | 10 | register( 11 | 'yahoo_csv', 12 | csv_ingester('YAHOO', 13 | every_min_bar=False, # the price is daily 14 | csvdir_env='YAHOO_CSVDIR', 15 | csvdir=_DEFAULT_PATH, 16 | index_column='Date', 17 | column_mapper={'Open': 'open', 18 | 'High': 'high', 19 | 'Low': 'low', 20 | 'Close': 'close', 21 | 'Volume': 'volume', 22 | 'Adj Close': 'price', 23 | }, 24 | ), 25 | calendar_name='NYSE', 26 | ) 27 | 28 | from zipline.data.bundles.ingester import direct_ingester 29 | 30 | from zipline.data.bundles import yahoo 31 | register('yahoo_direct', # bundle's name 32 | direct_ingester('YAHOO', 33 | every_min_bar=False, 34 | symbol_list_env='YAHOO_SYM_LST', # the environemnt variable holding the comma separated list of assert names 35 | downloader=yahoo.get_downloader(start_date='2010-01-01', 36 | end_date='2020-01-01' 37 | ), 38 | ), 39 | calendar_name='NYSE', 40 | ) 41 | 42 | from zipline.data.bundles import iex 43 | import exchange_calendars as xcals 44 | 45 | cal=xcals.get_calendar('NYSE') 46 | register('iex', # bundle's name 47 | direct_ingester('IEX Cloud', 48 | every_min_bar=False, 49 | symbol_list_env='IEX_SYM_LST', # the environemnt variable holding the comma separated list of assert names 50 | downloader=iex.get_downloader(start_date='2020-01-01', 51 | end_date='2020-01-05' 52 | ), 53 | filter_cb=lambda df: df[[cal.is_session(dt) for dt in df.index]] 54 | ), 55 | calendar_name='NYSE', 56 | ) 57 | 58 | from zipline.data.bundles import binance 59 | 60 | register('binance_daily', # bundle's name 61 | direct_ingester('Binance Exchange', 62 | every_min_bar=False, 63 | symbol_list_env='BINANCE_SYM_LST', # the environemnt variable holding the comma separated list of assert names 64 | downloader=binance.get_downloader(start_date='2020-01-01', 65 | end_date='2020-01-05', 66 | every_min_bar=False # True for minute price, False for dailyprice 67 | ), 68 | ), 69 | calendar_name='24/7', 70 | ) 71 | 72 | register('binance_min', # bundle's name 73 | direct_ingester('Binance Exchange', 74 | every_min_bar=True, 75 | symbol_list_env='BINANCE_SYM_LST', # the environemnt variable holding the comma separated list of assert names 76 | downloader=binance.get_downloader(start_date='2020-01-01', 77 | end_date='2020-01-05', 78 | every_min_bar=True # True for minute price, False for dailyprice 79 | ), 80 | ), 81 | calendar_name='24/7', 82 | ) 83 | -------------------------------------------------------------------------------- /tests/direct_ingester_test.py: -------------------------------------------------------------------------------- 1 | from context import ingester as ig 2 | 3 | import os 4 | import unittest 5 | import pandas as pd 6 | 7 | _g_start_date = pd.Timestamp('2020.01.01') 8 | 9 | df_A=pd.DataFrame({'open': range(10), 10 | 'high': range(10, 20), 11 | 'low': range(20, 30), 12 | 'close': range(30, 40), 13 | 'volume': range(40, 50), 14 | 'dividend': [0]*10, 15 | 'split': [1]*10}, index= [_g_start_date + pd.Timedelta(days=i) for i in range(10)]) 16 | 17 | df_B=df_A + 5 18 | 19 | def downloader(symbol): 20 | df = None 21 | if symbol == 'A': 22 | df = df_A 23 | elif symbol == 'B': 24 | df = df_B 25 | return df 26 | 27 | class DirectIngesterTestCase(unittest.TestCase): 28 | def __init__(self, *args, **kwargs): 29 | super().__init__(*args, **kwargs) 30 | 31 | def test_create_symbol_list(self): 32 | self.assertEqual(len(ig.direct_ingester.create_symbol_list('SYM_LIST', [])), 0) 33 | self.assertEqual(len(ig.direct_ingester.create_symbol_list('SYM_LIST', None)), 0) 34 | symlst = ig.direct_ingester.create_symbol_list('SYM_LIST', ['A', 'B']) 35 | self.assertEqual(len(symlst), 2) 36 | self.assertTrue('A' in symlst) 37 | self.assertTrue('B' in symlst) 38 | symlst = ig.direct_ingester.create_symbol_list('SYM_LIST', ['A', '']) 39 | self.assertEqual(len(symlst), 1) 40 | self.assertTrue('A' in symlst) 41 | os.environ['SYM_LIST'] = 'A,B,, ,' 42 | symlst = ig.direct_ingester.create_symbol_list('SYM_LIST', ['A', 'B']) 43 | self.assertEqual(len(symlst), 2) 44 | self.assertTrue('A' in symlst) 45 | self.assertTrue('B' in symlst) 46 | 47 | def test_read_and_convert(self): 48 | class fake_adjustment_writer: 49 | def write(self): 50 | pass 51 | 52 | class fake_bar_writer: 53 | def write(self, gen, show_progress): 54 | self.dfs = list(gen) 55 | 56 | class fake_db_writer: 57 | def write(self,equities): # asset_db_writer 58 | self.df_metadata = equities 59 | 60 | ingester=ig.direct_ingester('EXX', False, None, downloader, symbol_list = ('A', 'B')) 61 | self.assertEqual(len(ingester._symbols), 2) 62 | 63 | adjustment_writer=fake_adjustment_writer() 64 | bar_writer=fake_bar_writer() 65 | db_writer=fake_db_writer() 66 | ingester(environ=None, 67 | asset_db_writer=db_writer, 68 | minute_bar_writer=None, 69 | daily_bar_writer=bar_writer, 70 | adjustment_writer=adjustment_writer, 71 | calendar=None, 72 | start_session=None, 73 | end_session=None, 74 | cache=None, 75 | show_progress=True, 76 | output_dir=None) 77 | self.assertEqual(len(bar_writer.dfs), 2) 78 | self.assertEqual(bar_writer.dfs[0][0], 0) 79 | self.assertEqual(bar_writer.dfs[1][0], 1) 80 | find_sym_idx=lambda df,sym: df[df.symbol == sym].index[0] 81 | idx_A=find_sym_idx(db_writer.df_metadata, 'A') 82 | idx_B=find_sym_idx(db_writer.df_metadata, 'B') 83 | self.assertTrue(bar_writer.dfs[idx_A][1].equals(df_A)) 84 | self.assertTrue(bar_writer.dfs[idx_B][1].equals(df_B)) 85 | 86 | self.assertEqual(len(db_writer.df_metadata), 2) 87 | self.assertEqual(db_writer.df_metadata.symbol.loc[idx_A], 'A') 88 | self.assertEqual(db_writer.df_metadata.symbol.loc[idx_B], 'B') 89 | for d in db_writer.df_metadata.start_date: 90 | self.assertEqual(d, pd.Timestamp('2020.01.01')) 91 | for d in db_writer.df_metadata.end_date: 92 | self.assertEqual(d, pd.Timestamp('2020.01.10')) 93 | 94 | 95 | if __name__ == '__main__': 96 | unittest.main() 97 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Zipline Bundles 2 | =============== 3 | 4 | This repository contains some zipline data bundles, which are used to 5 | download and extract historical price data for backtesting in zipline 6 | platform. Zipline is a backtesting framework written in python, which 7 | can be used to test, analyze and visualize trading strategies. Zipline 8 | was developed and maintained by Quantopian until 2020. Since 9 | [Quantopian's 10 | shutdown](https://www.bizjournals.com/boston/news/2020/11/10/quantopian-shuts-down-cofounders-head-elsewhere.html), 11 | this repository is developed and tested with 12 | [zipline_reloaded](https://github.com/stefan-jansen/zipline-reloaded), 13 | one of zipline's actively developed fork. 14 | 15 | ## Quick start 16 | 17 | You have already cloned the repository and switched the working 18 | directory to the repository root. Then, in an environment where 19 | zipline is installed and working, adding all data bundles can be done 20 | by 21 | 22 | ```sh 23 | python install.py 24 | ``` 25 | 26 | Note that the installer complains if there already exist python 27 | modules with the same name. To force the installer to overwrite the 28 | existing modules, add `-f`. Apart from `zipline` itself and its 29 | dependencies, there are additional dependencies used by each 30 | bundle. To install them all run 31 | 32 | ```sh 33 | pip install -r requirements.txt 34 | ``` 35 | 36 | You can check if the installation is complete by running: 37 | ```sh 38 | zipline bundles 39 | ``` 40 | 41 | You should see new bundles are added to the list: 42 | 43 | ```bash 44 | csvdir 45 | iex 46 | quandl 47 | quantopian-quandl 48 | yahoo_csv 49 | yahoo_direct 50 | ``` 51 | 52 | To test the installation, a simple strategy backtest can be executed 53 | over price data read by one of the bundles. For this, `yahoo_csv` 54 | bundle is used, which reads data from a directory containing csv files 55 | that are downloaded from yahoo finance. First, ingest price data 56 | stored in [data](data) directory: 57 | 58 | ```bash 59 | YAHOO_CSVDIR=./data/ zipline ingest -b yahoo_csv 60 | ``` 61 | 62 | Then backtest buy and hold strategy over the ingested data: 63 | 64 | ```bash 65 | zipline run -f tests/buy_and_hold.py -b yahoo_csv --start 2019-07-02 --end 2020-07-02 66 | ``` 67 | 68 | The cumulative return of the strategy will be depicted in a plot after 69 | backtesting. 70 | 71 | ## Bundles 72 | 73 | The following bundles are currently defined by the repository. 74 | 75 | | Bundle | Data Source | Dependency | Module | 76 | | :----- | ---------- | :----------| ------- | 77 | | `yahoo_csv` | csv files downloaded from [yahoo finance](https://finance.yahoo.com) | none | none | 78 | | `yahoo_direct`| [yahoo finance](https://finance.yahoo.com) | [`yahoofinancials`](https://pypi.org/project/yahoofinancials/) | [yahoo.py](lib/yahoo.py) | 79 | | `iex` | [IEX cloud](https://iexcloud.io) | [`iexfinance`](https://pypi.org/project/iexfinance/) | [iex.py](lib/iex.py) | 80 | | `binance_daily` | daily price from [binance exchange](https://www.binance.com) | [`python-binance`](https://python-binance.readthedocs.io) | [binance.py](lib/binance.py) | 81 | | `binance_min` | per minute price from [binance exchange](https://www.binance.com) | [`python-binance`](https://python-binance.readthedocs.io) | [binance.py](lib/binance.py) | 82 | 83 | ### `yahoo_csv` 84 | 85 | This bundle takes data from CSV files downloaded from yahoo 86 | finance. Each file contains price data of a single asset and shall be 87 | named as `assert_name.csv`. The bundle reads all the csv files located 88 | in a directory given by environment variable `YAHOO_CSVDIR`: 89 | 90 | ```bash 91 | YAHOO_CSVDIR=/path/to/csvdir zipline ingest -b yahoo_csv 92 | ``` 93 | ### `yahoo_direct` 94 | 95 | It directly downloads price data from yahoo finance. The bundle 96 | extracts asset names from environment variable `YAHOO_SYM_LST`, which 97 | holds a comma separated list of asset names. For example: 98 | 99 | ```bash 100 | YAHOO_SYM_LST=SPY,AAPL zipline ingest -b yahoo_direct 101 | ``` 102 | 103 | ingests price data of assets `SPY` and `AAPL`. The start and the end 104 | date of ingestion can be set into variables `start_date` and 105 | `end_date`, respectively. These variables are passed to function 106 | `get_downloader` where the bundle is registered in 107 | `$HOME/.zipline/extension.py`. Here is how the registration may look 108 | like: 109 | 110 | ```python 111 | register('yahoo_direct', # bundle's name 112 | direct_ingester('YAHOO', 113 | every_min_bar=False, 114 | symbol_list_env='YAHOO_SYM_LST', # the environment variable holding the comma separated list of assert names 115 | downloader=yahoo.get_downloader(start_date='2010-01-01', 116 | end_date='2020-01-01' 117 | ), 118 | ), 119 | calendar_name='NYSE', 120 | ) 121 | ``` 122 | 123 | In addition to the start and the end date, the environment variable 124 | name holding price data can be set here. `direct_ingester` can 125 | additionally takes callable `filter_cb`. It takes as a parameter a 126 | data frame that is just retured from the downloader and returns a new 127 | data frame. It is useful when the downloaded price data needs 128 | additional prepossessing. 129 | 130 | ### `iex` 131 | 132 | It downloads price data from IEX cloud. Its usage is fairly similar to 133 | that of `yahoo_direct`. Fetching price data from IEX cloud however 134 | requires passing a valid API token, which is stored in environment 135 | variable `IEX_TOKEN`. Moreover, the environment variable storing asset 136 | names is called `IEX_SYM_LST`. 137 | 138 | ### `binance_daily` and `binance_min` 139 | 140 | Both collect data from binance cryptocurrency exchange with daily and 141 | minutely frequency. The list of symbols are taken from environment 142 | variable `BINANCE_SYM_LST`. Moreover, the API key and the secret key 143 | are supposed to set in environment variables `BINANCE_API_KEY` and 144 | `BINANCE_SECRET_KEY`. For example, the following command ingests the 145 | daily price of bitcoin and ethereum in USD. 146 | 147 | ```bash 148 | BINANCE_API_KEY=your_api_key BINANCE_SECRET_KEY=your_secret_key BINANCE_SYM_LST=BTCUSDT,ETHUSDT zipline ingest -b binance_daily 149 | ``` 150 | 151 | ## Manual installation 152 | [install.py](install.py) takes the following steps to add the bundles: 153 | 154 | * copy [extension.py](lib/extension.py) into `~/.zipline/`, 155 | 156 | * add [ingester.py](lib/ingester.py) as well as the proper module for 157 | each bundle listed in above table into package 158 | `zipline.data.bundles`, i.e. copy the modules into where the package 159 | is located. Package location differs depending on the way zipline is 160 | installed. One way to find out the location in an environment with 161 | zipline installed is to run the following code: 162 | 163 | ```bash 164 | python -c 'import zipline.data.bundles as bdl; print(bdl.__path__)' 165 | ``` 166 | 167 | If only a subset of bundles is needed, one way is to keep their 168 | registration in [extension.py](lib/extension.py), their dependency in 169 | [requirements.txt](requirements.txt) and their related modules in 170 | variable `src_ing` inside [install.py](install.py). Then, use the 171 | installation script! 172 | 173 | ## Adding new bundles 174 | 175 | It is possible to define new data bundles using the structures 176 | provided by this repository. The process is explained in [this 177 | post](https://hhatefi.github.io/posts/zipline_bundles/) in more 178 | detail. 179 | -------------------------------------------------------------------------------- /zipline-bundles/ingester.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import numpy as np 4 | import pandas as pd 5 | import datetime as dt 6 | # 7 | from logbook import Logger 8 | # 9 | from zipline.utils.cli import maybe_show_progress 10 | 11 | log = Logger(__name__) 12 | 13 | def create_metadata(nsymbols): 14 | """creates and return metadata dataframe with appropriate columns with length of `nsymbols` 15 | 16 | :param nsymbols: the number of symbols 17 | :type nsymbols: int 18 | :return: the resulting metadata dataframe 19 | :rtype: pandas.DataFrame 20 | """ 21 | return pd.DataFrame(np.empty(nsymbols, dtype=[ 22 | ('start_date', 'datetime64[ns]'), 23 | ('end_date', 'datetime64[ns]'), 24 | ('auto_close_date', 'datetime64[ns]'), 25 | ('symbol', 'object'), 26 | ('exchange', 'object'),])) 27 | 28 | 29 | class ingester_base: 30 | """ 31 | data bundle reader base 32 | """ 33 | def __init__(self, exchange, every_min_bar): 34 | """initializes an ingester instance 35 | 36 | :param exchange: the name of the exchange providing price data 37 | 38 | :param every_min_bar: The price time series given to an 39 | ingester may have 1-day or 1-minute frequency. This variable 40 | being `True` means the frequency is 1-minute, otherwise the 41 | price is provided daily. 42 | 43 | :type exchange: str 44 | :type every_min_bar: bool 45 | 46 | """ 47 | self._exchange=exchange 48 | self._every_min_bar=every_min_bar 49 | 50 | def __call__(self, 51 | environ, 52 | asset_db_writer, 53 | minute_bar_writer, 54 | daily_bar_writer, 55 | adjustment_writer, 56 | calendar, 57 | start_session, 58 | end_session, 59 | cache, 60 | show_progress, 61 | output_dir): 62 | """implements the ingest function 63 | 64 | For in detail parameter description see https://www.zipline.io/bundles.html#writing-a-new-bundle 65 | """ 66 | raise NotImplementedError 67 | 68 | class csv_ingester(ingester_base): 69 | """inegester from csv files 70 | """ 71 | def __init__(self, exchange, every_min_bar, csvdir, csvdir_env, index_column='date', column_mapper=None): 72 | """creates an instance of csv ingester 73 | 74 | :param exchange: an arbitrary name for the exchange providing 75 | price data 76 | 77 | :param every_min_bar: The price time series given to an 78 | ingester may have 1-day or 1-minute frequency. This variable 79 | being `True` means the frequency is 1-minute, otherwise the 80 | price is provided daily. 81 | 82 | :param csvdir: The path to the directory containing csv 83 | files. For each symbol there must be a single file of name 84 | '.csv' 85 | 86 | :param csvdir_env: The envireonment variable used to locate 87 | the csv directory containing the csv files. After setting this 88 | parameter, for example by 89 | `csv_ingester(...,csvdir_env='CSV_DIR'...)`, the user can pass 90 | a csv directory via 91 | `ENV_VAR=/path/to/csv/dir zipline ingest -b ` 92 | 93 | :param index_column: the label of the column in csv file that is 94 | interpreted as index. It reports the timestamp of the 95 | corrsponding price information. Its default value is 'date'. 96 | 97 | :param column_mapper: a dictionary that maps column labels 98 | read from csv file to the ones expected from zipline. Zipline 99 | accepts csv files in OHLCD format, which contains columns 100 | 'date', 'open', 'high', 'low', 'close' , 'volume', 'dividend' 101 | and 'split'. For example, a mapper passed by 102 | column_mapper={'Date': 'date'}, renames column label 'Date' to 103 | 'date' in all symbol dataframes read by the ingester. The 104 | default value is `None`, which means no renaming will happen. 105 | 106 | :type exchange: str 107 | :type every_min_bar: bool 108 | :type csvdir: str 109 | :type csvdir_env: str 110 | :type index_column: str 111 | :type column_mapper: dict mapping str to str 112 | 113 | """ 114 | super().__init__(exchange, every_min_bar) 115 | self._csvdir = csvdir 116 | self._csvdir_env = csvdir_env 117 | self._index_column=index_column 118 | self._column_mapper=column_mapper 119 | 120 | @staticmethod 121 | def get_csvdir(csvdir, csvdir_env, show_progress=False): 122 | """returns the csv directory to read csv files from 123 | 124 | It tries first to set the csv directory from environment 125 | variable. If no environment variable is given, or it is not 126 | set by the user, it will check csvdir for a valid 127 | directory. If that fails then ValueError will be raised. 128 | 129 | :param show_progress: if `True`, it will be verbose 130 | :type show_progress: bool 131 | 132 | :return: the path to csv directory 133 | :rtype: str 134 | :raise: ValueError when csv directory cannot be set 135 | """ 136 | if csvdir_env: 137 | path = os.environ.get(csvdir_env) 138 | if path and os.path.isdir(path): 139 | if show_progress: 140 | log.info('csv directory is set to \'{}\''.format(path)) 141 | return path 142 | elif show_progress: 143 | log.debug('\'{}\' is not a valid directory'.format(path)) 144 | if csvdir and os.path.isdir(csvdir): 145 | if show_progress: 146 | log.info('csv directory is set to \'{}\''.format(csvdir)) 147 | return csvdir 148 | error_msg="csv directory is not valid" 149 | if csvdir_env: 150 | error_msg="{}. It can be set via environment variable '{}'".format(error_msg, csvdir_env) 151 | if error_msg[-1] == "'": 152 | error_msg="{}. It can also be set inside '.zipline/extension.py' where the bundle is registered by setting argument 'csvdir'".format(error_msg) 153 | else: 154 | error_msg="{}. It can be set inside '.zipline/extension.py' where the bundle is registered by setting argument 'csvdir'".format(error_msg) 155 | raise ValueError(error_msg) 156 | 157 | def _get_csvdir(self, show_progress=False): 158 | """returns the csv directory and exit the program in case of failure 159 | """ 160 | try: 161 | return csv_ingester.get_csvdir(self._csvdir, self._csvdir_env, show_progress) 162 | except ValueError as exp: 163 | log.error("{}".format(exp)) 164 | sys.exit(1) 165 | 166 | 167 | def _extract_symbols(self): 168 | """returns the list of (symbol, csv_file_path) pair from the csv directory path 169 | 170 | This function extracts the list symbols from csv files located 171 | in `self._get_csvdir`. The assumption is that the price data 172 | of each asset is stored in `symbol_name.csv` within the csv 173 | directory. 174 | 175 | :return: the list of symbols 176 | :rtype: list of str 177 | """ 178 | return [csv_file_path.split('.csv')[0] # symbol name 179 | for csv_file_path in os.listdir(self._get_csvdir()) if csv_file_path.endswith('.csv')] 180 | 181 | def _update_symbol_metadata(self, symbol_index, symbol, df): 182 | """update metadata for the given symbol 183 | 184 | Metadata are extracted from the given dataframe `df`, which is 185 | the price data read from csv file or downloaded via the firm 186 | API. They are stored in `self._df_metadata[symbol_index]` 187 | 188 | :param symbol_index: the symbol index 189 | :param symbol: the symbol name 190 | :param df: the dataframe storing symbol's price data 191 | 192 | :type symbol_index: int 193 | :type symbol: str 194 | :type df: pandas.DataFrame 195 | """ 196 | start_date = df.index[0] 197 | end_date = df.index[-1] 198 | autoclose_date = end_date + pd.Timedelta(days=1) 199 | self._df_metadata.iloc[symbol_index] = start_date, end_date, autoclose_date, symbol, self._exchange 200 | 201 | def _read_and_convert(self, symbols, show_progress): 202 | """returns the generator of symbol index and the dataframe storing its price data 203 | """ 204 | path = self._get_csvdir(show_progress) 205 | with maybe_show_progress(symbols, show_progress, label='Loading csv files: ') as it: 206 | for symbol_index, symbol in enumerate(it): 207 | file_path = '{0}/{1}.csv'.format(path, symbol) 208 | if os.path.exists(file_path): 209 | # read data from csv file and set the index 210 | df_data = pd.read_csv(file_path, index_col=self._index_column, parse_dates=True, dtype={"Volumn": np.uint64}).sort_index() 211 | # rename columns if necessary 212 | if self._column_mapper: 213 | df_data.rename(columns=self._column_mapper, inplace=True) 214 | self._filter(df_data) 215 | self._update_symbol_metadata(symbol_index, symbol, df_data) 216 | yield symbol_index, df_data 217 | 218 | def _filter(self, df): 219 | """applies filter on price dataframe read by ingestor 220 | 221 | This method is called within `self._read_and_convert`, after 222 | the column mapping is done. It checks if the dataframe has 223 | `split` and `dividend` column, if not it creates them and 224 | assigns their default value. 225 | 226 | :param df: the price dataframe to be filtered 227 | :type df: pandas.DataFrame 228 | 229 | """ 230 | if 'dividend' not in df.columns: 231 | df['dividend'] = 0; 232 | if 'split' not in df.columns: 233 | df['split'] = 1 234 | 235 | def __call__(self, 236 | environ, 237 | asset_db_writer, 238 | minute_bar_writer, 239 | daily_bar_writer, 240 | adjustment_writer, 241 | calendar, 242 | start_session, 243 | end_session, 244 | cache, 245 | show_progress, 246 | output_dir): 247 | """implements the actual ingest function 248 | 249 | The order of calls are as follows 250 | 1. `self._extract_symbols()` 251 | 2. `create_metadata()` 252 | 3. `self._read_and_convert()` 253 | """ 254 | symbols = self._extract_symbols() 255 | if show_progress: 256 | log.info('symbols are: {0}'.format(symbols)) 257 | self._df_metadata=create_metadata(len(symbols)) 258 | if show_progress: 259 | log.info('writing data...') 260 | if self._every_min_bar: 261 | minute_bar_writer.write(self._read_and_convert(symbols, show_progress), show_progress=show_progress) 262 | else: 263 | daily_bar_writer.write(self._read_and_convert(symbols, show_progress), show_progress=show_progress) 264 | if show_progress: 265 | log.info('meta data:\n{0}'.format(self._df_metadata)) 266 | asset_db_writer.write(equities=self._df_metadata) 267 | adjustment_writer.write() 268 | if show_progress: 269 | log.info('writing completed') 270 | 271 | 272 | class direct_ingester(ingester_base): 273 | """inegester that directly downloads price data via callable downloader 274 | 275 | This class can be used to implement an ingester that download 276 | price data directly via REST API. A proper downloader callable 277 | should be defined in order to download price data and convert is 278 | to the format accepted by zipline. 279 | 280 | """ 281 | def __init__(self, exchange, every_min_bar, symbol_list_env, downloader, symbol_list=None, filter_cb=None): 282 | """creates an instance of csv ingester 283 | 284 | :param exchange: an arbitrary name for the exchange providing 285 | price data 286 | 287 | :param every_min_bar: The price time series given to an 288 | ingester may have 1-day or 1-minute frequency. This variable 289 | being `True` means the frequency is 1-minute, otherwise the 290 | price is provided daily. 291 | 292 | :param symbol_list_env: The envireonment variable used to collect 293 | the list of symbols whose price data should be 294 | downloaded. After setting this parameter, for example by 295 | `direct_ingester(...,symbol_list_env='SYMBOL_LIST'...)`, the 296 | user can provide the symbols as a comma separated list, e.g. 297 | `SYMBOL_LIST=SPY,AAPL zipline ingest -b `. 298 | 299 | :param symbol_list: an iterable providing the list of 300 | symbols. The final list of symbol is the union of symbols 301 | given by this parameter and those given by the environment 302 | variable 303 | 304 | :param downloader: a callable that downloads price data. It takes the following arguments: 305 | - symbol: an string referring to the symbol name 306 | 307 | :param filter_cb: The callback that is called after the 308 | downloader is invoked. It takes a data frame and returns the 309 | filtered dataframe 310 | 311 | :type exchange: str 312 | :type every_min_bar: bool 313 | :type symbol_list_env: str 314 | :type downloader: a callable that downloads price data 315 | :type symbol_list: an iterable container of str type 316 | :type filter_cb: a callable that takes a data frame and return a data frame 317 | 318 | """ 319 | super().__init__(exchange, every_min_bar) 320 | self._symbols = direct_ingester.create_symbol_list(symbol_list_env, symbol_list) 321 | self._downloader = downloader 322 | self._filter=filter_cb 323 | 324 | @staticmethod 325 | def create_symbol_list(symbol_list_env, symbol_list, show_progress=False): 326 | """creates and returns the symbol list 327 | 328 | 329 | The symbol list is computed by taking the union of the symbols 330 | in `symbol_list` and those listed in the environment variable 331 | with the name given by `symbol_list_env`. 332 | 333 | It tries first to set the csv directory from environment 334 | variable. If no environment variable is given, or it is not 335 | set by the user, it will check self._csvdir for a valid 336 | directory. If that fails then `sys.exit()` will be called. 337 | 338 | :param show_progress: if `True`, it will be verbose 339 | :type show_progress: bool 340 | 341 | :return: the symbol list 342 | :rtype: tuple of str 343 | 344 | """ 345 | symbols=set() 346 | 347 | if symbol_list_env: 348 | env_list = os.environ.get(symbol_list_env, '') # comma seperated 349 | # add symbols from environment variable 350 | symbols=symbols.union([sym for sym in env_list.split(',') if sym.strip()]) 351 | 352 | # add symbols from |symbol_list| 353 | if symbol_list: 354 | symbols=symbols.union([sym for sym in symbol_list if sym.strip()]) 355 | 356 | if show_progress: 357 | if len(symbols) == 0: 358 | log.warn("no symbol were added.") 359 | else: 360 | log.info("price data of symbols {} to be ".format(symbols)) 361 | return tuple(symbols) 362 | 363 | def _update_symbol_metadata(self, symbol_index, symbol, df): 364 | """update metadata for the given symbol 365 | 366 | Metadata are extracted from the given dataframe `df`, which is 367 | the price data read from csv file or downloaded via the firm 368 | API. They are stored in `self._df_metadata[symbol_index]` 369 | 370 | :param symbol_index: the symbol index 371 | :param symbol: the symbol name 372 | :param df: the dataframe storing symbol's price data 373 | 374 | :type symbol_index: int 375 | :type symbol: str 376 | :type df: pandas.DataFrame 377 | """ 378 | start_date = df.index[0] 379 | end_date = df.index[-1] 380 | autoclose_date = end_date + pd.Timedelta(days=1) 381 | self._df_metadata.iloc[symbol_index] = start_date, end_date, autoclose_date, symbol, self._exchange 382 | 383 | def _read_and_convert(self, calendar, show_progress): 384 | """returns the generator of symbol index and the dataframe storing its price data 385 | """ 386 | assert self._symbols, ( 387 | f"Symbol list for bundle {self._exchange} is empty. Consider " 388 | "setting the proper environment variable, or passing a symobol " 389 | "list at bundle registration time." 390 | ) 391 | with maybe_show_progress( 392 | self._symbols, 393 | show_progress, 394 | label=f"Downloading from {self._exchange}: ", 395 | length=len(self._symbols), 396 | item_show_func=lambda s: s, 397 | ) as it: 398 | for symbol_index, symbol in enumerate(it): 399 | # read data from csv file and set the index 400 | df_data = self._downloader(symbol) 401 | # apply filter when it is provided 402 | if self._filter is not None: 403 | df_data = self._filter(df_data) 404 | self._update_symbol_metadata(symbol_index, symbol, df_data) 405 | yield symbol_index, df_data 406 | 407 | def __call__(self, 408 | environ, 409 | asset_db_writer, 410 | minute_bar_writer, 411 | daily_bar_writer, 412 | adjustment_writer, 413 | calendar, 414 | start_session, 415 | end_session, 416 | cache, 417 | show_progress, 418 | output_dir): 419 | """implements the actual ingest function 420 | 421 | The order of calls are as follows 422 | 1. `create_metadata()` 423 | 2. `self._read_and_convert()` 424 | """ 425 | if show_progress: 426 | log.info('symbols are: {0}'.format(self._symbols)) 427 | self._df_metadata=create_metadata(len(self._symbols)) 428 | if show_progress: 429 | log.info('writing data...') 430 | if self._every_min_bar: 431 | minute_bar_writer.write(self._read_and_convert(calendar, show_progress), show_progress=show_progress) 432 | else: 433 | daily_bar_writer.write(self._read_and_convert(calendar, show_progress), show_progress=show_progress) 434 | if show_progress: 435 | log.info('meta data:\n{0}'.format(self._df_metadata)) 436 | asset_db_writer.write(equities=self._df_metadata) 437 | adjustment_writer.write() 438 | if show_progress: 439 | log.info('writing completed') 440 | -------------------------------------------------------------------------------- /data/AAPL.csv: -------------------------------------------------------------------------------- 1 | Date,Open,High,Low,Close,Adj Close,Volume 2 | 2019-07-02,201.410004,203.130005,201.360001,202.729996,200.339050,16935200 3 | 2019-07-03,203.279999,204.440002,202.690002,204.410004,201.999237,11362000 4 | 2019-07-05,203.350006,205.080002,202.899994,204.229996,201.821350,17265500 5 | 2019-07-08,200.809998,201.399994,198.410004,200.020004,197.661011,25338600 6 | 2019-07-09,199.199997,201.509995,198.809998,201.240005,198.866638,20578000 7 | 2019-07-10,201.850006,203.729996,201.559998,203.229996,200.833160,17897100 8 | 2019-07-11,203.309998,204.389999,201.710007,201.750000,199.370621,20191800 9 | 2019-07-12,202.449997,204.000000,202.199997,203.300003,200.902344,17595200 10 | 2019-07-15,204.089996,205.869995,204.000000,205.210007,202.789810,16947400 11 | 2019-07-16,204.589996,206.110001,203.500000,204.500000,202.088181,16866800 12 | 2019-07-17,204.050003,205.089996,203.270004,203.350006,200.951736,14107500 13 | 2019-07-18,204.000000,205.880005,203.699997,205.660004,203.234497,18582200 14 | 2019-07-19,205.789993,206.500000,202.360001,202.589996,200.200699,20929300 15 | 2019-07-22,203.649994,207.229996,203.610001,207.220001,204.776108,22277900 16 | 2019-07-23,208.460007,208.910004,207.289993,208.839996,206.376984,18355200 17 | 2019-07-24,207.669998,209.149994,207.169998,208.669998,206.209015,14991600 18 | 2019-07-25,208.889999,209.240005,206.729996,207.020004,204.578476,13909600 19 | 2019-07-26,207.479996,209.729996,207.139999,207.740005,205.289978,17618900 20 | 2019-07-29,208.460007,210.639999,208.440002,209.679993,207.207077,21673400 21 | 2019-07-30,208.759995,210.160004,207.309998,208.779999,206.317688,33935700 22 | 2019-07-31,216.419998,221.369995,211.300003,213.039993,210.527466,69281400 23 | 2019-08-01,213.899994,218.029999,206.740005,208.429993,205.971817,54017900 24 | 2019-08-02,205.529999,206.429993,201.630005,204.020004,201.613846,40862100 25 | 2019-08-05,197.990005,198.649994,192.580002,193.339996,191.059784,52393000 26 | 2019-08-06,196.309998,198.070007,194.039993,197.000000,194.676620,35824800 27 | 2019-08-07,195.410004,199.559998,193.820007,199.039993,196.692566,33364400 28 | 2019-08-08,200.199997,203.529999,199.389999,203.429993,201.030792,27009500 29 | 2019-08-09,201.300003,202.759995,199.289993,200.990005,199.374222,24619700 30 | 2019-08-12,199.619995,202.050003,199.149994,200.479996,198.868317,22474900 31 | 2019-08-13,201.020004,212.139999,200.479996,208.970001,207.290085,47218500 32 | 2019-08-14,203.160004,206.440002,202.589996,202.750000,201.120071,36547400 33 | 2019-08-15,203.460007,205.139999,199.669998,201.740005,200.118195,27227400 34 | 2019-08-16,204.279999,207.160004,203.839996,206.500000,204.839920,27620400 35 | 2019-08-19,210.619995,212.729996,210.029999,210.350006,208.658981,24413600 36 | 2019-08-20,210.880005,213.350006,210.320007,210.360001,208.668900,26884300 37 | 2019-08-21,212.990005,213.649994,211.600006,212.639999,210.930573,21535400 38 | 2019-08-22,213.190002,214.440002,210.750000,212.460007,210.752029,22253700 39 | 2019-08-23,209.429993,212.050003,201.000000,202.639999,201.010971,46818000 40 | 2019-08-26,205.860001,207.190002,205.059998,206.490005,204.830002,26043600 41 | 2019-08-27,207.860001,208.550003,203.529999,204.160004,202.518738,25873300 42 | 2019-08-28,204.100006,205.720001,203.320007,205.529999,203.877731,15938800 43 | 2019-08-29,208.500000,209.320007,206.660004,209.009995,207.329742,20990500 44 | 2019-08-30,210.160004,210.449997,207.199997,208.740005,207.061920,21143400 45 | 2019-09-03,206.429993,206.979996,204.220001,205.699997,204.046341,20023000 46 | 2019-09-04,208.389999,209.479996,207.320007,209.190002,207.508316,19188100 47 | 2019-09-05,212.000000,213.970001,211.509995,213.279999,211.565414,23913700 48 | 2019-09-06,214.050003,214.419998,212.509995,213.259995,211.545578,19362300 49 | 2019-09-09,214.839996,216.440002,211.070007,214.169998,212.448273,27309400 50 | 2019-09-10,213.860001,216.779999,211.710007,216.699997,214.957916,31777900 51 | 2019-09-11,218.070007,223.710007,217.729996,223.589996,221.792542,44289600 52 | 2019-09-12,224.800003,226.419998,222.860001,223.089996,221.296555,32226700 53 | 2019-09-13,220.000000,220.789993,217.020004,218.750000,216.991455,39763300 54 | 2019-09-16,217.729996,220.130005,217.559998,219.899994,218.132202,21158100 55 | 2019-09-17,219.960007,220.820007,219.119995,220.699997,218.925781,18318700 56 | 2019-09-18,221.059998,222.850006,219.440002,222.770004,220.979141,25340000 57 | 2019-09-19,222.009995,223.759995,220.369995,220.960007,219.183701,22060600 58 | 2019-09-20,221.380005,222.559998,217.470001,217.729996,215.979630,55413100 59 | 2019-09-23,218.949997,219.839996,217.649994,218.720001,216.961685,19165500 60 | 2019-09-24,221.029999,222.490005,217.190002,217.679993,215.930038,31190800 61 | 2019-09-25,218.550003,221.500000,217.139999,221.029999,219.253113,21903400 62 | 2019-09-26,220.000000,220.940002,218.830002,219.889999,218.122284,18833500 63 | 2019-09-27,220.539993,220.960007,217.279999,218.820007,217.060898,25352000 64 | 2019-09-30,220.899994,224.580002,220.789993,223.970001,222.169479,25977400 65 | 2019-10-01,225.070007,228.220001,224.199997,224.589996,222.784500,34805800 66 | 2019-10-02,223.059998,223.580002,217.929993,218.960007,217.199768,34612300 67 | 2019-10-03,218.429993,220.960007,215.130005,220.820007,219.044800,28606500 68 | 2019-10-04,225.639999,227.490005,223.889999,227.009995,225.185043,34619700 69 | 2019-10-07,226.270004,229.929993,225.839996,227.059998,225.234634,30576500 70 | 2019-10-08,225.820007,228.059998,224.330002,224.399994,222.596024,27955000 71 | 2019-10-09,227.029999,227.789993,225.639999,227.029999,225.204895,18692600 72 | 2019-10-10,227.929993,230.440002,227.300003,230.089996,228.240280,28253400 73 | 2019-10-11,232.949997,237.639999,232.309998,236.210007,234.311081,41698900 74 | 2019-10-14,234.899994,238.130005,234.669998,235.869995,233.973816,24106900 75 | 2019-10-15,236.389999,237.649994,234.880005,235.320007,233.428253,21840000 76 | 2019-10-16,233.369995,235.240005,233.199997,234.369995,232.485870,18475800 77 | 2019-10-17,235.089996,236.149994,233.520004,235.279999,233.388565,16896300 78 | 2019-10-18,234.589996,237.580002,234.289993,236.410004,234.509491,24358400 79 | 2019-10-21,237.520004,240.990005,237.320007,240.509995,238.576508,21811800 80 | 2019-10-22,241.160004,242.199997,239.619995,239.960007,238.030945,20573400 81 | 2019-10-23,242.100006,243.240005,241.220001,243.179993,241.225052,18957200 82 | 2019-10-24,244.509995,244.800003,241.809998,243.580002,241.621826,17318800 83 | 2019-10-25,243.160004,246.729996,242.880005,246.580002,244.597717,18369300 84 | 2019-10-28,247.419998,249.250000,246.720001,249.050003,247.047867,24143200 85 | 2019-10-29,248.970001,249.750000,242.570007,243.289993,241.334152,35709900 86 | 2019-10-30,244.759995,245.300003,241.210007,243.259995,241.304398,31130500 87 | 2019-10-31,247.240005,249.169998,237.259995,248.759995,246.760193,34790500 88 | 2019-11-01,249.539993,255.929993,249.160004,255.820007,253.763443,37781300 89 | 2019-11-04,257.329987,257.850006,255.380005,257.500000,255.429932,25818000 90 | 2019-11-05,257.049988,258.190002,256.320007,257.130005,255.062927,19974400 91 | 2019-11-06,256.769989,257.489990,255.369995,257.239990,255.172012,18966100 92 | 2019-11-07,258.739990,260.350006,258.109985,259.429993,258.117004,23735100 93 | 2019-11-08,258.690002,260.440002,256.850006,260.140015,258.823456,17496600 94 | 2019-11-11,258.299988,262.470001,258.279999,262.200012,260.873016,20455300 95 | 2019-11-12,261.549988,262.790009,260.920013,261.959991,260.634216,21847200 96 | 2019-11-13,261.130005,264.779999,261.070007,264.470001,263.131531,25683600 97 | 2019-11-14,263.750000,264.880005,262.100006,262.640015,261.310791,22295700 98 | 2019-11-15,263.679993,265.779999,263.010010,265.760010,264.415009,25051600 99 | 2019-11-18,265.799988,267.429993,264.230011,267.100006,265.748230,21675800 100 | 2019-11-19,267.899994,268.000000,265.390015,266.290009,264.942322,19041800 101 | 2019-11-20,265.540009,266.079987,260.399994,263.190002,261.858032,26558600 102 | 2019-11-21,263.690002,264.010010,261.179993,262.010010,260.683990,30348800 103 | 2019-11-22,262.589996,263.179993,260.839996,261.779999,260.455139,16331300 104 | 2019-11-25,262.709991,266.440002,262.519989,266.369995,265.021912,21005100 105 | 2019-11-26,266.940002,267.160004,262.500000,264.290009,262.952423,26301900 106 | 2019-11-27,265.579987,267.980011,265.309998,267.839996,266.484467,16308900 107 | 2019-11-29,266.600006,268.000000,265.899994,267.250000,265.897461,11654400 108 | 2019-12-02,267.269989,268.250000,263.450012,264.160004,262.823090,23621800 109 | 2019-12-03,258.309998,259.529999,256.290009,259.450012,258.136963,28607600 110 | 2019-12-04,261.070007,263.309998,260.679993,261.739990,260.415344,16795400 111 | 2019-12-05,263.790009,265.890015,262.730011,265.579987,264.235901,18606100 112 | 2019-12-06,267.480011,271.000000,267.299988,270.709991,269.339935,26518900 113 | 2019-12-09,270.000000,270.799988,264.910004,266.920013,265.569122,32010600 114 | 2019-12-10,268.600006,270.070007,265.859985,268.480011,267.121246,22605100 115 | 2019-12-11,268.809998,271.100006,268.500000,270.769989,269.399658,19689200 116 | 2019-12-12,267.779999,272.559998,267.320007,271.459991,270.086151,34327600 117 | 2019-12-13,271.459991,275.299988,270.929993,275.149994,273.757477,33396900 118 | 2019-12-16,277.000000,280.790009,276.980011,279.859985,278.443604,32046500 119 | 2019-12-17,279.570007,281.769989,278.799988,280.410004,278.990875,28539600 120 | 2019-12-18,279.799988,281.899994,279.119995,279.739990,278.324249,29007100 121 | 2019-12-19,279.500000,281.179993,278.950012,280.019989,278.602814,24592300 122 | 2019-12-20,282.230011,282.649994,278.559998,279.440002,278.025757,68994500 123 | 2019-12-23,280.529999,284.250000,280.369995,284.000000,282.562683,24643000 124 | 2019-12-24,284.690002,284.890015,282.920013,284.269989,282.831299,12119700 125 | 2019-12-26,284.820007,289.980011,284.700012,289.910004,288.442780,23280300 126 | 2019-12-27,291.119995,293.970001,288.119995,289.799988,288.333313,36566500 127 | 2019-12-30,289.459991,292.690002,285.220001,291.519989,290.044617,36028600 128 | 2019-12-31,289.929993,293.679993,289.519989,293.649994,292.163818,25201400 129 | 2020-01-02,296.239990,300.600006,295.190002,300.350006,298.829956,33870100 130 | 2020-01-03,297.149994,300.579987,296.500000,297.429993,295.924713,36580700 131 | 2020-01-06,293.790009,299.959991,292.750000,299.799988,298.282715,29596800 132 | 2020-01-07,299.839996,300.899994,297.480011,298.390015,296.879883,27218000 133 | 2020-01-08,297.160004,304.440002,297.160004,303.190002,301.655548,33019800 134 | 2020-01-09,307.239990,310.429993,306.200012,309.630005,308.062988,42527100 135 | 2020-01-10,310.600006,312.670013,308.250000,310.329987,308.759399,35161200 136 | 2020-01-13,311.640015,317.070007,311.149994,316.959991,315.355865,30383000 137 | 2020-01-14,316.700012,317.570007,312.170013,312.679993,311.097534,40488600 138 | 2020-01-15,311.850006,315.500000,309.549988,311.339996,309.764313,30480900 139 | 2020-01-16,313.589996,315.700012,312.089996,315.239990,313.644562,27207300 140 | 2020-01-17,316.269989,318.739990,315.000000,318.730011,317.116943,34454100 141 | 2020-01-21,317.190002,319.019989,316.000000,316.570007,314.967865,27710800 142 | 2020-01-22,318.579987,319.989990,317.309998,317.700012,316.092163,25458100 143 | 2020-01-23,317.920013,319.559998,315.649994,319.230011,317.614410,26118000 144 | 2020-01-24,320.250000,323.329987,317.519989,318.309998,316.699036,36634400 145 | 2020-01-27,310.059998,311.769989,304.880005,308.950012,307.386414,40485000 146 | 2020-01-28,312.600006,318.399994,312.190002,317.690002,316.082184,40558500 147 | 2020-01-29,324.450012,327.850006,321.380005,324.339996,322.698517,54057300 148 | 2020-01-30,320.540009,324.089996,318.750000,323.869995,322.230896,31685800 149 | 2020-01-31,320.929993,322.679993,308.290009,309.510010,307.943604,49897100 150 | 2020-02-03,304.299988,313.489990,302.220001,308.660004,307.097900,43496400 151 | 2020-02-04,315.309998,319.640015,313.630005,318.850006,317.236298,34154100 152 | 2020-02-05,323.519989,324.760010,318.950012,321.450012,319.823181,29706700 153 | 2020-02-06,322.570007,325.220001,320.260010,325.209991,323.564117,26356400 154 | 2020-02-07,322.369995,323.399994,318.000000,320.029999,319.166016,29421000 155 | 2020-02-10,314.179993,321.549988,313.850006,321.549988,320.681915,27337200 156 | 2020-02-11,323.600006,323.899994,318.709991,319.609985,318.747131,23580800 157 | 2020-02-12,321.470001,327.220001,321.470001,327.200012,326.316681,28432600 158 | 2020-02-13,324.190002,326.220001,323.350006,324.869995,323.992950,23686900 159 | 2020-02-14,324.739990,325.980011,322.850006,324.950012,324.072754,20028400 160 | 2020-02-18,315.359985,319.750000,314.609985,319.000000,318.138794,38132800 161 | 2020-02-19,320.000000,324.570007,320.000000,323.619995,322.746338,23496000 162 | 2020-02-20,322.630005,324.649994,318.209991,320.299988,319.435272,25141500 163 | 2020-02-21,318.619995,320.450012,310.500000,313.049988,312.204865,32388500 164 | 2020-02-24,297.260010,304.179993,289.230011,298.179993,297.375000,55548800 165 | 2020-02-25,300.950012,302.529999,286.130005,288.079987,287.302277,57668400 166 | 2020-02-26,286.529999,297.880005,286.500000,292.649994,291.859924,49513700 167 | 2020-02-27,281.100006,286.000000,272.959991,273.519989,272.781586,79834500 168 | 2020-02-28,257.260010,278.410004,256.369995,273.359985,272.622009,106721200 169 | 2020-03-02,282.279999,301.440002,277.720001,298.809998,298.003296,85349300 170 | 2020-03-03,303.670013,304.000000,285.799988,289.320007,288.538940,79868900 171 | 2020-03-04,296.440002,303.399994,293.130005,302.739990,301.922699,54794600 172 | 2020-03-05,295.519989,299.549988,291.410004,292.920013,292.129211,46893200 173 | 2020-03-06,282.000000,290.820007,281.230011,289.029999,288.249725,56544200 174 | 2020-03-09,263.750000,278.089996,263.000000,266.170013,265.451447,71686200 175 | 2020-03-10,277.140015,286.440002,269.369995,285.339996,284.569672,71322500 176 | 2020-03-11,277.390015,281.220001,271.859985,275.429993,274.686432,63899700 177 | 2020-03-12,255.940002,270.000000,248.000000,248.229996,247.559860,104618500 178 | 2020-03-13,264.890015,279.920013,252.949997,277.970001,277.219574,92683000 179 | 2020-03-16,241.949997,259.079987,240.000000,242.210007,241.556122,80605900 180 | 2020-03-17,247.509995,257.609985,238.399994,252.860001,252.177368,81014000 181 | 2020-03-18,239.770004,250.000000,237.119995,246.669998,246.004074,75058400 182 | 2020-03-19,247.389999,252.839996,242.610001,244.779999,244.119171,67964300 183 | 2020-03-20,247.179993,251.830002,228.000000,229.240005,228.621140,100423300 184 | 2020-03-23,228.080002,228.500000,212.610001,224.369995,223.764267,84188200 185 | 2020-03-24,236.360001,247.690002,234.300003,246.880005,246.213516,71882800 186 | 2020-03-25,250.750000,258.250000,244.300003,245.520004,244.857178,75900500 187 | 2020-03-26,246.520004,258.679993,246.360001,258.440002,257.742310,63021800 188 | 2020-03-27,252.750000,255.869995,247.050003,247.740005,247.071182,51054200 189 | 2020-03-30,250.740005,255.520004,249.399994,254.809998,254.122101,41994100 190 | 2020-03-31,255.600006,262.489990,252.000000,254.289993,253.603500,49250500 191 | 2020-04-01,246.500000,248.720001,239.130005,240.910004,240.259628,44054600 192 | 2020-04-02,240.339996,245.149994,236.899994,244.929993,244.268768,41483500 193 | 2020-04-03,242.800003,245.699997,238.970001,241.410004,240.758270,32470000 194 | 2020-04-06,250.899994,263.109985,249.380005,262.470001,261.761414,50455100 195 | 2020-04-07,270.799988,271.700012,259.000000,259.429993,258.729614,50721800 196 | 2020-04-08,262.739990,267.369995,261.230011,266.070007,265.351715,42223800 197 | 2020-04-09,268.700012,270.070007,264.700012,267.989990,267.266510,40529100 198 | 2020-04-13,268.309998,273.700012,265.829987,273.250000,272.512329,32755700 199 | 2020-04-14,280.000000,288.250000,278.049988,287.049988,286.275055,48748700 200 | 2020-04-15,282.399994,286.329987,280.630005,284.429993,283.662140,32788600 201 | 2020-04-16,287.380005,288.200012,282.350006,286.690002,285.916046,39281300 202 | 2020-04-17,284.690002,286.950012,276.859985,282.799988,282.036530,53812500 203 | 2020-04-20,277.950012,281.679993,276.850006,276.929993,276.182373,32503800 204 | 2020-04-21,276.279999,277.250000,265.429993,268.369995,267.645477,45247900 205 | 2020-04-22,273.609985,277.899994,272.200012,276.100006,275.354614,29264300 206 | 2020-04-23,275.869995,281.750000,274.869995,275.029999,274.287506,31203600 207 | 2020-04-24,277.200012,283.010010,277.000000,282.970001,282.206085,31627200 208 | 2020-04-27,281.799988,284.540009,279.950012,283.170013,282.405548,29271900 209 | 2020-04-28,285.079987,285.829987,278.200012,278.579987,277.827911,28001200 210 | 2020-04-29,284.730011,289.670013,283.890015,287.730011,286.953247,34320200 211 | 2020-04-30,289.959991,294.529999,288.350006,293.799988,293.006836,45457600 212 | 2020-05-01,286.250000,299.000000,285.850006,289.070007,288.289612,60154200 213 | 2020-05-04,289.170013,293.690002,286.320007,293.160004,292.368561,33392000 214 | 2020-05-05,295.059998,301.000000,294.459991,297.559998,296.756683,36937800 215 | 2020-05-06,300.459991,303.239990,298.869995,300.630005,299.818390,35583400 216 | 2020-05-07,303.220001,305.170013,301.970001,303.739990,302.919983,28803800 217 | 2020-05-08,305.640015,310.350006,304.290009,310.130005,310.130005,33512000 218 | 2020-05-11,308.100006,317.049988,307.239990,315.010010,315.010010,36405900 219 | 2020-05-12,317.829987,319.690002,310.910004,311.410004,311.410004,40575300 220 | 2020-05-13,312.149994,315.950012,303.209991,307.649994,307.649994,50155600 221 | 2020-05-14,304.510010,309.790009,301.529999,309.540009,309.540009,39732300 222 | 2020-05-15,300.350006,307.899994,300.209991,307.709991,307.709991,41587100 223 | 2020-05-18,313.170013,316.500000,310.320007,314.959991,314.959991,33843100 224 | 2020-05-19,315.029999,318.519989,313.010010,313.140015,313.140015,25432400 225 | 2020-05-20,316.679993,319.519989,316.519989,319.230011,319.230011,27876200 226 | 2020-05-21,318.660004,320.890015,315.869995,316.850006,316.850006,25672200 227 | 2020-05-22,315.769989,319.230011,315.350006,318.890015,318.890015,20450800 228 | 2020-05-26,323.500000,324.239990,316.500000,316.730011,316.730011,31380500 229 | 2020-05-27,316.140015,318.709991,313.089996,318.109985,318.109985,28236300 230 | 2020-05-28,316.769989,323.440002,315.630005,318.250000,318.250000,33390200 231 | 2020-05-29,319.250000,321.149994,316.470001,317.940002,317.940002,38399500 232 | 2020-06-01,317.750000,322.350006,317.209991,321.850006,321.850006,20197800 233 | 2020-06-02,320.750000,323.440002,318.929993,323.339996,323.339996,21910700 234 | 2020-06-03,324.660004,326.200012,322.299988,325.119995,325.119995,26122800 235 | 2020-06-04,324.390015,325.619995,320.779999,322.320007,322.320007,21890100 236 | 2020-06-05,323.350006,331.750000,323.230011,331.500000,331.500000,34312600 237 | 2020-06-08,330.250000,333.600006,327.320007,333.459991,333.459991,23913600 238 | 2020-06-09,332.140015,345.609985,332.010010,343.989990,343.989990,36928100 239 | 2020-06-10,347.899994,354.769989,346.089996,352.839996,352.839996,41662900 240 | 2020-06-11,349.309998,351.059998,335.480011,335.899994,335.899994,50415600 241 | 2020-06-12,344.720001,347.799988,334.220001,338.799988,338.799988,50001500 242 | 2020-06-15,333.250000,345.679993,332.579987,342.989990,342.989990,34702200 243 | 2020-06-16,351.459991,353.200012,344.720001,352.079987,352.079987,41357200 244 | 2020-06-17,355.149994,355.399994,351.089996,351.589996,351.589996,28532000 245 | 2020-06-18,351.410004,353.450012,349.220001,351.730011,351.730011,24205100 246 | 2020-06-19,354.640015,356.559998,345.149994,349.720001,349.720001,66119000 247 | 2020-06-22,351.339996,359.459991,351.149994,358.869995,358.869995,33861300 248 | 2020-06-23,364.000000,372.380005,362.269989,366.529999,366.529999,53038900 249 | 2020-06-24,365.000000,368.790009,358.519989,360.059998,360.059998,48155800 250 | 2020-06-25,360.700012,365.000000,357.570007,364.839996,364.839996,34380600 251 | 2020-06-26,364.410004,365.320007,353.019989,353.630005,353.630005,51314200 252 | 2020-06-29,353.250000,362.170013,351.279999,361.779999,361.779999,32661500 253 | 2020-06-30,360.079987,365.980011,360.000000,364.799988,364.799988,35055800 254 | 2020-07-01,365.119995,367.359985,363.910004,364.109985,364.109985,27638400 255 | 2020-07-02,367.850006,370.470001,365.670013,366.470001,366.470001,18439383 -------------------------------------------------------------------------------- /data/SPY.csv: -------------------------------------------------------------------------------- 1 | Date,Open,High,Low,Close,Adj Close,Volume 2 | 2019-07-02,2964.659912,2973.209961,2955.919922,2973.010010,2973.010010,3206840000 3 | 2019-07-03,2978.080078,2995.840088,2977.959961,2995.820068,2995.820068,1963720000 4 | 2019-07-05,2984.250000,2994.030029,2967.969971,2990.409912,2990.409912,2434210000 5 | 2019-07-08,2979.770020,2980.760010,2970.090088,2975.949951,2975.949951,2904550000 6 | 2019-07-09,2965.520020,2981.899902,2963.439941,2979.629883,2979.629883,3028210000 7 | 2019-07-10,2989.300049,3002.979980,2984.620117,2993.070068,2993.070068,3154240000 8 | 2019-07-11,2999.620117,3002.330078,2988.800049,2999.909912,2999.909912,3154620000 9 | 2019-07-12,3003.360107,3013.919922,3001.870117,3013.770020,3013.770020,2974960000 10 | 2019-07-15,3017.800049,3017.800049,3008.770020,3014.300049,3014.300049,2874970000 11 | 2019-07-16,3012.129883,3015.020020,3001.149902,3004.040039,3004.040039,3290650000 12 | 2019-07-17,3005.100098,3005.260010,2984.250000,2984.419922,2984.419922,3181600000 13 | 2019-07-18,2978.870117,2998.280029,2973.090088,2995.110107,2995.110107,3296580000 14 | 2019-07-19,3004.260010,3006.020020,2975.860107,2976.610107,2976.610107,3260360000 15 | 2019-07-22,2981.929932,2990.709961,2976.649902,2985.030029,2985.030029,3003720000 16 | 2019-07-23,2994.739990,3005.899902,2988.560059,3005.469971,3005.469971,3313660000 17 | 2019-07-24,2998.770020,3019.590088,2996.820068,3019.560059,3019.560059,3428980000 18 | 2019-07-25,3016.260010,3016.310059,2997.239990,3003.669922,3003.669922,3645270000 19 | 2019-07-26,3013.250000,3027.979980,3012.590088,3025.860107,3025.860107,3257590000 20 | 2019-07-29,3024.469971,3025.610107,3014.300049,3020.969971,3020.969971,3203710000 21 | 2019-07-30,3007.659912,3017.189941,3000.939941,3013.179932,3013.179932,3634330000 22 | 2019-07-31,3016.219971,3017.399902,2958.080078,2980.379883,2980.379883,4623430000 23 | 2019-08-01,2980.320068,3013.590088,2945.229980,2953.560059,2953.560059,4762300000 24 | 2019-08-02,2943.899902,2945.500000,2914.110107,2932.050049,2932.050049,3874660000 25 | 2019-08-05,2898.070068,2898.070068,2822.120117,2844.739990,2844.739990,4513730000 26 | 2019-08-06,2861.179932,2884.399902,2847.419922,2881.770020,2881.770020,4154240000 27 | 2019-08-07,2858.649902,2892.169922,2825.709961,2883.979980,2883.979980,4491750000 28 | 2019-08-08,2896.209961,2938.719971,2894.469971,2938.090088,2938.090088,4106370000 29 | 2019-08-09,2930.510010,2935.750000,2900.149902,2918.649902,2918.649902,3350640000 30 | 2019-08-12,2907.070068,2907.580078,2873.139893,2882.699951,2882.699951,2851630000 31 | 2019-08-13,2880.719971,2943.310059,2877.050049,2926.320068,2926.320068,3853600000 32 | 2019-08-14,2894.149902,2894.149902,2839.639893,2840.600098,2840.600098,4312530000 33 | 2019-08-15,2846.199951,2856.669922,2825.510010,2847.600098,2847.600098,4038000000 34 | 2019-08-16,2864.739990,2893.629883,2864.739990,2888.679932,2888.679932,3498150000 35 | 2019-08-19,2913.479980,2931.000000,2913.479980,2923.649902,2923.649902,3212880000 36 | 2019-08-20,2919.010010,2923.629883,2899.600098,2900.510010,2900.510010,3066300000 37 | 2019-08-21,2922.040039,2928.729980,2917.909912,2924.429932,2924.429932,3011190000 38 | 2019-08-22,2930.939941,2939.080078,2904.510010,2922.949951,2922.949951,2890880000 39 | 2019-08-23,2911.070068,2927.010010,2834.969971,2847.110107,2847.110107,3937300000 40 | 2019-08-26,2866.699951,2879.270020,2856.000000,2878.379883,2878.379883,2857600000 41 | 2019-08-27,2893.139893,2898.790039,2860.590088,2869.159912,2869.159912,3533630000 42 | 2019-08-28,2861.280029,2890.030029,2853.050049,2887.939941,2887.939941,3097420000 43 | 2019-08-29,2910.370117,2930.500000,2905.669922,2924.580078,2924.580078,3176190000 44 | 2019-08-30,2937.090088,2940.429932,2913.320068,2926.459961,2926.459961,3008450000 45 | 2019-09-03,2909.010010,2914.389893,2891.850098,2906.270020,2906.270020,3426790000 46 | 2019-09-04,2924.669922,2938.840088,2921.860107,2937.780029,2937.780029,3163260000 47 | 2019-09-05,2960.600098,2985.860107,2960.600098,2976.000000,2976.000000,3890700000 48 | 2019-09-06,2980.330078,2985.030029,2972.510010,2978.709961,2978.709961,3208280000 49 | 2019-09-09,2988.429932,2989.429932,2969.389893,2978.429932,2978.429932,4002890000 50 | 2019-09-10,2971.010010,2979.389893,2957.010010,2979.389893,2979.389893,4390770000 51 | 2019-09-11,2981.409912,3000.929932,2975.310059,3000.929932,3000.929932,3927550000 52 | 2019-09-12,3009.080078,3020.739990,3000.919922,3009.570068,3009.570068,3791860000 53 | 2019-09-13,3012.209961,3017.330078,3002.899902,3007.389893,3007.389893,3520060000 54 | 2019-09-16,2996.409912,3002.189941,2990.669922,2997.959961,2997.959961,4274640000 55 | 2019-09-17,2995.669922,3006.209961,2993.729980,3005.699951,3005.699951,3671840000 56 | 2019-09-18,3001.500000,3007.830078,2978.570068,3006.729980,3006.729980,3435540000 57 | 2019-09-19,3010.360107,3021.989990,3003.159912,3006.790039,3006.790039,3251290000 58 | 2019-09-20,3008.419922,3016.370117,2984.679932,2992.070068,2992.070068,6094740000 59 | 2019-09-23,2983.500000,2999.149902,2982.229980,2991.780029,2991.780029,3186590000 60 | 2019-09-24,3002.429932,3007.979980,2957.729980,2966.600098,2966.600098,3868160000 61 | 2019-09-25,2968.350098,2989.820068,2952.860107,2984.870117,2984.870117,3318870000 62 | 2019-09-26,2985.729980,2987.280029,2963.709961,2977.620117,2977.620117,3077240000 63 | 2019-09-27,2985.469971,2987.310059,2945.530029,2961.790039,2961.790039,3243650000 64 | 2019-09-30,2967.070068,2983.850098,2967.070068,2976.739990,2976.739990,3247610000 65 | 2019-10-01,2983.689941,2992.530029,2938.699951,2940.250000,2940.250000,3558040000 66 | 2019-10-02,2924.780029,2924.780029,2874.929932,2887.610107,2887.610107,3912520000 67 | 2019-10-03,2885.379883,2911.129883,2855.939941,2910.629883,2910.629883,3503640000 68 | 2019-10-04,2918.560059,2953.739990,2918.560059,2952.010010,2952.010010,2990830000 69 | 2019-10-07,2944.229980,2959.750000,2935.679932,2938.790039,2938.790039,2940140000 70 | 2019-10-08,2920.399902,2925.469971,2892.659912,2893.060059,2893.060059,3356450000 71 | 2019-10-09,2911.100098,2929.320068,2907.409912,2919.399902,2919.399902,2726820000 72 | 2019-10-10,2918.550049,2948.459961,2917.120117,2938.129883,2938.129883,3217250000 73 | 2019-10-11,2963.070068,2993.280029,2963.070068,2970.270020,2970.270020,3580460000 74 | 2019-10-14,2965.810059,2972.840088,2962.939941,2966.149902,2966.149902,2557020000 75 | 2019-10-15,2973.610107,3003.280029,2973.610107,2995.679932,2995.679932,3340740000 76 | 2019-10-16,2989.679932,2997.540039,2985.199951,2989.689941,2989.689941,3222570000 77 | 2019-10-17,3000.770020,3008.290039,2991.790039,2997.949951,2997.949951,3115960000 78 | 2019-10-18,2996.840088,3000.000000,2976.310059,2986.199951,2986.199951,3264290000 79 | 2019-10-21,2996.479980,3007.330078,2995.350098,3006.719971,3006.719971,3271620000 80 | 2019-10-22,3010.729980,3014.570068,2995.040039,2995.989990,2995.989990,3523890000 81 | 2019-10-23,2994.010010,3004.780029,2991.209961,3004.520020,3004.520020,3392870000 82 | 2019-10-24,3014.780029,3016.070068,3000.419922,3010.290039,3010.290039,3692600000 83 | 2019-10-25,3003.320068,3027.389893,3001.939941,3022.550049,3022.550049,3370370000 84 | 2019-10-28,3032.120117,3044.080078,3032.120117,3039.419922,3039.419922,3521230000 85 | 2019-10-29,3035.389893,3047.870117,3034.810059,3036.889893,3036.889893,3589930000 86 | 2019-10-30,3039.739990,3050.100098,3025.959961,3046.770020,3046.770020,3776030000 87 | 2019-10-31,3046.899902,3046.899902,3023.189941,3037.560059,3037.560059,4139280000 88 | 2019-11-01,3050.719971,3066.949951,3050.719971,3066.909912,3066.909912,3930200000 89 | 2019-11-04,3078.959961,3085.199951,3074.870117,3078.270020,3078.270020,4146850000 90 | 2019-11-05,3080.800049,3083.949951,3072.149902,3074.620117,3074.620117,4486130000 91 | 2019-11-06,3075.100098,3078.340088,3065.889893,3076.780029,3076.780029,4458190000 92 | 2019-11-07,3087.020020,3097.770020,3080.229980,3085.179932,3085.179932,4144640000 93 | 2019-11-08,3081.250000,3093.090088,3073.580078,3093.080078,3093.080078,3499150000 94 | 2019-11-11,3080.330078,3088.330078,3075.820068,3087.010010,3087.010010,3035530000 95 | 2019-11-12,3089.280029,3102.610107,3084.729980,3091.840088,3091.840088,3466010000 96 | 2019-11-13,3084.179932,3098.060059,3078.800049,3094.040039,3094.040039,3509280000 97 | 2019-11-14,3090.750000,3098.199951,3083.260010,3096.629883,3096.629883,3276070000 98 | 2019-11-15,3107.919922,3120.459961,3104.600098,3120.459961,3120.459961,3335650000 99 | 2019-11-18,3117.909912,3124.169922,3112.060059,3122.030029,3122.030029,3436690000 100 | 2019-11-19,3127.449951,3127.639893,3113.469971,3120.179932,3120.179932,3590070000 101 | 2019-11-20,3114.659912,3118.969971,3091.409912,3108.459961,3108.459961,4034890000 102 | 2019-11-21,3108.489990,3110.110107,3094.550049,3103.540039,3103.540039,3720560000 103 | 2019-11-22,3111.409912,3112.870117,3099.260010,3110.290039,3110.290039,3226780000 104 | 2019-11-25,3117.439941,3133.830078,3117.439941,3133.639893,3133.639893,3511530000 105 | 2019-11-26,3134.850098,3142.689941,3131.000000,3140.520020,3140.520020,4595590000 106 | 2019-11-27,3145.489990,3154.260010,3143.409912,3153.629883,3153.629883,3033090000 107 | 2019-11-29,3147.179932,3150.300049,3139.340088,3140.979980,3140.979980,1743020000 108 | 2019-12-02,3143.850098,3144.310059,3110.780029,3113.870117,3113.870117,3268740000 109 | 2019-12-03,3087.409912,3094.969971,3070.330078,3093.199951,3093.199951,3653390000 110 | 2019-12-04,3103.500000,3119.379883,3102.530029,3112.760010,3112.760010,3695030000 111 | 2019-12-05,3119.209961,3119.449951,3103.760010,3117.429932,3117.429932,3355750000 112 | 2019-12-06,3134.620117,3150.600098,3134.620117,3145.909912,3145.909912,3479480000 113 | 2019-12-09,3141.860107,3148.870117,3135.459961,3135.959961,3135.959961,3345990000 114 | 2019-12-10,3135.360107,3142.120117,3126.090088,3132.520020,3132.520020,3343790000 115 | 2019-12-11,3135.750000,3143.979980,3133.209961,3141.629883,3141.629883,3252540000 116 | 2019-12-12,3141.229980,3176.280029,3138.469971,3168.570068,3168.570068,3990690000 117 | 2019-12-13,3166.649902,3182.679932,3156.510010,3168.800049,3168.800049,3736870000 118 | 2019-12-16,3183.629883,3197.709961,3183.629883,3191.449951,3191.449951,4051790000 119 | 2019-12-17,3195.399902,3198.219971,3191.030029,3192.520020,3192.520020,3837540000 120 | 2019-12-18,3195.209961,3198.479980,3191.139893,3191.139893,3191.139893,4014080000 121 | 2019-12-19,3192.320068,3205.479980,3192.320068,3205.370117,3205.370117,3720450000 122 | 2019-12-20,3223.330078,3225.649902,3216.030029,3221.219971,3221.219971,6454270000 123 | 2019-12-23,3226.050049,3227.780029,3222.300049,3224.010010,3224.010010,3060610000 124 | 2019-12-24,3225.449951,3226.429932,3220.510010,3223.379883,3223.379883,1296540000 125 | 2019-12-26,3227.199951,3240.080078,3227.199951,3239.909912,3239.909912,2160680000 126 | 2019-12-27,3247.229980,3247.929932,3234.370117,3240.020020,3240.020020,2428670000 127 | 2019-12-30,3240.090088,3240.919922,3216.570068,3221.290039,3221.290039,3013290000 128 | 2019-12-31,3215.179932,3231.719971,3212.030029,3230.780029,3230.780029,2893810000 129 | 2020-01-02,3244.669922,3258.139893,3235.530029,3257.850098,3257.850098,3458250000 130 | 2020-01-03,3226.360107,3246.149902,3222.340088,3234.850098,3234.850098,3461290000 131 | 2020-01-06,3217.550049,3246.840088,3214.639893,3246.280029,3246.280029,3674070000 132 | 2020-01-07,3241.860107,3244.909912,3232.429932,3237.179932,3237.179932,3420380000 133 | 2020-01-08,3238.590088,3267.070068,3236.669922,3253.050049,3253.050049,3720890000 134 | 2020-01-09,3266.030029,3275.580078,3263.669922,3274.699951,3274.699951,3638390000 135 | 2020-01-10,3281.810059,3282.989990,3260.860107,3265.350098,3265.350098,3212970000 136 | 2020-01-13,3271.129883,3288.129883,3268.429932,3288.129883,3288.129883,3456380000 137 | 2020-01-14,3285.350098,3294.250000,3277.189941,3283.149902,3283.149902,3665130000 138 | 2020-01-15,3282.270020,3298.659912,3280.689941,3289.290039,3289.290039,3716840000 139 | 2020-01-16,3302.969971,3317.110107,3302.820068,3316.810059,3316.810059,3535080000 140 | 2020-01-17,3323.659912,3329.879883,3318.860107,3329.620117,3329.620117,3698170000 141 | 2020-01-21,3321.030029,3329.790039,3316.610107,3320.790039,3320.790039,4105340000 142 | 2020-01-22,3330.020020,3337.770020,3320.040039,3321.750000,3321.750000,3619850000 143 | 2020-01-23,3315.770020,3326.879883,3301.870117,3325.540039,3325.540039,3764860000 144 | 2020-01-24,3333.100098,3333.179932,3281.530029,3295.469971,3295.469971,3707130000 145 | 2020-01-27,3247.159912,3258.850098,3234.500000,3243.629883,3243.629883,3823100000 146 | 2020-01-28,3255.350098,3285.780029,3253.219971,3276.239990,3276.239990,3526720000 147 | 2020-01-29,3289.459961,3293.469971,3271.889893,3273.399902,3273.399902,3584500000 148 | 2020-01-30,3256.449951,3285.909912,3242.800049,3283.659912,3283.659912,3787250000 149 | 2020-01-31,3282.330078,3282.330078,3214.679932,3225.520020,3225.520020,4527830000 150 | 2020-02-03,3235.659912,3268.439941,3235.659912,3248.919922,3248.919922,3757910000 151 | 2020-02-04,3280.610107,3306.919922,3280.610107,3297.590088,3297.590088,3995320000 152 | 2020-02-05,3324.909912,3337.580078,3313.750000,3334.689941,3334.689941,4117730000 153 | 2020-02-06,3344.919922,3347.959961,3334.389893,3345.780029,3345.780029,3868370000 154 | 2020-02-07,3335.540039,3341.419922,3322.120117,3327.709961,3327.709961,3730650000 155 | 2020-02-10,3318.280029,3352.260010,3317.770020,3352.090088,3352.090088,3450350000 156 | 2020-02-11,3365.870117,3375.629883,3352.719971,3357.750000,3357.750000,3760550000 157 | 2020-02-12,3370.500000,3381.469971,3369.719971,3379.449951,3379.449951,3926380000 158 | 2020-02-13,3365.899902,3385.090088,3360.520020,3373.939941,3373.939941,3498240000 159 | 2020-02-14,3378.080078,3380.689941,3366.149902,3380.159912,3380.159912,3398040000 160 | 2020-02-18,3369.040039,3375.010010,3355.610107,3370.290039,3370.290039,3746720000 161 | 2020-02-19,3380.389893,3393.520020,3378.830078,3386.149902,3386.149902,3600150000 162 | 2020-02-20,3380.449951,3389.149902,3341.020020,3373.229980,3373.229980,4007320000 163 | 2020-02-21,3360.500000,3360.760010,3328.449951,3337.750000,3337.750000,3899270000 164 | 2020-02-24,3257.610107,3259.810059,3214.649902,3225.889893,3225.889893,4842960000 165 | 2020-02-25,3238.939941,3246.989990,3118.770020,3128.209961,3128.209961,5591510000 166 | 2020-02-26,3139.899902,3182.510010,3108.989990,3116.389893,3116.389893,5478110000 167 | 2020-02-27,3062.540039,3097.070068,2977.389893,2978.760010,2978.760010,7058840000 168 | 2020-02-28,2916.899902,2959.719971,2855.840088,2954.219971,2954.219971,8563850000 169 | 2020-03-02,2974.280029,3090.959961,2945.189941,3090.229980,3090.229980,6376400000 170 | 2020-03-03,3096.459961,3136.719971,2976.629883,3003.370117,3003.370117,6355940000 171 | 2020-03-04,3045.750000,3130.969971,3034.379883,3130.120117,3130.120117,5035480000 172 | 2020-03-05,3075.699951,3083.040039,2999.830078,3023.939941,3023.939941,5575550000 173 | 2020-03-06,2954.199951,2985.929932,2901.540039,2972.370117,2972.370117,6552140000 174 | 2020-03-09,2863.889893,2863.889893,2734.429932,2746.560059,2746.560059,8423050000 175 | 2020-03-10,2813.479980,2882.590088,2734.000000,2882.229980,2882.229980,7635960000 176 | 2020-03-11,2825.600098,2825.600098,2707.219971,2741.379883,2741.379883,7374110000 177 | 2020-03-12,2630.860107,2660.949951,2478.860107,2480.639893,2480.639893,8829380000 178 | 2020-03-13,2569.989990,2711.330078,2492.370117,2711.020020,2711.020020,8258670000 179 | 2020-03-16,2508.590088,2562.979980,2380.939941,2386.129883,2386.129883,7781540000 180 | 2020-03-17,2425.659912,2553.929932,2367.040039,2529.189941,2529.189941,8358500000 181 | 2020-03-18,2436.500000,2453.570068,2280.520020,2398.100098,2398.100098,8755780000 182 | 2020-03-19,2393.479980,2466.969971,2319.780029,2409.389893,2409.389893,7946710000 183 | 2020-03-20,2431.939941,2453.010010,2295.560059,2304.919922,2304.919922,9044690000 184 | 2020-03-23,2290.709961,2300.729980,2191.860107,2237.399902,2237.399902,7402180000 185 | 2020-03-24,2344.439941,2449.709961,2344.439941,2447.330078,2447.330078,7547350000 186 | 2020-03-25,2457.770020,2571.419922,2407.530029,2475.560059,2475.560059,8285670000 187 | 2020-03-26,2501.290039,2637.010010,2500.719971,2630.070068,2630.070068,7753160000 188 | 2020-03-27,2555.870117,2615.909912,2520.020020,2541.469971,2541.469971,6194330000 189 | 2020-03-30,2558.979980,2631.800049,2545.280029,2626.649902,2626.649902,5746220000 190 | 2020-03-31,2614.689941,2641.389893,2571.149902,2584.590088,2584.590088,6568290000 191 | 2020-04-01,2498.080078,2522.750000,2447.489990,2470.500000,2470.500000,5947900000 192 | 2020-04-02,2458.540039,2533.219971,2455.790039,2526.899902,2526.899902,6454990000 193 | 2020-04-03,2514.919922,2538.179932,2459.959961,2488.649902,2488.649902,6087190000 194 | 2020-04-06,2578.280029,2676.850098,2574.570068,2663.679932,2663.679932,6391860000 195 | 2020-04-07,2738.649902,2756.889893,2657.669922,2659.409912,2659.409912,7040720000 196 | 2020-04-08,2685.000000,2760.750000,2663.300049,2749.979980,2749.979980,5856370000 197 | 2020-04-09,2776.989990,2818.570068,2762.360107,2789.820068,2789.820068,7880140000 198 | 2020-04-13,2782.459961,2782.459961,2721.169922,2761.629883,2761.629883,5274310000 199 | 2020-04-14,2805.100098,2851.850098,2805.100098,2846.060059,2846.060059,5567400000 200 | 2020-04-15,2795.639893,2801.879883,2761.540039,2783.360107,2783.360107,5203390000 201 | 2020-04-16,2799.340088,2806.510010,2764.320068,2799.550049,2799.550049,5179990000 202 | 2020-04-17,2842.429932,2879.219971,2830.879883,2874.560059,2874.560059,5792140000 203 | 2020-04-20,2845.620117,2868.979980,2820.429932,2823.159912,2823.159912,5220160000 204 | 2020-04-21,2784.810059,2785.540039,2727.100098,2736.560059,2736.560059,5075830000 205 | 2020-04-22,2787.889893,2815.100098,2775.949951,2799.310059,2799.310059,5049660000 206 | 2020-04-23,2810.419922,2844.899902,2794.260010,2797.800049,2797.800049,5756520000 207 | 2020-04-24,2812.639893,2842.709961,2791.760010,2836.739990,2836.739990,5374480000 208 | 2020-04-27,2854.649902,2887.719971,2852.889893,2878.479980,2878.479980,5194260000 209 | 2020-04-28,2909.959961,2921.149902,2860.709961,2863.389893,2863.389893,5672880000 210 | 2020-04-29,2918.459961,2954.860107,2912.159912,2939.510010,2939.510010,6620140000 211 | 2020-04-30,2930.909912,2930.909912,2892.469971,2912.429932,2912.429932,6523120000 212 | 2020-05-01,2869.090088,2869.090088,2821.610107,2830.709961,2830.709961,4753160000 213 | 2020-05-04,2815.010010,2844.239990,2797.850098,2842.739990,2842.739990,4723140000 214 | 2020-05-05,2868.879883,2898.229980,2863.550049,2868.439941,2868.439941,5129590000 215 | 2020-05-06,2883.139893,2891.110107,2847.649902,2848.419922,2848.419922,4861920000 216 | 2020-05-07,2878.260010,2901.919922,2876.479980,2881.189941,2881.189941,5164640000 217 | 2020-05-08,2908.830078,2932.159912,2902.879883,2929.800049,2929.800049,4857160000 218 | 2020-05-11,2915.459961,2944.250000,2903.439941,2930.189941,2930.189941,4807320000 219 | 2020-05-12,2939.500000,2945.820068,2869.590088,2870.120117,2870.120117,5107710000 220 | 2020-05-13,2865.860107,2874.139893,2793.149902,2820.000000,2820.000000,6143130000 221 | 2020-05-14,2794.540039,2852.800049,2766.639893,2852.500000,2852.500000,5641920000 222 | 2020-05-15,2829.949951,2865.010010,2816.780029,2863.699951,2863.699951,5477040000 223 | 2020-05-18,2913.860107,2968.090088,2913.860107,2953.909912,2953.909912,6364290000 224 | 2020-05-19,2948.590088,2964.209961,2922.350098,2922.939941,2922.939941,4969330000 225 | 2020-05-20,2953.629883,2980.290039,2953.629883,2971.610107,2971.610107,4992970000 226 | 2020-05-21,2969.949951,2978.500000,2938.570068,2948.510010,2948.510010,4966940000 227 | 2020-05-22,2948.050049,2956.760010,2933.590088,2955.449951,2955.449951,3952800000 228 | 2020-05-26,3004.080078,3021.719971,2988.169922,2991.770020,2991.770020,5837060000 229 | 2020-05-27,3015.649902,3036.250000,2969.750000,3036.129883,3036.129883,6371230000 230 | 2020-05-28,3046.610107,3068.669922,3023.399902,3029.729980,3029.729980,5402670000 231 | 2020-05-29,3025.169922,3049.169922,2998.610107,3044.310059,3044.310059,7275080000 232 | 2020-06-01,3038.780029,3062.179932,3031.540039,3055.729980,3055.729980,4673410000 233 | 2020-06-02,3064.780029,3081.070068,3051.639893,3080.820068,3080.820068,5187230000 234 | 2020-06-03,3098.899902,3130.939941,3098.899902,3122.870117,3122.870117,5989560000 235 | 2020-06-04,3111.560059,3128.909912,3090.409912,3112.350098,3112.350098,6428130000 236 | 2020-06-05,3163.840088,3211.719971,3163.840088,3193.929932,3193.929932,8617590000 237 | 2020-06-08,3199.919922,3233.129883,3196.000000,3232.389893,3232.389893,8437380000 238 | 2020-06-09,3213.320068,3222.709961,3193.110107,3207.179932,3207.179932,6382620000 239 | 2020-06-10,3213.419922,3223.270020,3181.489990,3190.139893,3190.139893,6570840000 240 | 2020-06-11,3123.530029,3123.530029,2999.489990,3002.100098,3002.100098,7018890000 241 | 2020-06-12,3071.040039,3088.419922,2984.469971,3041.310059,3041.310059,5832250000 242 | 2020-06-15,2993.760010,3079.760010,2965.659912,3066.590088,3066.590088,5740660000 243 | 2020-06-16,3131.000000,3153.449951,3076.060059,3124.739990,3124.739990,5829240000 244 | 2020-06-17,3136.129883,3141.159912,3108.030029,3113.489990,3113.489990,4549390000 245 | 2020-06-18,3101.639893,3120.000000,3093.510010,3115.340088,3115.340088,4429030000 246 | 2020-06-19,3140.290039,3155.530029,3083.110107,3097.739990,3097.739990,8327780000 247 | 2020-06-22,3094.419922,3120.919922,3079.389893,3117.860107,3117.860107,4665380000 248 | 2020-06-23,3138.699951,3154.899902,3127.120117,3131.290039,3131.290039,4704830000 249 | 2020-06-24,3114.399902,3115.010010,3032.129883,3050.330078,3050.330078,5587200000 250 | 2020-06-25,3046.600098,3086.250000,3024.010010,3083.760010,3083.760010,4815420000 251 | 2020-06-26,3073.199951,3073.729980,3004.629883,3009.050049,3009.050049,8098120000 252 | 2020-06-29,3018.590088,3053.889893,2999.739990,3053.239990,3053.239990,4462770000 253 | 2020-06-30,3050.199951,3111.510010,3047.830078,3100.290039,3100.290039,4696280000 254 | 2020-07-01,3105.919922,3128.439941,3101.169922,3115.860107,3115.860107,4443130000 255 | 2020-07-02,3143.639893,3165.810059,3143.639893,3150.629883,3150.629883,655473416 --------------------------------------------------------------------------------