Пример #1
0
 def setup(self):
     print ('creating poloniex object')
     auth = get_exchange_auth('poloniex')
     self.exchange = Poloniex(
         key=auth['key'],
         secret=auth['secret'],
         base_currency='btc'
     )
Пример #2
0
def get_exchange(exchange_name):
    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
            portfolio=None
        )
    elif exchange_name == 'bittrex':
        return Bittrex(
            key=exchange_auth['key'],
            secret=exchange_auth['secret'],
            base_currency=None,
            portfolio=None
        )
    elif exchange_name == 'poloniex':
        return Poloniex(
            key=exchange_auth['key'],
            secret=exchange_auth['secret'],
            base_currency=None,
            portfolio=None
        )
    else:
        raise ExchangeNotFoundError(exchange_name=exchange_name)
Пример #3
0
def _run(handle_data, initialize, before_trading_start, analyze, algofile,
         algotext, defines, data_frequency, capital_base, data, bundle,
         bundle_timestamp, start, end, output, print_algo, local_namespace,
         environ, live, exchange, algo_namespace, base_currency, live_graph):
    """Run a backtest for the given algorithm.

    This is shared between the cli and :func:`catalyst.run_algo`.
    """
    if algotext is not None:
        if local_namespace:
            ip = get_ipython()  # noqa
            namespace = ip.user_ns
        else:
            namespace = {}

        for assign in defines:
            try:
                name, value = assign.split('=', 2)
            except ValueError:
                raise ValueError(
                    'invalid define %r, should be of the form name=value' %
                    assign, )
            try:
                # evaluate in the same namespace so names may refer to
                # eachother
                namespace[name] = eval(value, namespace)
            except Exception as e:
                raise ValueError(
                    'failed to execute definition for name %r: %s' %
                    (name, e), )
    elif defines:
        raise _RunAlgoError(
            'cannot pass define without `algotext`',
            "cannot pass '-D' / '--define' without '-t' / '--algotext'",
        )
    else:
        namespace = {}
        if algofile is not None:
            algotext = algofile.read()

    if print_algo:
        if PYGMENTS:
            highlight(
                algotext,
                PythonLexer(),
                TerminalFormatter(),
                outfile=sys.stdout,
            )
        else:
            click.echo(algotext)

    mode = 'live' if live else 'backtest'
    log.info('running algo in {mode} mode'.format(mode=mode))

    exchange_name = exchange
    if exchange_name is None:
        raise ValueError('Please specify at least one exchange.')

    exchange_list = [x.strip().lower() for x in exchange.split(',')]

    exchanges = dict()
    for exchange_name in exchange_list:

        # Looking for the portfolio from the cache first
        portfolio = get_algo_object(algo_name=algo_namespace,
                                    key='portfolio_{}'.format(exchange_name),
                                    environ=environ)

        if portfolio is None:
            portfolio = ExchangePortfolio(start_date=pd.Timestamp.utcnow())

        # This corresponds to the json file containing api token info
        exchange_auth = get_exchange_auth(exchange_name)

        if live and (exchange_auth['key'] == ''
                     or exchange_auth['secret'] == ''):
            raise ExchangeAuthEmpty(exchange=exchange_name.title(),
                                    filename=os.path.join(
                                        get_exchange_folder(
                                            exchange_name, environ),
                                        'auth.json'))

        if exchange_name == 'bitfinex':
            exchanges[exchange_name] = Bitfinex(key=exchange_auth['key'],
                                                secret=exchange_auth['secret'],
                                                base_currency=base_currency,
                                                portfolio=portfolio)
        elif exchange_name == 'bittrex':
            exchanges[exchange_name] = Bittrex(key=exchange_auth['key'],
                                               secret=exchange_auth['secret'],
                                               base_currency=base_currency,
                                               portfolio=portfolio)
        elif exchange_name == 'poloniex':
            exchanges[exchange_name] = Poloniex(key=exchange_auth['key'],
                                                secret=exchange_auth['secret'],
                                                base_currency=base_currency,
                                                portfolio=portfolio)
        else:
            raise ExchangeNotFoundError(exchange_name=exchange_name)

    open_calendar = get_calendar('OPEN')

    env = TradingEnvironment(
        load=partial(load_crypto_market_data,
                     environ=environ,
                     start_dt=start,
                     end_dt=end),
        environ=environ,
        exchange_tz='UTC',
        asset_db_path=None  # We don't need an asset db, we have exchanges
    )
    env.asset_finder = AssetFinderExchange()
    choose_loader = None  # TODO: use the DataPortal for in the algorithm class for this

    if live:
        start = pd.Timestamp.utcnow()

        # TODO: fix the end data.
        end = start + timedelta(hours=8760)

        data = DataPortalExchangeLive(exchanges=exchanges,
                                      asset_finder=env.asset_finder,
                                      trading_calendar=open_calendar,
                                      first_trading_day=pd.to_datetime(
                                          'today', utc=True))

        def fetch_capital_base(exchange, attempt_index=0):
            """
            Fetch the base currency amount required to bootstrap
            the algorithm against the exchange.

            The algorithm cannot continue without this value.

            :param exchange: the targeted exchange
            :param attempt_index:
            :return capital_base: the amount of base currency available for
            trading
            """
            try:
                log.debug('retrieving capital base in {} to bootstrap '
                          'exchange {}'.format(base_currency, exchange_name))
                balances = exchange.get_balances()
            except ExchangeRequestError as e:
                if attempt_index < 20:
                    log.warn('could not retrieve balances on {}: {}'.format(
                        exchange.name, e))
                    sleep(5)
                    return fetch_capital_base(exchange, attempt_index + 1)

                else:
                    raise ExchangeRequestErrorTooManyAttempts(
                        attempts=attempt_index, error=e)

            if base_currency in balances:
                return balances[base_currency]
            else:
                raise BaseCurrencyNotFoundError(base_currency=base_currency,
                                                exchange=exchange_name)

        capital_base = 0
        for exchange_name in exchanges:
            exchange = exchanges[exchange_name]
            capital_base += fetch_capital_base(exchange)

        sim_params = create_simulation_parameters(start=start,
                                                  end=end,
                                                  capital_base=capital_base,
                                                  emission_rate='minute',
                                                  data_frequency='minute')

        # TODO: use the constructor instead
        sim_params._arena = 'live'

        algorithm_class = partial(ExchangeTradingAlgorithmLive,
                                  exchanges=exchanges,
                                  algo_namespace=algo_namespace,
                                  live_graph=live_graph)
    else:
        # Removed the existing Poloniex fork to keep things simple
        # We can add back the complexity if required.

        # I don't think that we should have arbitrary price data bundles
        # Instead, we should center this data around exchanges.
        # We still need to support bundles for other misc data, but we
        # can handle this later.

        data = DataPortalExchangeBacktest(exchanges=exchanges,
                                          asset_finder=None,
                                          trading_calendar=open_calendar,
                                          first_trading_day=start,
                                          last_available_session=end)

        sim_params = create_simulation_parameters(
            start=start,
            end=end,
            capital_base=capital_base,
            data_frequency=data_frequency,
            emission_rate=data_frequency,
        )

        algorithm_class = partial(ExchangeTradingAlgorithmBacktest,
                                  exchanges=exchanges)

    perf = algorithm_class(
        namespace=namespace,
        env=env,
        get_pipeline_loader=choose_loader,
        sim_params=sim_params,
        **{
            'initialize': initialize,
            'handle_data': handle_data,
            'before_trading_start': before_trading_start,
            'analyze': analyze,
        } if algotext is None else {
            'algo_filename': getattr(algofile, 'name', '<algorithm>'),
            'script': algotext,
        }).run(
            data,
            overwrite_sim_params=False,
        )

    if output == '-':
        click.echo(str(perf))
    elif output != os.devnull:  # make the catalyst magic not write any data
        perf.to_pickle(output)

    return perf
Пример #4
0
class TestPoloniex(BaseExchangeTestCase):
    @classmethod
    def setup(self):
        print ('creating poloniex object')
        auth = get_exchange_auth('poloniex')
        self.exchange = Poloniex(
            key=auth['key'],
            secret=auth['secret'],
            base_currency='btc'
        )

    def test_order(self):
        log.info('creating order')
        asset = self.exchange.get_asset('neos_btc')
        order_id = self.exchange.order(
            asset=asset,
            limit_price=0.0005,
            amount=1,
        )
        log.info('order created {}'.format(order_id))
        assert order_id is not None
        pass

    def test_open_orders(self):
        log.info('retrieving open orders')
        # asset = self.exchange.get_asset('neos_btc')
        # orders = self.exchange.get_open_orders(asset)
        pass

    def test_get_order(self):
        log.info('retrieving order')
        order = self.exchange.get_order(
            u'2c584020-9caf-4af5-bde0-332c0bba17e2')
        assert isinstance(order, Order)
        pass

    def test_cancel_order(self, ):
        log.info('cancel order')
        self.exchange.cancel_order(u'dc7bcca2-5219-4145-8848-8a593d2a72f9')
        pass

    def test_get_candles(self):
        log.info('retrieving candles')
        assets = self.exchange.get_asset('eth_btc')
        ohlcv = self.exchange.get_candles(
            # end_dt=pd.to_datetime('2017-11-01', utc=True),
            end_dt=None,
            freq='5T',
            assets=assets,
            bar_count=200
        )
        df = pd.DataFrame(ohlcv)
        df.set_index('last_traded', drop=True, inplace=True)
        log.info(df.tail(25))

        path = output_df(df, assets, '5min_candles')
        log.info('saved candles: {}'.format(path))
        pass

    def test_tickers(self):
        log.info('retrieving tickers')
        tickers = self.exchange.tickers([
            self.exchange.get_asset('eth_btc'),
            self.exchange.get_asset('etc_btc')
        ])
        assert len(tickers) == 2
        pass

    def test_get_balances(self):
        log.info('testing wallet balances')
        # balances = self.exchange.get_balances()
        pass

    def test_get_account(self):
        log.info('testing account data')
        pass

    def test_orderbook(self):
        log.info('testing order book for poloniex')
        # asset = self.exchange.get_asset('eth_btc')
        # orderbook = self.exchange.get_orderbook(asset)
        pass
Пример #5
0
def load_crypto_market_data(trading_day=None, trading_days=None,
                            bm_symbol=None, bundle=None, bundle_data=None,
                            environ=None, exchange=None, start_dt=None,
                            end_dt=None):
    if trading_day is None:
        trading_day = get_calendar('OPEN').trading_day

    # TODO: consider making configurable
    bm_symbol = 'btc_usdt'
    # if trading_days is None:
    #    trading_days = get_calendar('OPEN').schedule

    # if start_dt is None:
    start_dt = get_calendar('OPEN').first_trading_session

    if end_dt is None:
        end_dt = pd.Timestamp.utcnow()

    # We expect to have benchmark and treasury data that's current up until
    # **two** full trading days prior to the most recently completed trading
    # day.
    # Example:
    # On Thu Oct 22 2015, the previous completed trading day is Wed Oct 21.
    # However, data for Oct 21 doesn't become available until the early morning
    # hours of Oct 22.  This means that there are times on the 22nd at which we
    # cannot reasonably expect to have data for the 21st available.  To be
    # conservative, we instead expect that at any time on the 22nd, we can
    # download data for Tuesday the 20th, which is two full trading days prior
    # to the date on which we're running a test.

    # We'll attempt to download new data if the latest entry in our cache is
    # before this date.
    '''
    if(bundle_data):
        # If we are using the bundle to retrieve the cryptobenchmark, find the last
        # date for which there is trading data in the bundle
        asset = bundle_data.asset_finder.lookup_symbol(symbol=bm_symbol,as_of_date=None)
        ix = bundle_data.daily_bar_reader._last_rows[asset.sid]
        last_date = pd.to_datetime(bundle_data.daily_bar_reader._spot_col('day')[ix],unit='s')
    else:
        last_date = trading_days[trading_days.get_loc(now, method='ffill') - 2]
    '''
    last_date = trading_days[trading_days.get_loc(end_dt, method='ffill') - 1]

    if exchange is None:
        # This is exceptional, since placing the import at the module scope
        #  breaks things and it's only needed here
        from catalyst.exchange.poloniex.poloniex import Poloniex
        exchange = Poloniex('', '', '')

    benchmark_asset = exchange.get_asset(bm_symbol)

    # exchange.get_history_window() already ensures that we have the right data
    # for the right dates
    br = exchange.get_history_window_with_bundle(
        assets=[benchmark_asset],
        end_dt=last_date,
        bar_count=pd.Timedelta(last_date - start_dt).days,
        frequency='1d',
        field='close',
        data_frequency='daily',
        force_auto_ingest=True)
    br.columns = ['close']
    br = br.pct_change(1).iloc[1:]
    br.loc[start_dt] = 0
    br = br.sort_index()

    # Override first_date for treasury data since we have it for many more years
    # and is independent of crypto data
    first_date_treasury = pd.Timestamp('1990-01-02', tz='UTC')
    tc = ensure_treasury_data(
        bm_symbol,
        first_date_treasury,
        last_date,
        end_dt,
        environ,
    )
    benchmark_returns = br[br.index.slice_indexer(start_dt, last_date)]
    treasury_curves = tc[
        tc.index.slice_indexer(first_date_treasury, last_date)]
    return benchmark_returns, treasury_curves
Пример #6
0
class PoloniexTestCase(BaseExchangeTestCase):
    @classmethod
    def setup(self):
        print('creating poloniex object')
        auth = get_exchange_auth('poloniex')
        self.exchange = Poloniex(key=auth['key'],
                                 secret=auth['secret'],
                                 base_currency='btc')

    def test_order(self):
        log.info('creating order')
        asset = self.exchange.get_asset('neo_btc')
        order_id = self.exchange.order(
            asset=asset,
            limit_price=0.0005,
            amount=1,
        )
        log.info('order created {}'.format(order_id))
        assert order_id is not None
        pass

    def test_open_orders(self):
        log.info('retrieving open orders')
        asset = self.exchange.get_asset('neo_btc')
        orders = self.exchange.get_open_orders(asset)
        pass

    def test_get_order(self):
        log.info('retrieving order')
        order = self.exchange.get_order(
            u'2c584020-9caf-4af5-bde0-332c0bba17e2')
        assert isinstance(order, Order)
        pass

    def test_cancel_order(self, ):
        log.info('cancel order')
        self.exchange.cancel_order(u'dc7bcca2-5219-4145-8848-8a593d2a72f9')
        pass

    def test_get_candles(self):
        log.info('retrieving candles')
        ohlcv_neo = self.exchange.get_candles(
            data_frequency='5m', assets=self.exchange.get_asset('neo_btc'))
        ohlcv_neo_ubq = self.exchange.get_candles(
            data_frequency='5m',
            assets=[
                self.exchange.get_asset('neo_btc'),
                self.exchange.get_asset('ubq_btc')
            ],
            bar_count=14)
        pass

    def test_tickers(self):
        log.info('retrieving tickers')
        tickers = self.exchange.tickers([
            self.exchange.get_asset('eth_btc'),
            self.exchange.get_asset('etc_btc')
        ])
        assert len(tickers) == 2
        pass

    def test_get_balances(self):
        log.info('testing wallet balances')
        balances = self.exchange.get_balances()
        pass

    def test_get_account(self):
        log.info('testing account data')
        pass

    def test_orderbook(self):
        log.info('testing order book for poloniex')
        asset = self.exchange.get_asset('eth_btc')

        orderbook = self.exchange.get_orderbook(asset)
        pass