diff --git a/catalyst/examples/buy_and_hold_live.py b/catalyst/examples/buy_and_hold_live.py
index 25c57533..985c06fa 100644
--- a/catalyst/examples/buy_and_hold_live.py
+++ b/catalyst/examples/buy_and_hold_live.py
@@ -18,7 +18,7 @@ log = Logger('buy_and_hold_live')
def initialize(context):
log.info('initializing algo')
- context.asset = symbol('eos_usd')
+ context.asset = symbol('eos_btc')
context.TARGET_HODL_RATIO = 0.8
context.RESERVE_RATIO = 1.0 - context.TARGET_HODL_RATIO
@@ -53,7 +53,7 @@ def handle_data(context, data):
# Check if still buying and could (approximately) afford another purchase
if context.is_buying and cash > price:
# Place order to make position in asset equal to target_hodl_value
- order(context.asset, 1, limit_price=price + 1.1)
+ order(context.asset, 1, limit_price=price * 1.1)
# This works
# order_target_value(
# context.asset,
@@ -79,7 +79,7 @@ exchange_conn = dict(
name='bitfinex',
key='',
secret=b'',
- base_currency='usd'
+ base_currency='btc'
)
run_algorithm(
initialize=initialize,
diff --git a/catalyst/exchange/bitfinex.py b/catalyst/exchange/bitfinex.py
index e317a52d..8dbb1ca8 100644
--- a/catalyst/exchange/bitfinex.py
+++ b/catalyst/exchange/bitfinex.py
@@ -193,7 +193,8 @@ class Bitfinex(Exchange):
portfolio.cash = float(base_position['available'])
if portfolio.positions:
- tickers = self.tickers(portfolio.positions.keys())
+ assets = portfolio.positions.keys()
+ tickers = self.tickers(assets)
portfolio.positions_value = 0.0
for ticker in tickers:
# TODO: convert if the position is not in the base currency
@@ -209,8 +210,9 @@ class Bitfinex(Exchange):
@property
def portfolio(self):
"""
- TODO: I'm not sure how that's used yet
- :return:
+ Return the Portfolio
+
+ :return:
"""
if self.store.portfolio is None:
portfolio = ExchangePortfolio(
@@ -402,18 +404,16 @@ class Bitfinex(Exchange):
:func:`catalyst.api.order_value`
:func:`catalyst.api.order_percent`
"""
- log.debug(
- 'ordering {amount} {symbol} {style}'.format(
- amount=amount,
- symbol=asset.symbol,
- style=style
- )
- )
-
if amount == 0:
log.warn('skipping order amount of 0')
return None
+ base_currency = asset.symbol.split('_')[1]
+ if base_currency.lower() != self.base_currency.lower():
+ raise NotImplementedError(
+ 'Currency pairs must share their base with the exchange.'
+ )
+
is_buy = (amount > 0)
if isinstance(style, MarketOrder):
@@ -432,6 +432,14 @@ class Bitfinex(Exchange):
else:
raise NotImplementedError('%s orders not available' % style)
+ log.debug(
+ 'ordering {amount} {symbol} for {price}'.format(
+ amount=amount,
+ symbol=asset.symbol,
+ price=price
+ )
+ )
+
exchange_symbol = self.get_symbol(asset)
req = dict(
symbol=exchange_symbol,
diff --git a/catalyst/exchange/exchange_clock.py b/catalyst/exchange/exchange_clock.py
index f3866ce8..4698297c 100644
--- a/catalyst/exchange/exchange_clock.py
+++ b/catalyst/exchange/exchange_clock.py
@@ -64,8 +64,8 @@ class ExchangeClock(object):
server_time = current_time.floor('1 min')
if self._last_emit is None or server_time > self._last_emit:
+ log.debug('emitting minutely bar: {}'.format(server_time))
- print 'emitting bar %s' % server_time
self._last_emit = server_time
yield server_time, BAR
diff --git a/docs/source/live-trading-blueprint.md b/docs/source/live-trading-blueprint.md
index 327986e0..d26638f2 100644
--- a/docs/source/live-trading-blueprint.md
+++ b/docs/source/live-trading-blueprint.md
@@ -3,36 +3,33 @@ The purpose of this document is to allow project contributors navigate
through the ongoing live trading implementation.
Components
-At a high level the following components have been implemented to coerce
+At a high level, the following components have been implemented to coerce
zipline into live trading.
Exchange
*catalyst/exchange*
-Exchange is a new package which introduces the concept of cryptocurrency
-exchanges to zipline. The package contains all new component
-implementations adapted to characteristics of exchanges.
+Exchange is a new package introducing cryptocurrency
+exchanges to zipline. The package contains mostly new implementations
+of existing components, adapted to characteristics of exchanges.
-Here are some key characteristics which makes exchanges different from
-equity and futures currently implemented in zipline.
+Here are some key characteristics which make cryptocurrency exchanges
+exchanges different compared to equity brokers.
* 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.
+* They trade currency pairs (i.e. the base currency is not always be USD).
+This is a paradigm shift in context of zipline. Additional
+business logic will be required to manage the portfolio data and orders.
+* The price of a single asset might vary across exchanges. This means
+arbitrage opportunities. 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.
+* There are no splits, mergers, etc. to worry about.
+* A complete order book is usually available, the platform should
+offer access to it order to help traders reduce slippage.
New Components
These components of the exchange package were added to the zipline
@@ -42,7 +39,7 @@ sources.
*catalyst/exchange/exchange.py*
-Abstract class which acts an interface for the implementation of
+Abstract class which acts as an interface for the implementation of
various exchanges. It also contains logic common to all exchanges.
Bitfinex
@@ -59,14 +56,20 @@ 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, `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.
+For example, `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.
+
+At the time of writing, it only supports spot data but I believe that
+it should be extended to historical data as well. Some exchanges
+have better historical data APIs than others. This will need to
+be considered during each individual implementation.
ExchangeClock
*catalyst/exchange/exchange_clock.py*
-An implementation to the zipline Clock which runs 24/7. It yeilds a
+An implementation to the zipline Clock which runs 24/7. It yields a
bar every minute.
AssetFinderExchange
@@ -76,15 +79,14 @@ bar every minute.
An alternate implementation of AssetFinder which locates each asset
against the exchanges instead of bundle databases.
-For example, `symbol('eth_usd')` retrieves an Asset object against the exchange as opposed to querying
-a database of equities.
+For example, `symbol('eth_usd')` should return an Ethereum/USD asset
+regardless of currency notation of the target exchange.
-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.
+To acheive this, I have created a dictionary of currencies for the
+Bitfinex exchange. Here is what it looks like.
* 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 symbol attribute represents the abstract symbol common across
+all exchanges for the given currency.
* The start_date attribute should correspond to its first trading day
on the exchange.
@@ -132,13 +134,15 @@ business logic to enable live trading.
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.
+the catalyst concurrency bundles. I added conditional logic
+which should not interfere with backtesting.
-At a high-level the run_algorithm method now contains two additional
+In a nutshell, the run_algorithm method now contains three additional
parameters:
* live: If True, zipline will attempt to trade live. If False or not
specified, it will run a backtest as normal.
+* algo_namespace: An arbitrary namespace for the current algorithm.
+It will be used to persist data between runs.
* exchange_conn: A dictionary containing the attributes required
to instantiate an exchange. Here is an example for Bitfinex:
@@ -189,7 +193,7 @@ cost basis would correspond to all positions, not just those
initiated by the algorithm.
* It would not be possible impose trading limits on algorithms.
-It follow that Portfolio metrics should be calculated using a strategic
+It follows that Portfolio metrics should be calculated using a strategic
combination of the exchange data and algorithm activity. While tracking
the activity of an algorithm works well in backtesting, it is more
challenging during live trading. A live algorithm might run over