diff --git a/catalyst/__main__.py b/catalyst/__main__.py index dd15e6f7..8b7f001b 100644 --- a/catalyst/__main__.py +++ b/catalyst/__main__.py @@ -9,7 +9,7 @@ from six import text_type from catalyst.data import bundles as bundles_module from catalyst.exchange.exchange_bundle import ExchangeBundle -from catalyst.exchange.init_utils import get_exchange +from catalyst.exchange.factory import get_exchange from catalyst.utils.cli import Date, Timestamp from catalyst.utils.run_algo import _run, load_extensions diff --git a/catalyst/assets/_assets.pyx b/catalyst/assets/_assets.pyx index bd67526e..19ddacd3 100644 --- a/catalyst/assets/_assets.pyx +++ b/catalyst/assets/_assets.pyx @@ -559,6 +559,20 @@ cdef class TradingPair(Asset): end_minute=self.end_minute ) + def is_exchange_open(self, dt_minute): + """ + Parameters + ---------- + dt_minute: pd.Timestamp (UTC, tz-aware) + The minute to check. + + Returns + ------- + boolean: whether the asset's exchange is open at the given minute. + """ + #TODO: consider implementing to spot holds + return True + cpdef __reduce__(self): """ Function used by pickle to determine how to serialize/deserialize this diff --git a/catalyst/examples/simple_loop.py b/catalyst/examples/simple_loop.py index 52400485..9ebf93b1 100644 --- a/catalyst/examples/simple_loop.py +++ b/catalyst/examples/simple_loop.py @@ -1,13 +1,13 @@ import talib - import pandas as pd + from catalyst import run_algorithm from catalyst.api import symbol def initialize(context): print('initializing') - context.asset = symbol('burst_btc') + context.asset = symbol('eth_btc') def handle_data(context, data): @@ -16,36 +16,38 @@ def handle_data(context, data): price = data.current(context.asset, 'close') print('got price {price}'.format(price=price)) - prices = data.history( - context.asset, - fields='price', - bar_count=15, - frequency='1d' - ) - rsi = talib.RSI(prices.values, timeperiod=14)[-1] - print('got rsi: {}'.format(rsi)) - pass + try: + prices = data.history( + context.asset, + fields='price', + bar_count=16, + frequency='5T' + ) + rsi = talib.RSI(prices.values, timeperiod=14)[-1] + print('got rsi: {}'.format(rsi)) + except Exception as e: + print(e) -run_algorithm( - capital_base=250, - start=pd.to_datetime('2017-08-01', utc=True), - end=pd.to_datetime('2017-9-30', utc=True), - data_frequency='minute', - initialize=initialize, - handle_data=handle_data, - analyze=None, - exchange_name='poloniex', - algo_namespace='simple_loop', - base_currency='btc' -) # run_algorithm( +# capital_base=250, +# start=pd.to_datetime('2017-1-1', utc=True), +# end=pd.to_datetime('2017-10-22', utc=True), +# data_frequency='daily', # initialize=initialize, # handle_data=handle_data, # analyze=None, # exchange_name='bitfinex', -# live=True, # algo_namespace='simple_loop', -# base_currency='eth', -# live_graph=False +# base_currency='btc' # ) +run_algorithm( + initialize=initialize, + handle_data=handle_data, + analyze=None, + exchange_name='poloniex', + live=True, + algo_namespace='simple_loop', + base_currency='eth', + live_graph=False +) diff --git a/catalyst/exchange/bitfinex/bitfinex.py b/catalyst/exchange/bitfinex/bitfinex.py index ea243a1f..4c878e04 100644 --- a/catalyst/exchange/bitfinex/bitfinex.py +++ b/catalyst/exchange/bitfinex/bitfinex.py @@ -240,7 +240,7 @@ class Bitfinex(Exchange): # TODO: fetch account data and keep in cache return None - def get_candles(self, data_frequency, assets, bar_count=None, + def get_candles(self, freq, assets, bar_count=None, start_dt=None, end_dt=None): """ Retrieve OHLVC candles from Bitfinex @@ -259,39 +259,36 @@ class Bitfinex(Exchange): 'retrieving {bars} {freq} candles on {exchange} from ' '{end_dt} for markets {symbols}, '.format( bars=bar_count, - freq=data_frequency, + freq=freq, exchange=self.name, end_dt=end_dt, symbols=get_symbols_string(assets) ) ) - freq_match = re.match(r'([0-9].*)(m|h|d)', data_frequency, re.M | re.I) + allowed_frequencies = ['1T', '5T', '15T', '30T', '60T', '180T', + '360T', '720T', '1D', '7D', '14D', '30D'] + if freq not in allowed_frequencies: + raise InvalidHistoryFrequencyError(frequency=freq) + + freq_match = re.match(r'([0-9].*)(T|H|D)', freq, re.M | re.I) if freq_match: number = int(freq_match.group(1)) unit = freq_match.group(2) - if unit == 'd': - converted_unit = 'D' + if unit == 'T': + if number in [60, 180, 360, 720]: + number = number / 60 + converted_unit = 'h' + else: + converted_unit = 'm' else: converted_unit = unit frequency = '{}{}'.format(number, converted_unit) - allowed_frequencies = ['1m', '5m', '15m', '30m', '1h', '3h', '6h', - '12h', '1D', '7D', '14D', '1M'] - if frequency not in allowed_frequencies: - raise InvalidHistoryFrequencyError( - frequency=data_frequency - ) - elif data_frequency == 'minute': - frequency = '1m' - elif data_frequency == 'daily': - frequency = '1D' else: - raise InvalidHistoryFrequencyError( - frequency=data_frequency - ) + raise InvalidHistoryFrequencyError(frequency=freq) # Making sure that assets are iterable asset_list = [assets] if isinstance(assets, TradingPair) else assets diff --git a/catalyst/exchange/bittrex/bittrex.py b/catalyst/exchange/bittrex/bittrex.py index 1bbfc68b..6c490a46 100644 --- a/catalyst/exchange/bittrex/bittrex.py +++ b/catalyst/exchange/bittrex/bittrex.py @@ -210,14 +210,14 @@ class Bittrex(Exchange): error=status['message'] ) - def get_candles(self, data_frequency, assets, bar_count=None, + def get_candles(self, freq, assets, bar_count=None, start_dt=None, end_dt=None): """ Supported Intervals ------------------- day, oneMin, fiveMin, thirtyMin, hour - :param data_frequency: + :param freq: :param assets: :param bar_count: :param start_dt @@ -233,28 +233,25 @@ class Bittrex(Exchange): 'retrieving {bars} {freq} candles on {exchange} from ' '{end_dt} for markets {symbols}, '.format( bars=bar_count, - freq=data_frequency, + freq=freq, exchange=self.name, end_dt=end_dt, symbols=get_symbols_string(assets) ) ) - data_frequency = data_frequency.lower() - if data_frequency == 'minute' or data_frequency == '1m': + if freq == '1T': frequency = 'oneMin' - elif data_frequency == '5m': + elif freq == '5T': frequency = 'fiveMin' - elif data_frequency == '30m': + elif freq == '30T': frequency = 'thirtyMin' - elif data_frequency == '1h': + elif freq == '60T': frequency = 'hour' - elif data_frequency == 'daily' or data_frequency == '1d': + elif freq == '1D': frequency = 'day' else: - raise InvalidHistoryFrequencyError( - frequency=data_frequency - ) + raise InvalidHistoryFrequencyError(frequency=freq) # Making sure that assets are iterable asset_list = [assets] if isinstance(assets, TradingPair) else assets @@ -297,6 +294,7 @@ class Bittrex(Exchange): if bar_count is None: ohlc_map[asset] = ohlc_from_candle(ordered_candles[0]) else: + # TODO: optimize ohlc_bars = [] for candle in ordered_candles[:bar_count]: ohlc = ohlc_from_candle(candle) diff --git a/catalyst/exchange/bundle_utils.py b/catalyst/exchange/bundle_utils.py index b1aa1a07..4510bce4 100644 --- a/catalyst/exchange/bundle_utils.py +++ b/catalyst/exchange/bundle_utils.py @@ -7,22 +7,42 @@ import numpy as np import pandas as pd import pytz -from catalyst.data.bundles import from_bundle_ingest_dirname from catalyst.data.bundles.core import download_without_progress -from catalyst.exchange.exchange_errors import NoDataAvailableOnExchange from catalyst.exchange.exchange_utils import get_exchange_bundles_folder -from catalyst.utils.deprecate import deprecated -from catalyst.utils.paths import data_path EXCHANGE_NAMES = ['bitfinex', 'bittrex', 'poloniex'] API_URL = 'http://data.enigma.co/api/v1' def get_date_from_ms(ms): + """ + The date from the number of miliseconds from the epoch. + + Parameters + ---------- + ms: int + + Returns + ------- + datetime + + """ return datetime.fromtimestamp(ms / 1000.0) def get_seconds_from_date(date): + """ + The number of seconds from the epoch. + + Parameters + ---------- + date: datetime + + Returns + ------- + int + + """ epoch = datetime.utcfromtimestamp(0) epoch = epoch.replace(tzinfo=pytz.UTC) @@ -33,16 +53,19 @@ def get_bcolz_chunk(exchange_name, symbol, data_frequency, period): """ Download and extract a bcolz bundle. - :param exchange_name: - :param symbol: - :param data_frequency: - :param period: - :return: + Parameters + ---------- + exchange_name: str + symbol: str + data_frequency: str + period: str - Note: + Returns + ------- + str Filename: bitfinex-daily-neo_eth-2017-10.tar.gz - """ + """ root = get_exchange_bundles_folder(exchange_name) name = '{exchange}-{frequency}-{symbol}-{period}'.format( exchange=exchange_name, @@ -67,32 +90,80 @@ def get_bcolz_chunk(exchange_name, symbol, data_frequency, period): def get_delta(periods, data_frequency): + """ + Get a time delta based on the specified data frequency. + + Parameters + ---------- + periods: int + data_frequency: str + + Returns + ------- + timedelta + + """ return timedelta(minutes=periods) \ if data_frequency == 'minute' else timedelta(days=periods) -def get_periods_range(start_dt, end_dt, data_frequency): - freq = 'T' if data_frequency == 'minute' else 'D' +def get_periods_range(start_dt, end_dt, freq): + """ + Get a date range for the specified parameters. + + Parameters + ---------- + start_dt: datetime + end_dt: datetime + freq: str + + Returns + ------- + DateTimeIndex + + """ + if freq == 'minute': + freq = 'T' + + elif freq == 'daily': + freq = 'D' return pd.date_range(start_dt, end_dt, freq=freq) -def get_periods(start_dt, end_dt, data_frequency): - delta = end_dt - start_dt +def get_periods(start_dt, end_dt, freq): + """ + The number of periods in the specified range. - if data_frequency == 'minute': - delta_periods = delta.total_seconds() / 60 + Parameters + ---------- + start_dt: datetime + end_dt: datetime + freq: str - elif data_frequency == 'daily': - delta_periods = delta.total_seconds() / 60 / 60 / 24 + Returns + ------- + int - else: - raise ValueError('frequency not supported') - - return int(delta_periods) + """ + return len(get_periods_range(start_dt, end_dt, freq)) def get_start_dt(end_dt, bar_count, data_frequency): + """ + The start date based on specified end date and data frequency. + + Parameters + ---------- + end_dt: datetime + bar_count: int + data_frequency: str + + Returns + ------- + datetime + + """ periods = bar_count if periods > 1: delta = get_delta(periods, data_frequency) @@ -103,41 +174,96 @@ def get_start_dt(end_dt, bar_count, data_frequency): return start_dt - - -def get_month_start_end(dt): +def get_period_label(dt, data_frequency): """ - Returns the first and last day of the month for the specified date. + The period label for the specified date and frequency. + + Parameters + ---------- + dt: datetime + data_frequency: str + + Returns + ------- + str + + """ + return '{}-{:02d}'.format(dt.year, dt.month) if data_frequency == 'minute' \ + else '{}'.format(dt.year) + + +def get_month_start_end(dt, first_day=None, last_day=None): + """ + The first and last day of the month for the specified date. + + Parameters + ---------- + dt: datetime + first_day: datetime + last_day: datetime + + Returns + ------- + datetime, datetime - :param dt: - :return: """ month_range = calendar.monthrange(dt.year, dt.month) - month_start = pd.to_datetime(datetime( - dt.year, dt.month, 1, 0, 0, 0, 0 - ), utc=True) - month_end = pd.to_datetime(datetime( - dt.year, dt.month, month_range[1], 23, 59, 0, 0 - ), utc=True) + if first_day: + month_start = first_day + else: + month_start = pd.to_datetime(datetime( + dt.year, dt.month, 1, 0, 0, 0, 0 + ), utc=True) + + if last_day: + month_end = last_day + else: + month_end = pd.to_datetime(datetime( + dt.year, dt.month, month_range[1], 23, 59, 0, 0 + ), utc=True) return month_start, month_end -def get_year_start_end(dt): +def get_year_start_end(dt, first_day=None, last_day=None): """ - Returns the first and last day of the year for the specified date. + The first and last day of the year for the specified date. + + Parameters + ---------- + + dt: datetime + first_day: datetime + last_day: datetime + + Returns + ------- + datetime, datetime - :param dt: - :return: """ - year_start = pd.to_datetime(date(dt.year, 1, 1), utc=True) - year_end = pd.to_datetime(date(dt.year, 12, 31), utc=True) + year_start = first_day if first_day \ + else pd.to_datetime(date(dt.year, 1, 1), utc=True) + year_end = last_day if last_day \ + else pd.to_datetime(date(dt.year, 12, 31), utc=True) return year_start, year_end def get_df_from_arrays(arrays, periods): + """ + A DataFrame from the specified OHCLV arrays. + + Parameters + ---------- + arrays: Object + periods: DateTimeIndex + + Returns + ------- + DataFrame + + """ ohlcv = dict() for index, field in enumerate( ['open', 'high', 'low', 'close', 'volume']): @@ -155,11 +281,17 @@ def range_in_bundle(asset, start_dt, end_dt, reader): Evaluate whether price data of an asset is included has been ingested in the exchange bundle for the given date range. - :param asset: - :param start_dt: - :param end_dt: - :param reader: - :return: + Parameters + ---------- + asset: TradingPair + start_dt: datetime + end_dt: datetime + reader: BcolzBarMinuteReader + + Returns + ------- + bool + """ has_data = True if has_data and reader is not None: @@ -183,36 +315,3 @@ def range_in_bundle(asset, start_dt, end_dt, reader): has_data = False return has_data - - -@deprecated -def find_most_recent_time(bundle_name): - """ - Find most recent "time folder" for a given bundle. - - :param bundle_name: - The name of the targeted bundle. - - :return folder: - The name of the time folder. - """ - try: - bundle_folders = os.listdir( - data_path([bundle_name]), - ) - except OSError: - return None - - most_recent_bundle = dict() - for folder in bundle_folders: - date = from_bundle_ingest_dirname(folder) - if not most_recent_bundle or date > \ - most_recent_bundle[list(most_recent_bundle.keys())[0]]: - most_recent_bundle = dict() - most_recent_bundle[folder] = date - - if most_recent_bundle: - return list(most_recent_bundle.keys())[0] - else: - return None - diff --git a/catalyst/exchange/exchange.py b/catalyst/exchange/exchange.py index 31037882..f10bbaf0 100644 --- a/catalyst/exchange/exchange.py +++ b/catalyst/exchange/exchange.py @@ -1,5 +1,4 @@ import abc -import re from abc import ABCMeta, abstractmethod, abstractproperty from datetime import timedelta from time import sleep @@ -12,17 +11,20 @@ from logbook import Logger from catalyst.constants import LOG_LEVEL from catalyst.data.data_portal import BASE_FIELDS from catalyst.exchange.bundle_utils import get_start_dt, \ - get_delta, get_periods + get_delta, get_periods, get_periods_range from catalyst.exchange.exchange_bundle import ExchangeBundle from catalyst.exchange.exchange_errors import MismatchingBaseCurrencies, \ InvalidOrderStyle, BaseCurrencyNotFoundError, SymbolNotFoundOnExchange, \ - InvalidHistoryFrequencyError, PricingDataNotLoadedError + PricingDataNotLoadedError, \ + NoDataAvailableOnExchange from catalyst.exchange.exchange_execution import ExchangeStopLimitOrder, \ ExchangeLimitOrder, ExchangeStopOrder from catalyst.exchange.exchange_portfolio import ExchangePortfolio -from catalyst.exchange.exchange_utils import get_exchange_symbols +from catalyst.exchange.exchange_utils import get_exchange_symbols, \ + get_frequency, resample_history_df from catalyst.finance.order import ORDER_STATUS from catalyst.finance.transaction import Transaction +from catalyst.utils.deprecate import deprecated log = Logger('Exchange', level=LOG_LEVEL) @@ -50,9 +52,11 @@ class Exchange: @property def portfolio(self): """ - Return the Portfolio + The exchange portfolio - :return: + Returns + ------- + ExchangePortfolio """ if self._portfolio is None: self._portfolio = ExchangePortfolio( @@ -70,6 +74,22 @@ class Exchange: def time_skew(self): pass + def is_open(self, dt): + """ + Is the exchange open + + Parameters + ---------- + dt: Timestamp + + Returns + ------- + bool + + """ + # TODO: implement for each exchange. + return True + def ask_request(self): """ Asks permission to issue a request to the exchange. @@ -78,7 +98,9 @@ class Exchange: The application will pause if the maximum requests per minute permitted by the exchange is exceeded. - :return boolean: + Returns + ------- + bool """ now = pd.Timestamp.utcnow() @@ -110,10 +132,16 @@ class Exchange: def get_symbol(self, asset): """ - Get the exchange specific symbol of the given asset. + The the exchange specific symbol of the specified market. + + Parameters + ---------- + asset: TradingPair + + Returns + ------- + str - :param asset: Asset - :return: symbol: str """ symbol = None @@ -131,17 +159,34 @@ class Exchange: """ Get a list of symbols corresponding to each given asset. - :param assets: Asset[] - :return: + Parameters + ---------- + assets: list[TradingPair] + + Returns + ------- + list[str] + """ symbols = [] - for asset in assets: symbols.append(self.get_symbol(asset)) return symbols def get_assets(self, symbols=None): + """ + The list of markets for the specified symbols. + + Parameters + ---------- + symbols: list[str] + + Returns + ------- + list[TradingPair] + + """ assets = [] if symbols is not None: @@ -156,9 +201,16 @@ class Exchange: def get_asset(self, symbol): """ - Find an Asset on the current exchange based on its Catalyst symbol - :param symbol: the [target]_[base] currency pair symbol - :return: Asset + The market for the specified symbol. + + Parameters + ---------- + symbol: str + + Returns + ------- + TradingPair + """ asset = None @@ -189,7 +241,6 @@ class Exchange: currency pair symbol. The universal symbol is contained in the 'symbol' attribute of each asset. - Notes ----- The sid of each asset is calculated based on a numeric hash of the @@ -198,8 +249,8 @@ class Exchange: This method can be overridden if an exchange offers equivalent data via its api. - """ + """ symbol_map = self.fetch_symbol_map() for exchange_symbol in symbol_map: asset = symbol_map[exchange_symbol] @@ -260,8 +311,10 @@ class Exchange: For each executed order found, create a transaction and apply to the Portfolio. - :return: - transactions: Transaction[] + Returns + ------- + list[Transaction] + """ transactions = list() if self.portfolio.open_orders: @@ -344,17 +397,24 @@ class Exchange: """ Similar to 'get_spot_value' but for a single asset - Note - ---- + Notes + ----- We're writing each minute bar to disk using zipline's machinery. This is especially useful when running multiple algorithms concurrently. By using local data when possible, we try to reaching request limits on exchanges. - :param asset: - :param field: - :param data_frequency: - :return value: The spot value of the given asset / field + Parameters + ---------- + asset: TradingPair + field: str + data_frequency: str + + Returns + ------- + float + The spot value of the given asset / field + """ log.debug( 'fetching spot value {field} for symbol {symbol}'.format( @@ -363,7 +423,8 @@ class Exchange: ) ) - ohlc = self.get_candles(data_frequency, asset) + freq = '1T' if data_frequency == 'minute' else '1D' + ohlc = self.get_candles(freq, asset) if field not in ohlc: raise KeyError('Invalid column: %s' % field) @@ -377,35 +438,45 @@ class Exchange: """ Get a series of field data for the specified candles. - :param candles: - :param start_dt: - :param end_dt: - :param field: - :param previous_value: - :return: - """ + Parameters + ---------- + candles: list[dict[str, float]] + start_dt: datetime + end_dt: datetime + data_frequency: str + field: str + previous_value: float + Returns + ------- + Series + + """ dates = [candle['last_traded'] for candle in candles] values = [candle[field] for candle in candles] - - periods = self.bundle.get_calendar_periods_range( - start_dt, end_dt, data_frequency - ) series = pd.Series(values, index=dates) - #TODO: ensure that this working as expected, if not use fillna - series.reindex(periods, method='ffill', fill_value=previous_value) + periods = get_periods_range( + start_dt, end_dt, data_frequency + ) + # TODO: ensure that this working as expected, if not use fillna + series = series.reindex( + periods, + method='ffill', + fill_value=previous_value, + ) return series - def get_history_window(self, - assets, - end_dt, - bar_count, - frequency, - field, - data_frequency=None, - ffill=True): + @deprecated + def get_history_window_direct(self, + assets, + end_dt, + bar_count, + frequency, + field, + data_frequency=None, + ffill=True): """ Public API method that returns a dataframe containing the requested @@ -413,10 +484,11 @@ class Exchange: Parameters ---------- - assets : list of catalyst.data.Asset objects + assets : list[TradingPair] The assets whose data is desired. - end_dt: not applicable to cryptocurrencies + end_dt: datetime + The date of the last bar bar_count: int The number of bars desired. @@ -438,28 +510,79 @@ class Exchange: Returns ------- - A dataframe containing the requested data. + DataFrame + A dataframe containing the requested data. + """ + start_dt = get_start_dt(end_dt, bar_count, data_frequency) - freq_match = re.match(r'([0-9].*)(m|M|d|D)', frequency, re.M | re.I) - if freq_match: - candle_size = int(freq_match.group(1)) - unit = freq_match.group(2) + # The get_history method supports multiple asset + candles = self.get_candles( + data_frequency=frequency, + assets=assets, + bar_count=bar_count, + start_dt=start_dt, + end_dt=end_dt + ) + candle_series = self.get_series_from_candles( + candles=candles, + start_dt=start_dt, + end_dt=end_dt, + data_frequency=frequency, + field=field, + ) - else: - raise InvalidHistoryFrequencyError(frequency) + df = pd.DataFrame(candle_series) + return df - if unit.lower() == 'd': - if data_frequency == 'minute': - data_frequency = 'daily' + def get_history_window(self, + assets, + end_dt, + bar_count, + frequency, + field, + data_frequency=None, + ffill=True): - elif unit.lower() == 'm': - if data_frequency == 'daily': - data_frequency = 'minute' + """ + Public API method that returns a dataframe containing the requested + history window. Data is fully adjusted. - else: - raise InvalidHistoryFrequencyError(frequency) + Parameters + ---------- + assets : list[TradingPair] + The assets whose data is desired. + end_dt: datetime + The date of the last bar. + + bar_count: int + The number of bars desired. + + frequency: string + "1d" or "1m" + + field: string + The desired field of the asset. + + data_frequency: string + The frequency of the data to query; i.e. whether the data is + 'daily' or 'minute' bars. + + # TODO: fill how? + ffill: boolean + Forward-fill missing values. Only has effect if field + is 'price'. + + Returns + ------- + DataFrame + A dataframe containing the requested data. + + """ + freq, candle_size, unit, data_frequency = get_frequency( + frequency, data_frequency + ) adj_bar_count = candle_size * bar_count try: series = self.bundle.get_history_window_series_and_load( @@ -469,7 +592,7 @@ class Exchange: field=field, data_frequency=data_frequency ) - except PricingDataNotLoadedError: + except (PricingDataNotLoadedError, NoDataAvailableOnExchange): series = dict() for asset in assets: @@ -482,12 +605,14 @@ class Exchange: series[asset].index[-1] + get_delta(1, data_frequency) \ if asset in series else start_dt - trailing_bar_count = \ - get_periods(trailing_dt, end_dt, data_frequency) - # The get_history method supports multiple asset + # Use the original frequency to let each api optimize + # the size of result sets + trailing_bar_count = get_periods( + trailing_dt, end_dt, freq + ) candles = self.get_candles( - data_frequency=data_frequency, + freq=freq, assets=asset, bar_count=trailing_bar_count, start_dt=start_dt, @@ -497,6 +622,8 @@ class Exchange: last_value = series[asset].iloc(0) if asset in series \ else np.nan + # Create a series with the common data_frequency, ffill + # missing values candle_series = self.get_series_from_candles( candles=candles, start_dt=trailing_dt, @@ -512,23 +639,9 @@ class Exchange: else: series[asset] = candle_series - df = pd.DataFrame(series) - - if candle_size > 1: - if field == 'open': - agg = 'first' - elif field == 'high': - agg = 'max' - elif field == 'low': - agg = 'min' - elif field == 'close': - agg = 'last' - elif field == 'volume': - agg = 'sum' - else: - raise ValueError('Invalid field.') - - df = df.resample('{}T'.format(candle_size)).agg(agg) + df = resample_history_df(pd.DataFrame(series), freq, field) + # TODO: consider this more carefully + df.dropna(inplace=True) return df @@ -537,7 +650,6 @@ class Exchange: Update the portfolio cash and position balances based on the latest ticker prices. - :return: """ log.debug('synchronizing portfolio with exchange {}'.format(self.name)) balances = self.get_balances() @@ -581,16 +693,20 @@ class Exchange: Parameters ---------- - asset : Asset + asset : TradingPair The asset that this order is for. + amount : int The amount of shares to order. If ``amount`` is positive, this is the number of shares to buy or cover. If ``amount`` is negative, this is the number of shares to sell or short. + limit_price : float, optional The limit price for the order. + stop_price : float, optional The stop price for the order. + style : ExecutionStyle, optional The execution style for the order. @@ -615,6 +731,7 @@ class Exchange: :class:`catalyst.finance.execution.ExecutionStyle` :func:`catalyst.api.order_value` :func:`catalyst.api.order_percent` + """ if amount == 0: log.warn('skipping order amount of 0') @@ -664,8 +781,12 @@ class Exchange: @abstractmethod def get_balances(self): """ - Retrieve wallet balances for the exchange - :return balances: A dict of currency => available balance + Retrieve wallet balances for the exchange. + + Returns + ------- + dict[TradingPair, float] + """ pass @@ -674,17 +795,25 @@ class Exchange: """ Place an order on the exchange. - :param asset : Asset - The asset that this order is for. - :param amount : int + Parameters + ---------- + asset: TradingPair + The target market. + + amount: float The amount of shares to order. If ``amount`` is positive, this is the number of shares to buy or cover. If ``amount`` is negative, this is the number of shares to sell or short. - :param style : ExecutionStyle - The execution style for the order. - :param is_buy: boolean + + is_buy: bool Is it a buy order? - :return: + + style: ExecutionStyle + + Returns + ------- + Order + """ pass @@ -739,23 +868,32 @@ class Exchange: pass @abstractmethod - def get_candles(self, data_frequency, assets, bar_count=None, + def get_candles(self, freq, assets, bar_count=None, start_dt=None, end_dt=None): """ Retrieve OHLCV candles for the given assets - :param data_frequency: - The candle frequency: minute or daily - :param assets: list[TradingPair] + Parameters + ---------- + freq: str + The frequency alias per convention: + http://pandas.pydata.org/pandas-docs/stable/timeseries.html#offset-aliases + + assets: list[TradingPair] The targeted assets. - :param bar_count: + + bar_count: int The number of bar desired. (default 1) - :param end_dt: datetime, optional + + end_dt: datetime, optional The last bar date. - :param start_dt: datetime, optional + + start_dt: datetime, optional The first bar date. - :return dict[TradingPair, dict[str, Object]]: OHLCV data + Returns + ------- + dict[TradingPair, dict[str, Object]] A dictionary of OHLCV candles. Each TradingPair instance is mapped to a list of dictionaries with this structure: open: float @@ -775,8 +913,14 @@ class Exchange: """ Retrieve current tick data for the given assets - :param assets: - :return: + Parameters + ---------- + assets: list[TradingPair] + + Returns + ------- + list[dict[str, float] + """ pass @@ -784,7 +928,6 @@ class Exchange: def get_account(self): """ Retrieve the account parameters. - :return: """ pass @@ -793,11 +936,15 @@ class Exchange: """ Retrieve the the orderbook for the given trading pair. - :param asset: TradingPair - :param order_type: str + Parameters + ---------- + asset: TradingPair + order_type: str The type of orders: bid, ask or all - :param limit + limit: int - :return: + Returns + ------- + list[dict[str, float] """ pass diff --git a/catalyst/exchange/exchange_algorithm.py b/catalyst/exchange/exchange_algorithm.py index 6650fda2..c05e559f 100644 --- a/catalyst/exchange/exchange_algorithm.py +++ b/catalyst/exchange/exchange_algorithm.py @@ -127,7 +127,13 @@ class ExchangeTradingAlgorithmBase(TradingAlgorithm): """ Creates a dictionary representing the state of the tracker. + Parameters + ---------- + start_dt: datetime + end_dt: datetime + Notes + ----- I rewrote this in an attempt to better control the stats. I don't want things to happen magically through complex logic pertaining to backtesting. @@ -296,6 +302,18 @@ class ExchangeTradingAlgorithmLive(ExchangeTradingAlgorithmBase): self.exchange.minute_reader = BcolzMinuteBarReader(root) def signal_handler(self, signal, frame): + """ + Handles the keyboard interruption signal. + + Parameters + ---------- + signal + frame + + Returns + ------- + + """ self.is_running = False if self._analyze is None: @@ -384,7 +402,11 @@ class ExchangeTradingAlgorithmLive(ExchangeTradingAlgorithmBase): """ We skip the entire performance tracker business and update the portfolio directly. - :return: + + Returns + ------- + ExchangePortfolio + """ # TODO: build cumulative portfolio return self.perf_tracker.get_portfolio(False) @@ -450,6 +472,17 @@ class ExchangeTradingAlgorithmLive(ExchangeTradingAlgorithmBase): ) def add_pnl_stats(self, period_stats): + """ + Save p&l stats. + + Parameters + ---------- + period_stats + + Returns + ------- + + """ starting = period_stats['starting_cash'] current = period_stats['portfolio_value'] appreciation = (current / starting) - 1 @@ -466,6 +499,17 @@ class ExchangeTradingAlgorithmLive(ExchangeTradingAlgorithmBase): save_algo_df(self.algo_namespace, 'pnl_stats', self.pnl_stats) def add_custom_signals_stats(self, period_stats): + """ + Save custom signals stats. + + Parameters + ---------- + period_stats + + Returns + ------- + + """ log.debug('adding custom signals stats: {}'.format(self.recorded_vars)) df = pd.DataFrame( data=[self.recorded_vars], @@ -477,6 +521,17 @@ class ExchangeTradingAlgorithmLive(ExchangeTradingAlgorithmBase): self.custom_signals_stats) def add_exposure_stats(self, period_stats): + """ + Save exposure stats. + + Parameters + ---------- + period_stats + + Returns + ------- + + """ data = dict( long_exposure=period_stats['long_exposure'], base_currency=period_stats['ending_cash'] @@ -493,6 +548,14 @@ class ExchangeTradingAlgorithmLive(ExchangeTradingAlgorithmBase): self.exposure_stats) def handle_data(self, data): + """ + Wrapper around the handle_data method of each algo. + + Parameters + ---------- + data + + """ if not self.is_running: return @@ -619,15 +682,16 @@ class ExchangeTradingAlgorithmLive(ExchangeTradingAlgorithmBase): The cumulative portfolio does not contain open orders but exchange portfolios do. - :param asset: TradingPair - :param amount: float - :param limit_price: float - :param stop_price: float - :param style: Style - :return order: Order + Parameters + ---------- + asset: TradingPair + amount: float + limit_price: float + stop_price: float + style: Style + order: Order The catalyst order object or None """ - amount, style = self._calculate_order(asset, amount, limit_price, stop_price, style) @@ -689,15 +753,53 @@ class ExchangeTradingAlgorithmLive(ExchangeTradingAlgorithmBase): 'get_open_orders. Use `asset` instead.') @api_method def get_open_orders(self, asset=None): + """Retrieve all of the current open orders. + + Parameters + ---------- + asset : Asset + If passed and not None, return only the open orders for the given + asset instead of all open orders. + + Returns + ------- + open_orders : dict[list[Order]] or list[Order] + If no asset is passed this will return a dict mapping Assets + to a list containing all the open orders for the asset. + If an asset is passed then this will return a list of the open + orders for this asset. + """ return self._get_open_orders(asset) @api_method def get_order(self, order_id, exchange_name): + """Lookup an order based on the order id returned from one of the + order functions. + + Parameters + ---------- + order_id : str + The unique identifier for the order. + + Returns + ------- + order : Order + The order object. + execution_price: float + The execution price per share of the order + """ exchange = self.exchanges[exchange_name] return exchange.get_order(order_id) @api_method def cancel_order(self, order_param, exchange_name): + """Cancel an open order. + + Parameters + ---------- + order_param : str or Order + The order_id or order object to cancel. + """ exchange = self.exchanges[exchange_name] order_id = order_param diff --git a/catalyst/exchange/exchange_bcolz.py b/catalyst/exchange/exchange_bcolz.py index 326745ac..10e85488 100644 --- a/catalyst/exchange/exchange_bcolz.py +++ b/catalyst/exchange/exchange_bcolz.py @@ -39,17 +39,25 @@ class BcolzExchangeBarReader(BcolzMinuteBarReader): return self._data_frequency def load_raw_arrays(self, fields, start_dt, end_dt, sids): + """ + Parameters + ---------- + fields : list of str + 'open', 'high', 'low', 'close', or 'volume' + start_dt: Timestamp + Beginning of the window range. + end_dt: Timestamp + End of the window range. + sids : list of int + The asset identifiers in the window. - # if self._data_frequency == 'minute': - # return super(BcolzExchangeBarReader, self) \ - # .load_raw_arrays(fields, start_dt, end_dt, sids) - # - # else: - # return self._load_daily_raw_arrays(fields, start_dt, end_dt, sids) - - return self._load_raw_arrays(fields, start_dt, end_dt, sids) - - def _load_raw_arrays(self, fields, start_dt, end_dt, sids): + Returns + ------- + list of np.ndarray + A list with an entry per field of ndarrays with shape + (minutes in range, sids) with a dtype of float64, containing the + values for the respective field over start and end dt range. + """ start_idx = self._find_position_of_minute(start_dt) end_idx = self._find_position_of_minute(end_dt) diff --git a/catalyst/exchange/exchange_blotter.py b/catalyst/exchange/exchange_blotter.py index 2ca2cb88..365682c7 100644 --- a/catalyst/exchange/exchange_blotter.py +++ b/catalyst/exchange/exchange_blotter.py @@ -5,16 +5,16 @@ from catalyst.constants import LOG_LEVEL from catalyst.finance.blotter import Blotter from catalyst.finance.commission import CommissionModel from catalyst.finance.slippage import SlippageModel -from catalyst.finance.transaction import Transaction +from catalyst.finance.transaction import create_transaction log = Logger('exchange_blotter', level=LOG_LEVEL) # It seems like we need to accept greater slippage risk in cryptos # Orders won't often close at Equity levels. -# TODO: consider adjusting dynamically based on trading pair -DEFAULT_SLIPPAGE_SPREAD = 0.02 -DEFAULT_MAKER_FEE = 0.001 -DEFAULT_TAKER_FEE = 0.002 +# TODO: should work with set_commission and set_slippage +DEFAULT_SLIPPAGE_SPREAD = 0.0001 +DEFAULT_MAKER_FEE = 0.0015 +DEFAULT_TAKER_FEE = 0.0025 class TradingPairFeeSchedule(CommissionModel): @@ -97,12 +97,8 @@ class TradingPairFixedSlippage(SlippageModel): execution_price, execution_volume = self.process_order(data, order) - transaction = Transaction( - asset=order.asset, - amount=abs(execution_volume), - dt=dt, - price=execution_price, - order_id=order.id + transaction = create_transaction( + order, dt, execution_price, execution_volume ) self._volume_for_bar += abs(transaction.amount) diff --git a/catalyst/exchange/exchange_bundle.py b/catalyst/exchange/exchange_bundle.py index 353c5fc9..f5df0f8e 100644 --- a/catalyst/exchange/exchange_bundle.py +++ b/catalyst/exchange/exchange_bundle.py @@ -1,9 +1,14 @@ import os +import os import shutil -from datetime import timedelta +from itertools import chain import pandas as pd +from catalyst.assets._assets import TradingPair from logbook import Logger +from pandas.tslib import Timestamp +from pytz import UTC +from six import itervalues from catalyst import get_calendar from catalyst.constants import LOG_LEVEL @@ -11,11 +16,11 @@ from catalyst.data.minute_bars import BcolzMinuteOverlappingData, \ BcolzMinuteBarMetadata from catalyst.exchange.bundle_utils import range_in_bundle, \ get_bcolz_chunk, get_delta, get_month_start_end, \ - get_year_start_end, get_df_from_arrays, get_start_dt + get_year_start_end, get_df_from_arrays, get_start_dt, get_period_label from catalyst.exchange.exchange_bcolz import BcolzExchangeBarReader, \ BcolzExchangeBarWriter from catalyst.exchange.exchange_errors import EmptyValuesInBundleError, \ - InvalidHistoryFrequencyError, TempBundleNotFoundError, \ + TempBundleNotFoundError, \ NoDataAvailableOnExchange, \ PricingDataNotLoadedError from catalyst.exchange.exchange_utils import get_exchange_folder @@ -54,7 +59,10 @@ class ExchangeBundle: """ Get a data writer object, either a new object or from cache - :return: BcolzMinuteBarReader or BcolzDailyBarReader + Returns + ------- + BcolzMinuteBarReader | BcolzDailyBarReader + """ if path is None: root = get_exchange_folder(self.exchange.name) @@ -83,7 +91,10 @@ class ExchangeBundle: """ Get a data writer object, either a new object or from cache - :return: BcolzMinuteBarWriter or BcolzDailyBarWriter + Returns + ------- + BcolzMinuteBarWriter | BcolzDailyBarWriter + """ root = get_exchange_folder(self.exchange.name) path = BUNDLE_NAME_TEMPLATE.format( @@ -139,13 +150,19 @@ class ExchangeBundle: If the data exists, the chunk ingestion is complete. If any data is missing we ingest the data. - :param assets: list[TradingPair] + Parameters + ---------- + assets: list[TradingPair] The assets is scope. - :param start_dt: + start_dt: datetime The chunk start date. - :param end_dt: + end_dt: datetime The chunk end date. - :return: list[TradingPair] + data_frequency: str + + Returns + ------- + list[TradingPair] The assets missing from the bundle """ reader = self.get_reader(data_frequency) @@ -159,13 +176,6 @@ class ExchangeBundle: return missing_assets def _write(self, data, writer, data_frequency): - """ - Write data to the writer - - :param df: - :param writer: - :return: - """ try: writer.write( data=data, @@ -190,6 +200,20 @@ class ExchangeBundle: ) def get_calendar_periods_range(self, start_dt, end_dt, data_frequency): + """ + Get a list of dates for the specified range. + + Parameters + ---------- + start_dt: datetime + end_dt: datetime + data_frequency: str + + Returns + ------- + list[datetime] + + """ return self.calendar.minutes_in_range(start_dt, end_dt) \ if data_frequency == 'minute' \ else self.calendar.sessions_in_range(start_dt, end_dt) @@ -199,13 +223,14 @@ class ExchangeBundle: """ Ingest a DataFrame of OHLCV data for a given market. - :param ohlcv_df: - :param data_frequency: - :param asset: - :param writer: - :param path: - :param empty_rows_behavior: - :return: + Parameters + ---------- + ohlcv_df: DataFrame + data_frequency: str + asset: TradingPair + writer: + empty_rows_behavior: str + """ if empty_rows_behavior is not 'ignore': nan_rows = ohlcv_df[ohlcv_df.isnull().T.any().T].index @@ -259,19 +284,21 @@ class ExchangeBundle: self._write(data, writer, data_frequency) - def ingest_ctable(self, asset, data_frequency, period, start_dt, end_dt, + def ingest_ctable(self, asset, data_frequency, period, writer, empty_rows_behavior='strip', cleanup=False): """ Merge a ctable bundle chunk into the main bundle for the exchange. - :param asset: TradingPair - :param data_frequency: str - :param period: str - :param writer: - :param empty_rows_behavior: str + Parameters + ---------- + asset: TradingPair + data_frequency: str + period: str + writer: + empty_rows_behavior: str Ensure that the bundle does not have any missing data. - :param cleanup: bool + cleanup: bool Remove the temp bundle directory after ingestion. :return: @@ -288,6 +315,12 @@ class ExchangeBundle: if reader is None: raise TempBundleNotFoundError(path=path) + start_dt = reader.first_trading_day + end_dt = reader.last_available_dt + + if data_frequency == 'daily': + end_dt = end_dt - pd.Timedelta(hours=23, minutes=59) + arrays = None try: arrays = reader.load_raw_arrays( @@ -326,13 +359,19 @@ class ExchangeBundle: def get_adj_dates(self, start, end, assets, data_frequency): """ - Contains a date range to the trading availability of the specified pairs. + Contains a date range to the trading availability of the specified + markets. - :param start: - :param end: - :param assets: - :param data_frequency: - :return: + Parameters + ---------- + start: datetime + end: datetime + assets: list[TradingPair] + data_frequency: str + + Returns + ------- + datetime, datetime """ earliest_trade = None last_entry = None @@ -375,15 +414,27 @@ class ExchangeBundle: Split a price data request into chunks corresponding to individual bundles. - :param assets: - :param data_frequency: - :param start_dt: - :param end_dt: - :return: + Parameters + ---------- + assets: list[TradingPair] + data_frequency: str + start_dt: datetime + end_dt: datetime + + Returns + ------- + dict[TradingPair, list[dict(str, Object]]] + """ + get_start_end = get_month_start_end \ + if data_frequency == 'minute' else get_year_start_end + + start_dt, _ = get_start_end(start_dt) + _, end_dt = get_start_end(end_dt) + reader = self.get_reader(data_frequency) - chunks = [] + chunks = dict() for asset in assets: try: # Checking if the the asset has price data in the specified @@ -397,106 +448,75 @@ class ExchangeBundle: log.debug('skipping {}: {}'.format(asset.symbol, e)) continue - # This is either the first trading day of the asset or the - # first session available in the calendar - first_trading_dt = asset.start_date \ - if asset.start_date > self.calendar.first_session \ - else self.calendar.first_session + dates = pd.date_range( + start=get_period_label(adj_start, data_frequency), + end=get_period_label(adj_end, data_frequency), + freq='MS' if data_frequency == 'minute' else 'AS', + tz=UTC + ) - # Aligning start / end dates with the daily calendar - sessions = self.calendar.sessions_in_range(adj_start, adj_end) + # Adjusting the last date of the range to avoid + # going over the asset's trading bounds + dates.values[0] = adj_start + dates.values[-1] = adj_end - # We loop through each session to create chunks for each period - chunk_labels = [] - dt = sessions[0] - while dt <= sessions[-1]: - label = '{}-{:02d}'.format(dt.year, dt.month) \ - if data_frequency == 'minute' else '{}'.format(dt.year) + chunks[asset] = [] + for index, dt in enumerate(dates): - if label not in chunk_labels: - chunk_labels.append(label) + period_start, period_end = get_start_end( + dt=dt, + first_day=dt if index == 0 else None, + last_day=dt if index == len(dates) - 1 else None + ) - # Adjusting the period dates to match the availability - # of the trading pair - if data_frequency == 'minute': - period_start, period_end = get_month_start_end(dt) + # Currencies don't always start trading at midnight. + # Checking the last minute of the day instead. + range_start = period_start.replace(hour=23, minute=59) \ + if data_frequency == 'minute' else period_start - asset_start_month, _ = get_month_start_end( - first_trading_dt + # Checking if the data already exists in the bundle + # for the date range of the chunk. If not, we create + # a chunk for ingestion. + has_data = range_in_bundle( + asset, range_start, period_end, reader + ) + if not has_data: + chunks[asset].append( + dict( + asset=asset, + period_start=period_start, + period_end=period_end, + period=get_period_label(dt, data_frequency) ) - if asset_start_month == period_start \ - and period_start < first_trading_dt: - period_start = first_trading_dt - - # TODO: need to filter closed pairs? - _, asset_end_month = get_month_start_end( - asset.end_minute - ) - if asset_end_month == period_end \ - and period_end > asset.end_minute: - period_end = asset.end_minute - - elif data_frequency == 'daily': - period_start, period_end = get_year_start_end(dt) - - asset_start_year, _ = get_year_start_end( - first_trading_dt - ) - if asset_start_year == period_start \ - and period_start < first_trading_dt: - period_start = first_trading_dt - - _, asset_end_year = get_year_start_end( - asset.end_daily - ) - if asset_end_year == period_end \ - and period_end > asset.end_daily: - period_end = asset.end_daily - - else: - raise InvalidHistoryFrequencyError( - frequency=data_frequency - ) - - # Currencies don't always start trading at midnight. - # Checking the last minute of the day instead. - range_start = period_start.replace(hour=23, minute=59) \ - if data_frequency == 'minute' else period_start - - # Checking if the data already exists in the bundle - # for the date range of the chunk. If not, we create - # a chunk for ingestion. - has_data = range_in_bundle( - asset, range_start, period_end, reader ) - if not has_data: - log.debug('adding period: {}'.format(label)) - chunks.append( - dict( - asset=asset, - period_start=period_start, - period_end=period_end, - period=label - ) - ) - dt += timedelta(days=1) - - # We sort the chunks by end date to ingest most recent data first - chunks.sort(key=lambda chunk: chunk['period_end']) + # We sort the chunks by end date to ingest most recent data first + chunks[asset].sort(key=lambda chunk: chunk['period_end']) return chunks - def ingest_assets(self, assets, start_dt, end_dt, data_frequency, - show_progress=False): + def ingest_assets(self, assets, data_frequency, start_dt=None, end_dt=None, + show_progress=False, asset_chunks=False): """ Determine if data is missing from the bundle and attempt to ingest it. - :param assets: - :param start_dt: - :param end_dt: - :return: + Parameters + ---------- + assets: list[TradingPair] + start_dt: datetime + end_dt: datetime + """ + + if start_dt is None: + start_dt = self.calendar.first_session + + if end_dt is None: + end_dt = pd.Timestamp.utcnow() + + start_dt, end_dt = self.get_adj_dates( + start_dt, end_dt, assets, data_frequency + ) chunks = self.prepare_chunks( assets=assets, data_frequency=data_frequency, @@ -507,7 +527,8 @@ class ExchangeBundle: # Since chunks are either monthly or yearly, it is possible that # our ingestion data range is greater than specified. We adjust # the boundaries to ensure that the writer can write all data. - for chunk in chunks: + all_chunks = list(chain.from_iterable(itervalues(chunks))) + for chunk in all_chunks: if chunk['period_start'] < start_dt: start_dt = chunk['period_start'] @@ -515,54 +536,94 @@ class ExchangeBundle: end_dt = chunk['period_end'] writer = self.get_writer(start_dt, end_dt, data_frequency) - with maybe_show_progress( - chunks, - show_progress, - label='Fetching {exchange} {frequency} candles: '.format( - exchange=self.exchange.name, - frequency=data_frequency - )) as it: - for chunk in it: - self.ingest_ctable( - asset=chunk['asset'], - data_frequency=data_frequency, - period=chunk['period'], - start_dt=chunk['period_start'], - end_dt=chunk['period_end'], - writer=writer, - empty_rows_behavior='strip', - cleanup=True - ) + + if asset_chunks: + for asset in chunks: + with maybe_show_progress( + chunks[asset], + show_progress, + label='Ingesting {frequency} price data for ' + '{symbol} on {exchange}'.format( + exchange=self.exchange.name, + frequency=data_frequency, + symbol=asset.symbol + )) as it: + for chunk in it: + self.ingest_ctable( + asset=chunk['asset'], + data_frequency=data_frequency, + period=chunk['period'], + writer=writer, + empty_rows_behavior='strip', + cleanup=True + ) + else: + with maybe_show_progress( + all_chunks, + show_progress, + label='Ingesting {frequency} price data on ' + '{exchange}'.format( + exchange=self.exchange.name, + frequency=data_frequency, + )) as it: + for chunk in it: + self.ingest_ctable( + asset=chunk['asset'], + data_frequency=data_frequency, + period=chunk['period'], + writer=writer, + empty_rows_behavior='strip', + cleanup=True + ) def ingest(self, data_frequency, include_symbols=None, exclude_symbols=None, start=None, end=None, show_progress=True, environ=os.environ): """ + Inject data based on specified parameters. + + Parameters + ---------- + data_frequency: str + include_symbols: str + exclude_symbols: str + start: datetime + end: datetime + show_progress: bool + environ: - :param data_frequency: - :param include_symbols: - :param exclude_symbols: - :param start: - :param end: - :param show_progress: - :param environ: - :return: """ assets = self.get_assets(include_symbols, exclude_symbols) - start_dt, end_dt = self.get_adj_dates( - start, end, assets, data_frequency - ) for frequency in data_frequency.split(','): - self.ingest_assets(assets, start_dt, end_dt, frequency, + self.ingest_assets(assets, frequency, start, end, show_progress) def get_history_window_series_and_load(self, - assets, - end_dt, - bar_count, - field, - data_frequency): + assets, # type: List[TradingPair] + end_dt, # type: Timestamp + bar_count, # type: int + field, # type: str + data_frequency, # type: str + algo_end_dt=None # type: Timestamp + ): + """ + Retrieve price data history, ingest missing data. + + Parameters + ---------- + assets: list[TradingPair] + end_dt: datetime + bar_count: int + field: str + data_frequency: str + algo_end_dt: datetime + + Returns + ------- + Series + + """ try: series = self.get_history_window_series( assets=assets, @@ -586,9 +647,10 @@ class ExchangeBundle: self.ingest_assets( assets=assets, start_dt=start_dt, - end_dt=end_dt, + end_dt=algo_end_dt, data_frequency=data_frequency, - show_progress=True + show_progress=True, + asset_chunks=True ) series = self.get_history_window_series( assets=assets, @@ -596,12 +658,29 @@ class ExchangeBundle: bar_count=bar_count, field=field, data_frequency=data_frequency, - reset_reader=True + reset_reader=False ) return series - def get_spot_values(self, assets, field, dt, data_frequency, - reset_reader=False): + def get_spot_values(self, + assets, # type: List[TradingPair] + field, # type: str + dt, # type: Timestamp + data_frequency, # type: str + reset_reader=False # type: bool + ): + # type: (...) -> List[float] + """ + The spot values for the gives assets, field and date. Reads from + the exchange data bundle. + + :param assets: + :param field: + :param dt: + :param data_frequency: + :param reset_reader: + :return: + """ values = [] try: reader = self.get_reader(data_frequency) diff --git a/catalyst/exchange/data_portal_exchange.py b/catalyst/exchange/exchange_data_portal.py similarity index 83% rename from catalyst/exchange/data_portal_exchange.py rename to catalyst/exchange/exchange_data_portal.py index 3eebf3aa..a6cf4db7 100644 --- a/catalyst/exchange/data_portal_exchange.py +++ b/catalyst/exchange/exchange_data_portal.py @@ -1,16 +1,3 @@ -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - import abc from time import sleep @@ -26,6 +13,7 @@ from catalyst.exchange.exchange_errors import ( ExchangeRequestError, ExchangeBarDataError, PricingDataNotLoadedError) +from catalyst.exchange.exchange_utils import get_frequency, resample_history_df log = Logger('DataPortalExchange', level=LOG_LEVEL) @@ -237,6 +225,25 @@ class DataPortalExchangeLive(DataPortalExchangeBase): field, data_frequency, ffill=True): + """ + Fetching price history window from the exchange. + + Parameters + ---------- + exchange: Exchange + assets: list[TradingPair] + end_dt: datetime + bar_count: int + frequency: str + field: str + data_frequency: str + ffill: bool + + Returns + ------- + DataFrame + + """ df = exchange.get_history_window( assets, end_dt, @@ -249,6 +256,22 @@ class DataPortalExchangeLive(DataPortalExchangeBase): def get_exchange_spot_value(self, exchange, assets, field, dt, data_frequency): + """ + A spot value for the exchange. + + Parameters + ---------- + exchange: Exchange + assets: list[TradingPair] + field: str + dt: datetime + data_frequency: str + + Returns + ------- + float + + """ exchange_spot_values = exchange.get_spot_value( assets, field, dt, data_frequency) @@ -287,34 +310,69 @@ class DataPortalExchangeBacktest(DataPortalExchangeBase): """ Fetching price history window from the exchange bundle. - Using a try... except approach to minimize reads most of the time, - when the data exists. + Parameters + ---------- + exchange: Exchange + assets: list[TradingPair] + end_dt: datetime + bar_count: int + frequency: str + field: str + data_frequency: str + ffill: bool + + Returns + ------- + DataFrame - :param exchange: - :param assets: - :param end_dt: - :param bar_count: - :param frequency: - :param field: - :param data_frequency: - :param ffill: - :return: """ + bundle = self.exchange_bundles[exchange.name] # type: ExchangeBundle + + freq, candle_size, unit, adj_data_frequency = get_frequency( + frequency, data_frequency + ) + adj_bar_count = candle_size * bar_count + + if data_frequency == 'minute' and adj_data_frequency == 'daily': + end_dt = end_dt.floor('1D') - bundle = self.exchange_bundles[exchange.name] series = bundle.get_history_window_series_and_load( assets=assets, end_dt=end_dt, - bar_count=bar_count, + bar_count=adj_bar_count, field=field, - data_frequency=data_frequency + data_frequency=adj_data_frequency, + algo_end_dt=self._last_available_session, ) - return pd.DataFrame(series) - def get_exchange_spot_value(self, exchange, assets, field, dt, - data_frequency): + df = resample_history_df(pd.DataFrame(series), freq, field) + return df + + def get_exchange_spot_value(self, + exchange, + assets, + field, + dt, + data_frequency + ): + """ + A spot value for the exchange bundle. Try to ingest data if not in + the bundle. + + Parameters + ---------- + exchange: Exchange + assets: list[TradingPair] + field: str + dt: datetime + data_frequency: str + + Returns + ------- + float + + """ bundle = self.exchange_bundles[exchange.name] - if data_frequency == 'daily': dt = dt.floor('1D') else: diff --git a/catalyst/exchange/exchange_errors.py b/catalyst/exchange/exchange_errors.py index 6cd55014..00e53395 100644 --- a/catalyst/exchange/exchange_errors.py +++ b/catalyst/exchange/exchange_errors.py @@ -86,6 +86,14 @@ class AlgoPickleNotFound(ZiplineError): ).strip() +class InvalidHistoryFrequencyAlias(ZiplineError): + msg = ( + 'Invalid frequency alias {freq}. Valid suffixes are M (minute) ' + 'and D (day). For example, these aliases would be valid ' + '1M, 5M, 1D.' + ).strip() + + class InvalidHistoryFrequencyError(ZiplineError): msg = ( 'Frequency {frequency} not supported by the exchange.' diff --git a/catalyst/exchange/exchange_execution.py b/catalyst/exchange/exchange_execution.py index 6527678e..536b526a 100644 --- a/catalyst/exchange/exchange_execution.py +++ b/catalyst/exchange/exchange_execution.py @@ -4,9 +4,16 @@ from catalyst.finance.execution import LimitOrder, StopOrder, StopLimitOrder class ExchangeLimitOrder(LimitOrder): def get_limit_price(self, is_buy): """ - We may be trading Satoshis with 8 decimals, we cannot round numbers - :param is_buy: - :return: + We may be trading Satoshis with 8 decimals, we cannot round numbers. + + Parameters + ---------- + is_buy: bool + + Returns + ------- + float + """ return self.limit_price @@ -14,9 +21,16 @@ class ExchangeLimitOrder(LimitOrder): class ExchangeStopOrder(StopOrder): def get_stop_price(self, is_buy): """ - We may be trading Satoshis with 8 decimals, we cannot round numbers - :param is_buy: - :return: + We may be trading Satoshis with 8 decimals, we cannot round numbers. + + Parameters + ---------- + is_buy: bool + + Returns + ------- + float + """ return self.stop_price @@ -24,16 +38,30 @@ class ExchangeStopOrder(StopOrder): class ExchangeStopLimitOrder(StopLimitOrder): def get_limit_price(self, is_buy): """ - We may be trading Satoshis with 8 decimals, we cannot round numbers - :param is_buy: - :return: + We may be trading Satoshis with 8 decimals, we cannot round numbers. + + Parameters + ---------- + is_buy: bool + + Returns + ------- + float + """ return self.limit_price def get_stop_price(self, is_buy): """ - We may be trading Satoshis with 8 decimals, we cannot round numbers - :param is_buy: - :return: + We may be trading Satoshis with 8 decimals, we cannot round numbers. + + Parameters + ---------- + is_buy: bool + + Returns + ------- + float + """ return self.stop_price diff --git a/catalyst/exchange/exchange_portfolio.py b/catalyst/exchange/exchange_portfolio.py index 2c0b1ac2..2003654b 100644 --- a/catalyst/exchange/exchange_portfolio.py +++ b/catalyst/exchange/exchange_portfolio.py @@ -3,6 +3,7 @@ from logbook import Logger from catalyst.constants import LOG_LEVEL from catalyst.protocol import Portfolio, Positions, Position +from catalyst.utils.deprecate import deprecated log = Logger('ExchangePortfolio', level=LOG_LEVEL) @@ -29,10 +30,15 @@ class ExchangePortfolio(Portfolio): self.positions_value = 0.0 self.open_orders = dict() - def calculate_pnl(self): - log.debug('calculating pnl') - def create_order(self, order): + """ + Create an open order and store in memory. + + Parameters + ---------- + order: Order + + """ log.debug('creating order {}'.format(order.id)) self.open_orders[order.id] = order @@ -47,6 +53,18 @@ class ExchangePortfolio(Portfolio): log.debug('open order added to portfolio') def execute_order(self, order, transaction): + """ + Update the open orders and positions to apply an executed order. + + Unlike with backtesting, we do not need to add slippage and fees. + The executed price includes transaction fees. + + Parameters + ---------- + order: Order + transaction: Transaction + + """ log.debug('executing order {}'.format(order.id)) del self.open_orders[order.id] @@ -71,7 +89,9 @@ class ExchangePortfolio(Portfolio): log.debug('updated portfolio with executed order') + @deprecated def execute_transaction(self, transaction): + # TODO: almost duplicate of execute_order. Not sure why Poloniex needs this. log.debug('executing transaction {}'.format(transaction.order_id)) order_position = self.positions[transaction.asset] \ @@ -96,6 +116,14 @@ class ExchangePortfolio(Portfolio): log.debug('updated portfolio with executed order') def remove_order(self, order): + """ + Removing an open order. + + Parameters + ---------- + order: Order + + """ log.info('removing cancelled order {}'.format(order.id)) del self.open_orders[order.id] diff --git a/catalyst/exchange/exchange_utils.py b/catalyst/exchange/exchange_utils.py index 77e0fc56..4db41d9e 100644 --- a/catalyst/exchange/exchange_utils.py +++ b/catalyst/exchange/exchange_utils.py @@ -1,14 +1,15 @@ import json import os import pickle - -from catalyst.assets._assets import TradingPair -from six.moves.urllib import request +import re from datetime import date, datetime import pandas as pd +from catalyst.assets._assets import TradingPair +from six.moves.urllib import request -from catalyst.exchange.exchange_errors import ExchangeSymbolsNotFound +from catalyst.exchange.exchange_errors import ExchangeSymbolsNotFound, \ + InvalidHistoryFrequencyError, InvalidHistoryFrequencyAlias from catalyst.utils.paths import data_root, ensure_directory, \ last_modified_time @@ -17,6 +18,19 @@ SYMBOLS_URL = 'https://s3.amazonaws.com/enigmaco/catalyst-exchanges/' \ def get_exchange_folder(exchange_name, environ=None): + """ + The root path of an exchange folder. + + Parameters + ---------- + exchange_name: str + environ: + + Returns + ------- + str + + """ if not environ: environ = os.environ @@ -28,11 +42,37 @@ def get_exchange_folder(exchange_name, environ=None): def get_exchange_symbols_filename(exchange_name, environ=None): + """ + The absolute path of the exchange's symbol.json file. + + Parameters + ---------- + exchange_name: + environ: + + Returns + ------- + str + + """ exchange_folder = get_exchange_folder(exchange_name, environ) return os.path.join(exchange_folder, 'symbols.json') def download_exchange_symbols(exchange_name, environ=None): + """ + Downloads the exchange's symbols.json from the repository. + + Parameters + ---------- + exchange_name: str + environ: + + Returns + ------- + str + + """ filename = get_exchange_symbols_filename(exchange_name) url = SYMBOLS_URL.format(exchange=exchange_name) response = request.urlretrieve(url=url, filename=filename) @@ -40,6 +80,19 @@ def download_exchange_symbols(exchange_name, environ=None): def get_exchange_symbols(exchange_name, environ=None): + """ + The de-serialized content of the exchange's symbols.json. + + Parameters + ---------- + exchange_name: str + environ: + + Returns + ------- + Object + + """ filename = get_exchange_symbols_filename(exchange_name) if not os.path.isfile(filename) or \ @@ -60,11 +113,36 @@ def get_exchange_symbols(exchange_name, environ=None): def get_symbols_string(assets): + """ + A concatenated string of symbols from a list of assets. + + Parameters + ---------- + assets: list[TradingPair] + + Returns + ------- + str + + """ array = [assets] if isinstance(assets, TradingPair) else assets return ', '.join([asset.symbol for asset in array]) def get_exchange_auth(exchange_name, environ=None): + """ + The de-serialized contend of the exchange's auth.json file. + + Parameters + ---------- + exchange_name: str + environ: + + Returns + ------- + Object + + """ exchange_folder = get_exchange_folder(exchange_name, environ) filename = os.path.join(exchange_folder, 'auth.json') @@ -81,6 +159,19 @@ def get_exchange_auth(exchange_name, environ=None): def get_algo_folder(algo_name, environ=None): + """ + The algorithm root folder of the algorithm. + + Parameters + ---------- + algo_name: str + environ: + + Returns + ------- + str + + """ if not environ: environ = os.environ @@ -92,6 +183,21 @@ def get_algo_folder(algo_name, environ=None): def get_algo_object(algo_name, key, environ=None, rel_path=None): + """ + The de-serialized object of the algo name and key. + + Parameters + ---------- + algo_name: str + key: str + environ: + rel_path: str + + Returns + ------- + Object + + """ if algo_name is None: return None @@ -113,6 +219,18 @@ def get_algo_object(algo_name, key, environ=None, rel_path=None): def save_algo_object(algo_name, key, obj, environ=None, rel_path=None): + """ + Serialize and save an object by algo name and key. + + Parameters + ---------- + algo_name: str + key: str + obj: Object + environ: + rel_path: str + + """ folder = get_algo_folder(algo_name, environ) if rel_path is not None: @@ -125,16 +243,22 @@ def save_algo_object(algo_name, key, obj, environ=None, rel_path=None): pickle.dump(obj, handle, protocol=pickle.HIGHEST_PROTOCOL) -def append_algo_object(algo_name, key, obj, environ=None): - algo_folder = get_algo_folder(algo_name, environ) - filename = os.path.join(algo_folder, key + '.p') - - mode = 'a+b' if os.path.isfile(filename) else 'wb' - with open(filename, mode) as handle: - pickle.dump(obj, handle, protocol=pickle.HIGHEST_PROTOCOL) - - def get_algo_df(algo_name, key, environ=None, rel_path=None): + """ + The de-serialized DataFrame of an algo name and key. + + Parameters + ---------- + algo_name: str + key: str + environ: + rel_path: str + + Returns + ------- + DataFrame + + """ folder = get_algo_folder(algo_name, environ) if rel_path is not None: @@ -153,6 +277,18 @@ def get_algo_df(algo_name, key, environ=None, rel_path=None): def save_algo_df(algo_name, key, df, environ=None, rel_path=None): + """ + Serialize to csv and save a DataFrame by algo name and key. + + Parameters + ---------- + algo_name: str + key: str + df: DataFrame + environ: + rel_path: str + + """ folder = get_algo_folder(algo_name, environ) if rel_path is not None: @@ -166,6 +302,19 @@ def save_algo_df(algo_name, key, df, environ=None, rel_path=None): def get_exchange_minute_writer_root(exchange_name, environ=None): + """ + The minute writer folder for the exchange. + + Parameters + ---------- + exchange_name: str + environ: + + Returns + ------- + BcolzExchangeBarWriter + + """ exchange_folder = get_exchange_folder(exchange_name, environ) minute_data_folder = os.path.join(exchange_folder, 'minute_data') @@ -175,6 +324,19 @@ def get_exchange_minute_writer_root(exchange_name, environ=None): def get_exchange_bundles_folder(exchange_name, environ=None): + """ + The temp folder for bundle downloads by algo name. + + Parameters + ---------- + exchange_name: str + environ: + + Returns + ------- + str + + """ exchange_folder = get_exchange_folder(exchange_name, environ) temp_bundles = os.path.join(exchange_folder, 'temp_bundles') @@ -184,8 +346,140 @@ def get_exchange_bundles_folder(exchange_name, environ=None): def perf_serial(obj): - """JSON serializer for objects not serializable by default json code""" + """ + JSON serializer for objects not serializable by default json code + Parameters + ---------- + obj: Object + + Returns + ------- + str + + """ if isinstance(obj, (datetime, date)): return obj.isoformat() + raise TypeError("Type %s not serializable" % type(obj)) + + +def get_common_assets(exchanges): + """ + The assets available in all specified exchanges. + + Parameters + ---------- + exchanges: list[Exchange] + + Returns + ------- + list[TradingPair] + + """ + symbols = [] + for exchange_name in exchanges: + s = [asset.symbol for asset in exchanges[exchange_name].get_assets()] + symbols.append(s) + + inter_symbols = set.intersection(*map(set, symbols)) + + assets = [] + for symbol in inter_symbols: + for exchange_name in exchanges: + asset = exchanges[exchange_name].get_asset(symbol) + assets.append(asset) + + return assets + + +def get_frequency(freq, data_frequency): + """ + Get the frequency parameters. + + Notes + ----- + We're trying to use Pandas convention for frequency aliases. + + Parameters + ---------- + freq: str + data_frequency: str + + Returns + ------- + str, int, str, str + + """ + if freq == 'minute': + unit = 'T' + candle_size = 1 + + elif freq == 'daily': + unit = 'D' + candle_size = 1 + + else: + freq_match = re.match(r'([0-9].*)?(m|M|d|D|h|H|T)', freq, re.M | re.I) + if freq_match: + candle_size = int(freq_match.group(1)) if freq_match.group(1) \ + else 1 + unit = freq_match.group(2) + + else: + raise InvalidHistoryFrequencyError(frequency=freq) + + if unit.lower() == 'd': + alias = '{}D'.format(candle_size) + + if data_frequency == 'minute': + data_frequency = 'daily' + + elif unit.lower() == 'm' or unit == 'T': + alias = '{}T'.format(candle_size) + + if data_frequency == 'daily': + data_frequency = 'minute' + + # elif unit.lower() == 'h': + # candle_size = candle_size * 60 + # + # alias = '{}T'.format(candle_size) + # if data_frequency == 'daily': + # data_frequency = 'minute' + + else: + raise InvalidHistoryFrequencyAlias(freq=freq) + + return alias, candle_size, unit, data_frequency + + +def resample_history_df(df, freq, field): + """ + Resample the OHCLV DataFrame using the specified frequency. + + Parameters + ---------- + df: DataFrame + freq: str + field: str + + Returns + ------- + DataFrame + + """ + if field == 'open': + agg = 'first' + elif field == 'high': + agg = 'max' + elif field == 'low': + agg = 'min' + elif field == 'close': + agg = 'last' + elif field == 'volume': + agg = 'sum' + else: + raise ValueError('Invalid field.') + + return df.resample(freq).agg(agg) diff --git a/catalyst/exchange/init_utils.py b/catalyst/exchange/factory.py similarity index 72% rename from catalyst/exchange/init_utils.py rename to catalyst/exchange/factory.py index a37f0441..72c66bd8 100644 --- a/catalyst/exchange/init_utils.py +++ b/catalyst/exchange/factory.py @@ -5,28 +5,39 @@ from catalyst.exchange.exchange_utils import get_exchange_auth from catalyst.exchange.poloniex.poloniex import Poloniex -def get_exchange(exchange_name): +def get_exchange(exchange_name, base_currency=None): exchange_auth = get_exchange_auth(exchange_name) if exchange_name == 'bitfinex': return Bitfinex( key=exchange_auth['key'], secret=exchange_auth['secret'], - base_currency=None, # TODO: make optional at the exchange + base_currency=base_currency, portfolio=None ) + elif exchange_name == 'bittrex': return Bittrex( key=exchange_auth['key'], secret=exchange_auth['secret'], - base_currency=None, + base_currency=base_currency, portfolio=None ) + elif exchange_name == 'poloniex': return Poloniex( key=exchange_auth['key'], secret=exchange_auth['secret'], - base_currency=None, + base_currency=base_currency, portfolio=None ) + else: raise ExchangeNotFoundError(exchange_name=exchange_name) + + +def get_exchanges(exchange_names): + exchanges = dict() + for exchange_name in exchange_names: + exchanges[exchange_name] = get_exchange(exchange_name) + + return exchanges diff --git a/catalyst/exchange/live_graph_clock.py b/catalyst/exchange/live_graph_clock.py index ecc83677..6f674455 100644 --- a/catalyst/exchange/live_graph_clock.py +++ b/catalyst/exchange/live_graph_clock.py @@ -1,16 +1,3 @@ -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - import pandas as pd from catalyst.gens.sim_engine import ( BAR, @@ -33,8 +20,8 @@ class LiveGraphClock(object): This mixes the clock with a live graph. - Note - ---- + Notes + ----- This seemingly awkward approach allows us to run the program using a single thread. This is important because Matplotlib does not play nice with multi-threaded environments. Zipline probably does not either. @@ -53,7 +40,7 @@ class LiveGraphClock(object): def __init__(self, sessions, context, time_skew=pd.Timedelta('0s')): - global mdates, plt #TODO: Could be cleaner + global mdates, plt # TODO: Could be cleaner import matplotlib.dates as mdates from matplotlib import pyplot as plt from matplotlib import style @@ -95,11 +82,12 @@ class LiveGraphClock(object): """ Trying to assign reasonable parameters to the time axis. - TODO: room for improvement + Parameters + ---------- + ax: - :param ax: - :return: """ + # TODO: room for improvement ax.xaxis.set_major_locator(mdates.DayLocator(interval=1)) ax.xaxis.set_major_formatter(self.fmt) @@ -113,9 +101,21 @@ class LiveGraphClock(object): ax.grid(True) def set_legend(self, ax): + """ + Set legend on the chart. + + Parameters + ---------- + ax + + """ ax.legend(loc='upper left', ncol=1, fontsize=10, numpoints=1) def draw_pnl(self): + """ + Draw p&l line on the chart. + + """ ax = self.ax_pnl df = self.context.pnl_stats @@ -136,6 +136,10 @@ class LiveGraphClock(object): self.format_ax(ax) def draw_custom_signals(self): + """ + Draw custom signals on the chart. + + """ ax = self.ax_custom_signals df = self.context.custom_signals_stats @@ -154,6 +158,10 @@ class LiveGraphClock(object): self.format_ax(ax) def draw_exposure(self): + """ + Draw exposure line on the chart. + + """ ax = self.ax_exposure context = self.context df = context.exposure_stats diff --git a/catalyst/exchange/poloniex/poloniex.py b/catalyst/exchange/poloniex/poloniex.py index 468463b0..65c397c7 100644 --- a/catalyst/exchange/poloniex/poloniex.py +++ b/catalyst/exchange/poloniex/poloniex.py @@ -1,3 +1,4 @@ +import calendar import json import json import time @@ -171,12 +172,12 @@ class Poloniex(Exchange): # TODO: fetch account data and keep in cache return None - def get_candles(self, data_frequency, assets, bar_count=None, + def get_candles(self, freq, assets, bar_count=None, start_dt=None, end_dt=None): """ Retrieve OHLVC candles from Poloniex - :param data_frequency: + :param freq: :param assets: :param bar_count: :return: @@ -193,31 +194,33 @@ class Poloniex(Exchange): 'retrieving {bars} {freq} candles on {exchange} from ' '{end_dt} for markets {symbols}, '.format( bars=bar_count, - freq=data_frequency, + freq=freq, exchange=self.name, end_dt=end_dt, symbols=get_symbols_string(assets) ) ) - if data_frequency == '5m': + if freq == '1T' and (bar_count == 1 or bar_count is None): + # TODO: use the order book instead + # We use the 5m to fetch the last bar frequency = 300 - elif data_frequency == '15m': + elif freq == '5T': + frequency = 300 + elif freq == '15T': frequency = 900 - elif data_frequency == '30m': + elif freq == '30T': frequency = 1800 - elif data_frequency == '2h': + elif freq == '120T': frequency = 7200 - elif data_frequency == '4h': + elif freq == '240T': frequency = 14400 - elif data_frequency == '1D' or data_frequency == 'daily': + elif freq == '1D': frequency = 86400 else: # Poloniex does not offer 1m data candles # It is likely to error out there frequently - raise InvalidHistoryFrequencyError( - frequency=data_frequency - ) + raise InvalidHistoryFrequencyError(frequency=freq) # Making sure that assets are iterable asset_list = [assets] if isinstance(assets, TradingPair) else assets @@ -225,15 +228,18 @@ class Poloniex(Exchange): for asset in asset_list: - end = int(time.mktime(end_dt.timetuple())) + # TODO: what's wrong with this? + # end = int(time.mktime(end_dt.timetuple())) + end = int(time.time()) if bar_count is None: start = end - 2 * frequency else: start = end - bar_count * frequency try: - response = self.api.returnchartdata(self.get_symbol(asset), - frequency, start, end) + response = self.api.returnchartdata( + self.get_symbol(asset), frequency, start, end + ) except Exception as e: raise ExchangeRequestError(error=e) diff --git a/catalyst/exchange/stats_utils.py b/catalyst/exchange/stats_utils.py index 602694d6..b7bfda98 100644 --- a/catalyst/exchange/stats_utils.py +++ b/catalyst/exchange/stats_utils.py @@ -1,14 +1,73 @@ +import numpy as np import pandas as pd +def crossover(source, target): + """ + The `x`-series is defined as having crossed over `y`-series if the value + of `x` is greater than the value of `y` and the value of `x` was less than + the value of `y` on the bar immediately preceding the current bar. + + Parameters + ---------- + source: Series + target: Series + + Returns + ------- + bool + + """ + if source[-1] is np.nan or source[-2] is np.nan \ + or target[-1] is np.nan or target[-2] is np.nan: + return False + + if source[-1] > target[-1] and source[-2] < target[-2]: + return True + else: + return False + + +def crossunder(source, target): + """ + The `x`-series is defined as having crossed under `y`-series if the value + of `x` is less than the value of `y` and the value of `x` was greater than + the value of `y` on the bar immediately preceding the current bar. + + Parameters + ---------- + source: Series + target: Series + + Returns + ------- + bool + + """ + if source[-1] is np.nan or source[-2] is np.nan \ + or target[-1] is np.nan or target[-2] is np.nan: + return False + + if source[-1] < target[-1] and source[-2] > target[-2]: + return True + else: + return False + + def get_pretty_stats(stats_df, recorded_cols=None, num_rows=10): """ Format and print the last few rows of a statistics DataFrame. See the pyfolio project for the data structure. - :param stats_df: - :param num_rows: - :return: + Parameters + ---------- + stats_df: DataFrame + num_rows: int + + Returns + ------- + str + """ stats_df.set_index('period_close', drop=True, inplace=True) stats_df.dropna(axis=1, how='all', inplace=True) @@ -52,6 +111,18 @@ def get_pretty_stats(stats_df, recorded_cols=None, num_rows=10): def df_to_string(df): + """ + Create a formatted str representation of the DataFrame. + + Parameters + ---------- + df: DataFrame + + Returns + ------- + str + + """ pd.set_option('display.expand_frame_repr', False) pd.set_option('precision', 8) pd.set_option('display.width', 1000) diff --git a/catalyst/support/__init__.py b/catalyst/support/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/catalyst/support/issue_44.py b/catalyst/support/issue_44.py new file mode 100644 index 00000000..b6d1277a --- /dev/null +++ b/catalyst/support/issue_44.py @@ -0,0 +1,109 @@ +import pandas as pd +from catalyst import run_algorithm +from catalyst.exchange.exchange_utils import get_exchange_symbols + +from catalyst.api import ( + symbols, +) + + +def initialize(context): + context.i = -1 + context.base_currency = 'btc' + + +def handle_data(context, data): + lookback = 60 * 24 * 7 # (minutes, hours, days) + context.i += 1 + if context.i < lookback: + return + + today = context.blotter.current_dt.strftime('%Y-%m-%d %H:%M:%S') + + try: + # update universe everyday + new_day = 60 * 24 + if not context.i % new_day: + context.universe = universe(context, today) + + # get data every 30 minutes + minutes = 30 + if not context.i % minutes and context.universe: + for coin in context.coins: + pair = str(coin.symbol) + + # ohlcv data + open = data.history(coin, 'open', lookback, + '1m').ffill().bfill().resample( + '30T').first() + high = data.history(coin, 'high', lookback, + '1m').ffill().bfill().resample('30T').max() + low = data.history(coin, 'low', lookback, + '1m').ffill().bfill().resample('30T').min() + close = data.history(coin, 'price', lookback, + '1m').ffill().bfill().resample( + '30T').last() + volume = data.history(coin, 'volume', lookback, + '1m').ffill().bfill().resample( + '30T').sum() + + print(today, pair, close[-1]) + + except Exception as e: + print(e) + + +def analyze(context=None, results=None): + pass + + +def universe(context, today): + json_symbols = get_exchange_symbols('poloniex') + poloniex_universe_df = pd.DataFrame.from_dict( + json_symbols).transpose().astype(str) + poloniex_universe_df['base_currency'] = poloniex_universe_df.apply( + lambda row: row.symbol.split('_')[1], + axis=1) + poloniex_universe_df['market_currency'] = poloniex_universe_df.apply( + lambda row: row.symbol.split('_')[0], + axis=1) + poloniex_universe_df = poloniex_universe_df[ + poloniex_universe_df['base_currency'] == context.base_currency] + poloniex_universe_df = poloniex_universe_df[ + poloniex_universe_df.symbol != 'gas_btc'] + + # Markets currently not working on Catalyst 0.3.1 + # 2017-01-01 + # poloniex_universe_df = poloniex_universe_df[poloniex_universe_df.symbol != 'bcn_btc'] + # poloniex_universe_df = poloniex_universe_df[poloniex_universe_df.symbol != 'burst_btc'] + # poloniex_universe_df = poloniex_universe_df[poloniex_universe_df.symbol != 'dgb_btc'] + # poloniex_universe_df = poloniex_universe_df[poloniex_universe_df.symbol != 'doge_btc'] + # poloniex_universe_df = poloniex_universe_df[poloniex_universe_df.symbol != 'emc2_btc'] + # poloniex_universe_df = poloniex_universe_df[poloniex_universe_df.symbol != 'pink_btc'] + # poloniex_universe_df = poloniex_universe_df[poloniex_universe_df.symbol != 'sc_btc'] + print(poloniex_universe_df.head()) + + date = str(today).split(' ')[0] + + poloniex_universe_df = poloniex_universe_df[ + poloniex_universe_df.start_date < date] + context.coins = symbols(*poloniex_universe_df.symbol) + print(len(poloniex_universe_df)) + return poloniex_universe_df.symbol.tolist() + + +if __name__ == '__main__': + start_date = pd.to_datetime('2017-01-01', utc=True) + end_date = pd.to_datetime('2017-10-15', utc=True) + + performance = run_algorithm(start=start_date, end=end_date, + capital_base=10000.0, + initialize=initialize, + handle_data=handle_data, + analyze=analyze, + exchange_name='poloniex', + data_frequency='minute', + base_currency='btc', + live=False, + live_graph=False, + algo_namespace='test') diff --git a/catalyst/support/issue_47.py b/catalyst/support/issue_47.py new file mode 100644 index 00000000..5341dd03 --- /dev/null +++ b/catalyst/support/issue_47.py @@ -0,0 +1,140 @@ +""" +Requires Catalyst version 0.3.0 or above +Tested on Catalyst version 0.3.2 + +These example aims to provide and easy way for users to learn how to collect data from the different exchanges. +You simply need to specify the exchange and the market that you want to focus on. +You will all see how to create a universe and filter it base on the exchange and the market you desire. + +The example prints out the closing price of all the pairs for a given market-exchange every 30 minutes. +The example also contains the ohlcv minute data for the past seven days which could be used to create indicators +Use this as the backbone to create your own trading strategies. + +Variables lookback date and date are used to ensure data for a coin existed on the lookback period specified. +""" + +import numpy as np +import pandas as pd +from datetime import timedelta +from catalyst import run_algorithm +from catalyst.exchange.exchange_utils import get_exchange_symbols + +from catalyst.api import ( + symbols, +) + + +def initialize(context): + context.i = -1 # counts the minutes + context.exchange = 'poloniex' # must match the exchange specified in run_algorithm + context.base_currency = 'eth' # must match the base currency specified in run_algorithm + + +def handle_data(context, data): + lookback = 60 * 24 * 7 # (minutes, hours, days) of how far to lookback in the data history + context.i += 1 + + # current date formatted into a string + today = context.blotter.current_dt + date, time = today.strftime('%Y-%m-%d %H:%M:%S').split(' ') + lookback_date = today - timedelta(days=( + lookback / (60 * 24))) # subtract the amount of days specified in lookback + lookback_date = lookback_date.strftime('%Y-%m-%d %H:%M:%S').split(' ')[ + 0] # get only the date as a string + + # update universe everyday + new_day = 60 * 24 + if not context.i % new_day: + context.universe = universe(context, lookback_date, date) + + # get data every 30 minutes + minutes = 30 + if not context.i % minutes and context.universe: + # we iterate for every pair in the current universe + for coin in context.coins: + pair = str(coin.symbol) + + # 30 minute interval ohlcv data (the standard data required for candlestick or indicators/signals) + # 30T means 30 minutes re-sampling of one minute data. change to your desire time interval. + open = fill(data.history(coin, 'open', bar_count=lookback, + frequency='1m')).resample('30T').first() + high = fill(data.history(coin, 'high', bar_count=lookback, + frequency='1m')).resample('30T').max() + low = fill(data.history(coin, 'low', bar_count=lookback, + frequency='1m')).resample('30T').min() + close = fill(data.history(coin, 'price', bar_count=lookback, + frequency='1m')).resample('30T').last() + volume = fill(data.history(coin, 'volume', bar_count=lookback, + frequency='1m')).resample('30T').sum() + + # close[-1] is the equivalent to current price + # displays the minute price for each pair every 30 minutes + print( + today, pair, open[-1], high[-1], low[-1], close[-1], volume[-1]) + + # ---------------------------------------------------------------------------------------------------------- + # -------------------------------------- Insert Your Strategy Here ----------------------------------------- + # ---------------------------------------------------------------------------------------------------------- + + +def analyze(context=None, results=None): + pass + + +# Get the universe for a given exchange and a given base_currency market +# Example: Poloniex BTC Market +def universe(context, lookback_date, current_date): + json_symbols = get_exchange_symbols( + context.exchange) # get all the pairs for the exchange + universe_df = pd.DataFrame.from_dict(json_symbols).transpose().astype( + str) # convert into a dataframe + universe_df['base_currency'] = universe_df.apply( + lambda row: row.symbol.split('_')[1], + axis=1) + universe_df['market_currency'] = universe_df.apply( + lambda row: row.symbol.split('_')[0], + axis=1) + # Filter all the exchange pairs to only the ones for a give base currency + universe_df = universe_df[ + universe_df['base_currency'] == context.base_currency] + + # Filter all the pairs to ensure that pair existed in the current date range + universe_df = universe_df[universe_df.start_date < lookback_date] + universe_df = universe_df[universe_df.end_daily >= current_date] + context.coins = symbols( + *universe_df.symbol) # convert all the pairs to symbols + print(universe_df.head(), len(universe_df)) + return universe_df.symbol.tolist() + + +# Replace all NA, NAN or infinite values with its nearest value +def fill(series): + if isinstance(series, pd.Series): + return series.replace([np.inf, -np.inf], np.nan).ffill().bfill() + elif isinstance(series, np.ndarray): + return pd.Series(series).replace([np.inf, -np.inf], + np.nan).ffill().bfill().values + else: + return series + + +if __name__ == '__main__': + start_date = pd.to_datetime('2017-01-01', utc=True) + end_date = pd.to_datetime('2017-10-15', utc=True) + + performance = run_algorithm(start=start_date, end=end_date, + capital_base=10000.0, + initialize=initialize, + handle_data=handle_data, + analyze=analyze, + exchange_name='poloniex', + data_frequency='minute', + base_currency='eth', + live=False, + live_graph=False, + algo_namespace='simple_universe') + +""" +Run in Terminal (inside catalyst environment): +python simple_universe.py +""" diff --git a/catalyst/support/rodrigo_1.py b/catalyst/support/rodrigo_1.py new file mode 100644 index 00000000..ec32c617 --- /dev/null +++ b/catalyst/support/rodrigo_1.py @@ -0,0 +1,153 @@ +import pandas as pd +from logbook import Logger, DEBUG + +from catalyst import run_algorithm +from catalyst.api import (schedule_function, order_target_percent, symbol, + date_rules, get_open_orders, cancel_order, record, + set_commission, set_slippage) + +log = Logger('rodrigo_1', level=DEBUG) +""" +The initialize function sets any data or variables that +you'll use in your algorithm. +It's only called once at the beginning of your algorithm. +""" + + +def initialize(context): + # Select asset of interest + context.asset = symbol('BTC_USD') + + # set_commission(TradingPairFeeSchedule(maker_fee=0.5, taker_fee=0.5)) + # set_slippage(TradingPairFixedSlippage(spread=0.5)) + # Set up a rebalance method to run every day + schedule_function(rebalance, date_rule=date_rules.every_day()) + + +""" +Rebalance function scheduled to run once per day. +""" + + +def rebalance(context, data): + # To make market decisions, we're calculating the token's + # moving average for the last 5 days. + + # We get the price history for the last 5 days. + price_history = data.history(context.asset, fields='price', bar_count=5, + frequency='1d') + + # Then we take an average of those 5 days. + average_price = price_history.mean() + + # We also get the coin's current price. + price = data.current(context.asset, 'price') + + # Cancel any outstanding orders + orders = get_open_orders(context.asset) or [] + for order in orders: + cancel_order(order) + + # If our coin is currently listed on a major exchange + if data.can_trade(context.asset): + # If the current price is 1% above the 5-day average price, + # we open a long position. If the current price is below the + # average price, then we want to close our position to 0 shares. + if price > (1.01 * average_price): + # Place the buy order (positive means buy, negative means sell) + order_target_percent(context.asset, .99) + log.info("Buying %s" % (context.asset.symbol)) + elif price < average_price: + # Sell all of our shares by setting the target position to zero + order_target_percent(context.asset, 0) + log.info("Selling %s" % (context.asset.symbol)) + + # Use the record() method to track up to five custom signals. + # Record Apple's current price and the average price over the last + # five days. + cash = context.portfolio.cash + leverage = context.account.leverage + + record(price=price, average_price=average_price, cash=cash, + leverage=leverage) + + +def analyze(context=None, results=None): + import matplotlib.pyplot as plt + + # Plot the portfolio and asset data. + ax1 = plt.subplot(511) + results[['portfolio_value']].plot(ax=ax1) + ax1.set_ylabel('Portfolio Value (USD)') + + ax2 = plt.subplot(512, sharex=ax1) + ax2.set_ylabel('{asset} (USD)'.format(asset=context.asset)) + (results[[ + 'price', + ]]).plot(ax=ax2) + + trans = results.ix[[t != [] for t in results.transactions]] + buys = trans.ix[ + [t[0]['amount'] > 0 for t in trans.transactions] + ] + sells = trans.ix[ + [t[0]['amount'] < 0 for t in trans.transactions] + ] + + ax2.plot( + buys.index, + results.price[buys.index], + '^', + markersize=10, + color='g', + ) + ax2.plot( + sells.index, + results.price[sells.index], + 'v', + markersize=10, + color='r', + ) + + ax3 = plt.subplot(513, sharex=ax1) + results[['leverage']].plot(ax=ax3) + ax3.set_ylabel('Leverage ') + + ax4 = plt.subplot(514, sharex=ax1) + results[['cash']].plot(ax=ax4) + ax4.set_ylabel('Cash (USD)') + + results[[ + 'algorithm', + 'benchmark', + ]] = results[[ + 'algorithm_period_return', + 'benchmark_period_return', + ]] + + ax5 = plt.subplot(515, sharex=ax1) + results[[ + 'algorithm', + 'benchmark', + ]].plot(ax=ax5) + ax5.set_ylabel('Percent Change') + + plt.legend(loc=3) + + # Show the plot. + plt.gcf().set_size_inches(18, 8) + plt.show() + + +run_algorithm( + capital_base=100000, + start=pd.to_datetime('2017-1-1', utc=True), + end=pd.to_datetime('2017-10-22', utc=True), + data_frequency='minute', + initialize=initialize, + handle_data=None, + analyze=analyze, + exchange_name='bitfinex', + algo_namespace='rodrigo_1', + base_currency='usd' +) diff --git a/catalyst/utils/run_algo.py b/catalyst/utils/run_algo.py index a5293ac5..c12dedc9 100644 --- a/catalyst/utils/run_algo.py +++ b/catalyst/utils/run_algo.py @@ -31,7 +31,7 @@ import catalyst.utils.paths as pth from catalyst.exchange.exchange_algorithm import ExchangeTradingAlgorithmLive, \ ExchangeTradingAlgorithmBacktest -from catalyst.exchange.data_portal_exchange import DataPortalExchangeLive, \ +from catalyst.exchange.exchange_data_portal import DataPortalExchangeLive, \ DataPortalExchangeBacktest from catalyst.exchange.asset_finder_exchange import AssetFinderExchange from catalyst.exchange.exchange_portfolio import ExchangePortfolio diff --git a/docs/live-trading-wiki.md b/docs/live-trading-wiki.md deleted file mode 100644 index a7dbd9f1..00000000 --- a/docs/live-trading-wiki.md +++ /dev/null @@ -1,105 +0,0 @@ -
| + +.. raw:: html + + | + +.. raw:: html + ++ +algo_volatility + +.. raw:: html + + | + +.. raw:: html + ++ +algorithm_period_return + +.. raw:: html + + | + +.. raw:: html + ++ +alpha + +.. raw:: html + + | + +.. raw:: html + ++ +benchmark_period_return + +.. raw:: html + + | + +.. raw:: html + ++ +benchmark_volatility + +.. raw:: html + + | + +.. raw:: html + ++ +beta + +.. raw:: html + + | + +.. raw:: html + ++ +capital_used + +.. raw:: html + + | + +.. raw:: html + ++ +cash + +.. raw:: html + + | + +.. raw:: html + ++ +ending_cash + +.. raw:: html + + | + +.. raw:: html + ++ +ending_exposure + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +starting_cash + +.. raw:: html + + | + +.. raw:: html + ++ +starting_exposure + +.. raw:: html + + | + +.. raw:: html + ++ +starting_value + +.. raw:: html + + | + +.. raw:: html + ++ +trading_days + +.. raw:: html + + | + +.. raw:: html + ++ +transactions + +.. raw:: html + + | + +.. raw:: html + ++ +treasury_period_return + +.. raw:: html + + | + +.. raw:: html + ++ +volume + +.. raw:: html + + | + +.. raw:: html + ++ +treasury + +.. raw:: html + + | + +.. raw:: html + ++ +algorithm + +.. raw:: html + + | + +.. raw:: html + ++ +benchmark + +.. raw:: html + + | + +.. raw:: html + +
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| + +2015-03-01 23:59:00+00:00 + +.. raw:: html + + | + +.. raw:: html + ++ +NaN + +.. raw:: html + + | + +.. raw:: html + ++ +0.000000 + +.. raw:: html + + | + +.. raw:: html + ++ +NaN + +.. raw:: html + + | + +.. raw:: html + ++ +0.045833 + +.. raw:: html + + | + +.. raw:: html + ++ +NaN + +.. raw:: html + + | + +.. raw:: html + ++ +NaN + +.. raw:: html + + | + +.. raw:: html + ++ +0.000000 + +.. raw:: html + + | + +.. raw:: html + ++ +100000.000000 + +.. raw:: html + + | + +.. raw:: html + ++ +100000.000000 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000 + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +100000.0 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000 + +.. raw:: html + + | + +.. raw:: html + ++ +1 + +.. raw:: html + + | + +.. raw:: html + ++ +[] + +.. raw:: html + + | + +.. raw:: html + ++ +0.0200 + +.. raw:: html + + | + +.. raw:: html + ++ +317 + +.. raw:: html + + | + +.. raw:: html + ++ +0.0200 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000000 + +.. raw:: html + + | + +.. raw:: html + ++ +0.045833 + +.. raw:: html + + | + +.. raw:: html + +
| + +2015-03-02 23:59:00+00:00 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000278 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.000025 + +.. raw:: html + + | + +.. raw:: html + ++ +0.011045 + +.. raw:: html + + | + +.. raw:: html + ++ +0.120833 + +.. raw:: html + + | + +.. raw:: html + ++ +0.290503 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.000956 + +.. raw:: html + + | + +.. raw:: html + ++ +-85544.474955 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +85542.000 + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +100000.0 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000 + +.. raw:: html + + | + +.. raw:: html + ++ +2 + +.. raw:: html + + | + +.. raw:: html + ++ +[{u’commission’: None, u’amount’: 318, u’sid’:… + +.. raw:: html + + | + +.. raw:: html + ++ +0.0208 + +.. raw:: html + + | + +.. raw:: html + ++ +98063 + +.. raw:: html + + | + +.. raw:: html + ++ +0.0208 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.000025 + +.. raw:: html + + | + +.. raw:: html + ++ +0.120833 + +.. raw:: html + + | + +.. raw:: html + +
| + +2015-03-03 23:59:00+00:00 + +.. raw:: html + + | + +.. raw:: html + ++ +0.051796 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.005688 + +.. raw:: html + + | + +.. raw:: html + ++ +-1.197544 + +.. raw:: html + + | + +.. raw:: html + ++ +0.113416 + +.. raw:: html + + | + +.. raw:: html + ++ +0.633538 + +.. raw:: html + + | + +.. raw:: html + ++ +0.077239 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000000 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +84975.642 + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +100000.0 + +.. raw:: html + + | + +.. raw:: html + ++ +85542.000 + +.. raw:: html + + | + +.. raw:: html + ++ +85542.000 + +.. raw:: html + + | + +.. raw:: html + ++ +3 + +.. raw:: html + + | + +.. raw:: html + ++ +[] + +.. raw:: html + + | + +.. raw:: html + ++ +0.0212 + +.. raw:: html + + | + +.. raw:: html + ++ +442983 + +.. raw:: html + + | + +.. raw:: html + ++ +0.0212 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.005688 + +.. raw:: html + + | + +.. raw:: html + ++ +0.113416 + +.. raw:: html + + | + +.. raw:: html + +
| + +2015-03-04 23:59:00+00:00 + +.. raw:: html + + | + +.. raw:: html + ++ +0.342118 + +.. raw:: html + + | + +.. raw:: html + ++ +0.034955 + +.. raw:: html + + | + +.. raw:: html + ++ +0.401861 + +.. raw:: html + + | + +.. raw:: html + ++ +0.166666 + +.. raw:: html + + | + +.. raw:: html + ++ +0.524400 + +.. raw:: html + + | + +.. raw:: html + ++ +0.181468 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000000 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +89040.000 + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +100000.0 + +.. raw:: html + + | + +.. raw:: html + ++ +84975.642 + +.. raw:: html + + | + +.. raw:: html + ++ +84975.642 + +.. raw:: html + + | + +.. raw:: html + ++ +4 + +.. raw:: html + + | + +.. raw:: html + ++ +[] + +.. raw:: html + + | + +.. raw:: html + ++ +0.0212 + +.. raw:: html + + | + +.. raw:: html + ++ +245889 + +.. raw:: html + + | + +.. raw:: html + ++ +0.0212 + +.. raw:: html + + | + +.. raw:: html + ++ +0.034955 + +.. raw:: html + + | + +.. raw:: html + ++ +0.166666 + +.. raw:: html + + | + +.. raw:: html + +
| + +2015-03-05 23:59:00+00:00 + +.. raw:: html + + | + +.. raw:: html + ++ +0.637226 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.038185 + +.. raw:: html + + | + +.. raw:: html + ++ +-3.914003 + +.. raw:: html + + | + +.. raw:: html + ++ +0.070834 + +.. raw:: html + + | + +.. raw:: html + ++ +0.976896 + +.. raw:: html + + | + +.. raw:: html + ++ +0.550520 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000000 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +81726.000 + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +100000.0 + +.. raw:: html + + | + +.. raw:: html + ++ +89040.000 + +.. raw:: html + + | + +.. raw:: html + ++ +89040.000 + +.. raw:: html + + | + +.. raw:: html + ++ +5 + +.. raw:: html + + | + +.. raw:: html + ++ +[] + +.. raw:: html + + | + +.. raw:: html + ++ +0.0211 + +.. raw:: html + + | + +.. raw:: html + ++ +117440 + +.. raw:: html + + | + +.. raw:: html + ++ +0.0211 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.038185 + +.. raw:: html + + | + +.. raw:: html + ++ +0.070834 + +.. raw:: html + + | + +.. raw:: html + +
| + +2015-03-06 23:59:00+00:00 + +.. raw:: html + + | + +.. raw:: html + ++ +0.580521 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.028645 + +.. raw:: html + + | + +.. raw:: html + ++ +-3.100822 + +.. raw:: html + + | + +.. raw:: html + ++ +0.083333 + +.. raw:: html + + | + +.. raw:: html + ++ +0.874082 + +.. raw:: html + + | + +.. raw:: html + ++ +0.546703 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000000 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +82680.000 + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +100000.0 + +.. raw:: html + + | + +.. raw:: html + ++ +81726.000 + +.. raw:: html + + | + +.. raw:: html + ++ +81726.000 + +.. raw:: html + + | + +.. raw:: html + ++ +6 + +.. raw:: html + + | + +.. raw:: html + ++ +[] + +.. raw:: html + + | + +.. raw:: html + ++ +0.0224 + +.. raw:: html + + | + +.. raw:: html + ++ +84197 + +.. raw:: html + + | + +.. raw:: html + ++ +0.0224 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.028645 + +.. raw:: html + + | + +.. raw:: html + ++ +0.083333 + +.. raw:: html + + | + +.. raw:: html + +
| + +2015-03-07 23:59:00+00:00 + +.. raw:: html + + | + +.. raw:: html + ++ +0.530557 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.028645 + +.. raw:: html + + | + +.. raw:: html + ++ +-2.625704 + +.. raw:: html + + | + +.. raw:: html + ++ +0.083333 + +.. raw:: html + + | + +.. raw:: html + ++ +0.802793 + +.. raw:: html + + | + +.. raw:: html + ++ +0.536589 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000000 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +82680.000 + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +100000.0 + +.. raw:: html + + | + +.. raw:: html + ++ +82680.000 + +.. raw:: html + + | + +.. raw:: html + ++ +82680.000 + +.. raw:: html + + | + +.. raw:: html + ++ +7 + +.. raw:: html + + | + +.. raw:: html + ++ +[] + +.. raw:: html + + | + +.. raw:: html + ++ +0.0224 + +.. raw:: html + + | + +.. raw:: html + ++ +181 + +.. raw:: html + + | + +.. raw:: html + ++ +0.0224 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.028645 + +.. raw:: html + + | + +.. raw:: html + ++ +0.083333 + +.. raw:: html + + | + +.. raw:: html + +
| + +2015-03-08 23:59:00+00:00 + +.. raw:: html + + | + +.. raw:: html + ++ +0.491628 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.028645 + +.. raw:: html + + | + +.. raw:: html + ++ +-2.276841 + +.. raw:: html + + | + +.. raw:: html + ++ +0.083333 + +.. raw:: html + + | + +.. raw:: html + ++ +0.746605 + +.. raw:: html + + | + +.. raw:: html + ++ +0.529163 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000000 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +82680.000 + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +100000.0 + +.. raw:: html + + | + +.. raw:: html + ++ +82680.000 + +.. raw:: html + + | + +.. raw:: html + ++ +82680.000 + +.. raw:: html + + | + +.. raw:: html + ++ +8 + +.. raw:: html + + | + +.. raw:: html + ++ +[] + +.. raw:: html + + | + +.. raw:: html + ++ +0.0224 + +.. raw:: html + + | + +.. raw:: html + ++ +30900 + +.. raw:: html + + | + +.. raw:: html + ++ +0.0224 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.028645 + +.. raw:: html + + | + +.. raw:: html + ++ +0.083333 + +.. raw:: html + + | + +.. raw:: html + +
| + +2015-03-09 23:59:00+00:00 + +.. raw:: html + + | + +.. raw:: html + ++ +0.467885 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.015925 + +.. raw:: html + + | + +.. raw:: html + ++ +-1.895269 + +.. raw:: html + + | + +.. raw:: html + ++ +0.100000 + +.. raw:: html + + | + +.. raw:: html + ++ +0.698764 + +.. raw:: html + + | + +.. raw:: html + ++ +0.532652 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000000 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +83952.000 + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +100000.0 + +.. raw:: html + + | + +.. raw:: html + ++ +82680.000 + +.. raw:: html + + | + +.. raw:: html + ++ +82680.000 + +.. raw:: html + + | + +.. raw:: html + ++ +9 + +.. raw:: html + + | + +.. raw:: html + ++ +[] + +.. raw:: html + + | + +.. raw:: html + ++ +0.0220 + +.. raw:: html + + | + +.. raw:: html + ++ +128367 + +.. raw:: html + + | + +.. raw:: html + ++ +0.0220 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.015925 + +.. raw:: html + + | + +.. raw:: html + ++ +0.100000 + +.. raw:: html + + | + +.. raw:: html + +
| + +2015-03-10 23:59:00+00:00 + +.. raw:: html + + | + +.. raw:: html + ++ +0.626552 + +.. raw:: html + + | + +.. raw:: html + ++ +0.069935 + +.. raw:: html + + | + +.. raw:: html + ++ +-1.625285 + +.. raw:: html + + | + +.. raw:: html + ++ +0.212500 + +.. raw:: html + + | + +.. raw:: html + ++ +0.800983 + +.. raw:: html + + | + +.. raw:: html + ++ +0.676289 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000000 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +92538.000 + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +100000.0 + +.. raw:: html + + | + +.. raw:: html + ++ +83952.000 + +.. raw:: html + + | + +.. raw:: html + ++ +83952.000 + +.. raw:: html + + | + +.. raw:: html + ++ +10 + +.. raw:: html + + | + +.. raw:: html + ++ +[] + +.. raw:: html + + | + +.. raw:: html + ++ +0.0214 + +.. raw:: html + + | + +.. raw:: html + ++ +54961 + +.. raw:: html + + | + +.. raw:: html + ++ +0.0214 + +.. raw:: html + + | + +.. raw:: html + ++ +0.069935 + +.. raw:: html + + | + +.. raw:: html + ++ +0.212500 + +.. raw:: html + + | + +.. raw:: html + +
| + +2015-03-11 23:59:00+00:00 + +.. raw:: html + + | + +.. raw:: html + ++ +0.644515 + +.. raw:: html + + | + +.. raw:: html + ++ +0.022235 + +.. raw:: html + + | + +.. raw:: html + ++ +-1.727710 + +.. raw:: html + + | + +.. raw:: html + ++ +0.150000 + +.. raw:: html + + | + +.. raw:: html + ++ +0.834650 + +.. raw:: html + + | + +.. raw:: html + ++ +0.684052 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000000 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +87768.000 + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +100000.0 + +.. raw:: html + + | + +.. raw:: html + ++ +92538.000 + +.. raw:: html + + | + +.. raw:: html + ++ +92538.000 + +.. raw:: html + + | + +.. raw:: html + ++ +11 + +.. raw:: html + + | + +.. raw:: html + ++ +[] + +.. raw:: html + + | + +.. raw:: html + ++ +0.0211 + +.. raw:: html + + | + +.. raw:: html + ++ +42511 + +.. raw:: html + + | + +.. raw:: html + ++ +0.0211 + +.. raw:: html + + | + +.. raw:: html + ++ +0.022235 + +.. raw:: html + + | + +.. raw:: html + ++ +0.150000 + +.. raw:: html + + | + +.. raw:: html + +
| + +2015-03-12 23:59:00+00:00 + +.. raw:: html + + | + +.. raw:: html + ++ +0.614650 + +.. raw:: html + + | + +.. raw:: html + ++ +0.022235 + +.. raw:: html + + | + +.. raw:: html + ++ +-1.573455 + +.. raw:: html + + | + +.. raw:: html + ++ +0.150000 + +.. raw:: html + + | + +.. raw:: html + ++ +0.798403 + +.. raw:: html + + | + +.. raw:: html + ++ +0.680882 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000000 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +87768.000 + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +100000.0 + +.. raw:: html + + | + +.. raw:: html + ++ +87768.000 + +.. raw:: html + + | + +.. raw:: html + ++ +87768.000 + +.. raw:: html + + | + +.. raw:: html + ++ +12 + +.. raw:: html + + | + +.. raw:: html + ++ +[] + +.. raw:: html + + | + +.. raw:: html + ++ +0.0210 + +.. raw:: html + + | + +.. raw:: html + ++ +2909 + +.. raw:: html + + | + +.. raw:: html + ++ +0.0210 + +.. raw:: html + + | + +.. raw:: html + ++ +0.022235 + +.. raw:: html + + | + +.. raw:: html + ++ +0.150000 + +.. raw:: html + + | + +.. raw:: html + +
| + +2015-03-13 23:59:00+00:00 + +.. raw:: html + + | + +.. raw:: html + ++ +0.588942 + +.. raw:: html + + | + +.. raw:: html + ++ +0.019405 + +.. raw:: html + + | + +.. raw:: html + ++ +-1.454733 + +.. raw:: html + + | + +.. raw:: html + ++ +0.146291 + +.. raw:: html + + | + +.. raw:: html + ++ +0.767688 + +.. raw:: html + + | + +.. raw:: html + ++ +0.677881 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000000 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +87484.980 + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +100000.0 + +.. raw:: html + + | + +.. raw:: html + ++ +87768.000 + +.. raw:: html + + | + +.. raw:: html + ++ +87768.000 + +.. raw:: html + + | + +.. raw:: html + ++ +13 + +.. raw:: html + + | + +.. raw:: html + ++ +[] + +.. raw:: html + + | + +.. raw:: html + ++ +0.0213 + +.. raw:: html + + | + +.. raw:: html + ++ +57613 + +.. raw:: html + + | + +.. raw:: html + ++ +0.0213 + +.. raw:: html + + | + +.. raw:: html + ++ +0.019405 + +.. raw:: html + + | + +.. raw:: html + ++ +0.146291 + +.. raw:: html + + | + +.. raw:: html + +
| + +2015-03-14 23:59:00+00:00 + +.. raw:: html + + | + +.. raw:: html + ++ +0.565911 + +.. raw:: html + + | + +.. raw:: html + ++ +0.019373 + +.. raw:: html + + | + +.. raw:: html + ++ +-1.344915 + +.. raw:: html + + | + +.. raw:: html + ++ +0.146250 + +.. raw:: html + + | + +.. raw:: html + ++ +0.739230 + +.. raw:: html + + | + +.. raw:: html + ++ +0.675665 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000000 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +87481.800 + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +100000.0 + +.. raw:: html + + | + +.. raw:: html + ++ +87484.980 + +.. raw:: html + + | + +.. raw:: html + ++ +87484.980 + +.. raw:: html + + | + +.. raw:: html + ++ +14 + +.. raw:: html + + | + +.. raw:: html + ++ +[] + +.. raw:: html + + | + +.. raw:: html + ++ +0.0213 + +.. raw:: html + + | + +.. raw:: html + ++ +48310 + +.. raw:: html + + | + +.. raw:: html + ++ +0.0213 + +.. raw:: html + + | + +.. raw:: html + ++ +0.019373 + +.. raw:: html + + | + +.. raw:: html + ++ +0.146250 + +.. raw:: html + + | + +.. raw:: html + +
| + +2015-03-15 23:59:00+00:00 + +.. raw:: html + + | + +.. raw:: html + ++ +0.551394 + +.. raw:: html + + | + +.. raw:: html + ++ +0.041659 + +.. raw:: html + + | + +.. raw:: html + ++ +-1.191436 + +.. raw:: html + + | + +.. raw:: html + ++ +0.175450 + +.. raw:: html + + | + +.. raw:: html + ++ +0.714876 + +.. raw:: html + + | + +.. raw:: html + ++ +0.680484 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000000 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +89710.344 + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +100000.0 + +.. raw:: html + + | + +.. raw:: html + ++ +87481.800 + +.. raw:: html + + | + +.. raw:: html + ++ +87481.800 + +.. raw:: html + + | + +.. raw:: html + ++ +15 + +.. raw:: html + + | + +.. raw:: html + ++ +[] + +.. raw:: html + + | + +.. raw:: html + ++ +0.0213 + +.. raw:: html + + | + +.. raw:: html + ++ +29454 + +.. raw:: html + + | + +.. raw:: html + ++ +0.0213 + +.. raw:: html + + | + +.. raw:: html + ++ +0.041659 + +.. raw:: html + + | + +.. raw:: html + ++ +0.175450 + +.. raw:: html + + | + +.. raw:: html + +
| + +2015-03-16 23:59:00+00:00 + +.. raw:: html + + | + +.. raw:: html + ++ +0.541846 + +.. raw:: html + + | + +.. raw:: html + ++ +0.019055 + +.. raw:: html + + | + +.. raw:: html + ++ +-1.188212 + +.. raw:: html + + | + +.. raw:: html + ++ +0.145833 + +.. raw:: html + + | + +.. raw:: html + ++ +0.706049 + +.. raw:: html + + | + +.. raw:: html + ++ +0.680281 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000000 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +87450.000 + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +100000.0 + +.. raw:: html + + | + +.. raw:: html + ++ +89710.344 + +.. raw:: html + + | + +.. raw:: html + ++ +89710.344 + +.. raw:: html + + | + +.. raw:: html + ++ +16 + +.. raw:: html + + | + +.. raw:: html + ++ +[] + +.. raw:: html + + | + +.. raw:: html + ++ +0.0210 + +.. raw:: html + + | + +.. raw:: html + ++ +25564 + +.. raw:: html + + | + +.. raw:: html + ++ +0.0210 + +.. raw:: html + + | + +.. raw:: html + ++ +0.019055 + +.. raw:: html + + | + +.. raw:: html + ++ +0.145833 + +.. raw:: html + + | + +.. raw:: html + +
| + +2015-03-17 23:59:00+00:00 + +.. raw:: html + + | + +.. raw:: html + ++ +0.524682 + +.. raw:: html + + | + +.. raw:: html + ++ +0.019055 + +.. raw:: html + + | + +.. raw:: html + ++ +-1.115149 + +.. raw:: html + + | + +.. raw:: html + ++ +0.145833 + +.. raw:: html + + | + +.. raw:: html + ++ +0.684599 + +.. raw:: html + + | + +.. raw:: html + ++ +0.678870 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000000 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +87450.000 + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +100000.0 + +.. raw:: html + + | + +.. raw:: html + ++ +87450.000 + +.. raw:: html + + | + +.. raw:: html + ++ +87450.000 + +.. raw:: html + + | + +.. raw:: html + ++ +17 + +.. raw:: html + + | + +.. raw:: html + ++ +[] + +.. raw:: html + + | + +.. raw:: html + ++ +0.0206 + +.. raw:: html + + | + +.. raw:: html + ++ +9 + +.. raw:: html + + | + +.. raw:: html + ++ +0.0206 + +.. raw:: html + + | + +.. raw:: html + ++ +0.019055 + +.. raw:: html + + | + +.. raw:: html + ++ +0.145833 + +.. raw:: html + + | + +.. raw:: html + +
| + +2015-03-18 23:59:00+00:00 + +.. raw:: html + + | + +.. raw:: html + ++ +0.532621 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.021999 + +.. raw:: html + + | + +.. raw:: html + ++ +-1.180440 + +.. raw:: html + + | + +.. raw:: html + ++ +0.092041 + +.. raw:: html + + | + +.. raw:: html + ++ +0.696261 + +.. raw:: html + + | + +.. raw:: html + ++ +0.685307 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000000 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +83344.620 + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +100000.0 + +.. raw:: html + + | + +.. raw:: html + ++ +87450.000 + +.. raw:: html + + | + +.. raw:: html + ++ +87450.000 + +.. raw:: html + + | + +.. raw:: html + ++ +18 + +.. raw:: html + + | + +.. raw:: html + ++ +[] + +.. raw:: html + + | + +.. raw:: html + ++ +0.0193 + +.. raw:: html + + | + +.. raw:: html + ++ +164911 + +.. raw:: html + + | + +.. raw:: html + ++ +0.0193 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.021999 + +.. raw:: html + + | + +.. raw:: html + ++ +0.092041 + +.. raw:: html + + | + +.. raw:: html + +
| + +2015-03-19 23:59:00+00:00 + +.. raw:: html + + | + +.. raw:: html + ++ +0.518811 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.013234 + +.. raw:: html + + | + +.. raw:: html + ++ +-1.096387 + +.. raw:: html + + | + +.. raw:: html + ++ +0.103526 + +.. raw:: html + + | + +.. raw:: html + ++ +0.676861 + +.. raw:: html + + | + +.. raw:: html + ++ +0.686186 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000000 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +84221.028 + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +100000.0 + +.. raw:: html + + | + +.. raw:: html + ++ +83344.620 + +.. raw:: html + + | + +.. raw:: html + ++ +83344.620 + +.. raw:: html + + | + +.. raw:: html + ++ +19 + +.. raw:: html + + | + +.. raw:: html + ++ +[] + +.. raw:: html + + | + +.. raw:: html + ++ +0.0198 + +.. raw:: html + + | + +.. raw:: html + ++ +713904 + +.. raw:: html + + | + +.. raw:: html + ++ +0.0198 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.013234 + +.. raw:: html + + | + +.. raw:: html + ++ +0.103526 + +.. raw:: html + + | + +.. raw:: html + +
| + +2015-03-20 23:59:00+00:00 + +.. raw:: html + + | + +.. raw:: html + ++ +0.505168 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.017324 + +.. raw:: html + + | + +.. raw:: html + ++ +-1.050273 + +.. raw:: html + + | + +.. raw:: html + ++ +0.098170 + +.. raw:: html + + | + +.. raw:: html + ++ +0.659945 + +.. raw:: html + + | + +.. raw:: html + ++ +0.685070 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000000 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +83812.080 + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +100000.0 + +.. raw:: html + + | + +.. raw:: html + ++ +84221.028 + +.. raw:: html + + | + +.. raw:: html + ++ +84221.028 + +.. raw:: html + + | + +.. raw:: html + ++ +20 + +.. raw:: html + + | + +.. raw:: html + ++ +[] + +.. raw:: html + + | + +.. raw:: html + ++ +0.0193 + +.. raw:: html + + | + +.. raw:: html + ++ +132725 + +.. raw:: html + + | + +.. raw:: html + ++ +0.0193 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.017324 + +.. raw:: html + + | + +.. raw:: html + ++ +0.098170 + +.. raw:: html + + | + +.. raw:: html + +
| + +2015-03-21 23:59:00+00:00 + +.. raw:: html + + | + +.. raw:: html + ++ +0.492384 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.018494 + +.. raw:: html + + | + +.. raw:: html + ++ +-1.002051 + +.. raw:: html + + | + +.. raw:: html + ++ +0.096637 + +.. raw:: html + + | + +.. raw:: html + ++ +0.643679 + +.. raw:: html + + | + +.. raw:: html + ++ +0.684283 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000000 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +83695.056 + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +100000.0 + +.. raw:: html + + | + +.. raw:: html + ++ +83812.080 + +.. raw:: html + + | + +.. raw:: html + ++ +83812.080 + +.. raw:: html + + | + +.. raw:: html + ++ +21 + +.. raw:: html + + | + +.. raw:: html + ++ +[] + +.. raw:: html + + | + +.. raw:: html + ++ +0.0193 + +.. raw:: html + + | + +.. raw:: html + ++ +201155 + +.. raw:: html + + | + +.. raw:: html + ++ +0.0193 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.018494 + +.. raw:: html + + | + +.. raw:: html + ++ +0.096637 + +.. raw:: html + + | + +.. raw:: html + +
| + +2015-03-22 23:59:00+00:00 + +.. raw:: html + + | + +.. raw:: html + ++ +0.482998 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.004744 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.927947 + +.. raw:: html + + | + +.. raw:: html + ++ +0.114653 + +.. raw:: html + + | + +.. raw:: html + ++ +0.629319 + +.. raw:: html + + | + +.. raw:: html + ++ +0.686478 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000000 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +85070.088 + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +100000.0 + +.. raw:: html + + | + +.. raw:: html + ++ +83695.056 + +.. raw:: html + + | + +.. raw:: html + ++ +83695.056 + +.. raw:: html + + | + +.. raw:: html + ++ +22 + +.. raw:: html + + | + +.. raw:: html + ++ +[] + +.. raw:: html + + | + +.. raw:: html + ++ +0.0193 + +.. raw:: html + + | + +.. raw:: html + ++ +64378 + +.. raw:: html + + | + +.. raw:: html + ++ +0.0193 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.004744 + +.. raw:: html + + | + +.. raw:: html + ++ +0.114653 + +.. raw:: html + + | + +.. raw:: html + +
| + +2015-03-23 23:59:00+00:00 + +.. raw:: html + + | + +.. raw:: html + ++ +0.477523 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.026505 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.935352 + +.. raw:: html + + | + +.. raw:: html + ++ +0.086139 + +.. raw:: html + + | + +.. raw:: html + ++ +0.623502 + +.. raw:: html + + | + +.. raw:: html + ++ +0.687025 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000000 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +82894.014 + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +100000.0 + +.. raw:: html + + | + +.. raw:: html + ++ +85070.088 + +.. raw:: html + + | + +.. raw:: html + ++ +85070.088 + +.. raw:: html + + | + +.. raw:: html + ++ +23 + +.. raw:: html + + | + +.. raw:: html + ++ +[] + +.. raw:: html + + | + +.. raw:: html + ++ +0.0192 + +.. raw:: html + + | + +.. raw:: html + ++ +61850 + +.. raw:: html + + | + +.. raw:: html + ++ +0.0192 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.026505 + +.. raw:: html + + | + +.. raw:: html + ++ +0.086139 + +.. raw:: html + + | + +.. raw:: html + +
| + +2015-03-24 23:59:00+00:00 + +.. raw:: html + + | + +.. raw:: html + ++ +0.504086 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.084215 + +.. raw:: html + + | + +.. raw:: html + ++ +-1.021023 + +.. raw:: html + + | + +.. raw:: html + ++ +0.010523 + +.. raw:: html + + | + +.. raw:: html + ++ +0.655188 + +.. raw:: html + + | + +.. raw:: html + ++ +0.701025 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000000 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +77122.950 + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +100000.0 + +.. raw:: html + + | + +.. raw:: html + ++ +82894.014 + +.. raw:: html + + | + +.. raw:: html + ++ +82894.014 + +.. raw:: html + + | + +.. raw:: html + ++ +24 + +.. raw:: html + + | + +.. raw:: html + ++ +[] + +.. raw:: html + + | + +.. raw:: html + ++ +0.0188 + +.. raw:: html + + | + +.. raw:: html + ++ +490180 + +.. raw:: html + + | + +.. raw:: html + ++ +0.0188 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.084215 + +.. raw:: html + + | + +.. raw:: html + ++ +0.010523 + +.. raw:: html + + | + +.. raw:: html + +
| + +2015-03-25 23:59:00+00:00 + +.. raw:: html + + | + +.. raw:: html + ++ +0.497690 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.068474 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.952786 + +.. raw:: html + + | + +.. raw:: html + ++ +0.031148 + +.. raw:: html + + | + +.. raw:: html + ++ +0.644272 + +.. raw:: html + + | + +.. raw:: html + ++ +0.704251 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000000 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +78697.050 + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +100000.0 + +.. raw:: html + + | + +.. raw:: html + ++ +77122.950 + +.. raw:: html + + | + +.. raw:: html + ++ +77122.950 + +.. raw:: html + + | + +.. raw:: html + ++ +25 + +.. raw:: html + + | + +.. raw:: html + ++ +[] + +.. raw:: html + + | + +.. raw:: html + ++ +0.0193 + +.. raw:: html + + | + +.. raw:: html + ++ +90862 + +.. raw:: html + + | + +.. raw:: html + ++ +0.0193 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.068474 + +.. raw:: html + + | + +.. raw:: html + ++ +0.031148 + +.. raw:: html + + | + +.. raw:: html + +
| + +2015-03-26 23:59:00+00:00 + +.. raw:: html + + | + +.. raw:: html + ++ +0.489730 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.084215 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.943240 + +.. raw:: html + + | + +.. raw:: html + ++ +0.010523 + +.. raw:: html + + | + +.. raw:: html + ++ +0.634965 + +.. raw:: html + + | + +.. raw:: html + ++ +0.703738 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000000 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +77122.950 + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +100000.0 + +.. raw:: html + + | + +.. raw:: html + ++ +78697.050 + +.. raw:: html + + | + +.. raw:: html + ++ +78697.050 + +.. raw:: html + + | + +.. raw:: html + ++ +26 + +.. raw:: html + + | + +.. raw:: html + ++ +[] + +.. raw:: html + + | + +.. raw:: html + ++ +0.0201 + +.. raw:: html + + | + +.. raw:: html + ++ +2299 + +.. raw:: html + + | + +.. raw:: html + ++ +0.0201 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.084215 + +.. raw:: html + + | + +.. raw:: html + ++ +0.010523 + +.. raw:: html + + | + +.. raw:: html + +
| + +2015-03-27 23:59:00+00:00 + +.. raw:: html + + | + +.. raw:: html + ++ +0.495916 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.049785 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.857592 + +.. raw:: html + + | + +.. raw:: html + ++ +0.055636 + +.. raw:: html + + | + +.. raw:: html + ++ +0.636644 + +.. raw:: html + + | + +.. raw:: html + ++ +0.713671 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000000 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +80565.936 + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +100000.0 + +.. raw:: html + + | + +.. raw:: html + ++ +77122.950 + +.. raw:: html + + | + +.. raw:: html + ++ +77122.950 + +.. raw:: html + + | + +.. raw:: html + ++ +27 + +.. raw:: html + + | + +.. raw:: html + ++ +[] + +.. raw:: html + + | + +.. raw:: html + ++ +0.0195 + +.. raw:: html + + | + +.. raw:: html + ++ +663 + +.. raw:: html + + | + +.. raw:: html + ++ +0.0195 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.049785 + +.. raw:: html + + | + +.. raw:: html + ++ +0.055636 + +.. raw:: html + + | + +.. raw:: html + +
| + +2015-03-28 23:59:00+00:00 + +.. raw:: html + + | + +.. raw:: html + ++ +0.488469 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.064490 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.848769 + +.. raw:: html + + | + +.. raw:: html + ++ +0.036368 + +.. raw:: html + + | + +.. raw:: html + ++ +0.627920 + +.. raw:: html + + | + +.. raw:: html + ++ +0.713212 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000000 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +79095.504 + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +100000.0 + +.. raw:: html + + | + +.. raw:: html + ++ +80565.936 + +.. raw:: html + + | + +.. raw:: html + ++ +80565.936 + +.. raw:: html + + | + +.. raw:: html + ++ +28 + +.. raw:: html + + | + +.. raw:: html + ++ +[] + +.. raw:: html + + | + +.. raw:: html + ++ +0.0195 + +.. raw:: html + + | + +.. raw:: html + ++ +7061 + +.. raw:: html + + | + +.. raw:: html + ++ +0.0195 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.064490 + +.. raw:: html + + | + +.. raw:: html + ++ +0.036368 + +.. raw:: html + + | + +.. raw:: html + +
| + +2015-03-29 23:59:00+00:00 + +.. raw:: html + + | + +.. raw:: html + ++ +0.479671 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.066903 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.822844 + +.. raw:: html + + | + +.. raw:: html + ++ +0.033205 + +.. raw:: html + + | + +.. raw:: html + ++ +0.616787 + +.. raw:: html + + | + +.. raw:: html + ++ +0.712868 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000000 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +78854.142 + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +100000.0 + +.. raw:: html + + | + +.. raw:: html + ++ +79095.504 + +.. raw:: html + + | + +.. raw:: html + ++ +79095.504 + +.. raw:: html + + | + +.. raw:: html + ++ +29 + +.. raw:: html + + | + +.. raw:: html + ++ +[] + +.. raw:: html + + | + +.. raw:: html + ++ +0.0195 + +.. raw:: html + + | + +.. raw:: html + ++ +8526 + +.. raw:: html + + | + +.. raw:: html + ++ +0.0195 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.066903 + +.. raw:: html + + | + +.. raw:: html + ++ +0.033205 + +.. raw:: html + + | + +.. raw:: html + +
| + +2015-03-30 23:59:00+00:00 + +.. raw:: html + + | + +.. raw:: html + ++ +0.476306 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.046605 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.769239 + +.. raw:: html + + | + +.. raw:: html + ++ +0.059803 + +.. raw:: html + + | + +.. raw:: html + ++ +0.610002 + +.. raw:: html + + | + +.. raw:: html + ++ +0.716464 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000000 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +80883.936 + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +100000.0 + +.. raw:: html + + | + +.. raw:: html + ++ +78854.142 + +.. raw:: html + + | + +.. raw:: html + ++ +78854.142 + +.. raw:: html + + | + +.. raw:: html + ++ +30 + +.. raw:: html + + | + +.. raw:: html + ++ +[] + +.. raw:: html + + | + +.. raw:: html + ++ +0.0196 + +.. raw:: html + + | + +.. raw:: html + ++ +29654 + +.. raw:: html + + | + +.. raw:: html + ++ +0.0196 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.046605 + +.. raw:: html + + | + +.. raw:: html + ++ +0.059803 + +.. raw:: html + + | + +.. raw:: html + +
| + +… + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + +
| + +2017-05-30 23:59:00+00:00 + +.. raw:: html + + | + +.. raw:: html + ++ +0.495432 + +.. raw:: html + + | + +.. raw:: html + ++ +5.949752 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.016611 + +.. raw:: html + + | + +.. raw:: html + ++ +7.916664 + +.. raw:: html + + | + +.. raw:: html + ++ +0.554369 + +.. raw:: html + + | + +.. raw:: html + ++ +0.888883 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000000 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +680519.682 + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +100000.0 + +.. raw:: html + + | + +.. raw:: html + ++ +701826.000 + +.. raw:: html + + | + +.. raw:: html + ++ +701826.000 + +.. raw:: html + + | + +.. raw:: html + ++ +822 + +.. raw:: html + + | + +.. raw:: html + ++ +[] + +.. raw:: html + + | + +.. raw:: html + ++ +0.0221 + +.. raw:: html + + | + +.. raw:: html + ++ +40157964723 + +.. raw:: html + + | + +.. raw:: html + ++ +0.0221 + +.. raw:: html + + | + +.. raw:: html + ++ +5.949752 + +.. raw:: html + + | + +.. raw:: html + ++ +7.916664 + +.. raw:: html + + | + +.. raw:: html + +
| + +2017-05-31 23:59:00+00:00 + +.. raw:: html + + | + +.. raw:: html + ++ +0.495243 + +.. raw:: html + + | + +.. raw:: html + ++ +6.102328 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.017086 + +.. raw:: html + + | + +.. raw:: html + ++ +8.154164 + +.. raw:: html + + | + +.. raw:: html + ++ +0.554182 + +.. raw:: html + + | + +.. raw:: html + ++ +0.888844 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000000 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +695777.322 + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +100000.0 + +.. raw:: html + + | + +.. raw:: html + ++ +680519.682 + +.. raw:: html + + | + +.. raw:: html + ++ +680519.682 + +.. raw:: html + + | + +.. raw:: html + ++ +823 + +.. raw:: html + + | + +.. raw:: html + ++ +[] + +.. raw:: html + + | + +.. raw:: html + ++ +0.0221 + +.. raw:: html + + | + +.. raw:: html + ++ +31098652109 + +.. raw:: html + + | + +.. raw:: html + ++ +0.0221 + +.. raw:: html + + | + +.. raw:: html + ++ +6.102328 + +.. raw:: html + + | + +.. raw:: html + ++ +8.154164 + +.. raw:: html + + | + +.. raw:: html + +
| + +2017-06-01 23:59:00+00:00 + +.. raw:: html + + | + +.. raw:: html + ++ +0.495836 + +.. raw:: html + + | + +.. raw:: html + ++ +6.504967 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.014668 + +.. raw:: html + + | + +.. raw:: html + ++ +8.644144 + +.. raw:: html + + | + +.. raw:: html + ++ +0.554541 + +.. raw:: html + + | + +.. raw:: html + ++ +0.889303 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000000 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +736041.210 + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +100000.0 + +.. raw:: html + + | + +.. raw:: html + ++ +695777.322 + +.. raw:: html + + | + +.. raw:: html + ++ +695777.322 + +.. raw:: html + + | + +.. raw:: html + ++ +824 + +.. raw:: html + + | + +.. raw:: html + ++ +[] + +.. raw:: html + + | + +.. raw:: html + ++ +0.0221 + +.. raw:: html + + | + +.. raw:: html + ++ +40944880757 + +.. raw:: html + + | + +.. raw:: html + ++ +0.0221 + +.. raw:: html + + | + +.. raw:: html + ++ +6.504967 + +.. raw:: html + + | + +.. raw:: html + ++ +8.644144 + +.. raw:: html + + | + +.. raw:: html + +
| + +2017-06-02 23:59:00+00:00 + +.. raw:: html + + | + +.. raw:: html + ++ +0.495948 + +.. raw:: html + + | + +.. raw:: html + ++ +6.801995 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.013641 + +.. raw:: html + + | + +.. raw:: html + ++ +9.033331 + +.. raw:: html + + | + +.. raw:: html + ++ +0.554581 + +.. raw:: html + + | + +.. raw:: html + ++ +0.889440 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000000 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +765744.000 + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +100000.0 + +.. raw:: html + + | + +.. raw:: html + ++ +736041.210 + +.. raw:: html + + | + +.. raw:: html + ++ +736041.210 + +.. raw:: html + + | + +.. raw:: html + ++ +825 + +.. raw:: html + + | + +.. raw:: html + ++ +[] + +.. raw:: html + + | + +.. raw:: html + ++ +0.0215 + +.. raw:: html + + | + +.. raw:: html + ++ +22364557424 + +.. raw:: html + + | + +.. raw:: html + ++ +0.0215 + +.. raw:: html + + | + +.. raw:: html + ++ +6.801995 + +.. raw:: html + + | + +.. raw:: html + ++ +9.033331 + +.. raw:: html + + | + +.. raw:: html + +
| + +2017-06-03 23:59:00+00:00 + +.. raw:: html + + | + +.. raw:: html + ++ +0.495729 + +.. raw:: html + + | + +.. raw:: html + ++ +6.952409 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.013100 + +.. raw:: html + + | + +.. raw:: html + ++ +9.230418 + +.. raw:: html + + | + +.. raw:: html + ++ +0.554317 + +.. raw:: html + + | + +.. raw:: html + ++ +0.889470 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000000 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +780785.400 + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +100000.0 + +.. raw:: html + + | + +.. raw:: html + ++ +765744.000 + +.. raw:: html + + | + +.. raw:: html + ++ +765744.000 + +.. raw:: html + + | + +.. raw:: html + ++ +826 + +.. raw:: html + + | + +.. raw:: html + ++ +[] + +.. raw:: html + + | + +.. raw:: html + ++ +0.0215 + +.. raw:: html + + | + +.. raw:: html + ++ +23687278961 + +.. raw:: html + + | + +.. raw:: html + ++ +0.0215 + +.. raw:: html + + | + +.. raw:: html + ++ +6.952409 + +.. raw:: html + + | + +.. raw:: html + ++ +9.230418 + +.. raw:: html + + | + +.. raw:: html + +
| + +2017-06-04 23:59:00+00:00 + +.. raw:: html + + | + +.. raw:: html + ++ +0.495450 + +.. raw:: html + + | + +.. raw:: html + ++ +7.042244 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.012768 + +.. raw:: html + + | + +.. raw:: html + ++ +9.348122 + +.. raw:: html + + | + +.. raw:: html + ++ +0.553999 + +.. raw:: html + + | + +.. raw:: html + ++ +0.889479 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000000 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +789768.900 + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +100000.0 + +.. raw:: html + + | + +.. raw:: html + ++ +780785.400 + +.. raw:: html + + | + +.. raw:: html + ++ +780785.400 + +.. raw:: html + + | + +.. raw:: html + ++ +827 + +.. raw:: html + + | + +.. raw:: html + ++ +[] + +.. raw:: html + + | + +.. raw:: html + ++ +0.0215 + +.. raw:: html + + | + +.. raw:: html + ++ +21332021248 + +.. raw:: html + + | + +.. raw:: html + ++ +0.0215 + +.. raw:: html + + | + +.. raw:: html + ++ +7.042244 + +.. raw:: html + + | + +.. raw:: html + ++ +9.348122 + +.. raw:: html + + | + +.. raw:: html + +
| + +2017-06-05 23:59:00+00:00 + +.. raw:: html + + | + +.. raw:: html + ++ +0.496148 + +.. raw:: html + + | + +.. raw:: html + ++ +7.524987 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.011320 + +.. raw:: html + + | + +.. raw:: html + ++ +9.980649 + +.. raw:: html + + | + +.. raw:: html + ++ +0.554578 + +.. raw:: html + + | + +.. raw:: html + ++ +0.889805 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000000 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +838043.208 + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +100000.0 + +.. raw:: html + + | + +.. raw:: html + ++ +789768.900 + +.. raw:: html + + | + +.. raw:: html + ++ +789768.900 + +.. raw:: html + + | + +.. raw:: html + ++ +828 + +.. raw:: html + + | + +.. raw:: html + ++ +[] + +.. raw:: html + + | + +.. raw:: html + ++ +0.0218 + +.. raw:: html + + | + +.. raw:: html + ++ +22372229837 + +.. raw:: html + + | + +.. raw:: html + ++ +0.0218 + +.. raw:: html + + | + +.. raw:: html + ++ +7.524987 + +.. raw:: html + + | + +.. raw:: html + ++ +9.980649 + +.. raw:: html + + | + +.. raw:: html + +
| + +2017-06-06 23:59:00+00:00 + +.. raw:: html + + | + +.. raw:: html + ++ +0.497592 + +.. raw:: html + + | + +.. raw:: html + ++ +8.194835 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.009554 + +.. raw:: html + + | + +.. raw:: html + ++ +10.858330 + +.. raw:: html + + | + +.. raw:: html + ++ +0.555841 + +.. raw:: html + + | + +.. raw:: html + ++ +0.890368 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000000 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +905028.000 + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +100000.0 + +.. raw:: html + + | + +.. raw:: html + ++ +838043.208 + +.. raw:: html + + | + +.. raw:: html + ++ +838043.208 + +.. raw:: html + + | + +.. raw:: html + ++ +829 + +.. raw:: html + + | + +.. raw:: html + ++ +[] + +.. raw:: html + + | + +.. raw:: html + ++ +0.0214 + +.. raw:: html + + | + +.. raw:: html + ++ +81923184446 + +.. raw:: html + + | + +.. raw:: html + ++ +0.0214 + +.. raw:: html + + | + +.. raw:: html + ++ +8.194835 + +.. raw:: html + + | + +.. raw:: html + ++ +10.858330 + +.. raw:: html + + | + +.. raw:: html + +
| + +2017-06-07 23:59:00+00:00 + +.. raw:: html + + | + +.. raw:: html + ++ +0.498895 + +.. raw:: html + + | + +.. raw:: html + ++ +7.557258 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.011975 + +.. raw:: html + + | + +.. raw:: html + ++ +10.022932 + +.. raw:: html + + | + +.. raw:: html + ++ +0.557003 + +.. raw:: html + + | + +.. raw:: html + ++ +0.890845 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000000 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +841270.272 + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +100000.0 + +.. raw:: html + + | + +.. raw:: html + ++ +905028.000 + +.. raw:: html + + | + +.. raw:: html + ++ +905028.000 + +.. raw:: html + + | + +.. raw:: html + ++ +830 + +.. raw:: html + + | + +.. raw:: html + ++ +[] + +.. raw:: html + + | + +.. raw:: html + ++ +0.0218 + +.. raw:: html + + | + +.. raw:: html + ++ +49070430356 + +.. raw:: html + + | + +.. raw:: html + ++ +0.0218 + +.. raw:: html + + | + +.. raw:: html + ++ +7.557258 + +.. raw:: html + + | + +.. raw:: html + ++ +10.022932 + +.. raw:: html + + | + +.. raw:: html + +
| + +2017-06-08 23:59:00+00:00 + +.. raw:: html + + | + +.. raw:: html + ++ +0.499349 + +.. raw:: html + + | + +.. raw:: html + ++ +8.010395 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.010676 + +.. raw:: html + + | + +.. raw:: html + ++ +10.616664 + +.. raw:: html + + | + +.. raw:: html + ++ +0.557357 + +.. raw:: html + + | + +.. raw:: html + ++ +0.891092 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000000 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +886584.000 + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +100000.0 + +.. raw:: html + + | + +.. raw:: html + ++ +841270.272 + +.. raw:: html + + | + +.. raw:: html + ++ +841270.272 + +.. raw:: html + + | + +.. raw:: html + ++ +831 + +.. raw:: html + + | + +.. raw:: html + ++ +[] + +.. raw:: html + + | + +.. raw:: html + ++ +0.0219 + +.. raw:: html + + | + +.. raw:: html + ++ +34013412940 + +.. raw:: html + + | + +.. raw:: html + ++ +0.0219 + +.. raw:: html + + | + +.. raw:: html + ++ +8.010395 + +.. raw:: html + + | + +.. raw:: html + ++ +10.616664 + +.. raw:: html + + | + +.. raw:: html + +
| + +2017-06-09 23:59:00+00:00 + +.. raw:: html + + | + +.. raw:: html + ++ +0.499063 + +.. raw:: html + + | + +.. raw:: html + ++ +8.099750 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.010386 + +.. raw:: html + + | + +.. raw:: html + ++ +10.733746 + +.. raw:: html + + | + +.. raw:: html + ++ +0.557033 + +.. raw:: html + + | + +.. raw:: html + ++ +0.891098 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000000 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +895519.482 + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +100000.0 + +.. raw:: html + + | + +.. raw:: html + ++ +886584.000 + +.. raw:: html + + | + +.. raw:: html + ++ +886584.000 + +.. raw:: html + + | + +.. raw:: html + ++ +832 + +.. raw:: html + + | + +.. raw:: html + ++ +[] + +.. raw:: html + + | + +.. raw:: html + ++ +0.0221 + +.. raw:: html + + | + +.. raw:: html + ++ +25275425996 + +.. raw:: html + + | + +.. raw:: html + ++ +0.0221 + +.. raw:: html + + | + +.. raw:: html + ++ +8.099750 + +.. raw:: html + + | + +.. raw:: html + ++ +10.733746 + +.. raw:: html + + | + +.. raw:: html + +
| + +2017-06-10 23:59:00+00:00 + +.. raw:: html + + | + +.. raw:: html + ++ +0.498769 + +.. raw:: html + + | + +.. raw:: html + ++ +8.086143 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.010416 + +.. raw:: html + + | + +.. raw:: html + ++ +10.715915 + +.. raw:: html + + | + +.. raw:: html + ++ +0.556705 + +.. raw:: html + + | + +.. raw:: html + ++ +0.891098 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000000 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +894158.760 + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +100000.0 + +.. raw:: html + + | + +.. raw:: html + ++ +895519.482 + +.. raw:: html + + | + +.. raw:: html + ++ +895519.482 + +.. raw:: html + + | + +.. raw:: html + ++ +833 + +.. raw:: html + + | + +.. raw:: html + ++ +[] + +.. raw:: html + + | + +.. raw:: html + ++ +0.0221 + +.. raw:: html + + | + +.. raw:: html + ++ +30620792046 + +.. raw:: html + + | + +.. raw:: html + ++ +0.0221 + +.. raw:: html + + | + +.. raw:: html + ++ +8.086143 + +.. raw:: html + + | + +.. raw:: html + ++ +10.715915 + +.. raw:: html + + | + +.. raw:: html + +
| + +2017-06-11 23:59:00+00:00 + +.. raw:: html + + | + +.. raw:: html + ++ +0.498971 + +.. raw:: html + + | + +.. raw:: html + ++ +8.484533 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.009305 + +.. raw:: html + + | + +.. raw:: html + ++ +11.237914 + +.. raw:: html + + | + +.. raw:: html + ++ +0.556827 + +.. raw:: html + + | + +.. raw:: html + ++ +0.891266 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000000 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +933997.800 + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +100000.0 + +.. raw:: html + + | + +.. raw:: html + ++ +894158.760 + +.. raw:: html + + | + +.. raw:: html + ++ +894158.760 + +.. raw:: html + + | + +.. raw:: html + ++ +834 + +.. raw:: html + + | + +.. raw:: html + ++ +[] + +.. raw:: html + + | + +.. raw:: html + ++ +0.0221 + +.. raw:: html + + | + +.. raw:: html + ++ +30830678595 + +.. raw:: html + + | + +.. raw:: html + ++ +0.0221 + +.. raw:: html + + | + +.. raw:: html + ++ +8.484533 + +.. raw:: html + + | + +.. raw:: html + ++ +11.237914 + +.. raw:: html + + | + +.. raw:: html + +
| + +2017-06-12 23:59:00+00:00 + +.. raw:: html + + | + +.. raw:: html + ++ +0.503448 + +.. raw:: html + + | + +.. raw:: html + ++ +7.320494 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.014065 + +.. raw:: html + + | + +.. raw:: html + ++ +9.712706 + +.. raw:: html + + | + +.. raw:: html + ++ +0.560936 + +.. raw:: html + + | + +.. raw:: html + ++ +0.892695 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000000 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +817593.900 + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +100000.0 + +.. raw:: html + + | + +.. raw:: html + ++ +933997.800 + +.. raw:: html + + | + +.. raw:: html + ++ +933997.800 + +.. raw:: html + + | + +.. raw:: html + ++ +835 + +.. raw:: html + + | + +.. raw:: html + ++ +[] + +.. raw:: html + + | + +.. raw:: html + ++ +0.0221 + +.. raw:: html + + | + +.. raw:: html + ++ +88704710635 + +.. raw:: html + + | + +.. raw:: html + ++ +0.0221 + +.. raw:: html + + | + +.. raw:: html + ++ +7.320494 + +.. raw:: html + + | + +.. raw:: html + ++ +9.712706 + +.. raw:: html + + | + +.. raw:: html + +
| + +2017-06-13 23:59:00+00:00 + +.. raw:: html + + | + +.. raw:: html + ++ +0.503565 + +.. raw:: html + + | + +.. raw:: html + ++ +7.656697 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.013054 + +.. raw:: html + + | + +.. raw:: html + ++ +10.153225 + +.. raw:: html + + | + +.. raw:: html + ++ +0.560981 + +.. raw:: html + + | + +.. raw:: html + ++ +0.892830 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000000 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +851214.132 + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +100000.0 + +.. raw:: html + + | + +.. raw:: html + ++ +817593.900 + +.. raw:: html + + | + +.. raw:: html + ++ +817593.900 + +.. raw:: html + + | + +.. raw:: html + ++ +836 + +.. raw:: html + + | + +.. raw:: html + ++ +[] + +.. raw:: html + + | + +.. raw:: html + ++ +0.0221 + +.. raw:: html + + | + +.. raw:: html + ++ +42251296767 + +.. raw:: html + + | + +.. raw:: html + ++ +0.0221 + +.. raw:: html + + | + +.. raw:: html + ++ +7.656697 + +.. raw:: html + + | + +.. raw:: html + ++ +10.153225 + +.. raw:: html + + | + +.. raw:: html + +
| + +2017-06-14 23:59:00+00:00 + +.. raw:: html + + | + +.. raw:: html + ++ +0.506845 + +.. raw:: html + + | + +.. raw:: html + ++ +6.734516 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.016873 + +.. raw:: html + + | + +.. raw:: html + ++ +8.944917 + +.. raw:: html + + | + +.. raw:: html + ++ +0.563995 + +.. raw:: html + + | + +.. raw:: html + ++ +0.893862 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000000 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +758996.040 + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +100000.0 + +.. raw:: html + + | + +.. raw:: html + ++ +851214.132 + +.. raw:: html + + | + +.. raw:: html + ++ +851214.132 + +.. raw:: html + + | + +.. raw:: html + ++ +837 + +.. raw:: html + + | + +.. raw:: html + ++ +[] + +.. raw:: html + + | + +.. raw:: html + ++ +0.0215 + +.. raw:: html + + | + +.. raw:: html + ++ +63183088135 + +.. raw:: html + + | + +.. raw:: html + ++ +0.0215 + +.. raw:: html + + | + +.. raw:: html + ++ +6.734516 + +.. raw:: html + + | + +.. raw:: html + ++ +8.944917 + +.. raw:: html + + | + +.. raw:: html + +
| + +2017-06-15 23:59:00+00:00 + +.. raw:: html + + | + +.. raw:: html + ++ +0.506562 + +.. raw:: html + + | + +.. raw:: html + ++ +6.695367 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.016991 + +.. raw:: html + + | + +.. raw:: html + ++ +8.893622 + +.. raw:: html + + | + +.. raw:: html + ++ +0.563678 + +.. raw:: html + + | + +.. raw:: html + ++ +0.893865 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000000 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +755081.142 + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +100000.0 + +.. raw:: html + + | + +.. raw:: html + ++ +758996.040 + +.. raw:: html + + | + +.. raw:: html + ++ +758996.040 + +.. raw:: html + + | + +.. raw:: html + ++ +838 + +.. raw:: html + + | + +.. raw:: html + ++ +[] + +.. raw:: html + + | + +.. raw:: html + ++ +0.0216 + +.. raw:: html + + | + +.. raw:: html + ++ +104677533974 + +.. raw:: html + + | + +.. raw:: html + ++ +0.0216 + +.. raw:: html + + | + +.. raw:: html + ++ +6.695367 + +.. raw:: html + + | + +.. raw:: html + ++ +8.893622 + +.. raw:: html + + | + +.. raw:: html + +
| + +2017-06-16 23:59:00+00:00 + +.. raw:: html + + | + +.. raw:: html + ++ +0.506404 + +.. raw:: html + + | + +.. raw:: html + ++ +6.887855 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.016343 + +.. raw:: html + + | + +.. raw:: html + ++ +9.145831 + +.. raw:: html + + | + +.. raw:: html + ++ +0.563472 + +.. raw:: html + + | + +.. raw:: html + ++ +0.893913 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000000 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +774330.000 + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +100000.0 + +.. raw:: html + + | + +.. raw:: html + ++ +755081.142 + +.. raw:: html + + | + +.. raw:: html + ++ +755081.142 + +.. raw:: html + + | + +.. raw:: html + ++ +839 + +.. raw:: html + + | + +.. raw:: html + ++ +[] + +.. raw:: html + + | + +.. raw:: html + ++ +0.0216 + +.. raw:: html + + | + +.. raw:: html + ++ +43479966625 + +.. raw:: html + + | + +.. raw:: html + ++ +0.0216 + +.. raw:: html + + | + +.. raw:: html + ++ +6.887855 + +.. raw:: html + + | + +.. raw:: html + ++ +9.145831 + +.. raw:: html + + | + +.. raw:: html + +
| + +2017-06-17 23:59:00+00:00 + +.. raw:: html + + | + +.. raw:: html + ++ +0.507407 + +.. raw:: html + + | + +.. raw:: html + ++ +7.435283 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.014812 + +.. raw:: html + + | + +.. raw:: html + ++ +9.863113 + +.. raw:: html + + | + +.. raw:: html + ++ +0.564341 + +.. raw:: html + + | + +.. raw:: html + ++ +0.894311 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000000 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +829072.746 + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +100000.0 + +.. raw:: html + + | + +.. raw:: html + ++ +774330.000 + +.. raw:: html + + | + +.. raw:: html + ++ +774330.000 + +.. raw:: html + + | + +.. raw:: html + ++ +840 + +.. raw:: html + + | + +.. raw:: html + ++ +[] + +.. raw:: html + + | + +.. raw:: html + ++ +0.0216 + +.. raw:: html + + | + +.. raw:: html + ++ +36800919715 + +.. raw:: html + + | + +.. raw:: html + ++ +0.0216 + +.. raw:: html + + | + +.. raw:: html + ++ +7.435283 + +.. raw:: html + + | + +.. raw:: html + ++ +9.863113 + +.. raw:: html + + | + +.. raw:: html + +
| + +2017-06-18 23:59:00+00:00 + +.. raw:: html + + | + +.. raw:: html + ++ +0.507740 + +.. raw:: html + + | + +.. raw:: html + ++ +7.070069 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.016112 + +.. raw:: html + + | + +.. raw:: html + ++ +9.384581 + +.. raw:: html + + | + +.. raw:: html + ++ +0.564605 + +.. raw:: html + + | + +.. raw:: html + ++ +0.894482 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000000 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +792551.400 + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +100000.0 + +.. raw:: html + + | + +.. raw:: html + ++ +829072.746 + +.. raw:: html + + | + +.. raw:: html + ++ +829072.746 + +.. raw:: html + + | + +.. raw:: html + ++ +841 + +.. raw:: html + + | + +.. raw:: html + ++ +[] + +.. raw:: html + + | + +.. raw:: html + ++ +0.0216 + +.. raw:: html + + | + +.. raw:: html + ++ +46411759478 + +.. raw:: html + + | + +.. raw:: html + ++ +0.0216 + +.. raw:: html + + | + +.. raw:: html + ++ +7.070069 + +.. raw:: html + + | + +.. raw:: html + ++ +9.384581 + +.. raw:: html + + | + +.. raw:: html + +
| + +2017-06-19 23:59:00+00:00 + +.. raw:: html + + | + +.. raw:: html + ++ +0.507754 + +.. raw:: html + + | + +.. raw:: html + ++ +7.358645 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.015226 + +.. raw:: html + + | + +.. raw:: html + ++ +9.762694 + +.. raw:: html + + | + +.. raw:: html + ++ +0.564557 + +.. raw:: html + + | + +.. raw:: html + ++ +0.894583 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000000 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +821408.946 + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +100000.0 + +.. raw:: html + + | + +.. raw:: html + ++ +792551.400 + +.. raw:: html + + | + +.. raw:: html + ++ +792551.400 + +.. raw:: html + + | + +.. raw:: html + ++ +842 + +.. raw:: html + + | + +.. raw:: html + ++ +[] + +.. raw:: html + + | + +.. raw:: html + ++ +0.0219 + +.. raw:: html + + | + +.. raw:: html + ++ +28294406623 + +.. raw:: html + + | + +.. raw:: html + ++ +0.0219 + +.. raw:: html + + | + +.. raw:: html + ++ +7.358645 + +.. raw:: html + + | + +.. raw:: html + ++ +9.762694 + +.. raw:: html + + | + +.. raw:: html + +
| + +2017-06-20 23:59:00+00:00 + +.. raw:: html + + | + +.. raw:: html + ++ +0.507705 + +.. raw:: html + + | + +.. raw:: html + ++ +7.628795 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.014414 + +.. raw:: html + + | + +.. raw:: html + ++ +10.116664 + +.. raw:: html + + | + +.. raw:: html + ++ +0.564451 + +.. raw:: html + + | + +.. raw:: html + ++ +0.894665 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000000 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +848424.000 + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +100000.0 + +.. raw:: html + + | + +.. raw:: html + ++ +821408.946 + +.. raw:: html + + | + +.. raw:: html + ++ +821408.946 + +.. raw:: html + + | + +.. raw:: html + ++ +843 + +.. raw:: html + + | + +.. raw:: html + ++ +[] + +.. raw:: html + + | + +.. raw:: html + ++ +0.0216 + +.. raw:: html + + | + +.. raw:: html + ++ +36903854052 + +.. raw:: html + + | + +.. raw:: html + ++ +0.0216 + +.. raw:: html + + | + +.. raw:: html + ++ +7.628795 + +.. raw:: html + + | + +.. raw:: html + ++ +10.116664 + +.. raw:: html + + | + +.. raw:: html + +
| + +2017-06-21 23:59:00+00:00 + +.. raw:: html + + | + +.. raw:: html + ++ +0.507531 + +.. raw:: html + + | + +.. raw:: html + ++ +7.476155 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.014900 + +.. raw:: html + + | + +.. raw:: html + ++ +9.916664 + +.. raw:: html + + | + +.. raw:: html + ++ +0.564238 + +.. raw:: html + + | + +.. raw:: html + ++ +0.894696 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000000 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +833160.000 + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +100000.0 + +.. raw:: html + + | + +.. raw:: html + ++ +848424.000 + +.. raw:: html + + | + +.. raw:: html + ++ +848424.000 + +.. raw:: html + + | + +.. raw:: html + ++ +844 + +.. raw:: html + + | + +.. raw:: html + ++ +[] + +.. raw:: html + + | + +.. raw:: html + ++ +0.0216 + +.. raw:: html + + | + +.. raw:: html + ++ +43815656010 + +.. raw:: html + + | + +.. raw:: html + ++ +0.0216 + +.. raw:: html + + | + +.. raw:: html + ++ +7.476155 + +.. raw:: html + + | + +.. raw:: html + ++ +9.916664 + +.. raw:: html + + | + +.. raw:: html + +
| + +2017-06-22 23:59:00+00:00 + +.. raw:: html + + | + +.. raw:: html + ++ +0.507315 + +.. raw:: html + + | + +.. raw:: html + ++ +7.645891 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.014372 + +.. raw:: html + + | + +.. raw:: html + ++ +10.139065 + +.. raw:: html + + | + +.. raw:: html + ++ +0.563979 + +.. raw:: html + + | + +.. raw:: html + ++ +0.894725 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000000 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +850133.568 + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +100000.0 + +.. raw:: html + + | + +.. raw:: html + ++ +833160.000 + +.. raw:: html + + | + +.. raw:: html + ++ +833160.000 + +.. raw:: html + + | + +.. raw:: html + ++ +845 + +.. raw:: html + + | + +.. raw:: html + ++ +[] + +.. raw:: html + + | + +.. raw:: html + ++ +0.0215 + +.. raw:: html + + | + +.. raw:: html + ++ +22304647568 + +.. raw:: html + + | + +.. raw:: html + ++ +0.0215 + +.. raw:: html + + | + +.. raw:: html + ++ +7.645891 + +.. raw:: html + + | + +.. raw:: html + ++ +10.139065 + +.. raw:: html + + | + +.. raw:: html + +
| + +2017-06-23 23:59:00+00:00 + +.. raw:: html + + | + +.. raw:: html + ++ +0.507020 + +.. raw:: html + + | + +.. raw:: html + ++ +7.635155 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.014388 + +.. raw:: html + + | + +.. raw:: html + ++ +10.124997 + +.. raw:: html + + | + +.. raw:: html + ++ +0.563652 + +.. raw:: html + + | + +.. raw:: html + ++ +0.894725 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000000 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +849060.000 + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +100000.0 + +.. raw:: html + + | + +.. raw:: html + ++ +850133.568 + +.. raw:: html + + | + +.. raw:: html + ++ +850133.568 + +.. raw:: html + + | + +.. raw:: html + ++ +846 + +.. raw:: html + + | + +.. raw:: html + ++ +[] + +.. raw:: html + + | + +.. raw:: html + ++ +0.0215 + +.. raw:: html + + | + +.. raw:: html + ++ +13090231864 + +.. raw:: html + + | + +.. raw:: html + ++ +0.0215 + +.. raw:: html + + | + +.. raw:: html + ++ +7.635155 + +.. raw:: html + + | + +.. raw:: html + ++ +10.124997 + +.. raw:: html + + | + +.. raw:: html + +
| + +2017-06-24 23:59:00+00:00 + +.. raw:: html + + | + +.. raw:: html + ++ +0.507936 + +.. raw:: html + + | + +.. raw:: html + ++ +7.105628 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.016304 + +.. raw:: html + + | + +.. raw:: html + ++ +9.431173 + +.. raw:: html + + | + +.. raw:: html + ++ +0.564463 + +.. raw:: html + + | + +.. raw:: html + ++ +0.895061 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000000 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +796107.276 + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +100000.0 + +.. raw:: html + + | + +.. raw:: html + ++ +849060.000 + +.. raw:: html + + | + +.. raw:: html + ++ +849060.000 + +.. raw:: html + + | + +.. raw:: html + ++ +847 + +.. raw:: html + + | + +.. raw:: html + ++ +[] + +.. raw:: html + + | + +.. raw:: html + ++ +0.0215 + +.. raw:: html + + | + +.. raw:: html + ++ +34088563732 + +.. raw:: html + + | + +.. raw:: html + ++ +0.0215 + +.. raw:: html + + | + +.. raw:: html + ++ +7.105628 + +.. raw:: html + + | + +.. raw:: html + ++ +9.431173 + +.. raw:: html + + | + +.. raw:: html + +
| + +2017-06-25 23:59:00+00:00 + +.. raw:: html + + | + +.. raw:: html + ++ +0.507675 + +.. raw:: html + + | + +.. raw:: html + ++ +7.036714 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.016515 + +.. raw:: html + + | + +.. raw:: html + ++ +9.340880 + +.. raw:: html + + | + +.. raw:: html + ++ +0.564168 + +.. raw:: html + + | + +.. raw:: html + ++ +0.895069 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000000 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +789215.898 + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +100000.0 + +.. raw:: html + + | + +.. raw:: html + ++ +796107.276 + +.. raw:: html + + | + +.. raw:: html + ++ +796107.276 + +.. raw:: html + + | + +.. raw:: html + ++ +848 + +.. raw:: html + + | + +.. raw:: html + ++ +[] + +.. raw:: html + + | + +.. raw:: html + ++ +0.0215 + +.. raw:: html + + | + +.. raw:: html + ++ +41560204433 + +.. raw:: html + + | + +.. raw:: html + ++ +0.0215 + +.. raw:: html + + | + +.. raw:: html + ++ +7.036714 + +.. raw:: html + + | + +.. raw:: html + ++ +9.340880 + +.. raw:: html + + | + +.. raw:: html + +
| + +2017-06-26 23:59:00+00:00 + +.. raw:: html + + | + +.. raw:: html + ++ +0.507780 + +.. raw:: html + + | + +.. raw:: html + ++ +6.761571 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.017485 + +.. raw:: html + + | + +.. raw:: html + ++ +8.980368 + +.. raw:: html + + | + +.. raw:: html + ++ +0.564221 + +.. raw:: html + + | + +.. raw:: html + ++ +0.895175 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000000 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +761701.584 + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +100000.0 + +.. raw:: html + + | + +.. raw:: html + ++ +789215.898 + +.. raw:: html + + | + +.. raw:: html + ++ +789215.898 + +.. raw:: html + + | + +.. raw:: html + ++ +849 + +.. raw:: html + + | + +.. raw:: html + ++ +[] + +.. raw:: html + + | + +.. raw:: html + ++ +0.0214 + +.. raw:: html + + | + +.. raw:: html + ++ +73840480752 + +.. raw:: html + + | + +.. raw:: html + ++ +0.0214 + +.. raw:: html + + | + +.. raw:: html + ++ +6.761571 + +.. raw:: html + + | + +.. raw:: html + ++ +8.980368 + +.. raw:: html + + | + +.. raw:: html + +
| + +2017-06-27 23:59:00+00:00 + +.. raw:: html + + | + +.. raw:: html + ++ +0.508048 + +.. raw:: html + + | + +.. raw:: html + ++ +7.126355 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.016390 + +.. raw:: html + + | + +.. raw:: html + ++ +9.458331 + +.. raw:: html + + | + +.. raw:: html + ++ +0.564409 + +.. raw:: html + + | + +.. raw:: html + ++ +0.895349 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000000 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +798180.000 + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +100000.0 + +.. raw:: html + + | + +.. raw:: html + ++ +761701.584 + +.. raw:: html + + | + +.. raw:: html + ++ +761701.584 + +.. raw:: html + + | + +.. raw:: html + ++ +850 + +.. raw:: html + + | + +.. raw:: html + ++ +[] + +.. raw:: html + + | + +.. raw:: html + ++ +0.0221 + +.. raw:: html + + | + +.. raw:: html + ++ +62426319778 + +.. raw:: html + + | + +.. raw:: html + ++ +0.0221 + +.. raw:: html + + | + +.. raw:: html + ++ +7.126355 + +.. raw:: html + + | + +.. raw:: html + ++ +9.458331 + +.. raw:: html + + | + +.. raw:: html + +
| + +2017-06-28 23:59:00+00:00 + +.. raw:: html + + | + +.. raw:: html + ++ +0.507750 + +.. raw:: html + + | + +.. raw:: html + ++ +7.135895 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.016340 + +.. raw:: html + + | + +.. raw:: html + ++ +9.470831 + +.. raw:: html + + | + +.. raw:: html + ++ +0.564078 + +.. raw:: html + + | + +.. raw:: html + ++ +0.895349 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000000 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +799134.000 + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +100000.0 + +.. raw:: html + + | + +.. raw:: html + ++ +798180.000 + +.. raw:: html + + | + +.. raw:: html + ++ +798180.000 + +.. raw:: html + + | + +.. raw:: html + ++ +851 + +.. raw:: html + + | + +.. raw:: html + ++ +[] + +.. raw:: html + + | + +.. raw:: html + ++ +0.0222 + +.. raw:: html + + | + +.. raw:: html + ++ +39676839183 + +.. raw:: html + + | + +.. raw:: html + ++ +0.0222 + +.. raw:: html + + | + +.. raw:: html + ++ +7.135895 + +.. raw:: html + + | + +.. raw:: html + ++ +9.470831 + +.. raw:: html + + | + +.. raw:: html + +
+ +851 rows × 45 columns + +.. raw:: html + +
+ +.. raw:: html + +| + +.. raw:: html + + | + +.. raw:: html + ++ +algo_volatility + +.. raw:: html + + | + +.. raw:: html + ++ +algorithm_period_return + +.. raw:: html + + | + +.. raw:: html + ++ +alpha + +.. raw:: html + + | + +.. raw:: html + ++ +benchmark_period_return + +.. raw:: html + + | + +.. raw:: html + ++ +benchmark_volatility + +.. raw:: html + + | + +.. raw:: html + ++ +beta + +.. raw:: html + + | + +.. raw:: html + ++ +capital_used + +.. raw:: html + + | + +.. raw:: html + ++ +cash + +.. raw:: html + + | + +.. raw:: html + ++ +ending_cash + +.. raw:: html + + | + +.. raw:: html + ++ +ending_exposure + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +starting_cash + +.. raw:: html + + | + +.. raw:: html + ++ +starting_exposure + +.. raw:: html + + | + +.. raw:: html + ++ +starting_value + +.. raw:: html + + | + +.. raw:: html + ++ +trading_days + +.. raw:: html + + | + +.. raw:: html + ++ +transactions + +.. raw:: html + + | + +.. raw:: html + ++ +treasury_period_return + +.. raw:: html + + | + +.. raw:: html + ++ +volume + +.. raw:: html + + | + +.. raw:: html + ++ +treasury + +.. raw:: html + + | + +.. raw:: html + ++ +algorithm + +.. raw:: html + + | + +.. raw:: html + ++ +benchmark + +.. raw:: html + + | + +.. raw:: html + +
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| + +2015-03-01 23:59:00+00:00 + +.. raw:: html + + | + +.. raw:: html + ++ +NaN + +.. raw:: html + + | + +.. raw:: html + ++ +0.000000 + +.. raw:: html + + | + +.. raw:: html + ++ +NaN + +.. raw:: html + + | + +.. raw:: html + ++ +0.045833 + +.. raw:: html + + | + +.. raw:: html + ++ +NaN + +.. raw:: html + + | + +.. raw:: html + ++ +NaN + +.. raw:: html + + | + +.. raw:: html + ++ +0.000000 + +.. raw:: html + + | + +.. raw:: html + ++ +100000.000000 + +.. raw:: html + + | + +.. raw:: html + ++ +100000.000000 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000 + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +100000.0 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000 + +.. raw:: html + + | + +.. raw:: html + ++ +1 + +.. raw:: html + + | + +.. raw:: html + ++ +[] + +.. raw:: html + + | + +.. raw:: html + ++ +0.0200 + +.. raw:: html + + | + +.. raw:: html + ++ +317 + +.. raw:: html + + | + +.. raw:: html + ++ +0.0200 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000000 + +.. raw:: html + + | + +.. raw:: html + ++ +0.045833 + +.. raw:: html + + | + +.. raw:: html + +
| + +2015-03-02 23:59:00+00:00 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000278 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.000025 + +.. raw:: html + + | + +.. raw:: html + ++ +0.011045 + +.. raw:: html + + | + +.. raw:: html + ++ +0.120833 + +.. raw:: html + + | + +.. raw:: html + ++ +0.290503 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.000956 + +.. raw:: html + + | + +.. raw:: html + ++ +-85544.474955 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +85542.000 + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +100000.0 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000 + +.. raw:: html + + | + +.. raw:: html + ++ +2 + +.. raw:: html + + | + +.. raw:: html + ++ +[{u’commission’: None, u’amount’: 318, u’sid’:… + +.. raw:: html + + | + +.. raw:: html + ++ +0.0208 + +.. raw:: html + + | + +.. raw:: html + ++ +98063 + +.. raw:: html + + | + +.. raw:: html + ++ +0.0208 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.000025 + +.. raw:: html + + | + +.. raw:: html + ++ +0.120833 + +.. raw:: html + + | + +.. raw:: html + +
| + +2015-03-03 23:59:00+00:00 + +.. raw:: html + + | + +.. raw:: html + ++ +0.051796 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.005688 + +.. raw:: html + + | + +.. raw:: html + ++ +-1.197544 + +.. raw:: html + + | + +.. raw:: html + ++ +0.113416 + +.. raw:: html + + | + +.. raw:: html + ++ +0.633538 + +.. raw:: html + + | + +.. raw:: html + ++ +0.077239 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000000 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +84975.642 + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +100000.0 + +.. raw:: html + + | + +.. raw:: html + ++ +85542.000 + +.. raw:: html + + | + +.. raw:: html + ++ +85542.000 + +.. raw:: html + + | + +.. raw:: html + ++ +3 + +.. raw:: html + + | + +.. raw:: html + ++ +[] + +.. raw:: html + + | + +.. raw:: html + ++ +0.0212 + +.. raw:: html + + | + +.. raw:: html + ++ +442983 + +.. raw:: html + + | + +.. raw:: html + ++ +0.0212 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.005688 + +.. raw:: html + + | + +.. raw:: html + ++ +0.113416 + +.. raw:: html + + | + +.. raw:: html + +
| + +2015-03-04 23:59:00+00:00 + +.. raw:: html + + | + +.. raw:: html + ++ +0.342118 + +.. raw:: html + + | + +.. raw:: html + ++ +0.034955 + +.. raw:: html + + | + +.. raw:: html + ++ +0.401861 + +.. raw:: html + + | + +.. raw:: html + ++ +0.166666 + +.. raw:: html + + | + +.. raw:: html + ++ +0.524400 + +.. raw:: html + + | + +.. raw:: html + ++ +0.181468 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000000 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +89040.000 + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +100000.0 + +.. raw:: html + + | + +.. raw:: html + ++ +84975.642 + +.. raw:: html + + | + +.. raw:: html + ++ +84975.642 + +.. raw:: html + + | + +.. raw:: html + ++ +4 + +.. raw:: html + + | + +.. raw:: html + ++ +[] + +.. raw:: html + + | + +.. raw:: html + ++ +0.0212 + +.. raw:: html + + | + +.. raw:: html + ++ +245889 + +.. raw:: html + + | + +.. raw:: html + ++ +0.0212 + +.. raw:: html + + | + +.. raw:: html + ++ +0.034955 + +.. raw:: html + + | + +.. raw:: html + ++ +0.166666 + +.. raw:: html + + | + +.. raw:: html + +
| + +2015-03-05 23:59:00+00:00 + +.. raw:: html + + | + +.. raw:: html + ++ +0.637226 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.038185 + +.. raw:: html + + | + +.. raw:: html + ++ +-3.914003 + +.. raw:: html + + | + +.. raw:: html + ++ +0.070834 + +.. raw:: html + + | + +.. raw:: html + ++ +0.976896 + +.. raw:: html + + | + +.. raw:: html + ++ +0.550520 + +.. raw:: html + + | + +.. raw:: html + ++ +0.000000 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +14455.525045 + +.. raw:: html + + | + +.. raw:: html + ++ +81726.000 + +.. raw:: html + + | + +.. raw:: html + ++ +… + +.. raw:: html + + | + +.. raw:: html + ++ +100000.0 + +.. raw:: html + + | + +.. raw:: html + ++ +89040.000 + +.. raw:: html + + | + +.. raw:: html + ++ +89040.000 + +.. raw:: html + + | + +.. raw:: html + ++ +5 + +.. raw:: html + + | + +.. raw:: html + ++ +[] + +.. raw:: html + + | + +.. raw:: html + ++ +0.0211 + +.. raw:: html + + | + +.. raw:: html + ++ +117440 + +.. raw:: html + + | + +.. raw:: html + ++ +0.0211 + +.. raw:: html + + | + +.. raw:: html + ++ +-0.038185 + +.. raw:: html + + | + +.. raw:: html + ++ +0.070834 + +.. raw:: html + + | + +.. raw:: html + +
+ +5 rows × 45 columns + +.. raw:: html + +
+ +.. raw:: html + +