diff --git a/catalyst/exchange/bitfinex.py b/catalyst/exchange/bitfinex.py index 845fc664..de2a06de 100644 --- a/catalyst/exchange/bitfinex.py +++ b/catalyst/exchange/bitfinex.py @@ -308,14 +308,14 @@ class Bitfinex(Exchange): 'Unsupported frequency %s' % data_frequency ) - request = requests.get( + response = requests.get( '{url}/v2/candles/trade:{frequency}:{symbol}/last'.format( url=self.url, frequency=frequency, symbol=symbol ) ) - candles = request.json() + candles = response.json() if 'message' in candles: raise ValueError( @@ -333,7 +333,7 @@ class Bitfinex(Exchange): ) if field not in ohlc: - raise KeyError('Invalid column: ' + str(field)) + raise KeyError('Invalid column: %s' % field) return ohlc[field] diff --git a/catalyst/exchange/symbols/bitfinex.json b/catalyst/exchange/symbols/bitfinex.json index 2419516c..41bc17c9 100644 --- a/catalyst/exchange/symbols/bitfinex.json +++ b/catalyst/exchange/symbols/bitfinex.json @@ -1 +1,110 @@ -{ "btcusd": {"symbol":"btc_usd", "start_date": "2010-01-01"}, "ltcusd": {"symbol":"ltc-usd", "start_date": "2010-01-01"}, "ltcbtc": {"symbol":"ltc_btc", "start_date": "2010-01-01"}, "ethusd": {"symbol":"eth_usd", "start_date": "2010-01-01"}, "ethbtc": {"symbol":"eth_btc", "start_date": "2010-01-01"}, "etcbtc": {"symbol":"etc_btc", "start_date": "2010-01-01"}, "etcusd": {"symbol":"etc_usd", "start_date": "2010-01-01"}, "rrtusd": {"symbol":"rrt_usd", "start_date": "2010-01-01"}, "rrtbtc": {"symbol":"rrt_btc", "start_date": "2010-01-01"}, "zecusd": {"symbol":"zec_usd", "start_date": "2010-01-01"}, "zecbtc": {"symbol":"zec_btc", "start_date": "2010-01-01"}, "xmrusd": {"symbol":"xmr_usd", "start_date": "2010-01-01"}, "xmrbtc": {"symbol":"xmr_btc", "start_date": "2010-01-01"}, "dshusd": {"symbol":"dsh_usd", "start_date": "2010-01-01"}, "dshbtc": {"symbol":"dsh_btc", "start_date": "2010-01-01"}, "bccbtc": {"symbol":"bcc_btc", "start_date": "2010-01-01"}, "bcubtc": {"symbol":"bcu_btc", "start_date": "2010-01-01"}, "bccusd": {"symbol":"bcc_usd", "start_date": "2010-01-01"}, "bcuusd": {"symbol":"bcu_usd", "start_date": "2010-01-01"}, "xrpusd": {"symbol":"xrp_usd", "start_date": "2010-01-01"}, "xrpbtc": {"symbol":"xrp_btc", "start_date": "2010-01-01"}, "iotusd": {"symbol":"iot_usd", "start_date": "2010-01-01"}, "iotbtc": {"symbol":"iot_btc", "start_date": "2010-01-01"}, "ioteth": {"symbol":"iot_eth", "start_date": "2010-01-01"}, "eosusd": {"symbol":"eos_usd", "start_date": "2010-01-01"}, "eosbtc": {"symbol":"eos_btc", "start_date": "2010-01-01"}, "eoseth": {"symbol":"eos_eth", "start_date": "2010-01-01"} } \ No newline at end of file +{ + "btcusd": { + "symbol": "btc_usd", + "start_date": "2010-01-01" + }, + "ltcusd": { + "symbol": "ltc-usd", + "start_date": "2010-01-01" + }, + "ltcbtc": { + "symbol": "ltc_btc", + "start_date": "2010-01-01" + }, + "ethusd": { + "symbol": "eth_usd", + "start_date": "2010-01-01" + }, + "ethbtc": { + "symbol": "eth_btc", + "start_date": "2010-01-01" + }, + "etcbtc": { + "symbol": "etc_btc", + "start_date": "2010-01-01" + }, + "etcusd": { + "symbol": "etc_usd", + "start_date": "2010-01-01" + }, + "rrtusd": { + "symbol": "rrt_usd", + "start_date": "2010-01-01" + }, + "rrtbtc": { + "symbol": "rrt_btc", + "start_date": "2010-01-01" + }, + "zecusd": { + "symbol": "zec_usd", + "start_date": "2010-01-01" + }, + "zecbtc": { + "symbol": "zec_btc", + "start_date": "2010-01-01" + }, + "xmrusd": { + "symbol": "xmr_usd", + "start_date": "2010-01-01" + }, + "xmrbtc": { + "symbol": "xmr_btc", + "start_date": "2010-01-01" + }, + "dshusd": { + "symbol": "dsh_usd", + "start_date": "2010-01-01" + }, + "dshbtc": { + "symbol": "dsh_btc", + "start_date": "2010-01-01" + }, + "bccbtc": { + "symbol": "bcc_btc", + "start_date": "2010-01-01" + }, + "bcubtc": { + "symbol": "bcu_btc", + "start_date": "2010-01-01" + }, + "bccusd": { + "symbol": "bcc_usd", + "start_date": "2010-01-01" + }, + "bcuusd": { + "symbol": "bcu_usd", + "start_date": "2010-01-01" + }, + "xrpusd": { + "symbol": "xrp_usd", + "start_date": "2010-01-01" + }, + "xrpbtc": { + "symbol": "xrp_btc", + "start_date": "2010-01-01" + }, + "iotusd": { + "symbol": "iot_usd", + "start_date": "2010-01-01" + }, + "iotbtc": { + "symbol": "iot_btc", + "start_date": "2010-01-01" + }, + "ioteth": { + "symbol": "iot_eth", + "start_date": "2010-01-01" + }, + "eosusd": { + "symbol": "eos_usd", + "start_date": "2010-01-01" + }, + "eosbtc": { + "symbol": "eos_btc", + "start_date": "2010-01-01" + }, + "eoseth": { + "symbol": "eos_eth", + "start_date": "2010-01-01" + } +} \ No newline at end of file diff --git a/catalyst/exchange/trading_exchange.py b/catalyst/exchange/trading_exchange.py deleted file mode 100644 index 45ba342b..00000000 --- a/catalyst/exchange/trading_exchange.py +++ /dev/null @@ -1,2 +0,0 @@ -from catalyst.finance.trading import TradingEnvironment - diff --git a/docs/source/live-trading-blueprint.md b/docs/source/live-trading-blueprint.md new file mode 100644 index 00000000..9fc423d5 --- /dev/null +++ b/docs/source/live-trading-blueprint.md @@ -0,0 +1,185 @@ +

Live Trading Blueprint

+The purpose of this document is to allow project contributors navigate +ongoing live trading implementation. + +

Components

+At a high level the following components have been modified to coerce +zipline into live trading. + +

Exchange

+Exchange is a new package which introduces the concept of cryptocurrency +exchanges to zipline. The package contains all new component +implementations adapted to charasteristics of exchanges. + +``` +catalyst/exchange +``` + +Here are some key characteristics which makes exchanges different from +equity and futures currently implemented in zipline. +* They trade around the clock. +* Currency symbols are inconsistent across exchanges. +* They trade currency pairs, i.e. the base currency is not always be USD. +This is a significant departure from the equity market. Additional +business logic will be required both to assess performance and +manage trades. +* The cryptocurrency market being relatively immature, there are still +significant price arbitrage opportunities between exchanges. +In contrast with the equity markets, trader usually trade directly +against an exchange (as oppose to using a broker). Consequently, +to extract maximum alpha, the platform should not only support +multiple exchanges, but also multiple exchanges per algorithm. +* The fee model is usually more complex than that of an equity broker. +It can vary drastically between exchanges. +* There are no splits, mergers, etc to worry about. +* Their order book is publicly available, the platform should access to +it as it can be used to drastically reduce slippage. + +

New Components

+These components of the exchange package were added to the zipline +sources. + +
Exchange
+ +``` +catalyst/exchange/exchange.py +``` + +Abstract class which acts an interface for the implementation of +various exchanges. It also contains logic common to all exchanges. + +
Bitfinex
+ +``` +catalyst/exchange/bitfinex.py +``` + +The Bitfinex exchange implementation. It extends the Exchange class. + +
DataPortalExchange
+ +``` +catalyst/exchange/data_portal_exchange.py +``` + +Extends the zipline DataPortal to route spot data to the exchange. +This is critical because it allows the algoritm to request data in +real-time. + +For example, + +```python + data.current(asset, 'price') +``` + +retrieves the current price of the asset, not the price at the time +of yielding the bar this is critical to minimize slippage. + +
ExchangeClock
+ +``` +catalyst/exchange/exchange_clock.py +``` + +An implementation to the zipline Clock which runs 24/7. It yeilds a +bar every minute. + +
AssetFinderExchange
+ +``` +catalyst/exchange/asset_finder_exchange.py +``` + +An alternate implementation of AssetFinder which locates each asset +against the exchanges instead of bundle databases. + +For example, + +```python +symbol('eth_usd') +``` + +retrieves an Asset object against the exchange as opposed to querying +a database of equities. + +I have created a dictionary of currencies for the Bitfinex exchange. +The primary goal is to standardize the symbol notation across exchanges. +Here is a snippet of the file. +* Each key represents the exchange specific symbol. +* The symbol attribute represents the standard symbol which +should be common across exchanges for the given currency. +* The start_date attribute should correspond to its first trading day +on the exchange. + +```json +{ + "btcusd": { + "symbol": "btc_usd", + "start_date": "2010-01-01" + }, + "ltcusd": { + "symbol": "ltc_usd", + "start_date": "2010-01-01" + }, + "ltcbtc": { + "symbol": "ltc_btc", + "start_date": "2010-01-01" + }, + "ethusd": { + "symbol": "eth_usd", + "start_date": "2010-01-01" + }, + "ethbtc": { + "symbol": "eth_btc", + "start_date": "2010-01-01" + } +} +``` + +
ExchangeTradingAlgorithm
+ +``` +catalyst/exchange/algorithm_exchange.py +``` + +Extends the TradingAlgorithm class which orchestrates the api +operations. This class brings together most of the components +described above. + +

Modified Components

+ +The following components have been modified to include conditional +business logic to enable live trading. + +
run_algorithm
+ +``` +catalyst/utils/run_algo.py +``` + +The run_algorithm interface is an entry point to execute an +algorithm in zipline. This component was already modified for +the catalyst concurrency bundles. I added conditional logic to +which should not break any of the existing backtesting implementations. + +At a high-level the run_algorithm method now contains two additional +parameters: +* live: If True, zipline will attempt to trade live. If False or not +specified, it will run a backtest as normal. +* exchange_conn: A dictionary containing the attributes required +to instantiate an exchange. Here is an example for Bitfinex: + +```python +exchange_conn = dict( + name='bitfinex', + key='', + secret=b'', + base_currency='usd' +) +``` + +The following sample algorithm uses the run_algorithm interface: + +``` +catalyst/examples/buy_and_hold_live.py +```