Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
AvishaiW committed Apr 24, 2018
2 parents 528951b + 0fcb26e commit 9cceef7
Show file tree
Hide file tree
Showing 24 changed files with 346 additions and 235 deletions.
50 changes: 17 additions & 33 deletions catalyst/_protocol.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -254,9 +254,7 @@ cdef class BarData:
def current(self, assets, fields):
"""
Returns the current value of the given assets for the given fields
at the current simulation time. Current values are the as-traded price
and are usually not adjusted for events like splits or dividends (see
notes for more information).
at the current simulation time.
Parameters
----------
Expand Down Expand Up @@ -293,20 +291,20 @@ cdef class BarData:
"price" returns the last known close price of the asset. If there is
no last known value (either because the asset has never traded, or
because it has delisted) NaN is returned. If a value is found, and we
had to cross an adjustment boundary (split, dividend, etc) to get it,
the value is adjusted before being returned.
because it has delisted) NaN is returned.
"last_traded" returns the date of the last trade event of the asset,
even if the asset has stopped trading. If there is no last known value,
pd.NaT is returned.
"volume" returns the trade volume for the current simulation time. If
In backtest mode, "volume" returns the trade volume for the current simulation time. If
there is no trade this minute, 0 is returned.
"open", "high", "low", and "close" return the relevant information for
the current trade bar. If there is no current trade bar, NaN is
returned.
In live mode, "volume" returns the last 24 hour trading volume.
"""
multiple_assets = _is_iterable(assets)
multiple_fields = _is_iterable(fields)
Expand Down Expand Up @@ -438,25 +436,9 @@ cdef class BarData:
"""
For the given asset or iterable of assets, returns true if all of the
following are true:
1) the asset is alive for the session of the current simulation time
(if current simulation time is not a market minute, we use the next
session)
2) (if we are in minute mode) the asset's exchange is open at the
current simulation time or at the simulation calendar's next market
minute
3) there is a known last price for the asset.
Notes
-----
The second condition above warrants some further explanation.
- If the asset's exchange calendar is identical to the simulation
calendar, then this condition always returns True.
- If there are market minutes in the simulation calendar outside of
this asset's exchange's trading hours (for example, if the simulation
is running on the CME calendar but the asset is MSFT, which trades on
the NYSE), during those minutes, this condition will return false
(for example, 3:15 am Eastern on a weekday, during which the CME is
open but the NYSE is closed).
1) the asset is alive for the session of the current simulation time (if current simulation
time is not a market minute, we use the next session)
2) there is a known last price for the asset.
Parameters
----------
Expand All @@ -466,6 +448,7 @@ cdef class BarData:
-------
can_trade : bool or pd.Series[bool] indexed by asset.
"""

dt = self.simulation_dt_func()

if self._adjust_minutes:
Expand Down Expand Up @@ -594,8 +577,12 @@ cdef class BarData:
"""
Returns a window of data for the given assets and fields.
This data is adjusted for splits, dividends, and mergers as of the
current algorithm time.
The label of each candle is left-bound. This means that for example, in case of 5 minute candles,
the candle of 00:00:00 will hold the data between 00:00:00 and 00:04:59.
In minute mode, both in live and backtest, the last candle will almost always
be a partial one. For example, if the current time is 00:02:00 then the last 5 minute candle
with 00:00:00 timestamp will hold data between 00:00:00 and 00:01:59.
The semantics of missing data are identical to the ones described in
the notes for `get_spot_value`.
Expand All @@ -609,7 +596,8 @@ cdef class BarData:
bar_count: integer number of bars of trade data
frequency: string. "1m" for minutely data or "1d" for daily date
frequency: string. "T" for minutely data, "D" for daily date,
"H" for hourly data
Returns
-------
Expand All @@ -630,10 +618,6 @@ cdef class BarData:
Panel is indexed by field, has dt as the major axis, and assets
as the minor axis.
Notes
-----
If the current simulation time is not a valid market time, we use the
last market close instead.
"""
if isinstance(fields, string_types):
single_asset = isinstance(assets, PricingDataAssociable)
Expand Down
111 changes: 37 additions & 74 deletions catalyst/algorithm.py
Original file line number Diff line number Diff line change
Expand Up @@ -937,10 +937,8 @@ def get_environment(self, field='platform'):
field : {'platform', 'arena', 'data_frequency',
'start', 'end', 'capital_base', 'platform', '*'}
The field to query. The options have the following meanings:
arena : str
The arena from the simulation parameters. This will normally
be ``backtest`` but some systems may use this distinguish
live trading from backtesting.
arena : str {'backtest', 'live'}
The algorithm's arena.
data_frequency : {'daily', 'minute'}
data_frequency tells the algorithm if it is running with
daily or minute mode.
Expand Down Expand Up @@ -1269,7 +1267,7 @@ def continuous_future(self,

@api_method
def symbols(self, *args):
"""Lookup multuple Equities as a list.
"""Lookup multiple TradingPairs as a list.
Parameters
----------
Expand All @@ -1278,8 +1276,8 @@ def symbols(self, *args):
Returns
-------
equities : list[Equity]
The equities that held the given ticker symbols on the current
tradingPairs : list[TradingPair]
The tradingPairs that held the given ticker symbols on the current
symbol lookup date.
Raises
Expand Down Expand Up @@ -1420,11 +1418,11 @@ def order(self,
Parameters
----------
asset : Asset
The asset that this order is for.
The asset/TradingPair 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.
The amount of currency to order. If ``amount`` is positive, this is
the number of ``market_currency`` (the first asset in the pair) to buy. If ``amount`` is negative,
this is the number of ``market_currency`` to sell (buy ``base_currency``).
limit_price : float, optional
The limit price for the order.
stop_price : float, optional
Expand All @@ -1448,6 +1446,9 @@ def order(self,
``style=StopLimitOrder(N, M)``. It is an error to pass both a ``style``
and ``limit_price`` or ``stop_price``.
Currently, orders must be done only with one ``base_currency``
throughout all the algorithm.
See Also
--------
:class:`catalyst.finance.execution.ExecutionStyle`
Expand Down Expand Up @@ -1551,21 +1552,19 @@ def order_value(self,
limit_price=None,
stop_price=None,
style=None):
"""Place an order by desired value rather than desired number of
shares.
"""Place an order by ``base_currency`` value rather than desired number of
``market_currency`` wanted.
Parameters
----------
asset : Asset
The asset that this order is for.
asset : TradingPair
The TradingPair that this order is for.
value : float
If the requested asset exists, the requested value is
divided by its price to imply the number of shares to transact.
If the Asset being ordered is a Future, the 'value' calculated
is actually the exposure, as Futures have no 'value'.
If the requested tradingPair exists, the requested value is
divided by its price to imply the number of currency to transact.
value > 0 :: Buy/Cover
value < 0 :: Sell/Short
value < 0 :: Sell
limit_price : float, optional
The limit price for the order.
stop_price : float, optional
Expand Down Expand Up @@ -1772,8 +1771,6 @@ def set_cancel_policy(self, cancel_policy):
@api_method
def set_symbol_lookup_date(self, dt):
"""Set the date for which symbols will be resolved to their assets
(symbols may map to different firms or underlying assets at
different times)
Parameters
----------
Expand Down Expand Up @@ -1804,15 +1801,15 @@ def order_percent(self,
limit_price=None,
stop_price=None,
style=None):
"""Place an order in the specified asset corresponding to the given
"""Place an order in the specified tradingPair corresponding to the given
percent of the current portfolio value.
Parameters
----------
asset : Asset
The asset that this order is for.
asset : TradingPair
The tradingPair that this order is for.
percent : float
The percentage of the porfolio value to allocate to ``asset``.
The percentage of the portfolio value to allocate to ``asset``.
This is specified as a decimal, for example: 0.50 means 50%.
limit_price : float, optional
The limit price for the order.
Expand Down Expand Up @@ -1858,18 +1855,18 @@ def order_target(self,
limit_price=None,
stop_price=None,
style=None):
"""Place an order to adjust a position to a target number of shares. If
"""Place an order to adjust a position to a target number of currency. If
the position doesn't already exist, this is equivalent to placing a new
order. If the position does exist, this is equivalent to placing an
order for the difference between the target number of shares and the
current number of shares.
Parameters
----------
asset : Asset
The asset that this order is for.
asset : TradingPair
The TradingPair that this order is for.
target : int
The desired number of shares of ``asset``.
The desired number of ``TradingPair``.
limit_price : float, optional
The limit price for the order.
stop_price : float, optional
Expand All @@ -1885,17 +1882,7 @@ def order_target(self,
Notes
-----
``order_target`` does not take into account any open orders. For
example:
.. code-block:: python
order_target(sid(0), 10)
order_target(sid(0), 10)
This code will result in 20 shares of ``sid(0)`` because the first
call to ``order_target`` will not have been filled when the second
``order_target`` call is made.
``order_target`` takes into account open orders as well.
See :func:`catalyst.api.order` for more information about
``limit_price``, ``stop_price``, and ``style``
Expand Down Expand Up @@ -1936,15 +1923,13 @@ def order_target_value(self,
order. If the position does exist, this is equivalent to placing an
order for the difference between the target value and the
current value.
If the Asset being ordered is a Future, the 'target value' calculated
is actually the target exposure, as Futures have no 'value'.
Parameters
----------
asset : Asset
The asset that this order is for.
asset : TradingPair
The TradingPair that this order is for.
target : float
The desired total value of ``asset``.
The desired total value of ``TradingPair``.
limit_price : float, optional
The limit price for the order.
stop_price : float, optional
Expand All @@ -1959,17 +1944,6 @@ def order_target_value(self,
Notes
-----
``order_target_value`` does not take into account any open orders. For
example:
.. code-block:: python
order_target_value(sid(0), 10)
order_target_value(sid(0), 10)
This code will result in 20 dollars of ``sid(0)`` because the first
call to ``order_target_value`` will not have been filled when the
second ``order_target_value`` call is made.
See :func:`catalyst.api.order` for more information about
``limit_price``, ``stop_price``, and ``style``
Expand Down Expand Up @@ -2003,11 +1977,11 @@ def order_target_percent(self, asset, target,
Parameters
----------
asset : Asset
The asset that this order is for.
asset : TradingPair
The TradingPair that this order is for.
target : float
The desired percentage of the porfolio value to allocate to
``asset``. This is specified as a decimal, for example:
The desired percentage of the portfolio value to allocate to
``TradingPair``. This is specified as a decimal, for example:
0.50 means 50%.
limit_price : float, optional
The limit price for the order.
Expand All @@ -2023,17 +1997,6 @@ def order_target_percent(self, asset, target,
Notes
-----
``order_target_value`` does not take into account any open orders. For
example:
.. code-block:: python
order_target_percent(sid(0), 10)
order_target_percent(sid(0), 10)
This code will result in 20% of the portfolio being allocated to sid(0)
because the first call to ``order_target_percent`` will not have been
filled when the second ``order_target_percent`` call is made.
See :func:`catalyst.api.order` for more information about
``limit_price``, ``stop_price``, and ``style``
Expand Down Expand Up @@ -2067,7 +2030,7 @@ def batch_market_order(self, share_counts):
Parameters
----------
share_counts : pd.Series[Asset -> int]
Map from asset to number of shares to order for that asset.
Map from TradingPair to the number to order for that TradingPair.
Returns
-------
Expand All @@ -2090,7 +2053,7 @@ def get_open_orders(self, asset=None):
Parameters
----------
asset : Asset
asset : Asset, optional
If passed and not None, return only the open orders for the given
asset instead of all open orders.
Expand Down
2 changes: 1 addition & 1 deletion catalyst/examples/buy_btc_simple.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def handle_data(context, data):
initialize=initialize,
handle_data=handle_data,
exchange_name='poloniex',
algo_namespace='buy_and_hodl',
algo_namespace='buy_btc_simple',
base_currency='usdt',
start=pd.to_datetime('2015-03-01', utc=True),
end=pd.to_datetime('2017-10-31', utc=True),
Expand Down
10 changes: 10 additions & 0 deletions catalyst/exchange/ccxt/ccxt_exchange.py
Original file line number Diff line number Diff line change
Expand Up @@ -852,6 +852,16 @@ def get_open_orders(self, asset):

return orders

def _check_common_symbols(self, currency):
for key, value in self._common_symbols.items():
if value == currency:
return key.lower()
return currency

def _check_low_balance(self, currency, balances, amount):
updated_currency = self._check_common_symbols(currency)
return super(CCXT, self)._check_low_balance(updated_currency, balances, amount)

def _process_order_fallback(self, order):
"""
Fallback method for exchanges which do not play nice with
Expand Down
Loading

0 comments on commit 9cceef7

Please sign in to comment.